Skip to content

Commit 8e769de

Browse files
authored
Make librrd.c work with RRDD's inotify-based discovery mechanism (#5)
(1) This commit changes behaviour of the library to accommodate RRDD's new plugin discovery mechanism: * The library writes a file of static size and doesn't resize it. The size depends on RRD_MAX_SOURCES and no * The library immediately writes to the file after it opens it such that it contains a valid header, which is picked up by RRDD. * The library removes the file it has written when a plugin is closed. This is picked up by RRDD. (2) Furthermore, the commit contains these general improvements: * Linking the shared library requires zlib. * Check for memory leaks using valgrind as part of CI. * integrate new upstream release of JSON lib parson (3) The interface for clients changed: the sample() function now receives a pointer provided by the client. This makes it easier to write a sample function that is shared by multiple data sources. See the rrdtest.c for an example. Signed-off-by: Christian Lindig <[email protected]>
1 parent db0228e commit 8e769de

22 files changed

+369
-210
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ ocaml/rrdreader.native
66
*.o
77
*.a
88
*.rrd
9+
*.so
910

Makefile

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111

1212
NAME = rrd-client-lib
13-
VERSION = 1.0.0
13+
VERSION = 1.1.0
1414

1515
CC = gcc
1616
CFLAGS = -std=gnu99 -g -fpic -Wall
@@ -36,18 +36,15 @@ clean:
3636
test: rrdtest rrdclient
3737
./rrdtest
3838
seq 1 10 | ./rrdclient rrdclient.rrd
39+
test ! -f rrdclient.rrd
3940

4041
.PHONY: test-integration
4142
test-integration: rrdclient
42-
seq 1 10 | while read i; do \
43-
echo $$i | ./rrdclient rrdclient.rrd ;\
44-
rrdreader file --once rrdclient.rrd v2 ;\
45-
done
46-
seq 1 20 | while read i; do \
47-
echo $$i | ./rrdclient rrdclient.rrd ;\
48-
sleep 4 ;\
49-
done & rrdreader file rrdclient.rrd v2 \
50-
|| echo "a final exception Rrd_protocol.No_update is OK"
43+
seq 1 10 | while read i; do echo $$i ; sleep 4; done \
44+
| ./rrdclient rrdclient.rrd &
45+
rrdreader file rrdclient.rrd v2 \
46+
|| echo "a final exception Rrd_protocol.No_update is OK"
47+
test ! -f rrdclient.rrd
5148

5249
.PHONY: valgrind
5350
valgrind: rrdtest
@@ -70,7 +67,7 @@ librrd.a: $(OBJ)
7067
ranlib $@
7168

7269
librrd.so: $(OBJ)
73-
$(CC) -shared -o $@ $(OBJ)
70+
$(CC) -shared -o $@ $(OBJ) $(LIB)
7471

7572
rrdtest: rrdtest.o librrd.a
7673
$(CC) $(CFLAGS) -o $@ $^ $(LIB)

README.md

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ for a single machine (`RRD_LOCAL_DOMAIN`) or multiple
111111
NULL. If it isn't, it us used to obtain a timestamp instead of using
112112
time(3).
113113

114+
When a plugin is opened, the file at `path` is being created and it is
115+
removed when the plugin is closed.
116+
114117
## Data Sources
115118

116119
A typical client has several data sources. A data source either reports
@@ -139,24 +142,24 @@ dynamically.
139142
int64_t int64;
140143
double float64;
141144
} rrd_value_t;
142-
145+
143146
typedef struct rrd_source {
144147
char *name; /* name of the data source */
145148
char *description; /* for user interface */
146149
char *owner_uuid; /* UUID of the owner or NULL */
147150
char *rrd_units; /* for user interface */
148151
char *min; /* min <= sample() <= max */
149152
char *max; /* min <= sample() <= max */
150-
rrd_value_t(*sample) (void); /* reads value */
153+
rrd_value_t(*sample) (void *userdata); /* reads
154+
* value */
155+
void *userdata; /* passed to sample() */
151156
rrd_owner_t owner;
152157
int32_t rrd_default; /* true: rrd daemon will archive */
153158
rrd_scale_t scale; /* presentation of value */
154159
rrd_type_t type; /* type of value */
155160
} RRD_SOURCE;
156-
157161
typedef struct rrd_plugin RRD_PLUGIN;
158162

159-
160163
<<function declarations>>=
161164
int rrd_add_src(RRD_PLUGIN *plugin, RRD_SOURCE *source);
162165
int rrd_del_src(RRD_PLUGIN *plugin, RRD_SOURCE *source);
@@ -165,14 +168,16 @@ dynamically.
165168
An `RRD_SOURCE` has several descriptive fields for the value it is
166169
reporting. It includes a function (pointer) `sample` that obtains the
167170
value being reported. A value can be either a 64-bit integer or a 64-bit
168-
floating point value -- discriminated by `type`.
171+
floating point value -- discriminated by `type`. Part of an RRD_SOURCE
172+
is a pointer `userdata` that is passed to `sample()`. This allows to
173+
share a single sample function across several RRD_SOURCE values.
169174

170175
## Constants and Error Handling
171176

172177
Some functions return an error code.
173178

174179
<<constants>>=
175-
#define RRD_MAX_SOURCES 128
180+
#define RRD_MAX_SOURCES 16
176181

177182
#define RRD_OK 0
178183
#define RRD_TOO_MANY_SOURCES 1
@@ -191,6 +196,20 @@ is updated. When a data source is added or removed, the existing buffer
191196
containing binary and meta data is invalidated, recomputed and gets
192197
written out.
193198

199+
The design in constrained by the following behavior of the RRD daemon
200+
RRDD:
201+
202+
* RRDD maps an RRD file into memory and does not re-read it if the
203+
file size changes. Therefore the library writes a static size that
204+
depends on `RRD_MAX_SOURCES` and not on the actual number of data
205+
sources being in use.
206+
207+
* RRDD reads an RRD file and expects it have valid content. Hence, the
208+
library can't open the file and write it contents with a delay.
209+
Therefore the library writes an RRD file that indicated that initially
210+
there are no data sources and re-writes the file for each data source
211+
that is added. Checksums avoid other synchronisation problems.
212+
194213
# Data Layout
195214

196215
The data layout is not defined by this library but by the existing

0 commit comments

Comments
 (0)