예제 #1
0
static int readfile(
    const char *file_name,
    char **buffer,
    int skipfirst)
{
    long      writecnt = 0, totalcnt = MEMBLK;
    long      offset = 0;
    FILE     *input = NULL;
    char      c;

    if ((strcmp("-", file_name) == 0)) {
        input = stdin;
    } else {
        if ((input = fopen(file_name, "rb")) == NULL) {
            rrd_set_error("opening '%s': %s", file_name, rrd_strerror(errno));
            return (-1);
        }
    }
    if (skipfirst) {
        do {
            c = getc(input);
            offset++;
        } while (c != '\n' && !feof(input));
    }
    if (strcmp("-", file_name)) {
        fseek(input, 0, SEEK_END);
        /* have extra space for detecting EOF without realloc */
        totalcnt = (ftell(input) + 1) / sizeof(char) - offset;
        if (totalcnt < MEMBLK)
            totalcnt = MEMBLK;  /* sanitize */
        fseek(input, offset * sizeof(char), SEEK_SET);
    }
    if (((*buffer) = (char *) malloc((totalcnt + 4) * sizeof(char))) == NULL) {
        perror("Allocate Buffer:");
        exit(1);
    };
    do {
        writecnt +=
            fread((*buffer) + writecnt, 1,
                  (totalcnt - writecnt) * sizeof(char), input);
        if (writecnt >= totalcnt) {
            totalcnt += MEMBLK;
            if (((*buffer) =
                 rrd_realloc((*buffer),
                             (totalcnt + 4) * sizeof(char))) == NULL) {
                perror("Realloc Buffer:");
                exit(1);
            };
        }
    } while (!feof(input));
    (*buffer)[writecnt] = '\0';
    if (strcmp("-", file_name) != 0) {
        fclose(input);
    };
    return writecnt;
}
예제 #2
0
int rrd_add_ptr_chunk(void ***dest, size_t *dest_size, void *src,
                      size_t *alloc, size_t chunk)
{
    void **temp;

    assert(dest != NULL);
    assert(alloc != NULL);
    assert(*alloc >= *dest_size);

    if (*alloc == *dest_size)
    {
        temp = (void **) rrd_realloc(*dest, (*alloc+chunk) * sizeof(*dest));
        if (!temp)
            return 0;

        *dest = temp;
        *alloc += chunk;
    }

    (*dest)[*dest_size] = src;
    (*dest_size)++;

    return 1;
}
예제 #3
0
파일: rrd_create.c 프로젝트: yubo/rrdlite
/* Create the CF_DEVPREDICT, CF_DEVSEASONAL, CF_SEASONAL, and CF_FAILURES RRAs
 * associated with a CF_HWPREDICT RRA. */
int create_hw_contingent_rras(
		rrd_t *rrd,
		unsigned short period,
		unsigned long hashed_name)
{
	size_t    old_size;
	rra_def_t *current_rra;

	/* save index to CF_HWPREDICT */
	unsigned long hw_index = rrd->stat_head->rra_cnt;

	/* advance the pointer */
	(rrd->stat_head->rra_cnt)++;
	/* allocate the memory for the 4 contingent RRAs */
	old_size = sizeof(rra_def_t) * (rrd->stat_head->rra_cnt);
	if ((rrd->rra_def = (rra_def_t*)rrd_realloc(rrd->rra_def,
					old_size + 4 * sizeof(rra_def_t))) ==
			NULL) {
		rrd_free2(rrd);
		return (-RRD_ERR_ALLOC);
	}
	/* clear memory */
	memset(&(rrd->rra_def[rrd->stat_head->rra_cnt]), 0,
			4 * sizeof(rra_def_t));

	/* create the CF_SEASONAL RRA */
	current_rra = &(rrd->rra_def[rrd->stat_head->rra_cnt]);
	strcpy(current_rra->cf_nam, "SEASONAL");
	current_rra->row_cnt = period;
	current_rra->par[RRA_seasonal_smooth_idx].u_cnt = hashed_name % period;
	current_rra->pdp_cnt = 1;
	current_rra->par[RRA_seasonal_gamma].u_val =
		rrd->rra_def[hw_index].par[RRA_hw_alpha].u_val;
	current_rra->par[RRA_dependent_rra_idx].u_cnt = hw_index;
	rrd->rra_def[hw_index].par[RRA_dependent_rra_idx].u_cnt =
		rrd->stat_head->rra_cnt;

	/* create the CF_DEVSEASONAL RRA */
	(rrd->stat_head->rra_cnt)++;
	current_rra = &(rrd->rra_def[rrd->stat_head->rra_cnt]);
	strcpy(current_rra->cf_nam, "DEVSEASONAL");
	current_rra->row_cnt = period;
	current_rra->par[RRA_seasonal_smooth_idx].u_cnt = hashed_name % period;
	current_rra->pdp_cnt = 1;
	current_rra->par[RRA_seasonal_gamma].u_val =
		rrd->rra_def[hw_index].par[RRA_hw_alpha].u_val;
	current_rra->par[RRA_dependent_rra_idx].u_cnt = hw_index;

	/* create the CF_DEVPREDICT RRA */
	(rrd->stat_head->rra_cnt)++;
	current_rra = &(rrd->rra_def[rrd->stat_head->rra_cnt]);
	strcpy(current_rra->cf_nam, "DEVPREDICT");
	current_rra->row_cnt = (rrd->rra_def[hw_index]).row_cnt;
	current_rra->pdp_cnt = 1;
	current_rra->par[RRA_dependent_rra_idx].u_cnt = hw_index + 2;   /* DEVSEASONAL */

	/* create the CF_FAILURES RRA */
	(rrd->stat_head->rra_cnt)++;
	current_rra = &(rrd->rra_def[rrd->stat_head->rra_cnt]);
	strcpy(current_rra->cf_nam, "FAILURES");
	current_rra->row_cnt = period;
	current_rra->pdp_cnt = 1;
	current_rra->par[RRA_delta_pos].u_val = 2.0;
	current_rra->par[RRA_delta_neg].u_val = 2.0;
	current_rra->par[RRA_failure_threshold].u_cnt = 7;
	current_rra->par[RRA_window_len].u_cnt = 9;
	current_rra->par[RRA_dependent_rra_idx].u_cnt = hw_index + 2;   /* DEVSEASONAL */
	return 0;
}
예제 #4
0
파일: rrd_create.c 프로젝트: yubo/rrdlite
/* #define DEBUG */
int rrd_create_r( const char *filename, unsigned long pdp_step,
		time_t last_up, int argc, const char **argv) {
	rrd_t     rrd;
	long      i;
	int       offset;
	char     *token;
	char      dummychar1[2], dummychar2[2];
	unsigned short token_idx, error_flag, period = 0;
	unsigned long hashed_name;
	int       ret = 0;

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

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

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

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

	rrd.live_head->last_up = last_up;

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

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

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

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

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

			argvcopy = strdup(argv[i]);
			token = strtok_r(&argvcopy[4], ":", &tokptr);
			token_idx = error_flag = 0;

			while (token != NULL) {
				switch (token_idx) {
					case 0:
						if (sscanf(token, CF_NAM_FMT,
									rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam) !=
								1)
							ret = -RRD_ERR_FAILED_PARSE_CF_NAME;
						cf_id = cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam);
						switch (cf_id) {
							case CF_MHWPREDICT:
								strcpy(rrd.stat_head->version, RRD_VERSION);    /* MHWPREDICT causes Version 4 */
							case CF_HWPREDICT:
								token_min = 5;
								/* initialize some parameters */
								rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_hw_alpha].
									u_val = 0.1;
								rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_hw_beta].
									u_val = 1.0 / 288;
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_dependent_rra_idx].u_cnt =
									rrd.stat_head->rra_cnt;
								break;
							case CF_DEVSEASONAL:
								token_min = 3;
							case CF_SEASONAL:
								if (cf_id == CF_SEASONAL){
									token_min = 4;
								}
								/* initialize some parameters */
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_seasonal_gamma].u_val = 0.1;
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_seasonal_smoothing_window].u_val = 0.05;
								/* fall through */
							case CF_DEVPREDICT:
								if (cf_id == CF_DEVPREDICT){
									token_min = 3;
								}
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_dependent_rra_idx].u_cnt = -1;
								break;
							case CF_FAILURES:
								token_min = 5;
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_delta_pos].u_val = 2.0;
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_delta_neg].u_val = 2.0;
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_window_len].u_cnt = 3;
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_failure_threshold].u_cnt = 2;
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_dependent_rra_idx].u_cnt = -1;
								break;
								/* invalid consolidation function */
							case -1:
								ret = -RRD_ERR_UNREC_CONSOLIDATION_FUNC;
							default:
								break;
						}
						/* default: 1 pdp per cdp */
						rrd.rra_def[rrd.stat_head->rra_cnt].pdp_cnt = 1;
						break;
					case 1:
						switch (cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
							case CF_HWPREDICT:
							case CF_MHWPREDICT:
							case CF_DEVSEASONAL:
							case CF_SEASONAL:
							case CF_DEVPREDICT:
							case CF_FAILURES:
								row_cnt = atoi(token);
								if (row_cnt <= 0)
									ret = -RRD_ERR_INVALID_ROW_COUNT;
								rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt = row_cnt;
								break;
							default:
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_cdp_xff_val].u_val = atof(token);
								if (rrd.rra_def[rrd.stat_head->rra_cnt].
										par[RRA_cdp_xff_val].u_val < 0.0
										|| rrd.rra_def[rrd.stat_head->rra_cnt].
										par[RRA_cdp_xff_val].u_val >= 1.0)
									ret = -RRD_ERR_INVALID_XFF;
								break;
						}
						break;
					case 2:
						switch (cf_conv
								(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
							case CF_HWPREDICT:
							case CF_MHWPREDICT:
								rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_hw_alpha].
									u_val = atof(token);
								if (atof(token) <= 0.0 || atof(token) >= 1.0)
									ret = -RRD_ERR_INVALID_ALPHA;
								break;
							case CF_DEVSEASONAL:
							case CF_SEASONAL:
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_seasonal_gamma].u_val = atof(token);
								if (atof(token) <= 0.0 || atof(token) >= 1.0)
									ret = -RRD_ERR_INVALID_GAMMA;
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_seasonal_smooth_idx].u_cnt =
									hashed_name %
									rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt;
								break;
							case CF_FAILURES:
								/* specifies the # of violations that constitutes the failure threshold */
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_failure_threshold].u_cnt = atoi(token);
								if (atoi(token) < 1
										|| atoi(token) > MAX_FAILURES_WINDOW_LEN)
									ret = -RRD_ERR_FAILURE_THRESHOLD_OUT_OF_RANGE;
								break;
							case CF_DEVPREDICT:
								/* specifies the index (1-based) of CF_DEVSEASONAL array
								 * associated with this CF_DEVPREDICT array. */
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_dependent_rra_idx].u_cnt =
									atoi(token) - 1;
								break;
							default:
								rrd.rra_def[rrd.stat_head->rra_cnt].pdp_cnt =
									atoi(token);
								if (atoi(token) < 1)
									ret = -RRD_ERR_INVALID_STEP;
								break;
						}
						break;
					case 3:
						switch (cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
							case CF_HWPREDICT:
							case CF_MHWPREDICT:
								rrd.rra_def[rrd.stat_head->rra_cnt].par[RRA_hw_beta].
									u_val = atof(token);
								if (atof(token) < 0.0 || atof(token) > 1.0)
									ret = -RRD_ERR_INVALID_BETA;
								break;
							case CF_DEVSEASONAL:
							case CF_SEASONAL:
								/* specifies the index (1-based) of CF_HWPREDICT array
								 * associated with this CF_DEVSEASONAL or CF_SEASONAL array. 
								 * */
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_dependent_rra_idx].u_cnt =
									atoi(token) - 1;
								break;
							case CF_FAILURES:
								/* specifies the window length */
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_window_len].u_cnt = atoi(token);
								if (atoi(token) < 1
										|| atoi(token) > MAX_FAILURES_WINDOW_LEN)
									ret = RRD_ERR_WIN_LEN_OUT_OF_RANGE;
								/* verify that window length exceeds the failure threshold */
								if (rrd.rra_def[rrd.stat_head->rra_cnt].
										par[RRA_window_len].u_cnt <
										rrd.rra_def[rrd.stat_head->rra_cnt].
										par[RRA_failure_threshold].u_cnt)
									ret = -RRD_ERR_WINLEN_SHORTER_FAILURE_THRESHOLD;
								break;
							case CF_DEVPREDICT:
								/* shouldn't be any more arguments */
								ret = -RRD_ERR_INVALID_ARG1;
								break;
							default:
								row_cnt = atoi(token);
								if (row_cnt <= 0)
									ret = -RRD_ERR_INVALID_ROW_COUNT;
#if SIZEOF_TIME_T == 4
								if ((long long) pdp_step * rrd.rra_def[rrd.stat_head->rra_cnt].pdp_cnt * row_cnt > 4294967296LL){
									/* database timespan > 2**32, would overflow time_t */
									ret = -RRD_ERR_TIME_TOO_LARGE;
								}
#endif
								rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt = row_cnt;
								break;
						}
						break;
					case 4:
						switch (cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam)) {
							case CF_FAILURES:
								/* specifies the index (1-based) of CF_DEVSEASONAL array
								 * associated with this CF_DEVFAILURES array. */
								rrd.rra_def[rrd.stat_head->rra_cnt].
									par[RRA_dependent_rra_idx].u_cnt =
									atoi(token) - 1;
								break;
							case CF_DEVSEASONAL:
							case CF_SEASONAL:
								/* optional smoothing window */
								if (sscanf(token, "smoothing-window=%lf",
											&(rrd.rra_def[rrd.stat_head->rra_cnt].
												par[RRA_seasonal_smoothing_window].
												u_val))) {
									strcpy(rrd.stat_head->version, RRD_VERSION);    /* smoothing-window causes Version 4 */
									if (rrd.rra_def[rrd.stat_head->rra_cnt].
											par[RRA_seasonal_smoothing_window].u_val < 0.0
											|| rrd.rra_def[rrd.stat_head->rra_cnt].
											par[RRA_seasonal_smoothing_window].u_val >
											1.0) {
										ret = -RRD_ERR_INVALID_SMOOTHING_WINDOW;
									}
								} else {
									ret = -RRD_ERR_INVALID_OPT;
								}
								break;
							case CF_HWPREDICT:
							case CF_MHWPREDICT:
								/* length of the associated CF_SEASONAL and CF_DEVSEASONAL arrays. */
								period = atoi(token);
								if (period >
										rrd.rra_def[rrd.stat_head->rra_cnt].row_cnt)
									ret = -RRD_ERR_LEN_OF_SEASONAL_CYCLE;
								break;
							default:
								/* shouldn't be any more arguments */
								ret = -RRD_ERR_INVALID_ARG2;
								break;
						}
						break;
					case 5:
						/* If we are here, this must be a CF_HWPREDICT RRA.
						 * Specifies the index (1-based) of CF_SEASONAL array
						 * associated with this CF_HWPREDICT array. If this argument 
						 * is missing, then the CF_SEASONAL, CF_DEVSEASONAL, CF_DEVPREDICT,
						 * CF_FAILURES.
						 * arrays are created automatically. */
						rrd.rra_def[rrd.stat_head->rra_cnt].
							par[RRA_dependent_rra_idx].u_cnt = atoi(token) - 1;
						break;
					default:
						/* should never get here */
						ret = -RRD_ERR_UNKNOWN_ERROR;
						break;
				}       /* end switch */
				if (ret) {
					/* all errors are unrecoverable */
					free(argvcopy);
					rrd_free2(&rrd);
					return ret;
				}
				token = strtok_r(NULL, ":", &tokptr);
				token_idx++;
			}           /* end while */
			free(argvcopy);
			if (token_idx < token_min){
				rrd_free2(&rrd);
				return(-RRD_ERR_ARG3);
			}
#ifdef DEBUG
			fprintf(stderr,
					"Creating RRA CF: %s, dep idx %lu, current idx %lu\n",
					rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam,
					rrd.rra_def[rrd.stat_head->rra_cnt].
					par[RRA_dependent_rra_idx].u_cnt, rrd.stat_head->rra_cnt);
#endif
			/* should we create CF_SEASONAL, CF_DEVSEASONAL, and CF_DEVPREDICT? */
			if ((cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam) ==
						CF_HWPREDICT
						|| cf_conv(rrd.rra_def[rrd.stat_head->rra_cnt].cf_nam) ==
						CF_MHWPREDICT)
					&& rrd.rra_def[rrd.stat_head->rra_cnt].
					par[RRA_dependent_rra_idx].u_cnt == rrd.stat_head->rra_cnt) {
#ifdef DEBUG
				fprintf(stderr, "Creating HW contingent RRAs\n");
#endif
				if (create_hw_contingent_rras(&rrd, period, hashed_name) ==
						-1) {
					rrd_free2(&rrd);
					return (-RRD_ERR_CREATING_RRA);
				}
			}
			rrd.stat_head->rra_cnt++;
		} else {
			rrd_free2(&rrd);
			return (-RRD_ERR_ARG4);
		}
	}


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

	if (rrd.stat_head->ds_cnt < 1) {
		rrd_free2(&rrd);
		return (-RRD_ERR_ARG6);
	}
	return rrd_create_fn(filename, &rrd);
}
예제 #5
0
/* Scan buffer until an unescaped '>' arives.
 * Update argument array with arguments found.
 * Return end cursor where parsing stopped, or NULL in case of failure.
 *
 * FIXME:
 * To allow nested constructs, we call rrd_expand_vars() for arguments
 * that contain RRD::x directives. These introduce a small memory leak
 * since we have to stralloc the arguments the way parse() works.
 */
char*
scanargs(char *line, int *argument_count, char ***arguments)
{
	char 	*getP;		/* read cursor */
	char 	*putP;		/* write cursor */
	char 	Quote;		/* type of quote if in quoted string, 0 otherwise */
	int 	tagcount;	/* open tag count */
	int 	in_arg;		/* if we currently are parsing an argument or not */
	int 	argsz;		/* argument array size */
	int		curarg_contains_rrd_directives;

	/* local array of arguments while parsing */
	int argc = 0;
	char** argv;

#ifdef DEBUG_PARSER
	printf("<-- scanargs(%s) -->\n", line);
#endif

	*arguments = NULL;
	*argument_count = 0;

	/* create initial argument array of char pointers */
	argsz = 32;
	argv = (char **)malloc(argsz * sizeof(char *));
	if (!argv) {
		return NULL;
	}

	/* skip leading blanks */
	while (isspace((int)*line)) {
		line++;
	}

	getP = line;
	putP = line;

	Quote    = 0;
	in_arg   = 0;
	tagcount = 0;

	curarg_contains_rrd_directives = 0;

	/* start parsing 'line' for arguments */
	while (*getP)
	{
		unsigned char c = *getP++;

		if (c == '>' && !Quote && !tagcount) {
			/* this is our closing tag, quit scanning */
			break;
		}

 		/* remove all special chars */
		if (c < ' ') {
			c = ' ';
		}

		switch (c)
		{
		case ' ': 
			if (Quote || tagcount) {
				/* copy quoted/tagged (=RRD expanded) string */
				*putP++ = c;
			}
			else if (in_arg)
			{
				/* end argument string */
				*putP++ = 0;
				in_arg = 0;
				if (curarg_contains_rrd_directives) {
					argv[argc-1] = rrd_expand_vars(stralloc(argv[argc-1]));
					curarg_contains_rrd_directives = 0;
				}
			}
			break;

		case '"': /* Fall through */
		case '\'':
			if (Quote != 0) {
				if (Quote == c) {
			  		Quote = 0;
				} else {
					/* copy quoted string */
					*putP++ = c;
				}
			} else {
				if (!in_arg) {
					/* reference start of argument string in argument array */
					argv[argc++] = putP;
					in_arg=1;
				}
				Quote = c;
			}
			break;

		default:
				if (!in_arg) {
					/* start new argument */
					argv[argc++] = putP;
					in_arg = 1;
				}
				if (c == '>') {
					if (tagcount) {
						tagcount--;
					}
				}
				if (c == '<') {
					tagcount++;
					if (0 == strncmp(getP, "RRD::", strlen("RRD::"))) {
						curarg_contains_rrd_directives = 1;
					}
				}
			*putP++ = c;
			break;
		}

		/* check if our argument array is still large enough */
		if (argc == argsz) {
			/* resize argument array */
			argsz *= 2;
			argv = rrd_realloc(argv, argsz * sizeof(char *));
			if (*argv == NULL) {
				return NULL;
			}
		}
	}

	/* terminate last argument found */
	*putP = '\0';
	if (curarg_contains_rrd_directives) {
		argv[argc-1] = rrd_expand_vars(stralloc(argv[argc-1]));
	}

#ifdef DEBUG_PARSER
	if (argc > 0) {
		int n;
		printf("<-- arguments found [%d]\n", argc);
		for (n=0; n<argc; n++) {
			printf("arg %02d: '%s'\n", n, argv[n]);
		}
		printf("-->\n");
	} else {
		printf("<!-- No arguments found -->\n");
	}
#endif

	/* update caller's notion of the argument array and it's size */
	*arguments = argv;
	*argument_count = argc;

	if (Quote) {
		return NULL;
	}

	/* Return new scanning cursor:
	   pointer to char after closing bracket */
	return getP;
}
예제 #6
0
/*
 * Parse(): scan current portion of buffer for given tag.
 * If found, parse tag arguments and call 'func' for it.
 * The result of func is inserted at the current position
 * in the buffer.
 */
int
parse(
	char **buf, 	/* buffer */
	long i, 		/* offset in buffer */
	char *tag,  	/* tag to handle  */
	char *(*func)(long , const char **) /* function to call for 'tag' */
	)
{
	/* the name of the vairable ... */
	char *val;
	long valln;  
	char **args;
	char *end;
	long end_offset;
	int  argc;
	size_t taglen = strlen(tag);

	/* Current position in buffer should start with 'tag' */
	if (strncmp((*buf)+i, tag, taglen) != 0) {
		return 0;
	}
	/* .. and match exactly (a whitespace following 'tag') */
	if (! isspace(*((*buf) + i + taglen)) ) {
		return 0;
	}

#ifdef DEBUG_PARSER
	printf("parse(): handling tag '%s'\n", tag);
#endif

	/* Scan for arguments following the tag;
	   scanargs() puts \0 into *buf ... so after scanargs it is probably
	   not a good time to use strlen on buf */
	end = scanargs((*buf) + i + taglen, &argc, &args);
	if (end)
	{
		/* got arguments, call function for 'tag' with arguments */
		val = func(argc, (const char **) args);
		free(args);
	}
	else
	{
		/* unable to parse arguments, undo 0-termination by scanargs */
		for (; argc > 0; argc--) {
			*((args[argc-1])-1) = ' ';
		}

		/* next call, try parsing at current offset +1 */
		end = (*buf) + i + 1;

		val = stralloc("[ERROR: Parsing Problem with the following text\n"
			   			" Check original file. This may have been altered "
						"by parsing.]\n\n");
	}

	/* remember offset where we have to continue parsing */
	end_offset = end - (*buf);

	valln = 0;
	if (val) {
		valln = strlen(val);
	}

	/* Optionally resize buffer to hold the replacement value:
	   Calculating the new length of the buffer is simple. add current
	   buffer pos (i) to length of string after replaced tag to length
	   of replacement string and add 1 for the final zero ... */
	if (end - (*buf) < (i + valln)) {
		/* make sure we do not shrink the mallocd block */
		size_t newbufsize = i + strlen(end) + valln + 1;
		*buf = rrd_realloc(*buf, newbufsize);

		if (*buf == NULL) {
			perror("Realoc buf:");
			exit(1);
		};
	}

	/* Update new end pointer:
	   make sure the 'end' pointer gets moved along with the 
	   buf pointer when realloc moves memory ... */
	end = (*buf) + end_offset; 

	/* splice the variable:
	   step 1. Shift pending data to make room for 'val' */
	memmove((*buf) + i + valln, end, strlen(end) + 1);

	/* step 2. Insert val */
	if (val) {
		memmove((*buf)+i, val, valln);
		free(val);
	}
	return (valln > 0 ? valln-1: valln);
}
예제 #7
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);
}
예제 #8
0
파일: rrd_create.c 프로젝트: blair/orca
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);
}
예제 #9
0
파일: rrd_restore.c 프로젝트: OPSF/uClinux
/* 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;
}