On 10/26/06, Caleb Epstein <[EMAIL PROTECTED]> wrote:
So val.f will be zero when bytes_in < last_bytes_in.  Since these
counters are known to be 32-bit unsigned integers, can't this code do
a better job of calculating diff?  Something like:

OK, see attached patch against 3.0.3.  This seems to fix this overflow
problem here, and it eliminates a *lot* of redundant code from the
Linux version of metrics.c.

--
Caleb Epstein
--- srclib/libmetrics/linux/metrics.c.orig      2006-10-26 10:08:04.562930000 
-0400
+++ srclib/libmetrics/linux/metrics.c   2006-10-26 10:43:12.327831000 -0400
@@ -127,242 +127,106 @@
    return rval;
 }
 
+typedef struct {
+    int stamp;
+    double bytes_in, bytes_out, pkts_in, pkts_out;
+} net_dev_info_t;
+
+static net_dev_info_t last_net_info = { 0, 0, 0, 0, 0 };
+static net_dev_info_t net_info = { 0, 0, 0, 0, 0 };
+static g_val_t bytes_in, pkts_in, bytes_out, pkts_out;
+
 g_val_t
-pkts_in_func ( void )
+calc_rate (double last, double curr, double delta_t)
 {
-   char *p;
-   register int i;
-   static g_val_t val;
-   int size;
-   static int stamp;
-   static double        last_bytes_in,
-                last_bytes_out,
-                last_pkts_in,
-                last_pkts_out;
-   double bytes_in=0, bytes_out=0, pkts_in=0, pkts_out=0, t = 0;
-   double diff;
-   p = update_file(&proc_net_dev);
-   if (proc_net_dev.last_read != stamp) {
-
-     size = ( index (p, 0x00) ) - p;
-   /*  skip past the two-line header ... */
-     p = index (p, '\n')+1;
-     p = index (p, '\n')+1;
-     while (*p != 0x00 )
-       {
-       p = index(p, ':')+1; /*  skip past the interface tag portion of this 
line */
-       if ( (*(p-2) != 'o') && (*(p-3) != 'l') )
-          {
-          t = strtod( p, &p );
-          bytes_in += t;
-          t = strtod( p, &p );
-          pkts_in += t;
-          for (i = 0; i < 6; i++) strtol(p, &p, 10);
-          t = strtod( p, &p );
-          bytes_out += t;
-         pkts_out += strtod( p, &p );
-          }
-          p = index (p, '\n') + 1;    // skips a line
-       }
+    g_val_t rate;
+    double diff = curr - last;
 
-       diff = pkts_in - last_pkts_in;
-       val.f = 0.;
-       if ( diff >= 1. )
-         {
-         t = proc_net_dev.last_read - stamp;
-         val.f = diff / t;
-         }
+    rate.f = 0;
 
-       last_bytes_in  = bytes_in;
-       last_pkts_in = pkts_in;
-       last_pkts_out = pkts_out;
-       last_bytes_out = bytes_out;
+    // 32-bit counter overflow
+    if (diff < 0. && last > 0.)
+        diff += UINT_MAX;
 
-       stamp = proc_net_dev.last_read;
+    if (diff > 1.)
+        rate.f = diff / delta_t;
 
-     }
-   debug_msg(" **********  PKTS_IN RETURN:  %f", val.f);
-   return val;
+    return rate;
 }
 
-g_val_t
-pkts_out_func ( void )
+void
+get_net_info ( void )
 {
-   char *p;
-   register int i;
-   static g_val_t val;
-   int size;
-   static int stamp;
-   static double        last_bytes_in,
-                last_bytes_out,
-                last_pkts_in,
-                last_pkts_out;
-   double bytes_in=0, bytes_out=0, pkts_in=0, pkts_out=0, t = 0;
-   double diff;
-   p = update_file(&proc_net_dev);
-   if (proc_net_dev.last_read != stamp) {
+    char* p;
+    double t;
+    size_t size;
+    int i;
+    
+    p = update_file (&proc_net_dev);
+
+    if (proc_net_dev.last_read != net_info.stamp) {
+        last_net_info = net_info;
+        net_info.stamp = proc_net_dev.last_read;
+        net_info.bytes_in = net_info.bytes_out =
+            net_info.pkts_in = net_info.pkts_out = 0.;
 
      size = ( index (p, 0x00) ) - p;
    /*  skip past the two-line header ... */
      p = index (p, '\n')+1;
      p = index (p, '\n')+1;
-     while (*p != 0x00 )
-       {
+
+        while (*p != 0x00 ) {
        p = index(p, ':')+1; /*  skip past the interface tag portion of this 
line */
-       if ( (*(p-2) != 'o') && (*(p-3) != 'l') )
-          {
+            /* skip loopback interface */
+            if ( (*(p-2) != 'o') && (*(p-3) != 'l') ) {
           t = strtod( p, &p );
-          bytes_in += t;
+                net_info.bytes_in += t;
           t = strtod( p, &p );
-          pkts_in += t;
-          for (i = 0; i < 6; i++) strtol(p, &p, 10);
+                net_info.pkts_in += t;
+                for (i = 0; i < 6; i++)
+                    strtol(p, &p, 10);
           t = strtod( p, &p );
-          bytes_out += t;
-         pkts_out += strtod( p, &p );
+                net_info.bytes_out += t;
+                net_info.pkts_out += strtod( p, &p );
           }
           p = index (p, '\n') + 1;    // skips a line
        }
 
-       diff = pkts_out - last_pkts_out;
-       val.f = 0.;
-       if ( diff >= 1. )
-         {
-         t = proc_net_dev.last_read - stamp;
-         val.f = diff / t;
-         }
-
-       last_bytes_in  = bytes_in;
-       last_pkts_in = pkts_in;
-       last_pkts_out = pkts_out;
-       last_bytes_out = bytes_out;
-
-       stamp = proc_net_dev.last_read;
+        t = net_info.stamp - last_net_info.stamp;
 
+        bytes_in = calc_rate (last_net_info.bytes_in, net_info.bytes_in, t);
+        pkts_in = calc_rate (last_net_info.pkts_in, net_info.pkts_in, t);
+        bytes_out = calc_rate (last_net_info.bytes_out, net_info.bytes_out, t);
+        pkts_out = calc_rate (last_net_info.pkts_out, net_info.pkts_out, t);
      }
-   debug_msg(" **********  PKTS_OUT RETURN:  %f", val.f);
-   return val;
 }
 
 g_val_t
-bytes_out_func ( void )
+pkts_in_func ( void )
 {
-   char *p;
-   register int i;
-   static g_val_t val;
-   int size;
-   static int stamp;
-   static double        last_bytes_in,
-                last_bytes_out,
-                last_pkts_in,
-                last_pkts_out;
-   double bytes_in=0, bytes_out=0, pkts_in=0, pkts_out=0, t = 0;
-   double diff;
-   p = update_file(&proc_net_dev);
-   if (proc_net_dev.last_read != stamp) {
-
-     size = ( index (p, 0x00) ) - p;
-   /*  skip past the two-line header ... */
-     p = index (p, '\n')+1;
-     p = index (p, '\n')+1;
-     while (*p != 0x00 )
-       {
-       p = index(p, ':')+1; /*  skip past the interface tag portion of this 
line */
-       if ( (*(p-2) != 'o') && (*(p-3) != 'l') )
-          {
-          t = strtod( p, &p );
-          bytes_in += t;
-          t = strtod( p, &p );
-          pkts_in += t;
-          for (i = 0; i < 6; i++) strtol(p, &p, 10);
-          /* Fixed 2003 by Dr Michael Wirtz <[EMAIL PROTECTED]>
-            and Phil Radden <[EMAIL PROTECTED]> */
-          t = strtod( p, &p );
-          bytes_out += t;
-         pkts_out += strtod( p, &p );
-          }
-          p = index (p, '\n') + 1;    // skips a line
-       }
-
-       diff = bytes_out - last_bytes_out;
-       val.f = 0.;
-       if ( diff >= 1. )
-         {
-         t = proc_net_dev.last_read - stamp;
-         val.f = diff / t;
-         }
-
-       last_bytes_in  = bytes_in;
-       last_pkts_in = pkts_in;
-       last_pkts_out = pkts_out;
-       last_bytes_out = bytes_out;
+    get_net_info ();
+    return pkts_in;
+}
 
-       stamp = proc_net_dev.last_read;
+g_val_t
+pkts_out_func ( void )
+{
+    get_net_info ();
+    return pkts_out;
+}
 
-     }
-   debug_msg(" **********  BYTES_OUT RETURN:  %f", val.f);
-   return val;
+g_val_t
+bytes_out_func ( void )
+{
+    get_net_info ();
+    return bytes_out;
 }
 
 g_val_t
 bytes_in_func ( void )
 {
-   char *p;
-   register int i;
-   static g_val_t val;
-   int size;
-   static int stamp;
-   static double last_bytes_in,
-     last_bytes_out,
-     last_pkts_in,
-     last_pkts_out;
-   double bytes_in=0, bytes_out=0, pkts_in=0, pkts_out=0, t = 0;
-   double diff;
-   p = update_file(&proc_net_dev);
-   if (proc_net_dev.last_read != stamp) {
-
-     size = ( index (p, 0x00) ) - p;
-   /*  skip past the two-line header ... */
-     p = index (p, '\n')+1;
-     p = index (p, '\n')+1;
-     while (*p != 0x00 )
-       {
-       p = index(p, ':')+1; /*  skip past the interface tag portion of this 
line */
-       debug_msg(" Last two chars: %c%c\n", *p-2, *p-1 );
-       if ( (*(p-2) != 'o') && (*(p-3) != 'l') )
-          {
-          debug_msg(" Last two chars: %c%c\n", *p-2, *p-1 );
-          t = strtod( p, &p );
-          bytes_in += t;
-          t = strtod( p, &p );
-          pkts_in += t;
-          for (i = 0; i < 6; i++) strtol(p, &p, 10);
-          /* Fixed 2003 by Dr Michael Wirtz <[EMAIL PROTECTED]>
-            and Phil Radden <[EMAIL PROTECTED]>. */
-          t = strtod( p, &p );
-          bytes_out += t;
-          pkts_out += strtod( p, &p );
-          }
-          p = index (p, '\n') + 1;    // skips a line
-       }
-
-       diff = bytes_in - last_bytes_in;
-       val.f = 0.;
-       if ( diff >= 1. )
-         {
-         t = proc_net_dev.last_read - stamp;
-         val.f = diff / t;
-         }
-
-       last_bytes_in  = bytes_in;
-       last_pkts_in = pkts_in;
-       last_pkts_out = pkts_out;
-       last_bytes_out = bytes_out;
-
-       stamp = proc_net_dev.last_read;
-
-     }
-   debug_msg(" **********  BYTES_IN RETURN:  %f", val.f);
-   return val;
+    get_net_info ();
+    return bytes_in;
 }
 
 g_val_t

Reply via email to