]> git.ipfire.org Git - thirdparty/rrdtool-1.x.git/commitdiff
rrd_scaled_duration: refactor as utility function
authorPeter A. Bigot <pab@pabigot.com>
Fri, 16 May 2014 15:52:49 +0000 (10:52 -0500)
committerPeter A. Bigot <pab@pabigot.com>
Fri, 16 May 2014 17:11:50 +0000 (12:11 -0500)
Move the infrastructure supporting expression of counts and durations by
suffixed integers into librrd where it can be used by other programs.
Clean up the documentation to remove redundancies.

Signed-off-by: Peter A. Bigot <pab@pabigot.com>
doc/librrd.pod
doc/rrdcreate.pod
src/rrd.h
src/rrd_create.c
src/rrd_utils.c

index 0d05f6eeaa0f8c50b5a6e363299d34828b1a50af..c443386a0ef06ad032e491977ecf2581e6836dcb 100644 (file)
@@ -149,6 +149,81 @@ already exists and is a directory.
 
 =back
 
+=item B<rrd_scaled_duration (const char * token, unsigned long divisor, unsigned long * valuep)>
+
+Parse a token in a context where it contains a count (of seconds or
+PDP instances), or a duration that can be converted to a count by
+representing the duration in seconds and dividing by some scaling
+factor.  For example, if a user would natively express a 3 day archive
+of samples collected every 2 minutes, the sample interval can be
+represented by C<2m> instead of C<120>, and the archive duration by
+C<3d> (to be divided by 120) instead of C<2160> (3*24*60*60 / 120).
+See more examples in L<rrdcreate/"STEP, HEARTBEAT, and Rows As Durations">.
+
+C<token> must be a number with an optional single-character suffix
+encoding the scaling factor:
+
+=over 4
+
+=item C<s>
+
+indicates seconds
+
+=item C<m>
+
+indicates minutes.  The value is multipled by 60.
+
+=item C<h>
+
+indicates hours.  The value is multipled by 3600 (or C<60m>).
+
+=item C<d>
+
+indicates days.  The value is multipled by 86400 (or C<24h>).
+
+=item C<w>
+
+indicates weeks.  The value is multipled by 604800 (or C<7d>).
+
+=item C<M>
+
+indicates months.  The value is multipled by 2678400 (or C<31d>).
+(Note this factor accommodates the maximum number of days in a month.)
+
+=item C<y>
+
+indicates years.  The value is multipled by 31622400 (or C<366d>).
+(Note this factor accommodates leap years.)
+
+=back
+
+C<divisor> is a positive value representing the duration in seconds of
+an interval that the desired result counts.
+
+C<valuep> is a pointer to where the decoded value will be stored if
+the conversion is successful.
+
+The initial characters of C<token> must be the base-10 representation
+of a positive integer, or the conversion fails.
+
+If the remainder C<token> is empty (no suffix), it is a count and no
+scaling is performed.
+
+If C<token> has one of the suffixes above, the count is multipled to
+convert it to a duration in seconds.  The resulting number of seconds
+is divided by C<divisor> to produce a count of intervals each of
+duration C<divisor> seconds.  If division would produce a remainder
+(e.g., C<5m> (300 seconds) divided by C<90s>), the conversion is
+invalid.
+
+If C<token> has unrecognized trailing characters the conversion fails.
+
+The function returns a null pointer if the conversion was successful
+and C<valuep> has been updated to the scaled value.  On failure, it
+returns a text diagnostic suitable for use in user error messages.
+
+= back
+
 =head1 AUTHOR
 
 RRD Contributors <rrd-developers@lists.oetiker.ch>
index 43a8c6e3bece3b855de07ed6acfae13081d3643a..dc3367a83afc93e959a479e4bc504d9891abe16f 100644 (file)
@@ -423,47 +423,14 @@ one day averages.
 
 Step, heartbeat, and PDP counts and rows may also be specified as
 durations, which are positive integers with a single-character suffix
-that specifies a scaling factor:
-
-=over
-
-=item C<s>
-
-indicates seconds
-
-=item C<m>
-
-indicates minutes.  The value is multipled by 60.
-
-=item C<h>
-
-indicates hours.  The value is multipled by 3600 (or C<60m>).
-
-=item C<d>
-
-indicates days.  The value is multipled by 86400 (or C<24h>).
-
-=item C<w>
-
-indicates weeks.  The value is multipled by 604800 (or C<7d>).
-
-=item C<M>
-
-indicates months.  The value is multipled by 2678400 (or C<31d>).
-(Note this factor accommodates the maximum number of days in a month.)
-
-=item C<y>
-
-indicates years.  The value is multipled by 31622400 (or C<366d>).
-(Note this factor accommodates leap years.)
-
-=back
+that specifies a scaling factor.  See L<librrd/rrd_scaled_duration>
+for scale factors of the supported suffixes: C<s> (seconds), C<m>
+(minutes), C<h> (hours), C<d> (days), C<w> (weeks), C<M> (months), and
+C<y> (years).
 
 Scaled step and heartbeat values (which are natively durations in
 seconds) are used directly, while consolidation function row arguments
-are divided by their step to produce the number of rows.  Note that
-the multiplication factors for months and years correspond to the
-maximum number of days in a month or year.
+are divided by their step to produce the number of rows.
 
 With this feature the same specification as above can be written as:
 
index 0a1319bdd8a647e795db7712519dda72c1508778..bf6c889507e650a86fc64cd4d560ed8ac766b3d9 100644 (file)
--- a/src/rrd.h
+++ b/src/rrd.h
@@ -384,6 +384,10 @@ int       rrd_proc_start_end(
 
     int rrd_mkdir_p(const char *pathname, mode_t mode);
 
+    const char * rrd_scaled_duration (const char * token,
+                                      unsigned long divisor,
+                                      unsigned long * valuep);
+
 /*
  * The following functions are _internal_ functions needed to read the raw RRD
  * files. Since they are _internal_ they may change with the file format and
index 16f1658ca9229e29278d83955272bbbdbb87d622..bfc99380e9e6aa0b4e8954430dfe7945080805e0 100644 (file)
@@ -28,56 +28,6 @@ void      parseGENERIC_DS(
     const char *def,
     ds_def_t *ds_def);
 
-static const char * convert_to_count (const char * token,
-                                      unsigned long * valuep,
-                                      unsigned long divisor)
-{
-  char * ep = NULL;
-  unsigned long int value = strtoul(token, &ep, 10);
-  /* account for -1 => UMAXLONG which is not what we want */
-  if (! isdigit(token[0]))
-      return "value must be (suffixed) positive number";
-  /* Catch an internal error before we inhibit scaling */
-  if (0 == divisor)
-      return "INTERNAL ERROR: Zero divisor";
-  switch (*ep) {
-  case 0: /* count only, inhibit scaling */
-      divisor = 0;
-      break;
-  case 's': /* seconds */
-      break;
-  case 'm': /* minutes */
-      value *= 60;
-      break;
-  case 'h': /* hours */
-      value *= 60 * 60;
-      break;
-  case 'd': /* days */
-      value *= 24 * 60 * 60;
-      break;
-  case 'w': /* weeks */
-      value *= 7 * 24 * 60 * 60;
-      break;
-  case 'M': /* months */
-      value *= 31 * 24 * 60 * 60;
-      break;
-  case 'y': /* years */
-      value *= 366 * 24 * 60 * 60;
-      break;
-  default: /* trailing garbage */
-      return "value has trailing garbage";
-  }
-  if (0 == value)
-      return "value must be positive";
-  if ((0 != divisor) && (0 != value)) {
-      if (0 != (value % divisor))
-          return "value would truncate when scaled";
-      value /= divisor;
-  }
-  *valuep = value;
-  return NULL;
-}
-
 int rrd_create(
     int argc,
     char **argv)
@@ -142,7 +92,7 @@ int rrd_create(
             break;
 
         case 's':
-            if ((parsetime_error = convert_to_count(optarg, &pdp_step, 1))) {
+            if ((parsetime_error = rrd_scaled_duration(optarg, 1, &pdp_step))) {
                 rrd_set_error("step size: %s", parsetime_error);
                 return (-1);
             }
@@ -311,7 +261,7 @@ int parseRRA(const char *def,
            case CF_SEASONAL:
            case CF_DEVPREDICT:
            case CF_FAILURES:
-               if ((parsetime_error = convert_to_count(token, &rra_def->row_cnt, rrd->stat_head->pdp_step)))
+               if ((parsetime_error = rrd_scaled_duration(token, rrd->stat_head->pdp_step, &rra_def->row_cnt)))
                    rrd_set_error("Invalid row count %s: %s", token, parsetime_error);
                break;
            default:
@@ -359,7 +309,7 @@ int parseRRA(const char *def,
                    atoi(token) - 1;
                break;
            default:
-               if ((parsetime_error = convert_to_count(token, &rra_def->pdp_cnt, rrd->stat_head->pdp_step)))
+               if ((parsetime_error = rrd_scaled_duration(token, rrd->stat_head->pdp_step, &rra_def->pdp_cnt)))
                    rrd_set_error("Invalid step %s: %s", token, parsetime_error);
                break;
            }
@@ -401,8 +351,9 @@ int parseRRA(const char *def,
                    ("Unexpected extra argument for consolidation function DEVPREDICT");
                break;
            default:
-                if ((parsetime_error = convert_to_count(token, &rra_def->row_cnt,
-                                                        rrd->stat_head->pdp_step * rra_def->pdp_cnt)))
+                if ((parsetime_error = rrd_scaled_duration(token,
+                                                           rrd->stat_head->pdp_step * rra_def->pdp_cnt,
+                                                           &rra_def->row_cnt)))
                    rrd_set_error("Invalid row count %s: %s", token, parsetime_error);
 #if SIZEOF_TIME_T == 4
                if ((long long) pdp_step * rra_def->pdp_cnt * row_cnt > 4294967296LL){
@@ -708,7 +659,7 @@ void parseGENERIC_DS(
         strncpy (numbuf, def, heartbeat_len);
         numbuf[heartbeat_len] = 0;
 
-        if ((parsetime_error = convert_to_count(numbuf, &(ds_def->par[DS_mrhb_cnt].u_cnt), 1)))
+        if ((parsetime_error = rrd_scaled_duration(numbuf, 1, &(ds_def->par[DS_mrhb_cnt].u_cnt))))
             break;
 
         if (sscanf(1+colonp, "%18[^:]:%18[^:]",
index bab9ec8f9904b855fd13fcbe743ac6f1cf007d6e..0ff25f1f134b159ebab12e007d8dc3e39f47a307 100644 (file)
@@ -213,3 +213,53 @@ int rrd_mkdir_p(const char *pathname, mode_t mode)
     return 0;
 } /* rrd_mkdir_p */
 
+const char * rrd_scaled_duration (const char * token,
+                                  unsigned long divisor,
+                                  unsigned long * valuep)
+{
+    char * ep = NULL;
+    unsigned long int value = strtoul(token, &ep, 10);
+    /* account for -1 => UMAXLONG which is not what we want */
+    if (! isdigit(token[0]))
+        return "value must be (suffixed) positive number";
+    /* Catch an internal error before we inhibit scaling */
+    if (0 == divisor)
+        return "INTERNAL ERROR: Zero divisor";
+    switch (*ep) {
+    case 0: /* count only, inhibit scaling */
+        divisor = 0;
+        break;
+    case 's': /* seconds */
+        break;
+    case 'm': /* minutes */
+        value *= 60;
+        break;
+    case 'h': /* hours */
+        value *= 60 * 60;
+        break;
+    case 'd': /* days */
+        value *= 24 * 60 * 60;
+        break;
+    case 'w': /* weeks */
+        value *= 7 * 24 * 60 * 60;
+        break;
+    case 'M': /* months */
+        value *= 31 * 24 * 60 * 60;
+        break;
+    case 'y': /* years */
+        value *= 366 * 24 * 60 * 60;
+        break;
+    default: /* trailing garbage */
+        return "value has trailing garbage";
+    }
+    if (0 == value)
+        return "value must be positive";
+    if ((0 != divisor) && (0 != value)) {
+        if (0 != (value % divisor))
+            return "value would truncate when scaled";
+        value /= divisor;
+    }
+    *valuep = value;
+    return NULL;
+}
+