Code

python: Extend Notification class
[collectd.git] / src / pyvalues.c
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;
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;
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;
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;
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);
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;
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;
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;
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;
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;
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;
583 static void cpy_build_notification_meta(notification_t *n, PyObject *meta) {
584   cpy_build_meta(meta, &cpy_plugin_notification_meta, (void *)n);
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;
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;
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;
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;
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;
895 static void Values_dealloc(PyObject *self) {
896   Values_clear(self);
897   self->ob_type->tp_free(self);
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;
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(&notification, 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(&notification);
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;
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;
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;
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;
1186 static int Notification_traverse(PyObject *self, visitproc visit, void *arg) {
1187   Notification *n = (Notification *)self;
1188   Py_VISIT(n->meta);
1189   return 0;
1192 static int Notification_clear(PyObject *self) {
1193   Notification *n = (Notification *)self;
1194   Py_CLEAR(n->meta);
1195   return 0;
1198 static void Notification_dealloc(PyObject *self) {
1199   Notification_clear(self);
1200   self->ob_type->tp_free(self);
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 };