From fcbf2878a231442f4b62ee95fca39e28f04fc8d2 Mon Sep 17 00:00:00 2001 From: oetiker Date: Fri, 24 Sep 2004 21:11:09 +0000 Subject: [PATCH] misc fixed and TREND and reduce functionality by -- David M. Grimes git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk/program@291 a5681a0c-68f1-0310-ab6d-d61299d08faa --- CONTRIBUTORS | 2 +- doc/rrdgraph_data.src | 9 +++++++-- doc/rrdgraph_rpn.src | 26 +++++++++++++++++++++++++- src/rrd_graph.c | 19 ++++++++----------- src/rrd_graph.h | 1 + src/rrd_graph_helper.c | 27 +++++++++++++++++---------- src/rrd_resize.c | 6 ++++-- src/rrd_rpncalc.c | 28 ++++++++++++++++++++++++++-- src/rrd_rpncalc.h | 2 +- src/rrd_xport.c | 3 ++- 10 files changed, 92 insertions(+), 31 deletions(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index b924d24..717ff1f 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -60,7 +60,7 @@ Debugging and code contributions David L. Barker xport function bug fixes Mike Slifcak many rrdtool-1.1.x fixes Peter Speck eps/svg/pdf file format code in rrdtool-1.x - David Grimes SQRT/SORT/REV/SHIFT + David Grimes SQRT/SORT/REV/SHIFT/TREND Documentation diff --git a/doc/rrdgraph_data.src b/doc/rrdgraph_data.src index 88ac260..1f8fcb7 100644 --- a/doc/rrdgraph_data.src +++ b/doc/rrdgraph_data.src @@ -2,7 +2,7 @@ =head1 SYNOPSIS -BIvnameE>=IrrdfileE>:Ids-nameE>:ICFE>[:step=IstepE>][:start=ItimeE>][:end=ItimeE>] +BIvnameE>=IrrdfileE>:Ids-nameE>:ICFE>[:step=IstepE>][:start=ItimeE>][:end=ItimeE>][:reduce=IBE>] B:I=I @@ -18,7 +18,7 @@ a language called B which is described in its own manual page. =head1 DEF -BIvnameE>=IrrdfileE>:Ids-nameE>:ICFE>[:step=IstepE>][:start=ItimeE>][:end=ItimeE>] +BIvnameE>=IrrdfileE>:Ids-nameE>:ICFE>[:step=IstepE>][:start=ItimeE>][:end=ItimeE>][:reduce=IBE>] This command fetches data from an B file. The virtual name I can then be used throughout the rest of the script. By @@ -39,6 +39,11 @@ a resolution of 1800 seconds per B, you should create an image with width 400 and time span 400*1800 seconds (use appropriate start and end times, such as C<--start end-8days8hours>). +If consolidation needs to be done, the B of the B specified in the +B itself will be used to reduce the data density. This behaviour can +be changed using C<:reduce=IBE>>. This optional parameter +specifies the B to use during the data reduction phase. + Example: DEF:ds0=router.rrd:ds0:AVERAGE diff --git a/doc/rrdgraph_rpn.src b/doc/rrdgraph_rpn.src index ae1a91b..4aad477 100644 --- a/doc/rrdgraph_rpn.src +++ b/doc/rrdgraph_rpn.src @@ -108,7 +108,7 @@ Round down,up to the nearest integer Z<> -=item Ordering Operations +=item Set Operations B @@ -120,6 +120,30 @@ Example: C will compute the average of the values v1..v6 after removing the smallest and largest. +B + +Create a "sliding window" average of another data series. + +Usage: +CDEF:smoothed=x,1800,TREND + +This will create a half-hour (1800 second) sliding window average of x. The +average is essentially computed as shown here: + + +---!---!---!---!---!---!---!---!---> + now + delay t0 + <---------------> + delay t1 + <---------------> + delay t2 + <---------------> + + + Value at sample (t0) will be the average between (t0-delay) and (t0) + Value at sample (t1) will be the average between (t1-delay) and (t1) + Value at sample (t2) will be the average between (t2-delay) and (t2) + =item Special values B diff --git a/src/rrd_graph.c b/src/rrd_graph.c index 438b3e1..d22c853 100644 --- a/src/rrd_graph.c +++ b/src/rrd_graph.c @@ -698,6 +698,7 @@ data_fetch(image_desc_t *im ) continue; if ((strcmp(im->gdes[i].rrd, im->gdes[ii].rrd) == 0) && (im->gdes[i].cf == im->gdes[ii].cf) + && (im->gdes[i].cf_reduce == im->gdes[ii].cf_reduce) && (im->gdes[i].start == im->gdes[ii].start) && (im->gdes[i].end == im->gdes[ii].end) && (im->gdes[i].step == im->gdes[ii].step)) { @@ -730,9 +731,10 @@ data_fetch(image_desc_t *im ) return -1; } im->gdes[i].data_first = 1; + im->gdes[i].step = im->step; if (ft_step < im->gdes[i].step) { - reduce_data(im->gdes[i].cf, + reduce_data(im->gdes[i].cf_reduce, ft_step, &im->gdes[i].start, &im->gdes[i].end, @@ -838,7 +840,7 @@ data_calc( image_desc_t *im){ vdp->shift = im->gdes[gdi].shval; /* normalize shift to multiple of consolidated step */ - vdp->shift = (vdp->shift / vdp->step) * vdp->step; + vdp->shift = (vdp->shift / (long)vdp->step) * (long)vdp->step; /* apply shift */ vdp->start += vdp->shift; @@ -934,8 +936,8 @@ data_calc( image_desc_t *im){ for(rpi=0;im->gdes[gdi].rpnp[rpi].op != OP_END;rpi++){ if(im->gdes[gdi].rpnp[rpi].op == OP_VARIABLE || im->gdes[gdi].rpnp[rpi].op == OP_PREV_OTHER){ - long ptr = im->gdes[gdi].rpnp[rpi].ptr; - long diff = im->gdes[gdi].start - im->gdes[ptr].start; + long ptr = im->gdes[gdi].rpnp[rpi].ptr; + long diff = im->gdes[gdi].start - im->gdes[ptr].start; if(diff > 0) im->gdes[gdi].rpnp[rpi].data += (diff / im->gdes[ptr].step) * im->gdes[ptr].ds_cnt; @@ -2570,13 +2572,7 @@ graph_paint(image_desc_t *im, char ***calcpr) int gdes_alloc(image_desc_t *im){ - unsigned long def_step = (im->end-im->start)/im->xsize; - - if (im->step > def_step) /* step can be increassed ... no decreassed */ - def_step = im->step; - im->gdes_c++; - if ((im->gdes = (graph_desc_t *) rrd_realloc(im->gdes, (im->gdes_c) * sizeof(graph_desc_t)))==NULL){ rrd_set_error("realloc graph_descs"); @@ -2584,7 +2580,7 @@ gdes_alloc(image_desc_t *im){ } - im->gdes[im->gdes_c-1].step=def_step; + im->gdes[im->gdes_c-1].step=im->step; im->gdes[im->gdes_c-1].stack=0; im->gdes[im->gdes_c-1].debug=0; im->gdes[im->gdes_c-1].start=im->start; @@ -3081,6 +3077,7 @@ rrd_graph_options(int argc, char *argv[],image_desc_t *im) im->start = start_tmp; im->end = end_tmp; + im->step = max((long)im->step, (im->end-im->start)/im->xsize); } int diff --git a/src/rrd_graph.h b/src/rrd_graph.h index 607ab70..7cf2a6e 100644 --- a/src/rrd_graph.h +++ b/src/rrd_graph.h @@ -104,6 +104,7 @@ typedef struct graph_desc_t { char ds_nam[DS_NAM_SIZE]; /* data source name */ long ds; /* data source number */ enum cf_en cf; /* consolidation function */ + enum cf_en cf_reduce; /* consolidation function for reduce_data() */ gfx_color_t col; /* graph color */ char format[FMT_LEG_LEN+5]; /* format for PRINT AND GPRINT */ char legend[FMT_LEG_LEN+5]; /* legend*/ diff --git a/src/rrd_graph_helper.c b/src/rrd_graph_helper.c index c359f7a..29bcb5d 100644 --- a/src/rrd_graph_helper.c +++ b/src/rrd_graph_helper.c @@ -13,7 +13,7 @@ int rrd_parse_find_gf (char *, unsigned int *, graph_desc_t *); int rrd_parse_legend (char *, unsigned int *, graph_desc_t *); int rrd_parse_color (char *, graph_desc_t *); -int rrd_parse_CF (char *, unsigned int *, graph_desc_t *); +int rrd_parse_CF (char *, unsigned int *, graph_desc_t *, enum cf_en *); int rrd_parse_print (char *, unsigned int *, graph_desc_t *, image_desc_t *); int rrd_parse_shift (char *, unsigned int *, graph_desc_t *, image_desc_t *); int rrd_parse_xport (char *, unsigned int *, graph_desc_t *, image_desc_t *); @@ -98,7 +98,7 @@ rrd_parse_color(char *string, graph_desc_t *gdp) { } int -rrd_parse_CF(char *line, unsigned int *eaten, graph_desc_t *gdp) { +rrd_parse_CF(char *line, unsigned int *eaten, graph_desc_t *gdp, enum cf_en *cf) { char symname[CF_NAM_SIZE]; int i=0; @@ -110,7 +110,7 @@ rrd_parse_CF(char *line, unsigned int *eaten, graph_desc_t *gdp) { (*eaten)+=i; dprintf("- using CF '%s'\n",symname); - if ((int)(gdp->cf = cf_conv(symname))==-1) { + if ((int)(*cf = cf_conv(symname))==-1) { rrd_set_error("Unknown CF '%s' in '%s'",symname,line); return 1; } @@ -145,7 +145,7 @@ rrd_parse_print(char *line, unsigned int *eaten, graph_desc_t *gdp, image_desc_t case GF_DEF: case GF_CDEF: dprintf("- vname is of type DEF or CDEF, looking for CF\n"); - if (rrd_parse_CF(line,eaten,gdp)) return 1; + if (rrd_parse_CF(line,eaten,gdp,&gdp->cf)) return 1; break; case GF_VDEF: dprintf("- vname is of type VDEF\n"); @@ -307,7 +307,7 @@ rrd_parse_PVHLAST(char *line, unsigned int *eaten, graph_desc_t *gdp, image_desc if (colorfound) { /* no legend if no color */ if (gdp->gf == GF_TICK) { dprintf("- looking for optional number\n"); - sscanf(&line[*eaten],"%lf:%n",&gdp->yrule,&j); + sscanf(&line[*eaten],"%lf%n",&gdp->yrule,&j); if (j) { dprintf("- found number %f\n",gdp->yrule); (*eaten)+=j; @@ -315,6 +315,8 @@ rrd_parse_PVHLAST(char *line, unsigned int *eaten, graph_desc_t *gdp, image_desc rrd_set_error("Tick factor should be <= 1.0"); return 1; } + if (line[*eaten] == ':') + (*eaten)++; } else { dprintf("- not found, defaulting to 0.1\n"); gdp->yrule=0.1; @@ -379,7 +381,7 @@ rrd_parse_vname(char *line, unsigned int *eaten, graph_desc_t *gdp, image_desc_t int rrd_parse_def(char *line, unsigned int *eaten, graph_desc_t *gdp, image_desc_t *im) { int i=0; - char command[6]; /* step, start, end */ + char command[7]; /* step, start, end, reduce */ char tmpstr[256]; struct rrd_time_value start_tv,end_tv; time_t start_tmp=0,end_tmp=0; @@ -411,21 +413,26 @@ rrd_parse_def(char *line, unsigned int *eaten, graph_desc_t *gdp, image_desc_t * (*eaten)+=i; dprintf("- using DS '%s'\n",gdp->ds_nam); - if (rrd_parse_CF(line,eaten,gdp)) return 1; - + if (rrd_parse_CF(line,eaten,gdp,&gdp->cf)) return 1; + gdp->cf_reduce = gdp->cf; + if (line[*eaten]=='\0') return 0; while (1) { dprintf("- optional parameter follows: %s\n", &line[*eaten]); i=0; - sscanf(&line[*eaten], "%5[a-z]=%n", command, &i); + sscanf(&line[*eaten], "%6[a-z]=%n", command, &i); if (!i) { rrd_set_error("Parse error in '%s'",line); return 1; } (*eaten)+=i; dprintf("- processing '%s'\n",command); - if (!strcmp("step",command)) { + if (!strcmp("reduce",command)) { + if (rrd_parse_CF(line,eaten,gdp,&gdp->cf_reduce)) return 1; + if (line[*eaten] != '\0') + (*eaten)--; + } else if (!strcmp("step",command)) { i=0; sscanf(&line[*eaten],"%lu%n",&gdp->step,&i); (*eaten)+=i; diff --git a/src/rrd_resize.c b/src/rrd_resize.c index 3e67af7..6b1648e 100644 --- a/src/rrd_resize.c +++ b/src/rrd_resize.c @@ -170,8 +170,10 @@ rrd_resize(int argc, char **argv) } /* Move the rest of the CDPs */ - while (!(feof(infile))) { - fread(&buffer,sizeof(rrd_value_t),1,infile); + while (1) { + fread(&buffer,sizeof(rrd_value_t),1,infile); + if (feof(infile)) + break; fwrite(&buffer,sizeof(rrd_value_t),1,outfile); } rrdnew.rra_def[target_rra].row_cnt += modify; diff --git a/src/rrd_rpncalc.c b/src/rrd_rpncalc.c index 75c24cf..3cd582b 100644 --- a/src/rrd_rpncalc.c +++ b/src/rrd_rpncalc.c @@ -157,7 +157,7 @@ void rpn_compact2str(rpn_cdefds_t *rpnc,ds_def_t *ds_def,char **str) add_op(OP_SQRT,SQRT) add_op(OP_SORT,SORT) add_op(OP_REV,REV) - + add_op(OP_TREND,TREND) #undef add_op } (*str)[offset] = '\0'; @@ -319,7 +319,7 @@ rpn_parse(void *key_hash,char *expr,long (*lookup)(void *,char*)){ match_op(OP_NEGINF,NEGINF) match_op(OP_NE,NE) match_op(OP_COUNT,COUNT) - match_op_param(OP_PREV_OTHER,PREV) + match_op_param(OP_PREV_OTHER,PREV) match_op(OP_PREV,PREV) match_op(OP_INF,INF) match_op(OP_ISINF,ISINF) @@ -329,6 +329,7 @@ rpn_parse(void *key_hash,char *expr,long (*lookup)(void *,char*)){ match_op(OP_SQRT,SQRT) match_op(OP_SORT,SORT) match_op(OP_REV,REV) + match_op(OP_TREND,TREND) #undef match_op @@ -705,6 +706,29 @@ rpn_calc(rpnp_t *rpnp, rpnstack_t *rpnstack, long data_idx, } } break; + case OP_TREND: + stackunderflow(1); + if ((rpi < 2) || (rpnp[rpi-2].op != OP_VARIABLE)) { + rrd_set_error("malformed trend arguments"); + return -1; + } else { + time_t dur = (time_t)rpnstack -> s[stptr]; + time_t step = (time_t)rpnp[rpi-2].step; + + if (output_idx > (int)ceil((float)dur / (float)step)) { + double accum = 0.0; + int i = 0; + + do { + accum += rpnp[rpi-2].data[rpnp[rpi-2].ds_cnt * i--]; + dur -= step; + } while (dur > 0); + + rpnstack -> s[--stptr] = (accum / -i); + } else + rpnstack -> s[--stptr] = DNAN; + } + break; case OP_END: break; } diff --git a/src/rrd_rpncalc.h b/src/rrd_rpncalc.h index 9fd547a..39909a6 100644 --- a/src/rrd_rpncalc.h +++ b/src/rrd_rpncalc.h @@ -16,7 +16,7 @@ enum op_en {OP_NUMBER=0,OP_VARIABLE,OP_INF,OP_PREV,OP_NEGINF, OP_COS,OP_LOG,OP_EXP,OP_LT,OP_LE,OP_GT,OP_GE,OP_EQ,OP_IF, OP_MIN,OP_MAX,OP_LIMIT, OP_FLOOR, OP_CEIL, OP_UN,OP_END,OP_LTIME,OP_NE,OP_ISINF,OP_PREV_OTHER,OP_COUNT, - OP_ATAN,OP_SQRT,OP_SORT,OP_REV}; + OP_ATAN,OP_SQRT,OP_SORT,OP_REV,OP_TREND}; typedef struct rpnp_t { enum op_en op; diff --git a/src/rrd_xport.c b/src/rrd_xport.c index 95bf35b..3ba1b52 100644 --- a/src/rrd_xport.c +++ b/src/rrd_xport.c @@ -116,7 +116,8 @@ rrd_xport(int argc, char **argv, int *xsize, 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); -- 2.30.2