X-Git-Url: https://git.octo.it/?p=collectd.git;a=blobdiff_plain;f=src%2Flua.c;h=3f48a55dee5e122e042b38e550d2e26434f828d6;hp=2bd56a160cc2a9d098ba99397589f9524d077bfa;hb=54619dc85fd308b21ed09a0271e5c7383c7921b9;hpb=96b920e6b7bf70560eb95c911202afbeaab2b965 diff --git a/src/lua.c b/src/lua.c index 2bd56a16..3f48a55d 100644 --- a/src/lua.c +++ b/src/lua.c @@ -28,36 +28,29 @@ * Ruben Kerkhof **/ -/* defines a macro using "sprintf". Although not used here, - * GCC will complain about the macro definition. */ -#define DONT_POISON_SPRINTF_YET - -#include "common.h" -#include "plugin.h" #include "collectd.h" +#include "plugin.h" +#include "utils/common/common.h" +#include "utils_lua.h" /* Include the Lua API header files. */ #include #include #include -#include "utils_lua.h" #include -#if COLLECT_DEBUG && __GNUC__ -#undef sprintf -#pragma GCC poison sprintf -#endif +#define PLUGIN_READ 1 +#define PLUGIN_WRITE 2 typedef struct lua_script_s { - char *script_path; lua_State *lua_state; struct lua_script_s *next; } lua_script_t; typedef struct { lua_State *lua_state; - const char *lua_function_name; + char *lua_function_name; pthread_mutex_t lock; int callback_id; } clua_callback_data_t; @@ -79,29 +72,25 @@ static int clua_load_callback(lua_State *L, int callback_ref) /* {{{ */ if (!lua_isfunction(L, -1)) { lua_pop(L, 1); - return (-1); + return -1; } - return (0); + return 0; } /* }}} int clua_load_callback */ /* Store the threads in a global variable so they are not cleaned up by the * garbage collector. */ static int clua_store_thread(lua_State *L, int idx) /* {{{ */ { - if (idx < 0) - idx += lua_gettop(L) + 1; + if (!lua_isthread(L, idx)) { + return -1; + } /* Copy the thread pointer */ - lua_pushvalue(L, idx); /* +1 = 3 */ - if (!lua_isthread(L, -1)) { - lua_pop(L, 3); /* -3 = 0 */ - return (-1); - } + lua_pushvalue(L, idx); luaL_ref(L, LUA_REGISTRYINDEX); - lua_pop(L, 1); /* -1 = 0 */ - return (0); + return 0; } /* }}} int clua_store_thread */ static int clua_read(user_data_t *ud) /* {{{ */ @@ -117,7 +106,7 @@ static int clua_read(user_data_t *ud) /* {{{ */ ERROR("Lua plugin: Unable to load callback \"%s\" (id %i).", cb->lua_function_name, cb->callback_id); pthread_mutex_unlock(&cb->lock); - return (-1); + return -1; } /* +1 = 1 */ @@ -131,7 +120,7 @@ static int clua_read(user_data_t *ud) /* {{{ */ ERROR("Lua plugin: Calling a read callback failed: %s", errmsg); lua_pop(L, 1); pthread_mutex_unlock(&cb->lock); - return (-1); + return -1; } if (!lua_isnumber(L, -1)) { @@ -147,7 +136,7 @@ static int clua_read(user_data_t *ud) /* {{{ */ lua_pop(L, 1); /* -1 = 0 */ pthread_mutex_unlock(&cb->lock); - return (status); + return status; } /* }}} int clua_read */ static int clua_write(const data_set_t *ds, const value_list_t *vl, /* {{{ */ @@ -163,7 +152,7 @@ static int clua_write(const data_set_t *ds, const value_list_t *vl, /* {{{ */ ERROR("Lua plugin: Unable to load callback \"%s\" (id %i).", cb->lua_function_name, cb->callback_id); pthread_mutex_unlock(&cb->lock); - return (-1); + return -1; } /* +1 = 1 */ @@ -172,7 +161,7 @@ static int clua_write(const data_set_t *ds, const value_list_t *vl, /* {{{ */ lua_pop(L, 1); /* -1 = 0 */ pthread_mutex_unlock(&cb->lock); ERROR("Lua plugin: luaC_pushvaluelist failed."); - return (-1); + return -1; } /* +1 = 2 */ @@ -186,7 +175,7 @@ static int clua_write(const data_set_t *ds, const value_list_t *vl, /* {{{ */ ERROR("Lua plugin: Calling the write callback failed:\n%s", errmsg); lua_pop(L, 1); /* -1 = 0 */ pthread_mutex_unlock(&cb->lock); - return (-1); + return -1; } if (!lua_isnumber(L, -1)) { @@ -200,7 +189,7 @@ static int clua_write(const data_set_t *ds, const value_list_t *vl, /* {{{ */ lua_pop(L, 1); /* -1 = 0 */ pthread_mutex_unlock(&cb->lock); - return (status); + return status; } /* }}} int clua_write */ /* @@ -272,60 +261,46 @@ static int lua_cb_dispatch_values(lua_State *L) /* {{{ */ return 0; } /* }}} lua_cb_dispatch_values */ -static int lua_cb_register_read(lua_State *L) /* {{{ */ +static void lua_cb_free(void *data) { + clua_callback_data_t *cb = data; + free(cb->lua_function_name); + pthread_mutex_destroy(&cb->lock); + free(cb); +} + +static int lua_cb_register_generic(lua_State *L, int type) /* {{{ */ { int nargs = lua_gettop(L); if (nargs != 1) return luaL_error(L, "Invalid number of arguments (%d != 1)", nargs); - luaL_checktype(L, 1, LUA_TFUNCTION); - - char function_name[DATA_MAX_NAME_LEN]; - ssnprintf(function_name, sizeof(function_name), "lua/%s", lua_tostring(L, 1)); - - int callback_id = clua_store_callback(L, 1); - if (callback_id < 0) - return luaL_error(L, "%s", "Storing callback function failed"); - - lua_State *thread = lua_newthread(L); - if (thread == NULL) - return luaL_error(L, "%s", "lua_newthread failed"); - clua_store_thread(L, -1); - lua_pop(L, 1); - - clua_callback_data_t *cb = calloc(1, sizeof(*cb)); - if (cb == NULL) - return luaL_error(L, "%s", "calloc failed"); - - cb->lua_state = thread; - cb->callback_id = callback_id; - cb->lua_function_name = strdup(function_name); - pthread_mutex_init(&cb->lock, NULL); - - int status = plugin_register_complex_read(/* group = */ "lua", - /* name = */ function_name, - /* callback = */ clua_read, - /* interval = */ 0, &(user_data_t){ - .data = cb, - }); - - if (status != 0) - return luaL_error(L, "%s", "plugin_register_complex_read failed"); - return 0; -} /* }}} int lua_cb_register_read */ - -static int lua_cb_register_write(lua_State *L) /* {{{ */ -{ - int nargs = lua_gettop(L); + char subname[DATA_MAX_NAME_LEN]; + if (!lua_isfunction(L, 1) && lua_isstring(L, 1)) { + const char *fname = lua_tostring(L, 1); + ssnprintf(subname, sizeof(subname), "%s()", fname); - if (nargs != 1) - return luaL_error(L, "Invalid number of arguments (%d != 1)", nargs); + lua_getglobal(L, fname); // Push function into stack + lua_remove(L, 1); // Remove string from stack + if (!lua_isfunction(L, -1)) { + return luaL_error(L, "Unable to find function '%s'", fname); + } + } else { + lua_getfield(L, LUA_REGISTRYINDEX, "collectd:callback_num"); + int tmp = lua_tointeger(L, -1); + ssnprintf(subname, sizeof(subname), "callback_%d", tmp); + lua_pop(L, 1); // Remove old value from stack + lua_pushinteger(L, tmp + 1); + lua_setfield(L, LUA_REGISTRYINDEX, "collectd:callback_num"); // pops value + } luaL_checktype(L, 1, LUA_TFUNCTION); - char function_name[DATA_MAX_NAME_LEN] = ""; - ssnprintf(function_name, sizeof(function_name), "lua/%s", lua_tostring(L, 1)); + lua_getfield(L, LUA_REGISTRYINDEX, "collectd:script_path"); + char function_name[DATA_MAX_NAME_LEN]; + ssnprintf(function_name, sizeof(function_name), "lua/%s/%s", + lua_tostring(L, -1), subname); + lua_pop(L, 1); int callback_id = clua_store_callback(L, 1); if (callback_id < 0) @@ -346,16 +321,42 @@ static int lua_cb_register_write(lua_State *L) /* {{{ */ cb->lua_function_name = strdup(function_name); pthread_mutex_init(&cb->lock, NULL); - int status = - plugin_register_write(/* name = */ function_name, - /* callback = */ clua_write, &(user_data_t){ - .data = cb, - }); + if (PLUGIN_READ == type) { + int status = plugin_register_complex_read(/* group = */ "lua", + /* name = */ function_name, + /* callback = */ clua_read, + /* interval = */ 0, + &(user_data_t){ + .data = cb, + .free_func = lua_cb_free, + }); + + if (status != 0) + return luaL_error(L, "%s", "plugin_register_complex_read failed"); + return 0; + } else if (PLUGIN_WRITE == type) { + int status = plugin_register_write(/* name = */ function_name, + /* callback = */ clua_write, + &(user_data_t){ + .data = cb, + .free_func = lua_cb_free, + }); + + if (status != 0) + return luaL_error(L, "%s", "plugin_register_write failed"); + return 0; + } else { + return luaL_error(L, "%s", "lua_cb_register_generic unsupported type"); + } +} /* }}} int lua_cb_register_generic */ + +static int lua_cb_register_read(lua_State *L) { + return lua_cb_register_generic(L, PLUGIN_READ); +} - if (status != 0) - return luaL_error(L, "%s", "plugin_register_write failed"); - return 0; -} /* }}} int lua_cb_register_write */ +static int lua_cb_register_write(lua_State *L) { + return lua_cb_register_generic(L, PLUGIN_WRITE); +} static const luaL_Reg collectdlib[] = { {"log_debug", lua_cb_log_debug}, @@ -390,7 +391,6 @@ static void lua_script_free(lua_script_t *script) /* {{{ */ script->lua_state = NULL; } - sfree(script->script_path); sfree(script); lua_script_free(next); @@ -404,7 +404,7 @@ static int lua_script_init(lua_script_t *script) /* {{{ */ script->lua_state = luaL_newstate(); if (script->lua_state == NULL) { ERROR("Lua plugin: luaL_newstate() failed."); - return (-1); + return -1; } /* Open up all the standard Lua libraries. */ @@ -437,7 +437,7 @@ static int lua_script_init(lua_script_t *script) /* {{{ */ lua_pop(script->lua_state, 1); } - return (0); + return 0; } /* }}} int lua_script_init */ static int lua_script_load(const char *script_path) /* {{{ */ @@ -445,31 +445,29 @@ static int lua_script_load(const char *script_path) /* {{{ */ lua_script_t *script = malloc(sizeof(*script)); if (script == NULL) { ERROR("Lua plugin: malloc failed."); - return (-1); + return -1; } int status = lua_script_init(script); if (status != 0) { lua_script_free(script); - return (status); - } - - script->script_path = strdup(script_path); - if (script->script_path == NULL) { - ERROR("Lua plugin: strdup failed."); - lua_script_free(script); - return (-1); + return status; } - status = luaL_loadfile(script->lua_state, script->script_path); + status = luaL_loadfile(script->lua_state, script_path); if (status != 0) { ERROR("Lua plugin: luaL_loadfile failed: %s", lua_tostring(script->lua_state, -1)); lua_pop(script->lua_state, 1); lua_script_free(script); - return (-1); + return -1; } + lua_pushstring(script->lua_state, script_path); + lua_setfield(script->lua_state, LUA_REGISTRYINDEX, "collectd:script_path"); + lua_pushinteger(script->lua_state, 0); + lua_setfield(script->lua_state, LUA_REGISTRYINDEX, "collectd:callback_num"); + status = lua_pcall(script->lua_state, /* nargs = */ 0, /* nresults = */ LUA_MULTRET, @@ -482,11 +480,8 @@ static int lua_script_load(const char *script_path) /* {{{ */ "In addition, no error message could be retrieved from the stack.", status); else - ERROR("Lua plugin: Executing script \"%s\" failed:\n%s", - script->script_path, errmsg); - - lua_script_free(script); - return (-1); + ERROR("Lua plugin: Executing script \"%s\" failed: %s", script_path, + errmsg); } /* Append this script to the global list of scripts. */ @@ -500,14 +495,17 @@ static int lua_script_load(const char *script_path) /* {{{ */ scripts = script; } - return (0); + if (status != 0) + return -1; + + return 0; } /* }}} int lua_script_load */ static int lua_config_base_path(const oconfig_item_t *ci) /* {{{ */ { int status = cf_util_get_string_buffer(ci, base_path, sizeof(base_path)); if (status != 0) - return (status); + return status; size_t len = strlen(base_path); while ((len > 0) && (base_path[len - 1] == '/')) { @@ -517,7 +515,7 @@ static int lua_config_base_path(const oconfig_item_t *ci) /* {{{ */ DEBUG("Lua plugin: base_path = \"%s\";", base_path); - return (0); + return 0; } /* }}} int lua_config_base_path */ static int lua_config_script(const oconfig_item_t *ci) /* {{{ */ @@ -526,7 +524,7 @@ static int lua_config_script(const oconfig_item_t *ci) /* {{{ */ int status = cf_util_get_string_buffer(ci, rel_path, sizeof(rel_path)); if (status != 0) - return (status); + return status; char abs_path[PATH_MAX]; @@ -539,7 +537,7 @@ static int lua_config_script(const oconfig_item_t *ci) /* {{{ */ status = lua_script_load(abs_path); if (status != 0) - return (status); + return status; INFO("Lua plugin: File \"%s\" loaded successfully", abs_path); @@ -576,12 +574,10 @@ static int lua_shutdown(void) /* {{{ */ { lua_script_free(scripts); - return (0); + return 0; } /* }}} int lua_shutdown */ void module_register(void) { plugin_register_complex_config("lua", lua_config); plugin_register_shutdown("lua", lua_shutdown); } - -/* vim: set sw=2 sts=2 et fdm=marker : */