From ba6801e05bb6970fca853c3f4568223db3bf51a0 Mon Sep 17 00:00:00 2001 From: Florian Forster Date: Sun, 28 Nov 2010 09:41:19 +0100 Subject: [PATCH] lua plugin: Move the type conversion functions to a separate module. --- src/Makefile.am | 3 +- src/lua.c | 212 +------------------------------------------------ src/utils_lua.c | 239 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/utils_lua.h | 39 +++++++++ 4 files changed, 283 insertions(+), 210 deletions(-) create mode 100644 src/utils_lua.c create mode 100644 src/utils_lua.h diff --git a/src/Makefile.am b/src/Makefile.am index de92ff41..91a233ad 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -536,7 +536,8 @@ endif if BUILD_PLUGIN_LUA pkglib_LTLIBRARIES += lua.la -lua_la_SOURCES = lua.c +lua_la_SOURCES = lua.c \ + utils_lua.c utils_lua.h lua_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBLUA_CPPFLAGS) lua_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBLUA_LDFLAGS) lua_la_LIBADD = $(BUILD_WITH_LIBLUA_LIBS) diff --git a/src/lua.c b/src/lua.c index d13acc82..b4f30ee1 100644 --- a/src/lua.c +++ b/src/lua.c @@ -36,6 +36,7 @@ #include #include #include +#include "utils_lua.h" #if defined(COLLECT_DEBUG) && COLLECT_DEBUG && defined(__GNUC__) && __GNUC__ # undef sprintf @@ -111,213 +112,6 @@ static int clua_read (user_data_t *ud) /* {{{ */ return (1); \ } while (0) -static int ltoc_value (lua_State *l, /* {{{ */ - int ds_type, value_t *ret_value) -{ - if (!lua_isnumber (l, /* stack pos = */ -1)) - return (-1); - - if (ds_type == DS_TYPE_GAUGE) - ret_value->gauge = (gauge_t) lua_tonumber (l, /* stack pos = */ -1); - else if (ds_type == DS_TYPE_DERIVE) - ret_value->derive = (derive_t) lua_tointeger (l, /* stack pos = */ -1); - else if (ds_type == DS_TYPE_COUNTER) - ret_value->counter = (counter_t) lua_tointeger (l, /* stack pos = */ -1); - else if (ds_type == DS_TYPE_ABSOLUTE) - ret_value->absolute = (absolute_t) lua_tointeger (l, /* stack pos = */ -1); - else - assert (23 == 42); - - return (0); -} /* }}} int ltoc_value */ - -static int ltoc_values (lua_State *l, /* {{{ */ - const data_set_t *ds, - value_t *ret_values) -{ - size_t i; - int status = 0; - - if (!lua_istable (l, -1)) - { - lua_pop (l, /* nelem = */ 1); - return (-1); - } - - /* Push initial key */ - lua_pushnil (l); - for (i = 0; i < ((size_t) ds->ds_num); i++) - { - /* Pops old key and pushed new key and value. */ - status = lua_next (l, -2); - if (status == 0) /* no more elements */ - break; - - status = ltoc_value (l, ds->ds[i].type, ret_values + i); - if (status != 0) - { - DEBUG ("ltoc_value failed."); - break; - } - - /* Pop the value */ - lua_pop (l, /* nelems = */ 1); - } - /* Pop the key and the table itself */ - lua_pop (l, /* nelems = */ 2); - - return (status); -} /* }}} int ltoc_values */ - -static int ltoc_table_values (lua_State *l, /* {{{ */ - const data_set_t *ds, value_list_t *vl) -{ - int status; - - lua_pushstring (l, "values"); - lua_gettable (l, -2); - - if (!lua_istable (l, -1)) - { - NOTICE ("lua plugin: ltoc_table_values: The \"values\" member is not a table."); - lua_pop (l, /* nelem = */ 1); - return (-1); - } - - vl->values_len = ds->ds_num; - vl->values = calloc ((size_t) vl->values_len, sizeof (*vl->values)); - if (vl->values == NULL) - { - ERROR ("lua plugin: calloc failed."); - vl->values_len = 0; - lua_pop (l, /* nelem = */ 1); - return (-1); - } - - status = ltoc_values (l, ds, vl->values); - - lua_pop (l, /* nelem = */ 1); - - if (status != 0) - { - vl->values_len = 0; - sfree (vl->values); - } - - return (status); -} /* }}} int ltoc_table_values */ - -static int ltoc_string_buffer (lua_State *l, /* {{{ */ - char *buffer, size_t buffer_size, - _Bool consume) -{ - const char *str; - - str = lua_tostring (l, /* stack pos = */ -1); - if (str != NULL) - sstrncpy (buffer, str, buffer_size); - - if (consume) - lua_pop (l, /* nelem = */ 1); - - return ((str != NULL) ? 0 : -1); -} /* }}} int ltoc_string_buffer */ - -static int ltoc_table_string_buffer (lua_State *l, /* {{{ */ - const char *table_key, - char *buffer, size_t buffer_size) -{ - lua_pushstring (l, table_key); - lua_gettable (l, -2); - - if (!lua_isstring (l, /* stack pos = */ -1)) - { - lua_pop (l, /* nelem = */ 1); - return (-1); - } - - return (ltoc_string_buffer (l, buffer, buffer_size, /* consume = */ 1)); -} /* }}} int ltoc_table_string_buffer */ - -static int ltoc_table_cdtime (lua_State *l, /* {{{ */ - const char *table_key, cdtime_t *ret_time) -{ - double d; - - lua_pushstring (l, table_key); - lua_gettable (l, -2); - - if (!lua_isnumber (l, /* stack pos = */ -1)) - { - lua_pop (l, /* nelem = */ 1); - return (-1); - } - - d = (double) lua_tonumber (l, -1); - lua_pop (l, /* nelem = */ 1); - - *ret_time = DOUBLE_TO_CDTIME_T (d); - return (0); -} /* }}} int ltoc_table_cdtime */ - -static value_list_t *ltoc_value_list (lua_State *l) /* {{{ */ -{ - const data_set_t *ds; - value_list_t *vl; - int status; - - vl = malloc (sizeof (*vl)); - if (vl == NULL) - return (NULL); - memset (vl, 0, sizeof (*vl)); - vl->values = NULL; - vl->meta = NULL; - -#define COPY_FIELD(field,def) do { \ - status = ltoc_table_string_buffer (l, #field, vl->field, sizeof (vl->field)); \ - if (status != 0) { \ - if ((def) == NULL) \ - return (NULL); \ - else \ - sstrncpy (vl->field, (def), sizeof (vl->field)); \ - } \ -} while (0) - - COPY_FIELD (host, hostname_g); - COPY_FIELD (plugin, NULL); - COPY_FIELD (plugin_instance, ""); - COPY_FIELD (type, NULL); - COPY_FIELD (type_instance, ""); - -#undef COPY_FIELD - - ds = plugin_get_ds (vl->type); - if (ds == NULL) - { - INFO ("lua plugin: Unable to lookup type \"%s\".", vl->type); - sfree (vl); - return (NULL); - } - - status = ltoc_table_cdtime (l, "time", &vl->time); - if (status != 0) - vl->time = cdtime (); - - status = ltoc_table_cdtime (l, "interval", &vl->interval); - if (status != 0) - vl->interval = interval_g; - - status = ltoc_table_values (l, ds, vl); - if (status != 0) - { - WARNING ("lua plugin: ltoc_table_values failed."); - sfree (vl); - return (NULL); - } - - return (vl); -} /* }}} value_list_t *ltoc_value_list */ - /* * Exported functions */ @@ -382,11 +176,11 @@ static int lua_cb_dispatch_values (lua_State *l) /* {{{ */ if (!lua_istable (l, 1)) { WARNING ("lua plugin: The first argument to collectd_dispatch_values() " - "must be a table."); + "must be a \"value list\" (i.e. a table)."); RETURN_LUA (l, -1); } - vl = ltoc_value_list (l); + vl = luaC_tovaluelist (l, /* idx = */ -1); if (vl == NULL) { WARNING ("lua plugin: ltoc_value_list failed."); diff --git a/src/utils_lua.c b/src/utils_lua.c new file mode 100644 index 00000000..c01e5949 --- /dev/null +++ b/src/utils_lua.c @@ -0,0 +1,239 @@ +/** + * collectd - src/utils_lua.c + * Copyright (C) 2010 Florian Forster + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; only version 2.1 of the License is + * applicable. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Florian Forster + **/ + +#include "utils_lua.h" +#include "common.h" + +static int ltoc_values (lua_State *l, /* {{{ */ + const data_set_t *ds, + value_t *ret_values) +{ + size_t i; + int status = 0; + + if (!lua_istable (l, -1)) + return (-1); + + /* Push initial key */ + lua_pushnil (l); + for (i = 0; i < ((size_t) ds->ds_num); i++) + { + /* Pops old key and pushed new key and value. */ + status = lua_next (l, -2); + if (status == 0) /* no more elements */ + break; + + ret_values[i] = luaC_tovalue (l, /* idx = */ -1, ds->ds[i].type); + + /* Pop the value */ + lua_pop (l, /* nelems = */ 1); + } + /* Pop the key */ + lua_pop (l, /* nelems = */ 1); + + return (status); +} /* }}} int ltoc_values */ + +static int ltoc_table_values (lua_State *l, int idx, /* {{{ */ + const data_set_t *ds, value_list_t *vl) +{ + int status; + + /* We're only called from "luaC_tovaluelist", which ensures that "idx" is an + * absolute index (i.e. a positive number) */ + assert (idx > 0); + + lua_pushstring (l, "values"); + lua_gettable (l, idx); + + if (!lua_istable (l, -1)) + { + NOTICE ("lua plugin: ltoc_table_values: The \"values\" member is not a table."); + lua_pop (l, /* nelem = */ 1); + return (-1); + } + + vl->values_len = ds->ds_num; + vl->values = calloc ((size_t) vl->values_len, sizeof (*vl->values)); + if (vl->values == NULL) + { + ERROR ("lua plugin: calloc failed."); + vl->values_len = 0; + lua_pop (l, /* nelem = */ 1); + return (-1); + } + + status = ltoc_values (l, ds, vl->values); + + lua_pop (l, /* nelem = */ 1); + + if (status != 0) + { + vl->values_len = 0; + sfree (vl->values); + } + + return (status); +} /* }}} int ltoc_table_values */ + +/* + * Public functions + */ +cdtime_t luaC_tocdtime (lua_State *l, int idx) /* {{{ */ +{ + double d; + + if (!lua_isnumber (l, /* stack pos = */ idx)) + return (0); + + d = (double) lua_tonumber (l, idx); + + return (DOUBLE_TO_CDTIME_T (d)); +} /* }}} int ltoc_table_cdtime */ + +int luaC_tostringbuffer (lua_State *l, int idx, /* {{{ */ + char *buffer, size_t buffer_size) +{ + const char *str; + + str = lua_tostring (l, idx); + if (str == NULL) + return (-1); + + sstrncpy (buffer, str, buffer_size); + return (0); +} /* }}} int luaC_tostringbuffer */ + +value_t luaC_tovalue (lua_State *l, int idx, int ds_type) /* {{{ */ +{ + value_t v; + + memset (&v, 0, sizeof (v)); + + if (!lua_isnumber (l, idx)) + return (v); + + if (ds_type == DS_TYPE_GAUGE) + v.gauge = (gauge_t) lua_tonumber (l, /* stack pos = */ -1); + else if (ds_type == DS_TYPE_DERIVE) + v.derive = (derive_t) lua_tointeger (l, /* stack pos = */ -1); + else if (ds_type == DS_TYPE_COUNTER) + v.counter = (counter_t) lua_tointeger (l, /* stack pos = */ -1); + else if (ds_type == DS_TYPE_ABSOLUTE) + v.absolute = (absolute_t) lua_tointeger (l, /* stack pos = */ -1); + + return (v); +} /* }}} value_t luaC_tovalue */ + +value_list_t *luaC_tovaluelist (lua_State *l, int idx) /* {{{ */ +{ + const data_set_t *ds; + value_list_t *vl; + int status; +#if COLLECT_DEBUG + int stack_top_before = lua_gettop (l); +#endif + + /* Convert relative indexes to absolute indexes, so it doesn't change when we + * push / pop stuff. */ + if (idx < 1) + idx += lua_gettop (l) + 1; + + /* Check that idx is in the valid range */ + if ((idx < 1) || (idx > lua_gettop (l))) + return (NULL); + + vl = malloc (sizeof (*vl)); + if (vl == NULL) + return (NULL); + memset (vl, 0, sizeof (*vl)); + vl->values = NULL; + vl->meta = NULL; + + /* Push initial key */ + lua_pushnil (l); + while (lua_next (l, idx) != 0) + { + const char *key = lua_tostring (l, /* stack pos = */ -2); + + if (key == NULL) + { + DEBUG ("luaC_tovaluelist: Ignoring non-string key."); + } + else if (strcasecmp ("host", key) == 0) + luaC_tostringbuffer (l, /* idx = */ -1, + vl->host, sizeof (vl->host)); + else if (strcasecmp ("plugin", key) == 0) + luaC_tostringbuffer (l, /* idx = */ -1, + vl->plugin, sizeof (vl->plugin)); + else if (strcasecmp ("plugin_instance", key) == 0) + luaC_tostringbuffer (l, /* idx = */ -1, + vl->plugin_instance, sizeof (vl->plugin_instance)); + else if (strcasecmp ("type", key) == 0) + luaC_tostringbuffer (l, /* idx = */ -1, + vl->type, sizeof (vl->type)); + else if (strcasecmp ("type_instance", key) == 0) + luaC_tostringbuffer (l, /* idx = */ -1, + vl->type_instance, sizeof (vl->type_instance)); + else if (strcasecmp ("time", key) == 0) + vl->time = luaC_tocdtime (l, -1); + else if (strcasecmp ("interval", key) == 0) + vl->interval = luaC_tocdtime (l, -1); + else if (strcasecmp ("values", key) == 0) + { + /* This key is not handled here, because we have to assure "type" is read + * first. */ + } + else + { + DEBUG ("luaC_tovaluelist: Ignoring unknown key \"%s\".", key); + } + + /* Pop the value */ + lua_pop (l, 1); + } + /* Pop the key */ + lua_pop (l, 1); + + ds = plugin_get_ds (vl->type); + if (ds == NULL) + { + INFO ("lua plugin: Unable to lookup type \"%s\".", vl->type); + sfree (vl); + return (NULL); + } + + status = ltoc_table_values (l, idx, ds, vl); + if (status != 0) + { + WARNING ("lua plugin: ltoc_table_values failed."); + sfree (vl); + return (NULL); + } + +#if COLLECT_DEBUG + assert (stack_top_before == lua_gettop (l)); +#endif + return (vl); +} /* }}} value_list_t *luaC_tovaluelist */ + +/* vim: set sw=2 sts=2 et fdm=marker : */ diff --git a/src/utils_lua.h b/src/utils_lua.h new file mode 100644 index 00000000..bb97d858 --- /dev/null +++ b/src/utils_lua.h @@ -0,0 +1,39 @@ +/** + * collectd - src/utils_lua.h + * Copyright (C) 2010 Florian Forster + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; only version 2.1 of the License is + * applicable. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Florian Forster + **/ +#ifndef UTILS_LUA_H +#define UTILS_LUA_H 1 + +#include "collectd.h" +#include "plugin.h" + +#include + +/* + * access functions (stack -> C) + */ +cdtime_t luaC_tocdtime (lua_State *l, int idx); +int luaC_tostringbuffer (lua_State *l, int idx, char *buffer, size_t buffer_size); +value_t luaC_tovalue (lua_State *l, int idx, int ds_type); +value_list_t *luaC_tovaluelist (lua_State *l, int idx); + +#endif /* UTILS_LUA_H */ +/* vim: set sw=2 sts=2 et fdm=marker : */ -- 2.11.0