[rrd-developers] Re: Another bug in CVS 12/25/01?

Bertelson, Tom (CAP, CARD) Tom.Bertelson at gecapital.com
Thu Feb 7 19:15:50 MET 2002


> -----Original Message-----
> From: Mike McHenry [mailto:mmchenry at origix.net]
> 
> After doing a little more digging it actually appears as 
> though this bug
> is presenting itself in the RRDs perl module and not the 
> rrdtool binary
> itself. I am digging a little more to see if I can find some more
> information but it appears as though this patch is 
> introducing some sort
> of logic bug in RRDs.so

I've had similar problems.  Everything worked fine on FreeBSD and AIX, but
not Solaris.  My workaround/fix was to cast the expressions to long's for
start_offset and end_offset in rrd_fetch.c.  If it's any help, try running
"gcc -W" (not "-Wall"):

$ cd src
$ make rrd_fetch.o CFLAGS=-W
gcc -DHAVE_CONFIG_H -I. -I. -I../config -I../cgilib-0.4 -I../gd1.3
-I../libpng-1.0.9 -I../zlib-1.1.3    -W -c rrd_fetch.c
rrd_fetch.c: In function `rrd_fetch':
rrd_fetch.c:106: warning: comparison between signed and unsigned
rrd_fetch.c: In function `rrd_fetch_fn':
rrd_fetch.c:153: warning: comparison between signed and unsigned
rrd_fetch.c:167: warning: comparison between signed and unsigned
rrd_fetch.c:235: warning: comparison between signed and unsigned
rrd_fetch.c:276: warning: comparison between signed and unsigned
rrd_fetch.c:300: warning: comparison between signed and unsigned
rrd_fetch.c:301: warning: division: NaN - producing operation
rrd_fetch.c:308: warning: comparison between signed and unsigned
rrd_fetch.c:312: warning: comparison between signed and unsigned
rrd_fetch.c:313: warning: division: NaN - producing operation
rrd_fetch.c:321: warning: comparison between signed and unsigned
rrd_fetch.c:327: warning: comparison between signed and unsigned
rrd_fetch.c:345: warning: comparison between signed and unsigned

I haven't had time to work on it further, but maybe this will help someone
else.
Solaris 2.6, 2.8  gcc 2.95.2, 3.0.1  Sun Workshop compiler 5.??

> I am trying to come up with a simple way to duplicate this problem,
> right now the problem is presenting itself when using a program called
> NMIS. This program it a pretty complex perl script that does all sorts
> of network monitoring on various routers. At certain times the program
> does "threshold" calculations, basically it takes a value from an RRD
> table, compares it to a stored threshold value, and then 
> sends an alarm
> when the RRD table value exceeds the stored threshold value.

Here's a patch I came up to help with troubleshooting.  If you set
$reuse_data to 1, it creates the file "base.dat", which has all the
randomly-generated data.  Useful for re-running the same graphs:

--- perl-shared/t/base.t.orig   Sat Apr  1 10:23:17 2000
+++ perl-shared/t/base.t        Thu Nov 29 12:41:07 2001
@@ -1,6 +1,6 @@
 #! /usr/bin/perl

-BEGIN { $| = 1; print "1..7\n"; }
+BEGIN { $| = 1; print "1..14\n"; }
 END {
   print "not ok 1\n" unless $loaded;
   unlink "demo.rrd";
@@ -33,6 +33,20 @@
 my $GIF1  = "demo1.gif";
 my $GIF2  = "demo2.gif";
 my $time  = 30*int(time/30);
+my @olddata;
+my $reuse_data = 0;
+my $rrddir;
+foreach my $path (qw(../src ../../src)) {
+  $rrddir = $path, last if -x "$path/rrdtool";
+}
+ok("found rrdtool", $rrddir ne "");
+if ($reuse_data and -f "base.dat") {
+  print "do base.dat\n";
+  #do "base.dat";
+  eval `cat base.dat`;
+}
+unlink qw(demo1.rrd demo2.rrd demo1.gif demo2.gif rrddemo.rrd rrddemo.gif);
+my $cmd;
 my $START = $time-$RUNS*$STEP;

 my @options = ("-b", $START, "-s", $STEP,
@@ -45,6 +59,7 @@
  "RRA:AVERAGE:0.5:10:500");

 print "* Creating RRD $RRD1 starting at $time.\n\n";
+#print "RRDs::create \"$RRD1\", \"", join("\", \"", @options), "\";\n";
 RRDs::create $RRD1, @options;

 my $ERROR = RRDs::error;
@@ -62,6 +77,20 @@
   die "$0: unable to create `$RRD2': $ERROR\n";
 }

+my ($sum1, $sum2, @sums);
+my (@args);
+$sum1 = `sum < $RRD1`;
+$sum2 = `sum < $RRD2`;
+ok("empty db compare",$sum1 eq $sum2);                                 #
3.5
+
+$cmd = "$rrddir/rrdtool create rrddemo.rrd '" .
+  join("' \\\n  '", @options) . "'\n";
+print $cmd;
+unlink "rrddemo.rrd";
+system $cmd;
+$sum2 = `sum < rrddemo.rrd`;
+ok("rrdtool create compare", $sum1 eq $sum2);
+
 my $last = RRDs::last $RRD1;
 if ($ERROR = RRDs::error) {
   die "$0: unable to get last `$RRD1': $ERROR\n";
@@ -82,23 +111,45 @@
 @options = ();

 my $counter = 1e7;
-for (my $t=$START+1;
-     $t<$START+$STEP*$RUNS;
-     $t+=$STEP+int((rand()-0.5)*7)){
-  $counter += 2500*sin($t/2000)*$STEP;
-  my $data = (1000+500*sin($t/1000)).":".
-      (1000+900*sin($t/2330)).":".
-      (2000*cos($t/1550)).":".
-      (3220*sin($t/3420)).":$counter";
-  push(@options, "$t:$data");
-  RRDs::update $RRD1, "$t:$data";
-  if ($ERROR = RRDs::error) {
-    warn "$0: unable to update `$RRD1': $ERROR\n";
+if (@olddata) {
+  foreach my $datum (@olddata) {
+    push(@options, "$datum");
+    RRDs::update $RRD1, "$datum";
+    if ($ERROR = RRDs::error) {
+      warn "$0: unable to update `$RRD1': $ERROR\n";
+    }
+  }
+} else {
+  for (my $t=$START+1;
+       $t<$START+$STEP*$RUNS;
+       $t+=$STEP+int((rand()-0.5)*7)){
+    $counter += 2500*sin($t/2000)*$STEP;
+    my $data = (1000+500*sin($t/1000)).":".
+       (1000+900*sin($t/2330)).":".
+       (2000*cos($t/1550)).":".
+       (3220*sin($t/3420)).":$counter";
+    push(@options, "$t:$data");
+    push(@olddata, "$t:$data");
+    RRDs::update $RRD1, "$t:$data";
+    if ($ERROR = RRDs::error) {
+      warn "$0: unable to update `$RRD1': $ERROR\n";
+    }
+  #print "".localtime($t),"   ".$t."   ";
+  #foreach my $val (split(/:/, $data)) {
+  #  if (!defined($val)) {
+  #    print "     *undef*";
+  #  } else {
+  #    printf "%12.1f", $val;
+  #  }
+  #}
+  #print "\n";
+  #print "\n";
   }
 }

 ok("update 1",!$ERROR);
#  3

+#print "RRDs::update \"$RRD1\", \"", join("\", \"", @options), "\";\n";
 RRDs::update $RRD2, @options;

 ok("update 2",!$ERROR);
#  3
@@ -107,15 +158,27 @@
   die "$0: unable to update `$RRD2': $ERROR\n";
 }

+$sum1 = `sum < $RRD1`;
+$sum2 = `sum < $RRD2`;
+ok("populated db compare",$sum1 eq $sum2);                             #
3.5
+
+$cmd = "$rrddir/rrdtool update rrddemo.rrd '" .
+  join("' \\\n  '", @options) . "'\n";
+print $cmd;
+system $cmd;
+$sum2 = `sum < rrddemo.rrd`;
+ok("rrdtool update compare", $sum1 eq $sum2);
+
 print "* Creating $GRUNS graphs: $GIF1 & $GIF2\n\n";
-my $now = $time;
+my $now = $time + 1000;
 for (my $i=0;$i<$GRUNS;$i++) {
   my @rrd_gifs = ($RRD1, $GIF1, $RRD2, $GIF2);
   while (@rrd_gifs) {
     my $RRD = shift(@rrd_gifs);
     my $GIF = shift(@rrd_gifs);
-    my ($graphret,$xs,$ys) = RRDs::graph $GIF, "--title", 'Test GRAPH',
-          "--vertical-label", 'Dummy Units', "--start", (-$RUNS*$STEP),
+    @args = ($GIF, "--title", 'Test GRAPH',
+          "--vertical-label", 'Dummy Units', "--start", ($now-$RUNS*$STEP),
+         "--end", $now,
           "DEF:alpha=$RRD:a:AVERAGE",
           "DEF:beta=$RRD:b:AVERAGE",
           "DEF:gamma=$RRD:c:AVERAGE",
@@ -138,30 +201,58 @@
           "GPRINT:calc:MAX:Max calc %1.2lf",
           "GPRINT:calc:MIN:Min calc %1.2lf",
           "VRULE:".($now-3600)."#008877:60 Minutes ago",
-          "VRULE:".($now-7200)."#008877:120 Minutes ago";
+          "VRULE:".($now-7200)."#008877:120 Minutes ago");
+    print join("\n ", "RRDs::graph", @args) . "\n\n";
+    my ($graphret,$xs,$ys) = RRDs::graph @args;

     if ($ERROR = RRDs::error) {
       print "ERROR: $ERROR\n";
     } else {
-      print "GIF Size: ${xs}x${ys}\n";
-      print "Graph Return:\n",(join "\n", @$graphret),"\n\n";
+      print "${xs}x${ys}\n";
+      print join("\n", @$graphret)."\n\n";
     }
+    push(@sums, `sum < $GIF`);
   }
 }

+$sum1 = shift(@sums);
+my ($x) = scalar grep($_ eq $sum1, @sums);
+ok("gif compare", $x == @sums);
+
+$args[0] = "rrddemo.gif";
+$cmd = "$rrddir/rrdtool graph '" .
+  join("' \\\n  '", @args) . "'\n";
+print $cmd;
+system $cmd;
+$sum2 = `sum < rrddemo.gif`;
+ok("rrdtool graph compare", $sum1 eq $sum2);


-my ($start,$step,$names,$array) = RRDs::fetch $RRD1, "AVERAGE";
+my ($start,$step,$names,$array) = RRDs::fetch $RRD1, "-s", $START, "-e",
$now, "AVERAGE";
 $ERROR = RRDs::error;
 print "ERROR: $ERROR\n" if $ERROR ;
 print "start=$start, step=$step\n";
-print "             ";
+print "                         ";
 map {printf("%12s",$_)} @$names ;
+print "\n";
 foreach my $line (@$array){
   print "".localtime($start),"   ";
   $start += $step;
   foreach my $val (@$line) {
-    printf "%12.1f", $val;
+    if (!defined($val)) {
+      print "     *undef*";
+    } else {
+      printf "%12.1f", $val;
+    }
   }
   print "\n";
+}
+
+$cmd = "$rrddir/rrdtool fetch rrddemo.rrd -s $START -e $now AVERAGE\n";
+print $cmd;
+
+if ($reuse_data and ! -f "base.dat" and open(BD, "> base.dat")) {
+  print BD "\$time = $time;\n";
+  print BD "\@olddata = qw(\n" . join("\n", @olddata) . "\n);\n";
+  close(BD);
 }

> 
> My first inclination is to point my finger at NMIS since it is
> performing the threshold calculations and it appears as though the RRD
> values are correct. However, with the removal of the one line patch I
> posted previously everything works as expected. I am at somewhat of a
> loss as to what is happening here but I will try to come up with some
> more details.

Good luck.  I spent nearly a month tracking my problem down for the Suns.
I hope someone finds an answer.
-- 
Tom Bertelson                "Any sufficient advanced technlogy
GE Card Services              is indistinguishable from magic."
tbertels at iname.com               -- Arthur C. Clarke
 

--
Unsubscribe mailto:rrd-developers-request at list.ee.ethz.ch?subject=unsubscribe
Help        mailto:rrd-developers-request at list.ee.ethz.ch?subject=help
Archive     http://www.ee.ethz.ch/~slist/rrd-developers
WebAdmin    http://www.ee.ethz.ch/~slist/lsg2.cgi



More information about the rrd-developers mailing list