]> git.ipfire.org Git - thirdparty/rrdtool-1.x.git/commitdiff
Add two new data types: DCOUNTER and DDERIVE, which resemble
authorMaksym Sobolyev <sobomax@sippysoft.com>
Tue, 24 Jun 2014 23:20:42 +0000 (16:20 -0700)
committerMaksym Sobolyev <sobomax@sippysoft.com>
Tue, 24 Jun 2014 23:20:42 +0000 (16:20 -0700)
COUNTER and DERIVE, but take double precision floating point
number as an argument. Like it or not, the world as we know it
is not described by integer numbers, not even the real numbers,
it's complex amplitudes, folks. But well, we don't onserve
amplitudes directly, so real numbers are the closest bet that
we have at the moment.

This is still WiP, documentation is coming.

src/rrd_create.c
src/rrd_format.c
src/rrd_format.h
src/rrd_update.c

index 18781fae47aa8cd768199f233601bcff053619ca..6ed740c642f0920e919436e379127074944a8467 100644 (file)
@@ -168,6 +168,8 @@ int parseDS(const char *def,
     case DST_ABSOLUTE:
     case DST_GAUGE:
     case DST_DERIVE:
+    case DST_DCOUNTER:
+    case DST_DDERIVE:
        parseGENERIC_DS(def + offset, ds_def);
        break;
     case DST_CDEF:
index fba9eb0e85a62105cdb9f88a2097bab4b692648a..4e34d63464563aa7edacf98da4b0f8da70f80c71 100644 (file)
@@ -64,6 +64,8 @@ enum dst_en dst_conv(
         converter(GAUGE, DST_GAUGE)
         converter(DERIVE, DST_DERIVE)
         converter(COMPUTE, DST_CDEF)
+        converter(DCOUNTER, DST_DCOUNTER)
+        converter(DDERIVE, DST_DDERIVE)
         rrd_set_error("unknown data acquisition function '%s'", string);
     return (enum dst_en)(-1);
 }
index b526a1448c8da31841dcac40de4b078af4c7d0d3..ac4a864800d61187fc18a2c88789362b206c948f 100644 (file)
@@ -138,7 +138,9 @@ enum dst_en { DST_COUNTER = 0,  /* data source types available */
     DST_ABSOLUTE,
     DST_GAUGE,
     DST_DERIVE,
-    DST_CDEF
+    DST_CDEF,
+    DST_DCOUNTER,
+    DST_DDERIVE
 };
 
 enum ds_param_en { DS_mrhb_cnt = 0, /* minimum required heartbeat. A
index a26005e0e258d2eb17f615c20d928536b08816d0..8cd5e92d2ff75acb757e48e0024d0ee4f9f18f98 100644 (file)
@@ -1348,6 +1348,25 @@ static int get_time_from_reading(
     return 0;
 }
 
+static int
+rrd_get_double(const char *cp, double *rval)
+{
+    char     *endptr;
+
+    errno = 0;
+    *rval = strtod(cp, &endptr);
+    if (errno) {
+        rrd_set_error("converting '%s' to float: %s", cp, rrd_strerror(errno));
+        return -1;
+    }
+    if (endptr[0] != '\0') {
+        rrd_set_error("conversion of '%s' to float not complete: tail '%s'",
+          cp, endptr);
+        return -1;
+    }
+    return 0;
+}
+
 /*
  * Update pdp_new by interpreting the updvals according to the DS type
  * (COUNTER, GAUGE, etc.).
@@ -1362,8 +1381,7 @@ static int update_pdp_prep(
 {
     unsigned long ds_idx;
     int       ii;
-    char     *endptr;   /* used in the conversion */
-    double    rate;
+    double    rate, newval, oldval;
     char     *old_locale;
     enum dst_en dst_idx;
 
@@ -1429,41 +1447,57 @@ static int update_pdp_prep(
                 break;
             case DST_ABSOLUTE:
                old_locale = setlocale(LC_NUMERIC, "C");
-                errno = 0;
-                pdp_new[ds_idx] = strtod(updvals[ds_idx + 1], &endptr);
-                if (errno > 0) {
-                    rrd_set_error("converting '%s' to float: %s",
-                                  updvals[ds_idx + 1], rrd_strerror(errno));
-                    return -1;
-                };
-                setlocale(LC_NUMERIC, old_locale);
-                if (endptr[0] != '\0') {
-                    rrd_set_error
-                        ("conversion of '%s' to float not complete: tail '%s'",
-                         updvals[ds_idx + 1], endptr);
+                if (rrd_get_double(updvals[ds_idx + 1], &newval) != 0) {
+                    setlocale(LC_NUMERIC, old_locale);
                     return -1;
                 }
+                setlocale(LC_NUMERIC, old_locale);
+                pdp_new[ds_idx] = newval;
                 rate = pdp_new[ds_idx] / interval;
                 break;
             case DST_GAUGE:
                old_locale = setlocale(LC_NUMERIC, "C");
-                errno = 0;
-                pdp_new[ds_idx] =
-                    strtod(updvals[ds_idx + 1], &endptr) * interval;
-                if (errno) {
-                    rrd_set_error("converting '%s' to float: %s",
-                                  updvals[ds_idx + 1], rrd_strerror(errno));
-                    return -1;
-                };
-                setlocale(LC_NUMERIC, old_locale);
-                if (endptr[0] != '\0') {
-                    rrd_set_error
-                        ("conversion of '%s' to float not complete: tail '%s'",
-                         updvals[ds_idx + 1], endptr);
+                if (rrd_get_double(updvals[ds_idx + 1], &newval) != 0) {
+                    setlocale(LC_NUMERIC, old_locale);
                     return -1;
                 }
-                rate = pdp_new[ds_idx] / interval;
+                setlocale(LC_NUMERIC, old_locale);
+                pdp_new[ds_idx] = newval * interval;
+                rate = newval;
                 break;
+            case DST_DCOUNTER:
+            case DST_DDERIVE:
+                if (rrd->pdp_prep[ds_idx].last_ds[0] != 'U') {
+                    old_locale = setlocale(LC_NUMERIC, NULL);
+                    setlocale(LC_NUMERIC, "C");
+                    if (rrd_get_double(updvals[ds_idx + 1], &newval) != 0) {
+                        setlocale(LC_NUMERIC, old_locale);
+                        return -1;
+                    }
+                    if (rrd_get_double(rrd->pdp_prep[ds_idx].last_ds, &oldval) != 0) {
+                        setlocale(LC_NUMERIC, old_locale);
+                        return -1;
+                    }
+                    setlocale(LC_NUMERIC, old_locale);
+                    if (dst_idx == DST_DCOUNTER) {
+                        /*
+                         * DST_DCOUNTER is always signed, so it can count either up,
+                         * or down, but not both at the same time. Changing direction
+                         * considered a "reset".
+                         */
+                        if ((newval > 0 && oldval > newval) ||
+                          (newval < 0 && newval > oldval)) {
+                            /* Counter reset detected */
+                            pdp_new[ds_idx] = DNAN;
+                            break;
+                        }
+                    }
+                    pdp_new[ds_idx] = newval - oldval;
+                    rate = pdp_new[ds_idx] / interval;
+                } else {
+                    pdp_new[ds_idx] = DNAN;
+                 }
+                 break;
             default:
                 rrd_set_error("rrd contains unknown DS type : '%s'",
                               rrd->ds_def[ds_idx].dst);