Added support for receiving meta data in write callbacks.
authorSven Trenkel <collectd@semidefinite.de>
Wed, 27 Jan 2010 10:27:54 +0000 (11:27 +0100)
committerSven Trenkel <collectd@semidefinite.de>
Wed, 27 Jan 2010 10:27:54 +0000 (11:27 +0100)
Probably, it's not like there is a test case.

src/cpython.h
src/python.c
src/pyvalues.c

index 3e80cb0..df7fc6a 100644 (file)
@@ -182,6 +182,7 @@ PyTypeObject PluginDataType;
 typedef struct {
        PluginData data;
        PyObject *values;    /* Sequence */
+       PyObject *meta;      /* dict */
        int interval;
 } Values;
 
index 5664b0c..a1e6a7e 100644 (file)
@@ -335,7 +335,7 @@ static int cpy_read_callback(user_data_t *data) {
 static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_list, user_data_t *data) {
        int i;
        cpy_callback_t *c = data->data;
-       PyObject *ret, *list;
+       PyObject *ret, *list, *temp, *dict = NULL;
        Values *v;
 
        CPY_LOCK_THREADS
@@ -374,6 +374,60 @@ static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_li
                                CPY_RETURN_FROM_THREADS 0;
                        }
                }
+               dict = PyDict_New();
+               if (value_list->meta) {
+                       int i, num;
+                       char **table;
+                       meta_data_t *meta = value_list->meta;
+
+                       num = meta_data_toc(meta, &table);
+                       for (i = 0; i < num; ++i) {
+                               int type;
+                               char *string;
+                               int64_t si;
+                               uint64_t ui;
+                               double d;
+                               _Bool b;
+                               
+                               type = meta_data_type(meta, table[i]);
+                               if (type == MD_TYPE_STRING) {
+                                       if (meta_data_get_string(meta, table[i], &string))
+                                               continue;
+                                       temp = cpy_string_to_unicode_or_bytes(string);
+                                       free(string);
+                                       PyDict_SetItemString(dict, table[i], temp);
+                                       Py_XDECREF(temp);
+                               } else if (type == MD_TYPE_SIGNED_INT) {
+                                       if (meta_data_get_signed_int(meta, table[i], &si))
+                                               continue;
+                                       temp = PyLong_FromLongLong(si);
+                                       PyDict_SetItemString(dict, table[i], temp);
+                                       Py_XDECREF(temp);
+                               } else if (type == MD_TYPE_UNSIGNED_INT) {
+                                       if (meta_data_get_unsigned_int(meta, table[i], &ui))
+                                               continue;
+                                       temp = PyLong_FromUnsignedLongLong(ui);
+                                       PyDict_SetItemString(dict, table[i], temp);
+                                       Py_XDECREF(temp);
+                               } else if (type == MD_TYPE_DOUBLE) {
+                                       if (meta_data_get_double(meta, table[i], &d))
+                                               continue;
+                                       temp = PyFloat_FromDouble(d);
+                                       PyDict_SetItemString(dict, table[i], temp);
+                                       Py_XDECREF(temp);
+                               } else if (type == MD_TYPE_BOOLEAN) {
+                                       if (meta_data_get_boolean(meta, table[i], &b))
+                                               continue;
+                                       if (b)
+                                               temp = Py_True;
+                                       else
+                                               temp = Py_False;
+                                       PyDict_SetItemString(dict, table[i], temp);
+                               }
+                               free(table[i]);
+                       }
+                       free(table);
+               }
                v = PyObject_New(Values, (void *) &ValuesType);
                sstrncpy(v->data.host, value_list->host, sizeof(v->data.host));
                sstrncpy(v->data.type, value_list->type, sizeof(v->data.type));
@@ -383,6 +437,7 @@ static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_li
                v->data.time = value_list->time;
                v->interval = value_list->interval;
                v->values = list;
+               v->meta = dict;
                ret = PyObject_CallFunctionObjArgs(c->callback, v, c->data, (void *) 0); /* New reference. */
                if (ret == NULL) {
                        cpy_log_exception("write callback");
index a632dc1..ed0270f 100644 (file)
@@ -308,6 +308,10 @@ static char values_doc[] = "These are the actual values that get dispatched to c
                "exception will be raised. If the content of the sequence is not a number,\n"
                "a TypeError exception will be raised.";
 
+static char meta_doc[] = "These are the meta data for this Value object.\n"
+               "It has to be a dictionary of numbers, strings or bools.\n"
+               "If the dict contains anything else a TypeError exception will be raised.";
+
 static char dispatch_doc[] = "dispatch([type][, values][, plugin_instance][, type_instance]"
                "[, plugin][, host][, time][, interval]) -> None.  Dispatch a value list.\n"
                "\n"
@@ -344,14 +348,14 @@ static int Values_init(PyObject *s, PyObject *args, PyObject *kwds) {
        Values *self = (Values *) s;
        int interval = 0;
        double time = 0;
-       PyObject *values = NULL, *tmp;
+       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", NULL};
+                       "plugin", "host", "time", "interval", "meta", NULL};
        
-       if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetdi", kwlist,
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetdiO", kwlist,
                        NULL, &type, &values, NULL, &plugin_instance, NULL, &type_instance,
-                       NULL, &plugin, NULL, &host, &time, &interval))
+                       NULL, &plugin, NULL, &host, &time, &interval, &meta))
                return -1;
        
        if (type[0] != 0 && plugin_get_ds(type) == NULL) {
@@ -373,8 +377,16 @@ static int Values_init(PyObject *s, PyObject *args, PyObject *kwds) {
                Py_INCREF(values);
        }
        
+       if (meta == NULL) {
+               meta = PyDict_New();
+               PyErr_Clear();
+       } else {
+               Py_INCREF(meta);
+       }
+       
        tmp = self->values;
        self->values = values;
+       self->meta = meta;
        Py_XDECREF(tmp);
        
        self->interval = interval;
@@ -582,17 +594,19 @@ static PyObject *Values_write(Values *self, PyObject *args, PyObject *kwds) {
 
 static PyObject *Values_repr(PyObject *s) {
        PyObject *ret, *tmp;
-       static PyObject *l_interval = NULL, *l_values = NULL, *l_closing = NULL;
+       static PyObject *l_interval = NULL, *l_values = NULL, *l_meta = NULL, *l_closing = NULL;
        Values *self = (Values *) s;
        
        if (l_interval == NULL)
                l_interval = cpy_string_to_unicode_or_bytes(",interval=");
        if (l_values == NULL)
                l_values = cpy_string_to_unicode_or_bytes(",values=");
+       if (l_meta == NULL)
+               l_meta = cpy_string_to_unicode_or_bytes(",meta=");
        if (l_closing == NULL)
                l_closing = cpy_string_to_unicode_or_bytes(")");
        
-       if (l_interval == NULL || l_values == NULL || l_closing == NULL)
+       if (l_interval == NULL || l_values == NULL || l_meta == NULL || l_closing == NULL)
                return NULL;
        
        ret = cpy_common_repr(s);
@@ -602,11 +616,16 @@ static PyObject *Values_repr(PyObject *s) {
                CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
                CPY_STRCAT_AND_DEL(&ret, tmp);
        }
-       if (self->values != NULL && PySequence_Length(self->values) > 0) {
+       if (self->values && (!PyList_Check(self->values) || PySequence_Length(self->values) > 0)) {
                CPY_STRCAT(&ret, l_values);
                tmp = PyObject_Repr(self->values);
                CPY_STRCAT_AND_DEL(&ret, tmp);
        }
+       if (self->meta && (!PyDict_Check(self->meta) || PyDict_Size(self->meta) > 0)) {
+               CPY_STRCAT(&ret, l_meta);
+               tmp = PyObject_Repr(self->meta);
+               CPY_STRCAT_AND_DEL(&ret, tmp);
+       }
        CPY_STRCAT(&ret, l_closing);
        return ret;
 }
@@ -614,12 +633,14 @@ static PyObject *Values_repr(PyObject *s) {
 static int Values_traverse(PyObject *self, visitproc visit, void *arg) {
        Values *v = (Values *) self;
        Py_VISIT(v->values);
+       Py_VISIT(v->meta);
        return 0;
 }
 
 static int Values_clear(PyObject *self) {
        Values *v = (Values *) self;
        Py_CLEAR(v->values);
+       Py_CLEAR(v->meta);
        return 0;
 }
 
@@ -631,6 +652,7 @@ static void Values_dealloc(PyObject *self) {
 static PyMemberDef Values_members[] = {
        {"interval", T_INT, offsetof(Values, interval), 0, interval_doc},
        {"values", T_OBJECT_EX, offsetof(Values, values), 0, values_doc},
+       {"meta", T_OBJECT_EX, offsetof(Values, meta), 0, meta_doc},
        {NULL}
 };