diff -Naur rrdtool-1.2.13.orig/bindings/python/Makefile.am rrdtool-1.2.13/bindings/python/Makefile.am --- rrdtool-1.2.13.orig/bindings/python/Makefile.am 2006-05-04 15:26:28.000000000 +0200 +++ rrdtool-1.2.13/bindings/python/Makefile.am 2006-07-15 08:51:24.000000000 +0200 @@ -2,11 +2,11 @@ #pythondir = $(pyexecdir)/python@PYTHON_VERSION@/site-packages -python_PROGRAMS = rrdtoolmodule.so +python_PROGRAMS = rrdtool.so -rrdtoolmodule_so_LDFLAGS = -module -shared -rrdtoolmodule_so_LDADD = $(top_builddir)/src/librrd.la -rrdtoolmodule_so_SOURCES = rrdtoolmodule.c +rrdtool_so_LDFLAGS = -module -shared +rrdtool_so_LDADD = $(top_builddir)/src/librrd.la +rrdtool_so_SOURCES = rrdtool.c noinst_HEADERS = rrd_extra.h diff -Naur rrdtool-1.2.13.orig/bindings/python/Makefile.in rrdtool-1.2.13/bindings/python/Makefile.in --- rrdtool-1.2.13.orig/bindings/python/Makefile.in 2006-05-04 15:27:59.000000000 +0200 +++ rrdtool-1.2.13/bindings/python/Makefile.in 2006-07-15 08:52:03.000000000 +0200 @@ -15,7 +15,7 @@ @SET_MAKE@ -SOURCES = $(rrdtoolmodule_so_SOURCES) +SOURCES = $(rrdtool_so_SOURCES) srcdir = @srcdir@ top_srcdir = @top_srcdir@ @@ -40,7 +40,7 @@ build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ -python_PROGRAMS = rrdtoolmodule.so$(EXEEXT) +python_PROGRAMS = rrdtool.so$(EXEEXT) subdir = bindings/python DIST_COMMON = README $(noinst_HEADERS) $(srcdir)/Makefile.am \ $(srcdir)/Makefile.in AUTHORS COPYING @@ -55,9 +55,9 @@ am__installdirs = "$(DESTDIR)$(pythondir)" pythonPROGRAMS_INSTALL = $(INSTALL_PROGRAM) PROGRAMS = $(python_PROGRAMS) -am_rrdtoolmodule_so_OBJECTS = rrdtoolmodule.$(OBJEXT) -rrdtoolmodule_so_OBJECTS = $(am_rrdtoolmodule_so_OBJECTS) -rrdtoolmodule_so_DEPENDENCIES = $(top_builddir)/src/librrd.la +am_rrdtool_so_OBJECTS = rrdtool.$(OBJEXT) +rrdtool_so_OBJECTS = $(am_rrdtool_so_OBJECTS) +rrdtool_so_DEPENDENCIES = $(top_builddir)/src/librrd.la DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp am__depfiles_maybe = depfiles @@ -69,8 +69,8 @@ CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ -SOURCES = $(rrdtoolmodule_so_SOURCES) -DIST_SOURCES = $(rrdtoolmodule_so_SOURCES) +SOURCES = $(rrdtool_so_SOURCES) +DIST_SOURCES = $(rrdtool_so_SOURCES) HEADERS = $(noinst_HEADERS) ETAGS = etags CTAGS = ctags @@ -228,9 +228,9 @@ target_os = @target_os@ target_vendor = @target_vendor@ AM_CPPFLAGS = @CFLAGS@ -I$(top_srcdir)/src @PYTHON_INCLUDES@ -rrdtoolmodule_so_LDFLAGS = -module -shared -rrdtoolmodule_so_LDADD = $(top_builddir)/src/librrd.la -rrdtoolmodule_so_SOURCES = rrdtoolmodule.c +rrdtool_so_LDFLAGS = -module -shared +rrdtool_so_LDADD = $(top_builddir)/src/librrd.la +rrdtool_so_SOURCES = rrdtool.c noinst_HEADERS = rrd_extra.h all: all-am @@ -293,9 +293,9 @@ echo " rm -f $$p $$f"; \ rm -f $$p $$f ; \ done -rrdtoolmodule.so$(EXEEXT): $(rrdtoolmodule_so_OBJECTS) $(rrdtoolmodule_so_DEPENDENCIES) - @rm -f rrdtoolmodule.so$(EXEEXT) - $(LINK) $(rrdtoolmodule_so_LDFLAGS) $(rrdtoolmodule_so_OBJECTS) $(rrdtoolmodule_so_LDADD) $(LIBS) +rrdtool.so$(EXEEXT): $(rrdtool_so_OBJECTS) $(rrdtool_so_DEPENDENCIES) + @rm -f rrdtool.so$(EXEEXT) + $(LINK) $(rrdtool_so_LDFLAGS) $(rrdtool_so_OBJECTS) $(rrdtool_so_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -303,7 +303,7 @@ distclean-compile: -rm -f *.tab.c -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdtoolmodule.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rrdtool.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ diff -Naur rrdtool-1.2.13.orig/bindings/python/rrdtool.c rrdtool-1.2.13/bindings/python/rrdtool.c --- rrdtool-1.2.13.orig/bindings/python/rrdtool.c 1970-01-01 01:00:00.000000000 +0100 +++ rrdtool-1.2.13/bindings/python/rrdtool.c 2006-05-04 15:26:28.000000000 +0200 @@ -0,0 +1,517 @@ +/* + * rrdtoolmodule.c + * + * RRDTool Python binding + * + * Author : Hye-Shik Chang + * Date : $Date: 2003/02/22 07:41:19 $ + * Created : 23 May 2002 + * + * $Revision: 1.14 $ + * + * ========================================================================== + * This file is part of py-rrdtool. + * + * py-rrdtool is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * py-rrdtool is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Foobar; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#ifdef UNUSED +#elif defined(__GNUC__) +# define UNUSED(x) x __attribute__((unused)) +#elif defined(__LCLINT__) +# define UNUSED(x) /*@unused@*/ x +#else +# define UNUSED(x) x +#endif + +static const char *__version__ = "$Revision: 1.14 $"; + +#include "Python.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); + +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); + if (*argv == NULL) + return -1; + + for (i = 0; i < size; 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; + } + } + (*argv)[0] = command; + *argc = size + 1; + + /* reset getopt state */ + opterr = optind = 0; + + return 0; +} + +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 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) +{ + PyObject *r; + char **argv; + int argc; + + if (create_args("create", args, &argc, &argv) < 0) + return NULL; + + if (rrd_create(argc, argv) == -1) { + PyErr_SetString(ErrorObject, rrd_get_error()); + rrd_clear_error(); + r = NULL; + } else { + Py_INCREF(Py_None); + r = Py_None; + } + + destroy_args(&argv); + return r; +} + +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...] ...]"; + +static PyObject * +PyRRD_update(PyObject UNUSED(*self), PyObject *args) +{ + PyObject *r; + char **argv; + int argc; + + if (create_args("update", args, &argc, &argv) < 0) + return NULL; + + if (rrd_update(argc, argv) == -1) { + PyErr_SetString(ErrorObject, rrd_get_error()); + rrd_clear_error(); + r = NULL; + } else { + Py_INCREF(Py_None); + r = Py_None; + } + + destroy_args(&argv); + return r; +} + +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]"; + +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; + + if (create_args("fetch", args, &argc, &argv) < 0) + return NULL; + + if (rrd_fetch(argc, argv, &start, &end, &step, + &ds_cnt, &ds_namv, &data) == -1) { + PyErr_SetString(ErrorObject, rrd_get_error()); + rrd_clear_error(); + 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; + + row = ((end - start) / step + 1); + + r = PyTuple_New(3); + range_tup = PyTuple_New(3); + dsnam_tup = PyTuple_New(ds_cnt); + data_list = PyList_New(row); + PyTuple_SET_ITEM(r, 0, range_tup); + PyTuple_SET_ITEM(r, 1, dsnam_tup); + PyTuple_SET_ITEM(r, 2, data_list); + + 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)); + + for (i = 0; i < ds_cnt; i++) + PyTuple_SET_ITEM(dsnam_tup, i, PyString_FromString(ds_namv[i])); + + for (i = 0; i < row; i ++) { + t = PyTuple_New(ds_cnt); + PyList_SET_ITEM(data_list, i, t); + + for (j = 0; j < ds_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 < ds_cnt; i++) + free(ds_namv[i]); + free(ds_namv); /* rrdtool don't use PyMem_Malloc :) */ + free(data); + } + + destroy_args(&argv); + return r; +} + +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) +{ + 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) { + 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)); + + if (calcpr) { + PyObject *e, *t; + + e = PyList_New(0); + PyTuple_SET_ITEM(r, 2, e); + + for(i = 0; calcpr[i]; i++) { + t = PyString_FromString(calcpr[i]); + PyList_Append(e, t); + Py_DECREF(t); + free(calcpr[i]); + } + free(calcpr); + } else { + Py_INCREF(Py_None); + PyTuple_SET_ITEM(r, 2, Py_None); + } + } + + destroy_args(&argv); + return r; +} + +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) +{ + PyObject *r; + char **argv; + int argc; + + if (create_args("tune", args, &argc, &argv) < 0) + return NULL; + + if (rrd_tune(argc, argv) == -1) { + PyErr_SetString(ErrorObject, rrd_get_error()); + rrd_clear_error(); + r = NULL; + } else { + Py_INCREF(Py_None); + r = Py_None; + } + + destroy_args(&argv); + return r; +} + +static char PyRRD_last__doc__[] = +"last(filename): Return the timestamp of the last data sample in an RRD"; + +static PyObject * +PyRRD_last(PyObject UNUSED(*self), PyObject *args) +{ + PyObject *r; + int argc, ts; + char **argv; + + if (create_args("last", args, &argc, &argv) < 0) + return NULL; + + if ((ts = rrd_last(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_resize__doc__[] = +"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) +{ + PyObject *r; + char **argv; + int argc, ts; + + if (create_args("resize", args, &argc, &argv) < 0) + return NULL; + + if ((ts = rrd_resize(argc, argv)) == -1) { + PyErr_SetString(ErrorObject, rrd_get_error()); + rrd_clear_error(); + r = NULL; + } else { + Py_INCREF(Py_None); + r = Py_None; + } + + destroy_args(&argv); + return r; +} + +static char PyRRD_info__doc__[] = +"info(filename): extract header information from an rrd"; + +static PyObject * +PyRRD_info(PyObject UNUSED(*self), PyObject *args) +{ + PyObject *r, *t, *ds; + rrd_t rrd; + FILE *in_file; + char *filename; + unsigned long i, j; + + if (! PyArg_ParseTuple(args, "s:info", &filename)) + return NULL; + + if (rrd_open(filename, &in_file, &rrd, RRD_READONLY) == -1) { + PyErr_SetString(ErrorObject, rrd_get_error()); + rrd_clear_error(); + return NULL; + } + fclose(in_file); + +#define DICTSET_STR(dict, name, value) \ + t = PyString_FromString(value); \ + PyDict_SetItemString(dict, name, t); \ + Py_DECREF(t); + +#define DICTSET_CNT(dict, name, value) \ + t = PyInt_FromLong((long)value); \ + PyDict_SetItemString(dict, name, t); \ + Py_DECREF(t); + +#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); + + r = PyDict_New(); + + 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); + } + + ds = PyList_New(rrd.stat_head->rra_cnt); + PyDict_SetItemString(r, "rra", ds); + Py_DECREF(ds); + + for (i = 0; i < rrd.stat_head->rra_cnt; i++) { + PyObject *d, *cdp; + + 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); + + cdp = PyList_New(rrd.stat_head->ds_cnt); + PyDict_SetItemString(d, "cdp_prep", cdp); + Py_DECREF(cdp); + + for (j = 0; j < rrd.stat_head->ds_cnt; j++) { + PyObject *cdd; + + cdd = PyDict_New(); + PyList_SET_ITEM(cdp, j, cdd); + + 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); + } + } + + rrd_free(&rrd); + + return r; +} + +/* List of methods defined in the module */ +#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} +}; + +#define SET_INTCONSTANT(dict, value) \ + t = PyInt_FromLong((long)value); \ + PyDict_SetItemString(dict, #value, t); \ + Py_DECREF(t); +#define SET_STRCONSTANT(dict, value) \ + t = PyString_FromString(value); \ + PyDict_SetItemString(dict, #value, t); \ + Py_DECREF(t); + +/* Initialization function for the module */ +void +initrrdtool(void) +{ + PyObject *m, *d, *t; + + /* Create the module and add the functions */ + m = Py_InitModule("rrdtool", _rrdtool_methods); + + /* Add some symbolic constants to the module */ + d = PyModule_GetDict(m); + + SET_STRCONSTANT(d, __version__); + ErrorObject = PyErr_NewException("_rrdtool.error", NULL, NULL); + PyDict_SetItemString(d, "error", ErrorObject); + + /* Check for errors */ + if (PyErr_Occurred()) + Py_FatalError("can't initialize the rrdtool module"); +} + +/* + * $Id: _rrdtoolmodule.c,v 1.14 2003/02/22 07:41:19 perky Exp $ + * ex: ts=8 sts=4 et + */ diff -Naur rrdtool-1.2.13.orig/bindings/python/rrdtoolmodule.c rrdtool-1.2.13/bindings/python/rrdtoolmodule.c --- rrdtool-1.2.13.orig/bindings/python/rrdtoolmodule.c 2006-05-04 15:26:28.000000000 +0200 +++ rrdtool-1.2.13/bindings/python/rrdtoolmodule.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,517 +0,0 @@ -/* - * rrdtoolmodule.c - * - * RRDTool Python binding - * - * Author : Hye-Shik Chang - * Date : $Date: 2003/02/22 07:41:19 $ - * Created : 23 May 2002 - * - * $Revision: 1.14 $ - * - * ========================================================================== - * This file is part of py-rrdtool. - * - * py-rrdtool is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published - * by the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * py-rrdtool is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Foobar; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#ifdef UNUSED -#elif defined(__GNUC__) -# define UNUSED(x) x __attribute__((unused)) -#elif defined(__LCLINT__) -# define UNUSED(x) /*@unused@*/ x -#else -# define UNUSED(x) x -#endif - -static const char *__version__ = "$Revision: 1.14 $"; - -#include "Python.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); - -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); - if (*argv == NULL) - return -1; - - for (i = 0; i < size; 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; - } - } - (*argv)[0] = command; - *argc = size + 1; - - /* reset getopt state */ - opterr = optind = 0; - - return 0; -} - -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 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) -{ - PyObject *r; - char **argv; - int argc; - - if (create_args("create", args, &argc, &argv) < 0) - return NULL; - - if (rrd_create(argc, argv) == -1) { - PyErr_SetString(ErrorObject, rrd_get_error()); - rrd_clear_error(); - r = NULL; - } else { - Py_INCREF(Py_None); - r = Py_None; - } - - destroy_args(&argv); - return r; -} - -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...] ...]"; - -static PyObject * -PyRRD_update(PyObject UNUSED(*self), PyObject *args) -{ - PyObject *r; - char **argv; - int argc; - - if (create_args("update", args, &argc, &argv) < 0) - return NULL; - - if (rrd_update(argc, argv) == -1) { - PyErr_SetString(ErrorObject, rrd_get_error()); - rrd_clear_error(); - r = NULL; - } else { - Py_INCREF(Py_None); - r = Py_None; - } - - destroy_args(&argv); - return r; -} - -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]"; - -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; - - if (create_args("fetch", args, &argc, &argv) < 0) - return NULL; - - if (rrd_fetch(argc, argv, &start, &end, &step, - &ds_cnt, &ds_namv, &data) == -1) { - PyErr_SetString(ErrorObject, rrd_get_error()); - rrd_clear_error(); - 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; - - row = ((end - start) / step + 1); - - r = PyTuple_New(3); - range_tup = PyTuple_New(3); - dsnam_tup = PyTuple_New(ds_cnt); - data_list = PyList_New(row); - PyTuple_SET_ITEM(r, 0, range_tup); - PyTuple_SET_ITEM(r, 1, dsnam_tup); - PyTuple_SET_ITEM(r, 2, data_list); - - 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)); - - for (i = 0; i < ds_cnt; i++) - PyTuple_SET_ITEM(dsnam_tup, i, PyString_FromString(ds_namv[i])); - - for (i = 0; i < row; i ++) { - t = PyTuple_New(ds_cnt); - PyList_SET_ITEM(data_list, i, t); - - for (j = 0; j < ds_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 < ds_cnt; i++) - free(ds_namv[i]); - free(ds_namv); /* rrdtool don't use PyMem_Malloc :) */ - free(data); - } - - destroy_args(&argv); - return r; -} - -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) -{ - 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) { - 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)); - - if (calcpr) { - PyObject *e, *t; - - e = PyList_New(0); - PyTuple_SET_ITEM(r, 2, e); - - for(i = 0; calcpr[i]; i++) { - t = PyString_FromString(calcpr[i]); - PyList_Append(e, t); - Py_DECREF(t); - free(calcpr[i]); - } - free(calcpr); - } else { - Py_INCREF(Py_None); - PyTuple_SET_ITEM(r, 2, Py_None); - } - } - - destroy_args(&argv); - return r; -} - -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) -{ - PyObject *r; - char **argv; - int argc; - - if (create_args("tune", args, &argc, &argv) < 0) - return NULL; - - if (rrd_tune(argc, argv) == -1) { - PyErr_SetString(ErrorObject, rrd_get_error()); - rrd_clear_error(); - r = NULL; - } else { - Py_INCREF(Py_None); - r = Py_None; - } - - destroy_args(&argv); - return r; -} - -static char PyRRD_last__doc__[] = -"last(filename): Return the timestamp of the last data sample in an RRD"; - -static PyObject * -PyRRD_last(PyObject UNUSED(*self), PyObject *args) -{ - PyObject *r; - int argc, ts; - char **argv; - - if (create_args("last", args, &argc, &argv) < 0) - return NULL; - - if ((ts = rrd_last(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_resize__doc__[] = -"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) -{ - PyObject *r; - char **argv; - int argc, ts; - - if (create_args("resize", args, &argc, &argv) < 0) - return NULL; - - if ((ts = rrd_resize(argc, argv)) == -1) { - PyErr_SetString(ErrorObject, rrd_get_error()); - rrd_clear_error(); - r = NULL; - } else { - Py_INCREF(Py_None); - r = Py_None; - } - - destroy_args(&argv); - return r; -} - -static char PyRRD_info__doc__[] = -"info(filename): extract header information from an rrd"; - -static PyObject * -PyRRD_info(PyObject UNUSED(*self), PyObject *args) -{ - PyObject *r, *t, *ds; - rrd_t rrd; - FILE *in_file; - char *filename; - unsigned long i, j; - - if (! PyArg_ParseTuple(args, "s:info", &filename)) - return NULL; - - if (rrd_open(filename, &in_file, &rrd, RRD_READONLY) == -1) { - PyErr_SetString(ErrorObject, rrd_get_error()); - rrd_clear_error(); - return NULL; - } - fclose(in_file); - -#define DICTSET_STR(dict, name, value) \ - t = PyString_FromString(value); \ - PyDict_SetItemString(dict, name, t); \ - Py_DECREF(t); - -#define DICTSET_CNT(dict, name, value) \ - t = PyInt_FromLong((long)value); \ - PyDict_SetItemString(dict, name, t); \ - Py_DECREF(t); - -#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); - - r = PyDict_New(); - - 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); - } - - ds = PyList_New(rrd.stat_head->rra_cnt); - PyDict_SetItemString(r, "rra", ds); - Py_DECREF(ds); - - for (i = 0; i < rrd.stat_head->rra_cnt; i++) { - PyObject *d, *cdp; - - 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); - - cdp = PyList_New(rrd.stat_head->ds_cnt); - PyDict_SetItemString(d, "cdp_prep", cdp); - Py_DECREF(cdp); - - for (j = 0; j < rrd.stat_head->ds_cnt; j++) { - PyObject *cdd; - - cdd = PyDict_New(); - PyList_SET_ITEM(cdp, j, cdd); - - 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); - } - } - - rrd_free(&rrd); - - return r; -} - -/* List of methods defined in the module */ -#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} -}; - -#define SET_INTCONSTANT(dict, value) \ - t = PyInt_FromLong((long)value); \ - PyDict_SetItemString(dict, #value, t); \ - Py_DECREF(t); -#define SET_STRCONSTANT(dict, value) \ - t = PyString_FromString(value); \ - PyDict_SetItemString(dict, #value, t); \ - Py_DECREF(t); - -/* Initialization function for the module */ -void -initrrdtool(void) -{ - PyObject *m, *d, *t; - - /* Create the module and add the functions */ - m = Py_InitModule("rrdtool", _rrdtool_methods); - - /* Add some symbolic constants to the module */ - d = PyModule_GetDict(m); - - SET_STRCONSTANT(d, __version__); - ErrorObject = PyErr_NewException("_rrdtool.error", NULL, NULL); - PyDict_SetItemString(d, "error", ErrorObject); - - /* Check for errors */ - if (PyErr_Occurred()) - Py_FatalError("can't initialize the rrdtool module"); -} - -/* - * $Id: _rrdtoolmodule.c,v 1.14 2003/02/22 07:41:19 perky Exp $ - * ex: ts=8 sts=4 et - */