Bug Summary

File:rrdtoolmodule.c
Warning:line 737, column 13
PyObject ownership leak with reference count of 1

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name rrdtoolmodule.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -analyzer-output=html -analyzer-checker=python -analyzer-disable-checker=deadcode -analyzer-config prune-paths=true,suppress-c++-stdlib=true,suppress-inlined-defensive-checks=false,suppress-null-return-paths=false,crosscheck-with-z3=true,model-path=/opt/pyrefcon/lib/pyrefcon/models/models -analyzer-config experimental-enable-naive-ctu-analysis=true,ctu-dir=/tmp/pyrefcon/python-rrdtool/csa-scan,ctu-index-name=/tmp/pyrefcon/python-rrdtool/csa-scan/externalDefMap.txt,ctu-invocation-list=/tmp/pyrefcon/python-rrdtool/csa-scan/invocations.yaml,display-ctu-progress=false -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debug-info-kind=limited -dwarf-version=4 -debugger-tuning=gdb -fcoverage-compilation-dir=/tmp/pyrefcon/python-rrdtool -resource-dir /opt/pyrefcon/lib/clang/13.0.0 -isystem /opt/pyrefcon/lib/pyrefcon/models/python3.8 -D NDEBUG -D _FORTIFY_SOURCE=2 -D PACKAGE_VERSION="0.1.15" -D WITH_FETCH_CB=1 -I /tmp/pyrefcon/python-rrdtool -I /usr/local/include -internal-isystem /opt/pyrefcon/lib/clang/13.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-result -Wsign-compare -Wall -Wformat -Wformat -Wdate-time -fdebug-compilation-dir=/tmp/pyrefcon/python-rrdtool -ferror-limit 19 -fwrapv -pthread -stack-protector 2 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/pyrefcon/python-rrdtool/csa-scan/reports -x c rrdtoolmodule.c

rrdtoolmodule.c

1/*
2 * python-rrdtool, Python bindings for rrdtool.
3 * Based on the rrdtool Python bindings for Python 2 from
4 * Hye-Shik Chang <perky@fallin.lv>.
5 *
6 * Copyright 2012 Christian Kroeger <commx@commx.ws>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as
10 * published by the Free Software Foundation; either version 2.1 of the
11 * License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21 * MA 02110-1301, USA.
22 *
23 */
24
25#include <Python.h>
26#include <datetime.h>
27#include "rrdtoolmodule.h"
28
29/* Some macros to maintain compatibility between Python 2.x and 3.x */
30#if PY_MAJOR_VERSION3 >= 3
31#define HAVE_PY3K
32#define PyRRD_String_Check(x)((((((PyObject*)(x))->ob_type))->tp_flags & ((1UL <<
28))) != 0)
PyUnicode_Check(x)((((((PyObject*)(x))->ob_type))->tp_flags & ((1UL <<
28))) != 0)
33#define PyRRD_String_FromString(x)PyUnicode_FromString(x) PyUnicode_FromString(x)
34#define PyRRD_String_AS_STRING(x)PyUnicode_AsUTF8(x) PyUnicode_AsUTF8(x)
35#define PyRRD_String_FromStringAndSize(x, y)PyBytes_FromStringAndSize(x, y) PyBytes_FromStringAndSize(x, y)
36#define PyRRD_String_Size(x)PyUnicode_Size(x) PyUnicode_Size(x)
37#define PyRRD_Int_FromLong(x)PyLong_FromLong(x) PyLong_FromLong(x)
38#define PyRRD_Int_FromString(x, y, z)PyLong_FromString(x,y,z) PyLong_FromString(x,y,z)
39#define PyRRD_Long_Check(x)((((((PyObject*)(x))->ob_type))->tp_flags & ((1UL <<
24))) != 0)
PyLong_Check(x)((((((PyObject*)(x))->ob_type))->tp_flags & ((1UL <<
24))) != 0)
40#else
41#define PyRRD_String_Check(x)((((((PyObject*)(x))->ob_type))->tp_flags & ((1UL <<
28))) != 0)
PyString_Check(x)
42#define PyRRD_String_FromString(x)PyUnicode_FromString(x) PyString_FromString(x)
43#define PyRRD_String_AS_STRING(x)PyUnicode_AsUTF8(x) PyString_AS_STRING(x)
44#define PyRRD_String_FromStringAndSize(x, y)PyBytes_FromStringAndSize(x, y) PyString_FromStringAndSize(x, y)
45#define PyRRD_String_Size(x)PyUnicode_Size(x) PyString_Size(x)
46#define PyRRD_Int_FromLong(x)PyLong_FromLong(x) PyInt_FromLong(x)
47#define PyRRD_Int_FromString(x, y, z)PyLong_FromString(x,y,z) PyInt_FromString(x,y,z)
48#define PyRRD_Long_Check(x)((((((PyObject*)(x))->ob_type))->tp_flags & ((1UL <<
24))) != 0)
(PyInt_Check(x) || PyLong_Check(x)((((((PyObject*)(x))->ob_type))->tp_flags & ((1UL <<
24))) != 0)
)
49#endif
50
51#ifndef Py_UNUSED
52#ifdef __GNUC__4
53 #define Py_UNUSED(name)_unused_name __attribute__((unused)) _unused_ ## name __attribute__((unused))
54#else
55 #define Py_UNUSED(name)_unused_name __attribute__((unused)) _unused_ ## -name
56#endif
57#endif
58
59#ifndef DS_NAM_SIZE20
60#define DS_NAM_SIZE20 20
61#endif
62
63/** Binding version. */
64static const char *_version = PACKAGE_VERSION"0.1.15";
65
66/** Exception types. */
67static PyObject *rrdtool_OperationalError;
68static PyObject *rrdtool_ProgrammingError;
69
70/**
71 * PyRRD_DateTime_FromTS: convert UNIX timestamp (time_t)
72 * to Python datetime object.
73 *
74 * @param ts UNIX timestamp (time_t)
75 * @return Pointer to new PyObject (New Reference)
76 */
77static PyObject *
78PyRRD_DateTime_FromTS(time_t ts)
79{
80 PyObject *ret;
81 struct tm lt;
82
83 localtime_r(&ts, &lt);
84
85 ret = PyDateTime_FromDateAndTime(PyDateTimeAPI->DateTime_FromDateAndTime(lt.tm_year + 1900,
lt.tm_mon + 1, lt.tm_mday, lt.tm_hour, lt.tm_min, lt.tm_sec,
0, (&_Py_NoneStruct), PyDateTimeAPI->DateTimeType)
86 lt.tm_year + 1900,PyDateTimeAPI->DateTime_FromDateAndTime(lt.tm_year + 1900,
lt.tm_mon + 1, lt.tm_mday, lt.tm_hour, lt.tm_min, lt.tm_sec,
0, (&_Py_NoneStruct), PyDateTimeAPI->DateTimeType)
87 lt.tm_mon + 1,PyDateTimeAPI->DateTime_FromDateAndTime(lt.tm_year + 1900,
lt.tm_mon + 1, lt.tm_mday, lt.tm_hour, lt.tm_min, lt.tm_sec,
0, (&_Py_NoneStruct), PyDateTimeAPI->DateTimeType)
88 lt.tm_mday,PyDateTimeAPI->DateTime_FromDateAndTime(lt.tm_year + 1900,
lt.tm_mon + 1, lt.tm_mday, lt.tm_hour, lt.tm_min, lt.tm_sec,
0, (&_Py_NoneStruct), PyDateTimeAPI->DateTimeType)
89 lt.tm_hour,PyDateTimeAPI->DateTime_FromDateAndTime(lt.tm_year + 1900,
lt.tm_mon + 1, lt.tm_mday, lt.tm_hour, lt.tm_min, lt.tm_sec,
0, (&_Py_NoneStruct), PyDateTimeAPI->DateTimeType)
90 lt.tm_min,PyDateTimeAPI->DateTime_FromDateAndTime(lt.tm_year + 1900,
lt.tm_mon + 1, lt.tm_mday, lt.tm_hour, lt.tm_min, lt.tm_sec,
0, (&_Py_NoneStruct), PyDateTimeAPI->DateTimeType)
91 lt.tm_sec,PyDateTimeAPI->DateTime_FromDateAndTime(lt.tm_year + 1900,
lt.tm_mon + 1, lt.tm_mday, lt.tm_hour, lt.tm_min, lt.tm_sec,
0, (&_Py_NoneStruct), PyDateTimeAPI->DateTimeType)
92 0)PyDateTimeAPI->DateTime_FromDateAndTime(lt.tm_year + 1900,
lt.tm_mon + 1, lt.tm_mday, lt.tm_hour, lt.tm_min, lt.tm_sec,
0, (&_Py_NoneStruct), PyDateTimeAPI->DateTimeType)
;
93
94 return ret;
95}
96
97/**
98 * PyRRD_String_FromCF: get string representation of CF enum index
99 *
100 * @param cf enum cf_en
101 * @return Null-terminated string
102 */
103const char *
104PyRRD_String_FromCF(enum cf_en cf)
105{
106 switch (cf) {
107 case CF_AVERAGE:
108 return "AVERAGE";
109 case CF_MINIMUM:
110 return "MIN";
111 case CF_MAXIMUM:
112 return "MAX";
113 case CF_LAST:
114 return "LAST";
115 default:
116 return "INVALID";
117 }
118}
119
120/**
121 * Helper function to convert Python objects into a representation that the
122 * rrdtool functions can work with.
123 *
124 * @param command RRDtool command name
125 * @param args Command arguments
126 * @return Zero if the function succeeds, otherwise -1
127 */
128static int
129convert_args(char *command, PyObject *args, char ***rrdtool_argv, int *rrdtool_argc)
130{
131 PyObject *o, *lo;
132 int i, j, args_count, argv_count, element_count;
133
134 argv_count = element_count = 0;
135 args_count = PyTuple_Size(args);
136
137 for (i = 0; i < args_count; i++) {
138 o = PyTuple_GET_ITEM(args, i)((((void) (0)), (PyTupleObject *)(args))->ob_item[i]);
139
140 if (PyRRD_String_Check(o)((((((PyObject*)(o))->ob_type))->tp_flags & ((1UL <<
28))) != 0)
)
141 element_count++;
142 else if (PyList_CheckExact(o)((((PyObject*)(o))->ob_type) == &PyList_Type))
143 element_count += PyList_Size(o);
144 else {
145 PyErr_Format(PyExc_TypeError,
146 "Argument %d must be str or a list of str", i);
147 return -1;
148 }
149 }
150
151 *rrdtool_argv = PyMem_New(char *, element_count + 1)( ((size_t)(element_count + 1) > ((Py_ssize_t)(((size_t)-1
)>>1)) / sizeof(char *)) ? ((void*)0) : ( (char * *) PyMem_Malloc
((element_count + 1) * sizeof(char *)) ) )
;
152
153 if (*rrdtool_argv == NULL((void*)0))
154 return -1;
155
156 for (i = 0; i < args_count; i++) {
157 o = PyTuple_GET_ITEM(args, i)((((void) (0)), (PyTupleObject *)(args))->ob_item[i]);
158
159 if (PyRRD_String_Check(o)((((((PyObject*)(o))->ob_type))->tp_flags & ((1UL <<
28))) != 0)
)
160 (*rrdtool_argv)[++argv_count] = (char *)PyRRD_String_AS_STRING(o)PyUnicode_AsUTF8(o);
161 else if (PyList_CheckExact(o)((((PyObject*)(o))->ob_type) == &PyList_Type)) {
162 for (j = 0; j < PyList_Size(o); j++) {
163 lo = PyList_GetItem(o, j);
164
165 if (PyRRD_String_Check(lo)((((((PyObject*)(lo))->ob_type))->tp_flags & ((1UL <<
28))) != 0)
)
166 (*rrdtool_argv)[++argv_count] = (char *)PyRRD_String_AS_STRING(lo)PyUnicode_AsUTF8(lo);
167 else {
168 PyMem_DelPyMem_Free(*rrdtool_argv);
169 PyErr_Format(PyExc_TypeError,
170 "Element %d in argument %d must be str", j, i);
171 return -1;
172 }
173 }
174 } else {
175 PyMem_DelPyMem_Free(*rrdtool_argv);
176 PyErr_Format(rrdtool_ProgrammingError,
177 "Argument %d must be str or list of str", i);
178 return -1;
179 }
180 }
181
182 (*rrdtool_argv)[0] = command;
183 *rrdtool_argc = element_count + 1;
184
185 return 0;
186}
187
188/**
189 * Destroy argument vector.
190 */
191static void
192destroy_args(char ***rrdtool_argv)
193{
194 PyMem_DelPyMem_Free(*rrdtool_argv);
195 *rrdtool_argv = NULL((void*)0);
196}
197
198/**
199 * Convert RRDtool info to dict.
200 *
201 * @param data RRDtool info object
202 * @return Python dict object
203 */
204static PyObject *
205_rrdtool_util_info2dict(const rrd_info_t *data)
206{
207 PyObject *dict, *val;
208
209 dict = PyDict_New();
210
211 while (data) {
212 val = NULL((void*)0);
213
214 switch (data->type) {
215 case RD_I_VAL:
216 if (isnan(data->value.u_val)__builtin_isnan (data->value.u_val)) {
217 Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct))));
218 val = Py_None(&_Py_NoneStruct);
219 } else
220 val = PyFloat_FromDouble(data->value.u_val);
221 break;
222
223 case RD_I_CNT:
224 val = PyLong_FromUnsignedLong(data->value.u_cnt);
225 break;
226
227 case RD_I_INT:
228 val = PyLong_FromLong(data->value.u_int);
229 break;
230
231 case RD_I_STR:
232 val = PyRRD_String_FromString(data->value.u_str)PyUnicode_FromString(data->value.u_str);
233 break;
234
235 case RD_I_BLO:
236 val = PyRRD_String_FromStringAndSize(PyBytes_FromStringAndSize((char *)data->value.u_blo.ptr, data
->value.u_blo.size)
237 (char *)data->value.u_blo.ptr,PyBytes_FromStringAndSize((char *)data->value.u_blo.ptr, data
->value.u_blo.size)
238 data->value.u_blo.size)PyBytes_FromStringAndSize((char *)data->value.u_blo.ptr, data
->value.u_blo.size)
;
239 break;
240 default:
241 break;
242 }
243
244 if (val != NULL((void*)0)) {
245 PyDict_SetItemString(dict, data->key, val);
246 Py_DECREF(val)_Py_DECREF(((PyObject*)(val)));
247 }
248
249 data = data->next;
250 }
251
252 return dict;
253}
254
255static char _rrdtool_create__doc__[] = "Create a new Round Robin Database.\n\n\
256 Usage: create(args...)\n\
257 Arguments:\n\n\
258 filename\n\
259 [-b|--start start time]\n\
260 [-s|--step step]\n\
261 [-t|--template template-file]\n\
262 [-r|--source source-file]\n\
263 [-O|--no-overwrite]\n\
264 [-d|--daemon address]\n\
265 [DS:ds-name[=mapped-ds-name[source-index]]:DST:heartbeat:min:max]\n\
266 [RRA:CF:xff:steps:rows]\n\n\
267 Full documentation can be found at:\n\
268 https://oss.oetiker.ch/rrdtool/doc/rrdcreate.en.html";
269
270static PyObject *
271_rrdtool_create(PyObject *Py_UNUSED(self)_unused_self __attribute__((unused)), PyObject *args)
272{
273 char **rrdtool_argv = NULL((void*)0);
274 int rrdtool_argc = 0;
275 PyObject *ret;
276 int status;
277
278 if (convert_args("create", args, &rrdtool_argv, &rrdtool_argc) == -1)
279 return NULL((void*)0);
280
281 Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();
282 status = rrd_create(rrdtool_argc, rrdtool_argv);
283 Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); }
284
285 if (status == -1) {
286 PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
287 rrd_clear_error();
288 ret = NULL((void*)0);
289 } else {
290 Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct))));
291 ret = Py_None(&_Py_NoneStruct);
292 }
293
294 destroy_args(&rrdtool_argv);
295 return ret;
296}
297
298static char _rrdtool_dump__doc__[] = "Dump an RRD to XML.\n\n\
299 Usage: dump(args..)\n\
300 Arguments:\n\n\
301 [-h|--header {none,xsd,dtd}\n\
302 [-n|--no-header]\n\
303 [-d|--daemon address]\n\
304 file.rrd\n\
305 [file.xml]\n\n\
306 Full documentation can be found at:\n\
307 https://oss.oetiker.ch/rrdtool/doc/rrddump.en.html";
308
309static PyObject *
310_rrdtool_dump(PyObject *Py_UNUSED(self)_unused_self __attribute__((unused)), PyObject *args)
311{
312 char **rrdtool_argv = NULL((void*)0);
313 int rrdtool_argc = 0;
314 PyObject *ret;
315 int status;
316
317 if (convert_args("dump", args, &rrdtool_argv, &rrdtool_argc) == -1)
318 return NULL((void*)0);
319
320 Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();
321 status = rrd_dump(rrdtool_argc, rrdtool_argv);
322 Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); }
323
324 if (status != 0) {
325 PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
326 rrd_clear_error();
327 ret = NULL((void*)0);
328 } else {
329 Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct))));
330 ret = Py_None(&_Py_NoneStruct);
331 }
332
333 destroy_args(&rrdtool_argv);
334 return ret;
335}
336
337static char _rrdtool_update__doc__[] = "Store a new set of values into\
338 the RRD.\n\n\
339 Usage: update(args..)\n\
340 Arguments:\n\n\
341 filename\n\
342 [--template|-t ds-name[:ds-name]...]\n\
343 N|timestamp:value[:value...]\n\
344 [timestamp:value[:value...] ...]\n\n\
345 Full documentation can be found at:\n\
346 https://oss.oetiker.ch/rrdtool/doc/rrdupdate.en.html";
347
348static PyObject *
349_rrdtool_update(PyObject *Py_UNUSED(self)_unused_self __attribute__((unused)), PyObject *args)
350{
351 char **rrdtool_argv = NULL((void*)0);
352 int rrdtool_argc = 0;
353 PyObject *ret;
354 int status;
355
356 if (convert_args("update", args, &rrdtool_argv, &rrdtool_argc) == -1)
357 return NULL((void*)0);
358
359 Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();
360 status = rrd_update(rrdtool_argc, rrdtool_argv);
361 Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); }
362
363 if (status == -1) {
364 PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
365 rrd_clear_error();
366 ret = NULL((void*)0);
367 } else {
368 Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct))));
369 ret = Py_None(&_Py_NoneStruct);
370 }
371
372 destroy_args(&rrdtool_argv);
373 return ret;
374}
375
376static char _rrdtool_updatev__doc__[] = "Store a new set of values into "\
377 "the Round Robin Database and return an info dictionary.\n\n\
378 This function works in the same manner as 'update', but will return an\n\
379 info dictionary instead of None.";
380
381static PyObject *
382_rrdtool_updatev(PyObject *Py_UNUSED(self)_unused_self __attribute__((unused)), PyObject *args)
383{
384 char **rrdtool_argv = NULL((void*)0);
385 int rrdtool_argc = 0;
386 PyObject *ret;
387 rrd_info_t *data;
388
389 if (convert_args("updatev", args, &rrdtool_argv, &rrdtool_argc) == -1)
390 return NULL((void*)0);
391
392 Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();
393 data = rrd_update_v(rrdtool_argc, rrdtool_argv);
394 Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); }
395
396 if (data == NULL((void*)0)) {
397 PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
398 rrd_clear_error();
399 ret = NULL((void*)0);
400 } else {
401 ret = _rrdtool_util_info2dict(data);
402 rrd_info_free(data);
403 }
404
405 destroy_args(&rrdtool_argv);
406 return ret;
407}
408
409static char _rrdtool_fetch__doc__[] = "Fetch data from an RRD.\n\n\
410 Usage: fetch(args..)\n\
411 Arguments:\n\n\
412 filename\n\
413 CF\n\
414 [-r|--resolution resolution]\n\
415 [-s|--start start]\n\
416 [-e|--end end]\n\
417 [-a|--align-start]\n\
418 [-d|--daemon address]\n\n\
419 Full documentation can be found at:\n\
420 https://oss.oetiker.ch/rrdtool/doc/rrdfetch.en.html";
421
422static PyObject *
423_rrdtool_fetch(PyObject *Py_UNUSED(self)_unused_self __attribute__((unused)), PyObject *args)
424{
425 char **rrdtool_argv = NULL((void*)0);
426 int rrdtool_argc = 0;
427 PyObject *ret, *range_tup, *dsnam_tup, *data_list, *t;
428 rrd_value_t *data, *datai, dv;
429 unsigned long step, ds_cnt, i, j, row;
430 time_t start, end;
431 char **ds_namv;
432 int status;
433
434 if (convert_args("fetch", args, &rrdtool_argv, &rrdtool_argc) == -1)
435 return NULL((void*)0);
436
437 Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();
438 status = rrd_fetch(rrdtool_argc, rrdtool_argv, &start, &end, &step,
439 &ds_cnt, &ds_namv, &data);
440 Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); }
441
442 if (status == -1) {
443 PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
444 rrd_clear_error();
445 ret = NULL((void*)0);
446 } else {
447 row = (end - start) / step;
448 ret = PyTuple_New(3);
449 range_tup = PyTuple_New(3);
450 dsnam_tup = PyTuple_New(ds_cnt);
451 data_list = PyList_New(row);
452
453 PyTuple_SET_ITEM(ret, 0, range_tup)PyTuple_SetItem(ret, 0, range_tup);
454 PyTuple_SET_ITEM(ret, 1, dsnam_tup)PyTuple_SetItem(ret, 1, dsnam_tup);
455 PyTuple_SET_ITEM(ret, 2, data_list)PyTuple_SetItem(ret, 2, data_list);
456
457 datai = data;
458
459 PyTuple_SET_ITEM(range_tup, 0, PyRRD_Int_FromLong((long) start))PyTuple_SetItem(range_tup, 0, PyLong_FromLong((long) start));
460 PyTuple_SET_ITEM(range_tup, 1, PyRRD_Int_FromLong((long) end))PyTuple_SetItem(range_tup, 1, PyLong_FromLong((long) end));
461 PyTuple_SET_ITEM(range_tup, 2, PyRRD_Int_FromLong((long) step))PyTuple_SetItem(range_tup, 2, PyLong_FromLong((long) step));
462
463 for (i = 0; i < ds_cnt; i++)
464 PyTuple_SET_ITEM(dsnam_tup, i, PyRRD_String_FromString(ds_namv[i]))PyTuple_SetItem(dsnam_tup, i, PyUnicode_FromString(ds_namv[i]
))
;
465
466 for (i = 0; i < row; i++) {
467 t = PyTuple_New(ds_cnt);
468 PyList_SET_ITEM(data_list, i, t)PyList_SetItem(data_list, i, t);
469
470 for (j = 0; j < ds_cnt; j++) {
471 dv = *(datai++);
472 if (isnan(dv)__builtin_isnan (dv)) {
473 PyTuple_SET_ITEM(t, j, Py_None)PyTuple_SetItem(t, j, (&_Py_NoneStruct));
474 Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct))));
475 } else
476 PyTuple_SET_ITEM(t, j, PyFloat_FromDouble((double) dv))PyTuple_SetItem(t, j, PyFloat_FromDouble((double) dv));
477 }
478 }
479
480 for (i = 0; i < ds_cnt; i++)
481 rrd_freemem(ds_namv[i]);
482
483 rrd_freemem(ds_namv);
484 rrd_freemem(data);
485 }
486
487 destroy_args(&rrdtool_argv);
488 return ret;
489}
490
491static char _rrdtool_flushcached__doc__[] = "Flush RRD files from memory.\n\n\
492 Usage: flushcached(args..)\n\
493 Arguments:\n\n\
494 [-d|--daemon address]\n\
495 filename\n\
496 [filename ...]\n\n\
497 Full documentation can be found at:\n\
498 https://oss.oetiker.ch/rrdtool/doc/rrdflushcached.en.html";
499
500static PyObject *
501_rrdtool_flushcached(PyObject *Py_UNUSED(self)_unused_self __attribute__((unused)), PyObject *args)
502{
503 char **rrdtool_argv = NULL((void*)0);
504 int rrdtool_argc = 0;
505 PyObject *ret;
506 int status;
507
508 if (convert_args("flushcached", args, &rrdtool_argv, &rrdtool_argc) == -1)
509 return NULL((void*)0);
510
511 Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();
512 status = rrd_flushcached(rrdtool_argc, rrdtool_argv);
513 Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); }
514
515 if (status != 0) {
516 PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
517 rrd_clear_error();
518 ret = NULL((void*)0);
519 } else {
520 Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct))));
521 ret = Py_None(&_Py_NoneStruct);
522 }
523
524 destroy_args(&rrdtool_argv);
525 return ret;
526}
527
528static char _rrdtool_graph__doc__[] = "Create a graph based on one or more " \
529 "RRDs.\n\n\
530 Usage: graph(args..)\n\
531 Arguments:\n\n\
532 filename | -\n\
533 [-s|--start start]\n\
534 [-e|--end end]\n\
535 [-S|--step step]\n\
536 [-t|--title string]\n\
537 [-v|--vertical-label string]\n\
538 [-w|--width pixels]\n\
539 [-h|--height pixels]\n\
540 [-j|--only-graph]\n\
541 [-D|--full-size-mode]\n\
542 [-u|--upper-limit value]\n\
543 [-l|--lower-limit value]\n\
544 [-r|--rigid]\n\
545 [-A|--alt-autoscale]\n\
546 [-J|--alt-autoscale-min]\n\
547 [-M|--alt-autoscale-max]\n\
548 [-N|--no-gridfit]\n\
549 [-x|--x-grid (GTM:GST:MTM:MST:LTM:LST:LPR:LFM|none)]\n\
550 [-y|--y-grid (grid step:label factor|none)]\n\
551 [--week-fmt strftime format string]\n\
552 [--left-axis-formatter formatter-name]\n\
553 [--left-axis-format format-string]\n\
554 [-Y|--alt-y-grid]\n\
555 [-o|--logarithmic]\n\
556 [-X|--units-exponent value]\n\
557 [-L|--units-length value]\n\
558 [--units=si]\n\
559 [--right-axis scale:shift]\n\
560 [--right-axis-label label]\n\
561 [--right-axis-format format-string]\n\
562 [-g|--no-legend]\n\
563 [-F|--force-rules-legend]\n\
564 [--legend-position=(north|south|west|east)]\n\
565 [--legend-direction=(topdown|bottomup)]\n\
566 [-z|--lazy]\n\
567 [-d|--daemon address]\n\
568 [-f|--imginfo printfstr]\n\
569 [-c|--color COLORTAG#rrggbb[aa]]\n\
570 [--grid-dash on:off]\n\
571 [--border width]\n\
572 [--dynamic-labels]\n\
573 [-m|--zoom factor]\n\
574 [-n|--font FONTTAG:size:[font]]\n\
575 [-R|--font-render-mode {normal,light,mono}]\n\
576 [-B|--font-smoothing-threshold size]\n\
577 [-P|--pango-markup]\n\
578 [-G|--graph-render-mode {normal,mono}]\n\
579 [-E|--slope-mode]\n\
580 [-a|--imgformat {PNG,SVG,EPS,PDF,XML,XMLENUM,JSON,JSONTIME,CSV,TSV,SSV}]\n\
581 [-i|--interlaced]\n\
582 [-T|--tabwidth value]\n\
583 [-b|--base value]\n\
584 [-W|--watermark string]\n\
585 [-Z|--use-nan-for-all-missing-data]\n\
586 DEF:vname=rrdfile:ds-name:CF[:step=step][:start=time][:end=time]\n\
587 CDEF:vname=RPN expression\n\
588 VDEF=vname:RPN expression\n\n\
589 Full documentation can be found at:\n\
590 https://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html";
591
592static PyObject *
593_rrdtool_graph(PyObject *Py_UNUSED(self)_unused_self __attribute__((unused)), PyObject *args)
594{
595 char **rrdtool_argv = NULL((void*)0);
596 int rrdtool_argc = 0;
597 PyObject *ret;
598 int xsize, ysize, i, status;
599 double ymin, ymax;
600 char **calcpr = NULL((void*)0);
601
602 if (convert_args("graph", args, &rrdtool_argv, &rrdtool_argc) == -1)
603 return NULL((void*)0);
604
605 Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();
606 status = rrd_graph(rrdtool_argc, rrdtool_argv, &calcpr, &xsize, &ysize,
607 NULL((void*)0), &ymin, &ymax);
608 Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); }
609
610 if (status == -1) {
611 PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
612 rrd_clear_error();
613 ret = NULL((void*)0);
614 } else {
615 ret = PyTuple_New(3);
616
617 PyTuple_SET_ITEM(ret, 0, PyRRD_Int_FromLong((long) xsize))PyTuple_SetItem(ret, 0, PyLong_FromLong((long) xsize));
618 PyTuple_SET_ITEM(ret, 1, PyRRD_Int_FromLong((long) ysize))PyTuple_SetItem(ret, 1, PyLong_FromLong((long) ysize));
619
620 if (calcpr) {
621 PyObject *e, *t;
622
623 e = PyList_New(0);
624 PyTuple_SET_ITEM(ret, 2, e)PyTuple_SetItem(ret, 2, e);
625
626 for (i = 0; calcpr[i]; i++) {
627 t = PyRRD_String_FromString(calcpr[i])PyUnicode_FromString(calcpr[i]);
628 PyList_Append(e, t);
629 Py_DECREF(t)_Py_DECREF(((PyObject*)(t)));
630 rrd_freemem(calcpr[i]);
631 }
632 } else {
633 Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct))));
634 PyTuple_SET_ITEM(ret, 2, Py_None)PyTuple_SetItem(ret, 2, (&_Py_NoneStruct));
635 }
636 }
637
638 destroy_args(&rrdtool_argv);
639 return ret;
640}
641
642static char _rrdtool_graphv__doc__[] = "Create a graph based on one or more " \
643 "RRDs and return data in RRDtool info format.\n\n\
644 This function works the same way as 'graph', but will return a info\n\
645 dictionary instead of None.\n\n\
646 Full documentation can be found at (graphv section):\n\
647 https://oss.oetiker.ch/rrdtool/doc/rrdgraph.en.html";
648
649static PyObject *
650_rrdtool_graphv(PyObject *Py_UNUSED(self)_unused_self __attribute__((unused)), PyObject *args)
651{
652 char **rrdtool_argv = NULL((void*)0);
653 int rrdtool_argc = 0;
654 PyObject *ret;
655 rrd_info_t *data;
656
657 if (convert_args("graphv", args, &rrdtool_argv, &rrdtool_argc) == -1)
658 return NULL((void*)0);
659
660 Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();
661 data = rrd_graph_v(rrdtool_argc, rrdtool_argv);
662 Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); }
663
664 if (data == NULL((void*)0)) {
665 PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
666 rrd_clear_error();
667 ret = NULL((void*)0);
668 } else {
669 ret = _rrdtool_util_info2dict(data);
670 rrd_info_free(data);
671 }
672
673 destroy_args(&rrdtool_argv);
674 return ret;
675}
676
677static char _rrdtool_xport__doc__[] = "Dictionary representation of data " \
678 "stored in RRDs.\n\n\
679 Usage: xport(args..)\n\
680 Arguments:\n\n\
681 [-s[--start seconds]\n\
682 [-e|--end seconds]\n\
683 [-m|--maxrows rows]\n\
684 [--step value]\n\
685 [--json]\n\
686 [--enumds]\n\
687 [--daemon address]\n\
688 [DEF:vname=rrd:ds-name:CF]\n\
689 [CDEF:vname=rpn-expression]\n\
690 [XPORT:vname[:legend]]\n\n\
691 Full documentation can be found at:\n\
692 https://oss.oetiker.ch/rrdtool/doc/rrdxport.en.html";
693
694static PyObject *
695_rrdtool_xport(PyObject *Py_UNUSED(self)_unused_self __attribute__((unused)), PyObject *args)
696{
697 char **rrdtool_argv = NULL((void*)0);
698 int rrdtool_argc = 0;
699 PyObject *ret;
700 int xsize, status;
701 char **legend_v;
702 time_t start, end;
703 unsigned long step, col_cnt;
704 rrd_value_t *data, *datai;
705
706 if (convert_args("xport", args, &rrdtool_argv, &rrdtool_argc) == -1)
1
Assuming the condition is false
2
Taking false branch
707 return NULL((void*)0);
708
709 Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();
710 status = rrd_xport(rrdtool_argc, rrdtool_argv, &xsize, &start, &end, &step,
711 &col_cnt, &legend_v, &data);
712 Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); }
713
714 if (status == -1) {
3
Assuming the condition is false
4
Taking false branch
715 PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
716 rrd_clear_error();
717 ret = NULL((void*)0);
718 } else {
719 PyObject *meta_dict, *data_list, *legend_list, *t;
720 rrd_value_t dv;
721 unsigned long i, j, row_cnt = (end - start) / step;
722
723 ret = PyDict_New();
724 meta_dict = PyDict_New();
725 legend_list = PyList_New(col_cnt);
726 data_list = PyList_New(row_cnt);
727
728 PyDict_SetItem(ret, PyRRD_String_FromString("meta")PyUnicode_FromString("meta"), meta_dict);
729 PyDict_SetItem(ret, PyRRD_String_FromString("data")PyUnicode_FromString("data"), data_list);
730
731 datai = data;
732
733 PyDict_SetItem(meta_dict,
734 PyRRD_String_FromString("start")PyUnicode_FromString("start"),
735 PyRRD_Int_FromLong((long) start)PyLong_FromLong((long) start));
736 PyDict_SetItem(meta_dict,
737 PyRRD_String_FromString("end")PyUnicode_FromString("end"),
5
Calling 'PyUnicode_FromString'
7
Returning from 'PyUnicode_FromString'
8
PyObject ownership leak with reference count of 1
738 PyRRD_Int_FromLong((long) end)PyLong_FromLong((long) end));
739 PyDict_SetItem(meta_dict,
740 PyRRD_String_FromString("step")PyUnicode_FromString("step"),
741 PyRRD_Int_FromLong((long) step)PyLong_FromLong((long) step));
742 PyDict_SetItem(meta_dict,
743 PyRRD_String_FromString("rows")PyUnicode_FromString("rows"),
744 PyRRD_Int_FromLong((long) row_cnt)PyLong_FromLong((long) row_cnt));
745 PyDict_SetItem(meta_dict,
746 PyRRD_String_FromString("columns")PyUnicode_FromString("columns"),
747 PyRRD_Int_FromLong((long) col_cnt)PyLong_FromLong((long) col_cnt));
748 PyDict_SetItem(meta_dict,
749 PyRRD_String_FromString("legend")PyUnicode_FromString("legend"),
750 legend_list);
751
752 for (i = 0; i < col_cnt; i++)
753 PyList_SET_ITEM(legend_list, i, PyRRD_String_FromString(legend_v[i]))PyList_SetItem(legend_list, i, PyUnicode_FromString(legend_v[
i]))
;
754
755 for (i = 0; i < row_cnt; i++) {
756 t = PyTuple_New(col_cnt);
757 PyList_SET_ITEM(data_list, i, t)PyList_SetItem(data_list, i, t);
758
759 for (j = 0; j < col_cnt; j++) {
760 dv = *(datai++);
761
762 if (isnan(dv)__builtin_isnan (dv)) {
763 PyTuple_SET_ITEM(t, j, Py_None)PyTuple_SetItem(t, j, (&_Py_NoneStruct));
764 Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct))));
765 } else {
766 PyTuple_SET_ITEM(t, j, PyFloat_FromDouble((double) dv))PyTuple_SetItem(t, j, PyFloat_FromDouble((double) dv));
767 }
768 }
769 }
770
771 for (i = 0; i < col_cnt; i++)
772 rrd_freemem(legend_v[i]);
773
774 rrd_freemem(legend_v);
775 rrd_freemem(data);
776 }
777
778 destroy_args(&rrdtool_argv);
779
780 return ret;
781}
782
783static char _rrdtool_tune__doc__[] = "Modify some basic properties of a " \
784 "Round Robin Database.\n\n\
785 Usage: tune(args..)\n\
786 Arguments:\n\n\
787 filename\n\
788 [-h|--heartbeat ds-name:heartbeat]\n\
789 [-i|--minimum ds-name:min]\n\
790 [-a|--maximum ds-name:max]\n\
791 [-d|--data-source-type ds-name:DST]\n\
792 [-r|--data-source-rename old-name:new-name]\n\n\
793 Full documentation can be found at:\n\
794 https://oss.oetiker.ch/rrdtool/doc/rrdtune.en.html";
795
796static PyObject *
797_rrdtool_tune(PyObject *Py_UNUSED(self)_unused_self __attribute__((unused)), PyObject *args)
798{
799 char **rrdtool_argv = NULL((void*)0);
800 int rrdtool_argc = 0;
801 PyObject *ret;
802 int status;
803
804 if (convert_args("tune", args, &rrdtool_argv, &rrdtool_argc) == -1)
805 return NULL((void*)0);
806
807 Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();
808 status = rrd_tune(rrdtool_argc, rrdtool_argv);
809 Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); }
810
811 if (status == -1) {
812 PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
813 rrd_clear_error();
814 ret = NULL((void*)0);
815 } else {
816 Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct))));
817 ret = Py_None(&_Py_NoneStruct);
818 }
819
820 destroy_args(&rrdtool_argv);
821 return ret;
822}
823
824static char _rrdtool_first__doc__[] = "Get the first UNIX timestamp of the "\
825 "first data sample in an Round Robin Database.\n\n\
826 Usage: first(args..)\n\
827 Arguments:\n\n\
828 filename\n\
829 [--rraindex number]\n\
830 [-d|--daemon address]\n\n\
831 Full documentation can be found at:\n\
832 https://oss.oetiker.ch/rrdtool/doc/rrdfirst.en.html";
833
834static PyObject *
835_rrdtool_first(PyObject *Py_UNUSED(self)_unused_self __attribute__((unused)), PyObject *args)
836{
837 char **rrdtool_argv = NULL((void*)0);
838 int rrdtool_argc = 0;
839 PyObject *ret;
840 int ts;
841
842 if (convert_args("first", args, &rrdtool_argv, &rrdtool_argc) == -1)
843 return NULL((void*)0);
844
845 Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();
846 ts = rrd_first(rrdtool_argc, rrdtool_argv);
847 Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); }
848
849 if (ts == -1) {
850 PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
851 rrd_clear_error();
852 ret = NULL((void*)0);
853 } else
854 ret = PyRRD_Int_FromLong((long) ts)PyLong_FromLong((long) ts);
855
856 destroy_args(&rrdtool_argv);
857 return ret;
858}
859
860static char _rrdtool_last__doc__[] = "Get the UNIX timestamp of the most "\
861 "recent data sample in an Round Robin Database.\n\n\
862 Usage: last(args..)\n\
863 Arguments:\n\n\
864 filename\n\
865 [-d|--daemon address]\n\n\
866 Full documentation can be found at:\n\
867 https://oss.oetiker.ch/rrdtool/doc/rrdlast.en.html";
868
869static PyObject *
870_rrdtool_last(PyObject *Py_UNUSED(self)_unused_self __attribute__((unused)), PyObject *args)
871{
872 char **rrdtool_argv = NULL((void*)0);
873 int rrdtool_argc = 0;
874 PyObject *ret;
875 int ts;
876
877 if (convert_args("last", args, &rrdtool_argv, &rrdtool_argc) == -1)
878 return NULL((void*)0);
879
880 Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();
881 ts = rrd_last(rrdtool_argc, rrdtool_argv);
882 Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); }
883
884 if (ts == -1) {
885 PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
886 rrd_clear_error();
887 ret = NULL((void*)0);
888 } else
889 ret = PyRRD_Int_FromLong((long) ts)PyLong_FromLong((long) ts);
890
891 destroy_args(&rrdtool_argv);
892 return ret;
893}
894
895static char _rrdtool_resize__doc__[] = "Modify the number of rows in a "\
896 "Round Robin Database.\n\n\
897 Usage: resize(args..)\n\
898 Arguments:\n\n\
899 filename\n\
900 rra-num\n\
901 GROW|SHRINK\n\
902 rows\n\n\
903 Full documentation can be found at:\n\
904 https://oss.oetiker.ch/rrdtool/doc/rrdlast.en.html";
905
906static PyObject *
907_rrdtool_resize(PyObject *Py_UNUSED(self)_unused_self __attribute__((unused)), PyObject *args)
908{
909 char **rrdtool_argv = NULL((void*)0);
910 int rrdtool_argc = 0;
911 PyObject *ret;
912 int status;
913
914 if (convert_args("resize", args, &rrdtool_argv, &rrdtool_argc) == -1)
915 return NULL((void*)0);
916
917 Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();
918 status = rrd_resize(rrdtool_argc, rrdtool_argv);
919 Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); }
920
921 if (status == -1) {
922 PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
923 rrd_clear_error();
924 ret = NULL((void*)0);
925 } else {
926 Py_INCREF(Py_None)_Py_INCREF(((PyObject*)((&_Py_NoneStruct))));
927 ret = Py_None(&_Py_NoneStruct);
928 }
929
930 destroy_args(&rrdtool_argv);
931 return ret;
932}
933
934static char _rrdtool_info__doc__[] = "Extract header information from an "\
935 "Round Robin Database.\n\n\
936 Usage: info(filename, ...)\n\
937 Arguments:\n\n\
938 filename\n\
939 [-d|--daemon address]\n\
940 [-F|--noflush]\n\n\
941 Full documentation can be found at:\n\
942 https://oss.oetiker.ch/rrdtool/doc/rrdinfo.en.html";
943
944static PyObject *
945_rrdtool_info(PyObject *Py_UNUSED(self)_unused_self __attribute__((unused)), PyObject *args)
946{
947 char **rrdtool_argv = NULL((void*)0);
948 int rrdtool_argc = 0;
949 PyObject *ret;
950 rrd_info_t *data;
951
952 if (convert_args("info", args, &rrdtool_argv, &rrdtool_argc) == -1)
953 return NULL((void*)0);
954
955 Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();
956 data = rrd_info(rrdtool_argc, rrdtool_argv);
957 Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); }
958
959 if (data == NULL((void*)0)) {
960 PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
961 rrd_clear_error();
962 ret = NULL((void*)0);
963 } else {
964 ret = _rrdtool_util_info2dict(data);
965 rrd_info_free(data);
966 }
967
968 destroy_args(&rrdtool_argv);
969 return ret;
970}
971
972static char _rrdtool_lastupdate__doc__[] = "Returns datetime and value stored "\
973 "for each datum in the most recent update of an RRD.\n\n\
974 Usage: lastupdate(filename, ...)\n\
975 Arguments:\n\n\
976 filename\n\
977 [-d|--daemon address]\n\n\
978 Full documentation can be found at:\n\
979 https://oss.oetiker.ch/rrdtool/doc/rrdlastupdate.en.html";
980
981static PyObject *
982_rrdtool_lastupdate(PyObject *Py_UNUSED(self)_unused_self __attribute__((unused)), PyObject *args)
983{
984 char **rrdtool_argv = NULL((void*)0);
985 int rrdtool_argc = 0;
986 PyObject *ret, *ds_dict, *lastupd;
987 int status;
988 time_t last_update;
989 char **ds_names, **last_ds;
990 unsigned long ds_cnt, i;
991
992 if (convert_args("lastupdate", args, &rrdtool_argv, &rrdtool_argc) == -1)
993 return NULL((void*)0);
994 else if (rrdtool_argc < 2) {
995 PyErr_SetString(rrdtool_ProgrammingError, "Missing filename argument");
996 return NULL((void*)0);
997 }
998
999 Py_BEGIN_ALLOW_THREADS{ PyThreadState *_save; _save = PyEval_SaveThread();
1000 status = rrd_lastupdate_r(rrdtool_argv[1],
1001 &last_update,
1002 &ds_cnt,
1003 &ds_names,
1004 &last_ds);
1005 Py_END_ALLOW_THREADSPyEval_RestoreThread(_save); }
1006
1007 if (status != 0) {
1008 PyErr_SetString(rrdtool_OperationalError, rrd_get_error());
1009 rrd_clear_error();
1010 ret = NULL((void*)0);
1011 } else {
1012 /* convert last_update to Python datetime object */
1013 ret = PyDict_New();
1014 ds_dict = PyDict_New();
1015 lastupd = PyRRD_DateTime_FromTS(last_update);
1016
1017 PyDict_SetItemString(ret, "date", lastupd);
1018 PyDict_SetItemString(ret, "ds", ds_dict);
1019
1020 Py_DECREF(lastupd)_Py_DECREF(((PyObject*)(lastupd)));
1021 Py_DECREF(ds_dict)_Py_DECREF(((PyObject*)(ds_dict)));
1022
1023 for (i = 0; i < ds_cnt; i++) {
1024 PyObject* val = Py_None(&_Py_NoneStruct);
1025
1026 double num;
1027 if (sscanf(last_ds[i], "%lf", &num) == 1) {
1028 val = PyFloat_FromDouble(num);
1029 }
1030
1031 if (!val)
1032 return NULL((void*)0);
1033
1034 PyDict_SetItemString(ds_dict, ds_names[i], val);
1035
1036 if (val != Py_None(&_Py_NoneStruct))
1037 Py_DECREF(val)_Py_DECREF(((PyObject*)(val)));
1038
1039 free(last_ds[i]);
1040 free(ds_names[i]);
1041 }
1042
1043 free(last_ds);
1044 free(ds_names);
1045
1046 }
1047
1048 destroy_args(&rrdtool_argv);
1049
1050 return ret;
1051}
1052
1053#ifdef WITH_FETCH_CB1
1054
1055/** A Python object which will hold a callable for fetch callbacks */
1056static PyObject *_rrdtool_fetch_callable = NULL((void*)0);
1057
1058static int
1059_rrdtool_fetch_cb_wrapper(
1060 const char *filename,
1061 enum cf_en cf_idx,
1062 time_t *start,
1063 time_t *end,
1064 unsigned long *step,
1065 unsigned long *ds_cnt,
1066 char ***ds_namv,
1067 rrd_value_t **data)
1068{
1069 PyObject *args;
1070 PyObject *kwargs;
1071 PyObject *ret = NULL((void*)0);
1072 PyObject *tmp;
1073 PyObject *tmp_min_ts;
1074 PyGILState_STATE gstate;
1075 Py_ssize_t rowcount = 0;
1076 int rc = -1;
1077 unsigned int i, ii;
1078
1079 gstate = PyGILState_Ensure();
1080
1081 if (_rrdtool_fetch_callable == NULL((void*)0)) {
1082 rrd_set_error("use rrdtool.register_fetch_cb to register a fetch callback");
1083 goto gil_release_err;
1084 }
1085
1086 args = PyTuple_New(0);
1087 kwargs = PyDict_New();
1088
1089 /* minimum possible UNIX datetime */
1090 tmp_min_ts = PyLong_FromLong(0);
1091
1092 PyObject *po_filename = PyRRD_String_FromString(filename)PyUnicode_FromString(filename);
1093 PyDict_SetItemString(kwargs, "filename", po_filename);
1094 Py_DECREF(po_filename)_Py_DECREF(((PyObject*)(po_filename)));
1095
1096 PyObject *po_cfstr = PyRRD_String_FromString(PyRRD_String_FromCF(cf_idx))PyUnicode_FromString(PyRRD_String_FromCF(cf_idx));
1097 PyDict_SetItemString(kwargs, "cf", po_cfstr);
1098 Py_DECREF(po_cfstr)_Py_DECREF(((PyObject*)(po_cfstr)));
1099
1100 PyObject *po_start = PyLong_FromLong(*start);
1101 PyDict_SetItemString(kwargs, "start", po_start);
1102 Py_DECREF(po_start)_Py_DECREF(((PyObject*)(po_start)));
1103
1104 PyObject *po_end = PyLong_FromLong(*end);
1105 PyDict_SetItemString(kwargs, "end", po_end);
1106 Py_DECREF(po_end)_Py_DECREF(((PyObject*)(po_end)));
1107
1108 PyObject *po_step = PyLong_FromUnsignedLong(*step);
1109 PyDict_SetItemString(kwargs, "step", po_step);
1110 Py_DECREF(po_step)_Py_DECREF(((PyObject*)(po_step)));
1111
1112 /* execute Python callback method */
1113 ret = PyObject_Call(_rrdtool_fetch_callable, args, kwargs);
1114 Py_DECREF(args)_Py_DECREF(((PyObject*)(args)));
1115 Py_DECREF(kwargs)_Py_DECREF(((PyObject*)(kwargs)));
1116
1117 if (ret == NULL((void*)0)) {
1118 rrd_set_error("calling python callback failed");
1119 goto gil_release_err;
1120 }
1121
1122 /* handle return value of callback */
1123 if (!PyDict_Check(ret)((((((PyObject*)(ret))->ob_type))->tp_flags & ((1UL
<< 29))) != 0)
) {
1124 rrd_set_error("expected callback method to be a dict");
1125 goto gil_release_err;
1126 }
1127
1128 tmp = PyDict_GetItemString(ret, "step");
1129 if (tmp == NULL((void*)0)) {
1130 rrd_set_error("expected 'step' key in callback return value");
1131 goto gil_release_err;
1132 } else if (!PyRRD_Long_Check(tmp)((((((PyObject*)(tmp))->ob_type))->tp_flags & ((1UL
<< 24))) != 0)
) {
1133 rrd_set_error("the 'step' key in callback return value must be int");
1134 goto gil_release_err;
1135 } else
1136 *step = PyLong_AsLong(tmp);
1137
1138 tmp = PyDict_GetItemString(ret, "start");
1139 if (tmp == NULL((void*)0)) {
1140 rrd_set_error("expected 'start' key in callback return value");
1141 goto gil_release_err;
1142 } else if (!PyRRD_Long_Check(tmp)((((((PyObject*)(tmp))->ob_type))->tp_flags & ((1UL
<< 24))) != 0)
) {
1143 rrd_set_error("expected 'start' key in callback return value to be "
1144 "of type int");
1145 goto gil_release_err;
1146 } else if (PyObject_RichCompareBool(tmp, tmp_min_ts, Py_EQ2) ||
1147 PyObject_RichCompareBool(tmp, po_start, Py_LT0)) {
1148 rrd_set_error("expected 'start' value in callback return dict to be "
1149 "equal or earlier than passed start timestamp");
1150 goto gil_release_err;
1151 } else {
1152 *start = PyLong_AsLong(po_start);
1153
1154 if (*start == -1) {
1155 rrd_set_error("expected 'start' value in callback return value to"
1156 " not exceed LONG_MAX");
1157 goto gil_release_err;
1158 }
1159 }
1160
1161 tmp = PyDict_GetItemString(ret, "data");
1162 if (tmp == NULL((void*)0)) {
1163 rrd_set_error("expected 'data' key in callback return value");
1164 goto gil_release_err;
1165 } else if (!PyDict_Check(tmp)((((((PyObject*)(tmp))->ob_type))->tp_flags & ((1UL
<< 29))) != 0)
) {
1166 rrd_set_error("expected 'data' key in callback return value of type "
1167 "dict");
1168 goto gil_release_err;
1169 } else {
1170 *ds_cnt = (unsigned long)PyDict_Size(tmp);
1171 *ds_namv = (char **)calloc(*ds_cnt, sizeof(char *));
1172
1173 if (*ds_namv == NULL((void*)0)) {
1174 rrd_set_error("an error occurred while allocating memory for "
1175 "ds_namv when allocating memory for python callback");
1176 goto gil_release_err;
1177 }
1178
1179 PyObject *key, *value;
1180 Py_ssize_t pos = 0; /* don't use pos for indexing */
1181 unsigned int x = 0;
1182
1183 while (PyDict_Next(tmp, &pos, &key, &value)) {
1184 const char *key_str = PyRRD_String_AS_STRING(key)PyUnicode_AsUTF8(key);
1185
1186 if (key_str == NULL((void*)0)) {
1187 rrd_set_error("key of 'data' element from callback return "
1188 "value is not a string");
1189 goto gil_release_free_dsnamv_err;
1190 } else if (strlen(key_str) > DS_NAM_SIZE20) {
1191 rrd_set_error("key '%s' longer than the allowed maximum of %d "
1192 "byte", key_str, DS_NAM_SIZE20 - 1);
1193 goto gil_release_free_dsnamv_err;
1194 }
1195
1196 if ((((*ds_namv)[x]) = (char *)malloc(sizeof(char) * DS_NAM_SIZE20)) == NULL((void*)0)) {
1197 rrd_set_error("malloc fetch ds_namv entry");
1198 goto gil_release_free_dsnamv_err;
1199 }
1200
1201 strncpy((*ds_namv)[x], key_str, DS_NAM_SIZE20 - 1);
1202 (*ds_namv)[x][DS_NAM_SIZE20 - 1] = '\0';
1203
1204 if (!PyList_Check(value)((((((PyObject*)(value))->ob_type))->tp_flags & ((1UL
<< 25))) != 0)
) {
1205 rrd_set_error("expected 'data' dict values in callback return "
1206 "value of type list");
1207 goto gil_release_free_dsnamv_err;
1208 } else if (PyList_Size(value) > rowcount)
1209 rowcount = PyList_Size(value);
1210
1211 ++x;
1212 }
1213
1214 *end = *start + *step * rowcount;
1215
1216 if (((*data) = (rrd_value_t *)malloc(*ds_cnt * rowcount * sizeof(rrd_value_t))) == NULL((void*)0)) {
1217 rrd_set_error("malloc fetch data area");
1218 goto gil_release_free_dsnamv_err;
1219 }
1220
1221 for (i = 0; i < *ds_cnt; i++) {
1222 for (ii = 0; ii < (unsigned int)rowcount; ii++) {
1223 char *ds_namv_i = (*ds_namv)[i];
1224 double va;
1225 PyObject *lstv = PyList_GetItem(PyDict_GetItemString(tmp, ds_namv_i), ii);
1226
1227 /* lstv may be NULL here in case an IndexError has been raised;
1228 in such case the rowcount is higher than the number of elements for
1229 the list of that ds. use DNAN as value for these then */
1230 if (lstv == NULL((void*)0) || lstv == Py_None(&_Py_NoneStruct)) {
1231 if (lstv == NULL((void*)0))
1232 PyErr_Clear();
1233 va = DNANrrd_set_to_DNAN();
1234 }
1235 else {
1236 va = PyFloat_AsDouble(lstv);
1237 if (va == -1.0 && PyErr_Occurred()) {
1238 PyObject *exc_type, *exc_value, *exc_value_str = NULL((void*)0), *exc_tb;
1239 PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
1240
1241 if (exc_value != NULL((void*)0)) {
1242 exc_value_str = PyObject_Str(exc_value);
1243 rrd_set_error((char *)PyRRD_String_AS_STRING(exc_value_str)PyUnicode_AsUTF8(exc_value_str));
1244 Py_DECREF(exc_value)_Py_DECREF(((PyObject*)(exc_value)));
1245 }
1246
1247 Py_DECREF(exc_type)_Py_DECREF(((PyObject*)(exc_type)));
1248 Py_DECREF(exc_value_str)_Py_DECREF(((PyObject*)(exc_value_str)));
1249 if (exc_tb != NULL((void*)0))
1250 Py_DECREF(exc_tb)_Py_DECREF(((PyObject*)(exc_tb)));
1251 goto gil_release_free_dsnamv_err;
1252 }
1253 }
1254
1255 (*data)[i + ii * (*ds_cnt)] = va;
1256 }
1257 }
1258 }
1259
1260 /* success */
1261 rc = 1;
1262 goto gil_release;
1263
1264gil_release_free_dsnamv_err:
1265 for (i = 0; i < *ds_cnt; i++) {
1266 if ((*ds_namv)[i]) {
1267 free((*ds_namv)[i]);
1268 }
1269 }
1270
1271 free(*ds_namv);
1272
1273gil_release_err:
1274 rc = -1;
1275
1276gil_release:
1277 if (ret != NULL((void*)0))
1278 Py_DECREF(ret)_Py_DECREF(((PyObject*)(ret)));
1279 PyGILState_Release(gstate);
1280 return rc;
1281}
1282
1283static char _rrdtool_register_fetch_cb__doc__[] = "Register callback for "
1284 "fetching data";
1285
1286static PyObject *
1287_rrdtool_register_fetch_cb(PyObject *Py_UNUSED(self)_unused_self __attribute__((unused)), PyObject *args)
1288{
1289 PyObject *callable;
1290
1291 if (!PyArg_ParseTuple(args, "O", &callable))
1292 return NULL((void*)0);
1293 else if (!PyCallable_Check(callable)) {
1294 PyErr_SetString(rrdtool_ProgrammingError, "first argument must be callable");
1295 return NULL((void*)0);
1296 } else {
1297 _rrdtool_fetch_callable = callable;
1298 rrd_fetch_cb_register(_rrdtool_fetch_cb_wrapper);
1299 Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (&
_Py_NoneStruct)
;
1300 }
1301}
1302
1303static char _rrdtool_clear_fetch_cb__doc__[] = "Clear callback for "
1304 "fetching data";
1305
1306static PyObject *
1307_rrdtool_clear_fetch_cb(PyObject *Py_UNUSED(self)_unused_self __attribute__((unused)), PyObject *Py_UNUSED(args)_unused_args __attribute__((unused)))
1308{
1309 if (_rrdtool_fetch_callable == NULL((void*)0)) {
1310 PyErr_SetString(rrdtool_ProgrammingError, "no callback has been set previously");
1311 return NULL((void*)0);
1312 }
1313
1314 _rrdtool_fetch_callable = NULL((void*)0);
1315 rrd_fetch_cb_register(NULL((void*)0));
1316 Py_RETURN_NONEreturn _Py_INCREF(((PyObject*)((&_Py_NoneStruct)))), (&
_Py_NoneStruct)
;
1317}
1318
1319#endif /* WITH_FETCH_CB */
1320
1321static char _rrdtool_lib_version__doc__[] = "Get the version this binding "\
1322 "was compiled against.";
1323
1324/**
1325 * Returns a str object that contains the librrd version.
1326 *
1327 * @return librrd version (Python str object)
1328 */
1329static PyObject *
1330_rrdtool_lib_version(PyObject *Py_UNUSED(self)_unused_self __attribute__((unused)), PyObject *Py_UNUSED(args)_unused_args __attribute__((unused)))
1331{
1332 return PyRRD_String_FromString(rrd_strversion())PyUnicode_FromString(rrd_strversion());
1333}
1334
1335/** Method table. */
1336static PyMethodDef rrdtool_methods[] = {
1337 {"create", (PyCFunction)_rrdtool_create,
1338 METH_VARARGS0x0001, _rrdtool_create__doc__},
1339 {"dump", (PyCFunction)_rrdtool_dump,
1340 METH_VARARGS0x0001, _rrdtool_dump__doc__},
1341 {"update", (PyCFunction)_rrdtool_update,
1342 METH_VARARGS0x0001, _rrdtool_update__doc__},
1343 {"updatev", (PyCFunction)_rrdtool_updatev,
1344 METH_VARARGS0x0001, _rrdtool_updatev__doc__},
1345 {"fetch", (PyCFunction)_rrdtool_fetch,
1346 METH_VARARGS0x0001, _rrdtool_fetch__doc__},
1347 {"flushcached", (PyCFunction)_rrdtool_flushcached,
1348 METH_VARARGS0x0001, _rrdtool_flushcached__doc__},
1349 {"graph", (PyCFunction)_rrdtool_graph,
1350 METH_VARARGS0x0001, _rrdtool_graph__doc__},
1351 {"graphv", (PyCFunction)_rrdtool_graphv,
1352 METH_VARARGS0x0001, _rrdtool_graphv__doc__},
1353 {"xport", (PyCFunction)_rrdtool_xport,
1354 METH_VARARGS0x0001, _rrdtool_xport__doc__},
1355 {"tune", (PyCFunction)_rrdtool_tune,
1356 METH_VARARGS0x0001, _rrdtool_tune__doc__},
1357 {"first", (PyCFunction)_rrdtool_first,
1358 METH_VARARGS0x0001, _rrdtool_first__doc__},
1359 {"last", (PyCFunction)_rrdtool_last,
1360 METH_VARARGS0x0001, _rrdtool_last__doc__},
1361 {"resize", (PyCFunction)_rrdtool_resize,
1362 METH_VARARGS0x0001, _rrdtool_resize__doc__},
1363 {"info", (PyCFunction)_rrdtool_info,
1364 METH_VARARGS0x0001, _rrdtool_info__doc__},
1365 {"lastupdate", (PyCFunction)_rrdtool_lastupdate,
1366 METH_VARARGS0x0001, _rrdtool_lastupdate__doc__},
1367#ifdef WITH_FETCH_CB1
1368 {"register_fetch_cb", (PyCFunction)_rrdtool_register_fetch_cb,
1369 METH_VARARGS0x0001, _rrdtool_register_fetch_cb__doc__},
1370 {"clear_fetch_cb", (PyCFunction)_rrdtool_clear_fetch_cb,
1371 METH_NOARGS0x0004, _rrdtool_clear_fetch_cb__doc__},
1372#endif /* WITH_FETCH_CB */
1373 {"lib_version", (PyCFunction)_rrdtool_lib_version,
1374 METH_NOARGS0x0004, _rrdtool_lib_version__doc__},
1375 {NULL((void*)0), NULL((void*)0), 0, NULL((void*)0)}
1376};
1377
1378/** Library init function. */
1379#ifdef HAVE_PY3K
1380static struct PyModuleDef rrdtoolmodule = {
1381 .m_base = PyModuleDef_HEAD_INIT{ { 1, ((void*)0) }, ((void*)0), 0, ((void*)0), },
1382 .m_name = "rrdtool",
1383 .m_doc = "Python bindings for rrdtool",
1384 .m_size = -1,
1385 .m_methods = rrdtool_methods
1386};
1387
1388#endif
1389
1390#ifdef HAVE_PY3K
1391PyMODINIT_FUNCPyObject*
1392PyInit_rrdtool(void)
1393#else
1394void
1395initrrdtool(void)
1396#endif
1397{
1398 PyObject *m;
1399
1400 PyDateTime_IMPORTPyDateTimeAPI = (PyDateTime_CAPI *)PyCapsule_Import("datetime.datetime_CAPI"
, 0)
; /* initialize PyDateTime_ functions */
1401
1402 /* make sure that the GIL has been created as we need to aquire it */
1403 if (!PyEval_ThreadsInitialized())
1404 PyEval_InitThreads();
1405
1406#ifdef HAVE_PY3K
1407 m = PyModule_Create(&rrdtoolmodule)PyModule_Create2(&rrdtoolmodule, 1013);
1408#else
1409 m = Py_InitModule3("rrdtool",
1410 rrdtool_methods,
1411 "Python bindings for rrdtool");
1412#endif
1413
1414 if (m == NULL((void*)0))
1415#ifdef HAVE_PY3K
1416 return NULL((void*)0);
1417#else
1418 return;
1419#endif
1420
1421 rrdtool_ProgrammingError = PyErr_NewException("rrdtool.ProgrammingError",
1422 NULL((void*)0), NULL((void*)0));
1423 Py_INCREF(rrdtool_ProgrammingError)_Py_INCREF(((PyObject*)(rrdtool_ProgrammingError)));
1424 PyModule_AddObject(m, "ProgrammingError", rrdtool_ProgrammingError);
1425
1426 rrdtool_OperationalError = PyErr_NewException("rrdtool.OperationalError",
1427 NULL((void*)0), NULL((void*)0));
1428 Py_INCREF(rrdtool_OperationalError)_Py_INCREF(((PyObject*)(rrdtool_OperationalError)));
1429 PyModule_AddObject(m, "OperationalError", rrdtool_OperationalError);
1430 PyModule_AddStringConstant(m, "__version__", _version);
1431
1432#ifdef HAVE_PY3K
1433 return m;
1434#endif
1435}

/opt/pyrefcon/lib/pyrefcon/models/models/PyUnicode_FromString.model

1#ifndef PyUnicode_FromString
2struct _object;
3typedef struct _object PyObject;
4PyObject* clang_analyzer_PyObject_New_Reference();
5PyObject *PyUnicode_FromString(const char *u) {
6 return clang_analyzer_PyObject_New_Reference();
6
Setting reference count to 1
7}
8#else
9#warning "API PyUnicode_FromString is defined as a macro."
10#endif