Re: Discuss regarding Ticket 263

Jean-Edouard Babin <[email protected]>
Newsgroups gmane.comp.db.rrdtool.devel
Message-ID <[email protected]>
Hi Tobi,

Here is a patch.
I added a int instead of a bool as it seems that int is used for
booleans everywhere in the code.
I called fct1 time_clean. I tried to catch as much formatter as
possible but of course as strftime() formatter's are not the same
depending of OS my code can't handle this very well...
I hope my code is not too much ugly.. I did not practice C for a while.

Best regards,

On Wed, May 19, 2010 at 12:38 AM, Tobias Oetiker <[email protected]> wrote:
> Hi Jean-Edouard,
>
> the when part of the system simply does not make sense all the time
> ... eg for AVERAGE ...
>
> how about having boolean flag in the structure called 'never' when
> this is true your fct1 function would be called ...
>
> cheers
> tobi
>
>
> Today Jean-Edouard Babin wrote:
>
>> Hello,
>>
>> Yesterday I opened a new ticked
>> http://oss.oetiker.ch/rrdtool-trac/ticket/263 because I got a wrong
>> output when printing time of an empty VDEF. (time is 1st Jan 1970)
>> I just find out why, in function vdef_calc of rrd_graph.c, cases
>> (VDEF_MAXIMUM, VDEF_AVERAGE, VDEF_FIRST, ...) set dst->vf.when to 0 if
>> value is unknow (which is my case).
>>
>> I would be happy to try to do a patch, but I would like to discuss how
>> to do it before doing something. (I don't want to do something that
>> will not be commited because it's not a proper solution)
>>
>> vdef struct is currently as follow:
>>
>> typedef struct vdef_t {
>>     enum vdef_op_en op;
>>     double    param;    /* parameter for function, if applicable */
>>     double    val;      /* resulting value */
>>     time_t    when;     /* timestamp, if applicable */
>> } vdef_t;
>>
>> My idea would be to add a new 'isnull' boolean variable to the struct,
>> so that in print_calc I could add some test on isnull be able to run
>> something else that strftime (let's say fct1()) when isnull is true.
>> fct1() would replace each %X values by '-'.
>> So "GPRINT:maxabc2:  Reach 100% @ %c :strftime" would print "Reach
>> 100% @ -", "GPRINT:maxabc2:  Reach 100% @ %Y/%m/%d :strftime" would
>> print "Reach 100% @ -/-/-"
>>
>> Do you have any comments about this idea ?
>>
>> _______________________________________________
>> rrd-developers mailing list
>> [email protected]
>> https://lists.oetiker.ch/cgi-bin/listinfo/rrd-developers
>>
>>
>
> --
> Tobi Oetiker, OETIKER+PARTNER AG, Aarweg 15 CH-4600 Olten, Switzerland
> http://it.oetiker.ch [email protected] ++41 62 775 9902 / sb: -9900
>

-- 
Jean-Edouard Babin

_______________________________________________
rrd-developers mailing list
[email protected]
https://lists.oetiker.ch/cgi-bin/listinfo/rrd-developers
rrdtool_time.patch (application/octet-stream, 9.6 KB)
diff -u rrdtool-1.4.3.org/src/rrd_graph.c rrdtool-1.4.3/src/rrd_graph.c
--- rrdtool-1.4.3.org/src/rrd_graph.c   2010-05-18 23:13:17.000000000 +0200
+++ rrdtool-1.4.3/src/rrd_graph.c       2010-05-19 19:06:14.708422167 +0200
@@ -1590,8 +1590,12 @@
 
                 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);
@@ -1608,8 +1612,12 @@
                 /* 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
@@ -4843,6 +4851,7 @@
             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",
@@ -4864,6 +4873,7 @@
             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",
@@ -4909,6 +4919,7 @@
         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++)
@@ -4942,6 +4953,7 @@
         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;
@@ -4952,15 +4964,18 @@
         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++;
@@ -4983,9 +4998,11 @@
             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;
@@ -4996,10 +5013,12 @@
                 }
                 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;
@@ -5010,15 +5029,18 @@
         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++;
@@ -5034,10 +5056,12 @@
             step++;
         if (step == steps) {    /* all entries were NaN */
             dst->vf.val = DNAN;
-            dst->vf.when = 10;
+            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:
@@ -5051,9 +5075,11 @@
         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:
@@ -5091,16 +5117,20 @@
             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;
@@ -5149,3 +5179,59 @@
         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 -u rrdtool-1.4.3.org/src/rrd_graph.h rrdtool-1.4.3/src/rrd_graph.h
--- rrdtool-1.4.3.org/src/rrd_graph.h   2010-01-20 20:47:04.000000000 +0100
+++ rrdtool-1.4.3/src/rrd_graph.h       2010-05-19 18:57:12.927785718 +0200
@@ -112,6 +112,7 @@
     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 {
@@ -485,3 +486,7 @@
     image_desc_t *im,
     char *key,
     rrd_info_type_t type,    rrd_infoval_t value);
+
+void      time_clean(
+    char *result,
+    char *format);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.