4 * RRDTool Python binding
6 * Author : Hye-Shik Chang <perky@fallin.lv>
7 * Date : $Date: 2003/02/22 07:41:19 $
8 * Created : 23 May 2002
12 * ==========================================================================
13 * This file is part of py-rrdtool.
15 * py-rrdtool is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License as published
17 * by the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * py-rrdtool is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU Lesser General Public License for more details.
25 * You should have received a copy of the GNU Lesser General Public License
26 * along with Foobar; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 static const char *__version__ = "$Revision: 1.14 $";
35 #include "rrd_extra.h"
37 static PyObject *ErrorObject;
41 /* forward declaration to keep compiler happy */
42 void initrrdtool(void);
45 create_args(char *command, PyObject *args, int *argc, char ***argv)
50 size = PyTuple_Size(args);
51 *argv = PyMem_New(char *, size + 1);
55 for (i = 0; i < size; i++) {
56 o = PyTuple_GET_ITEM(args, i);
57 if (PyString_Check(o))
58 (*argv)[i + 1] = PyString_AS_STRING(o);
61 PyErr_Format(PyExc_TypeError, "argument %d must be string", i);
68 /* reset getopt state */
75 destroy_args(char ***argv)
81 static char PyRRD_create__doc__[] =
82 "create(args..): Set up a new Round Robin Database\n\
83 create filename [--start|-b start time] \
84 [--step|-s step] [DS:ds-name:DST:heartbeat:min:max] \
85 [RRA:CF:xff:steps:rows]";
88 PyRRD_create(PyObject *self, PyObject *args)
94 if (create_args("create", args, &argc, &argv) < 0)
97 if (rrd_create(argc, argv) == -1) {
98 PyErr_SetString(ErrorObject, rrd_get_error());
110 static char PyRRD_update__doc__[] =
111 "update(args..): Store a new set of values into the rrd\n"
112 " update filename [--template|-t ds-name[:ds-name]...] "
113 "N|timestamp:value[:value...] [timestamp:value[:value...] ...]";
116 PyRRD_update(PyObject *self, PyObject *args)
122 if (create_args("update", args, &argc, &argv) < 0)
125 if (rrd_update(argc, argv) == -1) {
126 PyErr_SetString(ErrorObject, rrd_get_error());
138 static char PyRRD_fetch__doc__[] =
139 "fetch(args..): fetch data from an rrd.\n"
140 " fetch filename CF [--resolution|-r resolution] "
141 "[--start|-s start] [--end|-e end]";
144 PyRRD_fetch(PyObject *self, PyObject *args)
147 rrd_value_t *data, *datai;
148 unsigned long step, ds_cnt;
151 char **argv, **ds_namv;
153 if (create_args("fetch", args, &argc, &argv) < 0)
156 if (rrd_fetch(argc, argv, &start, &end, &step,
157 &ds_cnt, &ds_namv, &data) == -1) {
158 PyErr_SetString(ErrorObject, rrd_get_error());
163 ((start, end, step), (name1, name2, ...), [(data1, data2, ..), ...]) */
164 PyObject *range_tup, *dsnam_tup, *data_list, *t;
165 unsigned long i, j, row;
168 row = ((end - start) / step + 1);
171 range_tup = PyTuple_New(3);
172 dsnam_tup = PyTuple_New(ds_cnt);
173 data_list = PyList_New(row);
174 PyTuple_SET_ITEM(r, 0, range_tup);
175 PyTuple_SET_ITEM(r, 1, dsnam_tup);
176 PyTuple_SET_ITEM(r, 2, data_list);
180 PyTuple_SET_ITEM(range_tup, 0, PyInt_FromLong((long)start));
181 PyTuple_SET_ITEM(range_tup, 1, PyInt_FromLong((long)end));
182 PyTuple_SET_ITEM(range_tup, 2, PyInt_FromLong((long)step));
184 for (i = 0; i < ds_cnt; i++)
185 PyTuple_SET_ITEM(dsnam_tup, i, PyString_FromString(ds_namv[i]));
187 for (i = 0; i < row; i ++) {
188 t = PyTuple_New(ds_cnt);
189 PyList_SET_ITEM(data_list, i, t);
191 for (j = 0; j < ds_cnt; j++) {
194 PyTuple_SET_ITEM(t, j, Py_None);
197 PyTuple_SET_ITEM(t, j, PyFloat_FromDouble((double)dv));
202 for (i = 0; i < ds_cnt; i++)
204 free(ds_namv); /* rrdtool don't use PyMem_Malloc :) */
212 static char PyRRD_graph__doc__[] =
213 "graph(args..): Create a graph based on data from one or several RRD\n"
214 " graph filename [-s|--start seconds] "
215 "[-e|--end seconds] [-x|--x-grid x-axis grid and label] "
216 "[-y|--y-grid y-axis grid and label] [--alt-y-grid] [--alt-y-mrtg] "
217 "[--alt-autoscale] [--alt-autoscale-max] [--units-exponent] value "
218 "[-v|--vertical-label text] [-w|--width pixels] [-h|--height pixels] "
220 "[-f|--imginfo formatstring] [-a|--imgformat GIF|PNG|GD] "
221 "[-B|--background value] [-O|--overlay value] "
222 "[-U|--unit value] [-z|--lazy] [-o|--logarithmic] "
223 "[-u|--upper-limit value] [-l|--lower-limit value] "
224 "[-g|--no-legend] [-r|--rigid] [--step value] "
225 "[-b|--base value] [-c|--color COLORTAG#rrggbb] "
226 "[-t|--title title] [DEF:vname=rrd:ds-name:CF] "
227 "[CDEF:vname=rpn-expression] [PRINT:vname:CF:format] "
228 "[GPRINT:vname:CF:format] [COMMENT:text] "
229 "[HRULE:value#rrggbb[:legend]] [VRULE:time#rrggbb[:legend]] "
230 "[LINE{1|2|3}:vname[#rrggbb[:legend]]] "
231 "[AREA:vname[#rrggbb[:legend]]] "
232 "[STACK:vname[#rrggbb[:legend]]]";
235 PyRRD_graph(PyObject *self, PyObject *args)
238 char **argv, **calcpr;
239 int argc, xsize, ysize, i;
241 if (create_args("graph", args, &argc, &argv) < 0)
244 if (rrd_graph(argc, argv, &calcpr, &xsize, &ysize, NULL, &ymin, &ymax) == -1) {
245 PyErr_SetString(ErrorObject, rrd_get_error());
251 PyTuple_SET_ITEM(r, 0, PyInt_FromLong((long)xsize));
252 PyTuple_SET_ITEM(r, 1, PyInt_FromLong((long)ysize));
258 PyTuple_SET_ITEM(r, 2, e);
260 for(i = 0; calcpr[i]; i++) {
261 t = PyString_FromString(calcpr[i]);
269 PyTuple_SET_ITEM(r, 2, Py_None);
277 static char PyRRD_tune__doc__[] =
278 "tune(args...): Modify some basic properties of a Round Robin Database\n"
279 " tune filename [--heartbeat|-h ds-name:heartbeat] "
280 "[--minimum|-i ds-name:min] [--maximum|-a ds-name:max] "
281 "[--data-source-type|-d ds-name:DST] [--data-source-rename|-r old-name:new-name]";
284 PyRRD_tune(PyObject *self, PyObject *args)
290 if (create_args("tune", args, &argc, &argv) < 0)
293 if (rrd_tune(argc, argv) == -1) {
294 PyErr_SetString(ErrorObject, rrd_get_error());
306 static char PyRRD_last__doc__[] =
307 "last(filename): Return the timestamp of the last data sample in an RRD";
310 PyRRD_last(PyObject *self, PyObject *args)
316 if (create_args("last", args, &argc, &argv) < 0)
319 if ((ts = rrd_last(argc, argv)) == -1) {
320 PyErr_SetString(ErrorObject, rrd_get_error());
324 r = PyInt_FromLong((long)ts);
330 static char PyRRD_resize__doc__[] =
331 "resize(args...): alters the size of an RRA.\n"
332 " resize filename rra-num GROW|SHRINK rows";
335 PyRRD_resize(PyObject *self, PyObject *args)
341 if (create_args("resize", args, &argc, &argv) < 0)
344 if ((ts = rrd_resize(argc, argv)) == -1) {
345 PyErr_SetString(ErrorObject, rrd_get_error());
357 static char PyRRD_info__doc__[] =
358 "info(filename): extract header information from an rrd";
361 PyRRD_info(PyObject *self, PyObject *args)
363 PyObject *r, *t, *ds;
369 if (! PyArg_ParseTuple(args, "s:info", &filename))
372 if (rrd_open(filename, &in_file, &rrd, RRD_READONLY) == -1) {
373 PyErr_SetString(ErrorObject, rrd_get_error());
379 #define DICTSET_STR(dict, name, value) \
380 t = PyString_FromString(value); \
381 PyDict_SetItemString(dict, name, t); \
384 #define DICTSET_CNT(dict, name, value) \
385 t = PyInt_FromLong((long)value); \
386 PyDict_SetItemString(dict, name, t); \
389 #define DICTSET_VAL(dict, name, value) \
390 t = isnan(value) ? (Py_INCREF(Py_None), Py_None) : \
391 PyFloat_FromDouble((double)value); \
392 PyDict_SetItemString(dict, name, t); \
397 DICTSET_STR(r, "filename", filename);
398 DICTSET_STR(r, "rrd_version", rrd.stat_head->version);
399 DICTSET_CNT(r, "step", rrd.stat_head->pdp_step);
400 DICTSET_CNT(r, "last_update", rrd.live_head->last_up);
403 PyDict_SetItemString(r, "ds", ds);
406 for (i = 0; i < rrd.stat_head->ds_cnt; i++) {
410 PyDict_SetItemString(ds, rrd.ds_def[i].ds_nam, d);
413 DICTSET_STR(d, "ds_name", rrd.ds_def[i].ds_nam);
414 DICTSET_STR(d, "type", rrd.ds_def[i].dst);
415 DICTSET_CNT(d, "minimal_heartbeat", rrd.ds_def[i].par[DS_mrhb_cnt].u_cnt);
416 DICTSET_VAL(d, "min", rrd.ds_def[i].par[DS_min_val].u_val);
417 DICTSET_VAL(d, "max", rrd.ds_def[i].par[DS_max_val].u_val);
418 DICTSET_STR(d, "last_ds", rrd.pdp_prep[i].last_ds);
419 DICTSET_VAL(d, "value", rrd.pdp_prep[i].scratch[PDP_val].u_val);
420 DICTSET_CNT(d, "unknown_sec", rrd.pdp_prep[i].scratch[PDP_unkn_sec_cnt].u_cnt);
423 ds = PyList_New(rrd.stat_head->rra_cnt);
424 PyDict_SetItemString(r, "rra", ds);
427 for (i = 0; i < rrd.stat_head->rra_cnt; i++) {
431 PyList_SET_ITEM(ds, i, d);
433 DICTSET_STR(d, "cf", rrd.rra_def[i].cf_nam);
434 DICTSET_CNT(d, "rows", rrd.rra_def[i].row_cnt);
435 DICTSET_CNT(d, "pdp_per_row", rrd.rra_def[i].pdp_cnt);
436 DICTSET_VAL(d, "xff", rrd.rra_def[i].par[RRA_cdp_xff_val].u_val);
438 cdp = PyList_New(rrd.stat_head->ds_cnt);
439 PyDict_SetItemString(d, "cdp_prep", cdp);
442 for (j = 0; j < rrd.stat_head->ds_cnt; j++) {
446 PyList_SET_ITEM(cdp, j, cdd);
448 DICTSET_VAL(cdd, "value",
449 rrd.cdp_prep[i*rrd.stat_head->ds_cnt+j].scratch[CDP_val].u_val);
450 DICTSET_CNT(cdd, "unknown_datapoints",
451 rrd.cdp_prep[i*rrd.stat_head->ds_cnt+j].scratch[CDP_unkn_pdp_cnt].u_cnt);
460 /* List of methods defined in the module */
461 #define meth(name, func, doc) {name, (PyCFunction)func, METH_VARARGS, doc}
463 static PyMethodDef _rrdtool_methods[] = {
464 meth("create", PyRRD_create, PyRRD_create__doc__),
465 meth("update", PyRRD_update, PyRRD_update__doc__),
466 meth("fetch", PyRRD_fetch, PyRRD_fetch__doc__),
467 meth("graph", PyRRD_graph, PyRRD_graph__doc__),
468 meth("tune", PyRRD_tune, PyRRD_tune__doc__),
469 meth("last", PyRRD_last, PyRRD_last__doc__),
470 meth("resize", PyRRD_resize, PyRRD_resize__doc__),
471 meth("info", PyRRD_info, PyRRD_info__doc__),
475 #define SET_INTCONSTANT(dict, value) \
476 t = PyInt_FromLong((long)value); \
477 PyDict_SetItemString(dict, #value, t); \
479 #define SET_STRCONSTANT(dict, value) \
480 t = PyString_FromString(value); \
481 PyDict_SetItemString(dict, #value, t); \
484 /* Initialization function for the module */
490 /* Create the module and add the functions */
491 m = Py_InitModule("rrdtool", _rrdtool_methods);
493 /* Add some symbolic constants to the module */
494 d = PyModule_GetDict(m);
496 SET_STRCONSTANT(d, __version__);
497 ErrorObject = PyErr_NewException("_rrdtool.error", NULL, NULL);
498 PyDict_SetItemString(d, "error", ErrorObject);
500 /* Check for errors */
501 if (PyErr_Occurred())
502 Py_FatalError("can't initialize the rrdtool module");
506 * $Id: _rrdtoolmodule.c,v 1.14 2003/02/22 07:41:19 perky Exp $