X-Git-Url: https://git.octo.it/?p=rrdtool.git;a=blobdiff_plain;f=bindings%2Fpython%2Frrdtoolmodule.c;h=aea40f175a9b5660d8b09473b0f460a5bba50233;hp=f5a96d959b74572b301de4b243cc7b51a7023b6a;hb=HEAD;hpb=82d1ca203c32a6b6a093583ef35323f019064fec diff --git a/bindings/python/rrdtoolmodule.c b/bindings/python/rrdtoolmodule.c index f5a96d9..aea40f1 100644 --- a/bindings/python/rrdtoolmodule.c +++ b/bindings/python/rrdtoolmodule.c @@ -37,43 +37,82 @@ # define UNUSED(x) x #endif -static const char *__version__ = "$Revision: 1.14 $"; + +#include "../../rrd_config.h" +static const char *__version__ = PACKAGE_VERSION; #include "Python.h" -#include "rrd.h" -#include "rrd_extra.h" +#include "../../src/rrd_tool.h" +//#include "rrd.h" +//#include "rrd_extra.h" static PyObject *ErrorObject; extern int optind; extern int opterr; /* forward declaration to keep compiler happy */ -/*void initrrdtool(void);*/ -void initrrdtoolmodule(void); - -static int -create_args(char *command, PyObject *args, int *argc, char ***argv) +void initrrdtool( + void); + +static int create_args( + char *command, + PyObject * args, + int *argc, + char ***argv) { - PyObject *o; - int size, i; - - size = PyTuple_Size(args); - *argv = PyMem_New(char *, size + 1); + PyObject *o, *lo; + int args_count, + argv_count, + element_count, + i, j; + + args_count = PyTuple_Size(args); + element_count = 0; + for (i = 0; i < args_count; i++) { + o = PyTuple_GET_ITEM(args, i); + if (PyString_Check(o)) + element_count++; + else if (PyList_CheckExact(o)) + element_count += PyList_Size(o); + else { + PyErr_Format(PyExc_TypeError, "argument %d must be string or list of strings", i); + return -1; + } + } + + *argv = PyMem_New(char *, + element_count + 1); + if (*argv == NULL) return -1; - for (i = 0; i < size; i++) { + argv_count = 0; + for (i = 0; i < args_count; i++) { o = PyTuple_GET_ITEM(args, i); - if (PyString_Check(o)) - (*argv)[i + 1] = PyString_AS_STRING(o); - else { - PyMem_Del(*argv); - PyErr_Format(PyExc_TypeError, "argument %d must be string", i); - return -1; - } + if (PyString_Check(o)) { + argv_count++; + (*argv)[argv_count] = PyString_AS_STRING(o); + } else if (PyList_CheckExact(o)) + for (j = 0; j < PyList_Size(o); j++) { + lo = PyList_GetItem(o, j); + if (PyString_Check(lo)) { + argv_count++; + (*argv)[argv_count] = PyString_AS_STRING(lo); + } else { + PyMem_Del(*argv); + PyErr_Format(PyExc_TypeError, "element %d in argument %d must be string", j, i); + return -1; + } + } + else { + PyMem_Del(*argv); + PyErr_Format(PyExc_TypeError, "argument %d must be string or list of strings", i); + return -1; + } } + (*argv)[0] = command; - *argc = size + 1; + *argc = element_count + 1; /* reset getopt state */ opterr = optind = 0; @@ -81,25 +120,26 @@ create_args(char *command, PyObject *args, int *argc, char ***argv) return 0; } -static void -destroy_args(char ***argv) +static void destroy_args( + char ***argv) { PyMem_Del(*argv); *argv = NULL; } static char PyRRD_create__doc__[] = -"create(args..): Set up a new Round Robin Database\n\ + "create(args..): Set up a new Round Robin Database\n\ create filename [--start|-b start time] \ [--step|-s step] [DS:ds-name:DST:heartbeat:min:max] \ [RRA:CF:xff:steps:rows]"; -static PyObject * -PyRRD_create(PyObject UNUSED(*self), PyObject *args) +static PyObject *PyRRD_create( + PyObject UNUSED(*self), + PyObject * args) { - PyObject *r; - char **argv; - int argc; + PyObject *r; + char **argv; + int argc; if (create_args("create", args, &argc, &argv) < 0) return NULL; @@ -118,16 +158,17 @@ PyRRD_create(PyObject UNUSED(*self), PyObject *args) } static char PyRRD_update__doc__[] = -"update(args..): Store a new set of values into the rrd\n" -" update filename [--template|-t ds-name[:ds-name]...] " -"N|timestamp:value[:value...] [timestamp:value[:value...] ...]"; + "update(args..): Store a new set of values into the rrd\n" + " update filename [--template|-t ds-name[:ds-name]...] " + "N|timestamp:value[:value...] [timestamp:value[:value...] ...]"; -static PyObject * -PyRRD_update(PyObject UNUSED(*self), PyObject *args) +static PyObject *PyRRD_update( + PyObject UNUSED(*self), + PyObject * args) { - PyObject *r; - char **argv; - int argc; + PyObject *r; + char **argv; + int argc; if (create_args("update", args, &argc, &argv) < 0) return NULL; @@ -146,19 +187,20 @@ PyRRD_update(PyObject UNUSED(*self), PyObject *args) } static char PyRRD_fetch__doc__[] = -"fetch(args..): fetch data from an rrd.\n" -" fetch filename CF [--resolution|-r resolution] " -"[--start|-s start] [--end|-e end]"; + "fetch(args..): fetch data from an rrd.\n" + " fetch filename CF [--resolution|-r resolution] " + "[--start|-s start] [--end|-e end]"; -static PyObject * -PyRRD_fetch(PyObject UNUSED(*self), PyObject *args) +static PyObject *PyRRD_fetch( + PyObject UNUSED(*self), + PyObject * args) { - PyObject *r; - rrd_value_t *data, *datai; - unsigned long step, ds_cnt; - time_t start, end; - int argc; - char **argv, **ds_namv; + PyObject *r; + rrd_value_t *data, *datai; + unsigned long step, ds_cnt; + time_t start, end; + int argc; + char **argv, **ds_namv; if (create_args("fetch", args, &argc, &argv) < 0) return NULL; @@ -170,12 +212,12 @@ PyRRD_fetch(PyObject UNUSED(*self), PyObject *args) r = NULL; } else { /* Return : - ((start, end, step), (name1, name2, ...), [(data1, data2, ..), ...]) */ - PyObject *range_tup, *dsnam_tup, *data_list, *t; - unsigned long i, j, row; - rrd_value_t dv; + ((start, end, step), (name1, name2, ...), [(data1, data2, ..), ...]) */ + PyObject *range_tup, *dsnam_tup, *data_list, *t; + unsigned long i, j, row; + rrd_value_t dv; - row = ((end - start) / step + 1); + row = (end - start) / step; r = PyTuple_New(3); range_tup = PyTuple_New(3); @@ -187,14 +229,14 @@ PyRRD_fetch(PyObject UNUSED(*self), PyObject *args) datai = data; - PyTuple_SET_ITEM(range_tup, 0, PyInt_FromLong((long)start)); - PyTuple_SET_ITEM(range_tup, 1, PyInt_FromLong((long)end)); - PyTuple_SET_ITEM(range_tup, 2, PyInt_FromLong((long)step)); + PyTuple_SET_ITEM(range_tup, 0, PyInt_FromLong((long) start)); + PyTuple_SET_ITEM(range_tup, 1, PyInt_FromLong((long) end)); + PyTuple_SET_ITEM(range_tup, 2, PyInt_FromLong((long) step)); for (i = 0; i < ds_cnt; i++) PyTuple_SET_ITEM(dsnam_tup, i, PyString_FromString(ds_namv[i])); - for (i = 0; i < row; i ++) { + for (i = 0; i < row; i++) { t = PyTuple_New(ds_cnt); PyList_SET_ITEM(data_list, i, t); @@ -204,15 +246,15 @@ PyRRD_fetch(PyObject UNUSED(*self), PyObject *args) PyTuple_SET_ITEM(t, j, Py_None); Py_INCREF(Py_None); } else { - PyTuple_SET_ITEM(t, j, PyFloat_FromDouble((double)dv)); + PyTuple_SET_ITEM(t, j, PyFloat_FromDouble((double) dv)); } } } for (i = 0; i < ds_cnt; i++) - free(ds_namv[i]); - free(ds_namv); /* rrdtool don't use PyMem_Malloc :) */ - free(data); + rrd_freemem(ds_namv[i]); + rrd_freemem(ds_namv); /* rrdtool don't use PyMem_Malloc :) */ + rrd_freemem(data); } destroy_args(&argv); @@ -220,60 +262,62 @@ PyRRD_fetch(PyObject UNUSED(*self), PyObject *args) } static char PyRRD_graph__doc__[] = -"graph(args..): Create a graph based on data from one or several RRD\n" -" graph filename [-s|--start seconds] " -"[-e|--end seconds] [-x|--x-grid x-axis grid and label] " -"[-y|--y-grid y-axis grid and label] [--alt-y-grid] [--alt-y-mrtg] " -"[--alt-autoscale] [--alt-autoscale-max] [--units-exponent] value " -"[-v|--vertical-label text] [-w|--width pixels] [-h|--height pixels] " -"[-i|--interlaced] " -"[-f|--imginfo formatstring] [-a|--imgformat GIF|PNG|GD] " -"[-B|--background value] [-O|--overlay value] " -"[-U|--unit value] [-z|--lazy] [-o|--logarithmic] " -"[-u|--upper-limit value] [-l|--lower-limit value] " -"[-g|--no-legend] [-r|--rigid] [--step value] " -"[-b|--base value] [-c|--color COLORTAG#rrggbb] " -"[-t|--title title] [DEF:vname=rrd:ds-name:CF] " -"[CDEF:vname=rpn-expression] [PRINT:vname:CF:format] " -"[GPRINT:vname:CF:format] [COMMENT:text] " -"[HRULE:value#rrggbb[:legend]] [VRULE:time#rrggbb[:legend]] " -"[LINE{1|2|3}:vname[#rrggbb[:legend]]] " -"[AREA:vname[#rrggbb[:legend]]] " -"[STACK:vname[#rrggbb[:legend]]]"; - -static PyObject * -PyRRD_graph(PyObject UNUSED(*self), PyObject *args) + "graph(args..): Create a graph based on data from one or several RRD\n" + " graph filename [-s|--start seconds] " + "[-e|--end seconds] [-x|--x-grid x-axis grid and label] " + "[-y|--y-grid y-axis grid and label] [--alt-y-grid] [--alt-y-mrtg] " + "[--alt-autoscale] [--alt-autoscale-max] [--units-exponent] value " + "[-v|--vertical-label text] [-w|--width pixels] [-h|--height pixels] " + "[-i|--interlaced] " + "[-f|--imginfo formatstring] [-a|--imgformat GIF|PNG|GD] " + "[-B|--background value] [-O|--overlay value] " + "[-U|--unit value] [-z|--lazy] [-o|--logarithmic] " + "[-u|--upper-limit value] [-l|--lower-limit value] " + "[-g|--no-legend] [-r|--rigid] [--step value] " + "[-b|--base value] [-c|--color COLORTAG#rrggbb] " + "[-t|--title title] [DEF:vname=rrd:ds-name:CF] " + "[CDEF:vname=rpn-expression] [PRINT:vname:CF:format] " + "[GPRINT:vname:CF:format] [COMMENT:text] " + "[HRULE:value#rrggbb[:legend]] [VRULE:time#rrggbb[:legend]] " + "[LINE{1|2|3}:vname[#rrggbb[:legend]]] " + "[AREA:vname[#rrggbb[:legend]]] " "[STACK:vname[#rrggbb[:legend]]]"; + +static PyObject *PyRRD_graph( + PyObject UNUSED(*self), + PyObject * args) { - PyObject *r; - char **argv, **calcpr; - int argc, xsize, ysize, i; - double ymin, ymax; + PyObject *r; + char **argv, **calcpr; + int argc, xsize, ysize, i; + double ymin, ymax; + if (create_args("graph", args, &argc, &argv) < 0) return NULL; - if (rrd_graph(argc, argv, &calcpr, &xsize, &ysize, NULL, &ymin, &ymax) == -1) { + if (rrd_graph(argc, argv, &calcpr, &xsize, &ysize, NULL, &ymin, &ymax) == + -1) { PyErr_SetString(ErrorObject, rrd_get_error()); rrd_clear_error(); r = NULL; } else { r = PyTuple_New(3); - PyTuple_SET_ITEM(r, 0, PyInt_FromLong((long)xsize)); - PyTuple_SET_ITEM(r, 1, PyInt_FromLong((long)ysize)); + PyTuple_SET_ITEM(r, 0, PyInt_FromLong((long) xsize)); + PyTuple_SET_ITEM(r, 1, PyInt_FromLong((long) ysize)); if (calcpr) { - PyObject *e, *t; - + PyObject *e, *t; + e = PyList_New(0); PyTuple_SET_ITEM(r, 2, e); - for(i = 0; calcpr[i]; i++) { + for (i = 0; calcpr[i]; i++) { t = PyString_FromString(calcpr[i]); PyList_Append(e, t); Py_DECREF(t); - free(calcpr[i]); + rrd_freemem(calcpr[i]); } - free(calcpr); + rrd_freemem(calcpr); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(r, 2, Py_None); @@ -285,17 +329,18 @@ PyRRD_graph(PyObject UNUSED(*self), PyObject *args) } static char PyRRD_tune__doc__[] = -"tune(args...): Modify some basic properties of a Round Robin Database\n" -" tune filename [--heartbeat|-h ds-name:heartbeat] " -"[--minimum|-i ds-name:min] [--maximum|-a ds-name:max] " -"[--data-source-type|-d ds-name:DST] [--data-source-rename|-r old-name:new-name]"; - -static PyObject * -PyRRD_tune(PyObject UNUSED(*self), PyObject *args) + "tune(args...): Modify some basic properties of a Round Robin Database\n" + " tune filename [--heartbeat|-h ds-name:heartbeat] " + "[--minimum|-i ds-name:min] [--maximum|-a ds-name:max] " + "[--data-source-type|-d ds-name:DST] [--data-source-rename|-r old-name:new-name]"; + +static PyObject *PyRRD_tune( + PyObject UNUSED(*self), + PyObject * args) { - PyObject *r; - char **argv; - int argc; + PyObject *r; + char **argv; + int argc; if (create_args("tune", args, &argc, &argv) < 0) return NULL; @@ -313,15 +358,41 @@ PyRRD_tune(PyObject UNUSED(*self), PyObject *args) return r; } +static char PyRRD_first__doc__[] = + "first(filename): Return the timestamp of the first data sample in an RRD"; + +static PyObject *PyRRD_first( + PyObject UNUSED(*self), + PyObject * args) +{ + PyObject *r; + int argc, ts; + char **argv; + + if (create_args("first", args, &argc, &argv) < 0) + return NULL; + + if ((ts = rrd_first(argc, argv)) == -1) { + PyErr_SetString(ErrorObject, rrd_get_error()); + rrd_clear_error(); + r = NULL; + } else + r = PyInt_FromLong((long) ts); + + destroy_args(&argv); + return r; +} + static char PyRRD_last__doc__[] = -"last(filename): Return the timestamp of the last data sample in an RRD"; + "last(filename): Return the timestamp of the last data sample in an RRD"; -static PyObject * -PyRRD_last(PyObject UNUSED(*self), PyObject *args) +static PyObject *PyRRD_last( + PyObject UNUSED(*self), + PyObject * args) { - PyObject *r; - int argc, ts; - char **argv; + PyObject *r; + int argc, ts; + char **argv; if (create_args("last", args, &argc, &argv) < 0) return NULL; @@ -331,22 +402,23 @@ PyRRD_last(PyObject UNUSED(*self), PyObject *args) rrd_clear_error(); r = NULL; } else - r = PyInt_FromLong((long)ts); + r = PyInt_FromLong((long) ts); destroy_args(&argv); return r; } static char PyRRD_resize__doc__[] = -"resize(args...): alters the size of an RRA.\n" -" resize filename rra-num GROW|SHRINK rows"; + "resize(args...): alters the size of an RRA.\n" + " resize filename rra-num GROW|SHRINK rows"; -static PyObject * -PyRRD_resize(PyObject UNUSED(*self), PyObject *args) +static PyObject *PyRRD_resize( + PyObject UNUSED(*self), + PyObject * args) { - PyObject *r; - char **argv; - int argc, ts; + PyObject *r; + char **argv; + int argc, ts; if (create_args("resize", args, &argc, &argv) < 0) return NULL; @@ -364,106 +436,232 @@ PyRRD_resize(PyObject UNUSED(*self), PyObject *args) return r; } +static PyObject *PyDict_FromInfo( + rrd_info_t * data) +{ + PyObject *r; + + r = PyDict_New(); + while (data) { + PyObject *val = NULL; + + switch (data->type) { + case RD_I_VAL: + val = isnan(data->value.u_val) + ? (Py_INCREF(Py_None), Py_None) + : PyFloat_FromDouble(data->value.u_val); + break; + case RD_I_CNT: + val = PyLong_FromUnsignedLong(data->value.u_cnt); + break; + case RD_I_INT: + val = PyLong_FromLong(data->value.u_int); + break; + case RD_I_STR: + val = PyString_FromString(data->value.u_str); + break; + case RD_I_BLO: + val = + PyString_FromStringAndSize((char *) data->value.u_blo.ptr, + data->value.u_blo.size); + break; + } + if (val) { + PyDict_SetItemString(r, data->key, val); + Py_DECREF(val); + } + data = data->next; + } + return r; +} + static char PyRRD_info__doc__[] = -"info(filename): extract header information from an rrd"; + "info(filename): extract header information from an rrd"; + +static PyObject *PyRRD_info( + PyObject UNUSED(*self), + PyObject * args) +{ + PyObject *r; + int argc; + char **argv; + rrd_info_t *data; + + if (create_args("info", args, &argc, &argv) < 0) + return NULL; -static PyObject * -PyRRD_info(PyObject UNUSED(*self), PyObject *args) + if ((data = rrd_info(argc, argv)) == NULL) { + PyErr_SetString(ErrorObject, rrd_get_error()); + rrd_clear_error(); + r = NULL; + } else { + r = PyDict_FromInfo(data); + rrd_info_free(data); + } + + destroy_args(&argv); + return r; +} + +static char PyRRD_graphv__doc__[] = + "graphv is called in the same manner as graph"; + +static PyObject *PyRRD_graphv( + PyObject UNUSED(*self), + PyObject * args) { - PyObject *r, *t, *ds; - rrd_t rrd; - FILE *in_file; - char *filename; - unsigned long i, j; + PyObject *r; + int argc; + char **argv; + rrd_info_t *data; - if (! PyArg_ParseTuple(args, "s:info", &filename)) + if (create_args("graphv", args, &argc, &argv) < 0) return NULL; - if (rrd_open(filename, &in_file, &rrd, RRD_READONLY) == -1) { + if ((data = rrd_graph_v(argc, argv)) == NULL) { PyErr_SetString(ErrorObject, rrd_get_error()); rrd_clear_error(); + r = NULL; + } else { + r = PyDict_FromInfo(data); + rrd_info_free(data); + } + + destroy_args(&argv); + return r; +} + +static char PyRRD_updatev__doc__[] = + "updatev is called in the same manner as update"; + +static PyObject *PyRRD_updatev( + PyObject UNUSED(*self), + PyObject * args) +{ + PyObject *r; + int argc; + char **argv; + rrd_info_t *data; + + if (create_args("updatev", args, &argc, &argv) < 0) return NULL; + + if ((data = rrd_update_v(argc, argv)) == NULL) { + PyErr_SetString(ErrorObject, rrd_get_error()); + rrd_clear_error(); + r = NULL; + } else { + r = PyDict_FromInfo(data); + rrd_info_free(data); } - fclose(in_file); -#define DICTSET_STR(dict, name, value) \ - t = PyString_FromString(value); \ - PyDict_SetItemString(dict, name, t); \ - Py_DECREF(t); + destroy_args(&argv); + return r; +} -#define DICTSET_CNT(dict, name, value) \ - t = PyInt_FromLong((long)value); \ - PyDict_SetItemString(dict, name, t); \ - Py_DECREF(t); +static char PyRRD_flushcached__doc__[] = + "flush(args..): flush RRD files from memory\n" + " flush [--daemon address] file [file ...]"; -#define DICTSET_VAL(dict, name, value) \ - t = isnan(value) ? (Py_INCREF(Py_None), Py_None) : \ - PyFloat_FromDouble((double)value); \ - PyDict_SetItemString(dict, name, t); \ - Py_DECREF(t); +static PyObject *PyRRD_flushcached( + PyObject UNUSED(*self), + PyObject * args) +{ + PyObject *r; + int argc; + char **argv; - r = PyDict_New(); + if (create_args("flushcached", args, &argc, &argv) < 0) + return NULL; - DICTSET_STR(r, "filename", filename); - DICTSET_STR(r, "rrd_version", rrd.stat_head->version); - DICTSET_CNT(r, "step", rrd.stat_head->pdp_step); - DICTSET_CNT(r, "last_update", rrd.live_head->last_up); - - ds = PyDict_New(); - PyDict_SetItemString(r, "ds", ds); - Py_DECREF(ds); - - for (i = 0; i < rrd.stat_head->ds_cnt; i++) { - PyObject *d; - - d = PyDict_New(); - PyDict_SetItemString(ds, rrd.ds_def[i].ds_nam, d); - Py_DECREF(d); - - DICTSET_STR(d, "ds_name", rrd.ds_def[i].ds_nam); - DICTSET_STR(d, "type", rrd.ds_def[i].dst); - DICTSET_CNT(d, "minimal_heartbeat", rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt); - DICTSET_VAL(d, "min", rrd.ds_def[i].par[DS_min_val].u_val); - DICTSET_VAL(d, "max", rrd.ds_def[i].par[DS_max_val].u_val); - DICTSET_STR(d, "last_ds", rrd.pdp_prep[i].last_ds); - DICTSET_VAL(d, "value", rrd.pdp_prep[i].scratch[PDP_val].u_val); - DICTSET_CNT(d, "unknown_sec", rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt); + if (rrd_flushcached(argc, argv) != 0) { + PyErr_SetString(ErrorObject, rrd_get_error()); + rrd_clear_error(); + r = NULL; + } else { + Py_INCREF(Py_None); + r = Py_None; } - ds = PyList_New(rrd.stat_head->rra_cnt); - PyDict_SetItemString(r, "rra", ds); - Py_DECREF(ds); + destroy_args(&argv); + return r; +} - for (i = 0; i < rrd.stat_head->rra_cnt; i++) { - PyObject *d, *cdp; +static char PyRRD_xport__doc__[] = + "xport(args..): dictionary representation of data stored in RRDs\n" + " [-s|--start seconds] [-e|--end seconds] [-m|--maxrows rows]" + "[--step value] [--daemon address] [DEF:vname=rrd:ds-name:CF]" + "[CDEF:vname=rpn-expression] [XPORT:vname[:legend]]"; - d = PyDict_New(); - PyList_SET_ITEM(ds, i, d); - DICTSET_STR(d, "cf", rrd.rra_def[i].cf_nam); - DICTSET_CNT(d, "rows", rrd.rra_def[i].row_cnt); - DICTSET_CNT(d, "pdp_per_row", rrd.rra_def[i].pdp_cnt); - DICTSET_VAL(d, "xff", rrd.rra_def[i].par[RRA_cdp_xff_val].u_val); +static PyObject *PyRRD_xport( + PyObject UNUSED(*self), + PyObject * args) +{ + PyObject *r; + int argc, xsize; + char **argv, **legend_v; + time_t start, end; + unsigned long step, col_cnt; + rrd_value_t *data, *datai; + + if (create_args("xport", args, &argc, &argv) < 0) + return NULL; - cdp = PyList_New(rrd.stat_head->ds_cnt); - PyDict_SetItemString(d, "cdp_prep", cdp); - Py_DECREF(cdp); + if (rrd_xport(argc, argv, &xsize, &start, &end, + &step, &col_cnt, &legend_v, &data) == -1) { + PyErr_SetString(ErrorObject, rrd_get_error()); + rrd_clear_error(); + r = NULL; + } else { + PyObject *meta_dict, *data_list, *legend_list, *t; + unsigned long i, j; + rrd_value_t dv; + + unsigned long row_cnt = ((end - start) / step) + 1; - for (j = 0; j < rrd.stat_head->ds_cnt; j++) { - PyObject *cdd; + r = PyDict_New(); + meta_dict = PyDict_New(); + legend_list = PyList_New(col_cnt); + data_list = PyList_New(row_cnt); + PyDict_SetItem(r, PyString_FromString("meta"), meta_dict); + PyDict_SetItem(r, PyString_FromString("data"), data_list); - cdd = PyDict_New(); - PyList_SET_ITEM(cdp, j, cdd); + datai = data; + + PyDict_SetItem(meta_dict, PyString_FromString("start"), PyInt_FromLong((long) start)); + PyDict_SetItem(meta_dict, PyString_FromString("end"), PyInt_FromLong((long) end)); + PyDict_SetItem(meta_dict, PyString_FromString("step"), PyInt_FromLong((long) step)); + PyDict_SetItem(meta_dict, PyString_FromString("rows"), PyInt_FromLong((long) row_cnt)); + PyDict_SetItem(meta_dict, PyString_FromString("columns"), PyInt_FromLong((long) col_cnt)); + PyDict_SetItem(meta_dict, PyString_FromString("legend"), legend_list); - DICTSET_VAL(cdd, "value", - rrd.cdp_prep[i*rrd.stat_head->ds_cnt+j].scratch[CDP_val].u_val); - DICTSET_CNT(cdd, "unknown_datapoints", - rrd.cdp_prep[i*rrd.stat_head->ds_cnt+j].scratch[CDP_unkn_pdp_cnt].u_cnt); + for (i = 0; i < col_cnt; i++) { + PyList_SET_ITEM(legend_list, i, PyString_FromString(legend_v[i])); } - } - rrd_free(&rrd); + for (i = 0; i < row_cnt; i++) { + t = PyTuple_New(col_cnt); + PyList_SET_ITEM(data_list, i, t); + for (j = 0; j < col_cnt; j++) { + dv = *(datai++); + if (isnan(dv)) { + PyTuple_SET_ITEM(t, j, Py_None); + Py_INCREF(Py_None); + } else { + PyTuple_SET_ITEM(t, j, PyFloat_FromDouble((double) dv)); + } + } + } + + for (i = 0; i < col_cnt; i++) { + rrd_freemem(legend_v[i]); + } + rrd_freemem(legend_v); + rrd_freemem(data); + } + destroy_args(&argv); return r; } @@ -471,15 +669,20 @@ PyRRD_info(PyObject UNUSED(*self), PyObject *args) #define meth(name, func, doc) {name, (PyCFunction)func, METH_VARARGS, doc} static PyMethodDef _rrdtool_methods[] = { - meth("create", PyRRD_create, PyRRD_create__doc__), - meth("update", PyRRD_update, PyRRD_update__doc__), - meth("fetch", PyRRD_fetch, PyRRD_fetch__doc__), - meth("graph", PyRRD_graph, PyRRD_graph__doc__), - meth("tune", PyRRD_tune, PyRRD_tune__doc__), - meth("last", PyRRD_last, PyRRD_last__doc__), - meth("resize", PyRRD_resize, PyRRD_resize__doc__), - meth("info", PyRRD_info, PyRRD_info__doc__), - {NULL, NULL,0,NULL} + meth("create", PyRRD_create, PyRRD_create__doc__), + meth("update", PyRRD_update, PyRRD_update__doc__), + meth("fetch", PyRRD_fetch, PyRRD_fetch__doc__), + meth("graph", PyRRD_graph, PyRRD_graph__doc__), + meth("tune", PyRRD_tune, PyRRD_tune__doc__), + meth("first", PyRRD_first, PyRRD_first__doc__), + meth("last", PyRRD_last, PyRRD_last__doc__), + meth("resize", PyRRD_resize, PyRRD_resize__doc__), + meth("info", PyRRD_info, PyRRD_info__doc__), + meth("graphv", PyRRD_graphv, PyRRD_graphv__doc__), + meth("updatev", PyRRD_updatev, PyRRD_updatev__doc__), + meth("flushcached", PyRRD_flushcached, PyRRD_flushcached__doc__), + meth("xport", PyRRD_xport, PyRRD_xport__doc__), + {NULL, NULL, 0, NULL} }; #define SET_INTCONSTANT(dict, value) \ @@ -492,20 +695,19 @@ static PyMethodDef _rrdtool_methods[] = { Py_DECREF(t); /* Initialization function for the module */ -void -/*initrrdtool(void)*/ -initrrdtoolmodule(void) +void initrrdtool( + void) { - PyObject *m, *d, *t; + PyObject *m, *d, *t; /* Create the module and add the functions */ - m = Py_InitModule("rrdtoolmodule", _rrdtool_methods); + m = Py_InitModule("rrdtool", _rrdtool_methods); /* Add some symbolic constants to the module */ d = PyModule_GetDict(m); SET_STRCONSTANT(d, __version__); - ErrorObject = PyErr_NewException("rrdtoolmodule.error", NULL, NULL); + ErrorObject = PyErr_NewException("rrdtool.error", NULL, NULL); PyDict_SetItemString(d, "error", ErrorObject); /* Check for errors */