1 /**
2 * collectd - src/pyvalues.c
3 * Copyright (C) 2009 Sven Trenkel
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Sven Trenkel <collectd at semidefinite.de>
25 **/
27 #include <Python.h>
28 #include <structmember.h>
30 #include "collectd.h"
32 #include "common.h"
34 #include "cpython.h"
36 typedef struct {
37 int (*add_string)(void *, const char *, const char *);
38 int (*add_signed_int)(void *, const char *, int64_t);
39 int (*add_unsigned_int)(void *, const char *, uint64_t);
40 int (*add_double)(void *, const char *, double);
41 int (*add_boolean)(void *, const char *, _Bool);
42 } cpy_build_meta_handler_t;
44 #define FreeAll() \
45 do { \
46 PyMem_Free(type); \
47 PyMem_Free(plugin_instance); \
48 PyMem_Free(type_instance); \
49 PyMem_Free(plugin); \
50 PyMem_Free(host); \
51 } while (0)
53 #define CPY_BUILD_META_FUNC(meta_type, func, val_type) \
54 static int cpy_ ## func(void *meta, const char *key, val_type val) { \
55 return func((meta_type *)meta, key, val); \
56 }
58 #define CPY_BUILD_META_HANDLER(func_prefix, meta_type) \
59 CPY_BUILD_META_FUNC(meta_type, func_prefix ## _add_string, const char *) \
60 CPY_BUILD_META_FUNC(meta_type, func_prefix ## _add_signed_int, int64_t) \
61 CPY_BUILD_META_FUNC(meta_type, func_prefix ## _add_unsigned_int, uint64_t) \
62 CPY_BUILD_META_FUNC(meta_type, func_prefix ## _add_double, double) \
63 CPY_BUILD_META_FUNC(meta_type, func_prefix ## _add_boolean, _Bool) \
64 \
65 static cpy_build_meta_handler_t cpy_ ## func_prefix = { \
66 .add_string = cpy_ ## func_prefix ## _add_string, \
67 .add_signed_int = cpy_ ## func_prefix ## _add_signed_int, \
68 .add_unsigned_int = cpy_ ## func_prefix ## _add_unsigned_int, \
69 .add_double = cpy_ ## func_prefix ## _add_double, \
70 .add_boolean = cpy_ ## func_prefix ## _add_boolean \
71 }
73 static PyObject *cpy_common_repr(PyObject *s) {
74 PyObject *ret, *tmp;
75 static PyObject *l_type = NULL, *l_type_instance = NULL, *l_plugin = NULL,
76 *l_plugin_instance = NULL;
77 static PyObject *l_host = NULL, *l_time = NULL;
78 PluginData *self = (PluginData *)s;
80 if (l_type == NULL)
81 l_type = cpy_string_to_unicode_or_bytes("(type=");
82 if (l_type_instance == NULL)
83 l_type_instance = cpy_string_to_unicode_or_bytes(",type_instance=");
84 if (l_plugin == NULL)
85 l_plugin = cpy_string_to_unicode_or_bytes(",plugin=");
86 if (l_plugin_instance == NULL)
87 l_plugin_instance = cpy_string_to_unicode_or_bytes(",plugin_instance=");
88 if (l_host == NULL)
89 l_host = cpy_string_to_unicode_or_bytes(",host=");
90 if (l_time == NULL)
91 l_time = cpy_string_to_unicode_or_bytes(",time=");
93 if (!l_type || !l_type_instance || !l_plugin || !l_plugin_instance ||
94 !l_host || !l_time)
95 return NULL;
97 ret = cpy_string_to_unicode_or_bytes(s->ob_type->tp_name);
99 CPY_STRCAT(&ret, l_type);
100 tmp = cpy_string_to_unicode_or_bytes(self->type);
101 CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
102 CPY_STRCAT_AND_DEL(&ret, tmp);
104 if (self->type_instance[0] != 0) {
105 CPY_STRCAT(&ret, l_type_instance);
106 tmp = cpy_string_to_unicode_or_bytes(self->type_instance);
107 CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
108 CPY_STRCAT_AND_DEL(&ret, tmp);
109 }
111 if (self->plugin[0] != 0) {
112 CPY_STRCAT(&ret, l_plugin);
113 tmp = cpy_string_to_unicode_or_bytes(self->plugin);
114 CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
115 CPY_STRCAT_AND_DEL(&ret, tmp);
116 }
118 if (self->plugin_instance[0] != 0) {
119 CPY_STRCAT(&ret, l_plugin_instance);
120 tmp = cpy_string_to_unicode_or_bytes(self->plugin_instance);
121 CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
122 CPY_STRCAT_AND_DEL(&ret, tmp);
123 }
125 if (self->host[0] != 0) {
126 CPY_STRCAT(&ret, l_host);
127 tmp = cpy_string_to_unicode_or_bytes(self->host);
128 CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
129 CPY_STRCAT_AND_DEL(&ret, tmp);
130 }
132 if (self->time != 0) {
133 CPY_STRCAT(&ret, l_time);
134 tmp = PyFloat_FromDouble(self->time);
135 CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
136 CPY_STRCAT_AND_DEL(&ret, tmp);
137 }
138 return ret;
139 }
141 static char time_doc[] =
142 "This is the Unix timestamp of the time this value was read.\n"
143 "For dispatching values this can be set to 0 which means \"now\".\n"
144 "This means the time the value is actually dispatched, not the time\n"
145 "it was set to 0.";
147 static char host_doc[] =
148 "The hostname of the host this value was read from.\n"
149 "For dispatching this can be set to an empty string which means\n"
150 "the local hostname as defined in collectd.conf.";
152 static char type_doc[] =
153 "The type of this value. This type has to be defined\n"
154 "in the types.db file. Attempting to set it to any other value\n"
155 "will raise a TypeError exception.\n"
156 "Assigning a type is mandatory, calling dispatch without doing\n"
157 "so will raise a RuntimeError exception.";
159 static char type_instance_doc[] = "";
161 static char plugin_doc[] =
162 "The name of the plugin that read the data. Setting this\n"
163 "member to an empty string will insert \"python\" upon dispatching.";
165 static char plugin_instance_doc[] = "";
167 static char PluginData_doc[] =
168 "This is an internal class that is the base for Values\n"
169 "and Notification. It is pretty useless by itself and is therefore not\n"
170 "exported to the collectd module.";
172 static PyObject *PluginData_new(PyTypeObject *type, PyObject *args,
173 PyObject *kwds) {
174 PluginData *self;
176 self = (PluginData *)type->tp_alloc(type, 0);
177 if (self == NULL)
178 return NULL;
180 self->time = 0;
181 self->host[0] = 0;
182 self->plugin[0] = 0;
183 self->plugin_instance[0] = 0;
184 self->type[0] = 0;
185 self->type_instance[0] = 0;
186 return (PyObject *)self;
187 }
189 static int PluginData_init(PyObject *s, PyObject *args, PyObject *kwds) {
190 PluginData *self = (PluginData *)s;
191 double time = 0;
192 char *type = NULL, *plugin_instance = NULL, *type_instance = NULL,
193 *plugin = NULL, *host = NULL;
194 static char *kwlist[] = {
195 "type", "plugin_instance", "type_instance", "plugin", "host", "time",
196 NULL};
198 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etetetetetd", kwlist, NULL,
199 &type, NULL, &plugin_instance, NULL,
200 &type_instance, NULL, &plugin, NULL, &host,
201 &time))
202 return -1;
204 if (type && plugin_get_ds(type) == NULL) {
205 PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
206 FreeAll();
207 return -1;
208 }
210 sstrncpy(self->host, host ? host : "", sizeof(self->host));
211 sstrncpy(self->plugin, plugin ? plugin : "", sizeof(self->plugin));
212 sstrncpy(self->plugin_instance, plugin_instance ? plugin_instance : "",
213 sizeof(self->plugin_instance));
214 sstrncpy(self->type, type ? type : "", sizeof(self->type));
215 sstrncpy(self->type_instance, type_instance ? type_instance : "",
216 sizeof(self->type_instance));
217 self->time = time;
219 FreeAll();
221 return 0;
222 }
224 static PyObject *PluginData_repr(PyObject *s) {
225 PyObject *ret;
226 static PyObject *l_closing = NULL;
228 if (l_closing == NULL)
229 l_closing = cpy_string_to_unicode_or_bytes(")");
231 if (l_closing == NULL)
232 return NULL;
234 ret = cpy_common_repr(s);
235 CPY_STRCAT(&ret, l_closing);
236 return ret;
237 }
239 static PyMemberDef PluginData_members[] = {
240 {"time", T_DOUBLE, offsetof(PluginData, time), 0, time_doc}, {NULL}};
242 static PyObject *PluginData_getstring(PyObject *self, void *data) {
243 const char *value = ((char *)self) + (intptr_t)data;
245 return cpy_string_to_unicode_or_bytes(value);
246 }
248 static int PluginData_setstring(PyObject *self, PyObject *value, void *data) {
249 char *old;
250 const char *new;
252 if (value == NULL) {
253 PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
254 return -1;
255 }
256 Py_INCREF(value);
257 new = cpy_unicode_or_bytes_to_string(&value);
258 if (new == NULL) {
259 Py_DECREF(value);
260 return -1;
261 }
262 old = ((char *)self) + (intptr_t)data;
263 sstrncpy(old, new, DATA_MAX_NAME_LEN);
264 Py_DECREF(value);
265 return 0;
266 }
268 static int PluginData_settype(PyObject *self, PyObject *value, void *data) {
269 char *old;
270 const char *new;
272 if (value == NULL) {
273 PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
274 return -1;
275 }
276 Py_INCREF(value);
277 new = cpy_unicode_or_bytes_to_string(&value);
278 if (new == NULL) {
279 Py_DECREF(value);
280 return -1;
281 }
283 if (plugin_get_ds(new) == NULL) {
284 PyErr_Format(PyExc_TypeError, "Dataset %s not found", new);
285 Py_DECREF(value);
286 return -1;
287 }
289 old = ((char *)self) + (intptr_t)data;
290 sstrncpy(old, new, DATA_MAX_NAME_LEN);
291 Py_DECREF(value);
292 return 0;
293 }
295 static PyGetSetDef PluginData_getseters[] = {
296 {"host", PluginData_getstring, PluginData_setstring, host_doc,
297 (void *)offsetof(PluginData, host)},
298 {"plugin", PluginData_getstring, PluginData_setstring, plugin_doc,
299 (void *)offsetof(PluginData, plugin)},
300 {"plugin_instance", PluginData_getstring, PluginData_setstring,
301 plugin_instance_doc, (void *)offsetof(PluginData, plugin_instance)},
302 {"type_instance", PluginData_getstring, PluginData_setstring,
303 type_instance_doc, (void *)offsetof(PluginData, type_instance)},
304 {"type", PluginData_getstring, PluginData_settype, type_doc,
305 (void *)offsetof(PluginData, type)},
306 {NULL}};
308 PyTypeObject PluginDataType = {
309 CPY_INIT_TYPE "collectd.PluginData", /* tp_name */
310 sizeof(PluginData), /* tp_basicsize */
311 0, /* Will be filled in later */
312 0, /* tp_dealloc */
313 0, /* tp_print */
314 0, /* tp_getattr */
315 0, /* tp_setattr */
316 0, /* tp_compare */
317 PluginData_repr, /* tp_repr */
318 0, /* tp_as_number */
319 0, /* tp_as_sequence */
320 0, /* tp_as_mapping */
321 0, /* tp_hash */
322 0, /* tp_call */
323 0, /* tp_str */
324 0, /* tp_getattro */
325 0, /* tp_setattro */
326 0, /* tp_as_buffer */
327 Py_TPFLAGS_DEFAULT |
328 Py_TPFLAGS_BASETYPE /*| Py_TPFLAGS_HAVE_GC*/, /*tp_flags*/
329 PluginData_doc, /* tp_doc */
330 0, /* tp_traverse */
331 0, /* tp_clear */
332 0, /* tp_richcompare */
333 0, /* tp_weaklistoffset */
334 0, /* tp_iter */
335 0, /* tp_iternext */
336 0, /* tp_methods */
337 PluginData_members, /* tp_members */
338 PluginData_getseters, /* tp_getset */
339 0, /* tp_base */
340 0, /* tp_dict */
341 0, /* tp_descr_get */
342 0, /* tp_descr_set */
343 0, /* tp_dictoffset */
344 PluginData_init, /* tp_init */
345 0, /* tp_alloc */
346 PluginData_new /* tp_new */
347 };
349 static char interval_doc[] =
350 "The interval is the timespan in seconds between two submits for\n"
351 "the same data source. This value has to be a positive integer, so you "
352 "can't\n"
353 "submit more than one value per second. If this member is set to a\n"
354 "non-positive value, the default value as specified in the config file "
355 "will\n"
356 "be used (default: 10).\n"
357 "\n"
358 "If you submit values more often than the specified interval, the average\n"
359 "will be used. If you submit less values, your graphs will have gaps.";
361 static char values_doc[] =
362 "These are the actual values that get dispatched to collectd.\n"
363 "It has to be a sequence (a tuple or list) of numbers.\n"
364 "The size of the sequence and the type of its content depend on the type\n"
365 "member in the types.db file. For more information on this read the\n"
366 "types.db man page.\n"
367 "\n"
368 "If the sequence does not have the correct size upon dispatch a "
369 "RuntimeError\n"
370 "exception will be raised. If the content of the sequence is not a "
371 "number,\n"
372 "a TypeError exception will be raised.";
374 static char meta_doc[] =
375 "These are the meta data for this Value object.\n"
376 "It has to be a dictionary of numbers, strings or bools. All keys must be\n"
377 "strings. int and long objects will be dispatched as signed integers "
378 "unless\n"
379 "they are between 2**63 and 2**64-1, which will result in an unsigned "
380 "integer.\n"
381 "You can force one of these storage classes by using the classes\n"
382 "collectd.Signed and collectd.Unsigned. A meta object received by a write\n"
383 "callback will always contain Signed or Unsigned objects.";
385 static char dispatch_doc[] =
386 "dispatch([type][, values][, plugin_instance][, type_instance]"
387 "[, plugin][, host][, time][, interval]) -> None. Dispatch a value list.\n"
388 "\n"
389 "Dispatch this instance to the collectd process. The object has members\n"
390 "for each of the possible arguments for this method. For a detailed "
391 "explanation\n"
392 "of these parameters see the member of the same same.\n"
393 "\n"
394 "If you do not submit a parameter the value saved in its member will be "
395 "submitted.\n"
396 "If you do provide a parameter it will be used instead, without altering "
397 "the member.";
399 static char write_doc[] =
400 "write([destination][, type][, values][, plugin_instance][, type_instance]"
401 "[, plugin][, host][, time][, interval]) -> None. Dispatch a value list.\n"
402 "\n"
403 "Write this instance to a single plugin or all plugins if 'destination' is "
404 "omitted.\n"
405 "This will bypass the main collectd process and all filtering and "
406 "caching.\n"
407 "Other than that it works similar to 'dispatch'. In most cases 'dispatch' "
408 "should be\n"
409 "used instead of 'write'.\n";
411 static char Values_doc[] = "A Values object used for dispatching values to "
412 "collectd and receiving values from write "
413 "callbacks.";
415 static PyObject *Values_new(PyTypeObject *type, PyObject *args,
416 PyObject *kwds) {
417 Values *self;
419 self = (Values *)PluginData_new(type, args, kwds);
420 if (self == NULL)
421 return NULL;
423 self->values = PyList_New(0);
424 self->meta = PyDict_New();
425 self->interval = 0;
426 return (PyObject *)self;
427 }
429 static int Values_init(PyObject *s, PyObject *args, PyObject *kwds) {
430 Values *self = (Values *)s;
431 double interval = 0, time = 0;
432 PyObject *values = NULL, *meta = NULL, *tmp;
433 char *type = NULL, *plugin_instance = NULL, *type_instance = NULL,
434 *plugin = NULL, *host = NULL;
435 static char *kwlist[] = {
436 "type", "values", "plugin_instance", "type_instance", "plugin",
437 "host", "time", "interval", "meta", NULL};
439 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetddO", kwlist, NULL,
440 &type, &values, NULL, &plugin_instance, NULL,
441 &type_instance, NULL, &plugin, NULL, &host,
442 &time, &interval, &meta))
443 return -1;
445 if (type && plugin_get_ds(type) == NULL) {
446 PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
447 FreeAll();
448 return -1;
449 }
451 sstrncpy(self->data.host, host ? host : "", sizeof(self->data.host));
452 sstrncpy(self->data.plugin, plugin ? plugin : "", sizeof(self->data.plugin));
453 sstrncpy(self->data.plugin_instance, plugin_instance ? plugin_instance : "",
454 sizeof(self->data.plugin_instance));
455 sstrncpy(self->data.type, type ? type : "", sizeof(self->data.type));
456 sstrncpy(self->data.type_instance, type_instance ? type_instance : "",
457 sizeof(self->data.type_instance));
458 self->data.time = time;
460 FreeAll();
462 if (values == NULL) {
463 values = PyList_New(0);
464 PyErr_Clear();
465 } else {
466 Py_INCREF(values);
467 }
469 if (meta == NULL) {
470 meta = PyDict_New();
471 PyErr_Clear();
472 } else {
473 Py_INCREF(meta);
474 }
476 tmp = self->values;
477 self->values = values;
478 Py_XDECREF(tmp);
480 tmp = self->meta;
481 self->meta = meta;
482 Py_XDECREF(tmp);
484 self->interval = interval;
485 return 0;
486 }
488 static int cpy_build_meta(PyObject *meta, cpy_build_meta_handler_t *meta_func,
489 void *m) {
490 int s;
491 PyObject *l;
493 if ((meta == NULL) || (meta == Py_None))
494 return -1;
496 l = PyDict_Items(meta); /* New reference. */
497 if (!l) {
498 cpy_log_exception("building meta data");
499 return -1;
500 }
501 s = PyList_Size(l);
502 if (s <= 0) {
503 Py_XDECREF(l);
504 return -1;
505 }
507 for (int i = 0; i < s; ++i) {
508 const char *string, *keystring;
509 PyObject *key, *value, *item, *tmp;
511 item = PyList_GET_ITEM(l, i);
512 key = PyTuple_GET_ITEM(item, 0);
513 Py_INCREF(key);
514 keystring = cpy_unicode_or_bytes_to_string(&key);
515 if (!keystring) {
516 PyErr_Clear();
517 Py_XDECREF(key);
518 continue;
519 }
520 value = PyTuple_GET_ITEM(item, 1);
521 Py_INCREF(value);
522 if (value == Py_True) {
523 meta_func->add_boolean(m, keystring, 1);
524 } else if (value == Py_False) {
525 meta_func->add_boolean(m, keystring, 0);
526 } else if (PyFloat_Check(value)) {
527 meta_func->add_double(m, keystring, PyFloat_AsDouble(value));
528 } else if (PyObject_TypeCheck(value, &SignedType)) {
529 long long int lli;
530 lli = PyLong_AsLongLong(value);
531 if (!PyErr_Occurred() && (lli == (int64_t)lli))
532 meta_func->add_signed_int(m, keystring, lli);
533 } else if (PyObject_TypeCheck(value, &UnsignedType)) {
534 long long unsigned llu;
535 llu = PyLong_AsUnsignedLongLong(value);
536 if (!PyErr_Occurred() && (llu == (uint64_t)llu))
537 meta_func->add_unsigned_int(m, keystring, llu);
538 } else if (PyNumber_Check(value)) {
539 long long int lli;
540 long long unsigned llu;
541 tmp = PyNumber_Long(value);
542 lli = PyLong_AsLongLong(tmp);
543 if (!PyErr_Occurred() && (lli == (int64_t)lli)) {
544 meta_func->add_signed_int(m, keystring, lli);
545 } else {
546 PyErr_Clear();
547 llu = PyLong_AsUnsignedLongLong(tmp);
548 if (!PyErr_Occurred() && (llu == (uint64_t)llu))
549 meta_func->add_unsigned_int(m, keystring, llu);
550 }
551 Py_XDECREF(tmp);
552 } else {
553 string = cpy_unicode_or_bytes_to_string(&value);
554 if (string) {
555 meta_func->add_string(m, keystring, string);
556 } else {
557 PyErr_Clear();
558 tmp = PyObject_Str(value);
559 string = cpy_unicode_or_bytes_to_string(&tmp);
560 if (string)
561 meta_func->add_string(m, keystring, string);
562 Py_XDECREF(tmp);
563 }
564 }
565 if (PyErr_Occurred())
566 cpy_log_exception("building meta data");
567 Py_XDECREF(value);
568 Py_DECREF(key);
569 }
570 Py_XDECREF(l);
571 return 0;
572 }
574 CPY_BUILD_META_HANDLER(meta_data, meta_data_t);
575 CPY_BUILD_META_HANDLER(plugin_notification_meta, notification_t);
577 static meta_data_t *cpy_build_value_meta(PyObject *meta) {
578 meta_data_t *m = meta_data_create();
579 cpy_build_meta(meta, &cpy_meta_data, (void *)m);
580 return m;
581 }
583 static void cpy_build_notification_meta(notification_t *n, PyObject *meta) {
584 cpy_build_meta(meta, &cpy_plugin_notification_meta, (void *)n);
585 }
587 static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
588 int ret;
589 const data_set_t *ds;
590 size_t size;
591 value_t *value;
592 value_list_t value_list = VALUE_LIST_INIT;
593 PyObject *values = self->values, *meta = self->meta;
594 double time = self->data.time, interval = self->interval;
595 char *host = NULL, *plugin = NULL, *plugin_instance = NULL, *type = NULL,
596 *type_instance = NULL;
598 static char *kwlist[] = {
599 "type", "values", "plugin_instance", "type_instance", "plugin",
600 "host", "time", "interval", "meta", NULL};
601 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetddO", kwlist, NULL,
602 &type, &values, NULL, &plugin_instance, NULL,
603 &type_instance, NULL, &plugin, NULL, &host,
604 &time, &interval, &meta))
605 return NULL;
607 sstrncpy(value_list.host, host ? host : self->data.host,
608 sizeof(value_list.host));
609 sstrncpy(value_list.plugin, plugin ? plugin : self->data.plugin,
610 sizeof(value_list.plugin));
611 sstrncpy(value_list.plugin_instance,
612 plugin_instance ? plugin_instance : self->data.plugin_instance,
613 sizeof(value_list.plugin_instance));
614 sstrncpy(value_list.type, type ? type : self->data.type,
615 sizeof(value_list.type));
616 sstrncpy(value_list.type_instance,
617 type_instance ? type_instance : self->data.type_instance,
618 sizeof(value_list.type_instance));
619 FreeAll();
620 if (value_list.type[0] == 0) {
621 PyErr_SetString(PyExc_RuntimeError, "type not set");
622 FreeAll();
623 return NULL;
624 }
625 ds = plugin_get_ds(value_list.type);
626 if (ds == NULL) {
627 PyErr_Format(PyExc_TypeError, "Dataset %s not found", value_list.type);
628 return NULL;
629 }
630 if (values == NULL ||
631 (PyTuple_Check(values) == 0 && PyList_Check(values) == 0)) {
632 PyErr_Format(PyExc_TypeError, "values must be list or tuple");
633 return NULL;
634 }
635 if (meta != NULL && meta != Py_None && !PyDict_Check(meta)) {
636 PyErr_Format(PyExc_TypeError, "meta must be a dict");
637 return NULL;
638 }
639 size = (size_t)PySequence_Length(values);
640 if (size != ds->ds_num) {
641 PyErr_Format(PyExc_RuntimeError, "type %s needs %zu values, got %zu",
642 value_list.type, ds->ds_num, size);
643 return NULL;
644 }
645 value = calloc(size, sizeof(*value));
646 for (size_t i = 0; i < size; ++i) {
647 PyObject *item, *num;
648 item = PySequence_Fast_GET_ITEM(values, (int)i); /* Borrowed reference. */
649 switch (ds->ds[i].type) {
650 case DS_TYPE_COUNTER:
651 num = PyNumber_Long(item); /* New reference. */
652 if (num != NULL) {
653 value[i].counter = PyLong_AsUnsignedLongLong(num);
654 Py_XDECREF(num);
655 }
656 break;
657 case DS_TYPE_GAUGE:
658 num = PyNumber_Float(item); /* New reference. */
659 if (num != NULL) {
660 value[i].gauge = PyFloat_AsDouble(num);
661 Py_XDECREF(num);
662 }
663 break;
664 case DS_TYPE_DERIVE:
665 /* This might overflow without raising an exception.
666 * Not much we can do about it */
667 num = PyNumber_Long(item); /* New reference. */
668 if (num != NULL) {
669 value[i].derive = PyLong_AsLongLong(num);
670 Py_XDECREF(num);
671 }
672 break;
673 case DS_TYPE_ABSOLUTE:
674 /* This might overflow without raising an exception.
675 * Not much we can do about it */
676 num = PyNumber_Long(item); /* New reference. */
677 if (num != NULL) {
678 value[i].absolute = PyLong_AsUnsignedLongLong(num);
679 Py_XDECREF(num);
680 }
681 break;
682 default:
683 free(value);
684 PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s",
685 ds->ds[i].type, value_list.type);
686 return NULL;
687 }
688 if (PyErr_Occurred() != NULL) {
689 free(value);
690 return NULL;
691 }
692 }
693 value_list.values = value;
694 value_list.meta = cpy_build_value_meta(meta);
695 value_list.values_len = size;
696 value_list.time = DOUBLE_TO_CDTIME_T(time);
697 value_list.interval = DOUBLE_TO_CDTIME_T(interval);
698 if (value_list.host[0] == 0)
699 sstrncpy(value_list.host, hostname_g, sizeof(value_list.host));
700 if (value_list.plugin[0] == 0)
701 sstrncpy(value_list.plugin, "python", sizeof(value_list.plugin));
702 Py_BEGIN_ALLOW_THREADS;
703 ret = plugin_dispatch_values(&value_list);
704 Py_END_ALLOW_THREADS;
705 meta_data_destroy(value_list.meta);
706 free(value);
707 if (ret != 0) {
708 PyErr_SetString(PyExc_RuntimeError,
709 "error dispatching values, read the logs");
710 return NULL;
711 }
712 Py_RETURN_NONE;
713 }
715 static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
716 int ret;
717 const data_set_t *ds;
718 size_t size;
719 value_t *value;
720 value_list_t value_list = VALUE_LIST_INIT;
721 PyObject *values = self->values, *meta = self->meta;
722 double time = self->data.time, interval = self->interval;
723 char *host = NULL, *plugin = NULL, *plugin_instance = NULL, *type = NULL,
724 *type_instance = NULL, *dest = NULL;
726 static char *kwlist[] = {
727 "destination", "type", "values", "plugin_instance",
728 "type_instance", "plugin", "host", "time",
729 "interval", "meta", NULL};
730 if (!PyArg_ParseTupleAndKeywords(
731 args, kwds, "et|etOetetetetdiO", kwlist, NULL, &dest, NULL, &type,
732 &values, NULL, &plugin_instance, NULL, &type_instance, NULL, &plugin,
733 NULL, &host, &time, &interval, &meta))
734 return NULL;
736 sstrncpy(value_list.host, host ? host : self->data.host,
737 sizeof(value_list.host));
738 sstrncpy(value_list.plugin, plugin ? plugin : self->data.plugin,
739 sizeof(value_list.plugin));
740 sstrncpy(value_list.plugin_instance,
741 plugin_instance ? plugin_instance : self->data.plugin_instance,
742 sizeof(value_list.plugin_instance));
743 sstrncpy(value_list.type, type ? type : self->data.type,
744 sizeof(value_list.type));
745 sstrncpy(value_list.type_instance,
746 type_instance ? type_instance : self->data.type_instance,
747 sizeof(value_list.type_instance));
748 FreeAll();
749 if (value_list.type[0] == 0) {
750 PyErr_SetString(PyExc_RuntimeError, "type not set");
751 return NULL;
752 }
753 ds = plugin_get_ds(value_list.type);
754 if (ds == NULL) {
755 PyErr_Format(PyExc_TypeError, "Dataset %s not found", value_list.type);
756 return NULL;
757 }
758 if (values == NULL ||
759 (PyTuple_Check(values) == 0 && PyList_Check(values) == 0)) {
760 PyErr_Format(PyExc_TypeError, "values must be list or tuple");
761 return NULL;
762 }
763 size = (size_t)PySequence_Length(values);
764 if (size != ds->ds_num) {
765 PyErr_Format(PyExc_RuntimeError, "type %s needs %zu values, got %zu",
766 value_list.type, ds->ds_num, size);
767 return NULL;
768 }
769 value = calloc(size, sizeof(*value));
770 for (size_t i = 0; i < size; ++i) {
771 PyObject *item, *num;
772 item = PySequence_Fast_GET_ITEM(values, i); /* Borrowed reference. */
773 switch (ds->ds[i].type) {
774 case DS_TYPE_COUNTER:
775 num = PyNumber_Long(item); /* New reference. */
776 if (num != NULL) {
777 value[i].counter = PyLong_AsUnsignedLongLong(num);
778 Py_XDECREF(num);
779 }
780 break;
781 case DS_TYPE_GAUGE:
782 num = PyNumber_Float(item); /* New reference. */
783 if (num != NULL) {
784 value[i].gauge = PyFloat_AsDouble(num);
785 Py_XDECREF(num);
786 }
787 break;
788 case DS_TYPE_DERIVE:
789 /* This might overflow without raising an exception.
790 * Not much we can do about it */
791 num = PyNumber_Long(item); /* New reference. */
792 if (num != NULL) {
793 value[i].derive = PyLong_AsLongLong(num);
794 Py_XDECREF(num);
795 }
796 break;
797 case DS_TYPE_ABSOLUTE:
798 /* This might overflow without raising an exception.
799 * Not much we can do about it */
800 num = PyNumber_Long(item); /* New reference. */
801 if (num != NULL) {
802 value[i].absolute = PyLong_AsUnsignedLongLong(num);
803 Py_XDECREF(num);
804 }
805 break;
806 default:
807 free(value);
808 PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s",
809 ds->ds[i].type, value_list.type);
810 return NULL;
811 }
812 if (PyErr_Occurred() != NULL) {
813 free(value);
814 return NULL;
815 }
816 }
817 value_list.values = value;
818 value_list.values_len = size;
819 value_list.time = DOUBLE_TO_CDTIME_T(time);
820 value_list.interval = DOUBLE_TO_CDTIME_T(interval);
821 value_list.meta = cpy_build_value_meta(meta);
822 if (value_list.host[0] == 0)
823 sstrncpy(value_list.host, hostname_g, sizeof(value_list.host));
824 if (value_list.plugin[0] == 0)
825 sstrncpy(value_list.plugin, "python", sizeof(value_list.plugin));
826 Py_BEGIN_ALLOW_THREADS;
827 ret = plugin_write(dest, NULL, &value_list);
828 Py_END_ALLOW_THREADS;
829 meta_data_destroy(value_list.meta);
830 free(value);
831 if (ret != 0) {
832 PyErr_SetString(PyExc_RuntimeError,
833 "error dispatching values, read the logs");
834 return NULL;
835 }
836 Py_RETURN_NONE;
837 }
839 static PyObject *Values_repr(PyObject *s) {
840 PyObject *ret, *tmp;
841 static PyObject *l_interval = NULL, *l_values = NULL, *l_meta = NULL,
842 *l_closing = NULL;
843 Values *self = (Values *)s;
845 if (l_interval == NULL)
846 l_interval = cpy_string_to_unicode_or_bytes(",interval=");
847 if (l_values == NULL)
848 l_values = cpy_string_to_unicode_or_bytes(",values=");
849 if (l_meta == NULL)
850 l_meta = cpy_string_to_unicode_or_bytes(",meta=");
851 if (l_closing == NULL)
852 l_closing = cpy_string_to_unicode_or_bytes(")");
854 if (l_interval == NULL || l_values == NULL || l_meta == NULL ||
855 l_closing == NULL)
856 return NULL;
858 ret = cpy_common_repr(s);
859 if (self->interval != 0) {
860 CPY_STRCAT(&ret, l_interval);
861 tmp = PyFloat_FromDouble(self->interval);
862 CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
863 CPY_STRCAT_AND_DEL(&ret, tmp);
864 }
865 if (self->values &&
866 (!PyList_Check(self->values) || PySequence_Length(self->values) > 0)) {
867 CPY_STRCAT(&ret, l_values);
868 tmp = PyObject_Repr(self->values);
869 CPY_STRCAT_AND_DEL(&ret, tmp);
870 }
871 if (self->meta &&
872 (!PyDict_Check(self->meta) || PyDict_Size(self->meta) > 0)) {
873 CPY_STRCAT(&ret, l_meta);
874 tmp = PyObject_Repr(self->meta);
875 CPY_STRCAT_AND_DEL(&ret, tmp);
876 }
877 CPY_STRCAT(&ret, l_closing);
878 return ret;
879 }
881 static int Values_traverse(PyObject *self, visitproc visit, void *arg) {
882 Values *v = (Values *)self;
883 Py_VISIT(v->values);
884 Py_VISIT(v->meta);
885 return 0;
886 }
888 static int Values_clear(PyObject *self) {
889 Values *v = (Values *)self;
890 Py_CLEAR(v->values);
891 Py_CLEAR(v->meta);
892 return 0;
893 }
895 static void Values_dealloc(PyObject *self) {
896 Values_clear(self);
897 self->ob_type->tp_free(self);
898 }
900 static PyMemberDef Values_members[] = {
901 {"interval", T_DOUBLE, offsetof(Values, interval), 0, interval_doc},
902 {"values", T_OBJECT_EX, offsetof(Values, values), 0, values_doc},
903 {"meta", T_OBJECT_EX, offsetof(Values, meta), 0, meta_doc},
904 {NULL}};
906 static PyMethodDef Values_methods[] = {
907 {"dispatch", (PyCFunction)Values_dispatch, METH_VARARGS | METH_KEYWORDS,
908 dispatch_doc},
909 {"write", (PyCFunction)Values_write, METH_VARARGS | METH_KEYWORDS,
910 write_doc},
911 {NULL}};
913 PyTypeObject ValuesType = {
914 CPY_INIT_TYPE "collectd.Values", /* tp_name */
915 sizeof(Values), /* tp_basicsize */
916 0, /* Will be filled in later */
917 Values_dealloc, /* tp_dealloc */
918 0, /* tp_print */
919 0, /* tp_getattr */
920 0, /* tp_setattr */
921 0, /* tp_compare */
922 Values_repr, /* tp_repr */
923 0, /* tp_as_number */
924 0, /* tp_as_sequence */
925 0, /* tp_as_mapping */
926 0, /* tp_hash */
927 0, /* tp_call */
928 0, /* tp_str */
929 0, /* tp_getattro */
930 0, /* tp_setattro */
931 0, /* tp_as_buffer */
932 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
933 Values_doc, /* tp_doc */
934 Values_traverse, /* tp_traverse */
935 Values_clear, /* tp_clear */
936 0, /* tp_richcompare */
937 0, /* tp_weaklistoffset */
938 0, /* tp_iter */
939 0, /* tp_iternext */
940 Values_methods, /* tp_methods */
941 Values_members, /* tp_members */
942 0, /* tp_getset */
943 0, /* tp_base */
944 0, /* tp_dict */
945 0, /* tp_descr_get */
946 0, /* tp_descr_set */
947 0, /* tp_dictoffset */
948 Values_init, /* tp_init */
949 0, /* tp_alloc */
950 Values_new /* tp_new */
951 };
953 static char notification_meta_doc[] =
954 "These are the meta data for the Notification object.\n"
955 "It has to be a dictionary of numbers, strings or bools. All keys must be\n"
956 "strings. int and long objects will be dispatched as signed integers "
957 "unless\n"
958 "they are between 2**63 and 2**64-1, which will result in an unsigned "
959 "integer.\n"
960 "One of these storage classes can be forced by using the classes\n"
961 "collectd.Signed and collectd.Unsigned. A meta object received by a\n"
962 "notification callback will always contain Signed or Unsigned objects.";
964 static char severity_doc[] =
965 "The severity of this notification. Assign or compare to\n"
966 "NOTIF_FAILURE, NOTIF_WARNING or NOTIF_OKAY.";
968 static char message_doc[] = "Some kind of description what's going on and why "
969 "this Notification was generated.";
971 static char Notification_doc[] =
972 "The Notification class is a wrapper around the collectd notification.\n"
973 "It can be used to notify other plugins about bad stuff happening. It "
974 "works\n"
975 "similar to Values but has a severity and a message instead of interval\n"
976 "and time.\n"
977 "Notifications can be dispatched at any time and can be received with "
978 "register_notification.";
980 static int Notification_init(PyObject *s, PyObject *args, PyObject *kwds) {
981 Notification *self = (Notification *)s;
982 int severity = 0;
983 double time = 0;
984 char *message = NULL;
985 PyObject *meta = NULL;
986 char *type = NULL, *plugin_instance = NULL, *type_instance = NULL,
987 *plugin = NULL, *host = NULL;
988 static char *kwlist[] = {"type", "message", "plugin_instance",
989 "type_instance", "plugin", "host",
990 "time", "severity", "meta",
991 NULL};
993 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etetetetetetdiO", kwlist, NULL,
994 &type, NULL, &message, NULL,
995 &plugin_instance, NULL, &type_instance, NULL,
996 &plugin, NULL, &host, &time, &severity, &meta))
997 return -1;
999 if (type && plugin_get_ds(type) == NULL) {
1000 PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
1001 FreeAll();
1002 PyMem_Free(message);
1003 return -1;
1004 }
1006 sstrncpy(self->data.host, host ? host : "", sizeof(self->data.host));
1007 sstrncpy(self->data.plugin, plugin ? plugin : "", sizeof(self->data.plugin));
1008 sstrncpy(self->data.plugin_instance, plugin_instance ? plugin_instance : "",
1009 sizeof(self->data.plugin_instance));
1010 sstrncpy(self->data.type, type ? type : "", sizeof(self->data.type));
1011 sstrncpy(self->data.type_instance, type_instance ? type_instance : "",
1012 sizeof(self->data.type_instance));
1013 sstrncpy(self->message, message ? message : "", sizeof(self->message));
1014 self->data.time = time;
1015 self->severity = severity;
1017 FreeAll();
1018 PyMem_Free(message);
1020 if (meta == NULL) {
1021 meta = PyDict_New();
1022 PyErr_Clear();
1023 } else {
1024 Py_INCREF(meta);
1025 }
1027 PyObject *tmp = self->meta;
1028 self->meta = meta;
1029 Py_XDECREF(tmp);
1031 return 0;
1032 }
1034 static PyObject *Notification_dispatch(Notification *self, PyObject *args,
1035 PyObject *kwds) {
1036 int ret;
1037 const data_set_t *ds;
1038 notification_t notification;
1039 double t = self->data.time;
1040 PyObject *meta = self->meta;
1041 int severity = self->severity;
1042 char *host = NULL, *plugin = NULL, *plugin_instance = NULL, *type = NULL,
1043 *type_instance = NULL;
1044 char *message = NULL;
1046 static char *kwlist[] = {"type", "message", "plugin_instance",
1047 "type_instance", "plugin", "host",
1048 "time", "severity", "meta",
1049 NULL};
1050 if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etetetetetetdiO", kwlist, NULL,
1051 &type, NULL, &message, NULL,
1052 &plugin_instance, NULL, &type_instance, NULL,
1053 &plugin, NULL, &host, &t, &severity, &meta))
1054 return NULL;
1056 notification.time = DOUBLE_TO_CDTIME_T(t);
1057 notification.severity = severity;
1058 sstrncpy(notification.message, message ? message : self->message,
1059 sizeof(notification.message));
1060 sstrncpy(notification.host, host ? host : self->data.host,
1061 sizeof(notification.host));
1062 sstrncpy(notification.plugin, plugin ? plugin : self->data.plugin,
1063 sizeof(notification.plugin));
1064 sstrncpy(notification.plugin_instance,
1065 plugin_instance ? plugin_instance : self->data.plugin_instance,
1066 sizeof(notification.plugin_instance));
1067 sstrncpy(notification.type, type ? type : self->data.type,
1068 sizeof(notification.type));
1069 sstrncpy(notification.type_instance,
1070 type_instance ? type_instance : self->data.type_instance,
1071 sizeof(notification.type_instance));
1072 notification.meta = NULL;
1073 FreeAll();
1074 PyMem_Free(message);
1076 if (notification.type[0] == 0) {
1077 PyErr_SetString(PyExc_RuntimeError, "type not set");
1078 return NULL;
1079 }
1080 ds = plugin_get_ds(notification.type);
1081 if (ds == NULL) {
1082 PyErr_Format(PyExc_TypeError, "Dataset %s not found", notification.type);
1083 return NULL;
1084 }
1085 if (meta != NULL && meta != Py_None && !PyDict_Check(meta)) {
1086 PyErr_Format(PyExc_TypeError, "meta must be a dict");
1087 return NULL;
1088 }
1089 cpy_build_notification_meta(¬ification, meta);
1091 if (notification.time == 0)
1092 notification.time = cdtime();
1093 if (notification.host[0] == 0)
1094 sstrncpy(notification.host, hostname_g, sizeof(notification.host));
1095 if (notification.plugin[0] == 0)
1096 sstrncpy(notification.plugin, "python", sizeof(notification.plugin));
1097 Py_BEGIN_ALLOW_THREADS;
1098 ret = plugin_dispatch_notification(¬ification);
1099 if (notification.meta)
1100 plugin_notification_meta_free(notification.meta);
1101 Py_END_ALLOW_THREADS;
1102 if (ret != 0) {
1103 PyErr_SetString(PyExc_RuntimeError,
1104 "error dispatching notification, read the logs");
1105 return NULL;
1106 }
1107 Py_RETURN_NONE;
1108 }
1110 static PyObject *Notification_new(PyTypeObject *type, PyObject *args,
1111 PyObject *kwds) {
1112 Notification *self;
1114 self = (Notification *)PluginData_new(type, args, kwds);
1115 if (self == NULL)
1116 return NULL;
1118 self->meta = PyDict_New();
1119 self->message[0] = 0;
1120 self->severity = 0;
1121 return (PyObject *)self;
1122 }
1124 static int Notification_setstring(PyObject *self, PyObject *value, void *data) {
1125 char *old;
1126 const char *new;
1128 if (value == NULL) {
1129 PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
1130 return -1;
1131 }
1132 Py_INCREF(value);
1133 new = cpy_unicode_or_bytes_to_string(&value);
1134 if (new == NULL) {
1135 Py_DECREF(value);
1136 return -1;
1137 }
1138 old = ((char *)self) + (intptr_t)data;
1139 sstrncpy(old, new, NOTIF_MAX_MSG_LEN);
1140 Py_DECREF(value);
1141 return 0;
1142 }
1144 static PyObject *Notification_repr(PyObject *s) {
1145 PyObject *ret, *tmp;
1146 static PyObject *l_severity = NULL, *l_message = NULL, *l_meta = NULL,
1147 *l_closing = NULL;
1148 Notification *self = (Notification *)s;
1150 if (l_severity == NULL)
1151 l_severity = cpy_string_to_unicode_or_bytes(",severity=");
1152 if (l_message == NULL)
1153 l_message = cpy_string_to_unicode_or_bytes(",message=");
1154 if (l_meta == NULL)
1155 l_meta = cpy_string_to_unicode_or_bytes(",meta=");
1156 if (l_closing == NULL)
1157 l_closing = cpy_string_to_unicode_or_bytes(")");
1159 if (l_severity == NULL || l_message == NULL || l_meta == NULL ||
1160 l_closing == NULL)
1161 return NULL;
1163 ret = cpy_common_repr(s);
1164 if (self->severity != 0) {
1165 CPY_STRCAT(&ret, l_severity);
1166 tmp = PyInt_FromLong(self->severity);
1167 CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
1168 CPY_STRCAT_AND_DEL(&ret, tmp);
1169 }
1170 if (self->message[0] != 0) {
1171 CPY_STRCAT(&ret, l_message);
1172 tmp = cpy_string_to_unicode_or_bytes(self->message);
1173 CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
1174 CPY_STRCAT_AND_DEL(&ret, tmp);
1175 }
1176 if (self->meta &&
1177 (!PyDict_Check(self->meta) || PyDict_Size(self->meta) > 0)) {
1178 CPY_STRCAT(&ret, l_meta);
1179 tmp = PyObject_Repr(self->meta);
1180 CPY_STRCAT_AND_DEL(&ret, tmp);
1181 }
1182 CPY_STRCAT(&ret, l_closing);
1183 return ret;
1184 }
1186 static int Notification_traverse(PyObject *self, visitproc visit, void *arg) {
1187 Notification *n = (Notification *)self;
1188 Py_VISIT(n->meta);
1189 return 0;
1190 }
1192 static int Notification_clear(PyObject *self) {
1193 Notification *n = (Notification *)self;
1194 Py_CLEAR(n->meta);
1195 return 0;
1196 }
1198 static void Notification_dealloc(PyObject *self) {
1199 Notification_clear(self);
1200 self->ob_type->tp_free(self);
1201 }
1203 static PyMethodDef Notification_methods[] = {
1204 {"dispatch", (PyCFunction)Notification_dispatch,
1205 METH_VARARGS | METH_KEYWORDS, dispatch_doc},
1206 {NULL}};
1208 static PyMemberDef Notification_members[] = {
1209 {"severity", T_INT, offsetof(Notification, severity), 0, severity_doc},
1210 {"meta", T_OBJECT_EX, offsetof(Notification, meta), 0, notification_meta_doc},
1211 {NULL}};
1213 static PyGetSetDef Notification_getseters[] = {
1214 {"message", PluginData_getstring, Notification_setstring, message_doc,
1215 (void *)offsetof(Notification, message)},
1216 {NULL}};
1218 PyTypeObject NotificationType = {
1219 CPY_INIT_TYPE "collectd.Notification", /* tp_name */
1220 sizeof(Notification), /* tp_basicsize */
1221 0, /* Will be filled in later */
1222 Notification_dealloc, /* tp_dealloc */
1223 0, /* tp_print */
1224 0, /* tp_getattr */
1225 0, /* tp_setattr */
1226 0, /* tp_compare */
1227 Notification_repr, /* tp_repr */
1228 0, /* tp_as_number */
1229 0, /* tp_as_sequence */
1230 0, /* tp_as_mapping */
1231 0, /* tp_hash */
1232 0, /* tp_call */
1233 0, /* tp_str */
1234 0, /* tp_getattro */
1235 0, /* tp_setattro */
1236 0, /* tp_as_buffer */
1237 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
1238 Notification_doc, /* tp_doc */
1239 Notification_traverse, /* tp_traverse */
1240 Notification_clear, /* tp_clear */
1241 0, /* tp_richcompare */
1242 0, /* tp_weaklistoffset */
1243 0, /* tp_iter */
1244 0, /* tp_iternext */
1245 Notification_methods, /* tp_methods */
1246 Notification_members, /* tp_members */
1247 Notification_getseters, /* tp_getset */
1248 0, /* tp_base */
1249 0, /* tp_dict */
1250 0, /* tp_descr_get */
1251 0, /* tp_descr_set */
1252 0, /* tp_dictoffset */
1253 Notification_init, /* tp_init */
1254 0, /* tp_alloc */
1255 Notification_new /* tp_new */
1256 };
1258 static char Signed_doc[] =
1259 "This is a long by another name. Use it in meta data dicts\n"
1260 "to choose the way it is stored in the meta data.";
1262 PyTypeObject SignedType = {
1263 CPY_INIT_TYPE "collectd.Signed", /* tp_name */
1264 sizeof(Signed), /* tp_basicsize */
1265 0, /* Will be filled in later */
1266 0, /* tp_dealloc */
1267 0, /* tp_print */
1268 0, /* tp_getattr */
1269 0, /* tp_setattr */
1270 0, /* tp_compare */
1271 0, /* tp_repr */
1272 0, /* tp_as_number */
1273 0, /* tp_as_sequence */
1274 0, /* tp_as_mapping */
1275 0, /* tp_hash */
1276 0, /* tp_call */
1277 0, /* tp_str */
1278 0, /* tp_getattro */
1279 0, /* tp_setattro */
1280 0, /* tp_as_buffer */
1281 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
1282 Signed_doc /* tp_doc */
1283 };
1285 static char Unsigned_doc[] =
1286 "This is a long by another name. Use it in meta data dicts\n"
1287 "to choose the way it is stored in the meta data.";
1289 PyTypeObject UnsignedType = {
1290 CPY_INIT_TYPE "collectd.Unsigned", /* tp_name */
1291 sizeof(Unsigned), /* tp_basicsize */
1292 0, /* Will be filled in later */
1293 0, /* tp_dealloc */
1294 0, /* tp_print */
1295 0, /* tp_getattr */
1296 0, /* tp_setattr */
1297 0, /* tp_compare */
1298 0, /* tp_repr */
1299 0, /* tp_as_number */
1300 0, /* tp_as_sequence */
1301 0, /* tp_as_mapping */
1302 0, /* tp_hash */
1303 0, /* tp_call */
1304 0, /* tp_str */
1305 0, /* tp_getattro */
1306 0, /* tp_setattro */
1307 0, /* tp_as_buffer */
1308 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
1309 Unsigned_doc /* tp_doc */
1310 };