Merge branch 'collectd-4.10' into collectd-5.0
[collectd.git] / src / pyvalues.c
index cc7e296..9d8760a 100644 (file)
@@ -91,7 +91,7 @@ static PyObject *cpy_common_repr(PyObject *s) {
 
        if (self->time != 0) {
                CPY_STRCAT(&ret, l_time);
-               tmp = PyInt_FromLong(self->time);
+               tmp = PyFloat_FromDouble(self->time);
                CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
                CPY_STRCAT_AND_DEL(&ret, tmp);
        }
@@ -351,14 +351,13 @@ static PyObject *Values_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 
 static int Values_init(PyObject *s, PyObject *args, PyObject *kwds) {
        Values *self = (Values *) s;
-       int interval = 0;
-       double time = 0;
+       double interval = 0, time = 0;
        PyObject *values = NULL, *meta = NULL, *tmp;
        const char *type = "", *plugin_instance = "", *type_instance = "", *plugin = "", *host = "";
        static char *kwlist[] = {"type", "values", "plugin_instance", "type_instance",
                        "plugin", "host", "time", "interval", "meta", NULL};
        
-       if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetdiO", kwlist,
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetddO", kwlist,
                        NULL, &type, &values, NULL, &plugin_instance, NULL, &type_instance,
                        NULL, &plugin, NULL, &host, &time, &interval, &meta))
                return -1;
@@ -409,8 +408,12 @@ static meta_data_t *cpy_build_meta(PyObject *meta) {
        if (!meta)
                return NULL;
 
+       l = PyDict_Items(meta); /* New reference. */
+       if (!l) {
+               cpy_log_exception("building meta data");
+               return NULL;
+       }
        m = meta_data_create();
-       l = PyDict_Items(meta);
        s = PyList_Size(l);
        for (i = 0; i < s; ++i) {
                const char *string, *keystring;
@@ -475,6 +478,7 @@ static meta_data_t *cpy_build_meta(PyObject *meta) {
                Py_XDECREF(value);
                Py_DECREF(key);
        }
+       Py_XDECREF(l);
        return m;
 }
 
@@ -485,8 +489,7 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
        value_t *value;
        value_list_t value_list = VALUE_LIST_INIT;
        PyObject *values = self->values, *meta = self->meta;
-       double time = self->data.time;
-       int interval = self->interval;
+       double time = self->data.time, interval = self->interval;
        const char *host = self->data.host;
        const char *plugin = self->data.plugin;
        const char *plugin_instance = self->data.plugin_instance;
@@ -495,7 +498,7 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
        
        static char *kwlist[] = {"type", "values", "plugin_instance", "type_instance",
                        "plugin", "host", "time", "interval", "meta", NULL};
-       if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetdiO", kwlist,
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetddO", kwlist,
                        NULL, &type, &values, NULL, &plugin_instance, NULL, &type_instance,
                        NULL, &plugin, NULL, &host, &time, &interval, &meta))
                return NULL;
@@ -525,27 +528,35 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
        value = malloc(size * sizeof(*value));
        for (i = 0; i < size; ++i) {
                PyObject *item, *num;
-               item = PySequence_GetItem(values, i);
+               item = PySequence_Fast_GET_ITEM(values, i); /* Borrowed reference. */
                if (ds->ds->type == DS_TYPE_COUNTER) {
-                       num = PyNumber_Long(item);
-                       if (num != NULL)
+                       num = PyNumber_Long(item); /* New reference. */
+                       if (num != NULL) {
                                value[i].counter = PyLong_AsUnsignedLongLong(num);
+                               Py_XDECREF(num);
+                       }
                } else if (ds->ds->type == DS_TYPE_GAUGE) {
-                       num = PyNumber_Float(item);
-                       if (num != NULL)
+                       num = PyNumber_Float(item); /* New reference. */
+                       if (num != NULL) {
                                value[i].gauge = PyFloat_AsDouble(num);
+                               Py_XDECREF(num);
+                       }
                } else if (ds->ds->type == DS_TYPE_DERIVE) {
                        /* This might overflow without raising an exception.
                         * Not much we can do about it */
-                       num = PyNumber_Long(item);
-                       if (num != NULL)
+                       num = PyNumber_Long(item); /* New reference. */
+                       if (num != NULL) {
                                value[i].derive = PyLong_AsLongLong(num);
+                               Py_XDECREF(num);
+                       }
                } else if (ds->ds->type == DS_TYPE_ABSOLUTE) {
                        /* This might overflow without raising an exception.
                         * Not much we can do about it */
-                       num = PyNumber_Long(item);
-                       if (num != NULL)
+                       num = PyNumber_Long(item); /* New reference. */
+                       if (num != NULL) {
                                value[i].absolute = PyLong_AsUnsignedLongLong(num);
+                               Py_XDECREF(num);
+                       }
                } else {
                        free(value);
                        PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s", ds->ds->type, type);
@@ -559,8 +570,8 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
        value_list.values = value;
        value_list.meta = cpy_build_meta(meta);
        value_list.values_len = size;
-       value_list.time = time;
-       value_list.interval = interval;
+       value_list.time = DOUBLE_TO_CDTIME_T(time);
+       value_list.interval = DOUBLE_TO_CDTIME_T(interval);
        sstrncpy(value_list.host, host, sizeof(value_list.host));
        sstrncpy(value_list.plugin, plugin, sizeof(value_list.plugin));
        sstrncpy(value_list.plugin_instance, plugin_instance, sizeof(value_list.plugin_instance));
@@ -573,11 +584,12 @@ static PyObject *Values_dispatch(Values *self, PyObject *args, PyObject *kwds) {
        Py_BEGIN_ALLOW_THREADS;
        ret = plugin_dispatch_values(&value_list);
        Py_END_ALLOW_THREADS;
+       meta_data_destroy(value_list.meta);
+       free(value);
        if (ret != 0) {
                PyErr_SetString(PyExc_RuntimeError, "error dispatching values, read the logs");
                return NULL;
        }
-       free(value);
        Py_RETURN_NONE;
 }
 
@@ -588,8 +600,7 @@ static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
        value_t *value;
        value_list_t value_list = VALUE_LIST_INIT;
        PyObject *values = self->values, *meta = self->meta;
-       double time = self->data.time;
-       int interval = self->interval;
+       double time = self->data.time, interval = self->interval;
        const char *host = self->data.host;
        const char *plugin = self->data.plugin;
        const char *plugin_instance = self->data.plugin_instance;
@@ -599,7 +610,7 @@ static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
        
        static char *kwlist[] = {"destination", "type", "values", "plugin_instance", "type_instance",
                        "plugin", "host", "time", "interval", "meta", NULL};
-       if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetdiO", kwlist,
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetddO", kwlist,
                        NULL, &type, &values, NULL, &plugin_instance, NULL, &type_instance,
                        NULL, &plugin, NULL, &host, &time, &interval, &meta))
                return NULL;
@@ -625,27 +636,35 @@ static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
        value = malloc(size * sizeof(*value));
        for (i = 0; i < size; ++i) {
                PyObject *item, *num;
-               item = PySequence_GetItem(values, i);
+               item = PySequence_Fast_GET_ITEM(values, i); /* Borrowed reference. */
                if (ds->ds->type == DS_TYPE_COUNTER) {
-                       num = PyNumber_Long(item);
-                       if (num != NULL)
+                       num = PyNumber_Long(item); /* New reference. */
+                       if (num != NULL) {
                                value[i].counter = PyLong_AsUnsignedLongLong(num);
+                               Py_XDECREF(num);
+                       }
                } else if (ds->ds->type == DS_TYPE_GAUGE) {
-                       num = PyNumber_Float(item);
-                       if (num != NULL)
+                       num = PyNumber_Float(item); /* New reference. */
+                       if (num != NULL) {
                                value[i].gauge = PyFloat_AsDouble(num);
+                               Py_XDECREF(num);
+                       }
                } else if (ds->ds->type == DS_TYPE_DERIVE) {
                        /* This might overflow without raising an exception.
                         * Not much we can do about it */
-                       num = PyNumber_Long(item);
-                       if (num != NULL)
+                       num = PyNumber_Long(item); /* New reference. */
+                       if (num != NULL) {
                                value[i].derive = PyLong_AsLongLong(num);
+                               Py_XDECREF(num);
+                       }
                } else if (ds->ds->type == DS_TYPE_ABSOLUTE) {
                        /* This might overflow without raising an exception.
                         * Not much we can do about it */
-                       num = PyNumber_Long(item);
-                       if (num != NULL)
+                       num = PyNumber_Long(item); /* New reference. */
+                       if (num != NULL) {
                                value[i].absolute = PyLong_AsUnsignedLongLong(num);
+                               Py_XDECREF(num);
+                       }
                } else {
                        free(value);
                        PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s", ds->ds->type, type);
@@ -658,8 +677,8 @@ static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
        }
        value_list.values = value;
        value_list.values_len = size;
-       value_list.time = time;
-       value_list.interval = interval;
+       value_list.time = DOUBLE_TO_CDTIME_T(time);
+       value_list.interval = DOUBLE_TO_CDTIME_T(interval);
        sstrncpy(value_list.host, host, sizeof(value_list.host));
        sstrncpy(value_list.plugin, plugin, sizeof(value_list.plugin));
        sstrncpy(value_list.plugin_instance, plugin_instance, sizeof(value_list.plugin_instance));
@@ -673,11 +692,12 @@ static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
        Py_BEGIN_ALLOW_THREADS;
        ret = plugin_write(dest, NULL, &value_list);
        Py_END_ALLOW_THREADS;
+       meta_data_destroy(value_list.meta);
+       free(value);
        if (ret != 0) {
                PyErr_SetString(PyExc_RuntimeError, "error dispatching values, read the logs");
                return NULL;
        }
-       free(value);
        Py_RETURN_NONE;
 }
 
@@ -701,7 +721,7 @@ static PyObject *Values_repr(PyObject *s) {
        ret = cpy_common_repr(s);
        if (self->interval != 0) {
                CPY_STRCAT(&ret, l_interval);
-               tmp = PyInt_FromLong(self->interval);
+               tmp = PyFloat_FromDouble(self->interval);
                CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
                CPY_STRCAT_AND_DEL(&ret, tmp);
        }
@@ -864,7 +884,7 @@ static PyObject *Notification_dispatch(Notification *self, PyObject *args, PyObj
                return NULL;
        }
 
-       notification.time = t;
+       notification.time = DOUBLE_TO_CDTIME_T(t);
        notification.severity = severity;
        sstrncpy(notification.message, message, sizeof(notification.message));
        sstrncpy(notification.host, host, sizeof(notification.host));
@@ -873,8 +893,8 @@ static PyObject *Notification_dispatch(Notification *self, PyObject *args, PyObj
        sstrncpy(notification.type, type, sizeof(notification.type));
        sstrncpy(notification.type_instance, type_instance, sizeof(notification.type_instance));
        notification.meta = NULL;
-       if (notification.time < 1)
-               notification.time = time(0);
+       if (notification.time == 0)
+               notification.time = cdtime();
        if (notification.host[0] == 0)
                sstrncpy(notification.host, hostname_g, sizeof(notification.host));
        if (notification.plugin[0] == 0)