int main(int argc, char **argv) { if (parse_options(argc, argv) != 0) { fprintf(stderr, "USAGE: %s -t start:end <cf> <metric:name:with:ds>\n", argv[0]); exit(1); } if (OPTIONS.DEBUG) { fprintf(stderr, " cf min = %p\n", cf_min); fprintf(stderr, " cf max = %p\n", cf_max); fprintf(stderr, " cf sum = %p\n", cf_sum); fprintf(stderr, " cf mean = %p\n", cf_mean); fprintf(stderr, " cf median = %p\n", cf_median); fprintf(stderr, " cf stddev = %p\n", cf_stddev); fprintf(stderr, " cf variance = %p\n", cf_variance); fprintf(stderr, " cf nth = %p\n", cf_nth); fprintf(stderr, "-------------------------\n\n\n"); fprintf(stderr, "metric = %s\n", OPTIONS.metric); fprintf(stderr, " ds = %s\n", OPTIONS.ds); fprintf(stderr, " file = %s\n", OPTIONS.rrdfile); fprintf(stderr, " root = %s\n", OPTIONS.root); fprintf(stderr, " hash = %s\n", OPTIONS.hash); fprintf(stderr, " start = %lu\n", OPTIONS.start); fprintf(stderr, " end = %lu\n", OPTIONS.end); fprintf(stderr, " cf = %p\n", OPTIONS.cf); if (OPTIONS.cf == cf_nth) fprintf(stderr, " p = %f\n", OPTIONS.cf_arg.percentile); if (OPTIONS.cf_arg.skip_unknown) fprintf(stderr, " U = ignore/skip\n"); else fprintf(stderr, " U = %f\n", OPTIONS.cf_arg.unknown); fprintf(stderr, "\n\n"); } char **ds_names; unsigned long ds_count; unsigned long step = 1; rrd_value_t *raw; int rc; rc = rrd_fetch_r(OPTIONS.rrdfile, "AVERAGE", &OPTIONS.start, &OPTIONS.end, &step, &ds_count, &ds_names, &raw); if (rc != 0) { fprintf(stderr, "fetch failed!\n"); if (rrd_test_error()) { fprintf(stderr, "rrd said: %s\n", rrd_get_error()); } exit(2); } int ds; for (ds = 0; ds < ds_count; ds++) if (strcmp(OPTIONS.ds, ds_names[ds]) == 0) break; if (ds >= ds_count) { fprintf(stderr, "DS '%s' not found in RRD file\n", OPTIONS.ds); exit(2); } size_t n = (OPTIONS.end - OPTIONS.start) / step; double *set = calloc(n, sizeof(double)); rrd_value_t *d = raw + ds; int i, j; for (i = 0, j = 0; i < n; i++) { double v = (double)*d; if (isnan(v)) { if (OPTIONS.cf_arg.skip_unknown) { if (OPTIONS.DEBUG) fprintf(stderr, "skipping sample #%i (--unknown=ignore)\n", i+1); continue; } if (OPTIONS.DEBUG) fprintf(stderr, "sample #%i is UNKNOWN (substituting %e)\n", i+1, OPTIONS.cf_arg.unknown); v = OPTIONS.cf_arg.unknown; } set[j] = v; if (OPTIONS.DEBUG) fprintf(stderr, "[%i] %e (%lf)\n", j+1, set[j], set[j]); d += ds_count; j++; } printf("%e\n", (*OPTIONS.cf)(j, set, &OPTIONS.cf_arg)); return 0; }
int rrd_fetch( int argc, char **argv, time_t *start, time_t *end, /* which time frame do you want ? * will be changed to represent reality */ unsigned long *step, /* which stepsize do you want? * will be changed to represent reality */ unsigned long *ds_cnt, /* number of data sources in file */ char ***ds_namv, /* names of data sources */ rrd_value_t **data) { /* two dimensional array containing the data */ unsigned long step_tmp = 1; time_t start_tmp = 0, end_tmp = 0; const char *cf; char *opt_daemon = NULL; int align_start = 0; int status; rrd_time_value_t start_tv, end_tv; const char *parsetime_error = NULL; struct option long_options[] = { {"resolution", required_argument, 0, 'r'}, {"start", required_argument, 0, 's'}, {"end", required_argument, 0, 'e'}, {"align-start", optional_argument, 0, 'a'}, {"daemon", required_argument, 0, 'd'}, {0, 0, 0, 0} }; optind = 0; opterr = 0; /* initialize getopt */ /* init start and end time */ rrd_parsetime("end-24h", &start_tv); rrd_parsetime("now", &end_tv); while (1) { int option_index = 0; int opt; opt = getopt_long(argc, argv, "ar:s:e:d:", long_options, &option_index); if (opt == EOF) break; switch (opt) { case 's': if ((parsetime_error = rrd_parsetime(optarg, &start_tv))) { rrd_set_error("start time: %s", parsetime_error); return -1; } break; case 'e': if ((parsetime_error = rrd_parsetime(optarg, &end_tv))) { rrd_set_error("end time: %s", parsetime_error); return -1; } break; case 'a': align_start = 1; break; case 'r': if ((parsetime_error = rrd_scaled_duration(optarg, 1, &step_tmp))) { rrd_set_error("resolution: %s", parsetime_error); return -1; } break; 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; case '?': rrd_set_error("unknown option '-%c'", optopt); return (-1); } } if (rrd_proc_start_end(&start_tv, &end_tv, &start_tmp, &end_tmp) == -1) { return -1; } if (start_tmp < 3600 * 24 * 365 * 10) { rrd_set_error("the first entry to fetch should be after 1980"); return (-1); } if (align_start) { time_t delta = (start_tmp % step_tmp); start_tmp -= delta; end_tmp -= delta; } if (end_tmp < start_tmp) { rrd_set_error("start (%ld) should be less than end (%ld)", start_tmp, end_tmp); return (-1); } *start = start_tmp; *end = end_tmp; *step = step_tmp; if (optind + 1 >= argc) { rrd_set_error("Usage: rrdtool %s <file> <CF> [options]", argv[0]); return -1; } cf = argv[optind + 1]; rrdc_connect (opt_daemon); if (rrdc_is_connected (opt_daemon)) status = rrdc_fetch (argv[optind], cf, start, end, step, ds_cnt, ds_namv, data); else status = rrd_fetch_r(argv[optind], cf, start, end, step, ds_cnt, ds_namv, data); if (status != 0) return (-1); return (0); }
static uint64_t _rrd_consolidate_one(time_t t0, time_t t1, char* filename, char* rra_name, bool flag_approximate) { int status, rra_nb = -1; unsigned long step = 1, ds_count, ii; char cf[] = "AVERAGE"; char **ds_names; time_t ti, start = t0-1, end = t1+1; uint32_t nb_miss = 0, nb_values = 0; rrd_value_t *rrd_data, *rrd_data_p; rrd_value_t current_watt = (rrd_value_t)NO_VAL; rrd_value_t temp_energy = 0, consumed_energy = 0; last_valid_time = 0; last_valid_watt = (rrd_value_t)NO_VAL; status = rrd_fetch_r(filename, cf, &start, &end, &step, &ds_count, &ds_names, &rrd_data); if (status != 0){ if (debug_flags & DEBUG_FLAG_EXT_SENSORS) info("ext_sensors: error rrd_fetch %s",filename); return NO_VAL; } rrd_data_p = rrd_data; do { if (start == end) { consumed_energy = (rrd_value_t)NO_VAL; break; } if (ds_count == 0) { if (debug_flags & DEBUG_FLAG_EXT_SENSORS) info("ext_sensors: error ds_count==0 in RRD %s", filename); consumed_energy = (rrd_value_t)NO_VAL; break; } else if (ds_count == 1 || rra_name == NULL) rra_nb = 0; else { for (ii = 0; ii < ds_count; ii++){ if (!strcmp(ds_names[ii],rra_name)) { rra_nb = ii; break; } } if (rra_nb == -1) { if (debug_flags & DEBUG_FLAG_EXT_SENSORS) info("ext_sensors: error RRA %s not " "found in RRD %s", rra_name, filename); consumed_energy = (rrd_value_t)NO_VAL; break; } } ti = start; do { for (ii = 0; ii < rra_nb; ii++) rrd_data_p++; last_valid_watt = _validate_watt(rrd_data_p); if (last_valid_watt != (rrd_value_t)NO_VAL) last_valid_time = ti; for (ii = rra_nb; ii < ds_count; ii++) rrd_data_p++; ti += step; } while (ti < t0 && ti < end); if (ti != t0 && ti < end) { for (ii = 0; ii < rra_nb; ii++) rrd_data_p++; current_watt = _validate_watt(rrd_data_p); if (current_watt != (rrd_value_t)NO_VAL) { temp_energy = _get_additional_consumption( t0, ti < t1 ? ti : t1, current_watt, current_watt); last_valid_watt = current_watt; last_valid_time = ti; consumed_energy += temp_energy; nb_values += 1; } else { nb_miss += 10001; } for (ii = rra_nb; ii < ds_count; ii++) rrd_data_p++; } else if ((ti == t0) && (ti < end)) { for (ii = 0; ii < rra_nb; ii++) rrd_data_p++; current_watt = _validate_watt(rrd_data_p); if (current_watt != (rrd_value_t)NO_VAL) { last_valid_watt = current_watt; last_valid_time = ti; } for (ii = rra_nb; ii < ds_count; ii++) rrd_data_p++; ti += step; } while (((ti += step) <= t1) && (ti < end)) { for (ii = 0; ii < rra_nb; ii++) rrd_data_p++; current_watt = _validate_watt(rrd_data_p); if (current_watt != (rrd_value_t)NO_VAL && last_valid_watt != (rrd_value_t)NO_VAL) { temp_energy = _get_additional_consumption( ti-step, ti, last_valid_watt, current_watt); last_valid_watt = current_watt; last_valid_time = ti; consumed_energy += temp_energy; nb_values += 1; } else { nb_miss += 1; } for (ii = rra_nb; ii < ds_count; ii++) rrd_data_p++; } if ((ti > t1) && (t1 > (t0 + step)) && (ti-step < t1)) { if (current_watt != (rrd_value_t)NO_VAL) { temp_energy = _get_additional_consumption( ti-step, t1, current_watt, current_watt); consumed_energy += temp_energy; nb_values += 1; } else { nb_miss += 1; } } } while(0); if (nb_miss >= 10000) { if (debug_flags & DEBUG_FLAG_EXT_SENSORS) info("ext_sensors: RRD: no first value"); nb_miss -= 10000; } if (debug_flags & DEBUG_FLAG_EXT_SENSORS) info("ext_sensors: RRD: have %d values and miss %d values", nb_values, nb_miss); if (flag_approximate && current_watt == (rrd_value_t)NO_VAL && last_valid_watt != (rrd_value_t)NO_VAL) { temp_energy = _get_additional_consumption( last_valid_time, t1, last_valid_watt, last_valid_watt); consumed_energy += temp_energy; } for (ii = 0; ii < ds_count; ii++) free(ds_names[ii]); free(ds_names); free(rrd_data); return (uint64_t)consumed_energy; }
int rrd_fetch( int argc, char **argv, time_t *start, time_t *end, /* which time frame do you want ? * will be changed to represent reality */ unsigned long *step, /* which stepsize do you want? * will be changed to represent reality */ unsigned long *ds_cnt, /* number of data sources in file */ char ***ds_namv, /* names of data sources */ rrd_value_t **data) { /* two dimensional array containing the data */ long step_tmp = 1; time_t start_tmp = 0, end_tmp = 0; const char *cf; rrd_time_value_t start_tv, end_tv; char *parsetime_error = NULL; struct option long_options[] = { {"resolution", required_argument, 0, 'r'}, {"start", required_argument, 0, 's'}, {"end", required_argument, 0, 'e'}, {0, 0, 0, 0} }; optind = 0; opterr = 0; /* initialize getopt */ /* init start and end time */ rrd_parsetime("end-24h", &start_tv); rrd_parsetime("now", &end_tv); while (1) { int option_index = 0; int opt; opt = getopt_long(argc, argv, "r:s:e:", long_options, &option_index); if (opt == EOF) break; switch (opt) { case 's': if ((parsetime_error = rrd_parsetime(optarg, &start_tv))) { rrd_set_error("start time: %s", parsetime_error); return -1; } break; case 'e': if ((parsetime_error = rrd_parsetime(optarg, &end_tv))) { rrd_set_error("end time: %s", parsetime_error); return -1; } break; case 'r': step_tmp = atol(optarg); break; case '?': rrd_set_error("unknown option '-%c'", optopt); return (-1); } } if (rrd_proc_start_end(&start_tv, &end_tv, &start_tmp, &end_tmp) == -1) { return -1; } if (start_tmp < 3600 * 24 * 365 * 10) { rrd_set_error("the first entry to fetch should be after 1980"); return (-1); } if (end_tmp < start_tmp) { rrd_set_error("start (%ld) should be less than end (%ld)", start_tmp, end_tmp); return (-1); } *start = start_tmp; *end = end_tmp; if (step_tmp < 1) { rrd_set_error("step must be >= 1 second"); return -1; } *step = step_tmp; if (optind + 1 >= argc) { rrd_set_error("not enough arguments"); return -1; } cf = argv[optind + 1]; if (rrd_fetch_r(argv[optind], cf, start, end, step, ds_cnt, ds_namv, data) != 0) return (-1); return (0); }
static sdb_timeseries_t * sdb_rrd_fetch(const char *id, sdb_timeseries_opts_t *opts, sdb_object_t *user_data) { sdb_timeseries_t *ts; time_t start = (time_t)SDB_TIME_TO_SECS(opts->start); time_t end = (time_t)SDB_TIME_TO_SECS(opts->end); unsigned long step = 0; unsigned long ds_cnt = 0; unsigned long val_cnt = 0; char **ds_namv = NULL; rrd_value_t *data = NULL; if (user_data) { /* -> use RRDCacheD */ char *addr = SDB_OBJ_WRAPPER(user_data)->data; if (! rrdcached_connect(addr)) return NULL; #ifdef HAVE_RRD_CLIENT_H if (rrdc_flush(id)) { sdb_log(SDB_LOG_ERR, "Failed to flush '%s' through RRDCacheD: %s", id, rrd_get_error()); return NULL; } #endif } #define FREE_RRD_DATA() \ do { \ size_t i; \ for (i = 0; i < ds_cnt; ++i) \ rrd_freemem(ds_namv[i]); \ rrd_freemem(ds_namv); \ rrd_freemem(data); \ } while (0) /* limit to about 1000 data-points for now * TODO: make this configurable */ step = (end - start) / 1000; if (rrd_fetch_r(id, "AVERAGE", &start, &end, &step, &ds_cnt, &ds_namv, &data)) { char errbuf[1024]; sdb_strerror(errno, errbuf, sizeof(errbuf)); sdb_log(SDB_LOG_ERR, "Failed to fetch data from %s: %s", id, errbuf); return NULL; } val_cnt = (unsigned long)(end - start) / step; /* RRDtool does not support fetching specific data-sources, so we'll have * to filter the requested ones after fetching them all */ if (opts->data_names && opts->data_names_len) ts = sdb_timeseries_create(opts->data_names_len, (const char * const *)opts->data_names, val_cnt); else ts = sdb_timeseries_create(ds_cnt, (const char * const *)ds_namv, val_cnt); if (! ts) { char errbuf[1024]; sdb_strerror(errno, errbuf, sizeof(errbuf)); sdb_log(SDB_LOG_ERR, "Failed to allocate time-series object: %s", errbuf); FREE_RRD_DATA(); return NULL; } ts->start = SECS_TO_SDB_TIME(start + (time_t)step); ts->end = SECS_TO_SDB_TIME(end); if (copy_data(ts, data, (time_t)step, (size_t)ds_cnt, ds_namv) < 0) { FREE_RRD_DATA(); sdb_timeseries_destroy(ts); return NULL; } FREE_RRD_DATA(); return ts; } /* sdb_rrd_fetch */
/*then returns an R data.frame that contain the RRA values fitting between timestamps startIn (non incl) and sendIn*/ SEXP importRRD(SEXP filenameIn, SEXP cfIn, SEXP startIn, SEXP endIn, SEXP stepIn) { rrd_value_t *data; const char *filename; const char *cf; char** ds_namv; time_t start; time_t end; unsigned long step; unsigned long ds_cnt; int status; int size; int ds; int i; int timeStamp; SEXP out; SEXP vec; SEXP nam; SEXP rowNam; SEXP cls; filename = CHAR(asChar(filenameIn)); if (access(filename, F_OK) == -1) { printf("file does not exist\n"); exit(0); } cf = CHAR(asChar(cfIn)); start = (time_t) asInteger(startIn); end = (time_t) asInteger(endIn); step = (unsigned long) asInteger(stepIn); printf("calling rrdfetch\n"); status = rrd_fetch_r(filename, cf, &start, &end, &step, &ds_cnt, &ds_namv, &data); if (status != 0 || data == NULL) { printf("error running rrd_fetch_r\n"); if (data) free(data); if (ds_namv) { for (int k = 0; k < sizeof(ds_namv)/sizeof(char*); k++) { free(ds_namv[k]); } free(ds_namv); } exit(0); } printf("size of data %d start %d end %d step %d ds_cnt %d\n", sizeof(data)/sizeof(rrd_value_t), start, end, step, ds_cnt); //turns out rrd_fetch does not include start in data size = (end - start)/step - 1; out = PROTECT(allocVector(VECSXP, ds_cnt + 1) ); vec = PROTECT(allocVector(INTSXP, size)); PROTECT(rowNam = allocVector(STRSXP, size)); //turns out rrd_fetch does not include start in data timeStamp = start + step; for (i = 0; i < size; i++) { INTEGER(vec)[i] = timeStamp; timeStamp += step; } SET_VECTOR_ELT(out, 0, vec); setAttrib(out, R_RowNamesSymbol, vec); PROTECT(nam = allocVector(STRSXP, ds_cnt + 1)); SET_STRING_ELT(nam, 0, mkChar("timestamp")); for (ds = 0; ds < ds_cnt; ds++){ SET_STRING_ELT(nam, ds + 1, mkChar(ds_namv[ds])); vec = PROTECT(allocVector(REALSXP, size)); for (i = 0; i < size; i++){ /*printf("iterating.. i = %d\n", i);*/ REAL(vec)[i] = data[ds + i*ds_cnt]; } SET_VECTOR_ELT(out, ds + 1, vec); } PROTECT(cls = allocVector(STRSXP, 1)); // class attribute SET_STRING_ELT(cls, 0, mkChar("data.frame")); classgets(out, cls); namesgets(out, nam); free(data); for (int k = 0; k < sizeof(ds_namv)/sizeof(char*); k++) { free(ds_namv[k]); } free(ds_namv); UNPROTECT(ds_cnt + 4); return out; }
SEXP smartImportRRD(SEXP filenameIn){ time_t first; time_t last; time_t start; time_t end; time_t *startAr; unsigned long curStep; unsigned long ds_cnt; unsigned long step; int rraCnt; int status; int size; int i; int ds; int j; int timeStamp; char **ds_namv; const char *filename; rrd_value_t *data; rraInfo* rraInfoList; rraInfo* rraInfoTmp; rrd_info_t *rrdInfo; SEXP out; SEXP vec; SEXP rraSexpList; SEXP rraNames; SEXP nam; SEXP rowNam; SEXP cls; filename = CHAR(asChar(filenameIn)); if (access(filename, F_OK) == -1) { printf("file does not exist\n"); exit(0); } printf("calling rrd_last\n"); last = rrd_last_r(filename); printf("calling rrd_info\n"); rrdInfo = rrd_info_r(filename); if (rrdInfo == NULL) { printf("getting rrd info failed"); exit(0); } printf("calling getrrainfo\n"); rraInfoList = getRraInfo(rrdInfo, &rraCnt, &step); if (rraInfoList == NULL) { printf("getting rra info failed\n"); free(rrdInfo); exit(0); } printf("rraCnt %d step %d last %d rraInfoList %p\n", rraCnt, step, last, rraInfoList); printRraInfo(rraInfoList); startAr = malloc(rraCnt * sizeof(time_t)); if (startAr == NULL) { printf("memory allocation error"); free(rrdInfo); freeRraInfo(rraInfoList); exit(0); } for (i = 0; i < rraCnt; i++) { startAr[i] = rrd_first_r(filename, i); } rraInfoTmp = rraInfoList; PROTECT(rraNames = allocVector(STRSXP, rraCnt)); PROTECT(cls = allocVector(STRSXP, 1)); // class attribute SET_STRING_ELT(cls, 0, mkChar("data.frame")); out = PROTECT(allocVector(VECSXP, rraCnt)); i = 0; printf("entering loop\n"); while (rraInfoTmp) { start = startAr[i]; end = last; curStep = step * rraInfoTmp->perRow; status = rrd_fetch_r(filename, rraInfoTmp->cf, &start, &end, &curStep, &ds_cnt, &ds_namv, &data); if (status != 0 || data == NULL) { printf("error running rrd_fetch_r\n"); free(rrdInfo); freeRraInfo(rraInfoList); free(startAr); if (data) free(data); if (ds_namv) { for (int k = 0; k < sizeof(ds_namv)/sizeof(char*); k++) { free(ds_namv[k]); } free(ds_namv); } //TODO unprotect how many times? exit(0); } printf("size of data %d start %d end %d step %d ds_cnt %d\n", sizeof(data)/sizeof(rrd_value_t), start, end, curStep, ds_cnt); fflush(stdout); //rrd_fetch does not include start size = (end - start)/curStep - 1; printf("size %d\n", size); rraSexpList = PROTECT(allocVector(VECSXP, ds_cnt + 1)); vec = PROTECT(allocVector(INTSXP, size)); PROTECT(rowNam = allocVector(STRSXP, size)); //rrd_fetch does not include start timeStamp = start + curStep; for (int j = 0; j < size; j++) { INTEGER(vec)[j] = timeStamp; timeStamp += curStep; } printf("setting row names\n"); SET_VECTOR_ELT(rraSexpList, 0, vec); setAttrib(rraSexpList, R_RowNamesSymbol, vec); PROTECT(nam = allocVector(STRSXP, ds_cnt + 1)); SET_STRING_ELT(nam, 0, mkChar("timestamp")); //TODO stick to row/columns convention for (ds = 0; ds < ds_cnt; ds++){ SET_STRING_ELT(nam, ds + 1, mkChar(ds_namv[ds])); vec = PROTECT(allocVector(REALSXP, size)); for (j = 0; j < size; j++){ REAL(vec)[j] = data[ds + j*ds_cnt]; } printf("adding ds vector to data frame\n"); SET_VECTOR_ELT(rraSexpList, ds + 1, vec); } classgets(rraSexpList, cls); namesgets(rraSexpList, nam); printf("adding data frame to out\n"); SET_VECTOR_ELT(out, i, rraSexpList); char rraNameString[80]; char stepString[40]; sprintf(stepString, "%d", curStep); strcpy(rraNameString, rraInfoTmp->cf); strcat(rraNameString, stepString); SET_STRING_ELT(rraNames, i, mkChar(rraNameString)); rraInfoTmp = rraInfoTmp->next; i++; free(data); } setAttrib(out, R_NamesSymbol, rraNames); freeRraInfo(rraInfoList); free(startAr); free(rrdInfo); for (int k = 0; k < sizeof(ds_namv)/sizeof(char*); k++) { free(ds_namv[k]); } free(ds_namv); UNPROTECT((ds_cnt + 2)*rraCnt + 3); return out; }
int rrd_fetch( int argc, char **argv, time_t *start, time_t *end, /* which time frame do you want ? * will be changed to represent reality */ unsigned long *step, /* which stepsize do you want? * will be changed to represent reality */ unsigned long *ds_cnt, /* number of data sources in file */ char ***ds_namv, /* names of data sources */ rrd_value_t **data) { /* two dimensional array containing the data */ unsigned long step_tmp = 1; time_t start_tmp = 0, end_tmp = 0; const char *cf; char *opt_daemon = NULL; int align_start = 0; int status; rrd_time_value_t start_tv, end_tv; const char *parsetime_error = NULL; struct optparse_long longopts[] = { {"resolution", 'r', OPTPARSE_REQUIRED}, {"start", 's', OPTPARSE_REQUIRED}, {"end", 'e', OPTPARSE_REQUIRED}, {"align-start", 'a', OPTPARSE_NONE}, {"daemon", 'd', OPTPARSE_REQUIRED}, {0}, }; struct optparse options; int opt; /* init start and end time */ rrd_parsetime("end-24h", &start_tv); rrd_parsetime("now", &end_tv); optparse_init(&options, argc, argv); while ((opt = optparse_long(&options, longopts, NULL)) != -1) { switch (opt) { case 's': if ((parsetime_error = rrd_parsetime(options.optarg, &start_tv))) { rrd_set_error("start time: %s", parsetime_error); return -1; } break; case 'e': if ((parsetime_error = rrd_parsetime(options.optarg, &end_tv))) { rrd_set_error("end time: %s", parsetime_error); return -1; } break; case 'a': align_start = 1; break; case 'r': if ((parsetime_error = rrd_scaled_duration(options.optarg, 1, &step_tmp))) { rrd_set_error("resolution: %s", parsetime_error); return -1; } break; case 'd': if (opt_daemon != NULL) free (opt_daemon); opt_daemon = strdup(options.optarg); if (opt_daemon == NULL) { rrd_set_error ("strdup failed."); return -1; } break; case '?': rrd_set_error("%s", options.errmsg); return -1; } } if (rrd_proc_start_end(&start_tv, &end_tv, &start_tmp, &end_tmp) == -1) { return -1; } if (start_tmp < 3600 * 24 * 365 * 10) { rrd_set_error("the first entry to fetch should be after 1980"); return (-1); } if (align_start) { time_t delta = (start_tmp % step_tmp); start_tmp -= delta; end_tmp -= delta; } if (end_tmp < start_tmp) { rrd_set_error("start (%ld) should be less than end (%ld)", start_tmp, end_tmp); return (-1); } *start = start_tmp; *end = end_tmp; *step = step_tmp; if (options.optind + 1 >= options.argc) { rrd_set_error("Usage: rrdtool %s <file> <CF> [options]", options.argv[0]); return -1; } cf = options.argv[options.optind + 1]; rrdc_connect (opt_daemon); if (rrdc_is_connected (opt_daemon)) status = rrdc_fetch (options.argv[options.optind], cf, start, end, step, ds_cnt, ds_namv, data); else status = rrd_fetch_r(options.argv[options.optind], cf, start, end, step, ds_cnt, ds_namv, data); if (status != 0) return (-1); return (0); }