/* convenience function; if there is a daemon specified, or if we can * detect one from the environment, then flush the file. Otherwise, no-op */ int rrdc_flush_if_daemon (const char *opt_daemon, const char *filename) /* {{{ */ { int status = 0; rrdc_connect(opt_daemon); if (rrdc_is_connected(opt_daemon)) { rrd_clear_error(); status = rrdc_flush (filename); if (status != 0 && !rrd_test_error()) { if (status > 0) { rrd_set_error("rrdc_flush (%s) failed: %s", filename, rrd_strerror(status)); } else if (status < 0) { rrd_set_error("rrdc_flush (%s) failed with status %i.", filename, status); } } } /* if (rrdc_is_connected(..)) */ return status; } /* }}} int rrdc_flush_if_daemon */
rrd_info_t *rrd_info( int argc, char **argv) { struct optparse_long longopts[] = { {"daemon", 'd', OPTPARSE_REQUIRED}, {"noflush", 'F', OPTPARSE_NONE}, {0}, }; struct optparse options; int opt; rrd_info_t *info; char *opt_daemon = NULL; int status; int flushfirst = 1; optparse_init(&options, argc, argv); while ((opt = optparse_long(&options, longopts, NULL)) != -1) { switch (opt) { case 'd': if (opt_daemon != NULL) free (opt_daemon); opt_daemon = strdup(options.optarg); if (opt_daemon == NULL) { rrd_set_error ("strdup failed."); return NULL; } break; case 'F': flushfirst = 0; break; case '?': rrd_set_error("%s", options.errmsg); return NULL; } } /* while (opt != -1) */ if (options.argc - options.optind != 1) { rrd_set_error ("Usage: rrdtool %s [--daemon |-d <addr> [--noflush|-F]] <file>", options.argv[0]); return NULL; } if (flushfirst) { status = rrdc_flush_if_daemon(opt_daemon, options.argv[options.optind]); if (status) return (NULL); } rrdc_connect (opt_daemon); if (rrdc_is_connected (opt_daemon)) info = rrdc_info(options.argv[options.optind]); else info = rrd_info_r(options.argv[options.optind]); if (opt_daemon) free(opt_daemon); return (info); } /* rrd_info_t *rrd_info */
time_t rrd_last( int argc, char **argv) { char *opt_daemon = NULL; time_t lastupdate; optind = 0; opterr = 0; /* initialize getopt */ while (42) { int opt; int option_index = 0; static struct option long_options[] = { {"daemon", required_argument, 0, 'd'}, {0, 0, 0, 0} }; opt = getopt_long(argc, argv, "d:", 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: rrd_set_error ("Usage: rrdtool %s [--daemon <addr>] <file>", argv[0]); return (-1); break; } } /* while (42) */ if ((argc - optind) != 1) { rrd_set_error ("Usage: rrdtool %s [--daemon <addr>] <file>", argv[0]); return (-1); } rrdc_connect (opt_daemon); if (rrdc_is_connected (opt_daemon)) lastupdate = rrdc_last (argv[optind]); else lastupdate = rrd_last_r(argv[optind]); if (opt_daemon) free(opt_daemon); return (lastupdate); }
time_t rrd_first( int argc, char **argv) { struct optparse_long longopts[] = { {"rraindex", 129, OPTPARSE_REQUIRED}, {"daemon", 'd', OPTPARSE_REQUIRED}, {0}, }; struct optparse options; int opt; int target_rraindex = 0; char *endptr; char *opt_daemon = NULL; optparse_init(&options, argc, argv); while ((opt = optparse_long(&options, longopts, NULL)) != -1) { switch (opt) { case 129: target_rraindex = strtol(options.optarg, &endptr, 0); if (target_rraindex < 0) { rrd_set_error("invalid rraindex number"); 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 (options.optind >= options.argc) { rrd_set_error("usage rrdtool %s [--rraindex number] [--daemon|-d <addr>] file.rrd", options.argv[0]); return -1; } rrdc_connect (opt_daemon); if (rrdc_is_connected (opt_daemon)) { return rrdc_first(options.argv[options.optind], target_rraindex); } else { return rrd_first_r(options.argv[options.optind], target_rraindex); } }
static bool rrdcached_connect(char *addr) { #ifdef HAVE_RRD_CLIENT_H rrd_clear_error(); if (! rrdc_is_connected(addr)) { if (rrdc_connect(addr)) { sdb_log(SDB_LOG_ERR, "Failed to connectd to RRDCacheD at %s: %s", addr, rrd_get_error()); return 0; } } #else sdb_log(SDB_LOG_ERR, "Callback called with RRDCacheD address " "but your build of SysDB does not support that"); return 0; #endif return 1; } /* rrdcached_connect */
static int try_reconnect (void) { int status; rrdc_disconnect (); rrd_clear_error (); status = rrdc_connect (daemon_address); if (status != 0) { ERROR ("rrdcached plugin: Failed to reconnect to RRDCacheD " "at %s: %s (status=%d)", daemon_address, rrd_get_error (), status); return (-1); } INFO ("rrdcached plugin: Successfully reconnected to RRDCacheD " "at %s", daemon_address); return (0); } /* int try_reconnect */
int rrd_xport( int argc, char **argv, int UNUSED(*xsize), 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 *col_cnt, /* number of data columns in the result */ char ***legend_v, /* legend entries */ rrd_value_t **data) { /* two dimensional array containing the data */ image_desc_t im; time_t start_tmp = 0, end_tmp = 0; rrd_time_value_t start_tv, end_tv; char *parsetime_error = NULL; struct optparse options; optparse_init(&options, argc, argv); struct optparse_long longopts[] = { {"start", 's', OPTPARSE_REQUIRED}, {"end", 'e', OPTPARSE_REQUIRED}, {"maxrows",'m', OPTPARSE_REQUIRED}, {"step", 261, OPTPARSE_REQUIRED}, {"enumds", 262, OPTPARSE_NONE}, {"json", 263, OPTPARSE_NONE}, {"showtime", 't', OPTPARSE_NONE}, {"daemon", 'd', OPTPARSE_REQUIRED}, {0} }; rrd_graph_init(&im); rrd_parsetime("end-24h", &start_tv); rrd_parsetime("now", &end_tv); int enumds=0; int json=0; int showtime=0; int opt; while ((opt = optparse_long(&options,longopts,NULL)) != -1){ switch (opt) { case 261: im.step = atoi(options.optarg); break; case 262: enumds=1; break; case 263: json=1; break; case 't': showtime=1; break; 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 'm': im.xsize = atol(options.optarg); if (im.xsize < 10) { rrd_set_error("maxrows below 10 rows"); return -1; } break; case 'd': { if (im.daemon_addr != NULL) { rrd_set_error ("You cannot specify --daemon " "more than once."); return (-1); } im.daemon_addr = strdup(options.optarg); if (im.daemon_addr == NULL) { rrd_set_error("strdup error"); 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 (%ld)", start_tmp); return -1; } if (end_tmp < start_tmp) { rrd_set_error("start (%ld) should be less than end (%ld)", start_tmp, end_tmp); return -1; } im.start = start_tmp; im.end = end_tmp; im.step = max((long) im.step, (im.end - im.start) / im.xsize); rrd_graph_script(options.argc, options.argv, &im, options.optind); if (rrd_test_error()) { im_free(&im); return -1; } if (im.gdes_c == 0) { rrd_set_error("can't make an xport without contents"); im_free(&im); return (-1); } { /* try to connect to rrdcached */ int status = rrdc_connect(im.daemon_addr); if (status != 0) return status; } if (rrd_xport_fn(&im, start, end, step, col_cnt, legend_v, data,0) == -1) { im_free(&im); return -1; } /* and create the export */ if (!xsize) { int flags=0; if (json) { flags|=1; } if (showtime) { flags|=2; } if (enumds) { flags|=4; } stringbuffer_t buffer={0,0,NULL,stdout}; rrd_xport_format_xmljson(flags,&buffer,&im, *start, *end, *step, *col_cnt, *legend_v, *data); } im_free(&im); return 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; }
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); }
int rrd_flushcached (int argc, char **argv) { struct optparse_long longopts[] = { {"daemon", 'd', OPTPARSE_REQUIRED}, {0}, }; struct optparse options; int opt; char *opt_daemon = NULL; int status; int i; optparse_init(&options, argc, argv); while ((opt = optparse_long(&options, longopts, NULL)) != -1) { switch (opt) { 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; } } /* while (opt!=-1) */ if ((options.argc - options.optind) < 1) { rrd_set_error("Usage: rrdtool %s [--daemon|-d <addr>] <file> [<file> ...]", options.argv[0]); return -1; } /* try to connect to rrdcached */ status = rrdc_connect(opt_daemon); if (status != 0) goto out; if (! rrdc_is_connected(opt_daemon)) { rrd_set_error ("Daemon address \"%s\" unknown. Please use the \"--daemon\" " "option to set an address on the command line or set the " "\"%s\" environment variable.", opt_daemon, ENV_RRDCACHED_ADDRESS); status = -1; goto out; } status = 0; for (i = options.optind; i < options.argc; i++) { status = rrdc_flush(options.argv[i]); if (status) { char *error; int remaining; error = strdup(rrd_get_error()); remaining = options.argc - options.optind - 1; rrd_set_error("Flushing of file \"%s\" failed: %s. Skipping " "remaining %i file%s.", options.argv[i], ((! error) || (*error == '\0')) ? "unknown error" : error, remaining, (remaining == 1) ? "" : "s"); free(error); break; } } out: if (opt_daemon) free(opt_daemon); return status; } /* int rrd_flush */
int rrd_xport( int argc, char **argv, int UNUSED(*xsize), 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 *col_cnt, /* number of data columns in the result */ char ***legend_v, /* legend entries */ rrd_value_t **data) { /* two dimensional array containing the data */ image_desc_t im; time_t start_tmp = 0, end_tmp = 0; rrd_time_value_t start_tv, end_tv; char *parsetime_error = NULL; struct option long_options[] = { {"start", required_argument, 0, 's'}, {"end", required_argument, 0, 'e'}, {"maxrows", required_argument, 0, 'm'}, {"step", required_argument, 0, 261}, {"enumds", no_argument, 0, 262}, /* these are handled in the frontend ... */ {"json", no_argument, 0, 263}, /* these are handled in the frontend ... */ {"daemon", required_argument, 0, 'd'}, {0, 0, 0, 0} }; optind = 0; opterr = 0; /* initialize getopt */ rrd_graph_init(&im); rrd_parsetime("end-24h", &start_tv); rrd_parsetime("now", &end_tv); int enumds=0; int json=0; while (1) { int option_index = 0; int opt; opt = getopt_long(argc, argv, "s:e:m:d:", long_options, &option_index); if (opt == EOF) break; switch (opt) { case 261: im.step = atoi(optarg); break; case 262: enumds=1; break; case 263: json=1; break; 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 'm': im.xsize = atol(optarg); if (im.xsize < 10) { rrd_set_error("maxrows below 10 rows"); return -1; } break; case 'd': { if (im.daemon_addr != NULL) { rrd_set_error ("You cannot specify --daemon " "more than once."); return (-1); } im.daemon_addr = strdup(optarg); if (im.daemon_addr == NULL) { rrd_set_error("strdup error"); return -1; } break; } case '?': rrd_set_error("unknown option '%s'", argv[optind - 1]); 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 (%ld)", start_tmp); return -1; } if (end_tmp < start_tmp) { rrd_set_error("start (%ld) should be less than end (%ld)", start_tmp, end_tmp); return -1; } im.start = start_tmp; im.end = end_tmp; im.step = max((long) im.step, (im.end - im.start) / im.xsize); rrd_graph_script(argc, argv, &im, 0); if (rrd_test_error()) { im_free(&im); return -1; } if (im.gdes_c == 0) { rrd_set_error("can't make an xport without contents"); im_free(&im); return (-1); } { /* try to connect to rrdcached */ int status = rrdc_connect(im.daemon_addr); if (status != 0) return status; } if (rrd_xport_fn(&im, start, end, step, col_cnt, legend_v, data,0) == -1) { im_free(&im); return -1; } /* and create the export */ if (!xsize) { int flags=0; if (json) { flags|=1; } if (enumds) { flags|=4; } stringbuffer_t buffer={0,0,NULL,stdout}; rrd_xport_format_xmljson(flags,&buffer,&im, *start, *end, *step, *col_cnt, *legend_v, *data); } im_free(&im); return 0; }
static int rc_read (void) { int status; rrdc_stats_t *head; rrdc_stats_t *ptr; value_t values[1]; value_list_t vl = VALUE_LIST_INIT; if (daemon_address == NULL) return (-1); if (!config_collect_stats) return (-1); vl.values = values; vl.values_len = 1; if ((strncmp ("unix:", daemon_address, strlen ("unix:")) == 0) || (daemon_address[0] == '/')) sstrncpy (vl.host, hostname_g, sizeof (vl.host)); else sstrncpy (vl.host, daemon_address, sizeof (vl.host)); sstrncpy (vl.plugin, "rrdcached", sizeof (vl.plugin)); status = rrdc_connect (daemon_address); if (status != 0) { ERROR ("rrdcached plugin: rrdc_connect (%s) failed with status %i.", daemon_address, status); return (-1); } head = NULL; status = rrdc_stats_get (&head); if (status != 0) { ERROR ("rrdcached plugin: rrdc_stats_get failed with status %i.", status); return (-1); } for (ptr = head; ptr != NULL; ptr = ptr->next) { if (ptr->type == RRDC_STATS_TYPE_GAUGE) values[0].gauge = (gauge_t) ptr->value.gauge; else if (ptr->type == RRDC_STATS_TYPE_COUNTER) values[0].counter = (counter_t) ptr->value.counter; else continue; if (strcasecmp ("QueueLength", ptr->name) == 0) { sstrncpy (vl.type, "queue_length", sizeof (vl.type)); sstrncpy (vl.type_instance, "", sizeof (vl.type_instance)); } else if (strcasecmp ("UpdatesWritten", ptr->name) == 0) { sstrncpy (vl.type, "operations", sizeof (vl.type)); sstrncpy (vl.type_instance, "write-updates", sizeof (vl.type_instance)); } else if (strcasecmp ("DataSetsWritten", ptr->name) == 0) { sstrncpy (vl.type, "operations", sizeof (vl.type)); sstrncpy (vl.type_instance, "write-data_sets", sizeof (vl.type_instance)); } else if (strcasecmp ("TreeNodesNumber", ptr->name) == 0) { sstrncpy (vl.type, "gauge", sizeof (vl.type)); sstrncpy (vl.type_instance, "tree_nodes", sizeof (vl.type_instance)); } else if (strcasecmp ("TreeDepth", ptr->name) == 0) { sstrncpy (vl.type, "gauge", sizeof (vl.type)); sstrncpy (vl.type_instance, "tree_depth", sizeof (vl.type_instance)); } else if (strcasecmp ("FlushesReceived", ptr->name) == 0) { sstrncpy (vl.type, "operations", sizeof (vl.type)); sstrncpy (vl.type_instance, "receive-flush", sizeof (vl.type_instance)); } else if (strcasecmp ("JournalBytes", ptr->name) == 0) { sstrncpy (vl.type, "counter", sizeof (vl.type)); sstrncpy (vl.type_instance, "journal-bytes", sizeof (vl.type_instance)); } else if (strcasecmp ("JournalRotate", ptr->name) == 0) { sstrncpy (vl.type, "counter", sizeof (vl.type)); sstrncpy (vl.type_instance, "journal-rotates", sizeof (vl.type_instance)); } else if (strcasecmp ("UpdatesReceived", ptr->name) == 0) { sstrncpy (vl.type, "operations", sizeof (vl.type)); sstrncpy (vl.type_instance, "receive-update", sizeof (vl.type_instance)); } else { DEBUG ("rrdcached plugin: rc_read: Unknown statistic `%s'.", ptr->name); continue; } plugin_dispatch_values (&vl); } /* for (ptr = head; ptr != NULL; ptr = ptr->next) */ rrdc_stats_free (head); return (0); } /* int rc_read */
static int rc_read (void) { int status; rrdc_stats_t *head; _Bool retried = 0; value_list_t vl = VALUE_LIST_INIT; vl.values = &(value_t) { .gauge = NAN }; vl.values_len = 1; if (daemon_address == NULL) return (-1); if (!config_collect_stats) return (-1); if ((strncmp ("unix:", daemon_address, strlen ("unix:")) != 0) && (daemon_address[0] != '/')) sstrncpy (vl.host, daemon_address, sizeof (vl.host)); sstrncpy (vl.plugin, "rrdcached", sizeof (vl.plugin)); rrd_clear_error (); status = rrdc_connect (daemon_address); if (status != 0) { ERROR ("rrdcached plugin: Failed to connect to RRDCacheD " "at %s: %s (status=%d)", daemon_address, rrd_get_error (), status); return (-1); } while (42) { /* The RRD client lib does not provide any means for checking a * connection, hence we'll have to retry upon failed operations. */ head = NULL; rrd_clear_error (); status = rrdc_stats_get (&head); if (status == 0) break; if (!retried) { retried = 1; if (try_reconnect () == 0) continue; /* else: report the error and fail */ } ERROR ("rrdcached plugin: rrdc_stats_get failed: %s (status=%i).", rrd_get_error (), status); return (-1); } for (rrdc_stats_t *ptr = head; ptr != NULL; ptr = ptr->next) { if (ptr->type == RRDC_STATS_TYPE_GAUGE) vl.values[0].gauge = (gauge_t) ptr->value.gauge; else if (ptr->type == RRDC_STATS_TYPE_COUNTER) vl.values[0].counter = (counter_t) ptr->value.counter; else continue; if (strcasecmp ("QueueLength", ptr->name) == 0) { sstrncpy (vl.type, "queue_length", sizeof (vl.type)); sstrncpy (vl.type_instance, "", sizeof (vl.type_instance)); } else if (strcasecmp ("UpdatesWritten", ptr->name) == 0) { sstrncpy (vl.type, "operations", sizeof (vl.type)); sstrncpy (vl.type_instance, "write-updates", sizeof (vl.type_instance)); } else if (strcasecmp ("DataSetsWritten", ptr->name) == 0) { sstrncpy (vl.type, "operations", sizeof (vl.type)); sstrncpy (vl.type_instance, "write-data_sets", sizeof (vl.type_instance)); } else if (strcasecmp ("TreeNodesNumber", ptr->name) == 0) { sstrncpy (vl.type, "gauge", sizeof (vl.type)); sstrncpy (vl.type_instance, "tree_nodes", sizeof (vl.type_instance)); } else if (strcasecmp ("TreeDepth", ptr->name) == 0) { sstrncpy (vl.type, "gauge", sizeof (vl.type)); sstrncpy (vl.type_instance, "tree_depth", sizeof (vl.type_instance)); } else if (strcasecmp ("FlushesReceived", ptr->name) == 0) { sstrncpy (vl.type, "operations", sizeof (vl.type)); sstrncpy (vl.type_instance, "receive-flush", sizeof (vl.type_instance)); } else if (strcasecmp ("JournalBytes", ptr->name) == 0) { sstrncpy (vl.type, "counter", sizeof (vl.type)); sstrncpy (vl.type_instance, "journal-bytes", sizeof (vl.type_instance)); } else if (strcasecmp ("JournalRotate", ptr->name) == 0) { sstrncpy (vl.type, "counter", sizeof (vl.type)); sstrncpy (vl.type_instance, "journal-rotates", sizeof (vl.type_instance)); } else if (strcasecmp ("UpdatesReceived", ptr->name) == 0) { sstrncpy (vl.type, "operations", sizeof (vl.type)); sstrncpy (vl.type_instance, "receive-update", sizeof (vl.type_instance)); } else { DEBUG ("rrdcached plugin: rc_read: Unknown statistic `%s'.", ptr->name); continue; } plugin_dispatch_values (&vl); } /* for (ptr = head; ptr != NULL; ptr = ptr->next) */ rrdc_stats_free (head); return (0); } /* int rc_read */
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); }
int rrd_create( int argc, char **argv) { struct option long_options[] = { {"start", required_argument, 0, 'b'}, {"step", required_argument, 0, 's'}, {"daemon", required_argument, 0, 'd'}, {"no-overwrite", no_argument, 0, 'O'}, {0, 0, 0, 0} }; int option_index = 0; int opt; time_t last_up = time(NULL) - 10; unsigned long pdp_step = 300; rrd_time_value_t last_up_tv; char *parsetime_error = NULL; long long_tmp; int rc; char * opt_daemon = NULL; int opt_no_overwrite = 0; optind = 0; opterr = 0; /* initialize getopt */ while (1) { opt = getopt_long(argc, argv, "Ob:s:d:", 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; case 'b': if ((parsetime_error = rrd_parsetime(optarg, &last_up_tv))) { rrd_set_error("start time: %s", parsetime_error); 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"); 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"); 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"); return (-1); } pdp_step = long_tmp; break; case 'O': opt_no_overwrite = 1; break; case '?': if (optopt != 0) rrd_set_error("unknown option '%c'", optopt); else rrd_set_error("unknown option '%s'", argv[optind - 1]); return (-1); } } if (optind == argc) { rrd_set_error("need name of an rrd file to create"); return -1; } rrdc_connect (opt_daemon); if (rrdc_is_connected (opt_daemon)) { rc = rrdc_create (argv[optind], pdp_step, last_up, opt_no_overwrite, argc - optind - 1, (const char **) (argv + optind + 1)); } else { rc = rrd_create_r2(argv[optind], pdp_step, last_up, opt_no_overwrite, argc - optind - 1, (const char **) (argv + optind + 1)); } return rc; }
rrd_info_t *rrd_info( int argc, char **argv) { rrd_info_t *info; char *opt_daemon = NULL; int status; int flushfirst = 1; optind = 0; opterr = 0; /* initialize getopt */ while (42) { int opt; int option_index = 0; static struct option long_options[] = { {"daemon", required_argument, 0, 'd'}, {"noflush", no_argument, 0, 'F'}, {0, 0, 0, 0} }; opt = getopt_long(argc, argv, "d:F", 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 (NULL); } break; case 'F': flushfirst = 0; break; default: rrd_set_error ("Usage: rrdtool %s [--daemon <addr> [--noflush]] <file>", argv[0]); return (NULL); break; } } /* while (42) */ if ((argc - optind) != 1) { rrd_set_error ("Usage: rrdtool %s [--daemon <addr> [--noflush]] <file>", argv[0]); return (NULL); } if( flushfirst ) { status = rrdc_flush_if_daemon(opt_daemon, argv[optind]); if (status) return (NULL); } rrdc_connect (opt_daemon); if (rrdc_is_connected (opt_daemon)) info = rrdc_info (argv[optind]); else info = rrd_info_r(argv[optind]); if (opt_daemon) free(opt_daemon); return (info); } /* rrd_info_t *rrd_info */