]> git.ipfire.org Git - thirdparty/rrdtool-1.x.git/commitdiff
Factor out RRA definition parsing so it may be reused for rrdtool modify.
authorPeter Stamfest <peter@stamfest.at>
Thu, 27 Feb 2014 13:33:33 +0000 (14:33 +0100)
committerPeter Stamfest <peter@stamfest.at>
Thu, 27 Feb 2014 13:33:33 +0000 (14:33 +0100)
src/rrd_create.c
src/rrd_format.h
src/rrd_hw.h
src/rrd_modify.c

index e629a89a894661c6cd098d1aceff21d553e965c7..dfde17f9e31d0f75a0aee5feb3e4f0a4d5201ef7 100644 (file)
@@ -7,6 +7,7 @@
 #include <stdlib.h>
 #include <time.h>
 #include <locale.h>
+#include <math.h>
 
 #include "rrd_tool.h"
 #include "rrd_rpncalc.h"
 
 unsigned long FnvHash(
     const char *str);
-int       create_hw_contingent_rras(
-    rrd_t *rrd,
-    unsigned short period,
-    unsigned long hashed_name);
 void      parseGENERIC_DS(
     const char *def,
     ds_def_t *ds_def);
@@ -190,6 +187,304 @@ int parseDS(const char *def,
 }
 
 
+static int parseRRA(const char *def,
+                   rra_def_t *rra_def, 
+                   unsigned long hash) {
+    char     *argvcopy;
+    char     *tokptr = "";
+    unsigned short token_idx, error_flag, period = 0;
+    int       cf_id = -1;
+    int       token_min = 4;
+    int       row_cnt;
+
+    memset(rra_def, 0, sizeof(rra_def_t));
+
+    argvcopy = strdup(def);
+    char *token = strtok_r(&argvcopy[4], ":", &tokptr);
+    token_idx = error_flag = 0;
+            
+    while (token != NULL) {
+       switch (token_idx) {
+       case 0:
+           if (sscanf(token, CF_NAM_FMT, rra_def->cf_nam) != 1)
+               rrd_set_error("Failed to parse CF name");
+           cf_id = cf_conv(rra_def->cf_nam);
+           switch (cf_id) {
+           case CF_MHWPREDICT:
+               // FIXME                strcpy(rrd.stat_head->version, RRD_VERSION);    /* MHWPREDICT causes Version 4 */
+           case CF_HWPREDICT:
+               token_min = 5;
+               /* initialize some parameters */
+               rra_def->par[RRA_hw_alpha].
+                   u_val = 0.1;
+               rra_def->par[RRA_hw_beta].
+                   u_val = 1.0 / 288;
+               rra_def->par[RRA_dependent_rra_idx].u_cnt = INT_MAX;
+               break;
+           case CF_DEVSEASONAL:
+               token_min = 3;
+           case CF_SEASONAL:
+               if (cf_id == CF_SEASONAL){
+                   token_min = 4;
+               }
+               /* initialize some parameters */
+               rra_def->par[RRA_seasonal_gamma].u_val = 0.1;
+               rra_def->par[RRA_seasonal_smoothing_window].u_val = 0.05;
+               /* fall through */
+           case CF_DEVPREDICT:
+               if (cf_id == CF_DEVPREDICT){
+                   token_min = 3;
+               }
+               rra_def->par[RRA_dependent_rra_idx].u_cnt = -1;
+               break;
+           case CF_FAILURES:
+               token_min = 5;
+               rra_def->par[RRA_delta_pos].u_val = 2.0;
+               rra_def->par[RRA_delta_neg].u_val = 2.0;
+               rra_def->par[RRA_window_len].u_cnt = 3;
+               rra_def->par[RRA_failure_threshold].u_cnt = 2;
+               rra_def->par[RRA_dependent_rra_idx].u_cnt = -1;
+               break;
+               /* invalid consolidation function */
+           case -1:
+               rrd_set_error
+                   ("Unrecognized consolidation function %s",
+                    rra_def->cf_nam);
+           default:
+               break;
+           }
+           /* default: 1 pdp per cdp */
+           rra_def->pdp_cnt = 1;
+           break;
+       case 1:
+           switch (cf_conv
+                   (rra_def->cf_nam)) {
+           case CF_HWPREDICT:
+           case CF_MHWPREDICT:
+           case CF_DEVSEASONAL:
+           case CF_SEASONAL:
+           case CF_DEVPREDICT:
+           case CF_FAILURES:
+               row_cnt = atoi(token);
+               if (row_cnt <= 0)
+                   rrd_set_error("Invalid row count: %i", row_cnt);
+               rra_def->row_cnt = row_cnt;
+               break;
+           default:
+               rra_def->par[RRA_cdp_xff_val].u_val = atof(token);
+               if (rra_def->par[RRA_cdp_xff_val].u_val < 0.0
+                   || rra_def->par[RRA_cdp_xff_val].u_val >= 1.0)
+                   rrd_set_error
+                       ("Invalid xff: must be between 0 and 1");
+               break;
+           }
+           break;
+       case 2:
+           switch (cf_conv
+                   (rra_def->cf_nam)) {
+           case CF_HWPREDICT:
+           case CF_MHWPREDICT:
+               rra_def->par[RRA_hw_alpha].
+                   u_val = atof(token);
+               if (atof(token) <= 0.0 || atof(token) >= 1.0)
+                   rrd_set_error
+                       ("Invalid alpha: must be between 0 and 1");
+               break;
+           case CF_DEVSEASONAL:
+           case CF_SEASONAL:
+               rra_def->par[RRA_seasonal_gamma].u_val = atof(token);
+               if (atof(token) <= 0.0 || atof(token) >= 1.0)
+                   rrd_set_error
+                       ("Invalid gamma: must be between 0 and 1");
+               rra_def->par[RRA_seasonal_smooth_idx].u_cnt =
+                   hash % rra_def->row_cnt;
+               break;
+           case CF_FAILURES:
+               /* specifies the # of violations that constitutes the failure threshold */
+               rra_def->par[RRA_failure_threshold].u_cnt = atoi(token);
+               if (atoi(token) < 1
+                   || atoi(token) > MAX_FAILURES_WINDOW_LEN)
+                   rrd_set_error
+                       ("Failure threshold is out of range %d, %d",
+                        1, MAX_FAILURES_WINDOW_LEN);
+               break;
+           case CF_DEVPREDICT:
+               /* specifies the index (1-based) of CF_DEVSEASONAL array
+                * associated with this CF_DEVPREDICT array. */
+               rra_def->par[RRA_dependent_rra_idx].u_cnt =
+                   atoi(token) - 1;
+               break;
+           default:
+               rra_def->pdp_cnt = atoi(token);
+               if (atoi(token) < 1)
+                   rrd_set_error("Invalid step: must be >= 1");
+               break;
+           }
+           break;
+       case 3:
+           switch (cf_conv(rra_def->cf_nam)) {
+           case CF_HWPREDICT:
+           case CF_MHWPREDICT:
+               rra_def->par[RRA_hw_beta].u_val = atof(token);
+               if (atof(token) < 0.0 || atof(token) > 1.0)
+                   rrd_set_error
+                       ("Invalid beta: must be between 0 and 1");
+               break;
+           case CF_DEVSEASONAL:
+           case CF_SEASONAL:
+               /* specifies the index (1-based) of CF_HWPREDICT array
+                * associated with this CF_DEVSEASONAL or CF_SEASONAL array. 
+                * */
+               rra_def->par[RRA_dependent_rra_idx].u_cnt =
+                   atoi(token) - 1;
+               break;
+           case CF_FAILURES:
+               /* specifies the window length */
+               rra_def->par[RRA_window_len].u_cnt = atoi(token);
+               if (atoi(token) < 1
+                   || atoi(token) > MAX_FAILURES_WINDOW_LEN)
+                   rrd_set_error
+                       ("Window length is out of range %d, %d", 1,
+                        MAX_FAILURES_WINDOW_LEN);
+               /* verify that window length exceeds the failure threshold */
+               if (rra_def->par[RRA_window_len].u_cnt <
+                   rra_def->par[RRA_failure_threshold].u_cnt)
+                   rrd_set_error
+                       ("Window length is shorter than the failure threshold");
+               break;
+           case CF_DEVPREDICT:
+               /* shouldn't be any more arguments */
+               rrd_set_error
+                   ("Unexpected extra argument for consolidation function DEVPREDICT");
+               break;
+           default:
+               row_cnt = atoi(token);
+               if (row_cnt <= 0)
+                   rrd_set_error("Invalid row count: %i", row_cnt);
+#if SIZEOF_TIME_T == 4
+               if ((long long) pdp_step * rra_def->pdp_cnt * row_cnt > 4294967296LL){
+                   /* database timespan > 2**32, would overflow time_t */
+                   rrd_set_error("The time spanned by the database is too large: must be <= 4294967296 seconds");
+               }
+#endif
+               rra_def->row_cnt = row_cnt;
+               break;
+           }
+           break;
+       case 4:
+           switch (cf_conv(rra_def->cf_nam)) {
+           case CF_FAILURES:
+               /* specifies the index (1-based) of CF_DEVSEASONAL array
+                * associated with this CF_DEVFAILURES array. */
+               rra_def->par[RRA_dependent_rra_idx].u_cnt =
+                   atoi(token) - 1;
+               break;
+           case CF_DEVSEASONAL:
+           case CF_SEASONAL:
+               /* optional smoothing window */
+               if (sscanf(token, "smoothing-window=%lf",
+                          &(rra_def->par[RRA_seasonal_smoothing_window].
+                            u_val))) {
+                   // FIXME                 strcpy(rrd.stat_head->version, RRD_VERSION);    /* smoothing-window causes Version 4 */
+                   if (rra_def->par[RRA_seasonal_smoothing_window].u_val < 0.0
+                       || rra_def->par[RRA_seasonal_smoothing_window].u_val >
+                       1.0) {
+                       rrd_set_error
+                           ("Invalid smoothing-window %f: must be between 0 and 1",
+                            rra_def->par[RRA_seasonal_smoothing_window].
+                            u_val);
+                   }
+               } else {
+                   rrd_set_error("Invalid option %s", token);
+               }
+               break;
+           case CF_HWPREDICT:
+           case CF_MHWPREDICT:
+               /* length of the associated CF_SEASONAL and CF_DEVSEASONAL arrays. */
+               period = atoi(token);
+               if (period >
+                   rra_def->row_cnt)
+                   rrd_set_error
+                       ("Length of seasonal cycle exceeds length of HW prediction array");
+               rra_def->par[RRA_period].u_val = period;
+
+               break;
+           default:
+               /* shouldn't be any more arguments */
+               rrd_set_error
+                   ("Unexpected extra argument for consolidation function %s",
+                    rra_def->cf_nam);
+               break;
+           }
+           break;
+       case 5:
+           /* If we are here, this must be a CF_HWPREDICT RRA.
+            * Specifies the index (1-based) of CF_SEASONAL array
+            * associated with this CF_HWPREDICT array. If this argument 
+            * is missing, then the CF_SEASONAL, CF_DEVSEASONAL, CF_DEVPREDICT,
+            * CF_FAILURES.
+            * arrays are created automatically. */
+           rra_def->par[RRA_dependent_rra_idx].u_cnt = atoi(token) - 1;
+           break;
+       default:
+           /* should never get here */
+           rrd_set_error("Unknown error");
+           break;
+       }       /* end switch */
+       if (rrd_test_error()) {
+           /* all errors are unrecoverable */
+           free(argvcopy);
+           return (-1);
+       }
+       token = strtok_r(NULL, ":", &tokptr);
+       token_idx++;
+    }           /* end while */
+    free(argvcopy);
+    if (token_idx < token_min){
+       rrd_set_error("Expected at least %i arguments for RRA but got %i",token_min,token_idx);
+       return(-1);
+    }
+#ifdef DEBUG
+    fprintf(stderr,
+           "Creating RRA CF: %s, dep idx %lu\n",
+           rra_def->cf_nam,
+           rra_def->par[RRA_dependent_rra_idx].u_cnt);
+#endif
+
+    return 0;
+}
+/*
+  this function checks THE LAST rra_def in the rra_def_array (that is,
+  the one with index rra_cnt-1 to check if more RRAs have to be
+  created
+ */
+static rra_def_t *handle_dependent_rras(rra_def_t *rra_def_array, 
+                                       long unsigned int *rra_cnt, 
+                                       unsigned long hash) {
+    rra_def_t *rra_def = rra_def_array + (*rra_cnt-1);
+
+    /* should we create CF_SEASONAL, CF_DEVSEASONAL, and CF_DEVPREDICT? */
+    if ((cf_conv(rra_def->cf_nam) == CF_HWPREDICT
+        || cf_conv(rra_def->cf_nam) == CF_MHWPREDICT)
+       && rra_def->par[RRA_dependent_rra_idx].u_cnt == INT_MAX) {
+       rra_def->par[RRA_dependent_rra_idx].u_cnt = *rra_cnt-1;
+#ifdef DEBUG
+       fprintf(stderr, "Creating HW contingent RRAs\n");
+#endif
+
+       rra_def_array = create_hw_contingent_rras(rra_def_array,
+                                                 rra_cnt,
+                                                 rra_def->par[RRA_period].u_val,
+                                                 hash);
+       if (rra_def_array == NULL) {
+           rrd_set_error("creating contingent RRA");
+           return NULL;
+       }
+    }
+
+    return rra_def_array;
+}
+
 
 /* #define DEBUG */
 /* For backwards compatibility with previous API.  Use rrd_create_r2 if you
@@ -213,8 +508,6 @@ int rrd_create_r2(
 {
     rrd_t     rrd;
     long      i;
-    char     *token;
-    unsigned short token_idx, error_flag, period = 0;
     unsigned long hashed_name;
 
     /* clear any previous errors */
@@ -287,12 +580,7 @@ int rrd_create_r2(
             }
            
         } else if (strncmp(argv[i], "RRA:", 4) == 0) {
-            char     *argvcopy;
-            char     *tokptr = "";
-            int       cf_id = -1;
             size_t    old_size = sizeof(rra_def_t) * (rrd.stat_head->rra_cnt);
-            int       row_cnt;
-            int       token_min = 4;
             if ((rrd.rra_def = (rra_def_t*)rrd_realloc(rrd.rra_def,
                                            old_size + sizeof(rra_def_t))) ==
                 NULL) {
@@ -300,313 +588,23 @@ int rrd_create_r2(
                 rrd_free2(&rrd);
                 return (-1);
             }
-            memset(&rrd.rra_def[rrd.stat_head->rra_cnt], 0,
-                   sizeof(rra_def_t));
 
-            argvcopy = strdup(argv[i]);
-            token = strtok_r(&argvcopy[4], ":", &tokptr);
-            token_idx = error_flag = 0;
-            
-            while (token != NULL) {
-                switch (token_idx) {
-                case 0:
-                    if (sscanf(token, CF_NAM_FMT,
-                               rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam) !=
-                        1)
-                        rrd_set_error("Failed to parse CF name");
-                    cf_id = cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam);
-                    switch (cf_id) {
-                    case CF_MHWPREDICT:
-                        strcpy(rrd.stat_head->version, RRD_VERSION);    /* MHWPREDICT causes Version 4 */
-                    case CF_HWPREDICT:
-                        token_min = 5;
-                        /* initialize some parameters */
-                        rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_hw_alpha].
-                            u_val = 0.1;
-                        rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_hw_beta].
-                            u_val = 1.0 / 288;
-                        rrd.rra_def[rrd.stat_head->rra_cnt].
-                            par[RRA_dependent_rra_idx].u_cnt =
-                            rrd.stat_head->rra_cnt;
-                        break;
-                    case CF_DEVSEASONAL:
-                        token_min = 3;
-                    case CF_SEASONAL:
-                        if (cf_id == CF_SEASONAL){
-                           token_min = 4;
-                        }
-                        /* initialize some parameters */
-                        rrd.rra_def[rrd.stat_head->rra_cnt].
-                            par[RRA_seasonal_gamma].u_val = 0.1;
-                        rrd.rra_def[rrd.stat_head->rra_cnt].
-                            par[RRA_seasonal_smoothing_window].u_val = 0.05;
-                        /* fall through */
-                    case CF_DEVPREDICT:
-                        if (cf_id == CF_DEVPREDICT){
-                           token_min = 3;
-                        }
-                        rrd.rra_def[rrd.stat_head->rra_cnt].
-                            par[RRA_dependent_rra_idx].u_cnt = -1;
-                        break;
-                    case CF_FAILURES:
-                        token_min = 5;
-                        rrd.rra_def[rrd.stat_head->rra_cnt].
-                            par[RRA_delta_pos].u_val = 2.0;
-                        rrd.rra_def[rrd.stat_head->rra_cnt].
-                            par[RRA_delta_neg].u_val = 2.0;
-                        rrd.rra_def[rrd.stat_head->rra_cnt].
-                            par[RRA_window_len].u_cnt = 3;
-                        rrd.rra_def[rrd.stat_head->rra_cnt].
-                            par[RRA_failure_threshold].u_cnt = 2;
-                        rrd.rra_def[rrd.stat_head->rra_cnt].
-                            par[RRA_dependent_rra_idx].u_cnt = -1;
-                        break;
-                        /* invalid consolidation function */
-                    case -1:
-                        rrd_set_error
-                            ("Unrecognized consolidation function %s",
-                             rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam);
-                    default:
-                        break;
-                    }
-                    /* default: 1 pdp per cdp */
-                    rrd.rra_def[rrd.stat_head->rra_cnt].pdp_cnt = 1;
-                    break;
-                case 1:
-                    switch (cf_conv
-                            (rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
-                    case CF_HWPREDICT:
-                    case CF_MHWPREDICT:
-                    case CF_DEVSEASONAL:
-                    case CF_SEASONAL:
-                    case CF_DEVPREDICT:
-                    case CF_FAILURES:
-                        row_cnt = atoi(token);
-                        if (row_cnt <= 0)
-                            rrd_set_error("Invalid row count: %i", row_cnt);
-                        rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt = row_cnt;
-                        break;
-                    default:
-                        rrd.rra_def[rrd.stat_head->rra_cnt].
-                            par[RRA_cdp_xff_val].u_val = atof(token);
-                        if (rrd.rra_def[rrd.stat_head->rra_cnt].
-                            par[RRA_cdp_xff_val].u_val < 0.0
-                            || rrd.rra_def[rrd.stat_head->rra_cnt].
-                            par[RRA_cdp_xff_val].u_val >= 1.0)
-                            rrd_set_error
-                                ("Invalid xff: must be between 0 and 1");
-                        break;
-                    }
-                    break;
-                case 2:
-                    switch (cf_conv
-                            (rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
-                    case CF_HWPREDICT:
-                    case CF_MHWPREDICT:
-                        rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_hw_alpha].
-                            u_val = atof(token);
-                        if (atof(token) <= 0.0 || atof(token) >= 1.0)
-                            rrd_set_error
-                                ("Invalid alpha: must be between 0 and 1");
-                        break;
-                    case CF_DEVSEASONAL:
-                    case CF_SEASONAL:
-                        rrd.rra_def[rrd.stat_head->rra_cnt].
-                            par[RRA_seasonal_gamma].u_val = atof(token);
-                        if (atof(token) <= 0.0 || atof(token) >= 1.0)
-                            rrd_set_error
-                                ("Invalid gamma: must be between 0 and 1");
-                        rrd.rra_def[rrd.stat_head->rra_cnt].
-                            par[RRA_seasonal_smooth_idx].u_cnt =
-                            hashed_name %
-                            rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt;
-                        break;
-                    case CF_FAILURES:
-                        /* specifies the # of violations that constitutes the failure threshold */
-                        rrd.rra_def[rrd.stat_head->rra_cnt].
-                            par[RRA_failure_threshold].u_cnt = atoi(token);
-                        if (atoi(token) < 1
-                            || atoi(token) > MAX_FAILURES_WINDOW_LEN)
-                            rrd_set_error
-                                ("Failure threshold is out of range %d, %d",
-                                 1, MAX_FAILURES_WINDOW_LEN);
-                        break;
-                    case CF_DEVPREDICT:
-                        /* specifies the index (1-based) of CF_DEVSEASONAL array
-                         * associated with this CF_DEVPREDICT array. */
-                        rrd.rra_def[rrd.stat_head->rra_cnt].
-                            par[RRA_dependent_rra_idx].u_cnt =
-                            atoi(token) - 1;
-                        break;
-                    default:
-                        rrd.rra_def[rrd.stat_head->rra_cnt].pdp_cnt =
-                            atoi(token);
-                        if (atoi(token) < 1)
-                            rrd_set_error("Invalid step: must be >= 1");
-                        break;
-                    }
-                    break;
-                case 3:
-                    switch (cf_conv
-                            (rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
-                    case CF_HWPREDICT:
-                    case CF_MHWPREDICT:
-                        rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_hw_beta].
-                            u_val = atof(token);
-                        if (atof(token) < 0.0 || atof(token) > 1.0)
-                            rrd_set_error
-                                ("Invalid beta: must be between 0 and 1");
-                        break;
-                    case CF_DEVSEASONAL:
-                    case CF_SEASONAL:
-                        /* specifies the index (1-based) of CF_HWPREDICT array
-                         * associated with this CF_DEVSEASONAL or CF_SEASONAL array. 
-                         * */
-                        rrd.rra_def[rrd.stat_head->rra_cnt].
-                            par[RRA_dependent_rra_idx].u_cnt =
-                            atoi(token) - 1;
-                        break;
-                    case CF_FAILURES:
-                        /* specifies the window length */
-                        rrd.rra_def[rrd.stat_head->rra_cnt].
-                            par[RRA_window_len].u_cnt = atoi(token);
-                        if (atoi(token) < 1
-                            || atoi(token) > MAX_FAILURES_WINDOW_LEN)
-                            rrd_set_error
-                                ("Window length is out of range %d, %d", 1,
-                                 MAX_FAILURES_WINDOW_LEN);
-                        /* verify that window length exceeds the failure threshold */
-                        if (rrd.rra_def[rrd.stat_head->rra_cnt].
-                            par[RRA_window_len].u_cnt <
-                            rrd.rra_def[rrd.stat_head->rra_cnt].
-                            par[RRA_failure_threshold].u_cnt)
-                            rrd_set_error
-                                ("Window length is shorter than the failure threshold");
-                        break;
-                    case CF_DEVPREDICT:
-                        /* shouldn't be any more arguments */
-                        rrd_set_error
-                            ("Unexpected extra argument for consolidation function DEVPREDICT");
-                        break;
-                    default:
-                        row_cnt = atoi(token);
-                        if (row_cnt <= 0)
-                            rrd_set_error("Invalid row count: %i", row_cnt);
-#if SIZEOF_TIME_T == 4
-                        if ((long long) pdp_step * rrd.rra_def[rrd.stat_head->rra_cnt].pdp_cnt * row_cnt > 4294967296LL){
-                            /* database timespan > 2**32, would overflow time_t */
-                            rrd_set_error("The time spanned by the database is too large: must be <= 4294967296 seconds");
-                        }
-#endif
-                        rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt = row_cnt;
-                        break;
-                    }
-                    break;
-                case 4:
-                    switch (cf_conv
-                            (rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
-                    case CF_FAILURES:
-                        /* specifies the index (1-based) of CF_DEVSEASONAL array
-                         * associated with this CF_DEVFAILURES array. */
-                        rrd.rra_def[rrd.stat_head->rra_cnt].
-                            par[RRA_dependent_rra_idx].u_cnt =
-                            atoi(token) - 1;
-                        break;
-                    case CF_DEVSEASONAL:
-                    case CF_SEASONAL:
-                        /* optional smoothing window */
-                        if (sscanf(token, "smoothing-window=%lf",
-                                   &(rrd.rra_def[rrd.stat_head->rra_cnt].
-                                     par[RRA_seasonal_smoothing_window].
-                                     u_val))) {
-                            strcpy(rrd.stat_head->version, RRD_VERSION);    /* smoothing-window causes Version 4 */
-                            if (rrd.rra_def[rrd.stat_head->rra_cnt].
-                                par[RRA_seasonal_smoothing_window].u_val < 0.0
-                                || rrd.rra_def[rrd.stat_head->rra_cnt].
-                                par[RRA_seasonal_smoothing_window].u_val >
-                                1.0) {
-                                rrd_set_error
-                                    ("Invalid smoothing-window %f: must be between 0 and 1",
-                                     rrd.rra_def[rrd.stat_head->rra_cnt].
-                                     par[RRA_seasonal_smoothing_window].
-                                     u_val);
-                            }
-                        } else {
-                            rrd_set_error("Invalid option %s", token);
-                        }
-                        break;
-                    case CF_HWPREDICT:
-                    case CF_MHWPREDICT:
-                        /* length of the associated CF_SEASONAL and CF_DEVSEASONAL arrays. */
-                        period = atoi(token);
-                        if (period >
-                            rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt)
-                            rrd_set_error
-                                ("Length of seasonal cycle exceeds length of HW prediction array");
-                        break;
-                    default:
-                        /* shouldn't be any more arguments */
-                        rrd_set_error
-                            ("Unexpected extra argument for consolidation function %s",
-                             rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam);
-                        break;
-                    }
-                    break;
-                case 5:
-                    /* If we are here, this must be a CF_HWPREDICT RRA.
-                     * Specifies the index (1-based) of CF_SEASONAL array
-                     * associated with this CF_HWPREDICT array. If this argument 
-                     * is missing, then the CF_SEASONAL, CF_DEVSEASONAL, CF_DEVPREDICT,
-                     * CF_FAILURES.
-                     * arrays are created automatically. */
-                    rrd.rra_def[rrd.stat_head->rra_cnt].
-                        par[RRA_dependent_rra_idx].u_cnt = atoi(token) - 1;
-                    break;
-                default:
-                    /* should never get here */
-                    rrd_set_error("Unknown error");
-                    break;
-                }       /* end switch */
-                if (rrd_test_error()) {
-                    /* all errors are unrecoverable */
-                    free(argvcopy);
-                    rrd_free2(&rrd);
-                    return (-1);
-                }
-                token = strtok_r(NULL, ":", &tokptr);
-                token_idx++;
-            }           /* end while */
-            free(argvcopy);
-            if (token_idx < token_min){
-                rrd_set_error("Expected at least %i arguments for RRA but got %i",token_min,token_idx);
+           parseRRA(argv[i], rrd.rra_def + rrd.stat_head->rra_cnt,
+                    hashed_name);
+
+           if (rrd_test_error()) {
                 rrd_free2(&rrd);
-                return(-1);
-            }
-#ifdef DEBUG
-            fprintf(stderr,
-                    "Creating RRA CF: %s, dep idx %lu, current idx %lu\n",
-                    rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam,
-                    rrd.rra_def[rrd.stat_head->rra_cnt].
-                    par[RRA_dependent_rra_idx].u_cnt, rrd.stat_head->rra_cnt);
-#endif
-            /* should we create CF_SEASONAL, CF_DEVSEASONAL, and CF_DEVPREDICT? */
-            if ((cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam) ==
-                 CF_HWPREDICT
-                 || cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam) ==
-                 CF_MHWPREDICT)
-                && rrd.rra_def[rrd.stat_head->rra_cnt].
-                par[RRA_dependent_rra_idx].u_cnt == rrd.stat_head->rra_cnt) {
-#ifdef DEBUG
-                fprintf(stderr, "Creating HW contingent RRAs\n");
-#endif
-                if (create_hw_contingent_rras(&rrd, period, hashed_name) ==
-                    -1) {
-                    rrd_set_error("creating contingent RRA");
-                    rrd_free2(&rrd);
-                    return -1;
-                }
+                return -1;
             }
-            rrd.stat_head->rra_cnt++;
+
+           rrd.stat_head->rra_cnt++;
+
+           rrd.rra_def = handle_dependent_rras(rrd.rra_def, &(rrd.stat_head->rra_cnt), 
+                                               hashed_name);
+           if (rrd.rra_def == NULL) {
+               rrd_free2(&rrd);
+               return -1;
+           }
         } else {
             rrd_set_error("can't parse argument '%s'", argv[i]);
             rrd_free2(&rrd);
@@ -675,66 +673,74 @@ void parseGENERIC_DS(
 
 /* Create the CF_DEVPREDICT, CF_DEVSEASONAL, CF_SEASONAL, and CF_FAILURES RRAs
  * associated with a CF_HWPREDICT RRA. */
-int create_hw_contingent_rras(
-    rrd_t *rrd,
-    unsigned short period,
-    unsigned long hashed_name)
+rra_def_t * create_hw_contingent_rras(rra_def_t *rra_defs,
+                                     long unsigned int *rra_cnt, 
+                                     unsigned short period,
+                                     unsigned long hash)
 {
     size_t    old_size;
     rra_def_t *current_rra;
 
     /* save index to CF_HWPREDICT */
-    unsigned long hw_index = rrd->stat_head->rra_cnt;
+    unsigned long hw_index = *rra_cnt - 1;
 
-    /* advance the pointer */
-    (rrd->stat_head->rra_cnt)++;
     /* allocate the memory for the 4 contingent RRAs */
-    old_size = sizeof(rra_def_t) * (rrd->stat_head->rra_cnt);
-    if ((rrd->rra_def = (rra_def_t*)rrd_realloc(rrd->rra_def,
-                                    old_size + 4 * sizeof(rra_def_t))) ==
+    old_size = sizeof(rra_def_t) * (*rra_cnt);
+    if ((rra_defs = (rra_def_t*)rrd_realloc(rra_defs,
+                                          old_size + 4 * sizeof(rra_def_t))) ==
         NULL) {
-        rrd_free2(rrd);
-        rrd_set_error("allocating rrd.rra_def");
-        return (-1);
+        rrd_set_error("allocating rra_def");
+        return NULL;
     }
+
+
     /* clear memory */
-    memset(&(rrd->rra_def[rrd->stat_head->rra_cnt]), 0,
+    memset(&(rra_defs[*rra_cnt]), 0,
            4 * sizeof(rra_def_t));
 
+    rra_def_t *hw_rra = rra_defs + hw_index;
+
     /* create the CF_SEASONAL RRA */
-    current_rra = &(rrd->rra_def[rrd->stat_head->rra_cnt]);
+    current_rra = rra_defs + *rra_cnt;
+
     strcpy(current_rra->cf_nam, "SEASONAL");
     current_rra->row_cnt = period;
-    current_rra->par[RRA_seasonal_smooth_idx].u_cnt = hashed_name % period;
+    current_rra->par[RRA_seasonal_smooth_idx].u_cnt = hash % period;
     current_rra->pdp_cnt = 1;
-    current_rra->par[RRA_seasonal_gamma].u_val =
-        rrd->rra_def[hw_index].par[RRA_hw_alpha].u_val;
+    current_rra->par[RRA_seasonal_gamma].u_val = 
+       hw_rra->par[RRA_hw_alpha].u_val;
     current_rra->par[RRA_dependent_rra_idx].u_cnt = hw_index;
-    rrd->rra_def[hw_index].par[RRA_dependent_rra_idx].u_cnt =
-        rrd->stat_head->rra_cnt;
+
+    hw_rra->par[RRA_dependent_rra_idx].u_cnt = *rra_cnt;
+
+    (*rra_cnt)++;
 
     /* create the CF_DEVSEASONAL RRA */
-    (rrd->stat_head->rra_cnt)++;
-    current_rra = &(rrd->rra_def[rrd->stat_head->rra_cnt]);
+    current_rra = rra_defs + *rra_cnt;
+
     strcpy(current_rra->cf_nam, "DEVSEASONAL");
     current_rra->row_cnt = period;
-    current_rra->par[RRA_seasonal_smooth_idx].u_cnt = hashed_name % period;
+    current_rra->par[RRA_seasonal_smooth_idx].u_cnt = hash % period;
     current_rra->pdp_cnt = 1;
     current_rra->par[RRA_seasonal_gamma].u_val =
-        rrd->rra_def[hw_index].par[RRA_hw_alpha].u_val;
+        hw_rra->par[RRA_hw_alpha].u_val;
     current_rra->par[RRA_dependent_rra_idx].u_cnt = hw_index;
 
+    (*rra_cnt)++;
+
     /* create the CF_DEVPREDICT RRA */
-    (rrd->stat_head->rra_cnt)++;
-    current_rra = &(rrd->rra_def[rrd->stat_head->rra_cnt]);
+    current_rra = rra_defs + *rra_cnt;
+
     strcpy(current_rra->cf_nam, "DEVPREDICT");
-    current_rra->row_cnt = (rrd->rra_def[hw_index]).row_cnt;
+    current_rra->row_cnt = hw_rra->row_cnt;
     current_rra->pdp_cnt = 1;
     current_rra->par[RRA_dependent_rra_idx].u_cnt = hw_index + 2;   /* DEVSEASONAL */
 
+    (*rra_cnt)++;
+
     /* create the CF_FAILURES RRA */
-    (rrd->stat_head->rra_cnt)++;
-    current_rra = &(rrd->rra_def[rrd->stat_head->rra_cnt]);
+    current_rra = rra_defs + *rra_cnt;
+
     strcpy(current_rra->cf_nam, "FAILURES");
     current_rra->row_cnt = period;
     current_rra->pdp_cnt = 1;
@@ -743,7 +749,9 @@ int create_hw_contingent_rras(
     current_rra->par[RRA_failure_threshold].u_cnt = 7;
     current_rra->par[RRA_window_len].u_cnt = 9;
     current_rra->par[RRA_dependent_rra_idx].u_cnt = hw_index + 2;   /* DEVSEASONAL */
-    return 0;
+     (*rra_cnt)++;
+
+     return rra_defs;
 }
 
 /* create and empty rrd file according to the specs given */
index d4d79538d182f7df6492345745c6590cc3bf03f2..bb186fd8178f0cd1810cf85d93dcc1295b3bf110 100644 (file)
@@ -225,6 +225,9 @@ enum rra_par_en { RRA_cdp_xff_val = 0,  /* what part of the consolidated
      * For CF_FAILURES: index of the CF_DEVSEASONAL array.
      * */
 
+    /* CF_HWPREDICT: */
+    RRA_period = 4,
+
     /* CF_SEASONAL and CF_DEVSEASONAL: */
     RRA_seasonal_gamma = 1,
     /* exponential smoothing parameter for seasonal effects. */
index a24834dd2974d8db8368fdd6db3227721646b18f..500e2b478d4ccd44cbe8bdb850cd9f4e7a96b73a 100644 (file)
@@ -14,8 +14,9 @@ int       update_aberrant_CF(
     unsigned long ds_idx,
     unsigned short CDP_scratch_idx,
     rrd_value_t *seasonal_coef);
-int       create_hw_contingent_rras(
-    rrd_t *rrd,
+rra_def_t *create_hw_contingent_rras(
+    rra_def_t *rrd,
+    long unsigned int *rra_cnt,
     unsigned short period,
     unsigned long hashed_name);
 int       lookup_seasonal(
index 992ad27b89c0a18a25cfd462dbdf66b4a366fe77..cab6cd818d4fee7e789f5c70c7b40ea88fea4485 100644 (file)
@@ -41,10 +41,11 @@ static void * copy_over_realloc(void *dest, int dest_index,
 */
 
 typedef struct {
-    unsigned int index;
+    int index;
     char op;  // '+', '-', '='. 
     unsigned int row_count;
     unsigned int final_row_count;
+    
 } rra_mod_op_t;