Code

Varnish plugin: Use DERIVE data sources for (most of) the worker thread statistics.
[collectd.git] / src / python.c
1 /**
2  * collectd - src/python.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 <signal.h>
31 #if HAVE_PTHREAD_H
32 # include <pthread.h>
33 #endif
35 #include "collectd.h"
36 #include "common.h"
38 #include "cpython.h"
40 typedef struct cpy_callback_s {
41         char *name;
42         PyObject *callback;
43         PyObject *data;
44         struct cpy_callback_s *next;
45 } cpy_callback_t;
47 static char log_doc[] = "This function sends a string to all logging plugins.";
49 static char flush_doc[] = "flush([plugin][, timeout][, identifier]) -> None\n"
50                 "\n"
51                 "Flushes the cache of another plugin.";
53 static char unregister_doc[] = "Unregisters a callback. This function needs exactly one parameter either\n"
54                 "the function to unregister or the callback identifier to unregister.";
56 static char reg_log_doc[] = "register_log(callback[, data][, name]) -> identifier\n"
57                 "\n"
58                 "Register a callback function for log messages.\n"
59                 "\n"
60                 "'callback' is a callable object that will be called every time something\n"
61                 "    is logged.\n"
62                 "'data' is an optional object that will be passed back to the callback\n"
63                 "    function every time it is called.\n"
64                 "'name' is an optional identifier for this callback. The default name\n"
65                 "    is 'python.<module>'.\n"
66                 "    Every callback needs a unique identifier, so if you want to\n"
67                 "    register this callback multiple time from the same module you need\n"
68                 "    to specify a name here.\n"
69                 "'identifier' is the full identifier assigned to this callback.\n"
70                 "\n"
71                 "The callback function will be called with two or three parameters:\n"
72                 "severity: An integer that should be compared to the LOG_ constants.\n"
73                 "message: The text to be logged.\n"
74                 "data: The optional data parameter passed to the register function.\n"
75                 "    If the parameter was omitted it will be omitted here, too.";
77 static char reg_init_doc[] = "register_init(callback[, data][, name]) -> identifier\n"
78                 "\n"
79                 "Register a callback function that will be executed once after the config.\n"
80                 "file has been read, all plugins heve been loaded and the collectd has\n"
81                 "forked into the background.\n"
82                 "\n"
83                 "'callback' is a callable object that will be executed.\n"
84                 "'data' is an optional object that will be passed back to the callback\n"
85                 "    function when it is called.\n"
86                 "'name' is an optional identifier for this callback. The default name\n"
87                 "    is 'python.<module>'.\n"
88                 "    Every callback needs a unique identifier, so if you want to\n"
89                 "    register this callback multiple time from the same module you need\n"
90                 "    to specify a name here.\n"
91                 "'identifier' is the full identifier assigned to this callback.\n"
92                 "\n"
93                 "The callback function will be called without parameters, except for\n"
94                 "data if it was supplied.";
96 static char reg_config_doc[] = "register_config(callback[, data][, name]) -> identifier\n"
97                 "\n"
98                 "Register a callback function for config file entries.\n"
99                 "'callback' is a callable object that will be called for every config block.\n"
100                 "'data' is an optional object that will be passed back to the callback\n"
101                 "    function every time it is called.\n"
102                 "'name' is an optional identifier for this callback. The default name\n"
103                 "    is 'python.<module>'.\n"
104                 "    Every callback needs a unique identifier, so if you want to\n"
105                 "    register this callback multiple time from the same module you need\n"
106                 "    to specify a name here.\n"
107                 "'identifier' is the full identifier assigned to this callback.\n"
108                 "\n"
109                 "The callback function will be called with one or two parameters:\n"
110                 "config: A Config object.\n"
111                 "data: The optional data parameter passed to the register function.\n"
112                 "    If the parameter was omitted it will be omitted here, too.";
114 static char reg_read_doc[] = "register_read(callback[, interval][, data][, name]) -> identifier\n"
115                 "\n"
116                 "Register a callback function for reading data. It will just be called\n"
117                 "in a fixed interval to signal that it's time to dispatch new values.\n"
118                 "'callback' is a callable object that will be called every time something\n"
119                 "    is logged.\n"
120                 "'interval' is the number of seconds between between calls to the callback\n"
121                 "    function. Full float precision is supported here.\n"
122                 "'data' is an optional object that will be passed back to the callback\n"
123                 "    function every time it is called.\n"
124                 "'name' is an optional identifier for this callback. The default name\n"
125                 "    is 'python.<module>'.\n"
126                 "    Every callback needs a unique identifier, so if you want to\n"
127                 "    register this callback multiple time from the same module you need\n"
128                 "    to specify a name here.\n"
129                 "'identifier' is the full identifier assigned to this callback.\n"
130                 "\n"
131                 "The callback function will be called without parameters, except for\n"
132                 "data if it was supplied.";
134 static char reg_write_doc[] = "register_write(callback[, data][, name]) -> identifier\n"
135                 "\n"
136                 "Register a callback function to receive values dispatched by other plugins.\n"
137                 "'callback' is a callable object that will be called every time a value\n"
138                 "    is dispatched.\n"
139                 "'data' is an optional object that will be passed back to the callback\n"
140                 "    function every time it is called.\n"
141                 "'name' is an optional identifier for this callback. The default name\n"
142                 "    is 'python.<module>'.\n"
143                 "    Every callback needs a unique identifier, so if you want to\n"
144                 "    register this callback multiple time from the same module you need\n"
145                 "    to specify a name here.\n"
146                 "'identifier' is the full identifier assigned to this callback.\n"
147                 "\n"
148                 "The callback function will be called with one or two parameters:\n"
149                 "values: A Values object which is a copy of the dispatched values.\n"
150                 "data: The optional data parameter passed to the register function.\n"
151                 "    If the parameter was omitted it will be omitted here, too.";
153 static char reg_notification_doc[] = "register_notification(callback[, data][, name]) -> identifier\n"
154                 "\n"
155                 "Register a callback function for notifications.\n"
156                 "'callback' is a callable object that will be called every time a notification\n"
157                 "    is dispatched.\n"
158                 "'data' is an optional object that will be passed back to the callback\n"
159                 "    function every time it is called.\n"
160                 "'name' is an optional identifier for this callback. The default name\n"
161                 "    is 'python.<module>'.\n"
162                 "    Every callback needs a unique identifier, so if you want to\n"
163                 "    register this callback multiple time from the same module you need\n"
164                 "    to specify a name here.\n"
165                 "'identifier' is the full identifier assigned to this callback.\n"
166                 "\n"
167                 "The callback function will be called with one or two parameters:\n"
168                 "notification: A copy of the notification that was dispatched.\n"
169                 "data: The optional data parameter passed to the register function.\n"
170                 "    If the parameter was omitted it will be omitted here, too.";
172 static char reg_flush_doc[] = "register_flush(callback[, data][, name]) -> identifier\n"
173                 "\n"
174                 "Register a callback function for flush messages.\n"
175                 "'callback' is a callable object that will be called every time a plugin\n"
176                 "    requests a flush for either this or all plugins.\n"
177                 "'data' is an optional object that will be passed back to the callback\n"
178                 "    function every time it is called.\n"
179                 "'name' is an optional identifier for this callback. The default name\n"
180                 "    is 'python.<module>'.\n"
181                 "    Every callback needs a unique identifier, so if you want to\n"
182                 "    register this callback multiple time from the same module you need\n"
183                 "    to specify a name here.\n"
184                 "'identifier' is the full identifier assigned to this callback.\n"
185                 "\n"
186                 "The callback function will be called with two or three parameters:\n"
187                 "timeout: Indicates that only data older than 'timeout' seconds is to\n"
188                 "    be flushed.\n"
189                 "id: Specifies which values are to be flushed.\n"
190                 "data: The optional data parameter passed to the register function.\n"
191                 "    If the parameter was omitted it will be omitted here, too.";
193 static char reg_shutdown_doc[] = "register_shutdown(callback[, data][, name]) -> identifier\n"
194                 "\n"
195                 "Register a callback function for collectd shutdown.\n"
196                 "'callback' is a callable object that will be called once collectd is\n"
197                 "    shutting down.\n"
198                 "'data' is an optional object that will be passed back to the callback\n"
199                 "    function if it is called.\n"
200                 "'name' is an optional identifier for this callback. The default name\n"
201                 "    is 'python.<module>'.\n"
202                 "    Every callback needs a unique identifier, so if you want to\n"
203                 "    register this callback multiple time from the same module you need\n"
204                 "    to specify a name here.\n"
205                 "'identifier' is the full identifier assigned to this callback.\n"
206                 "\n"
207                 "The callback function will be called with no parameters except for\n"
208                 "    data if it was supplied.";
211 static int do_interactive = 0;
213 /* This is our global thread state. Python saves some stuff in thread-local
214  * storage. So if we allow the interpreter to run in the background
215  * (the scriptwriters might have created some threads from python), we have
216  * to save the state so we can resume it later after shutdown. */
218 static PyThreadState *state;
220 static PyObject *cpy_format_exception;
222 static cpy_callback_t *cpy_config_callbacks;
223 static cpy_callback_t *cpy_init_callbacks;
224 static cpy_callback_t *cpy_shutdown_callbacks;
226 static void cpy_destroy_user_data(void *data) {
227         cpy_callback_t *c = data;
228         free(c->name);
229         Py_DECREF(c->callback);
230         Py_XDECREF(c->data);
231         free(c);
234 /* You must hold the GIL to call this function!
235  * But if you managed to extract the callback parameter then you probably already do. */
237 static void cpy_build_name(char *buf, size_t size, PyObject *callback, const char *name) {
238         const char *module = NULL;
239         PyObject *mod = NULL;
240         
241         if (name != NULL) {
242                 snprintf(buf, size, "python.%s", name);
243                 return;
244         }
245         
246         mod = PyObject_GetAttrString(callback, "__module__"); /* New reference. */
247         if (mod != NULL)
248                 module = cpy_unicode_or_bytes_to_string(&mod);
249         
250         if (module != NULL) {
251                 snprintf(buf, size, "python.%s", module);
252                 Py_XDECREF(mod);
253                 PyErr_Clear();
254                 return;
255         }
256         Py_XDECREF(mod);
257         
258         snprintf(buf, size, "python.%p", callback);
259         PyErr_Clear();
262 void cpy_log_exception(const char *context) {
263         int l = 0, i;
264         const char *typename = NULL, *message = NULL;
265         PyObject *type, *value, *traceback, *tn, *m, *list;
266         
267         PyErr_Fetch(&type, &value, &traceback);
268         PyErr_NormalizeException(&type, &value, &traceback);
269         if (type == NULL) return;
270         tn = PyObject_GetAttrString(type, "__name__"); /* New reference. */
271         m = PyObject_Str(value); /* New reference. */
272         if (tn != NULL)
273                 typename = cpy_unicode_or_bytes_to_string(&tn);
274         if (m != NULL)
275                 message = cpy_unicode_or_bytes_to_string(&m);
276         if (typename == NULL)
277                 typename = "NamelessException";
278         if (message == NULL)
279                 message = "N/A";
280         Py_BEGIN_ALLOW_THREADS
281         ERROR("Unhandled python exception in %s: %s: %s", context, typename, message);
282         Py_END_ALLOW_THREADS
283         Py_XDECREF(tn);
284         Py_XDECREF(m);
285         if (!cpy_format_exception) {
286                 PyErr_Clear();
287                 Py_XDECREF(type);
288                 Py_XDECREF(value);
289                 Py_XDECREF(traceback);
290                 return;
291         }
292         if (!traceback) {
293                 PyErr_Clear();
294                 return;
295         }
296         list = PyObject_CallFunction(cpy_format_exception, "NNN", type, value, traceback); /* New reference. */
297         if (list)
298                 l = PyObject_Length(list);
299         for (i = 0; i < l; ++i) {
300                 char *s;
301                 PyObject *line;
302                 
303                 line = PyList_GET_ITEM(list, i); /* Borrowed reference. */
304                 Py_INCREF(line);
305                 s = strdup(cpy_unicode_or_bytes_to_string(&line));
306                 Py_DECREF(line);
307                 if (s[strlen(s) - 1] == '\n')
308                         s[strlen(s) - 1] = 0;
309                 Py_BEGIN_ALLOW_THREADS
310                 ERROR("%s", s);
311                 Py_END_ALLOW_THREADS
312                 free(s);
313         }
314         Py_XDECREF(list);
315         PyErr_Clear();
318 static int cpy_read_callback(user_data_t *data) {
319         cpy_callback_t *c = data->data;
320         PyObject *ret;
322         CPY_LOCK_THREADS
323                 ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
324                 if (ret == NULL) {
325                         cpy_log_exception("read callback");
326                 } else {
327                         Py_DECREF(ret);
328                 }
329         CPY_RELEASE_THREADS
330         if (ret == NULL)
331                 return 1;
332         return 0;
335 static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_list, user_data_t *data) {
336         int i;
337         cpy_callback_t *c = data->data;
338         PyObject *ret, *list, *temp, *dict = NULL;
339         Values *v;
341         CPY_LOCK_THREADS
342                 list = PyList_New(value_list->values_len); /* New reference. */
343                 if (list == NULL) {
344                         cpy_log_exception("write callback");
345                         CPY_RETURN_FROM_THREADS 0;
346                 }
347                 for (i = 0; i < value_list->values_len; ++i) {
348                         if (ds->ds->type == DS_TYPE_COUNTER) {
349                                 if ((long) value_list->values[i].counter == value_list->values[i].counter)
350                                         PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].counter));
351                                 else
352                                         PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].counter));
353                         } else if (ds->ds->type == DS_TYPE_GAUGE) {
354                                 PyList_SetItem(list, i, PyFloat_FromDouble(value_list->values[i].gauge));
355                         } else if (ds->ds->type == DS_TYPE_DERIVE) {
356                                 if ((long) value_list->values[i].derive == value_list->values[i].derive)
357                                         PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].derive));
358                                 else
359                                         PyList_SetItem(list, i, PyLong_FromLongLong(value_list->values[i].derive));
360                         } else if (ds->ds->type == DS_TYPE_ABSOLUTE) {
361                                 if ((long) value_list->values[i].absolute == value_list->values[i].absolute)
362                                         PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].absolute));
363                                 else
364                                         PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].absolute));
365                         } else {
366                                 Py_BEGIN_ALLOW_THREADS
367                                 ERROR("cpy_write_callback: Unknown value type %d.", ds->ds->type);
368                                 Py_END_ALLOW_THREADS
369                                 Py_DECREF(list);
370                                 CPY_RETURN_FROM_THREADS 0;
371                         }
372                         if (PyErr_Occurred() != NULL) {
373                                 cpy_log_exception("value building for write callback");
374                                 CPY_RETURN_FROM_THREADS 0;
375                         }
376                 }
377                 dict = PyDict_New();
378                 if (value_list->meta) {
379                         int i, num;
380                         char **table;
381                         meta_data_t *meta = value_list->meta;
383                         num = meta_data_toc(meta, &table);
384                         for (i = 0; i < num; ++i) {
385                                 int type;
386                                 char *string;
387                                 int64_t si;
388                                 uint64_t ui;
389                                 double d;
390                                 _Bool b;
391                                 
392                                 type = meta_data_type(meta, table[i]);
393                                 if (type == MD_TYPE_STRING) {
394                                         if (meta_data_get_string(meta, table[i], &string))
395                                                 continue;
396                                         temp = cpy_string_to_unicode_or_bytes(string);
397                                         free(string);
398                                         PyDict_SetItemString(dict, table[i], temp);
399                                         Py_XDECREF(temp);
400                                 } else if (type == MD_TYPE_SIGNED_INT) {
401                                         if (meta_data_get_signed_int(meta, table[i], &si))
402                                                 continue;
403                                         temp = PyObject_CallFunctionObjArgs((void *) &SignedType, PyLong_FromLongLong(si), (void *) 0);
404                                         PyDict_SetItemString(dict, table[i], temp);
405                                         Py_XDECREF(temp);
406                                 } else if (type == MD_TYPE_UNSIGNED_INT) {
407                                         if (meta_data_get_unsigned_int(meta, table[i], &ui))
408                                                 continue;
409                                         temp = PyObject_CallFunctionObjArgs((void *) &UnsignedType, PyLong_FromUnsignedLongLong(ui), (void *) 0);
410                                         PyDict_SetItemString(dict, table[i], temp);
411                                         Py_XDECREF(temp);
412                                 } else if (type == MD_TYPE_DOUBLE) {
413                                         if (meta_data_get_double(meta, table[i], &d))
414                                                 continue;
415                                         temp = PyFloat_FromDouble(d);
416                                         PyDict_SetItemString(dict, table[i], temp);
417                                         Py_XDECREF(temp);
418                                 } else if (type == MD_TYPE_BOOLEAN) {
419                                         if (meta_data_get_boolean(meta, table[i], &b))
420                                                 continue;
421                                         if (b)
422                                                 PyDict_SetItemString(dict, table[i], Py_True);
423                                         else
424                                                 PyDict_SetItemString(dict, table[i], Py_False);
425                                 }
426                                 free(table[i]);
427                         }
428                         free(table);
429                 }
430                 v = PyObject_New(Values, (void *) &ValuesType);
431                 sstrncpy(v->data.host, value_list->host, sizeof(v->data.host));
432                 sstrncpy(v->data.type, value_list->type, sizeof(v->data.type));
433                 sstrncpy(v->data.type_instance, value_list->type_instance, sizeof(v->data.type_instance));
434                 sstrncpy(v->data.plugin, value_list->plugin, sizeof(v->data.plugin));
435                 sstrncpy(v->data.plugin_instance, value_list->plugin_instance, sizeof(v->data.plugin_instance));
436                 v->data.time = value_list->time;
437                 v->interval = value_list->interval;
438                 v->values = list;
439                 v->meta = dict;
440                 ret = PyObject_CallFunctionObjArgs(c->callback, v, c->data, (void *) 0); /* New reference. */
441                 if (ret == NULL) {
442                         cpy_log_exception("write callback");
443                 } else {
444                         Py_DECREF(ret);
445                 }
446         CPY_RELEASE_THREADS
447         return 0;
450 static int cpy_notification_callback(const notification_t *notification, user_data_t *data) {
451         cpy_callback_t *c = data->data;
452         PyObject *ret;
453         Notification *n;
455         CPY_LOCK_THREADS
456                 n = PyObject_New(Notification, (void *) &NotificationType);
457                 sstrncpy(n->data.host, notification->host, sizeof(n->data.host));
458                 sstrncpy(n->data.type, notification->type, sizeof(n->data.type));
459                 sstrncpy(n->data.type_instance, notification->type_instance, sizeof(n->data.type_instance));
460                 sstrncpy(n->data.plugin, notification->plugin, sizeof(n->data.plugin));
461                 sstrncpy(n->data.plugin_instance, notification->plugin_instance, sizeof(n->data.plugin_instance));
462                 n->data.time = notification->time;
463                 sstrncpy(n->message, notification->message, sizeof(n->message));
464                 n->severity = notification->severity;
465                 ret = PyObject_CallFunctionObjArgs(c->callback, n, c->data, (void *) 0); /* New reference. */
466                 if (ret == NULL) {
467                         cpy_log_exception("notification callback");
468                 } else {
469                         Py_DECREF(ret);
470                 }
471         CPY_RELEASE_THREADS
472         return 0;
475 static void cpy_log_callback(int severity, const char *message, user_data_t *data) {
476         cpy_callback_t * c = data->data;
477         PyObject *ret, *text;
479         CPY_LOCK_THREADS
480         text = cpy_string_to_unicode_or_bytes(message);
481         if (c->data == NULL)
482                 ret = PyObject_CallFunction(c->callback, "iN", severity, text); /* New reference. */
483         else
484                 ret = PyObject_CallFunction(c->callback, "iNO", severity, text, c->data); /* New reference. */
486         if (ret == NULL) {
487                 /* FIXME */
488                 /* Do we really want to trigger a log callback because a log callback failed?
489                  * Probably not. */
490                 PyErr_Print();
491                 /* In case someone wanted to be clever, replaced stderr and failed at that. */
492                 PyErr_Clear();
493         } else {
494                 Py_DECREF(ret);
495         }
496         CPY_RELEASE_THREADS
499 static void cpy_flush_callback(int timeout, const char *id, user_data_t *data) {
500         cpy_callback_t * c = data->data;
501         PyObject *ret, *text;
503         CPY_LOCK_THREADS
504         text = cpy_string_to_unicode_or_bytes(id);
505         if (c->data == NULL)
506                 ret = PyObject_CallFunction(c->callback, "iN", timeout, text); /* New reference. */
507         else
508                 ret = PyObject_CallFunction(c->callback, "iNO", timeout, text, c->data); /* New reference. */
510         if (ret == NULL) {
511                 cpy_log_exception("flush callback");
512         } else {
513                 Py_DECREF(ret);
514         }
515         CPY_RELEASE_THREADS
518 static PyObject *cpy_register_generic(cpy_callback_t **list_head, PyObject *args, PyObject *kwds) {
519         char buf[512];
520         cpy_callback_t *c;
521         const char *name = NULL;
522         PyObject *callback = NULL, *data = NULL, *mod = NULL;
523         static char *kwlist[] = {"callback", "data", "name", NULL};
524         
525         if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data, NULL, &name) == 0) return NULL;
526         if (PyCallable_Check(callback) == 0) {
527                 PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
528                 return NULL;
529         }
530         cpy_build_name(buf, sizeof(buf), callback, name);
532         Py_INCREF(callback);
533         Py_XINCREF(data);
534         c = malloc(sizeof(*c));
535         c->name = strdup(buf);
536         c->callback = callback;
537         c->data = data;
538         c->next = *list_head;
539         *list_head = c;
540         Py_XDECREF(mod);
541         return cpy_string_to_unicode_or_bytes(buf);
544 static PyObject *cpy_flush(cpy_callback_t **list_head, PyObject *args, PyObject *kwds) {
545         int timeout = -1;
546         const char *plugin = NULL, *identifier = NULL;
547         static char *kwlist[] = {"plugin", "timeout", "identifier", NULL};
548         
549         if (PyArg_ParseTupleAndKeywords(args, kwds, "|etiet", kwlist, NULL, &plugin, &timeout, NULL, &identifier) == 0) return NULL;
550         Py_BEGIN_ALLOW_THREADS
551         plugin_flush(plugin, timeout, identifier);
552         Py_END_ALLOW_THREADS
553         Py_RETURN_NONE;
556 static PyObject *cpy_register_config(PyObject *self, PyObject *args, PyObject *kwds) {
557         return cpy_register_generic(&cpy_config_callbacks, args, kwds);
560 static PyObject *cpy_register_init(PyObject *self, PyObject *args, PyObject *kwds) {
561         return cpy_register_generic(&cpy_init_callbacks, args, kwds);
564 typedef int reg_function_t(const char *name, void *callback, void *data);
566 static PyObject *cpy_register_generic_userdata(void *reg, void *handler, PyObject *args, PyObject *kwds) {
567         char buf[512];
568         reg_function_t *register_function = (reg_function_t *) reg;
569         cpy_callback_t *c = NULL;
570         user_data_t *user_data = NULL;
571         const char *name = NULL;
572         PyObject *callback = NULL, *data = NULL;
573         static char *kwlist[] = {"callback", "data", "name", NULL};
574         
575         if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data, NULL, &name) == 0) return NULL;
576         if (PyCallable_Check(callback) == 0) {
577                 PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
578                 return NULL;
579         }
580         cpy_build_name(buf, sizeof(buf), callback, name);
581         
582         Py_INCREF(callback);
583         Py_XINCREF(data);
584         c = malloc(sizeof(*c));
585         c->name = strdup(buf);
586         c->callback = callback;
587         c->data = data;
588         c->next = NULL;
589         user_data = malloc(sizeof(*user_data));
590         user_data->free_func = cpy_destroy_user_data;
591         user_data->data = c;
592         register_function(buf, handler, user_data);
593         return cpy_string_to_unicode_or_bytes(buf);
596 static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwds) {
597         char buf[512];
598         cpy_callback_t *c = NULL;
599         user_data_t *user_data = NULL;
600         double interval = 0;
601         const char *name = NULL;
602         PyObject *callback = NULL, *data = NULL;
603         struct timespec ts;
604         static char *kwlist[] = {"callback", "interval", "data", "name", NULL};
605         
606         if (PyArg_ParseTupleAndKeywords(args, kwds, "O|dOet", kwlist, &callback, &interval, &data, NULL, &name) == 0) return NULL;
607         if (PyCallable_Check(callback) == 0) {
608                 PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
609                 return NULL;
610         }
611         cpy_build_name(buf, sizeof(buf), callback, name);
612         
613         Py_INCREF(callback);
614         Py_XINCREF(data);
615         c = malloc(sizeof(*c));
616         c->name = strdup(buf);
617         c->callback = callback;
618         c->data = data;
619         c->next = NULL;
620         user_data = malloc(sizeof(*user_data));
621         user_data->free_func = cpy_destroy_user_data;
622         user_data->data = c;
623         ts.tv_sec = interval;
624         ts.tv_nsec = (interval - ts.tv_sec) * 1000000000;
625         plugin_register_complex_read(/* group = */ NULL, buf,
626                         cpy_read_callback, &ts, user_data);
627         return cpy_string_to_unicode_or_bytes(buf);
630 static PyObject *cpy_register_log(PyObject *self, PyObject *args, PyObject *kwds) {
631         return cpy_register_generic_userdata((void *) plugin_register_log,
632                         (void *) cpy_log_callback, args, kwds);
635 static PyObject *cpy_register_write(PyObject *self, PyObject *args, PyObject *kwds) {
636         return cpy_register_generic_userdata((void *) plugin_register_write,
637                         (void *) cpy_write_callback, args, kwds);
640 static PyObject *cpy_register_notification(PyObject *self, PyObject *args, PyObject *kwds) {
641         return cpy_register_generic_userdata((void *) plugin_register_notification,
642                         (void *) cpy_notification_callback, args, kwds);
645 static PyObject *cpy_register_flush(PyObject *self, PyObject *args, PyObject *kwds) {
646         return cpy_register_generic_userdata((void *) plugin_register_flush,
647                         (void *) cpy_flush_callback, args, kwds);
650 static PyObject *cpy_register_shutdown(PyObject *self, PyObject *args, PyObject *kwds) {
651         return cpy_register_generic(&cpy_shutdown_callbacks, args, kwds);
654 static PyObject *cpy_error(PyObject *self, PyObject *args) {
655         const char *text;
656         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
657         Py_BEGIN_ALLOW_THREADS
658         plugin_log(LOG_ERR, "%s", text);
659         Py_END_ALLOW_THREADS
660         Py_RETURN_NONE;
663 static PyObject *cpy_warning(PyObject *self, PyObject *args) {
664         const char *text;
665         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
666         Py_BEGIN_ALLOW_THREADS
667         plugin_log(LOG_WARNING, "%s", text);
668         Py_END_ALLOW_THREADS
669         Py_RETURN_NONE;
672 static PyObject *cpy_notice(PyObject *self, PyObject *args) {
673         const char *text;
674         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
675         Py_BEGIN_ALLOW_THREADS
676         plugin_log(LOG_NOTICE, "%s", text);
677         Py_END_ALLOW_THREADS
678         Py_RETURN_NONE;
681 static PyObject *cpy_info(PyObject *self, PyObject *args) {
682         const char *text;
683         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
684         Py_BEGIN_ALLOW_THREADS
685         plugin_log(LOG_INFO, "%s", text);
686         Py_END_ALLOW_THREADS
687         Py_RETURN_NONE;
690 static PyObject *cpy_debug(PyObject *self, PyObject *args) {
691 #ifdef COLLECT_DEBUG
692         const char *text;
693         if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
694         Py_BEGIN_ALLOW_THREADS
695         plugin_log(LOG_DEBUG, "%s", text);
696         Py_END_ALLOW_THREADS
697 #endif
698         Py_RETURN_NONE;
701 static PyObject *cpy_unregister_generic(cpy_callback_t **list_head, PyObject *arg, const char *desc) {
702         char buf[512];
703         const char *name;
704         cpy_callback_t *prev = NULL, *tmp;
706         Py_INCREF(arg);
707         name = cpy_unicode_or_bytes_to_string(&arg);
708         if (name == NULL) {
709                 PyErr_Clear();
710                 if (!PyCallable_Check(arg)) {
711                         PyErr_SetString(PyExc_TypeError, "This function needs a string or a callable object as its only parameter.");
712                         Py_DECREF(arg);
713                         return NULL;
714                 }
715                 cpy_build_name(buf, sizeof(buf), arg, NULL);
716                 name = buf;
717         }
718         for (tmp = *list_head; tmp; prev = tmp, tmp = tmp->next)
719                 if (strcmp(name, tmp->name) == 0)
720                         break;
721         
722         Py_DECREF(arg);
723         if (tmp == NULL) {
724                 PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.", desc, name);
725                 return NULL;
726         }
727         /* Yes, this is actually save. To call this function the caller has to
728          * hold the GIL. Well, save as long as there is only one GIL anyway ... */
729         if (prev == NULL)
730                 *list_head = tmp->next;
731         else
732                 prev->next = tmp->next;
733         cpy_destroy_user_data(tmp);
734         Py_RETURN_NONE;
737 typedef int cpy_unregister_function_t(const char *name);
739 static PyObject *cpy_unregister_generic_userdata(cpy_unregister_function_t *unreg, PyObject *arg, const char *desc) {
740         char buf[512];
741         const char *name;
743         Py_INCREF(arg);
744         name = cpy_unicode_or_bytes_to_string(&arg);
745         if (name == NULL) {
746                 PyErr_Clear();
747                 if (!PyCallable_Check(arg)) {
748                         PyErr_SetString(PyExc_TypeError, "This function needs a string or a callable object as its only parameter.");
749                         Py_DECREF(arg);
750                         return NULL;
751                 }
752                 cpy_build_name(buf, sizeof(buf), arg, NULL);
753                 name = buf;
754         }
755         if (unreg(name) == 0) {
756                 Py_DECREF(arg);
757                 Py_RETURN_NONE;
758         }
759         PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.", desc, name);
760         Py_DECREF(arg);
761         return NULL;
764 static PyObject *cpy_unregister_log(PyObject *self, PyObject *arg) {
765         return cpy_unregister_generic_userdata(plugin_unregister_log, arg, "log");
768 static PyObject *cpy_unregister_init(PyObject *self, PyObject *arg) {
769         return cpy_unregister_generic(&cpy_init_callbacks, arg, "init");
772 static PyObject *cpy_unregister_config(PyObject *self, PyObject *arg) {
773         return cpy_unregister_generic(&cpy_config_callbacks, arg, "config");
776 static PyObject *cpy_unregister_read(PyObject *self, PyObject *arg) {
777         return cpy_unregister_generic_userdata(plugin_unregister_read, arg, "read");
780 static PyObject *cpy_unregister_write(PyObject *self, PyObject *arg) {
781         return cpy_unregister_generic_userdata(plugin_unregister_write, arg, "write");
784 static PyObject *cpy_unregister_notification(PyObject *self, PyObject *arg) {
785         return cpy_unregister_generic_userdata(plugin_unregister_notification, arg, "notification");
788 static PyObject *cpy_unregister_flush(PyObject *self, PyObject *arg) {
789         return cpy_unregister_generic_userdata(plugin_unregister_flush, arg, "flush");
792 static PyObject *cpy_unregister_shutdown(PyObject *self, PyObject *arg) {
793         return cpy_unregister_generic(&cpy_shutdown_callbacks, arg, "shutdown");
796 static PyMethodDef cpy_methods[] = {
797         {"debug", cpy_debug, METH_VARARGS, log_doc},
798         {"info", cpy_info, METH_VARARGS, log_doc},
799         {"notice", cpy_notice, METH_VARARGS, log_doc},
800         {"warning", cpy_warning, METH_VARARGS, log_doc},
801         {"error", cpy_error, METH_VARARGS, log_doc},
802         {"flush", (PyCFunction) cpy_flush, METH_VARARGS | METH_KEYWORDS, flush_doc},
803         {"register_log", (PyCFunction) cpy_register_log, METH_VARARGS | METH_KEYWORDS, reg_log_doc},
804         {"register_init", (PyCFunction) cpy_register_init, METH_VARARGS | METH_KEYWORDS, reg_init_doc},
805         {"register_config", (PyCFunction) cpy_register_config, METH_VARARGS | METH_KEYWORDS, reg_config_doc},
806         {"register_read", (PyCFunction) cpy_register_read, METH_VARARGS | METH_KEYWORDS, reg_read_doc},
807         {"register_write", (PyCFunction) cpy_register_write, METH_VARARGS | METH_KEYWORDS, reg_write_doc},
808         {"register_notification", (PyCFunction) cpy_register_notification, METH_VARARGS | METH_KEYWORDS, reg_notification_doc},
809         {"register_flush", (PyCFunction) cpy_register_flush, METH_VARARGS | METH_KEYWORDS, reg_flush_doc},
810         {"register_shutdown", (PyCFunction) cpy_register_shutdown, METH_VARARGS | METH_KEYWORDS, reg_shutdown_doc},
811         {"unregister_log", cpy_unregister_log, METH_O, unregister_doc},
812         {"unregister_init", cpy_unregister_init, METH_O, unregister_doc},
813         {"unregister_config", cpy_unregister_config, METH_O, unregister_doc},
814         {"unregister_read", cpy_unregister_read, METH_O, unregister_doc},
815         {"unregister_write", cpy_unregister_write, METH_O, unregister_doc},
816         {"unregister_notification", cpy_unregister_notification, METH_O, unregister_doc},
817         {"unregister_flush", cpy_unregister_flush, METH_O, unregister_doc},
818         {"unregister_shutdown", cpy_unregister_shutdown, METH_O, unregister_doc},
819         {0, 0, 0, 0}
820 };
822 static int cpy_shutdown(void) {
823         cpy_callback_t *c;
824         PyObject *ret;
825         
826         /* This can happen if the module was loaded but not configured. */
827         if (state != NULL)
828                 PyEval_RestoreThread(state);
830         for (c = cpy_shutdown_callbacks; c; c = c->next) {
831                 ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
832                 if (ret == NULL)
833                         cpy_log_exception("shutdown callback");
834                 else
835                         Py_DECREF(ret);
836         }
837         PyErr_Print();
838         Py_Finalize();
839         return 0;
842 static void cpy_int_handler(int sig) {
843         return;
846 static void *cpy_interactive(void *data) {
847         sigset_t sigset;
848         struct sigaction sig_int_action, old;
849         
850         /* Signal handler in a plugin? Bad stuff, but the best way to
851          * handle it I guess. In an interactive session people will
852          * press Ctrl+C at some time, which will generate a SIGINT.
853          * This will cause collectd to shutdown, thus killing the
854          * interactive interpreter, and leaving the terminal in a
855          * mess. Chances are, this isn't what the user wanted to do.
856          * 
857          * So this is the plan:
858          * 1. Block SIGINT in the main thread.
859          * 2. Install our own signal handler that does nothing.
860          * 3. Unblock SIGINT in the interactive thread.
861          *
862          * This will make sure that SIGINT won't kill collectd but
863          * still interrupt syscalls like sleep and pause.
864          * It does not raise a KeyboardInterrupt exception because so
865          * far nobody managed to figure out how to do that. */
866         memset (&sig_int_action, '\0', sizeof (sig_int_action));
867         sig_int_action.sa_handler = cpy_int_handler;
868         sigaction (SIGINT, &sig_int_action, &old);
869         
870         sigemptyset(&sigset);
871         sigaddset(&sigset, SIGINT);
872         pthread_sigmask(SIG_UNBLOCK, &sigset, NULL);
873         PyEval_AcquireThread(state);
874         if (PyImport_ImportModule("readline") == NULL) {
875                 /* This interactive session will suck. */
876                 cpy_log_exception("interactive session init");
877         }
878         PyRun_InteractiveLoop(stdin, "<stdin>");
879         PyErr_Print();
880         PyEval_ReleaseThread(state);
881         NOTICE("python: Interactive interpreter exited, stopping collectd ...");
882         /* Restore the original collectd SIGINT handler and raise SIGINT.
883          * The main thread still has SIGINT blocked and there's nothing we
884          * can do about that so this thread will handle it. But that's not
885          * important, except that it won't interrupt the main loop and so
886          * it might take a few seconds before collectd really shuts down. */
887         sigaction (SIGINT, &old, NULL);
888         raise(SIGINT);
889         pause();
890         return NULL;
893 static int cpy_init(void) {
894         cpy_callback_t *c;
895         PyObject *ret;
896         static pthread_t thread;
897         sigset_t sigset;
898         
899         PyEval_InitThreads();
900         /* Now it's finally OK to use python threads. */
901         for (c = cpy_init_callbacks; c; c = c->next) {
902                 ret = PyObject_CallFunctionObjArgs(c->callback, c->data, (void *) 0); /* New reference. */
903                 if (ret == NULL)
904                         cpy_log_exception("init callback");
905                 else
906                         Py_DECREF(ret);
907         }
908         sigemptyset(&sigset);
909         sigaddset(&sigset, SIGINT);
910         pthread_sigmask(SIG_BLOCK, &sigset, NULL);
911         state = PyEval_SaveThread();
912         if (do_interactive) {
913                 if (pthread_create(&thread, NULL, cpy_interactive, NULL)) {
914                         ERROR("python: Error creating thread for interactive interpreter.");
915                 }
916         }
918         return 0;
921 static PyObject *cpy_oconfig_to_pyconfig(oconfig_item_t *ci, PyObject *parent) {
922         int i;
923         PyObject *item, *values, *children, *tmp;
924         
925         if (parent == NULL)
926                 parent = Py_None;
927         
928         values = PyTuple_New(ci->values_num); /* New reference. */
929         for (i = 0; i < ci->values_num; ++i) {
930                 if (ci->values[i].type == OCONFIG_TYPE_STRING) {
931                         PyTuple_SET_ITEM(values, i, cpy_string_to_unicode_or_bytes(ci->values[i].value.string));
932                 } else if (ci->values[i].type == OCONFIG_TYPE_NUMBER) {
933                         PyTuple_SET_ITEM(values, i, PyFloat_FromDouble(ci->values[i].value.number));
934                 } else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN) {
935                         PyTuple_SET_ITEM(values, i, PyBool_FromLong(ci->values[i].value.boolean));
936                 }
937         }
938         
939         tmp = cpy_string_to_unicode_or_bytes(ci->key);
940         item = PyObject_CallFunction((void *) &ConfigType, "NONO", tmp, parent, values, Py_None);
941         if (item == NULL)
942                 return NULL;
943         children = PyTuple_New(ci->children_num); /* New reference. */
944         for (i = 0; i < ci->children_num; ++i) {
945                 PyTuple_SET_ITEM(children, i, cpy_oconfig_to_pyconfig(ci->children + i, item));
946         }
947         tmp = ((Config *) item)->children;
948         ((Config *) item)->children = children;
949         Py_XDECREF(tmp);
950         return item;
953 #ifdef IS_PY3K
954 static struct PyModuleDef collectdmodule = {
955         PyModuleDef_HEAD_INIT,
956         "collectd",   /* name of module */
957         "The python interface to collectd", /* module documentation, may be NULL */
958         -1,
959         cpy_methods
960 };
962 PyMODINIT_FUNC PyInit_collectd(void) {
963         return PyModule_Create(&collectdmodule);
965 #endif
967 static int cpy_config(oconfig_item_t *ci) {
968         int i;
969         PyObject *sys, *tb;
970         PyObject *sys_path;
971         PyObject *module;
972         
973         /* Ok in theory we shouldn't do initialization at this point
974          * but we have to. In order to give python scripts a chance
975          * to register a config callback we need to be able to execute
976          * python code during the config callback so we have to start
977          * the interpreter here. */
978         /* Do *not* use the python "thread" module at this point! */
980 #ifdef IS_PY3K
981         /* Add a builtin module, before Py_Initialize */
982         PyImport_AppendInittab("collectd", PyInit_collectd);
983 #endif
984         
985         Py_Initialize();
986         
987         PyType_Ready(&ConfigType);
988         PyType_Ready(&PluginDataType);
989         ValuesType.tp_base = &PluginDataType;
990         PyType_Ready(&ValuesType);
991         NotificationType.tp_base = &PluginDataType;
992         PyType_Ready(&NotificationType);
993         SignedType.tp_base = &PyLong_Type;
994         PyType_Ready(&SignedType);
995         UnsignedType.tp_base = &PyLong_Type;
996         PyType_Ready(&UnsignedType);
997         sys = PyImport_ImportModule("sys"); /* New reference. */
998         if (sys == NULL) {
999                 cpy_log_exception("python initialization");
1000                 return 1;
1001         }
1002         sys_path = PyObject_GetAttrString(sys, "path"); /* New reference. */
1003         Py_DECREF(sys);
1004         if (sys_path == NULL) {
1005                 cpy_log_exception("python initialization");
1006                 return 1;
1007         }
1008 #ifdef IS_PY3K
1009         module = PyImport_ImportModule("collectd");
1010 #else
1011         module = Py_InitModule("collectd", cpy_methods); /* Borrowed reference. */
1012 #endif
1013         PyModule_AddObject(module, "Config", (void *) &ConfigType); /* Steals a reference. */
1014         PyModule_AddObject(module, "Values", (void *) &ValuesType); /* Steals a reference. */
1015         PyModule_AddObject(module, "Notification", (void *) &NotificationType); /* Steals a reference. */
1016         PyModule_AddObject(module, "Signed", (void *) &SignedType); /* Steals a reference. */
1017         PyModule_AddObject(module, "Unsigned", (void *) &UnsignedType); /* Steals a reference. */
1018         PyModule_AddIntConstant(module, "LOG_DEBUG", LOG_DEBUG);
1019         PyModule_AddIntConstant(module, "LOG_INFO", LOG_INFO);
1020         PyModule_AddIntConstant(module, "LOG_NOTICE", LOG_NOTICE);
1021         PyModule_AddIntConstant(module, "LOG_WARNING", LOG_WARNING);
1022         PyModule_AddIntConstant(module, "LOG_ERROR", LOG_ERR);
1023         PyModule_AddIntConstant(module, "NOTIF_FAILURE", NOTIF_FAILURE);
1024         PyModule_AddIntConstant(module, "NOTIF_WARNING", NOTIF_WARNING);
1025         PyModule_AddIntConstant(module, "NOTIF_OKAY", NOTIF_OKAY);
1026         for (i = 0; i < ci->children_num; ++i) {
1027                 oconfig_item_t *item = ci->children + i;
1028                 
1029                 if (strcasecmp(item->key, "Interactive") == 0) {
1030                         if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_BOOLEAN)
1031                                 continue;
1032                         do_interactive = item->values[0].value.boolean;
1033                 } else if (strcasecmp(item->key, "Encoding") == 0) {
1034                         if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_STRING)
1035                                 continue;
1036                         /* Why is this even necessary? And undocumented? */
1037                         if (PyUnicode_SetDefaultEncoding(item->values[0].value.string))
1038                                 cpy_log_exception("setting default encoding");
1039                 } else if (strcasecmp(item->key, "LogTraces") == 0) {
1040                         if (item->values_num != 1 || item->values[0].type != OCONFIG_TYPE_BOOLEAN)
1041                                 continue;
1042                         if (!item->values[0].value.boolean) {
1043                                 Py_XDECREF(cpy_format_exception);
1044                                 cpy_format_exception = NULL;
1045                                 continue;
1046                         }
1047                         if (cpy_format_exception)
1048                                 continue;
1049                         tb = PyImport_ImportModule("traceback"); /* New reference. */
1050                         if (tb == NULL) {
1051                                 cpy_log_exception("python initialization");
1052                                 continue;
1053                         }
1054                         cpy_format_exception = PyObject_GetAttrString(tb, "format_exception"); /* New reference. */
1055                         Py_DECREF(tb);
1056                         if (cpy_format_exception == NULL)
1057                                 cpy_log_exception("python initialization");
1058                 } else if (strcasecmp(item->key, "ModulePath") == 0) {
1059                         char *dir = NULL;
1060                         PyObject *dir_object;
1061                         
1062                         if (cf_util_get_string(item, &dir) != 0) 
1063                                 continue;
1064                         dir_object = cpy_string_to_unicode_or_bytes(dir); /* New reference. */
1065                         if (dir_object == NULL) {
1066                                 ERROR("python plugin: Unable to convert \"%s\" to "
1067                                       "a python object.", dir);
1068                                 free(dir);
1069                                 cpy_log_exception("python initialization");
1070                                 continue;
1071                         }
1072                         if (PyList_Append(sys_path, dir_object) != 0) {
1073                                 ERROR("python plugin: Unable to append \"%s\" to "
1074                                       "python module path.", dir);
1075                                 cpy_log_exception("python initialization");
1076                         }
1077                         Py_DECREF(dir_object);
1078                         free(dir);
1079                 } else if (strcasecmp(item->key, "Import") == 0) {
1080                         char *module_name = NULL;
1081                         PyObject *module;
1082                         
1083                         if (cf_util_get_string(item, &module_name) != 0) 
1084                                 continue;
1085                         module = PyImport_ImportModule(module_name); /* New reference. */
1086                         if (module == NULL) {
1087                                 ERROR("python plugin: Error importing module \"%s\".", module_name);
1088                                 cpy_log_exception("importing module");
1089                         }
1090                         free(module_name);
1091                         Py_XDECREF(module);
1092                 } else if (strcasecmp(item->key, "Module") == 0) {
1093                         char *name = NULL;
1094                         cpy_callback_t *c;
1095                         PyObject *ret;
1096                         
1097                         if (cf_util_get_string(item, &name) != 0)
1098                                 continue;
1099                         for (c = cpy_config_callbacks; c; c = c->next) {
1100                                 if (strcasecmp(c->name + 7, name) == 0)
1101                                         break;
1102                         }
1103                         if (c == NULL) {
1104                                 WARNING("python plugin: Found a configuration for the \"%s\" plugin, "
1105                                         "but the plugin isn't loaded or didn't register "
1106                                         "a configuration callback.", name);
1107                                 free(name);
1108                                 continue;
1109                         }
1110                         free(name);
1111                         if (c->data == NULL)
1112                                 ret = PyObject_CallFunction(c->callback, "N",
1113                                         cpy_oconfig_to_pyconfig(item, NULL)); /* New reference. */
1114                         else
1115                                 ret = PyObject_CallFunction(c->callback, "NO",
1116                                         cpy_oconfig_to_pyconfig(item, NULL), c->data); /* New reference. */
1117                         if (ret == NULL)
1118                                 cpy_log_exception("loading module");
1119                         else
1120                                 Py_DECREF(ret);
1121                 } else {
1122                         WARNING("python plugin: Ignoring unknown config key \"%s\".", item->key);
1123                 }
1124         }
1125         Py_DECREF(sys_path);
1126         return 0;
1129 void module_register(void) {
1130         plugin_register_complex_config("python", cpy_config);
1131         plugin_register_init("python", cpy_init);
1132         plugin_register_shutdown("python", cpy_shutdown);