char *printtimelast( long argc, const char **args) { time_t last; struct tm tm_last; char *buf; if (argc == 2) { buf = malloc(255); if (buf == NULL) { return stralloc("[ERROR: allocating strftime buffer]"); }; /* not raising argc in step with args - 1 since the last argument will be used below for strftime */ last = rrd_last(argc, (char **) args - 1); if (rrd_test_error()) { const size_t len = strlen(rrd_get_error()) + DS_NAM_SIZE; char *err = malloc(len); snprintf(err, len, "[ERROR: %s]", rrd_get_error()); rrd_clear_error(); return err; } tm_last = *localtime(&last); strftime(buf, 254, args[1], &tm_last); return buf; } return stralloc("[ERROR: expected <RRD::TIME::LAST file.rrd strftime-format>]"); }
static int RRD_update( char *rrd, const char *sum, const char *num, unsigned int process_time ) { char *argv[3]; int argc = 3; char val[128]; /* If we are a host RRD, we "sum" over only one host. */ if (num) sprintf(val, "%d:%s:%s", process_time, sum, num); else sprintf(val, "%d:%s", process_time, sum); argv[0] = "dummy"; argv[1] = rrd; argv[2] = val; pthread_mutex_lock( &rrd_mutex ); optind=0; opterr=0; rrd_clear_error(); rrd_update(argc, argv); if(rrd_test_error()) { err_msg("RRD_update (%s): %s", rrd, rrd_get_error()); pthread_mutex_unlock( &rrd_mutex ); return 0; } /* debug_msg("Updated rrd %s with value %s", rrd, val); */ pthread_mutex_unlock( &rrd_mutex ); return 0; }
/* 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 */
char *drawgraph( long argc, const char **args) { int i, xsize, ysize; double ymin, ymax; for (i = 0; i < argc; i++) if (strcmp(args[i], "--imginfo") == 0 || strcmp(args[i], "-g") == 0) break; if (i == argc) { args[argc++] = "--imginfo"; args[argc++] = "<IMG SRC=\"./%s\" WIDTH=\"%lu\" HEIGHT=\"%lu\">"; } calfree(); if (rrd_graph (argc + 1, (char **) args - 1, &calcpr, &xsize, &ysize, NULL, &ymin, &ymax) != -1) { return stralloc(calcpr[0]); } else { if (rrd_test_error()) { const size_t len = strlen(rrd_get_error()) + DS_NAM_SIZE; char *err = malloc(len); snprintf(err, len, "[ERROR: %s]", rrd_get_error()); rrd_clear_error(); return err; } } return NULL; }
void rrdtool_create_command (const char *name, const char *what) { // rrd_create needs the time of the first entry, so it // called at the time of the first update; therefore, we // need to backup the original rrd entry -- in order not // overwrite the update command contained in rrd.cmd rrd_struct temp_rrd = rrd; if (RRD_DEBUG) fprintf (fp_stderr, "rrdtool: create(%s,%s)\n", name, what); #ifdef RRD_TREE sprintf (temp_rrd.file, "%s/%s", rrd.conf.path, name, what); struct stat fbuf; if (!((stat (temp_rrd.file, &fbuf) == 0) && S_ISDIR (fbuf.st_mode))) { mkdir (temp_rrd.file, 0775); if (debug > 1) fprintf (fp_stderr, "RRDtool database path <%s> created\n", temp_rrd.file); } sprintf (temp_rrd.file, "%s/%s/%s.rrd", rrd.conf.path, name, what); #else sprintf (temp_rrd.file, "%s/%s.%s.rrd", rrd.conf.path, name, what); #endif rrd.time_update = (unsigned long) current_time.tv_sec; if (stat (temp_rrd.file, &temp_rrd.fbuf) == 0) { if (debug > 1) fprintf (fp_stderr, "rrdtool: skip create <%s> ... already existent\n", temp_rrd.file); return; /* already called ? */ } /* MTRG-like behavior for on-line usage */ sprintf (temp_rrd.cmd, "create %s --step %lu --start %ld DS:%s:GAUGE:%lu:U:U %s %s %s %s", temp_rrd.file, (unsigned long) (GLOBALS.Max_Time_Step / 1000000), (long) rrd.time_update - 10, name, (unsigned long) (GLOBALS.Max_Time_Step / 500000), RRA_DAILY, RRA_WEEKLY, RRA_MONTHLY, RRA_YEARLY); if (debug > 1) fprintf (fp_stderr, "rrdtool: rrd_create('%s')\n", temp_rrd.cmd); optind = 0; opterr = 0; rrdtool_str2argv (temp_rrd.cmd); rrd_create (rrd.argc, rrd.argv); if (rrd_test_error ()) { fprintf (fp_stderr, "rrdtool: create command:\n%s\n", temp_rrd.cmd); fprintf (fp_stderr, "rrdtool: create error!\n%s\n", rrd_get_error ()); if (temp_rrd.fatal) exit (1); rrd_clear_error (); } }
char* printtimelast(long argc, const char **args) { time_t last; struct tm tm_last; char *buf; if ( argc == 2 ) { buf = malloc(255); if (buf == NULL){ return stralloc("[ERROR: allocating strftime buffer]"); }; last = rrd_last(argc+1, (char **) args-1); if (rrd_test_error()) { char *err = malloc((strlen(rrd_get_error())+DS_NAM_SIZE)*sizeof(char)); sprintf(err, "[ERROR: %s]",rrd_get_error()); rrd_clear_error(); return err; } tm_last = *localtime(&last); strftime(buf,254,args[1],&tm_last); return buf; } if ( argc < 2 ) { return stralloc("[ERROR: too few arguments for RRD::TIME::LAST]"); } return stralloc("[ERROR: not enough arguments for RRD::TIME::LAST]"); }
static int rrd_common_call (lua_State *L, const char *cmd, RRD_FUNCTION rrd_function) { char **argv; int argc = lua_gettop(L) + 1; if(ntop->getGlobals()->isShutdown()) return(CONST_LUA_PARAM_ERROR); ntop->rrdLock(__FILE__, __LINE__); rrd_clear_error(); argv = make_argv(cmd, L); reset_rrd_state(); rrd_function(argc, argv); free(argv); if(rrd_test_error()) { char *err = rrd_get_error(); if(err != NULL) { /* IMPORTANT It is important to unlock now as if luaL_error is called the function returns and no unlock will take place */ ntop->rrdUnlock(__FILE__, __LINE__); luaL_error(L, err); } } ntop->rrdUnlock(__FILE__, __LINE__); return 0; }
/** * @brief 创建RRD数据库 * @param rrd_file rrd数据库路径 * @param summary 标志位是否summary * @param step 步长 * @return 成功返回0,失败返回-1 */ int c_rrd_handler::RRD_create(const char *rrd_file, bool summary, unsigned int step) { /* Warning: RRD_create will overwrite a RRD if it already exists */ int argc = 0; const char *argv[128] = {NULL}; const char *data_source_type = "GAUGE"; int heartbeat = 30; char sstep[16] = {'\0'}; char sstart[64] = {'\0'}; char ssum[64] = {'\0'}; char snum[64] = {'\0'}; /* Our heartbeat is twice the step interval. */ heartbeat = 2 * step; argv[argc++] = "dummy"; argv[argc++] = rrd_file; argv[argc++] = "--step"; sprintf(sstep, "%u", step); argv[argc++] = sstep; argv[argc++] = "--start"; sprintf(sstart, "%lu", time(NULL) - 1); argv[argc++] = sstart; sprintf(ssum, "DS:sum:%s:%d:U:U", data_source_type, heartbeat); argv[argc++] = ssum; if(summary) { sprintf(snum, "DS:num:%s:%d:U:U", data_source_type, heartbeat); argv[argc++] = snum; } if (g_is_switch_rrd) { GEN_SWITCH_RRA(argc, argv); } else { GEN_SERVER_RRA(argc, argv); } optind = 0; optopt = 0; opterr = 0; optarg = NULL; rrd_clear_error(); rrd_create(argc, (char**)argv); if(rrd_test_error()) { ERROR_LOG("RRD_create error: %s", rrd_get_error()); return -1; } DEBUG_LOG("CREATE RRD[%s]", rrd_file); return 0; }
JNIEXPORT jobject JNICALL Java_gnu_rrd_RRDJNI_graph (JNIEnv *env, jclass cl, jobjectArray argv) { char **argv2; char **calcpr; char* info; const char* fn; int asize = 0; int i, j, xsize, ysize; double ymin, ymax; jcharArray graph; jclass RRDGraphClass; jmethodID RRDGraphMethodInit; jmethodID RRDGraphMethodSetElement; jobject graphObj = NULL; jobject o; o = (*env)->GetObjectArrayElement(env, argv, 0); fn = (*env)->GetStringUTFChars(env, (jstring)o, NULL); if (strcmp(fn,"-")==0) { throwException(env, "gnu/rrd/RRDException", "output to stdout is not supported."); return; } RRDGraphClass = (*env)->FindClass(env, "gnu/rrd/RRDGraph"); RRDGraphMethodInit = (*env)->GetMethodID(env, RRDGraphClass, "<init>", "(Ljava/lang/String;Ljava/lang/String;IIDD)V"); calcpr = NULL; argv2 = initArgs(env, argv, "graph"); if (rrd_graph((*env)->GetArrayLength(env, argv)+1, argv2, &calcpr, &xsize, &ysize, NULL, &ymin, &ymax) != -1 ) { if (calcpr) { for(i = 0; calcpr[i]; i++) asize = asize + strlen(calcpr[i]) + 1; if((info = (char*)malloc(asize+1))==NULL) { throwException(env, "gnu/rrd/RRDException", "unable to allocate memory for graph information."); freeArgs(env, argv, argv2); free(calcpr); return; } else { for(i = 0; calcpr[i]; i++){ if (i>0) info = strcat(strcat(info, "\n"), calcpr[i]); else info = strcat(info, calcpr[i]); free(calcpr[i]); } } free(calcpr); } graphObj = (*env)->NewObject(env, RRDGraphClass, RRDGraphMethodInit, (jstring)(*env)->GetObjectArrayElement(env, argv, 0), (jstring)(*env)->NewStringUTF(env, info), (jint)xsize, (jint)ysize, (jdouble)ymin, (jdouble)ymax); } freeArgs(env, argv, argv2); if (rrd_test_error()) throwException(env, "gnu/rrd/RRDException", rrd_get_error()); return graphObj; }
JNIEXPORT void JNICALL Java_gnu_rrd_RRDJNI_dump (JNIEnv *env, jclass cl, jobjectArray argv) { char **argv2; argv2 = initArgs(env, argv, "dump"); rrd_dump((*env)->GetArrayLength(env, argv)+1, argv2); freeArgs(env, argv, argv2); if (rrd_test_error()) throwException(env, "gnu/rrd/RRDException", rrd_get_error()); }
int rrdc_connect (const char *addr) /* {{{ */ { int status = 0; if (addr == NULL) { addr = getenv (ENV_RRDCACHED_ADDRESS); } if (addr == NULL || strcmp(addr,"") == 0 ) { addr = NULL; return 0; } pthread_mutex_lock(&lock); if (sd >= 0 && sd_path != NULL && strcmp(addr, sd_path) == 0) { /* connection to the same daemon; use cached connection */ pthread_mutex_unlock (&lock); return (0); } else { close_connection(); } rrd_clear_error (); if (strncmp ("unix:", addr, strlen ("unix:")) == 0) status = rrdc_connect_unix (addr + strlen ("unix:")); else if (addr[0] == '/') status = rrdc_connect_unix (addr); else status = rrdc_connect_network(addr); if (status == 0 && sd >= 0) sd_path = strdup(addr); else { char *err = rrd_test_error () ? rrd_get_error () : "Internal error"; /* err points the string that gets written to by rrd_set_error(), thus we * cannot pass it to that function */ err = strdup (err); rrd_set_error("Unable to connect to rrdcached: %s", (status < 0) ? (err ? err : "Internal error") : rrd_strerror (status)); if (err != NULL) free (err); } pthread_mutex_unlock (&lock); return (status); } /* }}} int rrdc_connect */
char *rrdError() { char *err = NULL; if (rrd_test_error()) { // RRD error is local for thread so other gorutine can call some RRD // function in the same thread before we use C.GoString. So we need to // copy current error before return from C to Go. It need to be freed // after C.GoString in Go code. err = strdup(rrd_get_error()); if (err == NULL) { abort(); } } return err; }
int main( int argc, char **argv) { char *name=basename(argv[0]); rrd_info_t *info; if (!strcmp(name, "rrdcreate")) { rrd_create(argc, argv); } else if (!strcmp(name, "rrdinfo")) { info=rrd_info(argc, argv); rrd_info_print(info); rrd_info_free(info); } else { rrd_update(argc, argv); } if (rrd_test_error()) { printf("RRDtool " PACKAGE_VERSION " Copyright by Tobi Oetiker, 1997-2010\n\n"); if (!strcmp(name, "rrdcreate")) { printf("Usage: rrdcreate <filename>\n" "\t\t\t[--start|-b start time]\n" "\t\t\t[--step|-s step]\n" "\t\t\t[--no-overwrite]\n" "\t\t\t[DS:ds-name:DST:dst arguments]\n" "\t\t\t[RRA:CF:cf arguments]\n\n"); } else if (!strcmp(name, "rrdinfo")) { printf("Usage: rrdinfo <filename>\n"); } else { printf("Usage: rrdupdate <filename>\n" "\t\t\t[--template|-t ds-name[:ds-name]...]\n" "\t\t\t[--skip-past-updates]\n" "\t\t\ttime|N:value[:value...]\n\n" "\t\t\tat-time@value[:value...]\n\n" "\t\t\t[ time:value[:value...] ..]\n\n"); } printf("ERROR: %s\n", rrd_get_error()); rrd_clear_error(); return 1; } return 0; }
static int ntop_rrd_fetch(lua_State* L) { int argc = lua_gettop(L) + 1; char **argv = make_argv("fetch", L); unsigned long i, j, step, ds_cnt; rrd_value_t *data, *p; char **names; time_t t, start, end; ntop->rrdLock(__FILE__, __LINE__); reset_rrd_state(); rrd_fetch(argc, argv, &start, &end, &step, &ds_cnt, &names, &data); free(argv); if (rrd_test_error()) luaL_error(L, rrd_get_error()); lua_pushnumber(L, (lua_Number) start); lua_pushnumber(L, (lua_Number) step); /* fprintf(stderr, "%lu, %lu, %lu, %lu\n", start, end, step, num_points); */ /* create the ds names array */ lua_newtable(L); for (i=0; i<ds_cnt; i++) { lua_pushstring(L, names[i]); lua_rawseti(L, -2, i+1); rrd_freemem(names[i]); } rrd_freemem(names); /* create the data points array */ lua_newtable(L); p = data; for (t=start, i=0; t<end; t+=step, i++) { lua_newtable(L); for (j=0; j<ds_cnt; j++) { /*fprintf(stderr, "Point #%lu\n", j+1); */ lua_pushnumber(L, (lua_Number) *p++); lua_rawseti(L, -2, j+1); } lua_rawseti(L, -2, i+1); } rrd_freemem(data); ntop->rrdUnlock(__FILE__, __LINE__); /* return the end as the last value */ lua_pushnumber(L, (lua_Number) end); return 5; }
void rrdtool_update_command (const char *name, const char *what, double val) { if (RRD_DEBUG) fprintf (fp_stderr, "rrdtool: update(%s,%s,%f)\n", name, what, val); #ifdef RRD_TREE sprintf (rrd.file, "%s/%s/%s.rrd", rrd.conf.path, name, what); #else sprintf (rrd.file, "%s/%s.%s.rrd", rrd.conf.path, name, what); #endif /* at the first call of this function, all the needed rrd files are created with the start time set appropriately */ if (stat (rrd.file, &rrd.fbuf) == -1) rrdtool_create_all (); if (rrd.time_update == 0) rrd.time_update = (unsigned long) current_time.tv_sec; #ifdef RRD_THREADED sprintf (rrd.cmd, "update %s %ld:%f\n", rrd.file, rrd.time_update, val); if (RRD_DEBUG) fprintf (fp_stderr, "rrdtool: rrd_update('%s')\n", rrd.cmd); write (command_pipe[1],rrd.cmd, strlen(rrd.cmd) ); #else sprintf (rrd.cmd, "update %s %ld:%f", rrd.file, rrd.time_update, val); if (RRD_DEBUG) fprintf (fp_stderr, "rrdtool: rrd_update('%s')\n", rrd.cmd); optind = 0; opterr = 0; rrdtool_str2argv (rrd.cmd); rrd_update (rrd.argc, rrd.argv); if (rrd_test_error ()) { fprintf (fp_stderr, "rrdtool: update command:\n%s\n", rrd.cmd); fprintf (fp_stderr, "rrdtool: update error!\n%s\n", rrd_get_error ()); if (rrd.fatal) exit (1); rrd_clear_error (); } #endif }
/** * @brief 更新RRD数据库 * @param rrd_file rrd数据库路径 * @param value 数值 * @param num 个数 * @return 成功返回0,失败返回-1 */ int c_rrd_handler::RRD_update(const char *rrd_file, const char *value, const char *num) { int argc = 3; const char *argv[4] = {NULL}; char val[128] = {'\0'}; if(NULL == rrd_file || NULL == value) { ERROR_LOG("RRD path OR Value is NULL."); return -1; } // if(access(rrd_file, F_OK | R_OK | W_OK) != 0) { // ERROR_LOG("Can not access rrd_file[%s]: [%s]", rrd_file, strerror(errno)); // return -1; // } if(num) { snprintf(val, sizeof(val) - 1, "N:%s:%s", value, num); } else { snprintf(val, sizeof(val) - 1, "N:%s", value); } argv[0] = "dummy"; argv[1] = rrd_file; argv[2] = val; optind = 0; optopt = 0; opterr = 0; optarg = NULL; rrd_clear_error(); rrd_update(argc, (char**)argv); if(rrd_test_error()) { ERROR_LOG("ERROR: RRD_update(%s): %s", rrd_file, rrd_get_error()); return -1; } return 0; }
void * call_rrd_update(void*arg){ char buffer [2000]; int i = 0; time_t t; srand((unsigned) time(&t)); /* Set Cpu and I/O low priority struct sched_param sc_par; sc_par.sched_priority = 0; pthread_setschedparam(pthread_self(), SCHED_OTHER, &sc_par); setpriority(PRIO_PROCESS, 0, 19); syscall(SYS_ioprio_set,1, 0, (2<< 13)| 7);*/ /* Open pipe as a stream */ FILE * buffer_pipe = fdopen(command_pipe[0], "r"); rrd_clear_error (); /* Infinite loop on pipe */ while(1){ usleep(10000); fgets(buffer,2000,buffer_pipe); /* Replace \n with \0 */ buffer[strlen(buffer)-1]= '\0'; /* Execute update */ rrdtool_str2argv(buffer); optind = 0; opterr = 0; rrd_update (rrd.argc, rrd.argv); //if (i++%1000 == 0)printf("RRD\n"); /* Check errors */ if (rrd_test_error ()) { fprintf (fp_stderr, "rrdtool: update command:\n'%s'\n", buffer); fprintf (fp_stderr, "rrdtool: update error!\n%s\n", rrd_get_error ()); if (rrd.fatal) exit (1); rrd_clear_error (); } } return NULL; }
char* includefile(long argc, const char **args){ char *buffer; if (argc >= 1) { const char* filename = args[0]; readfile(filename, &buffer, 0); if (rrd_test_error()) { char *err = malloc((strlen(rrd_get_error())+DS_NAM_SIZE)); sprintf(err, "[ERROR: %s]",rrd_get_error()); rrd_clear_error(); return err; } else { return buffer; } } else { return stralloc("[ERROR: No Inclue file defined]"); } }
/* * Parse a DS definition */ static int parse_tag_ds_cdef( xmlTextReaderPtr reader, rrd_t *rrd) { xmlChar *cdef; cdef = get_xml_text(reader); if (cdef != NULL){ /* We're always working on the last DS that has been added to the structure * when we get here */ parseCDEF_DS((char *)cdef, rrd->ds_def + rrd->stat_head->ds_cnt - 1, rrd, lookup_DS); xmlFree(cdef); if (rrd_test_error()) return -1; else return 0; } return -1; } /* int parse_tag_ds_cdef */
JNIEXPORT jobject JNICALL Java_gnu_rrd_RRDJNI_last (JNIEnv *env, jclass cl, jobjectArray argv) { char **argv2; time_t t; jclass DateClass; jmethodID DateMethodInit; jobject DateObj; jlong timestamp; argv2 = initArgs(env, argv, "last"); t = rrd_last((*env)->GetArrayLength(env, argv)+1, argv2); timestamp = t; DateClass = (*env)->FindClass(env, "java/util/Date"); DateMethodInit = (*env)->GetMethodID(env, DateClass, "<init>", "(J)V"); DateObj = (*env)->NewObject(env, DateClass, DateMethodInit, timestamp*1000); freeArgs(env, argv, argv2); if (rrd_test_error()) throwException(env, "gnu/rrd/RRDException", rrd_get_error()); return DateObj; }
char* drawgraph(long argc, char **args){ int i,xsize, ysize; for(i=0;i<argc;i++) if(strcmp(args[i],"--imginfo")==0 || strcmp(args[i],"-g")==0) break; if(i==argc) { args[argc++] = "--imginfo"; args[argc++] = "<IMG SRC=\"./%s\" WIDTH=\"%lu\" HEIGHT=\"%lu\">"; } optind=0; /* reset gnu getopt */ opterr=0; /* reset gnu getopt */ calfree(); if( rrd_graph(argc+1, args-1, &calcpr, &xsize, &ysize) != -1 ) { return stralloc(calcpr[0]); } else { if (rrd_test_error()) { char *err = malloc((strlen(rrd_get_error())+DS_NAM_SIZE)*sizeof(char)); sprintf(err, "[ERROR: %s]",rrd_get_error()); rrd_clear_error(); calfree(); return err; } } return NULL; }
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 main(int argc, char *argv[]) { long length; char *buffer; char *server_url = NULL; long i; long filter=0; #ifdef MUST_DISABLE_SIGFPE signal(SIGFPE,SIG_IGN); #endif #ifdef MUST_DISABLE_FPMASK fpsetmask(0); #endif optind = 0; opterr = 0; /* initialize getopt */ /* what do we get for cmdline arguments? for (i=0;i<argc;i++) printf("%d-'%s'\n",i,argv[i]); */ while (1) { static struct option long_options[] = { { "filter", no_argument, 0, 'f' }, { 0, 0, 0, 0} }; int option_index = 0; int opt; opt = getopt_long(argc, argv, "f", long_options, &option_index); if (opt == EOF) { break; } switch(opt) { case 'f': filter=1; break; case '?': printf("unknown commandline option '%s'\n",argv[optind-1]); return -1; } } if (!filter) { rrdcgiDebug(0,0); rrdcgiArg = rrdcgiInit(); server_url = getenv("SERVER_URL"); } /* make sure we have one extra argument, if there are others, we do not care Apache gives several */ /* if ( (optind != argc-2 && strstr( getenv("SERVER_SOFTWARE"),"Apache/2") != NULL) && optind != argc-1) { */ if ( optind >= argc ) { fprintf(stderr, "ERROR: expected a filename\n"); exit(1); } else { length = readfile(argv[optind], &buffer, 1); } if(rrd_test_error()) { fprintf(stderr, "ERROR: %s\n",rrd_get_error()); exit(1); } /* initialize variable heap */ initvar(); #ifdef DEBUG_PARSER /* some fake header for testing */ printf ("Content-Type: text/html\nContent-Length: 10000000\n\n\n"); #endif /* expand rrd directives in buffer recursivly */ for (i=0; buffer[i]; i++) { if (buffer[i] != '<') continue; if (!filter) { parse(&buffer, i, "<RRD::CV", cgiget); parse(&buffer, i, "<RRD::CV::PATH", cgigetqp); parse(&buffer, i, "<RRD::CV::QUOTE", cgigetq); parse(&buffer, i, "<RRD::GETENV", rrdgetenv); } parse(&buffer, i, "<RRD::GETVAR", rrdgetvar); parse(&buffer, i, "<RRD::GOODFOR", rrdgoodfor); parse(&buffer, i, "<RRD::GRAPH", drawgraph); parse(&buffer, i, "<RRD::INCLUDE", includefile); parse(&buffer, i, "<RRD::PRINT", drawprint); parse(&buffer, i, "<RRD::SETCONSTVAR", rrdsetvarconst); parse(&buffer, i, "<RRD::SETENV", rrdsetenv); parse(&buffer, i, "<RRD::SETVAR", rrdsetvar); parse(&buffer, i, "<RRD::TIME::LAST", printtimelast); parse(&buffer, i, "<RRD::TIME::NOW", printtimenow); parse(&buffer, i, "<RRD::TIME::STRFTIME", printstrftime); parse(&buffer, i, "<RRD::INTERNAL", rrdgetinternal); } if (!filter) { printf ("Content-Type: text/html\n" "Content-Length: %d\n", strlen(buffer)); if (labs(goodfor) > 0) { time_t now; now = time(NULL); printf("Last-Modified: %s\n", http_time(&now)); now += labs(goodfor); printf("Expires: %s\n", http_time(&now)); if (goodfor < 0) { printf("Refresh: %ld\n", labs(goodfor)); } } printf("\n"); } /* output result */ printf("%s", buffer); /* cleanup */ calfree(); if (buffer){ free(buffer); } donevar(); exit(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); }
/* Warning: RRD_create will overwrite a RRdb if it already exists */ static int RRD_create( char *rrd, int summary, unsigned int step, unsigned int process_time, ganglia_slope_t slope) { const char *data_source_type = "GAUGE"; char *argv[128]; int argc=0; int heartbeat; char s[16], start[64]; char sum[64]; char num[64]; int i; /* Our heartbeat is twice the step interval. */ heartbeat = 8*step; switch( slope) { case GANGLIA_SLOPE_POSITIVE: data_source_type = "COUNTER"; break; case GANGLIA_SLOPE_ZERO: case GANGLIA_SLOPE_NEGATIVE: case GANGLIA_SLOPE_BOTH: case GANGLIA_SLOPE_UNSPECIFIED: data_source_type = "GAUGE"; break; } argv[argc++] = "dummy"; argv[argc++] = rrd; argv[argc++] = "--step"; sprintf(s, "%u", step); argv[argc++] = s; argv[argc++] = "--start"; sprintf(start, "%u", process_time-1); argv[argc++] = start; sprintf(sum,"DS:sum:%s:%d:U:U", data_source_type, heartbeat); argv[argc++] = sum; if (summary) { sprintf(num,"DS:num:%s:%d:U:U", data_source_type, heartbeat); argv[argc++] = num; } for(i = 0; i< gmetad_config.num_RRAs; i++) { argv[argc++] = gmetad_config.RRAs[i]; } #if 0 /* Read in or defaulted in conf.c */ argv[argc++] = "RRA:AVERAGE:0.5:1:240"; argv[argc++] = "RRA:AVERAGE:0.5:24:240"; argv[argc++] = "RRA:AVERAGE:0.5:168:240"; argv[argc++] = "RRA:AVERAGE:0.5:672:240"; argv[argc++] = "RRA:AVERAGE:0.5:5760:370"; #endif pthread_mutex_lock( &rrd_mutex ); optind=0; opterr=0; rrd_clear_error(); rrd_create(argc, argv); if(rrd_test_error()) { err_msg("RRD_create: %s", rrd_get_error()); pthread_mutex_unlock( &rrd_mutex ); return 1; } debug_msg("Created rrd %s", rrd); pthread_mutex_unlock( &rrd_mutex ); return 0; }
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_tune(int argc, char **argv) { rrd_t rrd; FILE *rrd_file; int matches; int optcnt = 0; long ds; char ds_nam[DS_NAM_SIZE]; char ds_new[DS_NAM_SIZE]; long heartbeat; double min; double max; char dst[DST_SIZE]; optind = 0; opterr = 0; /* initialize getopt */ if(rrd_open(argv[1],&rrd_file,&rrd, RRD_READWRITE)==-1){ return -1; } while (1){ static struct option long_options[] = { {"heartbeat", required_argument, 0, 'h'}, {"minimum", required_argument, 0, 'i'}, {"maximum", required_argument, 0, 'a'}, {"data-source-type", required_argument, 0, 'd'}, {"data-source-rename", required_argument, 0, 'r'}, /* added parameter tuning options for aberrant behavior detection */ {"deltapos",required_argument,0,'p'}, {"deltaneg",required_argument,0,'n'}, {"window-length",required_argument,0,'w'}, {"failure-threshold",required_argument,0,'f'}, {"alpha",required_argument,0,'x'}, {"beta",required_argument,0,'y'}, {"gamma",required_argument,0,'z'}, {"gamma-deviation",required_argument,0,'v'}, {"aberrant-reset",required_argument,0,'b'}, {0,0,0,0} }; int option_index = 0; int opt; opt = getopt_long(argc, argv, "h:i:a:d:r:p:n:w:f:x:y:z:v:b:", long_options, &option_index); if (opt == EOF) break; optcnt++; switch(opt) { case 'h': if ((matches = sscanf(optarg, DS_NAM_FMT ":%ld",ds_nam,&heartbeat)) != 2){ rrd_set_error("invalid arguments for heartbeat"); rrd_free(&rrd); fclose(rrd_file); return -1; } if ((ds=ds_match(&rrd,ds_nam))==-1){ rrd_free(&rrd); fclose(rrd_file); return -1; } rrd.ds_def[ds].par[DS_mrhb_cnt].u_cnt = heartbeat; break; case 'i': if ((matches = sscanf(optarg,DS_NAM_FMT ":%lf",ds_nam,&min)) <1){ rrd_set_error("invalid arguments for minimum ds value"); rrd_free(&rrd); fclose(rrd_file); return -1; } if ((ds=ds_match(&rrd,ds_nam))==-1){ rrd_free(&rrd); fclose(rrd_file); return -1; } if(matches == 1) min= DNAN; rrd.ds_def[ds].par[DS_min_val].u_val = min; break; case 'a': if ((matches = sscanf(optarg, DS_NAM_FMT ":%lf",ds_nam,&max)) <1){ rrd_set_error("invalid arguments for maximum ds value"); rrd_free(&rrd); fclose(rrd_file); return -1; } if ((ds=ds_match(&rrd,ds_nam))==-1){ rrd_free(&rrd); fclose(rrd_file); return -1; } if(matches == 1) max= DNAN; rrd.ds_def[ds].par[DS_max_val].u_val = max; break; case 'd': if ((matches = sscanf(optarg, DS_NAM_FMT ":" DST_FMT ,ds_nam,dst)) != 2){ rrd_set_error("invalid arguments for data source type"); rrd_free(&rrd); fclose(rrd_file); return -1; } if ((ds=ds_match(&rrd,ds_nam))==-1){ rrd_free(&rrd); fclose(rrd_file); return -1; } if ((int)dst_conv(dst) == -1){ rrd_free(&rrd); fclose(rrd_file); return -1; } strncpy(rrd.ds_def[ds].dst,dst,DST_SIZE-1); rrd.ds_def[ds].dst[DST_SIZE-1]='\0'; rrd.pdp_prep[ds].last_ds[0] = 'U'; rrd.pdp_prep[ds].last_ds[1] = 'N'; rrd.pdp_prep[ds].last_ds[2] = 'K'; rrd.pdp_prep[ds].last_ds[3] = 'N'; rrd.pdp_prep[ds].last_ds[4] = '\0'; break; case 'r': if ((matches = sscanf(optarg,DS_NAM_FMT ":" DS_NAM_FMT , ds_nam,ds_new)) != 2){ rrd_set_error("invalid arguments for data source type"); rrd_free(&rrd); fclose(rrd_file); return -1; } if ((ds=ds_match(&rrd,ds_nam))==-1){ rrd_free(&rrd); fclose(rrd_file); return -1; } strncpy(rrd.ds_def[ds].ds_nam,ds_new,DS_NAM_SIZE-1); rrd.ds_def[ds].ds_nam[DS_NAM_SIZE-1]='\0'; break; case 'p': if (set_deltaarg(&rrd,RRA_delta_pos,optarg)) { rrd_free(&rrd); return -1; } break; case 'n': if (set_deltaarg(&rrd,RRA_delta_neg,optarg)) { rrd_free(&rrd); return -1; } break; case 'f': if (set_windowarg(&rrd,RRA_failure_threshold,optarg)) { rrd_free(&rrd); return -1; } break; case 'w': if (set_windowarg(&rrd,RRA_window_len,optarg)) { rrd_free(&rrd); return -1; } break; case 'x': if (set_hwarg(&rrd,CF_HWPREDICT,RRA_hw_alpha,optarg)) { rrd_free(&rrd); return -1; } break; case 'y': if (set_hwarg(&rrd,CF_HWPREDICT,RRA_hw_beta,optarg)) { rrd_free(&rrd); return -1; } break; case 'z': if (set_hwarg(&rrd,CF_SEASONAL,RRA_seasonal_gamma,optarg)) { rrd_free(&rrd); return -1; } break; case 'v': if (set_hwarg(&rrd,CF_DEVSEASONAL,RRA_seasonal_gamma,optarg)) { rrd_free(&rrd); return -1; } break; case 'b': if (sscanf(optarg,DS_NAM_FMT,ds_nam) != 1){ rrd_set_error("invalid argument for aberrant-reset"); rrd_free(&rrd); fclose(rrd_file); return -1; } if ((ds=ds_match(&rrd,ds_nam))==-1){ /* ds_match handles it own errors */ rrd_free(&rrd); fclose(rrd_file); return -1; } reset_aberrant_coefficients(&rrd,rrd_file,(unsigned long) ds); if (rrd_test_error()) { rrd_free(&rrd); fclose(rrd_file); return -1; } break; case '?': if (optopt != 0) rrd_set_error("unknown option '%c'", optopt); else rrd_set_error("unknown option '%s'",argv[optind-1]); rrd_free(&rrd); fclose(rrd_file); return -1; } } if(optcnt>0){ fseek(rrd_file,0,SEEK_SET); fwrite(rrd.stat_head, sizeof(stat_head_t),1, rrd_file); fwrite(rrd.ds_def, sizeof(ds_def_t), rrd.stat_head->ds_cnt, rrd_file); /* need to write rra_defs for RRA parameter changes */ fwrite(rrd.rra_def, sizeof(rra_def_t), rrd.stat_head->rra_cnt, rrd_file); } else { int i; for(i=0;i< (int)rrd.stat_head->ds_cnt;i++) if (dst_conv(rrd.ds_def[i].dst) != DST_CDEF) { printf("DS[%s] typ: %s\thbt: %ld\tmin: %1.4f\tmax: %1.4f\n", rrd.ds_def[i].ds_nam, rrd.ds_def[i].dst, rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt, rrd.ds_def[i].par[DS_min_val].u_val, rrd.ds_def[i].par[DS_max_val].u_val); } else { char *buffer = NULL; rpn_compact2str((rpn_cdefds_t *) &(rrd.ds_def[i].par[DS_cdef]),rrd.ds_def,&buffer); printf("DS[%s] typ: %s\tcdef: %s\n", rrd.ds_def[i].ds_nam,rrd.ds_def[i].dst,buffer); free(buffer); } } fclose(rrd_file); rrd_free(&rrd); return 0; }
/* HandleInputLine is NOT thread safe - due to readdir issues, resolving them portably is not really simple. */ int HandleInputLine( int argc, char **argv, FILE * out) { #if defined(HAVE_OPENDIR) && defined (HAVE_READDIR) DIR *curdir; /* to read current dir with ls */ struct dirent *dent; #endif /* Reset errno to 0 before we start. */ if (RemoteMode) { if (argc > 1 && strcmp("quit", argv[1]) == 0) { if (argc != 2) { printf("ERROR: invalid parameter count for quit\n"); return (1); } exit(0); } #if defined(HAVE_OPENDIR) && defined(HAVE_READDIR) && defined(HAVE_CHDIR) && defined(HAVE_SYS_STAT_H) if (argc > 1 && strcmp("cd", argv[1]) == 0) { if (argc != 3) { printf("ERROR: invalid parameter count for cd\n"); return (1); } #if ! defined(HAVE_CHROOT) || ! defined(HAVE_GETUID) if (getuid() == 0 && !ChangeRoot) { printf ("ERROR: chdir security problem - rrdtool is running as " "root but not chroot!\n"); return (1); } #endif if (chdir(argv[2]) != 0){ printf("ERROR: chdir %s %s\n", argv[2], rrd_strerror(errno)); return (1); } return (0); } if (argc > 1 && strcmp("pwd", argv[1]) == 0) { char *cwd; /* To hold current working dir on call to pwd */ if (argc != 2) { printf("ERROR: invalid parameter count for pwd\n"); return (1); } cwd = getcwd(NULL, MAXPATH); if (cwd == NULL) { printf("ERROR: getcwd %s\n", rrd_strerror(errno)); return (1); } printf("%s\n", cwd); free(cwd); return (0); } if (argc > 1 && strcmp("mkdir", argv[1]) == 0) { if (argc != 3) { printf("ERROR: invalid parameter count for mkdir\n"); return (1); } #if ! defined(HAVE_CHROOT) || ! defined(HAVE_GETUID) if (getuid() == 0 && !ChangeRoot) { printf ("ERROR: mkdir security problem - rrdtool is running as " "root but not chroot!\n"); return (1); } #endif if(mkdir(argv[2], 0777)!=0){ printf("ERROR: mkdir %s: %s\n", argv[2],rrd_strerror(errno)); return (1); } return (0); } if (argc > 1 && strcmp("ls", argv[1]) == 0) { if (argc != 2) { printf("ERROR: invalid parameter count for ls\n"); return (1); } if ((curdir = opendir(".")) != NULL) { struct stat st; while ((dent = readdir(curdir)) != NULL) { if (!stat(dent->d_name, &st)) { if (S_ISDIR(st.st_mode)) { printf("d %s\n", dent->d_name); } if (strlen(dent->d_name) > 4 && S_ISREG(st.st_mode)) { if (!strcmp (dent->d_name + NAMLEN(dent) - 4, ".rrd") || !strcmp(dent->d_name + NAMLEN(dent) - 4, ".RRD")) { printf("- %s\n", dent->d_name); } } } } closedir(curdir); } else { printf("ERROR: opendir .: %s\n", rrd_strerror(errno)); return (errno); } return (0); } #endif /* opendir and readdir */ } if (argc < 3 || strcmp("help", argv[1]) == 0 || strcmp("--help", argv[1]) == 0 || strcmp("-help", argv[1]) == 0 || strcmp("-?", argv[1]) == 0 || strcmp("-h", argv[1]) == 0) { PrintUsage(""); return 0; } if (strcmp("create", argv[1]) == 0) rrd_create(argc - 1, &argv[1]); else if (strcmp("dump", argv[1]) == 0) rrd_dump(argc - 1, &argv[1]); else if (strcmp("info", argv[1]) == 0 || strcmp("updatev", argv[1]) == 0) { rrd_info_t *data; if (strcmp("info", argv[1]) == 0) data = rrd_info(argc - 1, &argv[1]); else data = rrd_update_v(argc - 1, &argv[1]); rrd_info_print(data); rrd_info_free(data); } else if (strcmp("--version", argv[1]) == 0 || strcmp("version", argv[1]) == 0 || strcmp("v", argv[1]) == 0 || strcmp("-v", argv[1]) == 0 || strcmp("-version", argv[1]) == 0) printf("RRDtool " PACKAGE_VERSION " Copyright by Tobi Oetiker, 1997-2008 (%f)\n", rrd_version()); else if (strcmp("restore", argv[1]) == 0) rrd_restore(argc - 1, &argv[1]); else if (strcmp("resize", argv[1]) == 0) rrd_resize(argc - 1, &argv[1]); else if (strcmp("last", argv[1]) == 0) printf("%ld\n", rrd_last(argc - 1, &argv[1])); else if (strcmp("lastupdate", argv[1]) == 0) { rrd_lastupdate(argc - 1, &argv[1]); } else if (strcmp("first", argv[1]) == 0) printf("%ld\n", rrd_first(argc - 1, &argv[1])); else if (strcmp("update", argv[1]) == 0) rrd_update(argc - 1, &argv[1]); else if (strcmp("fetch", argv[1]) == 0) { time_t start, end, ti; unsigned long step, ds_cnt, i, ii; rrd_value_t *data, *datai; char **ds_namv; if (rrd_fetch (argc - 1, &argv[1], &start, &end, &step, &ds_cnt, &ds_namv, &data) == 0) { datai = data; printf(" "); for (i = 0; i < ds_cnt; i++) printf("%20s", ds_namv[i]); printf("\n\n"); for (ti = start + step; ti <= end; ti += step) { printf("%10lu:", ti); for (ii = 0; ii < ds_cnt; ii++) printf(" %0.10e", *(datai++)); printf("\n"); } for (i = 0; i < ds_cnt; i++) free(ds_namv[i]); free(ds_namv); free(data); } } else if (strcmp("xport", argv[1]) == 0) { #ifdef HAVE_RRD_GRAPH time_t start, end; unsigned long step, col_cnt; rrd_value_t *data; char **legend_v; rrd_xport (argc - 1, &argv[1], NULL, &start, &end, &step, &col_cnt, &legend_v, &data); #else rrd_set_error("the instance of rrdtool has been compiled without graphics"); #endif } else if (strcmp("graph", argv[1]) == 0) { #ifdef HAVE_RRD_GRAPH char **calcpr; #ifdef notused /*XXX*/ const char *imgfile = argv[2]; /* rrd_graph changes argv pointer */ #endif int xsize, ysize; double ymin, ymax; int i; int tostdout = (strcmp(argv[2], "-") == 0); int imginfo = 0; for (i = 2; i < argc; i++) { if (strcmp(argv[i], "--imginfo") == 0 || strcmp(argv[i], "-f") == 0) { imginfo = 1; break; } } if (rrd_graph (argc - 1, &argv[1], &calcpr, &xsize, &ysize, NULL, &ymin, &ymax) == 0) { if (!tostdout && !imginfo) printf("%dx%d\n", xsize, ysize); if (calcpr) { for (i = 0; calcpr[i]; i++) { if (!tostdout) printf("%s\n", calcpr[i]); free(calcpr[i]); } free(calcpr); } } #else rrd_set_error("the instance of rrdtool has been compiled without graphics"); #endif } else if (strcmp("graphv", argv[1]) == 0) { #ifdef HAVE_RRD_GRAPH rrd_info_t *grinfo = NULL; /* 1 to distinguish it from the NULL that rrd_graph sends in */ grinfo = rrd_graph_v(argc - 1, &argv[1]); if (grinfo) { rrd_info_print(grinfo); rrd_info_free(grinfo); } #else rrd_set_error("the instance of rrdtool has been compiled without graphics"); #endif } else if (strcmp("tune", argv[1]) == 0) rrd_tune(argc - 1, &argv[1]); else if (strcmp("flushcached", argv[1]) == 0) rrd_flushcached(argc - 1, &argv[1]); else if (strcmp("modify", argv[1]) == 0) rrd_modify(argc - 1, &argv[1]); else { rrd_set_error("unknown function '%s'", argv[1]); } if (rrd_test_error()) { fprintf(out, "ERROR: %s\n", rrd_get_error()); rrd_clear_error(); return 1; } return (0); }
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; }