I've been struggling with this for a week now and am hoping someone can point out what I am doing wrong. I'm sure its just a really silly bug in my code, but I can't seem to find it! I would really appreciate any help on this... I'm trying to create a utility library that I can call from other programs to manipulate rrd files.
Context: - using Raspian on a Raspberry Pi - Linux raspberryospi 3.12.20+ #686 PREEMPT Tue May 27 15:48:33 BST 2014 armv6l GNU/Linux - installed rrdtool using apt-get - RRDtool 1.4.7 Copyright 1997-2012 by Tobias Oetiker <[email protected]> Compiled Sep 4 2012 23:43:06 - using rrdtool to graph cpu temperatures - works fine using the command line tools from a shell script - same calls cause rrd file to be corrupted after rrdupdate() command Here's the working shell script, called every 5 minutes via cron: ------------- #!/bin/bash # # update .rrd database with CPU temperature # # This sets up an RRD called temperature.rrd which accepts one temperature value every 300 # seconds. If no new data is supplied for more than 1200 seconds, the temperature becomes # *UNKNOWN*. The minimum and maximum acceptable values are Undefined (U) # # A few archive areas are also defined. The first stores the temperatures supplied for 100 # hours (1'200 * 300 seconds = 100 hours). The second RRA stores the minimum temperature # recorded over every hour (12 * 300 seconds = 1 hour), for 100 days (2'400 hours). The third # and the fourth RRA's do the same for the maximum and average temperature, respectively. # INTERVAL=300 # This script is designed to be called from CRON every INTERVALseconds PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin export PATH cd /home/pi/temperature # create rrd database if not exists [ -f cputemp.rrd ] || { rrdtool create cputemp.rrd --step $INTERVAL \ DS:cputemp:GAUGE:1200:U:U \ RRA:AVERAGE:0.5:1:1200 \ RRA:MIN:0.5:12:2400 \ RRA:MAX:0.5:12:2400 \ RRA:AVERAGE:0.5:12:2400 } # read the temperature and convert “59234″ into “59.234″ (degrees celsius) TEMPERATURE=`cat /sys/class/thermal/thermal_zone0/temp` TEMPERATURE=`echo -n ${TEMPERATURE:0:2}; echo -n .; echo -n ${TEMPERATURE:2}` rrdtool update cputemp.rrd `date +%s`:$TEMPERATURE rrdtool graph cputemp.png DEF:temp=cputemp.rrd:cputemp:AVERAGE LINE2:temp#00FF00 --width 800 --start end-4d --end 00:00 >/dev/null 2>&1 ------------- the above works just fine. Now, here's my C program, which successfully creates the rrd file. I changed the interval to 20 seconds so its easier to test. The problem is that after the first rrd_upate(), which returns OK, the rrd file is corrupted, which causes the next rrd_update() to fail. The rrd_create() is working OK: If i comment out the rrd_update(), and run "rrdtool info" on the rrd file, its fine. What am i doing wrong?? ------------- #include <unistd.h> #include <stdlib.h> #include <time.h> #include <rrd.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include "rrdutil.h" int initRRD(char *rrdfile) { char *createparams[] = { "rrdcreate", rrdfile, "--step", "20", "DS:cputemp:GAUGE:1200:U:U", "RRA:AVERAGE:0.5:1:1200", "RRA:MIN:0.5:12:2400", "RRA:MAX:0.5:12:2400", "RRA:AVERAGE:0.5:12:2400", NULL }; struct stat sb; /* if rrd database file does not exist, then create it */ if (stat(rrdfile, &sb) == -1) { optind = opterr = 0; /* Because rrdtool uses getopt() */ rrd_clear_error(); rrd_create(9, createparams); if (rrd_test_error() != 0) { fprintf(stderr, "rrd_create() failed\n"); return(1); } printf("created rrd database: %s\n", rrdfile); } else { fprintf(stderr, "rrd file %s already exists\n", rrdfile); } return(0); }; int updateRRD(char *rrdfile, char *value) { /* construct time string as secs since 1/1/1970 */ char timestr[30]; time_t t; struct tm *ttm; t = time(NULL); ttm = localtime(&t); strftime(timestr, sizeof(timestr), "%s", ttm); char tbuf[30]; /* rrd needs "time-in-secs:value */ sprintf(tbuf, "%s:%s", timestr, value); printf("updating %s with %s\n", rrdfile, tbuf); char *updateparams[] = { "rrdupdate", rrdfile, tbuf, NULL }; /* update the rrd database with the new reading */ optind = opterr = 0; rrd_clear_error(); rrd_update(3, updateparams); if (rrd_test_error() != 0) { fprintf(stderr, "rrd_update(%s, %s) failed with %s\n", rrdfile, tbuf, rrd_get_error()); return(1); } /* graph the results */ char **calcpr = NULL; int rrdargcount, xsize, ysize, result; double ymin, ymax; char def[100]; sprintf(def, "DEF:temp=%s:cputemp:AVERAGE", rrdfile); char *rrdgraphargs[] = { "rrdgraph", rrdfile, def, "LINE2:temp#00FF00", "--width", "800", "--start", "end-4d", "--end", "00:00", NULL }; optind = opterr = 0; rrd_clear_error(); result = rrd_graph(10, rrdgraphargs, &calcpr, &xsize, &ysize, NULL, &ymin, &ymax); /* Was it OK ? */ if (rrd_test_error() || (result != 0)) { if (calcpr) { int i; for (i=0; (calcpr[i]); i++) free(calcpr[i]); calcpr = NULL; } fprintf(stderr,"Graph error: %s\n", rrd_get_error()); return(2); } return(0); }; #ifdef TEST extern char *optarg; extern int optind, opterr, optopt; int main(int argc, char **argv) { if (argc != 2) { fprintf(stderr, "usage: %s <rrd file path>\n", argv[0]); return(1); } char rrdfile[100]; strncpy(rrdfile, argv[1], sizeof(rrdfile)); if (initRRD(rrdfile) != 0) return(2); /* temperature returned as 5 digits, centigrade, no decimal */ int fd = open("/sys/class/thermal/thermal_zone0/temp", O_RDONLY); if (fd < 0) { fprintf(stderr, "open() of cpu temperature file failed\n"); return(3); } /* optimistic */ char temp[10]; (void) read(fd, temp, sizeof(temp)); (void) close(fd); char tempstr[10]; strncpy(tempstr, temp, 2); tempstr[2]= '.'; strncpy(&tempstr[3], &temp[2], 3); tempstr[6] = 0; if (updateRRD(rrdfile, tempstr) != 0) return(4); return(0); } #endif ---------- Makefile: rrdutil: rrdutil.cpp rrdutil.h gcc -Wno-write-strings -o rrdutil -DTEST -l :librrd.so.4 rrdutil.cpp clean: rm -f rrdutil ---------------- here's the output: pi@raspberryospi ~/temperature $ ./rrdutil fee.rrd created rrd database: fee.rrd updating fee.rrd with 1401552682:55.148 pi@raspberryospi ~/temperature $ ./rrdutil fee.rrd rrd file fee.rrd already exists updating fee.rrd with 1401552704:55.686 rrd_update(fee.rrd, 1401552704:55.686) failed with 'fee.rrd' is not an RRD file --------- _______________________________________________ rrd-users mailing list [email protected] https://lists.oetiker.ch/cgi-bin/listinfo/rrd-users
