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