示例#1
0
/*
 * Parse a DS definition
 */
static int parse_tag_ds_cdef(
    xmlTextReaderPtr reader,
    rrd_t *rrd)
{
    xmlChar *cdef;

    cdef = get_xml_text(reader);
    if (cdef != NULL){
        /* We're always working on the last DS that has been added to the structure
         * when we get here */
        parseCDEF_DS((char *)cdef, rrd->ds_def + rrd->stat_head->ds_cnt - 1,
		     rrd, lookup_DS);
        xmlFree(cdef);
        if (rrd_test_error())
            return -1;
        else            
            return 0;        
    }
    return -1;
}                       /* int parse_tag_ds_cdef */
示例#2
0
/* #define DEBUG */
int rrd_create_r(
    const char *filename,
    unsigned long pdp_step,
    time_t last_up,
    int argc,
    const char **argv)
{
    rrd_t     rrd;
    long      i;
    int       offset;
    char     *token;
    char      dummychar1[2], dummychar2[2];
    unsigned short token_idx, error_flag, period = 0;
    unsigned long hashed_name;

    /* init rrd clean */
    rrd_init(&rrd);
    /* static header */
    if ((rrd.stat_head = (stat_head_t*)calloc(1, sizeof(stat_head_t))) == NULL) {
        rrd_set_error("allocating rrd.stat_head");
        rrd_free2(&rrd);
        return (-1);
    }

    /* live header */
    if ((rrd.live_head = (live_head_t*)calloc(1, sizeof(live_head_t))) == NULL) {
        rrd_set_error("allocating rrd.live_head");
        rrd_free2(&rrd);
        return (-1);
    }

    /* set some defaults */
    strcpy(rrd.stat_head->cookie, RRD_COOKIE);
    strcpy(rrd.stat_head->version, RRD_VERSION3);   /* by default we are still version 3 */
    rrd.stat_head->float_cookie = FLOAT_COOKIE;
    rrd.stat_head->ds_cnt = 0;  /* this will be adjusted later */
    rrd.stat_head->rra_cnt = 0; /* ditto */
    rrd.stat_head->pdp_step = pdp_step; /* 5 minute default */

    /* a default value */
    rrd.ds_def = NULL;
    rrd.rra_def = NULL;

    rrd.live_head->last_up = last_up;

    /* optind points to the first non-option command line arg,
     * in this case, the file name. */
    /* Compute the FNV hash value (used by SEASONAL and DEVSEASONAL
     * arrays. */
    hashed_name = FnvHash(filename);
    for (i = 0; i < argc; i++) {
        unsigned int ii;

        if (strncmp(argv[i], "DS:", 3) == 0) {
            size_t    old_size = sizeof(ds_def_t) * (rrd.stat_head->ds_cnt);

            if ((rrd.ds_def = (ds_def_t*)rrd_realloc(rrd.ds_def,
                                          old_size + sizeof(ds_def_t))) ==
                NULL) {
                rrd_set_error("allocating rrd.ds_def");
                rrd_free2(&rrd);
                return (-1);
            }
            memset(&rrd.ds_def[rrd.stat_head->ds_cnt], 0, sizeof(ds_def_t));
            /* extract the name and type */
            switch (sscanf(&argv[i][3],
                           DS_NAM_FMT "%1[:]" DST_FMT "%1[:]%n",
                           rrd.ds_def[rrd.stat_head->ds_cnt].ds_nam,
                           dummychar1,
                           rrd.ds_def[rrd.stat_head->ds_cnt].dst,
                           dummychar2, &offset)) {
            case 0:
            case 1:
                rrd_set_error("Invalid DS name");
                break;
            case 2:
            case 3:
                rrd_set_error("Invalid DS type");
                break;
            case 4:    /* (%n may or may not be counted) */
            case 5:    /* check for duplicate datasource names */
                for (ii = 0; ii < rrd.stat_head->ds_cnt; ii++)
                    if (strcmp(rrd.ds_def[rrd.stat_head->ds_cnt].ds_nam,
                               rrd.ds_def[ii].ds_nam) == 0)
                        rrd_set_error("Duplicate DS name: %s",
                                      rrd.ds_def[ii].ds_nam);
                /* DS_type may be valid or not. Checked later */
                break;
            default:
                rrd_set_error("invalid DS format");
            }
            if (rrd_test_error()) {
                rrd_free2(&rrd);
                return -1;
            }

            /* parse the remainder of the arguments */
            switch (dst_conv(rrd.ds_def[rrd.stat_head->ds_cnt].dst)) {
            case DST_COUNTER:
            case DST_ABSOLUTE:
            case DST_GAUGE:
            case DST_DERIVE:
                parseGENERIC_DS(&argv[i][offset + 3], &rrd,
                                rrd.stat_head->ds_cnt);
                break;
            case DST_CDEF:
                parseCDEF_DS(&argv[i][offset + 3], &rrd,
                             rrd.stat_head->ds_cnt);
                break;
            default:
                rrd_set_error("invalid DS type specified");
                break;
            }

            if (rrd_test_error()) {
                rrd_free2(&rrd);
                return -1;
            }
            rrd.stat_head->ds_cnt++;
        } else if (strncmp(argv[i], "RRA:", 4) == 0) {
            char     *argvcopy;
            char     *tokptr = "";
            size_t    old_size = sizeof(rra_def_t) * (rrd.stat_head->rra_cnt);
            int       row_cnt;

            if ((rrd.rra_def = (rra_def_t*)rrd_realloc(rrd.rra_def,
                                           old_size + sizeof(rra_def_t))) ==
                NULL) {
                rrd_set_error("allocating rrd.rra_def");
                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");
                    switch (cf_conv
                            (rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
                    case CF_MHWPREDICT:
                        strcpy(rrd.stat_head->version, RRD_VERSION);    /* MHWPREDICT causes Version 4 */
                    case CF_HWPREDICT:
                        /* 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:
                    case CF_SEASONAL:
                        /* 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:
                        rrd.rra_def[rrd.stat_head->rra_cnt].
                            par[RRA_dependent_rra_idx].u_cnt = -1;
                        break;
                    case CF_FAILURES:
                        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);
                        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);
#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;
                }
            }
            rrd.stat_head->rra_cnt++;
        } else {
            rrd_set_error("can't parse argument '%s'", argv[i]);
            rrd_free2(&rrd);
            return -1;
        }
    }


    if (rrd.stat_head->rra_cnt < 1) {
        rrd_set_error("you must define at least one Round Robin Archive");
        rrd_free2(&rrd);
        return (-1);
    }

    if (rrd.stat_head->ds_cnt < 1) {
        rrd_set_error("you must define at least one Data Source");
        rrd_free2(&rrd);
        return (-1);
    }
    return rrd_create_fn(filename, &rrd);
}
示例#3
0
文件: rrd_create.c 项目: yubo/rrdlite
/* #define DEBUG */
int rrd_create_r( const char *filename, unsigned long pdp_step,
		time_t last_up, int argc, const char **argv) {
	rrd_t     rrd;
	long      i;
	int       offset;
	char     *token;
	char      dummychar1[2], dummychar2[2];
	unsigned short token_idx, error_flag, period = 0;
	unsigned long hashed_name;
	int       ret = 0;

	/* init rrd clean */
	rrd_init(&rrd);
	/* static header */
	if ((rrd.stat_head = (stat_head_t*)calloc(1, sizeof(stat_head_t))) == NULL) {
		rrd_free2(&rrd);
		return -RRD_ERR_ALLOC;
	}

	/* live header */
	if ((rrd.live_head = (live_head_t*)calloc(1, sizeof(live_head_t))) == NULL) {
		rrd_free2(&rrd);
		return -RRD_ERR_ALLOC;
	}

	/* set some defaults */
	strcpy(rrd.stat_head->cookie, RRD_COOKIE);
	strcpy(rrd.stat_head->version, RRD_VERSION3);   /* by default we are still version 3 */
	rrd.stat_head->float_cookie = FLOAT_COOKIE;
	rrd.stat_head->ds_cnt = 0;  /* this will be adjusted later */
	rrd.stat_head->rra_cnt = 0; /* ditto */
	rrd.stat_head->pdp_step = pdp_step; /* 5 minute default */

	/* a default value */
	rrd.ds_def = NULL;
	rrd.rra_def = NULL;

	rrd.live_head->last_up = last_up;

	/* optind points to the first non-option command line arg,
	 * in this case, the file name. */
	/* Compute the FNV hash value (used by SEASONAL and DEVSEASONAL
	 * arrays. */
	hashed_name = FnvHash(filename);
	for (i = 0; i < argc; i++) {
		unsigned int ii;

		if (strncmp(argv[i], "DS:", 3) == 0) {
			size_t    old_size = sizeof(ds_def_t) * (rrd.stat_head->ds_cnt);

			if ((rrd.ds_def = (ds_def_t*)rrd_realloc(rrd.ds_def,
							old_size + sizeof(ds_def_t))) ==
					NULL) {
				rrd_free2(&rrd);
				return -RRD_ERR_ALLOC;
			}
			memset(&rrd.ds_def[rrd.stat_head->ds_cnt], 0, sizeof(ds_def_t));
			/* extract the name and type */
			switch (sscanf(&argv[i][3],
						DS_NAM_FMT "%1[:]" DST_FMT "%1[:]%n",
						rrd.ds_def[rrd.stat_head->ds_cnt].ds_nam,
						dummychar1,
						rrd.ds_def[rrd.stat_head->ds_cnt].dst,
						dummychar2, &offset)) {
				case 0:
				case 1:
					ret = -RRD_ERR_INVALID_DS_NAME;
					break;
				case 2:
				case 3:
					ret = -RRD_ERR_INVALID_DS_TYPE;
					break;
				case 4:    /* (%n may or may not be counted) */
				case 5:    /* check for duplicate datasource names */
					for (ii = 0; ii < rrd.stat_head->ds_cnt; ii++)
						if (strcmp(rrd.ds_def[rrd.stat_head->ds_cnt].ds_nam,
									rrd.ds_def[ii].ds_nam) == 0)
							ret = -RRD_ERR_DUPLICATE_DS_NAME;
					/* DS_type may be valid or not. Checked later */
					break;
				default:
					ret = -RRD_ERR_INVALID_DS_FORMAT;
			}
			if (ret) {
				rrd_free2(&rrd);
				return ret;
			}

			/* parse the remainder of the arguments */
			switch (dst_conv(rrd.ds_def[rrd.stat_head->ds_cnt].dst)) {
				case DST_COUNTER:
				case DST_ABSOLUTE:
				case DST_GAUGE:
				case DST_DERIVE:
					ret = parseGENERIC_DS(&argv[i][offset + 3], &rrd,
							rrd.stat_head->ds_cnt);
					break;
				case DST_CDEF:
					ret = parseCDEF_DS(&argv[i][offset + 3], &rrd,
							rrd.stat_head->ds_cnt);
					break;
				default:
					ret = -RRD_ERR_INVALID_DS_TYPE_SPEC;
					break;
			}

			if (ret) {
				rrd_free2(&rrd);
				return ret;
			}
			rrd.stat_head->ds_cnt++;
		} 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) {
				rrd_free2(&rrd);
				return -RRD_ERR_ALLOC;
			}
			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)
							ret = -RRD_ERR_FAILED_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:
								ret = -RRD_ERR_UNREC_CONSOLIDATION_FUNC;
							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)
									ret = -RRD_ERR_INVALID_ROW_COUNT;
								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)
									ret = -RRD_ERR_INVALID_XFF;
								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)
									ret = -RRD_ERR_INVALID_ALPHA;
								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)
									ret = -RRD_ERR_INVALID_GAMMA;
								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)
									ret = -RRD_ERR_FAILURE_THRESHOLD_OUT_OF_RANGE;
								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)
									ret = -RRD_ERR_INVALID_STEP;
								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)
									ret = -RRD_ERR_INVALID_BETA;
								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)
									ret = RRD_ERR_WIN_LEN_OUT_OF_RANGE;
								/* 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)
									ret = -RRD_ERR_WINLEN_SHORTER_FAILURE_THRESHOLD;
								break;
							case CF_DEVPREDICT:
								/* shouldn't be any more arguments */
								ret = -RRD_ERR_INVALID_ARG1;
								break;
							default:
								row_cnt = atoi(token);
								if (row_cnt <= 0)
									ret = -RRD_ERR_INVALID_ROW_COUNT;
#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 */
									ret = -RRD_ERR_TIME_TOO_LARGE;
								}
#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) {
										ret = -RRD_ERR_INVALID_SMOOTHING_WINDOW;
									}
								} else {
									ret = -RRD_ERR_INVALID_OPT;
								}
								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)
									ret = -RRD_ERR_LEN_OF_SEASONAL_CYCLE;
								break;
							default:
								/* shouldn't be any more arguments */
								ret = -RRD_ERR_INVALID_ARG2;
								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 */
						ret = -RRD_ERR_UNKNOWN_ERROR;
						break;
				}       /* end switch */
				if (ret) {
					/* all errors are unrecoverable */
					free(argvcopy);
					rrd_free2(&rrd);
					return ret;
				}
				token = strtok_r(NULL, ":", &tokptr);
				token_idx++;
			}           /* end while */
			free(argvcopy);
			if (token_idx < token_min){
				rrd_free2(&rrd);
				return(-RRD_ERR_ARG3);
			}
#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_free2(&rrd);
					return (-RRD_ERR_CREATING_RRA);
				}
			}
			rrd.stat_head->rra_cnt++;
		} else {
			rrd_free2(&rrd);
			return (-RRD_ERR_ARG4);
		}
	}


	if (rrd.stat_head->rra_cnt < 1) {
		rrd_free2(&rrd);
		return (-RRD_ERR_ARG5);
	}

	if (rrd.stat_head->ds_cnt < 1) {
		rrd_free2(&rrd);
		return (-RRD_ERR_ARG6);
	}
	return rrd_create_fn(filename, &rrd);
}
示例#4
0
/* parse the data stored in buf and return a filled rrd structure */
int xml2rrd(char* buf, rrd_t* rrd, char rc){
  /* pass 1 identify number of RRAs  */
  char *ptr,*ptr2,*ptr3; /* walks thought the buffer */
  long rows=0,mempool=0,i=0;
  int rra_index;
  xml_lc(buf); /* lets lowercase all active parts of the xml */
  ptr=buf;
  ptr2=buf;
  ptr3=buf;
  /* start with an RRD tag */

  eat_tag(&ptr,"rrd");
  /* allocate static header */
  if((rrd->stat_head = calloc(1,sizeof(stat_head_t)))==NULL){
    rrd_set_error("allocating rrd.stat_head");
    return -1;    
  };

  strcpy(rrd->stat_head->cookie,RRD_COOKIE);
  read_tag(&ptr,"version","%4[0-9]",rrd->stat_head->version);
  /* added primitive version checking */
  if (atoi(rrd -> stat_head -> version) > atoi(RRD_VERSION) )
  {
    rrd_set_error("Incompatible file version, detected version %s is bigger than supported version %s\n",
		  rrd -> stat_head -> version, RRD_VERSION );
    free(rrd -> stat_head);
    return -1;
  }
  if (atoi(rrd -> stat_head -> version) < 2) 
  {
    rrd_set_error("Can only restore version >= 2 (Not %s). Dump your old rrd using a current rrdtool dump.",  rrd -> stat_head -> version );
    free(rrd -> stat_head);
    return -1;
  }
  rrd->stat_head->float_cookie = FLOAT_COOKIE;
  rrd->stat_head->ds_cnt = 0;
  rrd->stat_head->rra_cnt = 0;
  read_tag(&ptr,"step","%lu",&(rrd->stat_head->pdp_step));

  /* allocate live head */
  if((rrd->live_head = calloc(1,sizeof(live_head_t)))==NULL){
    rrd_set_error("allocating rrd.live_head");
    return -1;    
  }
  read_tag(&ptr,"lastupdate","%lu",&(rrd->live_head->last_up));

  /* Data Source Definition Part */
  ptr2 = ptr;
  while (eat_tag(&ptr2,"ds") == 1){
      rrd->stat_head->ds_cnt++;
      if((rrd->ds_def = rrd_realloc(rrd->ds_def,rrd->stat_head->ds_cnt*sizeof(ds_def_t)))==NULL){
	  rrd_set_error("allocating rrd.ds_def");
	  return -1;
      };
      /* clean out memory to make sure no data gets stored from previous tasks */
      memset(&(rrd->ds_def[rrd->stat_head->ds_cnt-1]), 0, sizeof(ds_def_t));
      if((rrd->pdp_prep = rrd_realloc(rrd->pdp_prep,rrd->stat_head->ds_cnt
				  *sizeof(pdp_prep_t)))==NULL){
	rrd_set_error("allocating pdp_prep");
	return(-1);
      }
      /* clean out memory to make sure no data gets stored from previous tasks */
      memset(&(rrd->pdp_prep[rrd->stat_head->ds_cnt-1]), 0, sizeof(pdp_prep_t));

      read_tag(&ptr2,"name",DS_NAM_FMT,rrd->ds_def[rrd->stat_head->ds_cnt-1].ds_nam);

      read_tag(&ptr2,"type",DST_FMT,rrd->ds_def[rrd->stat_head->ds_cnt-1].dst);
      /* test for valid type */
      if( (int)dst_conv(rrd->ds_def[rrd->stat_head->ds_cnt-1].dst) == -1) return -1;      

	  if (dst_conv(rrd->ds_def[rrd->stat_head->ds_cnt-1].dst) != DST_CDEF)
	  {
      read_tag(&ptr2,"minimal_heartbeat","%lu",
	       &(rrd->ds_def[rrd->stat_head->ds_cnt-1].par[DS_mrhb_cnt].u_cnt));
      read_tag(&ptr2,"min","%lf",&(rrd->ds_def[rrd->stat_head->ds_cnt-1].par[DS_min_val].u_val));
      read_tag(&ptr2,"max","%lf",&(rrd->ds_def[rrd->stat_head->ds_cnt-1].par[DS_max_val].u_val));
	  } else { /* DST_CDEF */
		 char buffer[1024];
	     read_tag(&ptr2,"cdef","%s",buffer);
		 parseCDEF_DS(buffer,rrd,rrd -> stat_head -> ds_cnt - 1);
	  }

      read_tag(&ptr2,"last_ds","%30s",rrd->pdp_prep[rrd->stat_head->ds_cnt-1].last_ds);
      read_tag(&ptr2,"value","%lf",&(rrd->pdp_prep[rrd->stat_head->ds_cnt-1].scratch[PDP_val].u_val));
      read_tag(&ptr2,"unknown_sec","%lu",&(rrd->pdp_prep[rrd->stat_head->ds_cnt-1].scratch[PDP_unkn_sec_cnt].u_cnt));      
      eat_tag(&ptr2,"/ds");
      ptr=ptr2;
  }
  
  ptr2 = ptr;
  while (eat_tag(&ptr2,"rra") == 1){
      rrd->stat_head->rra_cnt++;

      /* allocate and reset rra definition areas */
      if((rrd->rra_def = rrd_realloc(rrd->rra_def,rrd->stat_head->rra_cnt*sizeof(rra_def_t)))==NULL){
	  rrd_set_error("allocating rra_def"); return -1; }      
      memset(&(rrd->rra_def[rrd->stat_head->rra_cnt-1]), 0, sizeof(rra_def_t));

      /* allocate and reset consolidation point areas */
      if((rrd->cdp_prep = rrd_realloc(rrd->cdp_prep,
				  rrd->stat_head->rra_cnt
				  *rrd->stat_head->ds_cnt*sizeof(cdp_prep_t)))==NULL){
	  rrd_set_error("allocating cdp_prep"); return -1; }

      memset(&(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rrd->stat_head->rra_cnt-1)]), 
	     0, rrd->stat_head->ds_cnt*sizeof(cdp_prep_t));

      
      read_tag(&ptr2,"cf",CF_NAM_FMT,rrd->rra_def[rrd->stat_head->rra_cnt-1].cf_nam);
      /* test for valid type */
      if( (int)cf_conv(rrd->rra_def[rrd->stat_head->rra_cnt-1].cf_nam) == -1) return -1;

      read_tag(&ptr2,"pdp_per_row","%lu",&(rrd->rra_def[rrd->stat_head->rra_cnt-1].pdp_cnt));
      /* support to read RRA parameters */
      eat_tag(&ptr2, "params");
      skip(&ptr2);
      rra_index = rrd->stat_head->rra_cnt - 1;
      /* backwards compatibility w/ old patch */
      if (strncmp(ptr2, "<value>",7) == 0) {
         parse_patch1028_RRA_params(&ptr2,rrd,rra_index); 
      } else {
      switch(cf_conv(rrd -> rra_def[rra_index].cf_nam)) {
      case CF_HWPREDICT:
         read_tag(&ptr2, "hw_alpha", "%lf", 
            &(rrd->rra_def[rra_index].par[RRA_hw_alpha].u_val));
         read_tag(&ptr2, "hw_beta", "%lf", 
            &(rrd->rra_def[rra_index].par[RRA_hw_beta].u_val));
         read_tag(&ptr2, "dependent_rra_idx", "%lu", 
            &(rrd->rra_def[rra_index].par[RRA_dependent_rra_idx].u_cnt));
         break;
      case CF_SEASONAL:
      case CF_DEVSEASONAL:
         read_tag(&ptr2, "seasonal_gamma", "%lf", 
            &(rrd->rra_def[rra_index].par[RRA_seasonal_gamma].u_val));
         read_tag(&ptr2, "seasonal_smooth_idx", "%lu", 
            &(rrd->rra_def[rra_index].par[RRA_seasonal_smooth_idx].u_cnt));
         read_tag(&ptr2, "dependent_rra_idx", "%lu", 
            &(rrd->rra_def[rra_index].par[RRA_dependent_rra_idx].u_cnt));
         break;
      case CF_FAILURES:
         read_tag(&ptr2, "delta_pos", "%lf", 
            &(rrd->rra_def[rra_index].par[RRA_delta_pos].u_val));
         read_tag(&ptr2, "delta_neg", "%lf", 
            &(rrd->rra_def[rra_index].par[RRA_delta_neg].u_val));
         read_tag(&ptr2, "window_len", "%lu", 
            &(rrd->rra_def[rra_index].par[RRA_window_len].u_cnt));
         read_tag(&ptr2, "failure_threshold", "%lu", 
            &(rrd->rra_def[rra_index].par[RRA_failure_threshold].u_cnt));
         /* fall thru */
      case CF_DEVPREDICT:
         read_tag(&ptr2, "dependent_rra_idx", "%lu", 
            &(rrd->rra_def[rra_index].par[RRA_dependent_rra_idx].u_cnt));
         break;
      case CF_AVERAGE:
      case CF_MAXIMUM:
      case CF_MINIMUM:
      case CF_LAST:
      default:
         read_tag(&ptr2, "xff","%lf",
            &(rrd->rra_def[rra_index].par[RRA_cdp_xff_val].u_val));
      }
      }
      eat_tag(&ptr2, "/params");
      eat_tag(&ptr2,"cdp_prep");
      for(i=0;i< (int)rrd->stat_head->ds_cnt;i++)
      {
      eat_tag(&ptr2,"ds");
      /* support to read CDP parameters */
      rra_index = rrd->stat_head->rra_cnt-1; 
      skip(&ptr2);
      if (strncmp(ptr2, "<value>",7) == 0) {
         parse_patch1028_CDP_params(&ptr2,rrd,rra_index,i);
      } else {
         read_tag(&ptr2, "primary_value","%lf",
               &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index)
               +i].scratch[CDP_primary_val].u_val));
         read_tag(&ptr2, "secondary_value","%lf",
               &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index)
               +i].scratch[CDP_secondary_val].u_val));
         switch(cf_conv(rrd->rra_def[rra_index].cf_nam)) {
         case CF_HWPREDICT:
            read_tag(&ptr2,"intercept","%lf", 
               &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index)
               +i].scratch[CDP_hw_intercept].u_val));
            read_tag(&ptr2,"last_intercept","%lf", 
               &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index)
               +i].scratch[CDP_hw_last_intercept].u_val));
            read_tag(&ptr2,"slope","%lf", 
               &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index)
               +i].scratch[CDP_hw_slope].u_val));
            read_tag(&ptr2,"last_slope","%lf", 
               &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index)
               +i].scratch[CDP_hw_last_slope].u_val));
            read_tag(&ptr2,"nan_count","%lu", 
               &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index)
               +i].scratch[CDP_null_count].u_cnt));
            read_tag(&ptr2,"last_nan_count","%lu", 
               &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index)
               +i].scratch[CDP_last_null_count].u_cnt));
            break;
         case CF_SEASONAL:
         case CF_DEVSEASONAL:
            read_tag(&ptr2,"seasonal","%lf", 
               &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index)
               +i].scratch[CDP_hw_seasonal].u_val));
            read_tag(&ptr2,"last_seasonal","%lf", 
               &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index)
               +i].scratch[CDP_hw_last_seasonal].u_val));
            read_tag(&ptr2,"init_flag","%lu", 
               &(rrd->cdp_prep[rrd->stat_head->ds_cnt*(rra_index)
               +i].scratch[CDP_init_seasonal].u_cnt));
            break;
         case CF_DEVPREDICT:
            break;
         case CF_FAILURES:
            parse_FAILURES_history(&ptr2,rrd,rra_index,i); 
            break;
         case CF_AVERAGE:
         case CF_MAXIMUM:
         case CF_MINIMUM:
         case CF_LAST:
         default:
            read_tag(&ptr2,"value","%lf",&(rrd->cdp_prep[rrd->stat_head->ds_cnt
               *(rra_index) +i].scratch[CDP_val].u_val));
            read_tag(&ptr2,"unknown_datapoints","%lu",&(rrd->cdp_prep[rrd->stat_head->ds_cnt
               *(rra_index) +i].scratch[CDP_unkn_pdp_cnt].u_cnt));
            break;
	 }
      }
      eat_tag(&ptr2,"/ds");
      }
      eat_tag(&ptr2,"/cdp_prep");
      rrd->rra_def[rrd->stat_head->rra_cnt-1].row_cnt=0;
      eat_tag(&ptr2,"database");
      ptr3 = ptr2;      
      while (eat_tag(&ptr3,"row") == 1){
	
	  if(mempool==0){
	    mempool = 1000;
	    if((rrd->rrd_value = rrd_realloc(rrd->rrd_value,
					 (rows+mempool)*(rrd->stat_head->ds_cnt)
					 *sizeof(rrd_value_t)))==NULL) {
	      rrd_set_error("allocating rrd_values"); return -1; }
	  }
	  rows++;
	  mempool--;
	  rrd->rra_def[rrd->stat_head->rra_cnt-1].row_cnt++;
	  for(i=0;i< (int)rrd->stat_head->ds_cnt;i++){

		  rrd_value_t  * value = &(rrd->rrd_value[(rows-1)*rrd->stat_head->ds_cnt+i]);

		  read_tag(&ptr3,"v","%lf", value);
		  
		  if (
			  (rc == 1)			/* do we have to check for the ranges */
			  &&
		      (!isnan(*value))	/* not a NAN value */
		      &&
			  (dst_conv(rrd->ds_def[i].dst) != DST_CDEF)
			  &&
		      (					/* min defined and in the range ? */
			  (!isnan(rrd->ds_def[i].par[DS_min_val].u_val) 
			  	&& (*value < rrd->ds_def[i].par[DS_min_val].u_val)) 
			  ||				/* max defined and in the range ? */
			  (!isnan(rrd->ds_def[i].par[DS_max_val].u_val) 
			  	&& (*value > rrd->ds_def[i].par[DS_max_val].u_val))
		      )
		  ) {
		      fprintf (stderr, "out of range found [ds: %lu], [value : %0.10e]\n", i, *value);
		      *value = DNAN;
		  }
	  }
      	  eat_tag(&ptr3,"/row");                  
	  ptr2=ptr3;
      }
      eat_tag(&ptr2,"/database");
      eat_tag(&ptr2,"/rra");                  
      ptr=ptr2;
  }  
  eat_tag(&ptr,"/rrd");

  if((rrd->rra_ptr = calloc(1,sizeof(rra_ptr_t)*rrd->stat_head->rra_cnt)) == NULL) {
      rrd_set_error("allocating rra_ptr");
      return(-1);
  }

  for(i=0; i < (int)rrd->stat_head->rra_cnt; i++) {
	  /* last row in the xml file is the most recent; as
	   * rrd_update increments the current row pointer, set cur_row
	   * here to the last row. */
      rrd->rra_ptr[i].cur_row = rrd->rra_def[i].row_cnt-1;
  }
  if (ptr==NULL)
      return -1;
  return 1;
}