From: Aki Tuomi Date: Thu, 11 Oct 2018 16:10:17 +0000 (+0300) Subject: lib-lua: Add event interface X-Git-Tag: 2.3.9~1170 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e921e4121461805ff2d1a23d29178fc7e70abc9b;p=thirdparty%2Fdovecot%2Fcore.git lib-lua: Add event interface --- diff --git a/src/lib-lua/dlua-dovecot.c b/src/lib-lua/dlua-dovecot.c index 879f2c5d84..ac5d7e0f5e 100644 --- a/src/lib-lua/dlua-dovecot.c +++ b/src/lib-lua/dlua-dovecot.c @@ -1,9 +1,472 @@ /* Copyright (c) 2017-2018 Dovecot authors, see the included COPYING file */ #include "lib.h" +#include "ioloop.h" #include "dlua-script-private.h" #define LUA_SCRIPT_DOVECOT "dovecot" +#define DLUA_EVENT_PASSTHROUGH "struct event_passthrough" +#define DLUA_EVENT "struct event" + +static struct event_passthrough * +dlua_check_event_passthrough(struct dlua_script *script, int arg) +{ + if (!lua_istable(script->L, arg)) { + (void)luaL_error(script->L, "Bad argument #%d, expected %s got %s", + arg, DLUA_EVENT, + lua_typename(script->L, lua_type(script->L, arg))); + } + lua_pushliteral(script->L, "item"); + lua_rawget(script->L, arg); + void *bp = (void*)lua_touserdata(script->L, -1); + lua_pop(script->L, 1); + return (struct event_passthrough*)bp; +} + +static void dlua_push_event_passthrough(struct dlua_script *script, + struct event_passthrough *event) +{ + luaL_checkstack(script->L, 3, "out of memory"); + lua_createtable(script->L, 0, 1); + luaL_setmetatable(script->L, DLUA_EVENT_PASSTHROUGH); + + lua_pushlightuserdata(script->L, event); + lua_setfield(script->L, -2, "item"); +} + +static int dlua_event_pt_append_log_prefix(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event_passthrough *event = dlua_check_event_passthrough(script, 1); + const char *prefix = luaL_checkstring(script->L, 2); + + event->append_log_prefix(prefix); + + lua_pushvalue(script->L, 1); + + return 1; +} + +static int dlua_event_pt_replace_log_prefix(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event_passthrough *event = dlua_check_event_passthrough(script, 1); + const char *prefix = luaL_checkstring(script->L, 2); + + event->replace_log_prefix(prefix); + + lua_pushvalue(script->L, 1); + + return 1; +} + +static int dlua_event_pt_set_name(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event_passthrough *event = dlua_check_event_passthrough(script, 1); + const char *name = luaL_checkstring(script->L, 2); + + event->set_name(name); + + lua_pushvalue(script->L, 1); + + return 1; +} + + +static int dlua_event_pt_set_always_log_source(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event_passthrough *event = dlua_check_event_passthrough(script, 1); + + event->set_always_log_source(); + + lua_pushvalue(script->L, 1); + + return 1; +} + +static int dlua_event_pt_add_str(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event_passthrough *event = dlua_check_event_passthrough(script, 1); + const char *name = luaL_checkstring(script->L, 2); + const char *value = luaL_checkstring(script->L, 3); + + event->add_str(name, value); + + lua_pushvalue(script->L, 1); + + return 1; +} + +static int dlua_event_pt_add_int(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event_passthrough *event = dlua_check_event_passthrough(script, 1); + const char *name = luaL_checkstring(script->L, 2); + lua_Integer value = luaL_checkinteger(script->L, 3); + + event->add_int(name, value); + + lua_pushvalue(script->L, 1); + + return 1; +} + +static int dlua_event_pt_add_timeval(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event_passthrough *event = dlua_check_event_passthrough(script, 1); + const char *name = luaL_checkstring(script->L, 2); + /* this is time in seconds */ + lua_Integer value = luaL_checkinteger(script->L, 3); + struct timeval tv = { + .tv_sec = value, + }; + + event->add_timeval(name, &tv); + + lua_pushvalue(script->L, 1); + + return 1; +} + +static int dlua_event_pt_inc_int(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event_passthrough *event = dlua_check_event_passthrough(script, 1); + const char *name = luaL_checkstring(script->L, 2); + lua_Integer value = luaL_checkinteger(script->L, 3); + + event->inc_int(name, value); + + lua_pushvalue(script->L, 1); + + return 1; +} + +static int dlua_event_pt_log_debug(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event_passthrough *event = dlua_check_event_passthrough(script, 1); + const char *str = luaL_checkstring(script->L, 2); + + e_debug(event->event(), "%s", str); + + lua_pushvalue(script->L, 1); + + return 1; +} + +static int dlua_event_pt_log_info(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event_passthrough *event = dlua_check_event_passthrough(script, 1); + const char *str = luaL_checkstring(script->L, 2); + + e_info(event->event(), "%s", str); + + lua_pushvalue(script->L, 1); + + return 1; +} + +static int dlua_event_pt_log_warning(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event_passthrough *event = dlua_check_event_passthrough(script, 1); + const char *str = luaL_checkstring(script->L, 2); + + e_warning(event->event(), "%s", str); + + lua_pushvalue(script->L, 1); + + return 1; +} + +static int dlua_event_pt_log_error(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event_passthrough *event = dlua_check_event_passthrough(script, 1); + const char *str = luaL_checkstring(script->L, 2); + + e_error(event->event(), "%s", str); + + lua_pushvalue(script->L, 1); + + return 1; +} + +static const luaL_Reg event_passthrough_methods[] ={ + { "append_log_prefix", dlua_event_pt_append_log_prefix }, + { "replace_log_prefix", dlua_event_pt_replace_log_prefix }, + { "set_always_log_source", dlua_event_pt_set_always_log_source }, + { "set_name", dlua_event_pt_set_name }, + { "add_str", dlua_event_pt_add_str }, + { "add_int", dlua_event_pt_add_int }, + { "add_timeval", dlua_event_pt_add_timeval }, + { "inc_int", dlua_event_pt_inc_int }, + { "log_debug", dlua_event_pt_log_debug }, + { "log_info", dlua_event_pt_log_info }, + { "log_warning", dlua_event_pt_log_warning }, + { "log_error", dlua_event_pt_log_error }, + { NULL, NULL } +}; + +struct event * +dlua_check_event(struct dlua_script *script, int arg) +{ + if (!lua_istable(script->L, arg)) { + (void)luaL_error(script->L, "Bad argument #%d, expected %s got %s", + arg, DLUA_EVENT, + lua_typename(script->L, lua_type(script->L, arg))); + } + lua_pushliteral(script->L, "item"); + lua_rawget(script->L, arg); + void *bp = (void*)lua_touserdata(script->L, -1); + lua_pop(script->L, 1); + return (struct event*)bp; +} + +void dlua_push_event(struct dlua_script *script, struct event *event) +{ + luaL_checkstack(script->L, 3, "out of memory"); + lua_createtable(script->L, 0, 1); + luaL_setmetatable(script->L, DLUA_EVENT); + + lua_pushlightuserdata(script->L, event); + lua_setfield(script->L, -2, "item"); +} + +static int dlua_event_append_log_prefix(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event *event = dlua_check_event(script, 1); + const char *prefix = luaL_checkstring(script->L, 2); + + event_set_append_log_prefix(event, prefix); + + lua_pushvalue(script->L, 1); + + return 1; +} + +static int dlua_event_replace_log_prefix(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event *event = dlua_check_event(script, 1); + const char *prefix = luaL_checkstring(script->L, 2); + + event_replace_log_prefix(event, prefix); + + lua_pushvalue(script->L, 1); + + return 1; +} + +static int dlua_event_set_name(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event *event = dlua_check_event(script, 1); + const char *name = luaL_checkstring(script->L, 2); + + event_set_name(event, name); + + lua_pushvalue(script->L, 1); + + return 1; +} + + +static int dlua_event_set_always_log_source(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event *event = dlua_check_event(script, 1); + + event_set_always_log_source(event); + + lua_pushvalue(script->L, 1); + + return 1; +} + +static int dlua_event_add_str(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event *event = dlua_check_event(script, 1); + const char *name = luaL_checkstring(script->L, 2); + const char *value = luaL_checkstring(script->L, 3); + + event_add_str(event, name, value); + + lua_pushvalue(script->L, 1); + + return 1; +} + +static int dlua_event_add_int(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event *event = dlua_check_event(script, 1); + const char *name = luaL_checkstring(script->L, 2); + lua_Integer value = luaL_checkinteger(script->L, 3); + + event_add_int(event, name, value); + + lua_pushvalue(script->L, 1); + + return 1; +} + +static int dlua_event_add_timeval(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event *event = dlua_check_event(script, 1); + const char *name = luaL_checkstring(script->L, 2); + /* this is time in seconds */ + lua_Integer value = luaL_checkinteger(script->L, 3); + struct timeval tv = { + .tv_sec = value, + }; + + event_add_timeval(event, name, &tv); + + lua_pushvalue(script->L, 1); + + return 1; +} + +static int dlua_event_inc_int(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event *event = dlua_check_event(script, 1); + const char *name = luaL_checkstring(script->L, 2); + lua_Integer value = luaL_checkinteger(script->L, 3); + + event_inc_int(event, name, value); + + lua_pushvalue(script->L, 1); + + return 1; +} + +static int dlua_event_log_debug(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event *event = dlua_check_event(script, 1); + const char *str = luaL_checkstring(script->L, 2); + + e_debug(event, "%s", str); + + lua_pushvalue(script->L, 1); + + return 1; +} + +static int dlua_event_log_info(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event *event = dlua_check_event(script, 1); + const char *str = luaL_checkstring(script->L, 2); + + e_info(event, "%s", str); + + lua_pushvalue(script->L, 1); + + return 1; +} + +static int dlua_event_log_warning(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event *event = dlua_check_event(script, 1); + const char *str = luaL_checkstring(script->L, 2); + + e_warning(event, "%s", str); + + lua_pushvalue(script->L, 1); + + return 1; +} + +static int dlua_event_log_error(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event *event = dlua_check_event(script, 1); + const char *str = luaL_checkstring(script->L, 2); + + e_error(event, "%s", str); + + lua_pushvalue(script->L, 1); + + return 1; +} + +static int dlua_event_passthrough_event(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event *event = dlua_check_event(script, 1); + struct event_passthrough *e = event_create_passthrough(event); + dlua_push_event_passthrough(script, e); + + return 1; +} + +static int dlua_event_gc(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + struct event *event = dlua_check_event(script, 1); + event_unref(&event); + return 0; +} + +static int dlua_event_new(lua_State *L) +{ + struct dlua_script *script = dlua_script_from_state(L); + lua_Debug ar; + struct event *event, *parent = script->event; + if (lua_gettop(script->L) == 1) + parent = dlua_check_event(script, 1); + event = event_create(parent); + lua_getstack(script->L, 1, &ar); + lua_getinfo(script->L, "Sl", &ar); + event_set_source(event, ar.source, ar.currentline, TRUE); + dlua_push_event(script, event); + return 1; +} + +static const luaL_Reg event_methods[] ={ + { "append_log_prefix", dlua_event_append_log_prefix }, + { "replace_log_prefix", dlua_event_replace_log_prefix }, + { "set_always_log_source", dlua_event_set_always_log_source }, + { "set_name", dlua_event_set_name }, + { "add_str", dlua_event_add_str }, + { "add_int", dlua_event_add_int }, + { "add_timeval", dlua_event_add_timeval }, + { "inc_int", dlua_event_inc_int }, + { "log_debug", dlua_event_log_debug }, + { "log_info", dlua_event_log_info }, + { "log_warning", dlua_event_log_warning }, + { "log_error", dlua_event_log_error }, + { "passthrough_event", dlua_event_passthrough_event }, + { "__gc", dlua_event_gc }, + { NULL, NULL } +}; + +static void dlua_event_register(struct dlua_script *script){ + luaL_newmetatable(script->L, DLUA_EVENT_PASSTHROUGH); + lua_pushvalue(script->L, -1); + lua_setfield(script->L, -2, "__index"); + luaL_setfuncs(script->L, event_passthrough_methods, 0); + lua_pop(script->L, 1); + + luaL_newmetatable(script->L, DLUA_EVENT); + lua_pushvalue(script->L, -1); + lua_setfield(script->L, -2, "__index"); + luaL_setfuncs(script->L, event_methods, 0); + lua_pop(script->L, 1); +} static int dlua_i_debug(lua_State *L) { @@ -42,6 +505,7 @@ static luaL_Reg lua_dovecot_methods[] = { { "i_info", dlua_i_info }, { "i_warning", dlua_i_warning }, { "i_error", dlua_i_error }, + { "event", dlua_event_new }, { NULL, NULL } }; @@ -52,6 +516,8 @@ void dlua_getdovecot(struct dlua_script *script) void dlua_dovecot_register(struct dlua_script *script) { + dlua_event_register(script); + /* Create table for holding values */ lua_newtable(script->L); diff --git a/src/lib-lua/dlua-script.h b/src/lib-lua/dlua-script.h index e5cabece38..f5a15a8338 100644 --- a/src/lib-lua/dlua-script.h +++ b/src/lib-lua/dlua-script.h @@ -26,4 +26,10 @@ void dlua_script_unref(struct dlua_script **_script); /* see if particular function is registered */ bool dlua_script_has_function(struct dlua_script *script, const char *fn); +/* push event to top of stack */ +void dlua_push_event(struct dlua_script *script, struct event *event); + +/* get event from given stack position */ +struct event *dlua_check_event(struct dlua_script *script, int arg); + #endif