From: Tobias Oetiker Date: Wed, 28 May 2014 16:46:38 +0000 (+0200) Subject: the beginnings of a callback interface X-Git-Tag: v1.5.0-rc1~76^2~5 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=711f9caa3dffe6d2348d7d69d41e92d983b04086;p=thirdparty%2Frrdtool-1.x.git the beginnings of a callback interface --- diff --git a/bindings/perl-shared/RRDs.pm b/bindings/perl-shared/RRDs.pm index bb7d6bec..74c202df 100644 --- a/bindings/perl-shared/RRDs.pm +++ b/bindings/perl-shared/RRDs.pm @@ -34,6 +34,7 @@ RRDs - Access RRDtool as a shared module RRDs::dump ... RRDs::restore ... RRDs::flushcached ... + RRDs::register_fetch_cb ... $RRDs::VERSION =head1 DESCRIPTION @@ -147,6 +148,45 @@ epoch (1970-01-01) for the supplied "start" and "end" arguments, respectively. See the examples directory for more ways to use this extension. +=head2 Fetch Callback Function + +Normally when using graph, xport or fetch the data you see will come from an +actual rrd file. Some people who like the look of rrd charts, therefore +export their data from a database and then load it into an rrd file just to +be able to call rrdgraph on it. Using a custom callback, you can supply your own +code for handling the data requests from graph, xport and fetch. + +Todo this, you have to first write a fetch function in perl, and then register +this function using C. + +Finally you can use the pseudo path name B[I] to tell +rrdtool to use your callback routine instead of the normal rrdtool fetch function +to organize the data required. + +The callback function must look like this: + + sub fetch_callback { + my $args_hash = shift; + # { + # filename => 'cb//somefilename', + # cd => 'AVERAGE', + # start => 1401295291, + # end => 1401295591, + # step => 300 } + + # do some clever thing to get that data ready + + return { + start => $unix_timestamp, + step => $step_width, + data => { + dsName1 => [ value1, value2, ... ], + dsName2 => [ value1, value2, ... ], + dsName3 => [ value1, value2, ... ], + } + }; + } + =head1 NOTE If you are manipulating the TZ variable you should also call the POSIX diff --git a/src/Makefile.am b/src/Makefile.am index 974b9cbd..4f68b238 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -44,6 +44,7 @@ RRD_C_FILES = \ rrd_dump.c \ rrd_flushcached.c \ rrd_fetch.c \ + rrd_fetch_cb.c \ rrd_resize.c \ rrd_tune.c \ rrd_modify.c diff --git a/src/librrd.sym.in.in b/src/librrd.sym.in.in index a0e0e7b5..ba497595 100644 --- a/src/librrd.sym.in.in +++ b/src/librrd.sym.in.in @@ -13,6 +13,7 @@ rrd_dump_r rrd_dump_cb_r rrd_fetch rrd_fetch_r +rrd_fetch_cb_register rrd_flushcached rrd_first rrd_first_r diff --git a/src/rrd_fetch.c b/src/rrd_fetch.c index af74a2f6..45e2a09e 100644 --- a/src/rrd_fetch.c +++ b/src/rrd_fetch.c @@ -292,6 +292,9 @@ int rrd_fetch_fn( return rrd_fetch_fn_libdbi(filename,cf_idx,start,end,step,ds_cnt,ds_namv,data); } #endif + if (strncmp("cb//",filename,5)==0) { + return rrd_fetch_fn_cb(filename,cf_idx,start,end,step,ds_cnt,ds_namv,data); + } rrd_init(&rrd); rrd_file = rrd_open(filename, &rrd, RRD_READONLY); diff --git a/src/rrd_fetch_cb.c b/src/rrd_fetch_cb.c new file mode 100644 index 00000000..b7dde7e0 --- /dev/null +++ b/src/rrd_fetch_cb.c @@ -0,0 +1,35 @@ +#include "rrd_tool.h" +#include "unused.h" +#include + + +static rrd_fetch_cb_t callback = NULL; + +int rrd_fetch_cb_register(rrd_fetch_cb_t cb){ + callback = cb; + /* if we find a way to figure out of cb provided is to our + liking or not, we could return 0 if there is a problem */ + return 1; +} + +int +rrd_fetch_fn_cb( + const char *filename, /* name of the rrd */ + enum cf_en cf_idx, /* consolidation function */ + time_t *start, + time_t *end, /* which time frame do you want ? + * will be changed to represent reality */ + unsigned long *step, /* which stepsize do you want? + * will be changed to represent reality */ + unsigned long *ds_cnt, /* number of data sources in file */ + char ***ds_namv, /* names of data_sources */ + rrd_value_t **data) /* two dimensional array containing the data */ +{ + if (callback){ + return callback(filename,cf_idx,start,end,step,ds_cnt,ds_namv,data); + } + else { + rrd_set_error("use rrd_fetch_cb_register to register your callback prior to calling rrd_fetch_fn_cb"); + return -1; + } +} diff --git a/src/rrd_tool.h b/src/rrd_tool.h index d772d07f..dfe8e6ed 100644 --- a/src/rrd_tool.h +++ b/src/rrd_tool.h @@ -100,7 +100,7 @@ extern "C" { #ifdef HAVE_LIBDBI -int rrd_fetch_fn_libdbi(const char *filename, enum cf_en cf_idx, + int rrd_fetch_fn_libdbi(const char *filename, enum cf_en cf_idx, time_t *start,time_t *end, unsigned long *step, unsigned long *ds_cnt, @@ -108,6 +108,30 @@ int rrd_fetch_fn_libdbi(const char *filename, enum cf_en cf_idx, rrd_value_t **data); #endif +typedef int (*rrd_fetch_cb_t)( + const char *filename, /* name of the rrd */ + enum cf_en cf_idx, /* consolidation function */ + time_t *start, + time_t *end, /* which time frame do you want ? + * will be changed to represent reality */ + unsigned long *step, /* which stepsize do you want? + * will be changed to represent reality */ + unsigned long *ds_cnt, /* number of data sources in file */ + char ***ds_namv, /* names of data_sources */ + rrd_value_t **data /* two dimensional array containing the data */ +); + + + int rrd_fetch_fn_cb(const char *filename, enum cf_en cf_idx, + time_t *start,time_t *end, + unsigned long *step, + unsigned long *ds_cnt, + char ***ds_namv, + rrd_value_t **data); + + int rrd_fetch_cb_register(rrd_fetch_cb_t cb); + + #define RRD_READONLY (1<<0) #define RRD_READWRITE (1<<1) #define RRD_CREAT (1<<2)