From: Sven Trenkel Date: Tue, 3 Nov 2009 00:32:36 +0000 (+0100) Subject: Added write callbacks. X-Git-Tag: collectd-4.9.0~35^2~28 X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=54c1aa1fb0fd0b5a1e8a1f13bd9c92a1de3d6445;p=collectd.git Added write callbacks. --- diff --git a/src/cpython.h b/src/cpython.h index bec6cde9..4cac6c59 100644 --- a/src/cpython.h +++ b/src/cpython.h @@ -14,6 +14,10 @@ PyGILState_STATE gil_state;\ gil_state = PyGILState_Ensure(); +#define CPY_RETURN_FROM_THREADS \ + PyGILState_Release(gil_state);\ + return + #define CPY_RELEASE_THREADS \ PyGILState_Release(gil_state);\ } diff --git a/src/python.c b/src/python.c index c15b0d55..56061ff5 100644 --- a/src/python.c +++ b/src/python.c @@ -32,6 +32,92 @@ static void cpy_destroy_user_data(void *data) { free(c); } +static void cpy_build_name(char *buf, size_t size, PyObject *callback, const char *name) { + const char *module; + PyObject *mod = NULL, *n = NULL; + + if (name != NULL && strchr(name, '.') != NULL) { + snprintf(buf, size, "python.%s", name); + return; + } + + mod = PyObject_GetAttrString(callback, "__module__"); /* New reference. */ + if (mod != NULL) + module = PyString_AsString(mod); + else + module = "collectd"; + if (name != NULL) { + snprintf(buf, size, "python.%s.%s", module, name); + Py_XDECREF(mod); + return; + } + + n = PyObject_GetAttrString(callback, "__name__"); /* New reference. */ + if (n != NULL) + name = PyString_AsString(n); + + if (name != NULL) + snprintf(buf, size, "python.%s.%s", module, name); + else + snprintf(buf, size, "python.%s.%p", module, callback); + Py_XDECREF(mod); + Py_XDECREF(n); +} + +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, *v, *list; + + CPY_LOCK_THREADS + list = PyList_New(value_list->values_len); /* New reference. */ + if (list == NULL) { + PyErr_Print(); + CPY_RETURN_FROM_THREADS 0; + } + for (i = 0; i < value_list->values_len; ++i) { + if (ds->ds->type == DS_TYPE_COUNTER) { + if ((long) value_list->values[i].counter == value_list->values[i].counter) + PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].counter)); + else + PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].counter)); + } else if (ds->ds->type == DS_TYPE_GAUGE) { + PyList_SetItem(list, i, PyFloat_FromDouble(value_list->values[i].gauge)); + } else if (ds->ds->type == DS_TYPE_DERIVE) { + if ((long) value_list->values[i].derive == value_list->values[i].derive) + PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].derive)); + else + PyList_SetItem(list, i, PyLong_FromLongLong(value_list->values[i].derive)); + } else if (ds->ds->type == DS_TYPE_ABSOLUTE) { + if ((long) value_list->values[i].absolute == value_list->values[i].absolute) + PyList_SetItem(list, i, PyInt_FromLong(value_list->values[i].absolute)); + else + PyList_SetItem(list, i, PyLong_FromUnsignedLongLong(value_list->values[i].absolute)); + } else { + ERROR("cpy_write_callback: Unknown value type %d.", ds->ds->type); + Py_DECREF(list); + CPY_RETURN_FROM_THREADS 0; + } + if (PyErr_Occurred() != NULL) { + PyErr_Print(); + CPY_RETURN_FROM_THREADS 0; + } + } + v = PyObject_CallFunction((PyObject *) &ValuesType, "sOssssdi", value_list->type, list, + value_list->plugin_instance, value_list->type_instance, value_list->plugin, + value_list->host, (double) value_list->time, value_list->interval); + Py_DECREF(list); + ret = PyObject_CallFunctionObjArgs(c->callback, v, (void *) 0); + if (ret == NULL) { + /* FIXME */ + PyErr_Print(); + } else { + Py_DECREF(ret); + } + CPY_RELEASE_THREADS + return 0; +} + static void cpy_log_callback(int severity, const char *message, user_data_t *data) { cpy_callback_t * c = data->data; PyObject *ret; @@ -54,7 +140,7 @@ static void cpy_log_callback(int severity, const char *message, user_data_t *dat static PyObject *cpy_register_generic(cpy_callback_t **list_head, PyObject *args, PyObject *kwds) { cpy_callback_t *c; const char *name = NULL; - PyObject *callback = NULL, *data = NULL; + PyObject *callback = NULL, *data = NULL, *mod = NULL; static char *kwlist[] = {"callback", "data", "name", NULL}; if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oz", kwlist, &callback, &data, &name) == 0) return NULL; @@ -63,11 +149,10 @@ static PyObject *cpy_register_generic(cpy_callback_t **list_head, PyObject *args return NULL; } if (name == NULL) { - PyObject *mod; - - mod = PyObject_GetAttrString(callback, "__module__"); + mod = PyObject_GetAttrString(callback, "__module__"); /* New reference. */ if (mod != NULL) name = PyString_AsString(mod); if (name == NULL) { + Py_XDECREF(mod); PyErr_SetString(PyExc_ValueError, "No module name specified and " "callback function does not have a \"__module__\" attribute."); return NULL; @@ -81,6 +166,7 @@ static PyObject *cpy_register_generic(cpy_callback_t **list_head, PyObject *args c->data = data; c->next = *list_head; *list_head = c; + Py_XDECREF(mod); Py_RETURN_NONE; } @@ -92,7 +178,11 @@ static PyObject *cpy_register_init(PyObject *self, PyObject *args, PyObject *kwd return cpy_register_generic(&cpy_init_callbacks, args, kwds); } -static PyObject *cpy_register_log(PyObject *self, PyObject *args, PyObject *kwds) { +typedef int reg_function_t(const char *name, void *callback, void *data); + +static PyObject *cpy_register_generic_userdata(void *reg, void *handler, PyObject *args, PyObject *kwds) { + char buf[512]; + reg_function_t *register_function = (reg_function_t *) reg; cpy_callback_t *c = NULL; user_data_t *user_data = NULL; const char *name = NULL; @@ -104,29 +194,28 @@ static PyObject *cpy_register_log(PyObject *self, PyObject *args, PyObject *kwds PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object."); return NULL; } - if (name == NULL) { - PyObject *mod; - - mod = PyObject_GetAttrString(callback, "__module__"); - if (mod != NULL) name = PyString_AsString(mod); - if (name == NULL) { - PyErr_SetString(PyExc_ValueError, "No module name specified and " - "callback function does not have a \"__module__\" attribute."); - return NULL; - } - } + cpy_build_name(buf, sizeof(buf), callback, name); + Py_INCREF(callback); Py_XINCREF(data); c = malloc(sizeof(*c)); - c->name = strdup(name); + c->name = strdup(buf); c->callback = callback; c->data = data; c->next = NULL; user_data = malloc(sizeof(*user_data)); user_data->free_func = cpy_destroy_user_data; user_data->data = c; - plugin_register_log(name, cpy_log_callback, user_data); - Py_RETURN_NONE; + register_function(buf, handler, user_data); + return PyString_FromString(buf); +} + +static PyObject *cpy_register_log(PyObject *self, PyObject *args, PyObject *kwds) { + return cpy_register_generic_userdata(plugin_register_log, cpy_log_callback, args, kwds); +} + +static PyObject *cpy_register_write(PyObject *self, PyObject *args, PyObject *kwds) { + return cpy_register_generic_userdata(plugin_register_write, cpy_write_callback, args, kwds); } static PyObject *cpy_register_shutdown(PyObject *self, PyObject *args, PyObject *kwds) { @@ -187,6 +276,7 @@ static PyMethodDef cpy_methods[] = { {"register_log", (PyCFunction) cpy_register_log, METH_VARARGS | METH_KEYWORDS, "This is an unhelpful text."}, {"register_init", (PyCFunction) cpy_register_init, METH_VARARGS | METH_KEYWORDS, "This is an unhelpful text."}, {"register_config", (PyCFunction) cpy_register_config, METH_VARARGS | METH_KEYWORDS, "This is an unhelpful text."}, + {"register_write", (PyCFunction) cpy_register_write, METH_VARARGS | METH_KEYWORDS, "This is an unhelpful text."}, {"register_shutdown", (PyCFunction) cpy_register_shutdown, METH_VARARGS | METH_KEYWORDS, "This is an unhelpful text."}, {0, 0, 0, 0} };