Bernhard Fischer:
[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         free(rrd->stat_head);
636         rrd->stat_head = NULL;
637         free(rrd->ds_def);
638         rrd->ds_def = NULL;
639         free(rrd->rra_def);
640         rrd->rra_def = NULL;
641         return (-1);
642     }
643
644     fwrite(rrd->stat_head, sizeof(stat_head_t), 1, rrd_file);
645
646     fwrite(rrd->ds_def, sizeof(ds_def_t), rrd->stat_head->ds_cnt, rrd_file);
647
648     fwrite(rrd->rra_def,
649            sizeof(rra_def_t), rrd->stat_head->rra_cnt, rrd_file);
650
651     fwrite(rrd->live_head, sizeof(live_head_t), 1, rrd_file);
652
653     if ((rrd->pdp_prep = calloc(1, sizeof(pdp_prep_t))) == NULL) {
654         rrd_set_error("allocating pdp_prep");
655         rrd_free(rrd);
656         fclose(rrd_file);
657         return (-1);
658     }
659
660     strcpy(rrd->pdp_prep->last_ds, "UNKN");
661
662     rrd->pdp_prep->scratch[PDP_val].u_val = 0.0;
663     rrd->pdp_prep->scratch[PDP_unkn_sec_cnt].u_cnt =
664         rrd->live_head->last_up % rrd->stat_head->pdp_step;
665
666     for (i = 0; i < rrd->stat_head->ds_cnt; i++)
667         fwrite(rrd->pdp_prep, sizeof(pdp_prep_t), 1, rrd_file);
668
669     if ((rrd->cdp_prep = calloc(1, sizeof(cdp_prep_t))) == NULL) {
670         rrd_set_error("allocating cdp_prep");
671         rrd_free(rrd);
672         fclose(rrd_file);
673         return (-1);
674     }
675
676
677     for (i = 0; i < rrd->stat_head->rra_cnt; i++) {
678         switch (cf_conv(rrd->rra_def[i].cf_nam)) {
679         case CF_HWPREDICT:
680         case CF_MHWPREDICT:
681             init_hwpredict_cdp(rrd->cdp_prep);
682             break;
683         case CF_SEASONAL:
684         case CF_DEVSEASONAL:
685             init_seasonal_cdp(rrd->cdp_prep);
686             break;
687         case CF_FAILURES:
688             /* initialize violation history to 0 */
689             for (ii = 0; ii < MAX_CDP_PAR_EN; ii++) {
690                 /* We can zero everything out, by setting u_val to the
691                  * NULL address. Each array entry in scratch is 8 bytes
692                  * (a double), but u_cnt only accessed 4 bytes (long) */
693                 rrd->cdp_prep->scratch[ii].u_val = 0.0;
694             }
695             break;
696         default:
697             /* can not be zero because we don't know anything ... */
698             rrd->cdp_prep->scratch[CDP_val].u_val = DNAN;
699             /* startup missing pdp count */
700             rrd->cdp_prep->scratch[CDP_unkn_pdp_cnt].u_cnt =
701                 ((rrd->live_head->last_up -
702                   rrd->pdp_prep->scratch[PDP_unkn_sec_cnt].u_cnt)
703                  % (rrd->stat_head->pdp_step
704                     * rrd->rra_def[i].pdp_cnt)) / rrd->stat_head->pdp_step;
705             break;
706         }
707
708         for (ii = 0; ii < rrd->stat_head->ds_cnt; ii++) {
709             fwrite(rrd->cdp_prep, sizeof(cdp_prep_t), 1, rrd_file);
710         }
711     }
712
713     /* now, we must make sure that the rest of the rrd
714        struct is properly initialized */
715
716     if ((rrd->rra_ptr = calloc(1, sizeof(rra_ptr_t))) == NULL) {
717         rrd_set_error("allocating rra_ptr");
718         rrd_free(rrd);
719         fclose(rrd_file);
720         return (-1);
721     }
722
723     /* changed this initialization to be consistent with
724      * rrd_restore. With the old value (0), the first update
725      * would occur for cur_row = 1 because rrd_update increments
726      * the pointer a priori. */
727     for (i = 0; i < rrd->stat_head->rra_cnt; i++) {
728         rrd->rra_ptr->cur_row = rrd->rra_def[i].row_cnt - 1;
729         fwrite(rrd->rra_ptr, sizeof(rra_ptr_t), 1, rrd_file);
730     }
731     rrd_head_size = ftell(rrd_file);
732
733     /* write the empty data area */
734     if ((unknown = (rrd_value_t *) malloc(512 * sizeof(rrd_value_t))) == NULL) {
735         rrd_set_error("allocating unknown");
736         rrd_free(rrd);
737         fclose(rrd_file);
738         return (-1);
739     }
740     for (i = 0; i < 512; ++i)
741         unknown[i] = DNAN;
742
743     unkn_cnt = 0;
744     for (i = 0; i < rrd->stat_head->rra_cnt; i++)
745         unkn_cnt += rrd->stat_head->ds_cnt * rrd->rra_def[i].row_cnt;
746
747     while (unkn_cnt > 0) {
748         fwrite(unknown, sizeof(rrd_value_t), min(unkn_cnt, 512), rrd_file);
749         unkn_cnt -= 512;
750     }
751     free(unknown);
752
753     /* lets see if we had an error */
754     if (ferror(rrd_file)) {
755         rrd_set_error("a file error occurred while creating '%s'", file_name);
756         fclose(rrd_file);
757         rrd_free(rrd);
758         return (-1);
759     }
760 #ifdef HAVE_POSIX_FADVISE
761     /* this file is not going to be read again any time
762        soon, so we drop everything except the header portion from
763        the buffer cache. for this to work, we have to fdsync the file
764        first though. This will not be all that fast, but 'good' data
765        like other rrdfiles headers will stay in cache. Now this only works if creating
766        a single rrd file is not too large, but I assume this should not be the case
767        in general. Otherwhise we would have to sync and release while writing all
768        the unknown data. */
769     fflush(rrd_file);
770     fdatasync(fileno(rrd_file));
771     if (0 !=
772         posix_fadvise(fileno(rrd_file), rrd_head_size, 0,
773                       POSIX_FADV_DONTNEED)) {
774         rrd_set_error("setting POSIX_FADV_DONTNEED on '%s': %s", file_name,
775                       rrd_strerror(errno));
776         fclose(rrd_file);
777         return (-1);
778     }
779 #endif
780
781     fclose(rrd_file);
782     rrd_free(rrd);
783     return (0);
784 }