From a834877016ceaec229616e4a529d811fb5e028ac Mon Sep 17 00:00:00 2001 From: oetiker Date: Fri, 5 Jul 2002 18:57:02 +0000 Subject: [PATCH] new operand on rrdgraph CDEFs: PREV(xxxx) -- Gonzalo Augusto Arana Tagle git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk/program@156 a5681a0c-68f1-0310-ab6d-d61299d08faa --- doc/cdeftutorial.pod | 25 +++++++++++++++++++++++++ doc/rrdgraph_rpn.src | 7 +++++++ src/rrd_graph.c | 14 +++++++++----- src/rrd_rpncalc.c | 35 +++++++++++++++++++++++++++++++++-- src/rrd_rpncalc.h | 2 +- 5 files changed, 75 insertions(+), 8 deletions(-) diff --git a/doc/cdeftutorial.pod b/doc/cdeftutorial.pod index fe58063..101f1c9 100644 --- a/doc/cdeftutorial.pod +++ b/doc/cdeftutorial.pod @@ -838,6 +838,31 @@ the other half of your graph. This can be done in a relatively simple way: what you need is the "wipeout" variable and place a negative sign before it: "CDEF:wipeout2=wipeout,-1,*" +=head2 Filtering data + +You may do some complex data filtering: + + MEDIAN FILTER: filters shot noise + + DEF:var=database.rrd:traffic:AVERAGE + CDEF:prev1=PREV(var) + CDEF:prev2=PREV(prev1) + CDEF:prev3=PREV(prev2) + CDEF:median=prev1,prev2,prev3,+,+,3,/ + LINE3:median#000077:filtered + LINE1:prev2#007700:'raw data' + + + DERIVATE: + + DEF:var=database.rrd:traffic:AVERAGE + CDEF:prev1=PREV(var) + CDEF:time=TIME + CDEF:prevtime=PREV(time) + CDEF:derivate=var,prev1,-,time,prevtime,-,/ + LINE3:derivate#000077:derivate + LINE1:var#007700:'raw data' + =head1 Out of ideas for now This document was created from questions asked by either myself or diff --git a/doc/rrdgraph_rpn.src b/doc/rrdgraph_rpn.src index 8b5d49b..a8c4b11 100644 --- a/doc/rrdgraph_rpn.src +++ b/doc/rrdgraph_rpn.src @@ -123,6 +123,13 @@ set or otherwise the result of this B at the previous time step. This allows you to do calculations across the data. This function cannot be used in B instructions. +B + +Pushes an I value if this is the first value of a data +set or otherwise the result of vname variable at the previous time +step. This allows you to do calculations across the data. This +function cannot be used in B instructions. + Z<> =item Time diff --git a/src/rrd_graph.c b/src/rrd_graph.c index 80c4d0f..18be573 100644 --- a/src/rrd_graph.c +++ b/src/rrd_graph.c @@ -853,19 +853,22 @@ data_calc( image_desc_t *im){ * resulting data source. */ for(rpi=0;im->gdes[gdi].rpnp[rpi].op != OP_END;rpi++){ - if(im->gdes[gdi].rpnp[rpi].op == OP_VARIABLE){ + 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; if (im->gdes[ptr].ds_cnt == 0) { #if 0 -printf("DEBUG: inside CDEF '%s' processing VDEF '%s'\n", + printf("DEBUG: inside CDEF '%s' processing VDEF '%s'\n", im->gdes[gdi].vname, im->gdes[ptr].vname); -printf("DEBUG: value from vdef is %f\n",im->gdes[ptr].vf.val); + printf("DEBUG: value from vdef is %f\n",im->gdes[ptr].vf.val); #endif im->gdes[gdi].rpnp[rpi].val = im->gdes[ptr].vf.val; im->gdes[gdi].rpnp[rpi].op = OP_NUMBER; } else { - if ((steparray = rrd_realloc(steparray, (++stepcnt+1)*sizeof(*steparray)))==NULL){ + if ((steparray = + rrd_realloc(steparray, + (++stepcnt+1)*sizeof(*steparray)))==NULL){ rrd_set_error("realloc steparray"); rpnstack_free(&rpnstack); return -1; @@ -904,7 +907,8 @@ printf("DEBUG: value from vdef is %f\n",im->gdes[ptr].vf.val); /* move the data pointers to the correct period */ for(rpi=0;im->gdes[gdi].rpnp[rpi].op != OP_END;rpi++){ - if(im->gdes[gdi].rpnp[rpi].op == OP_VARIABLE){ + 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; if(im->gdes[gdi].start > im->gdes[ptr].start) { im->gdes[gdi].rpnp[rpi].data += im->gdes[gdi].rpnp[rpi].ds_cnt; diff --git a/src/rrd_rpncalc.c b/src/rrd_rpncalc.c index ab2bd36..3c7ccb8 100644 --- a/src/rrd_rpncalc.c +++ b/src/rrd_rpncalc.c @@ -40,7 +40,8 @@ short rpn_compact(rpnp_t *rpnp, rpn_cdefds_t **rpnc, short *count) return -1; } (*rpnc)[i].val = (short) temp; - } else if (rpnp[i].op == OP_VARIABLE) { + } else if (rpnp[i].op == OP_VARIABLE || + rpnp[i].op == OP_PREV_OTHER) { (*rpnc)[i].val = (short) rpnp[i].ptr; } } @@ -63,7 +64,8 @@ rpnp_t * rpn_expand(rpn_cdefds_t *rpnc) rpnp[i].op = (long) rpnc[i].op; if (rpnp[i].op == OP_NUMBER) { rpnp[i].val = (double) rpnc[i].val; - } else if (rpnp[i].op == OP_VARIABLE) { + } else if (rpnp[i].op == OP_VARIABLE || + rpnp[i].op == OP_PREV_OTHER) { rpnp[i].ptr = (long) rpnc[i].val; } } @@ -106,6 +108,12 @@ void rpn_compact2str(rpn_cdefds_t *rpnc,ds_def_t *ds_def,char **str) char *ds_name = ds_def[rpnc[i].val].ds_nam; add_op(OP_VARIABLE, ds_name) } + + if (rpnc[i].op == OP_PREV_OTHER) { + char *ds_name = ds_def[rpnc[i].val].ds_nam; + add_op(OP_VARIABLE, ds_name) + } + #undef add_op #define add_op(VV,VVV) \ @@ -261,6 +269,21 @@ rpn_parse(void *key_hash,char *expr,long (*lookup)(void *,char*)){ expr+=strlen(#VVV); \ } + +#define match_op_param(VV,VVV) \ + else if (sscanf(expr, #VVV "(%[a-z0-9]s)",vname) == 1) { \ + int length = 0; \ + if ((length = strlen(#VVV)+strlen(vname)+2, \ + expr[length] == ',' || expr[length] == '\0') ) { \ + rpnp[steps].op = VV; \ + rpnp[steps].ptr = (*lookup)(key_hash,vname); \ + if (rpnp[steps].ptr < 0) { \ + free(rpnp); \ + return NULL; \ + } else expr+=length; \ + } \ + } + match_op(OP_ADD,+) match_op(OP_SUB,-) match_op(OP_MUL,*) @@ -289,6 +312,7 @@ rpn_parse(void *key_hash,char *expr,long (*lookup)(void *,char*)){ match_op(OP_UN,UN) match_op(OP_NEGINF,NEGINF) match_op(OP_NE,NE) + match_op_param(OP_PREV_OTHER,PREV) match_op(OP_PREV,PREV) match_op(OP_INF,INF) match_op(OP_ISINF,ISINF) @@ -410,6 +434,13 @@ rpn_calc(rpnp_t *rpnp, rpnstack_t *rpnstack, long data_idx, rpnstack -> s[++stptr] = output[output_idx-1]; } break; + case OP_PREV_OTHER: + if ((output_idx-1) <= 0) { + rpnstack -> s[++stptr] = DNAN; + } else { + rpnstack -> s[++stptr] = rpnp[rpnp[rpi].ptr].data[output_idx-1]; + } + break; case OP_UNKN: rpnstack -> s[++stptr] = DNAN; break; diff --git a/src/rrd_rpncalc.h b/src/rrd_rpncalc.h index 4796695..915c949 100644 --- a/src/rrd_rpncalc.h +++ b/src/rrd_rpncalc.h @@ -8,7 +8,7 @@ * This is because COMPUTE (CDEF) DS store OP nodes by number (name is not * an option due to limited par array size). OP nodes must have the same * numeric values, otherwise the stored numbers will mean something different. */ -enum op_en {OP_NUMBER=0,OP_VARIABLE,OP_INF,OP_PREV,OP_NEGINF, +enum op_en {OP_NUMBER=0,OP_VARIABLE,OP_INF,OP_PREV,OP_PREV_OTHER,OP_NEGINF, OP_UNKN,OP_NOW,OP_TIME,OP_ADD,OP_MOD,OP_SUB,OP_MUL, OP_DIV,OP_SIN, OP_DUP, OP_EXC, OP_POP, OP_COS,OP_LOG,OP_EXP,OP_LT,OP_LE,OP_GT,OP_GE,OP_EQ,OP_IF, -- 2.11.0