X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Frrd_update.c;h=e9c75475b0ac2802a4964cac29df68d1442052ba;hb=e802fe69a7551c4a84c4f57f68a6f2c8685969a1;hp=e4f9712fb08ee56191dba1a0e800d6ea366d8460;hpb=285da1fa16e80919db972b1d7021c0b4705bedb1;p=rrdtool.git diff --git a/src/rrd_update.c b/src/rrd_update.c index e4f9712..e9c7547 100644 --- a/src/rrd_update.c +++ b/src/rrd_update.c @@ -5,6 +5,31 @@ ***************************************************************************** * $Id$ * $Log$ + * Revision 1.10 2003/04/29 19:14:12 jake + * Change updatev RRA return from index_number to cf_nam, pdp_cnt. + * Also revert accidental addition of -I to aclocal MakeMakefile. + * + * Revision 1.9 2003/04/25 18:35:08 jake + * Alternate update interface, updatev. Returns info about CDPs written to disk as result of update. Output format is similar to rrd_info, a hash of key-values. + * + * Revision 1.8 2003/03/31 21:22:12 oetiker + * enables RRDtool updates with microsecond or in case of windows millisecond + * precision. This is needed to reduce time measurement error when archive step + * is small. (<30s) -- Sasha Mikheev + * + * Revision 1.7 2003/02/13 07:05:27 oetiker + * Find attached the patch I promised to send to you. Please note that there + * are three new source files (src/rrd_is_thread_safe.h, src/rrd_thread_safe.c + * and src/rrd_not_thread_safe.c) and the introduction of librrd_th. This + * library is identical to librrd, but it contains support code for per-thread + * global variables currently used for error information only. This is similar + * to how errno per-thread variables are implemented. librrd_th must be linked + * alongside of libpthred + * + * There is also a new file "THREADS", holding some documentation. + * + * -- Peter Stamfest + * * Revision 1.6 2002/02/01 20:34:49 oetiker * fixed version number and date/time * @@ -41,8 +66,6 @@ #include "rrd_tool.h" #include #include -#include "rrd_hw.h" -#include "rrd_rpncalc.h" #ifdef WIN32 #include @@ -50,11 +73,61 @@ #include #endif +#include "rrd_hw.h" +#include "rrd_rpncalc.h" + +#include "rrd_is_thread_safe.h" + +#ifdef WIN32 +/* + * WIN32 does not have gettimeofday and struct timeval. This is a quick and dirty + * replacement. + */ +#include + +struct timeval { + time_t tv_sec; /* seconds */ + long tv_usec; /* microseconds */ +}; + +struct __timezone { + int tz_minuteswest; /* minutes W of Greenwich */ + int tz_dsttime; /* type of dst correction */ +}; + +static gettimeofday(struct timeval *t, struct __timezone *tz) { + + struct timeb current_time; + + _ftime(¤t_time); + + t->tv_sec = current_time.time; + t->tv_usec = current_time.millitm * 1000; +} + +#endif +/* + * normilize time as returned by gettimeofday. usec part must + * be always >= 0 + */ +static void normalize_time(struct timeval *t) +{ + if(t->tv_usec < 0) { + t->tv_sec--; + t->tv_usec += 1000000L; + } +} + /* Local prototypes */ int LockRRD(FILE *rrd_file); -void write_RRA_row (rrd_t *rrd, unsigned long rra_idx, unsigned long *rra_current, - unsigned short CDP_scratch_idx, FILE *rrd_file); - +info_t *write_RRA_row (rrd_t *rrd, unsigned long rra_idx, + unsigned long *rra_current, + unsigned short CDP_scratch_idx, FILE *rrd_file, + info_t *pcdp_summary, time_t *rra_time); +int rrd_update_r(char *filename, char *template, int argc, char **argv); +int _rrd_update(char *filename, char *template, int argc, char **argv, + info_t*); + #define IFDNAN(X,Y) (isnan(X) ? (Y) : (X)); @@ -78,13 +151,109 @@ main(int argc, char **argv){ } #endif +info_t *rrd_update_v(int argc, char **argv) +{ + char *template = NULL; + info_t *result = NULL; + infoval rc; + + while (1) { + static struct option long_options[] = + { + {"template", required_argument, 0, 't'}, + {0,0,0,0} + }; + int option_index = 0; + int opt; + opt = getopt_long(argc, argv, "t:", + long_options, &option_index); + + if (opt == EOF) + break; + + switch(opt) { + case 't': + template = optarg; + break; + + case '?': + rrd_set_error("unknown option '%s'",argv[optind-1]); + rc.u_int = -1; + goto end_tag; + } + } + + /* need at least 2 arguments: filename, data. */ + if (argc-optind < 2) { + rrd_set_error("Not enough arguments"); + rc.u_int = -1; + goto end_tag; + } + result = info_push(NULL,sprintf_alloc("return_value"),RD_I_INT,rc); + rc.u_int = _rrd_update(argv[optind], template, + argc - optind - 1, argv + optind + 1, result); + result->value.u_int = rc.u_int; +end_tag: + return result; +} + int rrd_update(int argc, char **argv) { + char *template = NULL; + int rc; + + while (1) { + static struct option long_options[] = + { + {"template", required_argument, 0, 't'}, + {0,0,0,0} + }; + int option_index = 0; + int opt; + opt = getopt_long(argc, argv, "t:", + long_options, &option_index); + + if (opt == EOF) + break; + + switch(opt) { + case 't': + template = optarg; + break; + + case '?': + rrd_set_error("unknown option '%s'",argv[optind-1]); + return(-1); + } + } + + /* need at least 2 arguments: filename, data. */ + if (argc-optind < 2) { + rrd_set_error("Not enough arguments"); + + return -1; + } + + rc = rrd_update_r(argv[optind], template, + argc - optind - 1, argv + optind + 1); + return rc; +} + +int +rrd_update_r(char *filename, char *template, int argc, char **argv) +{ + return _rrd_update(filename, template, argc, argv, NULL); +} + +int +_rrd_update(char *filename, char *template, int argc, char **argv, + info_t *pcdp_summary) +{ int arg_i = 2; short j; - long i,ii,iii=1; + unsigned long i,ii,iii=1; unsigned long rra_begin; /* byte pointer to the rra * area in the rrd file. this @@ -96,7 +265,7 @@ rrd_update(int argc, char **argv) unsigned long rra_current; /* byte pointer to the current write * spot in the rrd file. */ unsigned long rra_pos_tmp; /* temporary byte pointer. */ - unsigned long interval, + double interval, pre_int,post_int; /* interval between this and * the last run */ unsigned long proc_pdp_st; /* which pdp_st was the last @@ -118,14 +287,17 @@ rrd_update(int argc, char **argv) long *tmpl_idx; /* index representing the settings transported by the template index */ - long tmpl_cnt = 2; /* time and data */ + unsigned long tmpl_cnt = 2; /* time and data */ FILE *rrd_file; rrd_t rrd; - time_t current_time = time(NULL); + time_t current_time; + time_t rra_time; /* time of update for a RRA */ + unsigned long current_time_usec; /* microseconds part of current time */ + struct timeval tmp_time; /* used for time conversion */ + char **updvals; int schedule_smooth = 0; - char *template = NULL; rrd_value_t *seasonal_coef = NULL, *last_seasonal_coef = NULL; /* a vector of future Holt-Winters seasonal coefs */ unsigned long elapsed_pdp_st; @@ -142,44 +314,33 @@ rrd_update(int argc, char **argv) enum cf_en current_cf; /* numeric id of the current consolidation function */ rpnstack_t rpnstack; /* used for COMPUTE DS */ + int version; /* rrd version */ rpnstack_init(&rpnstack); - while (1) { - static struct option long_options[] = - { - {"template", required_argument, 0, 't'}, - {0,0,0,0} - }; - int option_index = 0; - int opt; - opt = getopt_long(argc, argv, "t:", - long_options, &option_index); - - if (opt == EOF) - break; - - switch(opt) { - case 't': - template = optarg; - break; - - case '?': - rrd_set_error("unknown option '%s'",argv[optind-1]); - rrd_free(&rrd); - return(-1); - } - } - - /* need at least 2 arguments: filename, data. */ - if (argc-optind < 2) { + /* need at least 1 arguments: data. */ + if (argc < 1) { rrd_set_error("Not enough arguments"); return -1; } + + - if(rrd_open(argv[optind],&rrd_file,&rrd, RRD_READWRITE)==-1){ + if(rrd_open(filename,&rrd_file,&rrd, RRD_READWRITE)==-1){ return -1; } + /* initialize time */ + version = atoi(rrd.stat_head->version); + gettimeofday(&tmp_time, 0); + normalize_time(&tmp_time); + current_time = tmp_time.tv_sec; + if(version >= 3) { + current_time_usec = tmp_time.tv_usec; + } + else { + current_time_usec = 0; + } + rra_current = rra_start = rra_begin = ftell(rrd_file); /* This is defined in the ANSI C standard, section 7.9.5.3: @@ -244,7 +405,7 @@ rrd_update(int argc, char **argv) if (template) { char *dsname; - int tmpl_len; + unsigned int tmpl_len; dsname = template; tmpl_cnt = 1; /* the first entry is the time */ tmpl_len = strlen(template); @@ -288,7 +449,7 @@ rrd_update(int argc, char **argv) } /* loop through the arguments. */ - for(arg_i=optind+1; arg_ilast_up){ rrd_set_error("illegal attempt to update using time %ld when " @@ -395,14 +567,17 @@ rrd_update(int argc, char **argv) /* when did the last pdp_st occur */ occu_pdp_age = current_time % rrd.stat_head->pdp_step; occu_pdp_st = current_time - occu_pdp_age; - interval = current_time - rrd.live_head->last_up; + /* interval = current_time - rrd.live_head->last_up; */ + interval = current_time + ((double)current_time_usec - (double)rrd.live_head->last_up_usec)/1000000.0 - rrd.live_head->last_up; if (occu_pdp_st > proc_pdp_st){ /* OK we passed the pdp_st moment*/ pre_int = occu_pdp_st - rrd.live_head->last_up; /* how much of the input data * occurred before the latest * pdp_st moment*/ + pre_int -= ((double)rrd.live_head->last_up_usec)/1000000.0; /* adjust usecs */ post_int = occu_pdp_age; /* how much after it */ + post_int += ((double)current_time_usec)/1000000.0; /* adjust usecs */ } else { pre_int = interval; post_int = 0; @@ -414,9 +589,9 @@ rrd_update(int argc, char **argv) "proc_pdp_st %lu\t" "occu_pfp_age %lu\t" "occu_pdp_st %lu\t" - "int %lu\t" - "pre_int %lu\t" - "post_int %lu\n", proc_pdp_age, proc_pdp_st, + "int %lf\t" + "pre_int %lf\t" + "post_int %lf\n", proc_pdp_age, proc_pdp_st, occu_pdp_age, occu_pdp_st, interval, pre_int, post_int); #endif @@ -998,7 +1173,14 @@ rrd_update(int argc, char **argv) fprintf(stderr," -- RRA Postseek %ld\n",ftell(rrd_file)); #endif scratch_idx = CDP_primary_val; - write_RRA_row(&rrd, i, &rra_current, scratch_idx, rrd_file); + if (pcdp_summary != NULL) + { + rra_time = (current_time - current_time + % (rrd.rra_def[i].pdp_cnt*rrd.stat_head->pdp_step)) + - ((rra_step_cnt[i]-1)*rrd.rra_def[i].pdp_cnt*rrd.stat_head->pdp_step); + } + pcdp_summary = write_RRA_row(&rrd, i, &rra_current, scratch_idx, rrd_file, + pcdp_summary, &rra_time); if (rrd_test_error()) break; /* write other rows of the bulk update, if any */ @@ -1025,7 +1207,14 @@ rrd_update(int argc, char **argv) #endif rra_current = rra_start; } - write_RRA_row(&rrd, i, &rra_current, scratch_idx, rrd_file); + if (pcdp_summary != NULL) + { + rra_time = (current_time - current_time + % (rrd.rra_def[i].pdp_cnt*rrd.stat_head->pdp_step)) + - ((rra_step_cnt[i]-2)*rrd.rra_def[i].pdp_cnt*rrd.stat_head->pdp_step); + } + pcdp_summary = write_RRA_row(&rrd, i, &rra_current, scratch_idx, rrd_file, + pcdp_summary, &rra_time); } if (rrd_test_error()) @@ -1040,6 +1229,7 @@ rrd_update(int argc, char **argv) } /* endif a pdp_st has occurred */ rrd.live_head->last_up = current_time; + rrd.live_head->last_up_usec = current_time_usec; free(step_start); } /* function argument loop */ @@ -1077,17 +1267,33 @@ rrd_update(int argc, char **argv) return(-1); } - if(fwrite( rrd.live_head, - sizeof(live_head_t), 1, rrd_file) != 1){ - rrd_set_error("fwrite live_head to rrd"); - free(updvals); - rrd_free(&rrd); - free(tmpl_idx); - free(pdp_temp); - free(pdp_new); - fclose(rrd_file); - return(-1); + if(version >= 3) { + if(fwrite( rrd.live_head, + sizeof(live_head_t), 1, rrd_file) != 1){ + rrd_set_error("fwrite live_head to rrd"); + free(updvals); + rrd_free(&rrd); + free(tmpl_idx); + free(pdp_temp); + free(pdp_new); + fclose(rrd_file); + return(-1); + } } + else { + if(fwrite( &rrd.live_head->last_up, + sizeof(time_t), 1, rrd_file) != 1){ + rrd_set_error("fwrite live_head to rrd"); + free(updvals); + rrd_free(&rrd); + free(tmpl_idx); + free(pdp_temp); + free(pdp_new); + fclose(rrd_file); + return(-1); + } + } + if(fwrite( rrd.pdp_prep, sizeof(pdp_prep_t), @@ -1149,9 +1355,9 @@ rrd_update(int argc, char **argv) if (schedule_smooth) { #ifndef WIN32 - rrd_file = fopen(argv[optind],"r+"); + rrd_file = fopen(filename,"r+"); #else - rrd_file = fopen(argv[optind],"rb+"); + rrd_file = fopen(filename,"rb+"); #endif rra_start = rra_begin; for (i = 0; i < rrd.stat_head -> rra_cnt; ++i) @@ -1217,12 +1423,14 @@ LockRRD(FILE *rrdfile) } -void -write_RRA_row (rrd_t *rrd, unsigned long rra_idx, unsigned long *rra_current, - unsigned short CDP_scratch_idx, FILE *rrd_file) +info_t +*write_RRA_row (rrd_t *rrd, unsigned long rra_idx, unsigned long *rra_current, + unsigned short CDP_scratch_idx, FILE *rrd_file, + info_t *pcdp_summary, time_t *rra_time) { unsigned long ds_idx, cdp_idx; - + infoval iv; + for (ds_idx = 0; ds_idx < rrd -> stat_head -> ds_cnt; ds_idx++) { /* compute the cdp index */ @@ -1232,7 +1440,16 @@ write_RRA_row (rrd_t *rrd, unsigned long rra_idx, unsigned long *rra_current, rrd -> cdp_prep[cdp_idx].scratch[CDP_scratch_idx].u_val,ftell(rrd_file), rrd -> rra_def[rra_idx].cf_nam); #endif - + if (pcdp_summary != NULL) + { + iv.u_val = rrd -> cdp_prep[cdp_idx].scratch[CDP_scratch_idx].u_val; + /* append info to the return hash */ + pcdp_summary = info_push(pcdp_summary, + sprintf_alloc("[%d]RRA[%s][%lu]DS[%s]", + *rra_time, rrd->rra_def[rra_idx].cf_nam, + rrd->rra_def[rra_idx].pdp_cnt, rrd->ds_def[ds_idx].ds_nam), + RD_I_VAL, iv); + } if(fwrite(&(rrd -> cdp_prep[cdp_idx].scratch[CDP_scratch_idx].u_val), sizeof(rrd_value_t),1,rrd_file) != 1) { @@ -1241,4 +1458,5 @@ write_RRA_row (rrd_t *rrd, unsigned long rra_idx, unsigned long *rra_current, } *rra_current += sizeof(rrd_value_t); } + return (pcdp_summary); }