X-Git-Url: https://git.octo.it/?p=rrdtool.git;a=blobdiff_plain;f=bindings%2Fpython%2Frrdtoolmodule.c;h=aea40f175a9b5660d8b09473b0f460a5bba50233;hp=b3caf192871881dc8d437e2a4cda207c7cb5cfe1;hb=HEAD;hpb=8d278938aef5adefa2915dd446abc028cc764550 diff --git a/bindings/python/rrdtoolmodule.c b/bindings/python/rrdtoolmodule.c index b3caf19..aea40f1 100644 --- a/bindings/python/rrdtoolmodule.c +++ b/bindings/python/rrdtoolmodule.c @@ -37,7 +37,9 @@ # 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 "../../src/rrd_tool.h" @@ -58,28 +60,59 @@ static int create_args( int *argc, char ***argv) { - PyObject *o; - int size, i; - - size = PyTuple_Size(args); + 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 *, - size + 1); + 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; @@ -184,7 +217,7 @@ static PyObject *PyRRD_fetch( 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); @@ -219,9 +252,9 @@ static PyObject *PyRRD_fetch( } 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); @@ -282,9 +315,9 @@ static PyObject *PyRRD_graph( 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); @@ -404,7 +437,7 @@ static PyObject *PyRRD_resize( } static PyObject *PyDict_FromInfo( - rrd_info_t *data) + rrd_info_t * data) { PyObject *r; @@ -435,6 +468,7 @@ static PyObject *PyDict_FromInfo( } if (val) { PyDict_SetItemString(r, data->key, val); + Py_DECREF(val); } data = data->next; } @@ -459,10 +493,13 @@ static PyObject *PyRRD_info( if ((data = rrd_info(argc, argv)) == NULL) { PyErr_SetString(ErrorObject, rrd_get_error()); rrd_clear_error(); - return NULL; + r = NULL; + } else { + r = PyDict_FromInfo(data); + rrd_info_free(data); } - r = PyDict_FromInfo(data); - rrd_info_free(data); + + destroy_args(&argv); return r; } @@ -484,10 +521,13 @@ static PyObject *PyRRD_graphv( if ((data = rrd_graph_v(argc, argv)) == NULL) { PyErr_SetString(ErrorObject, rrd_get_error()); rrd_clear_error(); - return NULL; + r = NULL; + } else { + r = PyDict_FromInfo(data); + rrd_info_free(data); } - r = PyDict_FromInfo(data); - rrd_info_free(data); + + destroy_args(&argv); return r; } @@ -509,10 +549,119 @@ static PyObject *PyRRD_updatev( 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); + } + + destroy_args(&argv); + return r; +} + +static char PyRRD_flushcached__doc__[] = + "flush(args..): flush RRD files from memory\n" + " flush [--daemon address] file [file ...]"; + +static PyObject *PyRRD_flushcached( + PyObject UNUSED(*self), + PyObject * args) +{ + PyObject *r; + int argc; + char **argv; + + if (create_args("flushcached", args, &argc, &argv) < 0) return NULL; + + 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; } - r = PyDict_FromInfo(data); - rrd_info_free(data); + + destroy_args(&argv); + return r; +} + +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]]"; + + +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; + + 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; + + 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); + + 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); + + for (i = 0; i < col_cnt; i++) { + PyList_SET_ITEM(legend_list, i, PyString_FromString(legend_v[i])); + } + + 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; } @@ -531,6 +680,8 @@ static PyMethodDef _rrdtool_methods[] = { 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} };