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;
116 }
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)
125 {
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;
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);
573 }
575 void parseGENERIC_DS(
576 const char *def,
577 rrd_t *rrd,
578 int ds_idx)
579 {
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);
617 }
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)
625 {
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;
690 }
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)
697 {
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);
841 }
844 static void rrd_free2(
845 rrd_t *rrd)
846 {
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);
855 }