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