Ejemplo n.º 1
0
static int parse_tag_ds_type(
    xmlTextReaderPtr reader,
    ds_def_t *ds_def)
{
    char *dst;
    dst = (char *)get_xml_text(reader);
    if (dst != NULL){
        int status;
        status = dst_conv(dst);
        if (status == -1) {
            rrd_set_error("parse_tag_ds_type: Unknown data source type: %s",
                          dst);
            return -1;
        }
        strncpy(ds_def->dst,dst,sizeof(ds_def->dst)-1);
        ds_def->dst[sizeof(ds_def->dst)-1] = '\0';
        xmlFree(dst);
        return 0;        
    }
    return -1;
}                       /* int parse_tag_ds_type */
Ejemplo n.º 2
0
int rrd_dump_cb_r(
    const char *filename,
    int opt_header,
    rrd_output_callback_t cb,
    void *user)
{
    unsigned int i, ii, ix, iii = 0;
    time_t    now;
    char      somestring[255];
    rrd_value_t my_cdp;
    off_t     rra_base, rra_start, rra_next;
    rrd_file_t *rrd_file;
    rrd_t     rrd;
    rrd_value_t value;
    struct tm tm;

//These two macros are local defines to clean up visible code from its redndancy
//and make it easier to read.
#define CB_PUTS(str)                                            \
    do {							\
        size_t len = strlen(str);				\
								\
        if (cb((str), len, user) != len)                        \
            goto err_out;                                       \
    } while (0);
#define CB_FMTS(...) do {                                       \
    char buffer[256];                                           \
    rrd_snprintf (buffer, sizeof(buffer), __VA_ARGS__);         \
    CB_PUTS (buffer);                                           \
    } while (0)
//These macros are to be undefined at the end of this function

    //Check if we got a (valid) callback method
    if (!cb) {
        return (-1);
    }

    rrd_init(&rrd);

    rrd_file = rrd_open(filename, &rrd, RRD_READONLY | RRD_READAHEAD);
    if (rrd_file == NULL) {
        rrd_free(&rrd);
        return (-1);
    }

    if (opt_header == 1) {
        CB_PUTS("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
        CB_PUTS("<!DOCTYPE rrd SYSTEM \"http://oss.oetiker.ch/rrdtool/rrdtool.dtd\">\n");
        CB_PUTS("<!-- Round Robin Database Dump -->\n");
        CB_PUTS("<rrd>\n");
    } else if (opt_header == 2) {
        CB_PUTS("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
        CB_PUTS("<!-- Round Robin Database Dump -->\n");
        CB_PUTS("<rrd xmlns=\"http://oss.oetiker.ch/rrdtool/rrdtool-dump.xml\" "
                "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
        CB_PUTS("\txsi:schemaLocation=\"http://oss.oetiker.ch/rrdtool/rrdtool-dump.xml "
                "http://oss.oetiker.ch/rrdtool/rrdtool-dump.xsd\">\n");
    } else {
        CB_PUTS("<!-- Round Robin Database Dump -->\n");
        CB_PUTS("<rrd>\n");
    }

    if (atoi(rrd.stat_head->version) <= 3) {
        CB_FMTS("\t<version>%s</version>\n", RRD_VERSION3);
    } else {
        CB_FMTS("\t<version>%s</version>\n", rrd.stat_head->version);
    }
    
    CB_FMTS("\t<step>%lu</step> <!-- Seconds -->\n",
        rrd.stat_head->pdp_step);

#ifdef HAVE_STRFTIME
    localtime_r(&rrd.live_head->last_up, &tm);
    strftime(somestring, 255, "%Y-%m-%d %H:%M:%S %Z", &tm);
#else
# error "Need strftime"
#endif
    CB_FMTS("\t<lastupdate>%lld</lastupdate> <!-- %s -->\n\n",
        (long long int) rrd.live_head->last_up, somestring);
    for (i = 0; i < rrd.stat_head->ds_cnt; i++) {
        CB_PUTS("\t<ds>\n");

        CB_FMTS("\t\t<name> %s </name>\n", rrd.ds_def[i].ds_nam);

        CB_FMTS("\t\t<type> %s </type>\n", rrd.ds_def[i].dst);

        if (dst_conv(rrd.ds_def[i].dst) != DST_CDEF) {
            CB_FMTS("\t\t<minimal_heartbeat>%lu</minimal_heartbeat>\n",
                    rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt);

            if (isnan(rrd.ds_def[i].par[DS_min_val].u_val)) {
                CB_PUTS("\t\t<min>NaN</min>\n");
            } else {
                CB_FMTS("\t\t<min>%0.10e</min>\n",
                    rrd.ds_def[i].par[DS_min_val].u_val);
            }
            
            if (isnan(rrd.ds_def[i].par[DS_max_val].u_val)) {
                CB_PUTS("\t\t<max>NaN</max>\n");
            } else {
                CB_FMTS("\t\t<max>%0.10e</max>\n",
                    rrd.ds_def[i].par[DS_max_val].u_val);
            }
        } else {        /* DST_CDEF */
            char     *str = NULL;

            rpn_compact2str((rpn_cdefds_t *) &(rrd.ds_def[i].par[DS_cdef]),
                rrd.ds_def, &str);

            //Splitting into 3 writes to avoid allocating memory
            //This is better compared to snprintf as str may be of arbitrary size
            CB_PUTS("\t\t<cdef> ");
            CB_PUTS(str);
            CB_PUTS(" </cdef>\n");

            free(str);
        }

        CB_PUTS("\n\t\t<!-- PDP Status -->\n");
        CB_FMTS("\t\t<last_ds>%s</last_ds>\n",
            rrd.pdp_prep[i].last_ds);

        if (isnan(rrd.pdp_prep[i].scratch[PDP_val].u_val)) {
            CB_PUTS("\t\t<value>NaN</value>\n");
        } else {
            CB_FMTS("\t\t<value>%0.10e</value>\n",
                rrd.pdp_prep[i].scratch[PDP_val].u_val);
        }

        CB_FMTS("\t\t<unknown_sec> %lu </unknown_sec>\n",
            rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt);

        CB_PUTS("\t</ds>\n\n");
    }

    CB_PUTS("\t<!-- Round Robin Archives -->\n");

    rra_base = rrd_file->header_len;
    rra_next = rra_base;

    for (i = 0; i < rrd.stat_head->rra_cnt; i++) {

        long      timer = 0;

        rra_start = rra_next;
        rra_next += (rrd.stat_head->ds_cnt
                     * rrd.rra_def[i].row_cnt * sizeof(rrd_value_t));

        CB_PUTS("\t<rra>\n");

        CB_FMTS("\t\t<cf>%s</cf>\n", rrd.rra_def[i].cf_nam);

        CB_FMTS("\t\t<pdp_per_row>%lu</pdp_per_row> <!-- %lu seconds -->\n\n",
            rrd.rra_def[i].pdp_cnt, 
            rrd.rra_def[i].pdp_cnt * rrd.stat_head->pdp_step);

        /* support for RRA parameters */
        CB_PUTS("\t\t<params>\n");

        switch (cf_conv(rrd.rra_def[i].cf_nam)) {
        case CF_HWPREDICT:
        case CF_MHWPREDICT:
            CB_FMTS("\t\t<hw_alpha>%0.10e</hw_alpha>\n",
                rrd.rra_def[i].par[RRA_hw_alpha].u_val);

            CB_FMTS("\t\t<hw_beta>%0.10e</hw_beta>\n",
                rrd.rra_def[i].par[RRA_hw_beta].u_val);

            CB_FMTS("\t\t<dependent_rra_idx>%lu</dependent_rra_idx>\n",
                rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
            break;
        case CF_SEASONAL:
        case CF_DEVSEASONAL:
            CB_FMTS("\t\t<seasonal_gamma>%0.10e</seasonal_gamma>\n",
                rrd.rra_def[i].par[RRA_seasonal_gamma].u_val);

            CB_FMTS("\t\t<seasonal_smooth_idx>%lu</seasonal_smooth_idx>\n",
                rrd.rra_def[i].par[RRA_seasonal_smooth_idx].u_cnt);

            if (atoi(rrd.stat_head->version) >= 4) {
                CB_FMTS("\t\t<smoothing_window>%0.10e</smoothing_window>\n",
                    rrd.rra_def[i].par[RRA_seasonal_smoothing_window].u_val);
            }

            CB_FMTS("\t\t<dependent_rra_idx>%lu</dependent_rra_idx>\n",
                rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
            break;
        case CF_FAILURES:
            CB_FMTS("\t\t<delta_pos>%0.10e</delta_pos>\n",
                rrd.rra_def[i].par[RRA_delta_pos].u_val);

            CB_FMTS("\t\t<delta_neg>%0.10e</delta_neg>\n",
                rrd.rra_def[i].par[RRA_delta_neg].u_val);

            CB_FMTS("\t\t<window_len>%lu</window_len>\n",
                rrd.rra_def[i].par[RRA_window_len].u_cnt);

            CB_FMTS("\t\t<failure_threshold>%lu</failure_threshold>\n",
                rrd.rra_def[i].par[RRA_failure_threshold].u_cnt);

            /* fall thru */
        case CF_DEVPREDICT:
            CB_FMTS("\t\t<dependent_rra_idx>%lu</dependent_rra_idx>\n",
                rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
            break;
        case CF_AVERAGE:
        case CF_MAXIMUM:
        case CF_MINIMUM:
        case CF_LAST:
        default:
            CB_FMTS("\t\t<xff>%0.10e</xff>\n",
                rrd.rra_def[i].par[RRA_cdp_xff_val].u_val);
            break;
        }

        CB_PUTS("\t\t</params>\n");
        CB_PUTS("\t\t<cdp_prep>\n");

        for (ii = 0; ii < rrd.stat_head->ds_cnt; ii++) {
            unsigned long ivalue;

            CB_PUTS("\t\t\t<ds>\n");
            /* support for exporting all CDP parameters */
            /* parameters common to all CFs */
            /* primary_val and secondary_val do not need to be saved between updates
             * so strictly speaking they could be omitted.
             * However, they can be useful for diagnostic purposes, so are included here. */
            value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                scratch[CDP_primary_val].u_val;
            if (isnan(value)) {
                CB_PUTS("\t\t\t<primary_value>NaN</primary_value>\n");
            } else {
                CB_FMTS("\t\t\t<primary_value>%0.10e</primary_value>\n", value);
            }

            value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                scratch[CDP_secondary_val].u_val;
            if (isnan(value)) {
                CB_PUTS("\t\t\t<secondary_value>NaN</secondary_value>\n");
            } else {
                CB_FMTS("\t\t\t<secondary_value>%0.10e</secondary_value>\n", value);
            }

            switch (cf_conv(rrd.rra_def[i].cf_nam)) {
            case CF_HWPREDICT:
            case CF_MHWPREDICT:
                value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                    scratch[CDP_hw_intercept].u_val;
                if (isnan(value)) {
                    CB_PUTS("\t\t\t<intercept>NaN</intercept>\n");
                } else {
                    CB_FMTS("\t\t\t<intercept>%0.10e</intercept>\n", value);
                }

                value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                    scratch[CDP_hw_last_intercept].u_val;
                if (isnan(value)) {
                    CB_PUTS("\t\t\t<last_intercept>NaN</last_intercept>\n");
                } else {
                    CB_FMTS("\t\t\t<last_intercept>%0.10e</last_intercept>\n", value);
                }

                value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                    scratch[CDP_hw_slope].u_val;
                if (isnan(value)) {
                    CB_PUTS("\t\t\t<slope>NaN</slope>\n");
                } else {
                    CB_FMTS("\t\t\t<slope>%0.10e</slope>\n", value);
                }

                value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                    scratch[CDP_hw_last_slope].u_val;
                if (isnan(value)) {
                    CB_PUTS("\t\t\t<last_slope>NaN</last_slope>\n");
                } else {
                    CB_FMTS("\t\t\t<last_slope>%0.10e</last_slope>\n", value);
                }

                ivalue = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                    scratch[CDP_null_count].u_cnt;
                CB_FMTS("\t\t\t<nan_count>%lu</nan_count>\n", ivalue);

                ivalue = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                    scratch[CDP_last_null_count].u_cnt;
                CB_FMTS("\t\t\t<last_nan_count>%lu</last_nan_count>\n", ivalue);
                break;
            case CF_SEASONAL:
            case CF_DEVSEASONAL:
                value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                    scratch[CDP_hw_seasonal].u_val;
                if (isnan(value)) {
                    CB_PUTS("\t\t\t<seasonal>NaN</seasonal>\n");
                } else {
                    CB_FMTS("\t\t\t<seasonal>%0.10e</seasonal>\n", value);
                }

                value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                    scratch[CDP_hw_last_seasonal].u_val;
                if (isnan(value)) {
                    CB_PUTS("\t\t\t<last_seasonal>NaN</last_seasonal>\n");
                } else {
                    CB_FMTS("\t\t\t<last_seasonal>%0.10e</last_seasonal>\n", value);
                }

                ivalue = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                    scratch[CDP_init_seasonal].u_cnt;
                CB_FMTS("\t\t\t<init_flag>%lu</init_flag>\n", ivalue);
                break;
            case CF_DEVPREDICT:
                break;
            case CF_FAILURES:
            {
                unsigned short vidx;
                char *violations_array = (char *) ((void *)
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].scratch);
                CB_PUTS("\t\t\t<history>");
                for (vidx = 0;
                    vidx < rrd.rra_def[i].par[RRA_window_len].u_cnt;
                    ++vidx) {
                    CB_FMTS("%d", violations_array[vidx]);
                }
                CB_PUTS("</history>\n");
            }
                break;
            case CF_AVERAGE:
            case CF_MAXIMUM:
            case CF_MINIMUM:
            case CF_LAST:
            default:
                value = rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].scratch[CDP_val].u_val;
                if (isnan(value)) {
                    CB_PUTS("\t\t\t<value>NaN</value>\n");
                } else {
                    CB_FMTS("\t\t\t<value>%0.10e</value>\n", value);
                }

                CB_FMTS("\t\t\t<unknown_datapoints>%lu</unknown_datapoints>\n",
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt + ii].
                        scratch[CDP_unkn_pdp_cnt].u_cnt);
                break;
            }
            CB_PUTS("\t\t\t</ds>\n");
        }
        CB_PUTS("\t\t</cdp_prep>\n");

        CB_PUTS("\t\t<database>\n");
        rrd_seek(rrd_file, (rra_start + (rrd.rra_ptr[i].cur_row + 1)
                            * rrd.stat_head->ds_cnt
                            * sizeof(rrd_value_t)), SEEK_SET);
        timer = -(long)(rrd.rra_def[i].row_cnt - 1);
        ii = rrd.rra_ptr[i].cur_row;
        for (ix = 0; ix < rrd.rra_def[i].row_cnt; ix++) {
            ii++;
            if (ii >= rrd.rra_def[i].row_cnt) {
                rrd_seek(rrd_file, rra_start, SEEK_SET);
                ii = 0; /* wrap if max row cnt is reached */
            }
            now = (rrd.live_head->last_up
                   - rrd.live_head->last_up
                   % (rrd.rra_def[i].pdp_cnt * rrd.stat_head->pdp_step))
                + (timer * rrd.rra_def[i].pdp_cnt * rrd.stat_head->pdp_step);

            timer++;
#if HAVE_STRFTIME
            localtime_r(&now, &tm);
            strftime(somestring, 255, "%Y-%m-%d %H:%M:%S %Z", &tm);
#else
# error "Need strftime"
#endif
            CB_FMTS("\t\t\t<!-- %s / %lld --> <row>",  somestring, (long long int) now);
            for (iii = 0; iii < rrd.stat_head->ds_cnt; iii++) {
                rrd_read(rrd_file, &my_cdp, sizeof(rrd_value_t) * 1);
                if (isnan(my_cdp)) {
                    CB_PUTS("<v>NaN</v>");
                } else {
                    CB_FMTS("<v>%0.10e</v>", my_cdp);
                }
            }
            CB_PUTS("</row>\n");
        }
        CB_PUTS("\t\t</database>\n\t</rra>\n");
    }

    CB_PUTS("</rrd>\n");

    rrd_free(&rrd);

    return rrd_close(rrd_file);

err_out:
    rrd_set_error("error writing output file: %s", rrd_strerror(errno));
    rrd_free(&rrd);
    rrd_close(rrd_file);
    return (-1);

//Undefining the previously defined shortcuts
//See start of this function
#undef CB_PUTS
#undef CB_FMTS
//End of macro undefining

}
Ejemplo n.º 3
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;
	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);
}
Ejemplo n.º 4
0
rrd_info_t *rrd_info_r(
    const char *filename)
{
    unsigned int i, ii = 0;
    rrd_t     rrd;
    rrd_info_t *data = NULL, *cd;
    rrd_infoval_t info;
    rrd_file_t *rrd_file;
    enum cf_en current_cf;
    enum dst_en current_ds;

    rrd_init(&rrd);
    rrd_file = rrd_open(filename, &rrd, RRD_READONLY);
    if (rrd_file == NULL)
        goto err_free;

    info.u_str = filename;
    cd = rrd_info_push(NULL, sprintf_alloc("filename"), RD_I_STR, info);
    data = cd;

    info.u_str = rrd.stat_head->version;
    cd = rrd_info_push(cd, sprintf_alloc("rrd_version"), RD_I_STR, info);

    info.u_cnt = rrd.stat_head->pdp_step;
    cd = rrd_info_push(cd, sprintf_alloc("step"), RD_I_CNT, info);

    info.u_cnt = rrd.live_head->last_up;
    cd = rrd_info_push(cd, sprintf_alloc("last_update"), RD_I_CNT, info);

    info.u_cnt = rrd_get_header_size(&rrd);
    cd = rrd_info_push(cd, sprintf_alloc("header_size"), RD_I_CNT, info);

    for (i = 0; i < rrd.stat_head->ds_cnt; i++) {

        info.u_cnt=i;
        cd= rrd_info_push(cd,sprintf_alloc("ds[%s].index",
                                     rrd.ds_def[i].ds_nam),
                     RD_I_CNT, info);
    
        info.u_str = rrd.ds_def[i].dst;
        cd = rrd_info_push(cd, sprintf_alloc("ds[%s].type",
                                             rrd.ds_def[i].ds_nam),
                           RD_I_STR, info);

        current_ds = dst_conv(rrd.ds_def[i].dst);
        switch (current_ds) {
        case DST_CDEF:
        {
            char     *buffer = NULL;

            rpn_compact2str((rpn_cdefds_t *) &(rrd.ds_def[i].par[DS_cdef]),
                            rrd.ds_def, &buffer);
            info.u_str = buffer;
            cd = rrd_info_push(cd,
                               sprintf_alloc("ds[%s].cdef",
                                             rrd.ds_def[i].ds_nam), RD_I_STR,
                               info);
            free(buffer);
        }
            break;
        default:
            info.u_cnt = rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt;
            cd = rrd_info_push(cd,
                               sprintf_alloc("ds[%s].minimal_heartbeat",
                                             rrd.ds_def[i].ds_nam), RD_I_CNT,
                               info);

            info.u_val = rrd.ds_def[i].par[DS_min_val].u_val;
            cd = rrd_info_push(cd,
                               sprintf_alloc("ds[%s].min",
                                             rrd.ds_def[i].ds_nam), RD_I_VAL,
                               info);

            info.u_val = rrd.ds_def[i].par[DS_max_val].u_val;
            cd = rrd_info_push(cd,
                               sprintf_alloc("ds[%s].max",
                                             rrd.ds_def[i].ds_nam), RD_I_VAL,
                               info);
            break;
        }

        info.u_str = rrd.pdp_prep[i].last_ds;
        cd = rrd_info_push(cd,
                           sprintf_alloc("ds[%s].last_ds",
                                         rrd.ds_def[i].ds_nam), RD_I_STR,
                           info);

        info.u_val = rrd.pdp_prep[i].scratch[PDP_val].u_val;
        cd = rrd_info_push(cd,
                           sprintf_alloc("ds[%s].value",
                                         rrd.ds_def[i].ds_nam), RD_I_VAL,
                           info);

        info.u_cnt = rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt;
        cd = rrd_info_push(cd,
                           sprintf_alloc("ds[%s].unknown_sec",
                                         rrd.ds_def[i].ds_nam), RD_I_CNT,
                           info);
    }

    for (i = 0; i < rrd.stat_head->rra_cnt; i++) {
        info.u_str = rrd.rra_def[i].cf_nam;
        cd = rrd_info_push(cd, sprintf_alloc("rra[%d].cf", i), RD_I_STR,
                           info);
        current_cf = cf_conv(rrd.rra_def[i].cf_nam);

        info.u_cnt = rrd.rra_def[i].row_cnt;
        cd = rrd_info_push(cd, sprintf_alloc("rra[%d].rows", i), RD_I_CNT,
                           info);

        info.u_cnt = rrd.rra_ptr[i].cur_row;
        cd = rrd_info_push(cd, sprintf_alloc("rra[%d].cur_row", i), RD_I_CNT,
                           info);

        info.u_cnt = rrd.rra_def[i].pdp_cnt;
        cd = rrd_info_push(cd, sprintf_alloc("rra[%d].pdp_per_row", i),
                           RD_I_CNT, info);

        switch (current_cf) {
        case CF_HWPREDICT:
        case CF_MHWPREDICT:
            info.u_val = rrd.rra_def[i].par[RRA_hw_alpha].u_val;
            cd = rrd_info_push(cd, sprintf_alloc("rra[%d].alpha", i),
                               RD_I_VAL, info);
            info.u_val = rrd.rra_def[i].par[RRA_hw_beta].u_val;
            cd = rrd_info_push(cd, sprintf_alloc("rra[%d].beta", i), RD_I_VAL,
                               info);
            break;
        case CF_SEASONAL:
        case CF_DEVSEASONAL:
            info.u_val = rrd.rra_def[i].par[RRA_seasonal_gamma].u_val;
            cd = rrd_info_push(cd, sprintf_alloc("rra[%d].gamma", i),
                               RD_I_VAL, info);
            if (atoi(rrd.stat_head->version) >= 4) {
                info.u_val =
                    rrd.rra_def[i].par[RRA_seasonal_smoothing_window].u_val;
                cd = rrd_info_push(cd,
                                   sprintf_alloc("rra[%d].smoothing_window",
                                                 i), RD_I_VAL, info);
            }
            break;
        case CF_FAILURES:
            info.u_val = rrd.rra_def[i].par[RRA_delta_pos].u_val;
            cd = rrd_info_push(cd, sprintf_alloc("rra[%d].delta_pos", i),
                               RD_I_VAL, info);
            info.u_val = rrd.rra_def[i].par[RRA_delta_neg].u_val;
            cd = rrd_info_push(cd, sprintf_alloc("rra[%d].delta_neg", i),
                               RD_I_VAL, info);
            info.u_cnt = rrd.rra_def[i].par[RRA_failure_threshold].u_cnt;
            cd = rrd_info_push(cd,
                               sprintf_alloc("rra[%d].failure_threshold", i),
                               RD_I_CNT, info);
            info.u_cnt = rrd.rra_def[i].par[RRA_window_len].u_cnt;
            cd = rrd_info_push(cd, sprintf_alloc("rra[%d].window_length", i),
                               RD_I_CNT, info);
            break;
        case CF_DEVPREDICT:
            break;
        default:
            info.u_val = rrd.rra_def[i].par[RRA_cdp_xff_val].u_val;
            cd = rrd_info_push(cd, sprintf_alloc("rra[%d].xff", i), RD_I_VAL,
                               info);
            break;
        }

        for (ii = 0; ii < rrd.stat_head->ds_cnt; ii++) {
            switch (current_cf) {
            case CF_HWPREDICT:
            case CF_MHWPREDICT:
                info.u_val =
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                 ii].scratch[CDP_hw_intercept].u_val;
                cd = rrd_info_push(cd,
                                   sprintf_alloc
                                   ("rra[%d].cdp_prep[%d].intercept", i, ii),
                                   RD_I_VAL, info);
                info.u_val =
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                 ii].scratch[CDP_hw_slope].u_val;
                cd = rrd_info_push(cd,
                                   sprintf_alloc("rra[%d].cdp_prep[%d].slope",
                                                 i, ii), RD_I_VAL, info);
                info.u_cnt =
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                 ii].scratch[CDP_null_count].u_cnt;
                cd = rrd_info_push(cd,
                                   sprintf_alloc
                                   ("rra[%d].cdp_prep[%d].NaN_count", i, ii),
                                   RD_I_CNT, info);
                break;
            case CF_SEASONAL:
                info.u_val =
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                 ii].scratch[CDP_hw_seasonal].u_val;
                cd = rrd_info_push(cd,
                                   sprintf_alloc
                                   ("rra[%d].cdp_prep[%d].seasonal", i, ii),
                                   RD_I_VAL, info);
                break;
            case CF_DEVSEASONAL:
                info.u_val =
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                 ii].scratch[CDP_seasonal_deviation].u_val;
                cd = rrd_info_push(cd,
                                   sprintf_alloc
                                   ("rra[%d].cdp_prep[%d].deviation", i, ii),
                                   RD_I_VAL, info);
                break;
            case CF_DEVPREDICT:
                break;
            case CF_FAILURES:
            {
                unsigned short j;
                char     *violations_array;
                char      history[MAX_FAILURES_WINDOW_LEN + 1];

                violations_array =
                    (char *) rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                          ii].scratch;
                for (j = 0; j < rrd.rra_def[i].par[RRA_window_len].u_cnt; ++j)
                    history[j] = (violations_array[j] == 1) ? '1' : '0';
                history[j] = '\0';
                info.u_str = history;
                cd = rrd_info_push(cd,
                                   sprintf_alloc
                                   ("rra[%d].cdp_prep[%d].history", i, ii),
                                   RD_I_STR, info);
            }
                break;
            default:
                info.u_val =
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                 ii].scratch[CDP_val].u_val;
                cd = rrd_info_push(cd,
                                   sprintf_alloc("rra[%d].cdp_prep[%d].value",
                                                 i, ii), RD_I_VAL, info);
                info.u_cnt =
                    rrd.cdp_prep[i * rrd.stat_head->ds_cnt +
                                 ii].scratch[CDP_unkn_pdp_cnt].u_cnt;
                cd = rrd_info_push(cd,
                                   sprintf_alloc
                                   ("rra[%d].cdp_prep[%d].unknown_datapoints",
                                    i, ii), RD_I_CNT, info);
                break;
            }
        }
    }

    rrd_close(rrd_file);
  err_free:
    rrd_free(&rrd);
    return (data);
}
Ejemplo n.º 5
0
int rrd_tune(
    int argc,
    char **argv)
{
    rrd_t     rrd;
    int       matches;
    int       optcnt = 0;
    long      ds;
    char      ds_nam[DS_NAM_SIZE];
    char      ds_new[DS_NAM_SIZE];
    long      heartbeat;
    double    min = 0;
    double    max = 0;
    char      dst[DST_SIZE];
    int       rc = -1;
    int       opt_newstep = -1;
    rrd_file_t *rrd_file = NULL;
    char      *opt_daemon = NULL;
    char      double_str[ 12 ];
    const char *in_filename = NULL;
    struct option long_options[] = {
        {"heartbeat", required_argument, 0, 'h'},
        {"minimum", required_argument, 0, 'i'},
        {"maximum", required_argument, 0, 'a'},
        {"data-source-type", required_argument, 0, 'd'},
        {"data-source-rename", required_argument, 0, 'r'},
        /* added parameter tuning options for aberrant behavior detection */
        {"deltapos", required_argument, 0, 'p'},
        {"deltaneg", required_argument, 0, 'n'},
        {"window-length", required_argument, 0, 'w'},
        {"failure-threshold", required_argument, 0, 'f'},
        {"alpha", required_argument, 0, 'x'},
        {"beta", required_argument, 0, 'y'},
        {"gamma", required_argument, 0, 'z'},
        {"gamma-deviation", required_argument, 0, 'v'},
        {"smoothing-window", required_argument, 0, 's'},
        {"smoothing-window-deviation", required_argument, 0, 'S'},
        {"aberrant-reset", required_argument, 0, 'b'},
	// integration of rrd_modify functionality.
        {"step", required_argument, 0, 't'},
	/* unfortunately, '-d' is already taken */
        {"daemon", required_argument, 0, 'D'},
        {0, 0, 0, 0}
    };

    optind = 0;
    opterr = 0;         /* initialize getopt */

    /* before we open the input RRD, we should flush it from any caching
    daemon, because we might totally rewrite it later on */

    /* for this, we FIRST have to find the daemon, this means we must parse options twice... */
    
    while (1) {
	int option_index = 0;
	int opt = getopt_long(argc, argv, "h:i:a:d:r:p:n:w:f:x:y:z:v:b:",
			      long_options, &option_index);
        if (opt == EOF)
            break;
	switch (opt) {
	case 'D':
            if (opt_daemon != NULL)
		free (opt_daemon);
            opt_daemon = strdup (optarg);
            if (opt_daemon == NULL)
            {
                rrd_set_error ("strdup failed.");
                return (-1);
            }
            break;
	default:
	    break;
	}
    }
    
    // connect to daemon (will take care of environment variable automatically)
    if (rrdc_connect(opt_daemon) != 0) {
    	rrd_set_error("Cannot connect to daemon");
	return 1;
    }

    if (opt_daemon) {
	free(opt_daemon);
	opt_daemon = NULL;
    }

    if (optind < 0 || optind >= argc) {
	// missing file name...
	rrd_set_error("missing file name");
	goto done;
    }
    
    /* NOTE: getopt_long reorders argv and places all NON option arguments to
    the back, starting with optind. This means the file name has travelled to
    argv[optind] */
    
    in_filename = argv[optind];
    
    if (rrdc_is_any_connected()) {
	// is it a good idea to just ignore the error ????
	rrdc_flush(in_filename);
	rrd_clear_error();
    }

    optind = 0;
    opterr = 0;         /* re-initialize getopt */
    
    rrd_init(&rrd);
    rrd_file = rrd_open(in_filename, &rrd, RRD_READWRITE | RRD_READAHEAD | RRD_READVALUES);
    if (rrd_file == NULL) {
	goto done;
    }

    while (1) {
        int       option_index = 0;
        int       opt;
        unsigned int strtod_ret_val;

        opt = getopt_long(argc, argv, "h:i:a:d:r:p:n:w:f:x:y:z:v:b:",
                          long_options, &option_index);
        if (opt == EOF)
            break;

        optcnt++;
        switch (opt) {
        case 'h':
            if ((matches =
		 sscanf(optarg, DS_NAM_FMT ":%ld", ds_nam,
			&heartbeat)) != 2) {
                rrd_set_error("invalid arguments for heartbeat");
		goto done;
            }
            if ((ds = ds_match(&rrd, ds_nam)) == -1) {
		goto done;
            }
            rrd.ds_def[ds].par[DS_mrhb_cnt].u_cnt = heartbeat;
            break;

        case 'i':
            matches = sscanf(optarg, DS_NAM_FMT ":%[0-9.e+-]", ds_nam, double_str);
            if( matches >= 1 ) {
                strtod_ret_val = rrd_strtodbl( double_str, NULL, &min, NULL );
            }

            if ((matches < 1) || (strtod_ret_val != 2)) {
                rrd_set_error("invalid arguments for minimum ds value");
		goto done;
            }

            if ((ds = ds_match(&rrd, ds_nam)) == -1) {
		goto done;
            }

            if (matches == 1)
                min = DNAN;
            rrd.ds_def[ds].par[DS_min_val].u_val = min;
            break;

        case 'a':
            matches = sscanf(optarg, DS_NAM_FMT ":%[0-9.e+-]", ds_nam, double_str);
            if( matches >= 1 ) {
                strtod_ret_val = rrd_strtodbl( double_str, NULL, &max, NULL );
            }

            if ((matches < 1 ) || (strtod_ret_val != 2)) {
                rrd_set_error("invalid arguments for maximum ds value");
		goto done;
            }

            if ((ds = ds_match(&rrd, ds_nam)) == -1) {
		goto done;
            }

            if (matches == 1)
                max = DNAN;
            rrd.ds_def[ds].par[DS_max_val].u_val = max;
            break;

        case 'd':
            if ((matches =
                 sscanf(optarg, DS_NAM_FMT ":" DST_FMT, ds_nam, dst)) != 2) {
                rrd_set_error("invalid arguments for data source type");
		goto done;
	    }
            if ((ds = ds_match(&rrd, ds_nam)) == -1) {
		goto done;
            }
            if ((int) dst_conv(dst) == -1) {
		goto done;
            }
            /* only reset when something is changed */
            if (strncmp(rrd.ds_def[ds].dst, dst, DST_SIZE - 1) != 0) {
                strncpy(rrd.ds_def[ds].dst, dst, DST_SIZE - 1);
                rrd.ds_def[ds].dst[DST_SIZE - 1] = '\0';

                rrd.pdp_prep[ds].last_ds[0] = 'U';
                rrd.pdp_prep[ds].last_ds[1] = 'N';
                rrd.pdp_prep[ds].last_ds[2] = 'K';
                rrd.pdp_prep[ds].last_ds[3] = 'N';
                rrd.pdp_prep[ds].last_ds[4] = '\0';
            }
            break;
        case 'r':
            if ((matches =
                 sscanf(optarg, DS_NAM_FMT ":" DS_NAM_FMT, ds_nam,
                        ds_new)) != 2) {
                rrd_set_error("invalid arguments for data source type");
		goto done;
            }
            if ((ds = ds_match(&rrd, ds_nam)) == -1) {
		goto done;
            }
            strncpy(rrd.ds_def[ds].ds_nam, ds_new, DS_NAM_SIZE - 1);
            rrd.ds_def[ds].ds_nam[DS_NAM_SIZE - 1] = '\0';
            break;
        case 'p':
            if (set_deltaarg(&rrd, RRA_delta_pos, optarg)) {
		goto done;
            }
            break;
        case 'n':
            if (set_deltaarg(&rrd, RRA_delta_neg, optarg)) {
		goto done;
            }
            break;
        case 'f':
            if (set_windowarg(&rrd, RRA_failure_threshold, optarg)) {
		goto done;
            }
            break;
        case 'w':
            if (set_windowarg(&rrd, RRA_window_len, optarg)) {
		goto done;
            }
            break;
        case 'x':
            if (set_hwarg(&rrd, CF_HWPREDICT, RRA_hw_alpha, optarg)) {
                if (set_hwarg(&rrd, CF_MHWPREDICT, RRA_hw_alpha, optarg)) {
		    goto done;
                }
                rrd_clear_error();
            }
            break;
        case 'y':
            if (set_hwarg(&rrd, CF_HWPREDICT, RRA_hw_beta, optarg)) {
                if (set_hwarg(&rrd, CF_MHWPREDICT, RRA_hw_beta, optarg)) {
		    goto done;
                }
                rrd_clear_error();
            }
            break;
        case 'z':
            if (set_hwarg(&rrd, CF_SEASONAL, RRA_seasonal_gamma, optarg)) {
		goto done;
            }
            break;
        case 'v':
            if (set_hwarg(&rrd, CF_DEVSEASONAL, RRA_seasonal_gamma, optarg)) {
		goto done;
	    }
            break;
        case 'b':
            if (sscanf(optarg, DS_NAM_FMT, ds_nam) != 1) {
                rrd_set_error("invalid argument for aberrant-reset");
		goto done;
            }
            if ((ds = ds_match(&rrd, ds_nam)) == -1) {
                /* ds_match handles it own errors */
		goto done;
            }
            reset_aberrant_coefficients(&rrd, rrd_file, (unsigned long) ds);
            if (rrd_test_error()) {
		goto done;
            }
            break;
        case 's':
            if (atoi(rrd.stat_head->version) < atoi(RRD_VERSION4)) {
                strcpy(rrd.stat_head->version, RRD_VERSION4);    /* smoothing_window causes Version 4 */
            }
            if (set_hwsmootharg
                (&rrd, CF_SEASONAL, RRA_seasonal_smoothing_window, optarg)) {
		goto done;
            }
            break;
        case 'S':
            if (atoi(rrd.stat_head->version) < atoi(RRD_VERSION4)) {
                strcpy(rrd.stat_head->version, RRD_VERSION4);    /* smoothing_window causes Version 4 */
            }
            if (set_hwsmootharg
                (&rrd, CF_DEVSEASONAL, RRA_seasonal_smoothing_window,
                 optarg)) {
		goto done;
            }
            break;
	case 't':
	    opt_newstep = atoi(optarg);
	    break;
	case 'D':
	    // ignore, handled in previous argv parsing round
	    break;
        case '?':
            if (optopt != 0)
                rrd_set_error("unknown option '%c'", optopt);
            else
                rrd_set_error("unknown option '%s'", argv[optind - 1]);
	    goto done;
        }
    }
    if (optcnt > 0) {
        rrd_seek(rrd_file, 0, SEEK_SET);
        rrd_write(rrd_file, rrd.stat_head, sizeof(stat_head_t) * 1);
        rrd_write(rrd_file, rrd.ds_def,
                  sizeof(ds_def_t) * rrd.stat_head->ds_cnt);
        /* need to write rra_defs for RRA parameter changes */
        rrd_write(rrd_file, rrd.rra_def,
                  sizeof(rra_def_t) * rrd.stat_head->rra_cnt);
    }
    
    if (optind >= argc) {
        int       i;

        for (i = 0; i < (int) rrd.stat_head->ds_cnt; i++)
            if (dst_conv(rrd.ds_def[i].dst) != DST_CDEF) {
                printf("DS[%s] typ: %s\thbt: %ld\tmin: %1.4f\tmax: %1.4f\n",
                       rrd.ds_def[i].ds_nam,
                       rrd.ds_def[i].dst,
                       rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt,
                       rrd.ds_def[i].par[DS_min_val].u_val,
                       rrd.ds_def[i].par[DS_max_val].u_val);
            } else {
                char     *buffer = NULL;

                rpn_compact2str((rpn_cdefds_t *) &
                                (rrd.ds_def[i].par[DS_cdef]), rrd.ds_def,
                                &buffer);
                printf("DS[%s] typ: %s\tcdef: %s\n", rrd.ds_def[i].ds_nam,
                       rrd.ds_def[i].dst, buffer);
                if (buffer) free(buffer);
            }
    }

    optind = handle_modify(&rrd, in_filename, argc, argv, optind + 1, opt_newstep);
    if (optind < 0) {
	goto done;
    }
    
    rc = 0;
done:
    if (in_filename && rrdc_is_any_connected()) {
        // save any errors....
        char *e = strdup(rrd_get_error());
	// is it a good idea to just ignore the error ????
	rrdc_forget(in_filename);
	rrd_clear_error();
        
        if (e && *e) {
            rrd_set_error(e);
        }
        if (e) free(e);
        
    }
    if (rrd_file) {
	rrd_close(rrd_file);
    }
    rrd_free(&rrd);
    return rc;
}
Ejemplo n.º 6
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);
}
Ejemplo n.º 7
0
int
rrd_tune(int argc, char **argv)    
{   
    rrd_t               rrd;
    FILE               *rrd_file;
    int                 matches;
    int                 optcnt = 0;
    long                ds;
    char                ds_nam[DS_NAM_SIZE];
    char                ds_new[DS_NAM_SIZE];
    long                heartbeat;
    double              min;
    double              max;
    char                dst[DST_SIZE];
    optind = 0; opterr = 0;  /* initialize getopt */


    if(rrd_open(argv[1],&rrd_file,&rrd, RRD_READWRITE)==-1){
        return -1;
    }

    
    while (1){
	static struct option long_options[] =
	{
	    {"heartbeat",        required_argument, 0, 'h'},
	    {"minimum",          required_argument, 0, 'i'},
	    {"maximum",          required_argument, 0, 'a'},
	    {"data-source-type", required_argument, 0, 'd'},
	    {"data-source-rename", required_argument, 0, 'r'},
	    /* added parameter tuning options for aberrant behavior detection */
		{"deltapos",required_argument,0,'p'},
		{"deltaneg",required_argument,0,'n'},
		{"window-length",required_argument,0,'w'},
		{"failure-threshold",required_argument,0,'f'},
	    {"alpha",required_argument,0,'x'},
	    {"beta",required_argument,0,'y'},
	    {"gamma",required_argument,0,'z'},
	    {"gamma-deviation",required_argument,0,'v'},
		{"aberrant-reset",required_argument,0,'b'},
	    {0,0,0,0}
	};
	int option_index = 0;
	int opt;
	opt = getopt_long(argc, argv, "h:i:a:d:r:p:n:w:f:x:y:z:v:b:", 
			  long_options, &option_index);
	if (opt == EOF)
	    break;
	
	optcnt++;
	switch(opt) {	    
	case 'h':
	    if ((matches = sscanf(optarg, DS_NAM_FMT ":%ld",ds_nam,&heartbeat)) != 2){
		rrd_set_error("invalid arguments for heartbeat");
		rrd_free(&rrd);
	        fclose(rrd_file);
		return -1;
	    }
	    if ((ds=ds_match(&rrd,ds_nam))==-1){
		rrd_free(&rrd);
                fclose(rrd_file);
		return -1;
	    }
	    rrd.ds_def[ds].par[DS_mrhb_cnt].u_cnt = heartbeat;
	    break;

	case 'i':
	    if ((matches = sscanf(optarg,DS_NAM_FMT ":%lf",ds_nam,&min)) <1){
		rrd_set_error("invalid arguments for minimum ds value");
		rrd_free(&rrd);
                fclose(rrd_file);
		return -1;
	    }
	    if ((ds=ds_match(&rrd,ds_nam))==-1){
		rrd_free(&rrd);
                fclose(rrd_file);
		return -1;
	    }

	    if(matches == 1)
		min= DNAN;
	    rrd.ds_def[ds].par[DS_min_val].u_val = min;
	    break;

	case 'a':
	    if ((matches = sscanf(optarg, DS_NAM_FMT ":%lf",ds_nam,&max)) <1){
		rrd_set_error("invalid arguments for maximum ds value");
		rrd_free(&rrd);
	        fclose(rrd_file);
		return -1;
	    }
	    if ((ds=ds_match(&rrd,ds_nam))==-1){
		rrd_free(&rrd);
	        fclose(rrd_file);
		return -1;
	    }
	    if(matches == 1) 
		max= DNAN; 
	    rrd.ds_def[ds].par[DS_max_val].u_val = max;
	    break;

	case 'd':
	    if ((matches = sscanf(optarg, DS_NAM_FMT ":" DST_FMT ,ds_nam,dst)) != 2){
		rrd_set_error("invalid arguments for data source type");
		rrd_free(&rrd);
	        fclose(rrd_file);
		return -1;
	    }
	    if ((ds=ds_match(&rrd,ds_nam))==-1){
		rrd_free(&rrd);
	        fclose(rrd_file);
		return -1;
	    }
	    if ((int)dst_conv(dst) == -1){
		rrd_free(&rrd);
	        fclose(rrd_file);
		return -1;
	    }
	    strncpy(rrd.ds_def[ds].dst,dst,DST_SIZE-1);
	    rrd.ds_def[ds].dst[DST_SIZE-1]='\0';

	    rrd.pdp_prep[ds].last_ds[0] = 'U';
	    rrd.pdp_prep[ds].last_ds[1] = 'N';
	    rrd.pdp_prep[ds].last_ds[2] = 'K';
	    rrd.pdp_prep[ds].last_ds[3] = 'N';
	    rrd.pdp_prep[ds].last_ds[4] = '\0';
	    
	    break;
	case 'r':
	    if ((matches = 
		 sscanf(optarg,DS_NAM_FMT ":" DS_NAM_FMT , ds_nam,ds_new)) != 2){
		rrd_set_error("invalid arguments for data source type");
		rrd_free(&rrd);
	        fclose(rrd_file);
		return -1;
	    }
	    if ((ds=ds_match(&rrd,ds_nam))==-1){
		rrd_free(&rrd);
	        fclose(rrd_file);
		return -1;
	    }
	    strncpy(rrd.ds_def[ds].ds_nam,ds_new,DS_NAM_SIZE-1);
	    rrd.ds_def[ds].ds_nam[DS_NAM_SIZE-1]='\0';
	    break;
    case 'p':
		if (set_deltaarg(&rrd,RRA_delta_pos,optarg)) {
		   rrd_free(&rrd);
		   return -1;
		}
		break;
	case 'n':
		if (set_deltaarg(&rrd,RRA_delta_neg,optarg)) {
		   rrd_free(&rrd);
		   return -1;
		}
		break;
	case 'f':
		if (set_windowarg(&rrd,RRA_failure_threshold,optarg)) {
		   rrd_free(&rrd);
		   return -1;
		}
		break;
	case 'w':
		if (set_windowarg(&rrd,RRA_window_len,optarg)) {
		   rrd_free(&rrd);
		   return -1;
		}
		break;
	case 'x':
		if (set_hwarg(&rrd,CF_HWPREDICT,RRA_hw_alpha,optarg)) {
		   rrd_free(&rrd);
		   return -1;
		}
		break;
	case 'y':
		if (set_hwarg(&rrd,CF_HWPREDICT,RRA_hw_beta,optarg)) {
		   rrd_free(&rrd);
		   return -1;
		}
		break;
	case 'z':
		if (set_hwarg(&rrd,CF_SEASONAL,RRA_seasonal_gamma,optarg)) {
		   rrd_free(&rrd);
		   return -1;
		}
		break;
	case 'v':
		if (set_hwarg(&rrd,CF_DEVSEASONAL,RRA_seasonal_gamma,optarg)) {
		   rrd_free(&rrd);
		   return -1;
		}
		break;
	case 'b':
		if (sscanf(optarg,DS_NAM_FMT,ds_nam) != 1){
		rrd_set_error("invalid argument for aberrant-reset");
		rrd_free(&rrd);
	        fclose(rrd_file);
		return -1;
	    }
	    if ((ds=ds_match(&rrd,ds_nam))==-1){
	    /* ds_match handles it own errors */	
		rrd_free(&rrd);
	        fclose(rrd_file);
		return -1;
	    }
	    reset_aberrant_coefficients(&rrd,rrd_file,(unsigned long) ds);
		if (rrd_test_error()) {
		   rrd_free(&rrd);
		   fclose(rrd_file);
		   return -1;
		}
		break;
	case '?':
            if (optopt != 0)
                rrd_set_error("unknown option '%c'", optopt);
            else
                rrd_set_error("unknown option '%s'",argv[optind-1]);
	    rrd_free(&rrd);	    
            fclose(rrd_file);
            return -1;
        }
    }
	if(optcnt>0){
	
	fseek(rrd_file,0,SEEK_SET);
	fwrite(rrd.stat_head,
	       sizeof(stat_head_t),1, rrd_file);
	fwrite(rrd.ds_def,
	       sizeof(ds_def_t), rrd.stat_head->ds_cnt, rrd_file);
	/* need to write rra_defs for RRA parameter changes */
	fwrite(rrd.rra_def, sizeof(rra_def_t), rrd.stat_head->rra_cnt,
		   rrd_file);
    } else {
	int i;
	for(i=0;i< (int)rrd.stat_head->ds_cnt;i++)
		if (dst_conv(rrd.ds_def[i].dst) != DST_CDEF) {
	    printf("DS[%s] typ: %s\thbt: %ld\tmin: %1.4f\tmax: %1.4f\n",
		   rrd.ds_def[i].ds_nam,
		   rrd.ds_def[i].dst,
		   rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt,
		   rrd.ds_def[i].par[DS_min_val].u_val,
		   rrd.ds_def[i].par[DS_max_val].u_val);
		} else {
		char *buffer = NULL;
		rpn_compact2str((rpn_cdefds_t *) &(rrd.ds_def[i].par[DS_cdef]),rrd.ds_def,&buffer);
		printf("DS[%s] typ: %s\tcdef: %s\n", rrd.ds_def[i].ds_nam,rrd.ds_def[i].dst,buffer);
	    free(buffer);
		}
    }
    fclose(rrd_file);
    rrd_free(&rrd);
    return 0;
}
Ejemplo n.º 8
0
int
rrd_create(int argc, char **argv) 
{
    rrd_t          rrd;
    long                i,long_tmp;
    time_t             last_up;
    struct rrd_time_value last_up_tv;
    char *parsetime_error = NULL;

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

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

    /* set some defaults */
    strcpy(rrd.stat_head->cookie,RRD_COOKIE);
    strcpy(rrd.stat_head->version,RRD_VERSION);
    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 = 300; /* 5 minute default */

    /* a default value */
    rrd.ds_def = NULL;
    rrd.rra_def = NULL;
    
    while (1){
	static struct option long_options[] =
	{
	    {"start",      required_argument, 0, 'b'},
	    {"step",        required_argument,0,'s'},
	    {0,0,0,0}
	};
	int option_index = 0;
	int opt;
	opt = getopt_long(argc, argv, "b:s:", 
			  long_options, &option_index);
	
	if (opt == EOF)
	  break;
	
	switch(opt) {
	case 'b':
            if ((parsetime_error = parsetime(optarg, &last_up_tv))) {
                rrd_set_error("start time: %s", parsetime_error );
		rrd_free(&rrd);
                return(-1);
	    }
	    if (last_up_tv.type == RELATIVE_TO_END_TIME ||
		last_up_tv.type == RELATIVE_TO_START_TIME) {
		rrd_set_error("specifying time relative to the 'start' "
                              "or 'end' makes no sense here");
		rrd_free(&rrd);
		return(-1);
	    }

	    last_up = mktime(&last_up_tv.tm) + last_up_tv.offset;
	    
	    if (last_up < 3600*24*365*10){
		rrd_set_error("the first entry to the RRD should be after 1980");
		rrd_free(&rrd);
		return(-1);
	    }	
	    break;

	case 's':
	    long_tmp = atol(optarg);
	    if (long_tmp < 1){
		rrd_set_error("step size should be no less than one second");
		rrd_free(&rrd);
		return(-1);
	    }
	    rrd.stat_head->pdp_step = long_tmp;
	    break;

	case '?':
            if (optopt != 0)
                rrd_set_error("unknown option '%c'", optopt);
            else
                rrd_set_error("unknown option '%s'",argv[optind-1]);
            rrd_free(&rrd);
	    return(-1);
	}
    }
    rrd.live_head->last_up = last_up;

    for(i=optind+1;i<argc;i++){
	char minstr[DS_NAM_SIZE], maxstr[DS_NAM_SIZE];	
	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 = rrd_realloc(rrd.ds_def,
				     old_size+sizeof(ds_def_t)))==NULL){
		rrd_set_error("allocating rrd.ds_def");
		rrd_free(&rrd);
		return(-1);	
	    }
	    memset(&rrd.ds_def[rrd.stat_head->ds_cnt], 0, sizeof(ds_def_t));
	    if (sscanf(&argv[i][3],
		       DS_NAM_FMT ":" DST_FMT ":%lu:%18[^:]:%18[^:]",
		       rrd.ds_def[rrd.stat_head->ds_cnt].ds_nam,
		       rrd.ds_def[rrd.stat_head->ds_cnt].dst,
		       &rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_mrhb_cnt].u_cnt,
		       minstr,maxstr) == 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);
		                rrd_free(&rrd);
                                return(-1);
			}				                                
		}
		if(dst_conv(rrd.ds_def[rrd.stat_head->ds_cnt].dst) == -1){
		    rrd_free(&rrd);
		    return (-1);
		}
		if (minstr[0] == 'U' && minstr[1] == 0)
		    rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_min_val].u_val = DNAN;
		else
		    rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_min_val].u_val = atof(minstr);
		
		if (maxstr[0] == 'U' && maxstr[1] == 0)
		    rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_max_val].u_val = DNAN;
		else
		    rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_max_val].u_val  = atof(maxstr);
		
		if (! isnan(rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_min_val].u_val) &&
		    ! isnan(rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_max_val].u_val) &&
		    rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_min_val].u_val
		    >= rrd.ds_def[rrd.stat_head->ds_cnt].par[DS_max_val].u_val ) {
		    rrd_set_error("min must be less than max in DS definition");
		    rrd_free(&rrd);
		    return (-1);		
		}
		rrd.stat_head->ds_cnt++;	    
	    } else {
		rrd_set_error("can't parse argument '%s'",argv[i]);
		rrd_free(&rrd);
		return (-1);		
	    }
	} else if (strncmp(argv[i],"RRA:",3)==0){
	    size_t old_size = sizeof(rra_def_t)*(rrd.stat_head->rra_cnt);
	    if((rrd.rra_def = rrd_realloc(rrd.rra_def,
				      old_size+sizeof(rra_def_t)))==NULL){
		rrd_set_error("allocating rrd.rra_def");
		rrd_free(&rrd);
		return(-1);	
	    }
	    memset(&rrd.rra_def[rrd.stat_head->rra_cnt], 0, sizeof(rra_def_t));
	    if (sscanf(&argv[i][4],
		       CF_NAM_FMT ":%lf:%lu:%lu",
		       rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam,
		       &rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_cdp_xff_val].u_val,
		       &rrd.rra_def[rrd.stat_head->rra_cnt].pdp_cnt,
		       &rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt) == 4){
		if(cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam) == -1){
		    rrd_free(&rrd);
		    return (-1);
		}
	        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("the xff must always be >= 0 and < 1");
		    rrd_free(&rrd);
		    return (-1);
		}
		rrd.stat_head->rra_cnt++;	    		
	    }
	    else {  
		rrd_set_error("can't parse argument '%s'",argv[i]);
		rrd_free(&rrd);
		return (-1);		
	    }

	} else {
	    rrd_set_error("can't parse argument '%s'",argv[i]);
	    rrd_free(&rrd);
            return -1;
	}
    }


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

    if (rrd.stat_head->ds_cnt < 1){
	rrd_set_error("you must define at least one Data Source");
	rrd_free(&rrd);
	return(-1);
    }
    return rrd_create_fn(argv[optind],&rrd);
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
0
int
rrd_dump_r(char *filename)    
{   
    unsigned int i,ii,ix,iii=0;
    time_t       now;
    char         somestring[255];
    rrd_value_t  my_cdp;
    long         rra_base, rra_start, rra_next;
    FILE        *in_file;
    rrd_t        rrd;
    rrd_value_t  value;
    struct tm    tm;
    if(rrd_open(filename, &in_file,&rrd, RRD_READONLY)==-1){
	rrd_free(&rrd);
	return(-1);
    }

    puts("<!-- Round Robin Database Dump -->");
    puts("<rrd>");
    printf("\t<version> %s </version>\n",RRD_VERSION);
    printf("\t<step> %lu </step> <!-- Seconds -->\n",rrd.stat_head->pdp_step);
#if HAVE_STRFTIME
    localtime_r(&rrd.live_head->last_up, &tm);
    strftime(somestring,200,"%Y-%m-%d %H:%M:%S %Z",
	     &tm);
#else
# error "Need strftime"
#endif
    printf("\t<lastupdate> %ld </lastupdate> <!-- %s -->\n\n",
	   rrd.live_head->last_up,somestring);
    for(i=0;i<rrd.stat_head->ds_cnt;i++){
	printf("\t<ds>\n");
	printf("\t\t<name> %s </name>\n",rrd.ds_def[i].ds_nam);
	printf("\t\t<type> %s </type>\n",rrd.ds_def[i].dst);
    if (dst_conv(rrd.ds_def[i].dst) != DST_CDEF) {
	printf("\t\t<minimal_heartbeat> %lu </minimal_heartbeat>\n",rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt);
	if (isnan(rrd.ds_def[i].par[DS_min_val].u_val)){
	  printf("\t\t<min> NaN </min>\n");
	} else {
	  printf("\t\t<min> %0.10e </min>\n",rrd.ds_def[i].par[DS_min_val].u_val);
	}
	if (isnan(rrd.ds_def[i].par[DS_max_val].u_val)){
	  printf("\t\t<max> NaN </max>\n");
	} else {
	  printf("\t\t<max> %0.10e </max>\n",rrd.ds_def[i].par[DS_max_val].u_val);
	}
    } else { /* DST_CDEF */
	  char *str;
	  rpn_compact2str((rpn_cdefds_t *) &(rrd.ds_def[i].par[DS_cdef]),rrd.ds_def,&str);
	  printf("\t\t<cdef> %s </cdef>\n", str);
	  free(str);
	}
	printf("\n\t\t<!-- PDP Status -->\n");
	printf("\t\t<last_ds> %s </last_ds>\n",rrd.pdp_prep[i].last_ds);
	if (isnan(rrd.pdp_prep[i].scratch[PDP_val].u_val)){
	  printf("\t\t<value> NaN </value>\n");
	} else {
	  printf("\t\t<value> %0.10e </value>\n",rrd.pdp_prep[i].scratch[PDP_val].u_val);
	}
	printf("\t\t<unknown_sec> %lu </unknown_sec>\n",
	       rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt);
	
	printf("\t</ds>\n\n");
    }

    puts("<!-- Round Robin Archives -->");

    rra_base=ftell(in_file);    
    rra_next = rra_base;

    for(i=0;i<rrd.stat_head->rra_cnt;i++){
	
	long timer=0;
	rra_start= rra_next;
	rra_next +=  ( rrd.stat_head->ds_cnt
                      * rrd.rra_def[i].row_cnt
                      * sizeof(rrd_value_t));
	printf("\t<rra>\n");
	printf("\t\t<cf> %s </cf>\n",rrd.rra_def[i].cf_nam);
	printf("\t\t<pdp_per_row> %lu </pdp_per_row> <!-- %lu seconds -->\n\n",
	       rrd.rra_def[i].pdp_cnt, rrd.rra_def[i].pdp_cnt
	       *rrd.stat_head->pdp_step);
	/* support for RRA parameters */
	printf("\t\t<params>\n");
	switch(cf_conv(rrd.rra_def[i].cf_nam)) {
	case CF_HWPREDICT:
	   printf("\t\t<hw_alpha> %0.10e </hw_alpha>\n", 
		  rrd.rra_def[i].par[RRA_hw_alpha].u_val);
	   printf("\t\t<hw_beta> %0.10e </hw_beta>\n", 
		  rrd.rra_def[i].par[RRA_hw_beta].u_val);
	   printf("\t\t<dependent_rra_idx> %lu </dependent_rra_idx>\n",
		  rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
	   break;
	case CF_SEASONAL:
	case CF_DEVSEASONAL:
	   printf("\t\t<seasonal_gamma> %0.10e </seasonal_gamma>\n", 
		  rrd.rra_def[i].par[RRA_seasonal_gamma].u_val);
	   printf("\t\t<seasonal_smooth_idx> %lu </seasonal_smooth_idx>\n",
		  rrd.rra_def[i].par[RRA_seasonal_smooth_idx].u_cnt);
	   printf("\t\t<dependent_rra_idx> %lu </dependent_rra_idx>\n",
		  rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
	   break;
	case CF_FAILURES:
	   printf("\t\t<delta_pos> %0.10e </delta_pos>\n", 
		  rrd.rra_def[i].par[RRA_delta_pos].u_val);
	   printf("\t\t<delta_neg> %0.10e </delta_neg>\n", 
		  rrd.rra_def[i].par[RRA_delta_neg].u_val);
	   printf("\t\t<window_len> %lu </window_len>\n",
		  rrd.rra_def[i].par[RRA_window_len].u_cnt);
	   printf("\t\t<failure_threshold> %lu </failure_threshold>\n",
		  rrd.rra_def[i].par[RRA_failure_threshold].u_cnt);
		  /* fall thru */
	case CF_DEVPREDICT:
	   printf("\t\t<dependent_rra_idx> %lu </dependent_rra_idx>\n",
		  rrd.rra_def[i].par[RRA_dependent_rra_idx].u_cnt);
	   break;
	case CF_AVERAGE:
	case CF_MAXIMUM:
	case CF_MINIMUM:
	case CF_LAST:
	default:
	   printf("\t\t<xff> %0.10e </xff>\n", rrd.rra_def[i].par[RRA_cdp_xff_val].u_val);
	   break;
	}
	printf("\t\t</params>\n");
	printf("\t\t<cdp_prep>\n");
	for(ii=0;ii<rrd.stat_head->ds_cnt;ii++){
		unsigned long ivalue;
		printf("\t\t\t<ds>\n");
		/* support for exporting all CDP parameters */
		/* parameters common to all CFs */
		    /* primary_val and secondary_val do not need to be saved between updates
			 * so strictly speaking they could be omitted.
			 * However, they can be useful for diagnostic purposes, so are included here. */
	        value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt
			   +ii].scratch[CDP_primary_val].u_val;
			if (isnan(value)) {
			   printf("\t\t\t<primary_value> NaN </primary_value>\n");
			} else {
			   printf("\t\t\t<primary_value> %0.10e </primary_value>\n", value);
			}
	        value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_secondary_val].u_val;
			if (isnan(value)) {
			   printf("\t\t\t<secondary_value> NaN </secondary_value>\n");
			} else {
			   printf("\t\t\t<secondary_value> %0.10e </secondary_value>\n", value);
			}
		switch(cf_conv(rrd.rra_def[i].cf_nam)) {
		case CF_HWPREDICT:
	        value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_hw_intercept].u_val;
			if (isnan(value)) {
			   printf("\t\t\t<intercept> NaN </intercept>\n");
			} else {
			   printf("\t\t\t<intercept> %0.10e </intercept>\n", value);
			}
	        value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_hw_last_intercept].u_val;
			if (isnan(value)) {
			   printf("\t\t\t<last_intercept> NaN </last_intercept>\n");
			} else {
			   printf("\t\t\t<last_intercept> %0.10e </last_intercept>\n", value);
			}
	        value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_hw_slope].u_val;
			if (isnan(value)) {
			   printf("\t\t\t<slope> NaN </slope>\n");
			} else {
			   printf("\t\t\t<slope> %0.10e </slope>\n", value);
			}
	        value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_hw_last_slope].u_val;
			if (isnan(value)) {
			   printf("\t\t\t<last_slope> NaN </last_slope>\n");
			} else {
			   printf("\t\t\t<last_slope> %0.10e </last_slope>\n", value);
			}
			ivalue = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_null_count].u_cnt;
			printf("\t\t\t<nan_count> %lu </nan_count>\n", ivalue);
			ivalue = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_last_null_count].u_cnt;
			printf("\t\t\t<last_nan_count> %lu </last_nan_count>\n", ivalue);
			break;
		case CF_SEASONAL:
		case CF_DEVSEASONAL:
	        value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_hw_seasonal].u_val;
			if (isnan(value)) {
			   printf("\t\t\t<seasonal> NaN </seasonal>\n");
			} else {
			   printf("\t\t\t<seasonal> %0.10e </seasonal>\n", value);
			}
	        value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_hw_last_seasonal].u_val;
			if (isnan(value)) {
			   printf("\t\t\t<last_seasonal> NaN </last_seasonal>\n");
			} else {
			   printf("\t\t\t<last_seasonal> %0.10e </last_seasonal>\n", value);
			}
	        ivalue = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_init_seasonal].u_cnt;
			printf("\t\t\t<init_flag> %lu </init_flag>\n", ivalue);
			break;
		case CF_DEVPREDICT:
			break;
		case CF_FAILURES:
		    {
            unsigned short vidx;
			char *violations_array = (char *) ((void*) 
			   rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch);
			printf("\t\t\t<history> ");
			for (vidx = 0; vidx < rrd.rra_def[i].par[RRA_window_len].u_cnt; ++vidx)
			{
				printf("%d",violations_array[vidx]);
			}
			printf(" </history>\n");
			}
			break;
		case CF_AVERAGE:
		case CF_MAXIMUM:
		case CF_MINIMUM:
		case CF_LAST:
		default:
	        value = rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_val].u_val;
			if (isnan(value)) {
			   printf("\t\t\t<value> NaN </value>\n");
			} else {
			   printf("\t\t\t<value> %0.10e </value>\n", value);
			}
		    printf("\t\t\t<unknown_datapoints> %lu </unknown_datapoints>\n",
		       rrd.cdp_prep[i*rrd.stat_head->ds_cnt+ii].scratch[CDP_unkn_pdp_cnt].u_cnt);
			break;
		}
        printf("\t\t\t</ds>\n");	 
    }
	printf("\t\t</cdp_prep>\n");

	printf("\t\t<database>\n");
	fseek(in_file,(rra_start
		       +(rrd.rra_ptr[i].cur_row+1)
		       * rrd.stat_head->ds_cnt
		       * sizeof(rrd_value_t)),SEEK_SET);
	timer = - (rrd.rra_def[i].row_cnt-1);
	ii=rrd.rra_ptr[i].cur_row;
	for(ix=0;ix<rrd.rra_def[i].row_cnt;ix++){	    
	    ii++;
	    if (ii>=rrd.rra_def[i].row_cnt) {
		fseek(in_file,rra_start,SEEK_SET);
		ii=0; /* wrap if max row cnt is reached */
	    }
	    now = (rrd.live_head->last_up 
		   - rrd.live_head->last_up 
		   % (rrd.rra_def[i].pdp_cnt*rrd.stat_head->pdp_step)) 
		+ (timer*rrd.rra_def[i].pdp_cnt*rrd.stat_head->pdp_step);

	    timer++;
#if HAVE_STRFTIME
	    localtime_r(&now, &tm);
	    strftime(somestring,200,"%Y-%m-%d %H:%M:%S %Z", &tm);
#else
# error "Need strftime"
#endif
	    printf("\t\t\t<!-- %s / %d --> <row>",somestring,(int)now);
	    for(iii=0;iii<rrd.stat_head->ds_cnt;iii++){			 
		fread(&my_cdp,sizeof(rrd_value_t),1,in_file);		
		if (isnan(my_cdp)){
		  printf("<v> NaN </v>");
		} else {
		  printf("<v> %0.10e </v>",my_cdp);
		};
	    }
	    printf("</row>\n");
	}
	printf("\t\t</database>\n\t</rra>\n");
	
    }
    printf("</rrd>\n");
    rrd_free(&rrd);
    fclose(in_file);
    return(0);
}