Merge pull request #2618 from ajssmith/amqp1_dev1_branch
[collectd.git] / src / python.c
index ac4b133..64db698 100644 (file)
@@ -241,7 +241,7 @@ static char CollectdError_doc[] =
 
 static pthread_t main_thread;
 static PyOS_sighandler_t python_sigint_handler;
-static _Bool do_interactive = 0;
+static bool do_interactive;
 
 /* This is our global thread state. Python saves some stuff in thread-local
  * storage. So if we allow the interpreter to run in the background
@@ -257,8 +257,8 @@ static cpy_callback_t *cpy_init_callbacks;
 static cpy_callback_t *cpy_shutdown_callbacks;
 
 /* Make sure to hold the GIL while modifying these. */
-static int cpy_shutdown_triggered = 0;
-static int cpy_num_callbacks = 0;
+static int cpy_shutdown_triggered;
+static int cpy_num_callbacks;
 
 static void cpy_destroy_user_data(void *data) {
   cpy_callback_t *c = data;
@@ -325,14 +325,14 @@ void cpy_log_exception(const char *context) {
     typename = "NamelessException";
   if (message == NULL)
     message = "N/A";
-  Py_BEGIN_ALLOW_THREADS
+  Py_BEGIN_ALLOW_THREADS;
   if (collectd_error) {
     WARNING("%s in %s: %s", typename, context, message);
   } else {
-    ERROR("Unhandled python exception in %s: %s: %s",
-          context, typename, message);
+    ERROR("Unhandled python exception in %s: %s: %s", context, typename,
+          message);
   }
-  Py_END_ALLOW_THREADS
+  Py_END_ALLOW_THREADS;
   Py_XDECREF(tn);
   Py_XDECREF(m);
   if (!cpy_format_exception || !traceback || collectd_error) {
@@ -369,9 +369,9 @@ void cpy_log_exception(const char *context) {
     if (cpy[strlen(cpy) - 1] == '\n')
       cpy[strlen(cpy) - 1] = 0;
 
-    Py_BEGIN_ALLOW_THREADS
+    Py_BEGIN_ALLOW_THREADS;
     ERROR("%s", cpy);
-    Py_END_ALLOW_THREADS
+    Py_END_ALLOW_THREADS;
 
     free(cpy);
   }
@@ -424,9 +424,9 @@ static int cpy_write_callback(const data_set_t *ds,
       PyList_SetItem(
           list, i, PyLong_FromUnsignedLongLong(value_list->values[i].absolute));
     } else {
-      Py_BEGIN_ALLOW_THREADS
+      Py_BEGIN_ALLOW_THREADS;
       ERROR("cpy_write_callback: Unknown value type %d.", ds->ds[i].type);
-      Py_END_ALLOW_THREADS
+      Py_END_ALLOW_THREADS;
       Py_DECREF(list);
       CPY_RETURN_FROM_THREADS 0;
     }
@@ -438,7 +438,7 @@ static int cpy_write_callback(const data_set_t *ds,
   }
   dict = PyDict_New(); /* New reference. */
   if (value_list->meta) {
-    char **table;
+    char **table = NULL;
     meta_data_t *meta = value_list->meta;
 
     int num = meta_data_toc(meta, &table);
@@ -448,7 +448,7 @@ static int cpy_write_callback(const data_set_t *ds,
       int64_t si;
       uint64_t ui;
       double d;
-      _Bool b;
+      bool b;
 
       type = meta_data_type(meta, table[i]);
       if (type == MD_TYPE_STRING) {
@@ -461,19 +461,21 @@ static int cpy_write_callback(const data_set_t *ds,
       } else if (type == MD_TYPE_SIGNED_INT) {
         if (meta_data_get_signed_int(meta, table[i], &si))
           continue;
-        temp = PyObject_CallFunctionObjArgs((void *)&SignedType,
-                                            PyLong_FromLongLong(si),
+        PyObject *sival = PyLong_FromLongLong(si); /* New reference */
+        temp = PyObject_CallFunctionObjArgs((void *)&SignedType, sival,
                                             (void *)0); /* New reference. */
         PyDict_SetItemString(dict, table[i], temp);
         Py_XDECREF(temp);
+        Py_XDECREF(sival);
       } else if (type == MD_TYPE_UNSIGNED_INT) {
         if (meta_data_get_unsigned_int(meta, table[i], &ui))
           continue;
-        temp = PyObject_CallFunctionObjArgs((void *)&UnsignedType,
-                                            PyLong_FromUnsignedLongLong(ui),
+        PyObject *uval = PyLong_FromUnsignedLongLong(ui); /* New reference */
+        temp = PyObject_CallFunctionObjArgs((void *)&UnsignedType, uval,
                                             (void *)0); /* New reference. */
         PyDict_SetItemString(dict, table[i], temp);
         Py_XDECREF(temp);
+        Py_XDECREF(uval);
       } else if (type == MD_TYPE_DOUBLE) {
         if (meta_data_get_double(meta, table[i], &d))
           continue;
@@ -525,6 +527,39 @@ static int cpy_notification_callback(const notification_t *notification,
   Notification *n;
 
   CPY_LOCK_THREADS
+  PyObject *dict = PyDict_New(); /* New reference. */
+  for (notification_meta_t *meta = notification->meta; meta != NULL;
+       meta = meta->next) {
+    PyObject *temp = NULL;
+    if (meta->type == NM_TYPE_STRING) {
+      temp = cpy_string_to_unicode_or_bytes(
+          meta->nm_value.nm_string); /* New reference. */
+      PyDict_SetItemString(dict, meta->name, temp);
+      Py_XDECREF(temp);
+    } else if (meta->type == NM_TYPE_SIGNED_INT) {
+      PyObject *sival = PyLong_FromLongLong(meta->nm_value.nm_signed_int);
+      temp = PyObject_CallFunctionObjArgs((void *)&SignedType, sival,
+                                          (void *)0); /* New reference. */
+      PyDict_SetItemString(dict, meta->name, temp);
+      Py_XDECREF(temp);
+      Py_XDECREF(sival);
+    } else if (meta->type == NM_TYPE_UNSIGNED_INT) {
+      PyObject *uval =
+          PyLong_FromUnsignedLongLong(meta->nm_value.nm_unsigned_int);
+      temp = PyObject_CallFunctionObjArgs((void *)&UnsignedType, uval,
+                                          (void *)0); /* New reference. */
+      PyDict_SetItemString(dict, meta->name, temp);
+      Py_XDECREF(temp);
+      Py_XDECREF(uval);
+    } else if (meta->type == NM_TYPE_DOUBLE) {
+      temp = PyFloat_FromDouble(meta->nm_value.nm_double); /* New reference. */
+      PyDict_SetItemString(dict, meta->name, temp);
+      Py_XDECREF(temp);
+    } else if (meta->type == NM_TYPE_BOOLEAN) {
+      PyDict_SetItemString(dict, meta->name,
+                           meta->nm_value.nm_boolean ? Py_True : Py_False);
+    }
+  }
   notify = Notification_New(); /* New reference. */
   n = (Notification *)notify;
   sstrncpy(n->data.host, notification->host, sizeof(n->data.host));
@@ -537,6 +572,8 @@ static int cpy_notification_callback(const notification_t *notification,
   n->data.time = CDTIME_T_TO_DOUBLE(notification->time);
   sstrncpy(n->message, notification->message, sizeof(n->message));
   n->severity = notification->severity;
+  Py_CLEAR(n->meta);
+  n->meta = dict; /* Steals a reference. */
   ret = PyObject_CallFunctionObjArgs(c->callback, n, c->data,
                                      (void *)0); /* New reference. */
   Py_XDECREF(notify);
@@ -683,9 +720,9 @@ static PyObject *cpy_flush(PyObject *self, PyObject *args, PyObject *kwds) {
   if (PyArg_ParseTupleAndKeywords(args, kwds, "|etiet", kwlist, NULL, &plugin,
                                   &timeout, NULL, &identifier) == 0)
     return NULL;
-  Py_BEGIN_ALLOW_THREADS
+  Py_BEGIN_ALLOW_THREADS;
   plugin_flush(plugin, timeout, identifier);
-  Py_END_ALLOW_THREADS
+  Py_END_ALLOW_THREADS;
   PyMem_Free(plugin);
   PyMem_Free(identifier);
   Py_RETURN_NONE;
@@ -820,9 +857,9 @@ static PyObject *cpy_error(PyObject *self, PyObject *args) {
   char *text;
   if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
     return NULL;
-  Py_BEGIN_ALLOW_THREADS
+  Py_BEGIN_ALLOW_THREADS;
   plugin_log(LOG_ERR, "%s", text);
-  Py_END_ALLOW_THREADS
+  Py_END_ALLOW_THREADS;
   PyMem_Free(text);
   Py_RETURN_NONE;
 }
@@ -831,9 +868,9 @@ static PyObject *cpy_warning(PyObject *self, PyObject *args) {
   char *text;
   if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
     return NULL;
-  Py_BEGIN_ALLOW_THREADS
+  Py_BEGIN_ALLOW_THREADS;
   plugin_log(LOG_WARNING, "%s", text);
-  Py_END_ALLOW_THREADS
+  Py_END_ALLOW_THREADS;
   PyMem_Free(text);
   Py_RETURN_NONE;
 }
@@ -842,9 +879,9 @@ static PyObject *cpy_notice(PyObject *self, PyObject *args) {
   char *text;
   if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
     return NULL;
-  Py_BEGIN_ALLOW_THREADS
+  Py_BEGIN_ALLOW_THREADS;
   plugin_log(LOG_NOTICE, "%s", text);
-  Py_END_ALLOW_THREADS
+  Py_END_ALLOW_THREADS;
   PyMem_Free(text);
   Py_RETURN_NONE;
 }
@@ -853,9 +890,9 @@ static PyObject *cpy_info(PyObject *self, PyObject *args) {
   char *text;
   if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
     return NULL;
-  Py_BEGIN_ALLOW_THREADS
+  Py_BEGIN_ALLOW_THREADS;
   plugin_log(LOG_INFO, "%s", text);
-  Py_END_ALLOW_THREADS
+  Py_END_ALLOW_THREADS;
   PyMem_Free(text);
   Py_RETURN_NONE;
 }
@@ -865,9 +902,9 @@ static PyObject *cpy_debug(PyObject *self, PyObject *args) {
   char *text;
   if (PyArg_ParseTuple(args, "et", NULL, &text) == 0)
     return NULL;
-  Py_BEGIN_ALLOW_THREADS
+  Py_BEGIN_ALLOW_THREADS;
   plugin_log(LOG_DEBUG, "%s", text);
-  Py_END_ALLOW_THREADS
+  Py_END_ALLOW_THREADS;
   PyMem_Free(text);
 #endif
   Py_RETURN_NONE;
@@ -1050,12 +1087,12 @@ static int cpy_shutdown(void) {
   }
   PyErr_Print();
 
-  Py_BEGIN_ALLOW_THREADS
+  Py_BEGIN_ALLOW_THREADS;
   cpy_unregister_list(&cpy_config_callbacks);
   cpy_unregister_list(&cpy_init_callbacks);
   cpy_unregister_list(&cpy_shutdown_callbacks);
   cpy_shutdown_triggered = 1;
-  Py_END_ALLOW_THREADS
+  Py_END_ALLOW_THREADS;
 
   if (!cpy_num_callbacks) {
     Py_Finalize();
@@ -1227,7 +1264,9 @@ static int cpy_init_python(void) {
   UnsignedType.tp_base = &PyLong_Type;
   PyType_Ready(&UnsignedType);
   errordict = PyDict_New();
-  PyDict_SetItemString(errordict, "__doc__", cpy_string_to_unicode_or_bytes(CollectdError_doc)); /* New reference. */
+  PyDict_SetItemString(
+      errordict, "__doc__",
+      cpy_string_to_unicode_or_bytes(CollectdError_doc)); /* New reference. */
   CollectdError = PyErr_NewException("collectd.CollectdError", NULL, errordict);
   sys = PyImport_ImportModule("sys"); /* New reference. */
   if (sys == NULL) {
@@ -1259,7 +1298,8 @@ static int cpy_init_python(void) {
   PyModule_AddObject(module, "Unsigned",
                      (void *)&UnsignedType); /* Steals a reference. */
   Py_XINCREF(CollectdError);
-  PyModule_AddObject(module, "CollectdError", CollectdError); /* Steals a reference. */
+  PyModule_AddObject(module, "CollectdError",
+                     CollectdError); /* Steals a reference. */
   PyModule_AddIntConstant(module, "LOG_DEBUG", LOG_DEBUG);
   PyModule_AddIntConstant(module, "LOG_INFO", LOG_INFO);
   PyModule_AddIntConstant(module, "LOG_NOTICE", LOG_NOTICE);
@@ -1322,7 +1362,7 @@ static int cpy_config(oconfig_item_t *ci) {
 #endif
       sfree(encoding);
     } else if (strcasecmp(item->key, "LogTraces") == 0) {
-      _Bool log_traces;
+      bool log_traces;
       if (cf_util_get_boolean(item, &log_traces) != 0) {
         status = 1;
         continue;