From 711ea600e6b1bf485b35d592d23f3038cb874a61 Mon Sep 17 00:00:00 2001 From: oetiker Date: Fri, 11 Jun 2010 13:45:15 +0000 Subject: [PATCH] integrated VDEF never patch git-svn-id: svn://svn.oetiker.ch/rrdtool/trunk@2087 a5681a0c-68f1-0310-ab6d-d61299d08faa --- program/NEWS | 3 ++ program/src/rrd_graph.c | 94 +++++++++++++++++++++++++++++++++++++++-- program/src/rrd_graph.h | 7 +++ 3 files changed, 100 insertions(+), 4 deletions(-) diff --git a/program/NEWS b/program/NEWS index af022721..985b7f46 100644 --- a/program/NEWS +++ b/program/NEWS @@ -13,6 +13,9 @@ RRD Graph * RRDcached awareness. Instead of just flushing the file, data can now be pulled in from remote RRDcached instances. +* VDEF results do now explicitly KNOW when they have no time associated + and can behave appropriately. -- Jean-Edouard Babin + RRDcached ---------- * New FETCH command allowing rrd_fetch to operate through the daemon and diff --git a/program/src/rrd_graph.c b/program/src/rrd_graph.c index c6805450..ef51b7c4 100644 --- a/program/src/rrd_graph.c +++ b/program/src/rrd_graph.c @@ -1597,8 +1597,12 @@ int print_calc( if (im->gdes[i].strftm) { prline.u_str = (char*)malloc((FMT_LEG_LEN + 2) * sizeof(char)); - strftime(prline.u_str, - FMT_LEG_LEN, im->gdes[i].format, &tmvdef); + if (im->gdes[vidx].vf.never == 1) { + time_clean(prline.u_str, im->gdes[i].format); + } else { + strftime(prline.u_str, + FMT_LEG_LEN, im->gdes[i].format, &tmvdef); + } } else if (bad_format(im->gdes[i].format)) { rrd_set_error ("bad format for PRINT in '%s'", im->gdes[i].format); @@ -1615,8 +1619,12 @@ int print_calc( /* GF_GPRINT */ if (im->gdes[i].strftm) { - strftime(im->gdes[i].legend, - FMT_LEG_LEN, im->gdes[i].format, &tmvdef); + if (im->gdes[vidx].vf.never == 1) { + time_clean(im->gdes[i].legend, im->gdes[i].format); + } else { + strftime(im->gdes[i].legend, + FMT_LEG_LEN, im->gdes[i].format, &tmvdef); + } } else { if (bad_format(im->gdes[i].format)) { rrd_set_error @@ -4895,6 +4903,7 @@ int vdef_parse( gdes->vf.param = param; gdes->vf.val = DNAN; /* undefined */ gdes->vf.when = 0; /* undefined */ + gdes->vf.never = 1; } else { rrd_set_error ("Parameter '%f' out of range in VDEF '%s'\n", @@ -4916,6 +4925,7 @@ int vdef_parse( gdes->vf.param = DNAN; gdes->vf.val = DNAN; gdes->vf.when = 0; + gdes->vf.never = 1; } else { rrd_set_error ("Function '%s' needs no parameter in VDEF '%s'\n", @@ -4961,6 +4971,7 @@ int vdef_calc( field = round((dst->vf.param * (double)(steps - 1)) / 100.0); dst->vf.val = array[field]; dst->vf.when = 0; /* no time component */ + dst->vf.never = 1; free(array); #if 0 for (step = 0; step < steps; step++) @@ -4994,6 +5005,7 @@ int vdef_calc( field = round( dst->vf.param * (double)(nancount - 1) / 100.0); dst->vf.val = array[field]; dst->vf.when = 0; /* no time component */ + dst->vf.never = 1; free(array); } break; @@ -5004,15 +5016,18 @@ int vdef_calc( if (step == steps) { dst->vf.val = DNAN; dst->vf.when = 0; + dst->vf.never = 1; } else { dst->vf.val = data[step * src->ds_cnt]; dst->vf.when = src->start + (step + 1) * src->step; + dst->vf.never = 0; } while (step != steps) { if (finite(data[step * src->ds_cnt])) { if (data[step * src->ds_cnt] > dst->vf.val) { dst->vf.val = data[step * src->ds_cnt]; dst->vf.when = src->start + (step + 1) * src->step; + dst->vf.never = 0; } } step++; @@ -5035,9 +5050,11 @@ int vdef_calc( if (dst->vf.op == VDEF_TOTAL) { dst->vf.val = sum * src->step; dst->vf.when = 0; /* no time component */ + dst->vf.never = 1; } else if (dst->vf.op == VDEF_AVERAGE) { dst->vf.val = sum / cnt; dst->vf.when = 0; /* no time component */ + dst->vf.never = 1; } else { average = sum / cnt; sum = 0.0; @@ -5048,10 +5065,12 @@ int vdef_calc( } dst->vf.val = pow(sum / cnt, 0.5); dst->vf.when = 0; /* no time component */ + dst->vf.never = 1; }; } else { dst->vf.val = DNAN; dst->vf.when = 0; + dst->vf.never = 1; } } break; @@ -5062,15 +5081,18 @@ int vdef_calc( if (step == steps) { dst->vf.val = DNAN; dst->vf.when = 0; + dst->vf.never = 1; } else { dst->vf.val = data[step * src->ds_cnt]; dst->vf.when = src->start + (step + 1) * src->step; + dst->vf.never = 0; } while (step != steps) { if (finite(data[step * src->ds_cnt])) { if (data[step * src->ds_cnt] < dst->vf.val) { dst->vf.val = data[step * src->ds_cnt]; dst->vf.when = src->start + (step + 1) * src->step; + dst->vf.never = 0; } } step++; @@ -5087,9 +5109,11 @@ int vdef_calc( if (step == steps) { /* all entries were NaN */ dst->vf.val = DNAN; dst->vf.when = 0; + dst->vf.never = 1; } else { dst->vf.val = data[step * src->ds_cnt]; dst->vf.when = src->start + step * src->step; + dst->vf.never = 0; } break; case VDEF_LAST: @@ -5103,9 +5127,11 @@ int vdef_calc( if (step < 0) { /* all entries were NaN */ dst->vf.val = DNAN; dst->vf.when = 0; + dst->vf.never = 1; } else { dst->vf.val = data[step * src->ds_cnt]; dst->vf.when = src->start + (step + 1) * src->step; + dst->vf.never = 0; } break; case VDEF_LSLSLOPE: @@ -5143,16 +5169,20 @@ int vdef_calc( if (dst->vf.op == VDEF_LSLSLOPE) { dst->vf.val = slope; dst->vf.when = 0; + dst->vf.never = 1; } else if (dst->vf.op == VDEF_LSLINT) { dst->vf.val = y_intercept; dst->vf.when = 0; + dst->vf.never = 1; } else if (dst->vf.op == VDEF_LSLCORREL) { dst->vf.val = correl; dst->vf.when = 0; + dst->vf.never = 1; }; } else { dst->vf.val = DNAN; dst->vf.when = 0; + dst->vf.never = 1; } } break; @@ -5201,3 +5231,59 @@ void grinfo_push( im->grinfo = im->grinfo_current; } } + +void time_clean( + char *result, + char *format) +{ + int j, jj; + + jj = 0; + for(j = 0; j < FMT_LEG_LEN - 1; j++) { /* we don't need to parse the last char */ + if (format[j] == '%') { + if ((format[j+1] == 'A') || (format[j+1] == 'a') || + (format[j+1] == 'B') || (format[j+1] == 'b') || + (format[j+1] == 'C') || (format[j+1] == 'c') || + (format[j+1] == 'D') || (format[j+1] == 'd') || + (format[j+1] == 'E') || (format[j+1] == 'e') || + (format[j+1] == 'F') || + (format[j+1] == 'G') || (format[j+1] == 'g') || + (format[j+1] == 'H') || (format[j+1] == 'h') || + (format[j+1] == 'I') || + (format[j+1] == 'j') || + (format[j+1] == 'k') || + (format[j+1] == 'l') || + (format[j+1] == 'M') || (format[j+1] == 'm') || + (format[j+1] == 'O') || + (format[j+1] == 'P') || (format[j+1] == 'p') || + (format[j+1] == 'R') || (format[j+1] == 'r') || + (format[j+1] == 'S') || (format[j+1] == 's') || + (format[j+1] == 'T') || + (format[j+1] == 'U') || (format[j+1] == 'u') || + (format[j+1] == 'V') || (format[j+1] == 'v') || + (format[j+1] == 'W') || (format[j+1] == 'w') || + (format[j+1] == 'X') || (format[j+1] == 'x') || + (format[j+1] == 'Y') || (format[j+1] == 'y') || + (format[j+1] == 'Z') || (format[j+1] == 'z') || + (format[j+1] == '+')) { + result[jj++] = '-'; + j++; /* We skip the following char */ + } else if (format[j+1] == '%') { + result[jj++] = '%'; + j++; /* We skip the following char */ + } else if (format[j+1] == 'n') { + result[jj++] = '\r'; + result[jj++] = '\n'; + j++; /* We skip the following char */ + } else if (format[j+1] == 't') { + result[jj++] = '\t'; + j++; /* We skip the following char */ + } else { + result[jj++] = format[j]; + } + } else { + result[jj++] = format[j]; + } + } + result[jj] = '\0'; /* We must force the end of the string */ +} diff --git a/program/src/rrd_graph.h b/program/src/rrd_graph.h index fa091528..04158152 100644 --- a/program/src/rrd_graph.h +++ b/program/src/rrd_graph.h @@ -112,6 +112,7 @@ typedef struct vdef_t { double param; /* parameter for function, if applicable */ double val; /* resulting value */ time_t when; /* timestamp, if applicable */ + int never; /* boolean, indicate that when value mean never */ } vdef_t; typedef struct xlab_t { @@ -372,6 +373,10 @@ int scan_for_col( void rrd_graph_init( image_desc_t *); +void time_clean( + char *result, + char *format); + void rrd_graph_options( int, char **, @@ -506,3 +511,5 @@ void grinfo_push( image_desc_t *im, char *key, rrd_info_type_t type, rrd_infoval_t value); + + -- 2.30.2