Code

50e26652024194c19887c20fe33a2963220d1269
[pkg-rrdtool.git] / src / rrd_create.c
1 /*****************************************************************************
2  * RRDtool 1.4.7  Copyright by Tobi Oetiker, 1997-2012
3  *****************************************************************************
4  * rrd_create.c  creates new rrds
5  *****************************************************************************/
7 #include <stdlib.h>
8 #include <time.h>
9 #include <locale.h>
11 #include "rrd_tool.h"
12 #include "rrd_rpncalc.h"
13 #include "rrd_hw.h"
15 #include "rrd_is_thread_safe.h"
16 static int opt_no_overwrite = 0;
18 #ifdef WIN32
19 # include <process.h>
20 #endif
22 unsigned long FnvHash(
23     const char *str);
24 int       create_hw_contingent_rras(
25     rrd_t *rrd,
26     unsigned short period,
27     unsigned long hashed_name);
28 void      parseGENERIC_DS(
29     const char *def,
30     rrd_t *rrd,
31     int ds_idx);
33 static void rrd_free2(
34     rrd_t *rrd);        /* our onwn copy, immmune to mmap */
36 int rrd_create(
37     int argc,
38     char **argv)
39 {
40     struct option long_options[] = {
41         {"start", required_argument, 0, 'b'},
42         {"step", required_argument, 0, 's'},
43         {"no-overwrite", no_argument, 0, 'O'},
44         {0, 0, 0, 0}
45     };
46     int       option_index = 0;
47     int       opt;
48     time_t    last_up = time(NULL) - 10;
49     unsigned long pdp_step = 300;
50     rrd_time_value_t last_up_tv;
51     char     *parsetime_error = NULL;
52     long      long_tmp;
53     int       rc;
55     optind = 0;
56     opterr = 0;         /* initialize getopt */
58     while (1) {
59         opt = getopt_long(argc, argv, "Ob:s:", long_options, &option_index);
61         if (opt == EOF)
62             break;
64         switch (opt) {
65         case 'b':
66             if ((parsetime_error = rrd_parsetime(optarg, &last_up_tv))) {
67                 rrd_set_error("start time: %s", parsetime_error);
68                 return (-1);
69             }
70             if (last_up_tv.type == RELATIVE_TO_END_TIME ||
71                 last_up_tv.type == RELATIVE_TO_START_TIME) {
72                 rrd_set_error("specifying time relative to the 'start' "
73                               "or 'end' makes no sense here");
74                 return (-1);
75             }
77             last_up = mktime(&last_up_tv.tm) +last_up_tv.offset;
79             if (last_up < 3600 * 24 * 365 * 10) {
80                 rrd_set_error
81                     ("the first entry to the RRD should be after 1980");
82                 return (-1);
83             }
84             break;
86         case 's':
87             long_tmp = atol(optarg);
88             if (long_tmp < 1) {
89                 rrd_set_error("step size should be no less than one second");
90                 return (-1);
91             }
92             pdp_step = long_tmp;
93             break;
95         case 'O':
96             opt_no_overwrite = 1;
97             break;
99         case '?':
100             if (optopt != 0)
101                 rrd_set_error("unknown option '%c'", optopt);
102             else
103                 rrd_set_error("unknown option '%s'", argv[optind - 1]);
104             return (-1);
105         }
106     }
107     if (optind == argc) {
108         rrd_set_error("need name of an rrd file to create");
109         return -1;
110     }
111     rc = rrd_create_r(argv[optind],
112                       pdp_step, last_up,
113                       argc - optind - 1, (const char **) (argv + optind + 1));
115     return rc;
118 /* #define DEBUG */
119 int rrd_create_r(
120     const char *filename,
121     unsigned long pdp_step,
122     time_t last_up,
123     int argc,
124     const char **argv)
126     rrd_t     rrd;
127     long      i;
128     int       offset;
129     char     *token;
130     char      dummychar1[2], dummychar2[2];
131     unsigned short token_idx, error_flag, period = 0;
132     unsigned long hashed_name;
134     /* init rrd clean */
135     rrd_init(&rrd);
136     /* static header */
137     if ((rrd.stat_head = (stat_head_t*)calloc(1, sizeof(stat_head_t))) == NULL) {
138         rrd_set_error("allocating rrd.stat_head");
139         rrd_free2(&rrd);
140         return (-1);
141     }
143     /* live header */
144     if ((rrd.live_head = (live_head_t*)calloc(1, sizeof(live_head_t))) == NULL) {
145         rrd_set_error("allocating rrd.live_head");
146         rrd_free2(&rrd);
147         return (-1);
148     }
150     /* set some defaults */
151     strcpy(rrd.stat_head->cookie, RRD_COOKIE);
152     strcpy(rrd.stat_head->version, RRD_VERSION3);   /* by default we are still version 3 */
153     rrd.stat_head->float_cookie = FLOAT_COOKIE;
154     rrd.stat_head->ds_cnt = 0;  /* this will be adjusted later */
155     rrd.stat_head->rra_cnt = 0; /* ditto */
156     rrd.stat_head->pdp_step = pdp_step; /* 5 minute default */
158     /* a default value */
159     rrd.ds_def = NULL;
160     rrd.rra_def = NULL;
162     rrd.live_head->last_up = last_up;
164     /* optind points to the first non-option command line arg,
165      * in this case, the file name. */
166     /* Compute the FNV hash value (used by SEASONAL and DEVSEASONAL
167      * arrays. */
168     hashed_name = FnvHash(filename);
169     for (i = 0; i < argc; i++) {
170         unsigned int ii;
172         if (strncmp(argv[i], "DS:", 3) == 0) {
173             size_t    old_size = sizeof(ds_def_t) * (rrd.stat_head->ds_cnt);
175             if ((rrd.ds_def = (ds_def_t*)rrd_realloc(rrd.ds_def,
176                                           old_size + sizeof(ds_def_t))) ==
177                 NULL) {
178                 rrd_set_error("allocating rrd.ds_def");
179                 rrd_free2(&rrd);
180                 return (-1);
181             }
182             memset(&rrd.ds_def[rrd.stat_head->ds_cnt], 0, sizeof(ds_def_t));
183             /* extract the name and type */
184             switch (sscanf(&argv[i][3],
185                            DS_NAM_FMT "%1[:]" DST_FMT "%1[:]%n",
186                            rrd.ds_def[rrd.stat_head->ds_cnt].ds_nam,
187                            dummychar1,
188                            rrd.ds_def[rrd.stat_head->ds_cnt].dst,
189                            dummychar2, &offset)) {
190             case 0:
191             case 1:
192                 rrd_set_error("Invalid DS name");
193                 break;
194             case 2:
195             case 3:
196                 rrd_set_error("Invalid DS type");
197                 break;
198             case 4:    /* (%n may or may not be counted) */
199             case 5:    /* check for duplicate datasource names */
200                 for (ii = 0; ii < rrd.stat_head->ds_cnt; ii++)
201                     if (strcmp(rrd.ds_def[rrd.stat_head->ds_cnt].ds_nam,
202                                rrd.ds_def[ii].ds_nam) == 0)
203                         rrd_set_error("Duplicate DS name: %s",
204                                       rrd.ds_def[ii].ds_nam);
205                 /* DS_type may be valid or not. Checked later */
206                 break;
207             default:
208                 rrd_set_error("invalid DS format");
209             }
210             if (rrd_test_error()) {
211                 rrd_free2(&rrd);
212                 return -1;
213             }
215             /* parse the remainder of the arguments */
216             switch (dst_conv(rrd.ds_def[rrd.stat_head->ds_cnt].dst)) {
217             case DST_COUNTER:
218             case DST_ABSOLUTE:
219             case DST_GAUGE:
220             case DST_DERIVE:
221                 parseGENERIC_DS(&argv[i][offset + 3], &rrd,
222                                 rrd.stat_head->ds_cnt);
223                 break;
224             case DST_CDEF:
225                 parseCDEF_DS(&argv[i][offset + 3], &rrd,
226                              rrd.stat_head->ds_cnt);
227                 break;
228             default:
229                 rrd_set_error("invalid DS type specified");
230                 break;
231             }
233             if (rrd_test_error()) {
234                 rrd_free2(&rrd);
235                 return -1;
236             }
237             rrd.stat_head->ds_cnt++;
238         } else if (strncmp(argv[i], "RRA:", 4) == 0) {
239             char     *argvcopy;
240             char     *tokptr = "";
241             int       cf_id = -1;
242             size_t    old_size = sizeof(rra_def_t) * (rrd.stat_head->rra_cnt);
243             int       row_cnt;
244             int       token_min = 4;
245             if ((rrd.rra_def = (rra_def_t*)rrd_realloc(rrd.rra_def,
246                                            old_size + sizeof(rra_def_t))) ==
247                 NULL) {
248                 rrd_set_error("allocating rrd.rra_def");
249                 rrd_free2(&rrd);
250                 return (-1);
251             }
252             memset(&rrd.rra_def[rrd.stat_head->rra_cnt], 0,
253                    sizeof(rra_def_t));
255             argvcopy = strdup(argv[i]);
256             token = strtok_r(&argvcopy[4], ":", &tokptr);
257             token_idx = error_flag = 0;
258             
259             while (token != NULL) {
260                 switch (token_idx) {
261                 case 0:
262                     if (sscanf(token, CF_NAM_FMT,
263                                rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam) !=
264                         1)
265                         rrd_set_error("Failed to parse CF name");
266                     cf_id = cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam);
267                     switch (cf_id) {
268                     case CF_MHWPREDICT:
269                         strcpy(rrd.stat_head->version, RRD_VERSION);    /* MHWPREDICT causes Version 4 */
270                     case CF_HWPREDICT:
271                         token_min = 5;
272                         /* initialize some parameters */
273                         rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_hw_alpha].
274                             u_val = 0.1;
275                         rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_hw_beta].
276                             u_val = 1.0 / 288;
277                         rrd.rra_def[rrd.stat_head->rra_cnt].
278                             par[RRA_dependent_rra_idx].u_cnt =
279                             rrd.stat_head->rra_cnt;
280                         break;
281                     case CF_DEVSEASONAL:
282                         token_min = 3;
283                     case CF_SEASONAL:
284                         if (cf_id == CF_SEASONAL){
285                            token_min = 4;
286                         }
287                         /* initialize some parameters */
288                         rrd.rra_def[rrd.stat_head->rra_cnt].
289                             par[RRA_seasonal_gamma].u_val = 0.1;
290                         rrd.rra_def[rrd.stat_head->rra_cnt].
291                             par[RRA_seasonal_smoothing_window].u_val = 0.05;
292                         /* fall through */
293                     case CF_DEVPREDICT:
294                         if (cf_id == CF_DEVPREDICT){
295                            token_min = 3;
296                         }
297                         rrd.rra_def[rrd.stat_head->rra_cnt].
298                             par[RRA_dependent_rra_idx].u_cnt = -1;
299                         break;
300                     case CF_FAILURES:
301                         token_min = 5;
302                         rrd.rra_def[rrd.stat_head->rra_cnt].
303                             par[RRA_delta_pos].u_val = 2.0;
304                         rrd.rra_def[rrd.stat_head->rra_cnt].
305                             par[RRA_delta_neg].u_val = 2.0;
306                         rrd.rra_def[rrd.stat_head->rra_cnt].
307                             par[RRA_window_len].u_cnt = 3;
308                         rrd.rra_def[rrd.stat_head->rra_cnt].
309                             par[RRA_failure_threshold].u_cnt = 2;
310                         rrd.rra_def[rrd.stat_head->rra_cnt].
311                             par[RRA_dependent_rra_idx].u_cnt = -1;
312                         break;
313                         /* invalid consolidation function */
314                     case -1:
315                         rrd_set_error
316                             ("Unrecognized consolidation function %s",
317                              rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam);
318                     default:
319                         break;
320                     }
321                     /* default: 1 pdp per cdp */
322                     rrd.rra_def[rrd.stat_head->rra_cnt].pdp_cnt = 1;
323                     break;
324                 case 1:
325                     switch (cf_conv
326                             (rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
327                     case CF_HWPREDICT:
328                     case CF_MHWPREDICT:
329                     case CF_DEVSEASONAL:
330                     case CF_SEASONAL:
331                     case CF_DEVPREDICT:
332                     case CF_FAILURES:
333                         row_cnt = atoi(token);
334                         if (row_cnt <= 0)
335                             rrd_set_error("Invalid row count: %i", row_cnt);
336                         rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt = row_cnt;
337                         break;
338                     default:
339                         rrd.rra_def[rrd.stat_head->rra_cnt].
340                             par[RRA_cdp_xff_val].u_val = atof(token);
341                         if (rrd.rra_def[rrd.stat_head->rra_cnt].
342                             par[RRA_cdp_xff_val].u_val < 0.0
343                             || rrd.rra_def[rrd.stat_head->rra_cnt].
344                             par[RRA_cdp_xff_val].u_val >= 1.0)
345                             rrd_set_error
346                                 ("Invalid xff: must be between 0 and 1");
347                         break;
348                     }
349                     break;
350                 case 2:
351                     switch (cf_conv
352                             (rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
353                     case CF_HWPREDICT:
354                     case CF_MHWPREDICT:
355                         rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_hw_alpha].
356                             u_val = atof(token);
357                         if (atof(token) <= 0.0 || atof(token) >= 1.0)
358                             rrd_set_error
359                                 ("Invalid alpha: must be between 0 and 1");
360                         break;
361                     case CF_DEVSEASONAL:
362                     case CF_SEASONAL:
363                         rrd.rra_def[rrd.stat_head->rra_cnt].
364                             par[RRA_seasonal_gamma].u_val = atof(token);
365                         if (atof(token) <= 0.0 || atof(token) >= 1.0)
366                             rrd_set_error
367                                 ("Invalid gamma: must be between 0 and 1");
368                         rrd.rra_def[rrd.stat_head->rra_cnt].
369                             par[RRA_seasonal_smooth_idx].u_cnt =
370                             hashed_name %
371                             rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt;
372                         break;
373                     case CF_FAILURES:
374                         /* specifies the # of violations that constitutes the failure threshold */
375                         rrd.rra_def[rrd.stat_head->rra_cnt].
376                             par[RRA_failure_threshold].u_cnt = atoi(token);
377                         if (atoi(token) < 1
378                             || atoi(token) > MAX_FAILURES_WINDOW_LEN)
379                             rrd_set_error
380                                 ("Failure threshold is out of range %d, %d",
381                                  1, MAX_FAILURES_WINDOW_LEN);
382                         break;
383                     case CF_DEVPREDICT:
384                         /* specifies the index (1-based) of CF_DEVSEASONAL array
385                          * associated with this CF_DEVPREDICT array. */
386                         rrd.rra_def[rrd.stat_head->rra_cnt].
387                             par[RRA_dependent_rra_idx].u_cnt =
388                             atoi(token) - 1;
389                         break;
390                     default:
391                         rrd.rra_def[rrd.stat_head->rra_cnt].pdp_cnt =
392                             atoi(token);
393                         if (atoi(token) < 1)
394                             rrd_set_error("Invalid step: must be >= 1");
395                         break;
396                     }
397                     break;
398                 case 3:
399                     switch (cf_conv
400                             (rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
401                     case CF_HWPREDICT:
402                     case CF_MHWPREDICT:
403                         rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_hw_beta].
404                             u_val = atof(token);
405                         if (atof(token) < 0.0 || atof(token) > 1.0)
406                             rrd_set_error
407                                 ("Invalid beta: must be between 0 and 1");
408                         break;
409                     case CF_DEVSEASONAL:
410                     case CF_SEASONAL:
411                         /* specifies the index (1-based) of CF_HWPREDICT array
412                          * associated with this CF_DEVSEASONAL or CF_SEASONAL array. 
413                          * */
414                         rrd.rra_def[rrd.stat_head->rra_cnt].
415                             par[RRA_dependent_rra_idx].u_cnt =
416                             atoi(token) - 1;
417                         break;
418                     case CF_FAILURES:
419                         /* specifies the window length */
420                         rrd.rra_def[rrd.stat_head->rra_cnt].
421                             par[RRA_window_len].u_cnt = atoi(token);
422                         if (atoi(token) < 1
423                             || atoi(token) > MAX_FAILURES_WINDOW_LEN)
424                             rrd_set_error
425                                 ("Window length is out of range %d, %d", 1,
426                                  MAX_FAILURES_WINDOW_LEN);
427                         /* verify that window length exceeds the failure threshold */
428                         if (rrd.rra_def[rrd.stat_head->rra_cnt].
429                             par[RRA_window_len].u_cnt <
430                             rrd.rra_def[rrd.stat_head->rra_cnt].
431                             par[RRA_failure_threshold].u_cnt)
432                             rrd_set_error
433                                 ("Window length is shorter than the failure threshold");
434                         break;
435                     case CF_DEVPREDICT:
436                         /* shouldn't be any more arguments */
437                         rrd_set_error
438                             ("Unexpected extra argument for consolidation function DEVPREDICT");
439                         break;
440                     default:
441                         row_cnt = atoi(token);
442                         if (row_cnt <= 0)
443                             rrd_set_error("Invalid row count: %i", row_cnt);
444                         rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt = row_cnt;
445                         break;
446                     }
447                     break;
448                 case 4:
449                     switch (cf_conv
450                             (rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
451                     case CF_FAILURES:
452                         /* specifies the index (1-based) of CF_DEVSEASONAL array
453                          * associated with this CF_DEVFAILURES array. */
454                         rrd.rra_def[rrd.stat_head->rra_cnt].
455                             par[RRA_dependent_rra_idx].u_cnt =
456                             atoi(token) - 1;
457                         break;
458                     case CF_DEVSEASONAL:
459                     case CF_SEASONAL:
460                         /* optional smoothing window */
461                         if (sscanf(token, "smoothing-window=%lf",
462                                    &(rrd.rra_def[rrd.stat_head->rra_cnt].
463                                      par[RRA_seasonal_smoothing_window].
464                                      u_val))) {
465                             strcpy(rrd.stat_head->version, RRD_VERSION);    /* smoothing-window causes Version 4 */
466                             if (rrd.rra_def[rrd.stat_head->rra_cnt].
467                                 par[RRA_seasonal_smoothing_window].u_val < 0.0
468                                 || rrd.rra_def[rrd.stat_head->rra_cnt].
469                                 par[RRA_seasonal_smoothing_window].u_val >
470                                 1.0) {
471                                 rrd_set_error
472                                     ("Invalid smoothing-window %f: must be between 0 and 1",
473                                      rrd.rra_def[rrd.stat_head->rra_cnt].
474                                      par[RRA_seasonal_smoothing_window].
475                                      u_val);
476                             }
477                         } else {
478                             rrd_set_error("Invalid option %s", token);
479                         }
480                         break;
481                     case CF_HWPREDICT:
482                     case CF_MHWPREDICT:
483                         /* length of the associated CF_SEASONAL and CF_DEVSEASONAL arrays. */
484                         period = atoi(token);
485                         if (period >
486                             rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt)
487                             rrd_set_error
488                                 ("Length of seasonal cycle exceeds length of HW prediction array");
489                         break;
490                     default:
491                         /* shouldn't be any more arguments */
492                         rrd_set_error
493                             ("Unexpected extra argument for consolidation function %s",
494                              rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam);
495                         break;
496                     }
497                     break;
498                 case 5:
499                     /* If we are here, this must be a CF_HWPREDICT RRA.
500                      * Specifies the index (1-based) of CF_SEASONAL array
501                      * associated with this CF_HWPREDICT array. If this argument 
502                      * is missing, then the CF_SEASONAL, CF_DEVSEASONAL, CF_DEVPREDICT,
503                      * CF_FAILURES.
504                      * arrays are created automatically. */
505                     rrd.rra_def[rrd.stat_head->rra_cnt].
506                         par[RRA_dependent_rra_idx].u_cnt = atoi(token) - 1;
507                     break;
508                 default:
509                     /* should never get here */
510                     rrd_set_error("Unknown error");
511                     break;
512                 }       /* end switch */
513                 if (rrd_test_error()) {
514                     /* all errors are unrecoverable */
515                     free(argvcopy);
516                     rrd_free2(&rrd);
517                     return (-1);
518                 }
519                 token = strtok_r(NULL, ":", &tokptr);
520                 token_idx++;
521             }           /* end while */
522             free(argvcopy);
523             if (token_idx < token_min){
524                 rrd_set_error("Expected at least %i arguments for RRA but got %i",token_min,token_idx);
525                 rrd_free2(&rrd);
526                 return(-1);
527             }
528 #ifdef DEBUG
529             fprintf(stderr,
530                     "Creating RRA CF: %s, dep idx %lu, current idx %lu\n",
531                     rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam,
532                     rrd.rra_def[rrd.stat_head->rra_cnt].
533                     par[RRA_dependent_rra_idx].u_cnt, rrd.stat_head->rra_cnt);
534 #endif
535             /* should we create CF_SEASONAL, CF_DEVSEASONAL, and CF_DEVPREDICT? */
536             if ((cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam) ==
537                  CF_HWPREDICT
538                  || cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam) ==
539                  CF_MHWPREDICT)
540                 && rrd.rra_def[rrd.stat_head->rra_cnt].
541                 par[RRA_dependent_rra_idx].u_cnt == rrd.stat_head->rra_cnt) {
542 #ifdef DEBUG
543                 fprintf(stderr, "Creating HW contingent RRAs\n");
544 #endif
545                 if (create_hw_contingent_rras(&rrd, period, hashed_name) ==
546                     -1) {
547                     rrd_set_error("creating contingent RRA");
548                     rrd_free2(&rrd);
549                     return -1;
550                 }
551             }
552             rrd.stat_head->rra_cnt++;
553         } else {
554             rrd_set_error("can't parse argument '%s'", argv[i]);
555             rrd_free2(&rrd);
556             return -1;
557         }
558     }
561     if (rrd.stat_head->rra_cnt < 1) {
562         rrd_set_error("you must define at least one Round Robin Archive");
563         rrd_free2(&rrd);
564         return (-1);
565     }
567     if (rrd.stat_head->ds_cnt < 1) {
568         rrd_set_error("you must define at least one Data Source");
569         rrd_free2(&rrd);
570         return (-1);
571     }
572     return rrd_create_fn(filename, &rrd);
575 void parseGENERIC_DS(
576     const char *def,
577     rrd_t *rrd,
578     int ds_idx)
580     char      minstr[DS_NAM_SIZE], maxstr[DS_NAM_SIZE];
581     char     *old_locale;
583     /*
584        int temp;
586        temp = sscanf(def,"%lu:%18[^:]:%18[^:]", 
587        &(rrd -> ds_def[ds_idx].par[DS_mrhb_cnt].u_cnt),
588        minstr,maxstr);
589      */
590     old_locale = setlocale(LC_NUMERIC, NULL);
591     setlocale(LC_NUMERIC, "C");
592     if (sscanf(def, "%lu:%18[^:]:%18[^:]",
593                &(rrd->ds_def[ds_idx].par[DS_mrhb_cnt].u_cnt),
594                minstr, maxstr) == 3) {
595         if (minstr[0] == 'U' && minstr[1] == 0)
596             rrd->ds_def[ds_idx].par[DS_min_val].u_val = DNAN;
597         else
598             rrd->ds_def[ds_idx].par[DS_min_val].u_val = atof(minstr);
600         if (maxstr[0] == 'U' && maxstr[1] == 0)
601             rrd->ds_def[ds_idx].par[DS_max_val].u_val = DNAN;
602         else
603             rrd->ds_def[ds_idx].par[DS_max_val].u_val = atof(maxstr);
605         if (!isnan(rrd->ds_def[ds_idx].par[DS_min_val].u_val) &&
606             !isnan(rrd->ds_def[ds_idx].par[DS_max_val].u_val) &&
607             rrd->ds_def[ds_idx].par[DS_min_val].u_val
608             >= rrd->ds_def[ds_idx].par[DS_max_val].u_val) {
609             rrd_set_error("min must be less than max in DS definition");
610             setlocale(LC_NUMERIC, old_locale);
611             return;
612         }
613     } else {
614         rrd_set_error("failed to parse data source %s", def);
615     }
616     setlocale(LC_NUMERIC, old_locale);
619 /* Create the CF_DEVPREDICT, CF_DEVSEASONAL, CF_SEASONAL, and CF_FAILURES RRAs
620  * associated with a CF_HWPREDICT RRA. */
621 int create_hw_contingent_rras(
622     rrd_t *rrd,
623     unsigned short period,
624     unsigned long hashed_name)
626     size_t    old_size;
627     rra_def_t *current_rra;
629     /* save index to CF_HWPREDICT */
630     unsigned long hw_index = rrd->stat_head->rra_cnt;
632     /* advance the pointer */
633     (rrd->stat_head->rra_cnt)++;
634     /* allocate the memory for the 4 contingent RRAs */
635     old_size = sizeof(rra_def_t) * (rrd->stat_head->rra_cnt);
636     if ((rrd->rra_def = (rra_def_t*)rrd_realloc(rrd->rra_def,
637                                     old_size + 4 * sizeof(rra_def_t))) ==
638         NULL) {
639         rrd_free2(rrd);
640         rrd_set_error("allocating rrd.rra_def");
641         return (-1);
642     }
643     /* clear memory */
644     memset(&(rrd->rra_def[rrd->stat_head->rra_cnt]), 0,
645            4 * sizeof(rra_def_t));
647     /* create the CF_SEASONAL RRA */
648     current_rra = &(rrd->rra_def[rrd->stat_head->rra_cnt]);
649     strcpy(current_rra->cf_nam, "SEASONAL");
650     current_rra->row_cnt = period;
651     current_rra->par[RRA_seasonal_smooth_idx].u_cnt = hashed_name % period;
652     current_rra->pdp_cnt = 1;
653     current_rra->par[RRA_seasonal_gamma].u_val =
654         rrd->rra_def[hw_index].par[RRA_hw_alpha].u_val;
655     current_rra->par[RRA_dependent_rra_idx].u_cnt = hw_index;
656     rrd->rra_def[hw_index].par[RRA_dependent_rra_idx].u_cnt =
657         rrd->stat_head->rra_cnt;
659     /* create the CF_DEVSEASONAL RRA */
660     (rrd->stat_head->rra_cnt)++;
661     current_rra = &(rrd->rra_def[rrd->stat_head->rra_cnt]);
662     strcpy(current_rra->cf_nam, "DEVSEASONAL");
663     current_rra->row_cnt = period;
664     current_rra->par[RRA_seasonal_smooth_idx].u_cnt = hashed_name % period;
665     current_rra->pdp_cnt = 1;
666     current_rra->par[RRA_seasonal_gamma].u_val =
667         rrd->rra_def[hw_index].par[RRA_hw_alpha].u_val;
668     current_rra->par[RRA_dependent_rra_idx].u_cnt = hw_index;
670     /* create the CF_DEVPREDICT RRA */
671     (rrd->stat_head->rra_cnt)++;
672     current_rra = &(rrd->rra_def[rrd->stat_head->rra_cnt]);
673     strcpy(current_rra->cf_nam, "DEVPREDICT");
674     current_rra->row_cnt = (rrd->rra_def[hw_index]).row_cnt;
675     current_rra->pdp_cnt = 1;
676     current_rra->par[RRA_dependent_rra_idx].u_cnt = hw_index + 2;   /* DEVSEASONAL */
678     /* create the CF_FAILURES RRA */
679     (rrd->stat_head->rra_cnt)++;
680     current_rra = &(rrd->rra_def[rrd->stat_head->rra_cnt]);
681     strcpy(current_rra->cf_nam, "FAILURES");
682     current_rra->row_cnt = period;
683     current_rra->pdp_cnt = 1;
684     current_rra->par[RRA_delta_pos].u_val = 2.0;
685     current_rra->par[RRA_delta_neg].u_val = 2.0;
686     current_rra->par[RRA_failure_threshold].u_cnt = 7;
687     current_rra->par[RRA_window_len].u_cnt = 9;
688     current_rra->par[RRA_dependent_rra_idx].u_cnt = hw_index + 2;   /* DEVSEASONAL */
689     return 0;
692 /* create and empty rrd file according to the specs given */
694 int rrd_create_fn(
695     const char *file_name,
696     rrd_t *rrd)
698     unsigned long i, ii;
699     rrd_value_t *unknown;
700     int       unkn_cnt;
701     rrd_file_t *rrd_file_dn;
702     rrd_t     rrd_dn;
703     unsigned  rrd_flags = RRD_READWRITE | RRD_CREAT;
705     if (opt_no_overwrite) {
706       rrd_flags |= RRD_EXCL ;
707     }
709     unkn_cnt = 0;
710     for (i = 0; i < rrd->stat_head->rra_cnt; i++)
711         unkn_cnt += rrd->stat_head->ds_cnt * rrd->rra_def[i].row_cnt;
713     if ((rrd_file_dn = rrd_open(file_name, rrd, rrd_flags)) == NULL) {
714         rrd_set_error("creating '%s': %s", file_name, rrd_strerror(errno));
715         rrd_free2(rrd);
716         return (-1);
717     }
719     rrd_write(rrd_file_dn, rrd->stat_head, sizeof(stat_head_t));
721     rrd_write(rrd_file_dn, rrd->ds_def, sizeof(ds_def_t) * rrd->stat_head->ds_cnt);
723     rrd_write(rrd_file_dn, rrd->rra_def,
724           sizeof(rra_def_t) * rrd->stat_head->rra_cnt);
726     rrd_write(rrd_file_dn, rrd->live_head, sizeof(live_head_t));
728     if ((rrd->pdp_prep = (pdp_prep_t*)calloc(1, sizeof(pdp_prep_t))) == NULL) {
729         rrd_set_error("allocating pdp_prep");
730         rrd_free2(rrd);
731         rrd_close(rrd_file_dn);
732         return (-1);
733     }
735     strcpy(rrd->pdp_prep->last_ds, "U");
737     rrd->pdp_prep->scratch[PDP_val].u_val = 0.0;
738     rrd->pdp_prep->scratch[PDP_unkn_sec_cnt].u_cnt =
739         rrd->live_head->last_up % rrd->stat_head->pdp_step;
741     for (i = 0; i < rrd->stat_head->ds_cnt; i++)
742         rrd_write(rrd_file_dn, rrd->pdp_prep, sizeof(pdp_prep_t));
744     if ((rrd->cdp_prep = (cdp_prep_t*)calloc(1, sizeof(cdp_prep_t))) == NULL) {
745         rrd_set_error("allocating cdp_prep");
746         rrd_free2(rrd);
747         rrd_close(rrd_file_dn);
748         return (-1);
749     }
752     for (i = 0; i < rrd->stat_head->rra_cnt; i++) {
753         switch (cf_conv(rrd->rra_def[i].cf_nam)) {
754         case CF_HWPREDICT:
755         case CF_MHWPREDICT:
756             init_hwpredict_cdp(rrd->cdp_prep);
757             break;
758         case CF_SEASONAL:
759         case CF_DEVSEASONAL:
760             init_seasonal_cdp(rrd->cdp_prep);
761             break;
762         case CF_FAILURES:
763             /* initialize violation history to 0 */
764             for (ii = 0; ii < MAX_CDP_PAR_EN; ii++) {
765                 /* We can zero everything out, by setting u_val to the
766                  * NULL address. Each array entry in scratch is 8 bytes
767                  * (a double), but u_cnt only accessed 4 bytes (long) */
768                 rrd->cdp_prep->scratch[ii].u_val = 0.0;
769             }
770             break;
771         default:
772             /* can not be zero because we don't know anything ... */
773             rrd->cdp_prep->scratch[CDP_val].u_val = DNAN;
774             /* startup missing pdp count */
775             rrd->cdp_prep->scratch[CDP_unkn_pdp_cnt].u_cnt =
776                 ((rrd->live_head->last_up -
777                   rrd->pdp_prep->scratch[PDP_unkn_sec_cnt].u_cnt)
778                  % (rrd->stat_head->pdp_step
779                     * rrd->rra_def[i].pdp_cnt)) / rrd->stat_head->pdp_step;
780             break;
781         }
783         for (ii = 0; ii < rrd->stat_head->ds_cnt; ii++) {
784             rrd_write(rrd_file_dn, rrd->cdp_prep, sizeof(cdp_prep_t));
785         }
786     }
788     /* now, we must make sure that the rest of the rrd
789        struct is properly initialized */
791     if ((rrd->rra_ptr = (rra_ptr_t*)calloc(1, sizeof(rra_ptr_t))) == NULL) {
792         rrd_set_error("allocating rra_ptr");
793         rrd_free2(rrd);
794         rrd_close(rrd_file_dn);
795         return (-1);
796     }
798     /* changed this initialization to be consistent with
799      * rrd_restore. With the old value (0), the first update
800      * would occur for cur_row = 1 because rrd_update increments
801      * the pointer a priori. */
802     for (i = 0; i < rrd->stat_head->rra_cnt; i++) {
803         rrd->rra_ptr->cur_row = rrd_select_initial_row(rrd_file_dn, i, &rrd->rra_def[i]);
804         rrd_write(rrd_file_dn, rrd->rra_ptr, sizeof(rra_ptr_t));
805     }
807     /* write the empty data area */
808     if ((unknown = (rrd_value_t *) malloc(512 * sizeof(rrd_value_t))) == NULL) {
809         rrd_set_error("allocating unknown");
810         rrd_free2(rrd);
811         rrd_close(rrd_file_dn);
812         return (-1);
813     }
814     for (i = 0; i < 512; ++i)
815         unknown[i] = DNAN;
817     while (unkn_cnt > 0) {
818         if(rrd_write(rrd_file_dn, unknown, sizeof(rrd_value_t) * min(unkn_cnt, 512)) < 0)
819         {
820             rrd_set_error("creating rrd: %s", rrd_strerror(errno));
821             return -1;
822         }
824         unkn_cnt -= 512;
825     }
826     free(unknown);
827     rrd_free2(rrd);
828     if (rrd_close(rrd_file_dn) == -1) {
829         rrd_set_error("creating rrd: %s", rrd_strerror(errno));
830         return -1;
831     }
832     /* flush all we don't need out of the cache */
833     rrd_init(&rrd_dn);
834     if((rrd_file_dn = rrd_open(file_name, &rrd_dn, RRD_READONLY)) != NULL)
835     {
836         rrd_dontneed(rrd_file_dn, &rrd_dn);
837         /* rrd_free(&rrd_dn); */
838         rrd_close(rrd_file_dn);
839     }
840     return (0);
844 static void rrd_free2(
845     rrd_t *rrd)
847     free(rrd->live_head);
848     free(rrd->stat_head);
849     free(rrd->ds_def);
850     free(rrd->rra_def);
851     free(rrd->rra_ptr);
852     free(rrd->pdp_prep);
853     free(rrd->cdp_prep);
854     free(rrd->rrd_value);