]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-lua: Add event interface
authorAki Tuomi <aki.tuomi@dovecot.fi>
Thu, 11 Oct 2018 16:10:17 +0000 (19:10 +0300)
committerAki Tuomi <aki.tuomi@open-xchange.com>
Thu, 18 Oct 2018 10:52:52 +0000 (10:52 +0000)
src/lib-lua/dlua-dovecot.c
src/lib-lua/dlua-script.h

index 879f2c5d84e1473d1914da4cecc708bcca22ccb2..ac5d7e0f5e0f883f044cafc1e997e672915b7ad1 100644 (file)
@@ -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);
 
index e5cabece387c9b74c4375ab601fe14a1531c2ee5..f5a15a83385ea624b4da86d2c55b6433f5dd0f19 100644 (file)
@@ -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