From 8e28051d2e7febe9b130b58c0ecbc07420340382 Mon Sep 17 00:00:00 2001 From: Hleran Date: Wed, 5 Aug 2015 23:58:22 +0300 Subject: [PATCH 01/17] lua_plugin: metatable.__tostring also can yield and send metatable with __tostring attr; some cleanups and optimizations; --- plugins/lua/lua_plugin.c | 228 +++++++++++++++++++++++---------------- 1 file changed, 137 insertions(+), 91 deletions(-) diff --git a/plugins/lua/lua_plugin.c b/plugins/lua/lua_plugin.c index d892498d..ad011d76 100644 --- a/plugins/lua/lua_plugin.c +++ b/plugins/lua/lua_plugin.c @@ -24,6 +24,9 @@ struct uwsgi_lua { #define ULUA_MYWID (uwsgi.mywid-1) #define ULUA_WORKER_STATE ulua.state[ULUA_MYWID] +#define ULUA_LOG_HEADER "[uwsgi-lua]" + +#define ulua_log(c, ar...) uwsgi_log(ULUA_LOG_HEADER" "c"\n", ##ar) struct uwsgi_plugin lua_plugin; @@ -54,6 +57,37 @@ static struct uwsgi_option uwsgi_lua_options[] = { }; +static int ulua_metatable_tostring(lua_State *L, int obj) { + // replaces table with __tostring result, or do nothing in case of fail + + if (!(luaL_getmetafield(L, obj, "__tostring"))) { + return 0; + } + + if (!(lua_isfunction(L, -1))) { + ulua_log("__tostring is not a function", lua_tostring(L, -1)); + lua_pop(L, 1); + return 0; + } + + lua_pushvalue(L, --obj); + + if (lua_pcall(L, 1, 1, 0) != 0) { + ulua_log("%s", lua_tostring(L, -1)); + lua_pop(L, 1); + return 0; + } + + if (lua_isstring(L, -1)) { + lua_replace(L, obj); + return 1; + } + + lua_pop(L, 1); + + return 0; +} + static void ulua_check_args(lua_State *L, const char *func, int n) { int args = lua_gettop(L); char error[1024]; @@ -77,7 +111,7 @@ static int uwsgi_api_log(lua_State *L) { if (lua_isstring(L, 1)) { logline = lua_tostring(L, 1); - uwsgi_log( "%s\n", logline); + ulua_log( "%s", logline); } return 0; @@ -109,7 +143,7 @@ static int uwsgi_api_rpc(lua_State *L) { uint64_t len; char *str = uwsgi_do_rpc((char *) lua_tostring(L, 1), (char *) lua_tostring(L, 2), argc, argv, argvs, &len); - if (len == 0) { // fail?? + if (!(len)) { // fail?? lua_pushnil(L); } else { lua_pushlstring(L, str, len); @@ -127,7 +161,7 @@ static int uwsgi_api_rpc(lua_State *L) { static int uwsgi_api_register_rpc(lua_State *L) { - uint8_t argc = lua_gettop(L); + uint8_t argc = lua_gettop(L); const char *name; // a hack for 64bit; int func; @@ -141,9 +175,12 @@ static int uwsgi_api_register_rpc(lua_State *L) { name = lua_tostring(L, 1); lua_pushvalue(L, 2); - func = luaL_ref(L, LUA_REGISTRYINDEX); + func = luaL_ref(L, LUA_REGISTRYINDEX); + +#ifdef UWSGI_DEBUG + ulua_log("registered function %d in global table of lua_State %d", func, ULUA_MYWID); +#endif - //uwsgi_log("registered function %d in global table of lua_State %d\n", func, ULUA_MYWID); lfunc = func; if (uwsgi_register_rpc((char *)name, &lua_plugin, 0, (void *) lfunc)) { @@ -159,9 +196,9 @@ static int uwsgi_api_register_rpc(lua_State *L) { static int uwsgi_api_cache_set(lua_State *L) { uint8_t argc = lua_gettop(L); - const char *key ; - const char *value ; - uint64_t expires = 0; + const char *key ; + const char *value ; + uint64_t expires = 0; size_t vallen; size_t keylen; const char *cache = NULL; @@ -721,7 +758,7 @@ static const luaL_Reg uwsgi_api[] = { static int uwsgi_lua_init(){ int i; - uwsgi_log("Initializing Lua environment... "); + uwsgi_log(ULUA_LOG_HEADER " Initializing Lua environment... "); ulua.state = uwsgi_malloc(sizeof(lua_State**) * uwsgi.numproc); @@ -774,7 +811,7 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { struct uwsgi_string_list *usl = ulua.load; while(usl) { if (luaL_dofile(L, usl->value)) { - uwsgi_log("unable to load Lua file %s: %s\n", usl->value, lua_tostring(L, -1)); + ulua_log("unable to load Lua file %s: %s", usl->value, lua_tostring(L, -1)); lua_pop(L, 1); } usl = usl->next; @@ -784,11 +821,11 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { if (ulua.filename) { if (luaL_loadfile(L, ulua.filename)) { - uwsgi_log("unable to load Lua file %s: %s\n", ulua.filename, lua_tostring(L, -1)); + ulua_log("unable to load Lua file %s: %s", ulua.filename, lua_tostring(L, -1)); lua_pop(L, 1); } else { if (lua_pcall(L, uslnargs, 1, 0) != 0) { - uwsgi_log("%s\n", lua_tostring(L, -1)); + ulua_log("%s", lua_tostring(L, -1)); lua_pop(L, 1); uslnargs = 0; } else { @@ -820,7 +857,7 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { lua_pop(L, uslnargs); } - uwsgi_log("Can't find WSAPI entry point (no function, nor a table with function'run').\n"); + ulua_log("Can't find WSAPI entry point (no function, nor a table with function'run')."); i = luaL_dostring(L, "return function() return '500'; end"); } @@ -837,44 +874,48 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { Ls[i] = lua_newthread(L); lua_rawseti(L, -2, i); - // push app from master and move to new - //lua_pushvalue(L, -2); - //lua_xmove(L, Ls[i], 1); } lua_setfield(L, -2, "luathreads"); } // and the worker is ready! - //lua_remove(L, -2); lua_pop(L, 1); lua_gc(L, LUA_GCCOLLECT, 0); - uwsgi_log("inited lua_State %d for worker %d\n", sid, wid); + ulua_log("inited lua_State %d for worker %d", sid, wid); } static int uwsgi_lua_request(struct wsgi_request *wsgi_req) { - int i; const char *http, *http2; - size_t slen, slen2; + size_t i, tlen, slen, slen2; lua_State *L = ULUA_WORKER_STATE[wsgi_req->async_id]; + /* Standard WSAPI request */ + if (!wsgi_req->len) { + ulua_log("Empty lua request. skip."); + return -1; + } + if (wsgi_req->async_status == UWSGI_AGAIN) { - if (lua_type(L, -1) != LUA_TFUNCTION) { - // wrong async_status status! - return -1; - } async_coroutine: while (lua_pcall(L, 0, 1, 0) == 0) { - if (lua_isstring(L, -1)) { - http = lua_tolstring(L, -1, &slen); - uwsgi_response_write_body_do(wsgi_req, (char *)http, slen); - } else if (lua_isnil(L, -1)) { // posible dead coroutine - lua_pop(L, 1); - lua_pushvalue(L, -1); - continue; // retry + switch(lua_type(L, -1)) { + case LUA_TNIL: // posible dead coroutine + + lua_pop(L, 1); + lua_pushvalue(L, -1); + continue; // retry + + case LUA_TTABLE: if(!(ulua_metatable_tostring(L, -1))) break; + case LUA_TNUMBER: + case LUA_TSTRING: + + http = lua_tolstring(L, -1, &slen); + uwsgi_response_write_body_do(wsgi_req, (char *)http, slen); + } lua_pop(L, 1); @@ -884,34 +925,24 @@ async_coroutine: goto clear; } - /* Standard WSAPI request */ - if (!wsgi_req->len) { - uwsgi_log( "Empty lua request. skip.\n"); - return -1; - } - if (uwsgi_parse_vars(wsgi_req)) { return -1; } // put function in the stack - //lua_getfield(L, LUA_GLOBALSINDEX, "run"); lua_rawgeti(L, LUA_REGISTRYINDEX, 1); - //lua_pushvalue(L, -1); // put cgi vars in the stack - lua_newtable(L); lua_pushstring(L, ""); lua_setfield(L, -2, "CONTENT_TYPE"); - for(i=0;ivar_cnt;i+=2) { + for(i = 0; i < wsgi_req->var_cnt; i+=2) { lua_pushlstring(L, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len); lua_pushlstring(L, wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len); lua_rawset(L, -3); } - // put "input" table lua_newtable(L); lua_pushcfunction(L, uwsgi_lua_input); @@ -920,80 +951,95 @@ async_coroutine: #ifdef UWSGI_DEBUG - uwsgi_log("stack pos %d\n", lua_gettop(L)); + ulua_log("stack pos %d", lua_gettop(L)); #endif // call function - if (lua_pcall(L, 1, 3, 0) != 0) { - uwsgi_log("%s\n", lua_tostring(L, -1)); + ulua_log("%s", lua_tostring(L, -1)); lua_pop(L, 1); - lua_pushvalue(L, -1); goto clear2; } - //uwsgi_log("%d %s %s %s\n",i,lua_typename(L, lua_type(L, -3)), lua_typename(L, lua_type(L, -2)) , lua_typename(L, lua_type(L, -1))); +#ifdef UWSGI_DEBUG + ulua_log("%d %s %s %s",i,lua_typename(L, lua_type(L, -3)), lua_typename(L, lua_type(L, -2)) , lua_typename(L, lua_type(L, -1))); +#endif // send status - if (lua_isstring(L, -3)) { - http = lua_tolstring(L, -3, &slen); - if (uwsgi_response_prepare_headers(wsgi_req, (char *) http, slen)) - goto clear2; - } - else { - uwsgi_log("[uwsgi-lua] invalid response status !!!\n"); + http = lua_tolstring(L, -3, &slen); + + if (!(slen)) { + ulua_log("invalid response status!!!"); // let's continue + } else { + if (uwsgi_response_prepare_headers(wsgi_req, (char *) http, slen)) { + lua_pop(L, 3); + goto clear2; + } } // send headers - if (lua_type(L, -2) == LUA_TTABLE) { + if (lua_istable(L, -2)) { + lua_pushnil(L); + while(lua_next(L, -3) != 0) { http = lua_tolstring(L, -2, &slen); - if (lua_type(L, -1) == LUA_TTABLE) { - for (i = 1; /*empty*/ ; ++i) { + if (lua_istable(L, -1)) { + tlen = lua_rawlen(L, -1); + + for (i = 1; i <= tlen; i++) { lua_rawgeti(L, -1, i); - - if (lua_isnil(L, -1)) { - lua_pop(L, 1); - break; - } - + http2 = lua_tolstring(L, -1, &slen2); uwsgi_response_add_header(wsgi_req, (char *) http, slen, (char *) http2, slen2); + lua_pop(L, 1); } - } - else { + + } else { + http2 = lua_tolstring(L, -1, &slen2); uwsgi_response_add_header(wsgi_req, (char *) http, slen, (char *) http2, slen2); } + lua_pop(L, 1); } } // send body with coroutine or copy from string lua_pushvalue(L, -1); - - if (lua_type(L, -1) == LUA_TFUNCTION) { - if (uwsgi.async > 0) { - goto async_coroutine; - } - while ( lua_pcall(L, 0, 1, 0) == 0) { - if (lua_isstring(L, -1)) { - http = lua_tolstring(L, -1, &slen); - uwsgi_response_write_body_do(wsgi_req, (char *)http, slen); + switch(lua_type(L, -1)) { + case LUA_TFUNCTION: + + if (uwsgi.async > 0) { + goto async_coroutine; + } + + while (lua_pcall(L, 0, 1, 0) == 0) { + switch(lua_type(L, -1)) { + case LUA_TTABLE: if(!(ulua_metatable_tostring(L, -1))) break; + case LUA_TNUMBER: + case LUA_TSTRING: + + http = lua_tolstring(L, -1, &slen); + uwsgi_response_write_body_do(wsgi_req, (char *) http, slen); + } + + lua_pop(L, 1); + lua_pushvalue(L, -1); } - lua_pop(L, 1); - lua_pushvalue(L, -1); - } - } - else if (lua_isstring(L, -1)) { - http = lua_tolstring(L, -1, &slen); - uwsgi_response_write_body_do(wsgi_req, (char *) http, slen); + break; + + case LUA_TTABLE: if(!(ulua_metatable_tostring(L, -1))) break; + case LUA_TNUMBER: + case LUA_TSTRING: + + http = lua_tolstring(L, -1, &slen); + uwsgi_response_write_body_do(wsgi_req, (char *) http, slen); } clear: @@ -1039,14 +1085,14 @@ static char *uwsgi_lua_code_string(char *id, char *code, char *func, char *key, L = luaL_newstate(); luaL_openlibs(L); if (luaL_loadfile(L, code) || lua_pcall(L, 0, 0, 0)) { - uwsgi_log("unable to load file %s: %s\n", code, lua_tostring(L, -1)); + ulua_log("unable to load file %s: %s", code, lua_tostring(L, -1)); lua_close(L); L = NULL; return NULL; } lua_getglobal(L, func); if (!lua_isfunction(L,-1)) { - uwsgi_log("unable to find %s function in lua file %s\n", func, code); + ulua_log("unable to find %s function in lua file %s", func, code); lua_close(L); L = NULL; return NULL; @@ -1061,11 +1107,11 @@ static char *uwsgi_lua_code_string(char *id, char *code, char *func, char *key, lua_pushlstring(L, key, keylen); #ifdef UWSGI_DEBUG - uwsgi_log("stack pos %d %.*s\n", lua_gettop(L), keylen, key); + ulua_log("stack pos %d %.*s", lua_gettop(L), keylen, key); #endif if (lua_pcall(L, 1, 1, 0) != 0) { - uwsgi_log("error running function `f': %s", lua_tostring(L, -1)); + ulua_log("error running function `f': %s", lua_tostring(L, -1)); return NULL; } @@ -1085,7 +1131,7 @@ static int uwsgi_lua_signal_handler(uint8_t sig, void *handler) { lua_State *L = ULUA_WORKER_STATE[wsgi_req->async_id]; #ifdef UWSGI_DEBUG - uwsgi_log("managing signal handler on core %d\n", wsgi_req->async_id); + ulua_log("managing signal handler on core %d", wsgi_req->async_id); #endif lua_rawgeti(L, LUA_REGISTRYINDEX, (long) handler); @@ -1093,7 +1139,7 @@ static int uwsgi_lua_signal_handler(uint8_t sig, void *handler) { lua_pushnumber(L, sig); if (lua_pcall(L, 1, 1, 0) != 0) { - uwsgi_log("error running function `f': %s", + ulua_log("error running function `f': %s", lua_tostring(L, -1)); return -1; @@ -1116,7 +1162,7 @@ static uint64_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t a lua_State *L = ULUA_WORKER_STATE[wsgi_req->async_id]; #ifdef UWSGI_DEBUG - uwsgi_log("get function %d\n", ifunc); + ulua_log("get function %d", ifunc); #endif lua_rawgeti(L, LUA_REGISTRYINDEX, ifunc); @@ -1125,7 +1171,7 @@ static uint64_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t a } if (lua_pcall(L, argc, 1, 0) != 0) { - uwsgi_log("error running function `f': %s", lua_tostring(L, -1)); + ulua_log("error running function `f': %s", lua_tostring(L, -1)); return 0; } @@ -1133,7 +1179,7 @@ static uint64_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t a sv = lua_tolstring(L, -1, &sl); #ifdef UWSGI_DEBUG - uwsgi_log("sv = %s sl = %lu\n", sv, (unsigned long) sl); + ulua_log("sv = %s sl = %lu", sv, (unsigned long) sl); #endif if (sl > 0) { *buffer = uwsgi_malloc(sl); @@ -1206,7 +1252,7 @@ static void uwsgi_lua_configurator(char *filename, char *magic_table[]) { char *value = uwsgi_str((char *)lua_tostring(L, -1)); add_exported_option(key, value, 0); lua_pop(L, 1); - } + } } else { char *value = uwsgi_str((char *)lua_tostring(L, -1)); From c375920c631abdcf722a835f68ea461d18f1cf3d Mon Sep 17 00:00:00 2001 From: Hleran Date: Thu, 6 Aug 2015 05:17:20 +0300 Subject: [PATCH 02/17] lua_plugin: proper uwsgi.log uwsgi.log like buildin print function dummy response cfunction --- plugins/lua/lua_plugin.c | 72 ++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 29 deletions(-) diff --git a/plugins/lua/lua_plugin.c b/plugins/lua/lua_plugin.c index ad011d76..81368669 100644 --- a/plugins/lua/lua_plugin.c +++ b/plugins/lua/lua_plugin.c @@ -5,10 +5,10 @@ #include #if LUA_VERSION_NUM < 502 -# define luaL_newuwsgilib(L,l) luaL_register(L, "uwsgi",l) +# define ulua_pushapi luaL_register # define lua_rawlen lua_objlen #else -# define luaL_newuwsgilib(L,l) lua_newtable(L);luaL_setfuncs (L, l, 0);lua_pushvalue(L,-1);lua_setglobal(L,"uwsgi") +# define ulua_pushapi(L,key,api) lua_newtable(L);luaL_setfuncs(L,api,0);lua_pushvalue(L,-1);lua_setglobal(L,key) #endif extern struct uwsgi_server uwsgi; @@ -30,8 +30,6 @@ struct uwsgi_lua { struct uwsgi_plugin lua_plugin; -#define lca(L, n) ulua_check_args(L, __FUNCTION__, n) - static void uwsgi_opt_luashell(char *opt, char *value, void *foobar) { uwsgi.honour_stdin = 1; @@ -88,32 +86,40 @@ static int ulua_metatable_tostring(lua_State *L, int obj) { return 0; } -static void ulua_check_args(lua_State *L, const char *func, int n) { - int args = lua_gettop(L); - char error[1024]; - if (args != n) { - if (n == 1) { - snprintf(error, 1024, "uwsgi.%s takes 1 parameter", func+10); - } - else { - snprintf(error, 1024, "uwsgi.%s takes %d parameters", func+10, n); - } - lua_pushstring(L, error); - lua_error(L); - } -} - static int uwsgi_api_log(lua_State *L) { + int16_t argc = lua_gettop(L); + unsigned long point; + int type; - const char *logline ; - - lca(L, 1); - - if (lua_isstring(L, 1)) { - logline = lua_tostring(L, 1); - ulua_log( "%s", logline); + if (!(argc)) { + return 0; + } + + uwsgi_log(ULUA_LOG_HEADER); + + for(argc = -argc; argc < 0; argc++) { + type = lua_type(L, argc); + + switch(type) { + case LUA_TNIL: uwsgi_log(" nil"); continue; + + case LUA_TBOOLEAN: uwsgi_log(lua_toboolean(L, argc) ? " true" : " false"); continue; + + case LUA_TTABLE: if(!(ulua_metatable_tostring(L, argc))) break; + case LUA_TNUMBER: + case LUA_TSTRING: uwsgi_log(" %s", lua_tostring(L, argc)); continue; + } + + point = (unsigned long) (lua_topointer(L, -argc)); + + if (point) { + uwsgi_log(" %s: 0x%.8x", lua_typename(L, type), point); + } else { + uwsgi_log(" %s", lua_typename(L, type)); + } } + uwsgi_log("\n"); return 0; } @@ -778,6 +784,10 @@ static int uwsgi_lua_init(){ return 0; } +static int uwsgi_lua_dummy_response(lua_State *L) { + lua_pushstring(L, "500"); + return 1; +} static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { int i; @@ -790,7 +800,7 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { // init worker state luaL_openlibs(L); - luaL_newuwsgilib(L, uwsgi_api); + ulua_pushapi(L, "uwsgi", uwsgi_api); lua_pushstring(L, UWSGI_VERSION); lua_setfield(L, -2, "version"); @@ -824,6 +834,10 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { ulua_log("unable to load Lua file %s: %s", ulua.filename, lua_tostring(L, -1)); lua_pop(L, 1); } else { + if (uslnargs > 0) { + lua_insert(L, -uslnargs-1); + } + if (lua_pcall(L, uslnargs, 1, 0) != 0) { ulua_log("%s", lua_tostring(L, -1)); lua_pop(L, 1); @@ -858,7 +872,7 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { } ulua_log("Can't find WSAPI entry point (no function, nor a table with function'run')."); - i = luaL_dostring(L, "return function() return '500'; end"); + lua_pushcfunction(L, uwsgi_lua_dummy_response); } lua_rawseti(L, LUA_REGISTRYINDEX, 1); @@ -1085,7 +1099,7 @@ static char *uwsgi_lua_code_string(char *id, char *code, char *func, char *key, L = luaL_newstate(); luaL_openlibs(L); if (luaL_loadfile(L, code) || lua_pcall(L, 0, 0, 0)) { - ulua_log("unable to load file %s: %s", code, lua_tostring(L, -1)); + ulua_log("unable to load file %s: %s", code, lua_tostring(L, -1)); lua_close(L); L = NULL; return NULL; From 271c6aa13b22a0997de2c4a7ddc4c9c3ed7e6e82 Mon Sep 17 00:00:00 2001 From: Hleran Date: Thu, 6 Aug 2015 19:40:52 +0300 Subject: [PATCH 03/17] lua_plugin: rpc via uwsgi.rpc_ref table --- plugins/lua/lua_plugin.c | 191 +++++++++++++++++++++++++++------------ 1 file changed, 135 insertions(+), 56 deletions(-) diff --git a/plugins/lua/lua_plugin.c b/plugins/lua/lua_plugin.c index 81368669..3eb80f18 100644 --- a/plugins/lua/lua_plugin.c +++ b/plugins/lua/lua_plugin.c @@ -56,14 +56,14 @@ static struct uwsgi_option uwsgi_lua_options[] = { }; static int ulua_metatable_tostring(lua_State *L, int obj) { - // replaces table with __tostring result, or do nothing in case of fail + // replace table with __tostring result, or do nothing in case of fail if (!(luaL_getmetafield(L, obj, "__tostring"))) { return 0; } if (!(lua_isfunction(L, -1))) { - ulua_log("__tostring is not a function", lua_tostring(L, -1)); + ulua_log("__tostring is not a function"); lua_pop(L, 1); return 0; } @@ -86,6 +86,25 @@ static int ulua_metatable_tostring(lua_State *L, int obj) { return 0; } + +static int ulua_metatable_call(lua_State *L, int obj) { + // get __call attr and place it before table, or do nothing in case of fail + + if (!(luaL_getmetafield(L, obj, "__call"))) { + return 0; + } + + if (!(lua_isfunction(L, -1))) { + ulua_log("__call is not a function"); + lua_pop(L, 1); + return 0; + } + + lua_insert(L, obj-1); + + return 1; +} + static int uwsgi_api_log(lua_State *L) { int16_t argc = lua_gettop(L); unsigned long point; @@ -120,6 +139,7 @@ static int uwsgi_api_log(lua_State *L) { } uwsgi_log("\n"); + return 0; } @@ -165,40 +185,83 @@ static int uwsgi_api_rpc(lua_State *L) { return 1; } +static int uwsgi_api_rpc_register_key(const char *key, size_t len) { + + // exists?? + size_t i; + int offset = uwsgi.mywid * uwsgi.rpc_max; + + for(i = 0; i < uwsgi.shared->rpc_count[uwsgi.mywid]; i++) { + if (!strncmp(key, (&uwsgi.rpc_table[offset + i])->name, len)) { + if ((&uwsgi.rpc_table[offset + i])->plugin == &lua_plugin) { + return 1; + } + + break; + } + } + + // no + char *name = (char *) uwsgi_malloc(sizeof(char) * len); + + memcpy(name, key, sizeof(char) * len); + + if (uwsgi_register_rpc(name, &lua_plugin, 0, name)) { + // error + free(name); + return 0; + } + + return 1; +} + static int uwsgi_api_register_rpc(lua_State *L) { + // legacy rpc register func uint8_t argc = lua_gettop(L); - const char *name; - // a hack for 64bit; - int func; - long lfunc; - + if (argc < 2) { lua_pushnil(L); return 1; + } else if (argc > 2) { + lua_pop(L, argc - 2); } - - name = lua_tostring(L, 1); - - lua_pushvalue(L, 2); - func = luaL_ref(L, LUA_REGISTRYINDEX); - -#ifdef UWSGI_DEBUG - ulua_log("registered function %d in global table of lua_State %d", func, ULUA_MYWID); -#endif - - lfunc = func; - - if (uwsgi_register_rpc((char *)name, &lua_plugin, 0, (void *) lfunc)) { - lua_pushnil(L); - } - else { + + lua_rawgeti(L, LUA_REGISTRYINDEX, 2); + + lua_pushvalue(L, -3); + lua_pushvalue(L, -3); + lua_settable(L, -3); + lua_pushvalue(L, -3); + + lua_rawget(L, -2); + + if (!(lua_isnil(L, -1))) { lua_pushboolean(L, 1); } - + return 1; } +static int uwsgi_api_register_rpc_newindex(lua_State *L) { + // 3 args: table, key(string or number), value(not nil) + + uint8_t argc = lua_gettop(L); + size_t len; + + if (argc != 3) { + return 0; + } + + const char *key = lua_tolstring(L, -2, &len); + + if (len && !(lua_isnil(L, -1)) && uwsgi_api_rpc_register_key(key, len)) { + lua_rawset(L, -3); + } + + return 0; +} + static int uwsgi_api_cache_set(lua_State *L) { uint8_t argc = lua_gettop(L); @@ -814,6 +877,17 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { // reserve ref 1 for ws func lua_pushvalue(L, -1); luaL_ref(L, LUA_REGISTRYINDEX); + + // rpc metatable ref 2 + lua_newtable(L); + lua_newtable(L); + lua_pushcfunction(L, uwsgi_api_register_rpc_newindex); + lua_setfield(L, -2, "__newindex"); + lua_setmetatable(L, -2); + lua_pushvalue(L, -1); + luaL_ref(L, LUA_REGISTRYINDEX); + lua_setfield(L, -2, "rpc_ref"); + // init main app uslnargs = lua_gettop(L); @@ -1165,46 +1239,51 @@ static int uwsgi_lua_signal_handler(uint8_t sig, void *handler) { static uint64_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) { - uint8_t i; - const char *sv; - size_t sl; - long lfunc = (long) func; - int ifunc = lfunc; + uint8_t i; + const char *sv; + size_t sl; + int type; struct wsgi_request *wsgi_req = current_wsgi_req(); lua_State *L = ULUA_WORKER_STATE[wsgi_req->async_id]; - -#ifdef UWSGI_DEBUG - ulua_log("get function %d", ifunc); -#endif - lua_rawgeti(L, LUA_REGISTRYINDEX, ifunc); - - for(i=0;i 0) { - *buffer = uwsgi_malloc(sl); - memcpy(*buffer, sv, sl); - lua_pop(L, 1); - return sl; + lua_pushstring(L, (char *) func); + lua_rawget(L, -2); + + type = lua_type(L, -1); + + if (!(type == LUA_TFUNCTION) && !(type == LUA_TTABLE && ulua_metatable_call(L, -1))) { + ulua_log("rpc: attempt to call a %s value", lua_typename(L, type)); + lua_pop(L, 2); + return 0; + } + + for(i = 0; i < argc; i++) { + lua_pushlstring(L, argv[i], argvs[i]); } - lua_pop(L, 1); - return 0; + if (type == LUA_TTABLE) { + ++argc; //table is the first arg + } + + if (lua_pcall(L, argc, 1, 0) != 0) { + ulua_log("rpc: error running function `f': %s", lua_tostring(L, -1)); + lua_pop(L, 2); + return 0; + } + sv = lua_tolstring(L, -1, &sl); + + if (sl > 0) { + *buffer = uwsgi_malloc(sizeof(char) * sl); + memcpy(*buffer, sv, sizeof(char) * sl); + } + + lua_pop(L, 2); + + return sl; } static void uwsgi_lua_configurator_array(lua_State *L) { From 37971671cb43d0b5314d4a02c50677a7c435c753 Mon Sep 17 00:00:00 2001 From: Hleran Date: Fri, 7 Aug 2015 02:39:44 +0300 Subject: [PATCH 04/17] lua_plugin: own signal ref table in each lua_State --- plugins/lua/lua_plugin.c | 123 ++++++++++++++++++++++++++------------- 1 file changed, 84 insertions(+), 39 deletions(-) diff --git a/plugins/lua/lua_plugin.c b/plugins/lua/lua_plugin.c index 3eb80f18..a4e6ef11 100644 --- a/plugins/lua/lua_plugin.c +++ b/plugins/lua/lua_plugin.c @@ -26,6 +26,10 @@ struct uwsgi_lua { #define ULUA_WORKER_STATE ulua.state[ULUA_MYWID] #define ULUA_LOG_HEADER "[uwsgi-lua]" +#define ULUA_WSAPI_REF 1 +#define ULUA_RPC_REF 2 +#define ULUA_SIGNAL_REF 3 + #define ulua_log(c, ar...) uwsgi_log(ULUA_LOG_HEADER" "c"\n", ##ar) struct uwsgi_plugin lua_plugin; @@ -55,7 +59,7 @@ static struct uwsgi_option uwsgi_lua_options[] = { }; -static int ulua_metatable_tostring(lua_State *L, int obj) { +static int uwsgi_lua_metatable_tostring(lua_State *L, int obj) { // replace table with __tostring result, or do nothing in case of fail if (!(luaL_getmetafield(L, obj, "__tostring"))) { @@ -87,7 +91,7 @@ static int ulua_metatable_tostring(lua_State *L, int obj) { } -static int ulua_metatable_call(lua_State *L, int obj) { +static int uwsgi_lua_metatable_call(lua_State *L, int obj) { // get __call attr and place it before table, or do nothing in case of fail if (!(luaL_getmetafield(L, obj, "__call"))) { @@ -105,6 +109,22 @@ static int ulua_metatable_call(lua_State *L, int obj) { return 1; } +static int uwsgi_api_signal(lua_State *L) { + uint8_t argc = lua_gettop(L); + + if (argc > 0 && lua_isnumber(L, 1)) { + if (argc > 1 && lua_isstring(L, 2)) { + lua_pushnumber(L, uwsgi_remote_signal_send((char *) lua_tostring(L, -2), (uint8_t) lua_tonumber(L, 1))); + + return 1; + } else { + uwsgi_signal_send(uwsgi.signal_socket, (uint8_t) lua_tonumber(L, 1)); + } + } + + return 0; +} + static int uwsgi_api_log(lua_State *L) { int16_t argc = lua_gettop(L); unsigned long point; @@ -124,12 +144,12 @@ static int uwsgi_api_log(lua_State *L) { case LUA_TBOOLEAN: uwsgi_log(lua_toboolean(L, argc) ? " true" : " false"); continue; - case LUA_TTABLE: if(!(ulua_metatable_tostring(L, argc))) break; + case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, argc))) break; case LUA_TNUMBER: case LUA_TSTRING: uwsgi_log(" %s", lua_tostring(L, argc)); continue; } - point = (unsigned long) (lua_topointer(L, -argc)); + point = (unsigned long) (lua_topointer(L, argc)); if (point) { uwsgi_log(" %s: 0x%.8x", lua_typename(L, type), point); @@ -147,8 +167,7 @@ static int uwsgi_api_rpc(lua_State *L) { uint8_t argc = lua_gettop(L); if (argc < 2) { - lua_pushnil(L); - return 1; + return 0; } argc-=2; @@ -223,17 +242,16 @@ static int uwsgi_api_register_rpc(lua_State *L) { if (argc < 2) { lua_pushnil(L); return 1; - } else if (argc > 2) { - lua_pop(L, argc - 2); } - lua_rawgeti(L, LUA_REGISTRYINDEX, 2); + lua_rawgeti(L, LUA_REGISTRYINDEX, ULUA_RPC_REF); + + lua_pushvalue(L, 1); + lua_pushvalue(L, 2); - lua_pushvalue(L, -3); - lua_pushvalue(L, -3); lua_settable(L, -3); - lua_pushvalue(L, -3); + lua_pushvalue(L, 1); lua_rawget(L, -2); if (!(lua_isnil(L, -1))) { @@ -255,7 +273,7 @@ static int uwsgi_api_register_rpc_newindex(lua_State *L) { const char *key = lua_tolstring(L, -2, &len); - if (len && !(lua_isnil(L, -1)) && uwsgi_api_rpc_register_key(key, len)) { + if (len && !(lua_isnil(L, -1)) && uwsgi_api_rpc_register_key(key, len + 1)) { lua_rawset(L, -3); } @@ -330,22 +348,31 @@ error: static int uwsgi_api_register_signal(lua_State *L) { int args = lua_gettop(L); - uint8_t sig; - long lhandler; const char *who; + uint8_t sig; + + if (args < 3 || !(lua_isnumber(L, 1))) { // non number value gives us signal 0 from lua_tonumber() result + lua_pushnil(L); + return 1; + } - if (args >= 3) { - - sig = lua_tonumber(L, 1); - who = lua_tostring(L, 2); + sig = (uint8_t) lua_tonumber(L, 1); + who = lua_tostring(L, 2); + + if ((uwsgi.mywid == 0 && (&uwsgi.shared->signal_table[sig])->handler) // we are master and alredy registered? + || !(uwsgi_register_signal(sig, (char *)who, (void *)(1 /* unused */), 6))) { + + lua_rawgeti(L, LUA_REGISTRYINDEX, ULUA_SIGNAL_REF); + lua_pushvalue(L, 3); - lhandler = luaL_ref(L, LUA_REGISTRYINDEX); - - uwsgi_register_signal(sig, (char *)who, (void *) lhandler, 6); + lua_rawseti(L, -2, sig); + + lua_pushboolean(L, 1); + return 1; } lua_pushnil(L); - return 1; + return 1; } static int uwsgi_api_cache_clear(lua_State *L) { @@ -798,6 +825,7 @@ static const luaL_Reg uwsgi_api[] = { {"register_signal", uwsgi_api_register_signal}, {"register_rpc", uwsgi_api_register_rpc}, {"rpc", uwsgi_api_rpc}, + {"signal", uwsgi_api_signal}, {"req_input_read", uwsgi_lua_input}, {"websocket_handshake", uwsgi_api_websocket_handshake}, @@ -885,10 +913,17 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { lua_setfield(L, -2, "__newindex"); lua_setmetatable(L, -2); lua_pushvalue(L, -1); + luaL_ref(L, LUA_REGISTRYINDEX); lua_setfield(L, -2, "rpc_ref"); - + // signal table ref 3 + lua_newtable(L); + lua_pushvalue(L, -1); + + luaL_ref(L, LUA_REGISTRYINDEX); + lua_setfield(L, -2, "signal_ref"); + // init main app uslnargs = lua_gettop(L); @@ -949,7 +984,7 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { lua_pushcfunction(L, uwsgi_lua_dummy_response); } - lua_rawseti(L, LUA_REGISTRYINDEX, 1); + lua_rawseti(L, LUA_REGISTRYINDEX, ULUA_WSAPI_REF); //init additional threads for current worker if(cores > 0) { @@ -997,7 +1032,7 @@ async_coroutine: lua_pushvalue(L, -1); continue; // retry - case LUA_TTABLE: if(!(ulua_metatable_tostring(L, -1))) break; + case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, -1))) break; case LUA_TNUMBER: case LUA_TSTRING: @@ -1018,7 +1053,7 @@ async_coroutine: } // put function in the stack - lua_rawgeti(L, LUA_REGISTRYINDEX, 1); + lua_rawgeti(L, LUA_REGISTRYINDEX, ULUA_WSAPI_REF); // put cgi vars in the stack lua_newtable(L); @@ -1108,7 +1143,7 @@ async_coroutine: while (lua_pcall(L, 0, 1, 0) == 0) { switch(lua_type(L, -1)) { - case LUA_TTABLE: if(!(ulua_metatable_tostring(L, -1))) break; + case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, -1))) break; case LUA_TNUMBER: case LUA_TSTRING: @@ -1122,7 +1157,7 @@ async_coroutine: break; - case LUA_TTABLE: if(!(ulua_metatable_tostring(L, -1))) break; + case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, -1))) break; case LUA_TNUMBER: case LUA_TSTRING: @@ -1214,27 +1249,37 @@ static char *uwsgi_lua_code_string(char *id, char *code, char *func, char *key, static int uwsgi_lua_signal_handler(uint8_t sig, void *handler) { + int type; struct wsgi_request *wsgi_req = current_wsgi_req(); lua_State *L = ULUA_WORKER_STATE[wsgi_req->async_id]; + + lua_rawgeti(L, LUA_REGISTRYINDEX, ULUA_SIGNAL_REF); + lua_rawgeti(L, -1, sig); #ifdef UWSGI_DEBUG ulua_log("managing signal handler on core %d", wsgi_req->async_id); #endif - lua_rawgeti(L, LUA_REGISTRYINDEX, (long) handler); - - lua_pushnumber(L, sig); - - if (lua_pcall(L, 1, 1, 0) != 0) { - ulua_log("error running function `f': %s", - lua_tostring(L, -1)); + type = lua_type(L, -1); + if (!(type == LUA_TFUNCTION) && !(type == LUA_TTABLE && uwsgi_lua_metatable_call(L, -1))) { + ulua_log("signal: attempt to call a %s value", lua_typename(L, type)); + lua_pop(L, 2); return -1; } + lua_pushnumber(L, sig); + + if (lua_pcall(L, 1 + (type == LUA_TTABLE), 1, 0) != 0) { + ulua_log("signal: error running function `f': %s", + lua_tostring(L, -1)); + lua_pop(L, 2); + return -1; + } + + lua_pop(L, 2); return 0; - } static uint64_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) { @@ -1247,14 +1292,14 @@ static uint64_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t a struct wsgi_request *wsgi_req = current_wsgi_req(); lua_State *L = ULUA_WORKER_STATE[wsgi_req->async_id]; - lua_rawgeti(L, LUA_REGISTRYINDEX, 2); + lua_rawgeti(L, LUA_REGISTRYINDEX, ULUA_RPC_REF); lua_pushstring(L, (char *) func); lua_rawget(L, -2); type = lua_type(L, -1); - if (!(type == LUA_TFUNCTION) && !(type == LUA_TTABLE && ulua_metatable_call(L, -1))) { + if (!(type == LUA_TFUNCTION) && !(type == LUA_TTABLE && uwsgi_lua_metatable_call(L, -1))) { ulua_log("rpc: attempt to call a %s value", lua_typename(L, type)); lua_pop(L, 2); return 0; From 6921e8f82096811cb7d6bffccceec7d5c8487b05 Mon Sep 17 00:00:00 2001 From: Hleran Date: Fri, 7 Aug 2015 07:36:13 +0300 Subject: [PATCH 05/17] lua_plugin: atexit, lazy signal routing uwsgi_lua_atexit to commit garbage-collection metamethods lazy signal routing: empty 'receiver' value on master table --- plugins/lua/lua_plugin.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/plugins/lua/lua_plugin.c b/plugins/lua/lua_plugin.c index a4e6ef11..5a40cefb 100644 --- a/plugins/lua/lua_plugin.c +++ b/plugins/lua/lua_plugin.c @@ -349,6 +349,7 @@ static int uwsgi_api_register_signal(lua_State *L) { int args = lua_gettop(L); const char *who; + size_t len; uint8_t sig; if (args < 3 || !(lua_isnumber(L, 1))) { // non number value gives us signal 0 from lua_tonumber() result @@ -357,11 +358,17 @@ static int uwsgi_api_register_signal(lua_State *L) { } sig = (uint8_t) lua_tonumber(L, 1); - who = lua_tostring(L, 2); + who = lua_tolstring(L, 2, &len); if ((uwsgi.mywid == 0 && (&uwsgi.shared->signal_table[sig])->handler) // we are master and alredy registered? || !(uwsgi_register_signal(sig, (char *)who, (void *)(1 /* unused */), 6))) { + if (uwsgi.mywid > 0) { // signal router hax + uwsgi_lock(uwsgi.signal_table_lock); + strncpy((&uwsgi.shared->signal_table[sig])->receiver, who, len + 1); + uwsgi_unlock(uwsgi.signal_table_lock); + } + lua_rawgeti(L, LUA_REGISTRYINDEX, ULUA_SIGNAL_REF); lua_pushvalue(L, 3); @@ -1460,6 +1467,15 @@ static void uwsgi_lua_init_apps() { } } +static void uwsgi_lua_atexit() { + lua_State **Ls = ULUA_WORKER_STATE; + int i; + + for (i = 0; i < uwsgi.threads; i++) { + lua_close(Ls[i]); + } +} + struct uwsgi_plugin lua_plugin = { .name = "lua", @@ -1479,6 +1495,7 @@ struct uwsgi_plugin lua_plugin = { .code_string = uwsgi_lua_code_string, .rpc = uwsgi_lua_rpc, + .atexit = uwsgi_lua_atexit, .on_load = uwsgi_register_lua_features, }; From 8d2465db9b60cf1b50e56b979e1f193bd3e0d534 Mon Sep 17 00:00:00 2001 From: Hleran Date: Sun, 16 Aug 2015 15:41:39 +0300 Subject: [PATCH 06/17] lua_plugin: lua_createtable, signals using prehashed lua_createtable when we can instead of lua_newtable plugin specific regsiter signal add_file_monitor, add_timer, add_rb_timer, add_cron, alarm --- plugins/lua/lua_plugin.c | 253 ++++++++++++++++++++++++++++++++------- 1 file changed, 209 insertions(+), 44 deletions(-) diff --git a/plugins/lua/lua_plugin.c b/plugins/lua/lua_plugin.c index 5a40cefb..831f19b1 100644 --- a/plugins/lua/lua_plugin.c +++ b/plugins/lua/lua_plugin.c @@ -126,7 +126,7 @@ static int uwsgi_api_signal(lua_State *L) { } static int uwsgi_api_log(lua_State *L) { - int16_t argc = lua_gettop(L); + int argc = lua_gettop(L); unsigned long point; int type; @@ -211,7 +211,7 @@ static int uwsgi_api_rpc_register_key(const char *key, size_t len) { int offset = uwsgi.mywid * uwsgi.rpc_max; for(i = 0; i < uwsgi.shared->rpc_count[uwsgi.mywid]; i++) { - if (!strncmp(key, (&uwsgi.rpc_table[offset + i])->name, len)) { + if (!strcmp(key, (&uwsgi.rpc_table[offset + i])->name)) { if ((&uwsgi.rpc_table[offset + i])->plugin == &lua_plugin) { return 1; } @@ -345,43 +345,6 @@ error: } -static int uwsgi_api_register_signal(lua_State *L) { - - int args = lua_gettop(L); - const char *who; - size_t len; - uint8_t sig; - - if (args < 3 || !(lua_isnumber(L, 1))) { // non number value gives us signal 0 from lua_tonumber() result - lua_pushnil(L); - return 1; - } - - sig = (uint8_t) lua_tonumber(L, 1); - who = lua_tolstring(L, 2, &len); - - if ((uwsgi.mywid == 0 && (&uwsgi.shared->signal_table[sig])->handler) // we are master and alredy registered? - || !(uwsgi_register_signal(sig, (char *)who, (void *)(1 /* unused */), 6))) { - - if (uwsgi.mywid > 0) { // signal router hax - uwsgi_lock(uwsgi.signal_table_lock); - strncpy((&uwsgi.shared->signal_table[sig])->receiver, who, len + 1); - uwsgi_unlock(uwsgi.signal_table_lock); - } - - lua_rawgeti(L, LUA_REGISTRYINDEX, ULUA_SIGNAL_REF); - - lua_pushvalue(L, 3); - lua_rawseti(L, -2, sig); - - lua_pushboolean(L, 1); - return 1; - } - - lua_pushnil(L); - return 1; -} - static int uwsgi_api_cache_clear(lua_State *L) { const char *cache = NULL; @@ -456,6 +419,199 @@ error: } + +static int uwsgi_api_register_signal(lua_State *L) { + + uint8_t args = lua_gettop(L); + uint8_t sig; + struct uwsgi_signal_entry *use; + const char *who; + size_t len; + int i; + + if(!(uwsgi.master_process)) { + ulua_log("no master, no signals"); + return 0; + } + + if (args < 1 || !(lua_isnumber(L, 1))) { + return 0; + } + + sig = (uint8_t) lua_tonumber(L, 1); + who = lua_tolstring(L, 2, &len); + use = &uwsgi.shared->signal_table[sig]; + + if (len == 0) { + who = (const char *) &len; // len is zero anyway + } else if (len > 63) { + ulua_log("receiver is too long: %s", who); + return 0; + } + + if (use->handler && use->modifier1 != 6) { + ulua_log("signal %s has already been taken, but not by lua-plugin", sig); + return 0; + } + + if (!(use->handler) || strcmp(use->receiver, who)) { + uwsgi_lock(uwsgi.signal_table_lock); + + strncpy(use->receiver, who, len + 1); + + if (!(use->handler)) { + use->handler = (void *) (1 /* unused */); + use->modifier1 = 6; + + if (uwsgi.mywid == 0) { + for(i = 1; i <= uwsgi.numproc; i++) { + use = &uwsgi.shared->signal_table[sig + i*256]; + use->handler = (void *) (1 /* unused */); + use->modifier1 = 6; + } + } + } + + uwsgi_unlock(uwsgi.signal_table_lock); + } + + if (uwsgi.mywid > 0) { + use = &uwsgi.shared->signal_table[sig + uwsgi.mywid*256]; + + if (use->modifier1 != 6) { + uwsgi_lock(uwsgi.signal_table_lock); + + use->handler = (void *) (1 /* unused */); + use->modifier1 = 6; + + uwsgi_unlock(uwsgi.signal_table_lock); + } + } + + if (args > 2) { + lua_rawgeti(L, LUA_REGISTRYINDEX, ULUA_SIGNAL_REF); + + lua_pushvalue(L, 3); + lua_rawseti(L, -2, sig); + } + + ulua_log("signum %d registered (by wid %d, target: %s)", sig, uwsgi.mywid, len != 0 ? who : "default"); + + lua_pushboolean(L, 1); + return 1; +} + +static int uwsgi_api_add_file_monitor(lua_State *L) { + uint8_t args = lua_gettop(L); + uint8_t sig; + const char *file; + size_t len; + + if (args < 2 || !(lua_isnumber(L, 1))) { + return 0; + } + + sig = (uint8_t) lua_tonumber(L, 1); + file = lua_tolstring(L, 2, &len); + + if (len == 0) { + return 0; + } + + if (!(uwsgi_add_file_monitor(sig, (char *) file))) { + lua_pushboolean(L, 1); + return 1; + } + + return 0; + +} + +static int uwsgi_api_signal_add_timer(lua_State *L) { + uint8_t args = lua_gettop(L); + uint8_t sig; + int secs; + + if (args < 2 || !(lua_isnumber(L, 1) && lua_isnumber(L, 2))) { + return 0; + } + + sig = (uint8_t) lua_tonumber(L, 1); + secs = lua_tonumber(L, 2); + + if (!(uwsgi_add_timer(sig, secs))) { + lua_pushboolean(L, 1); + return 1; + } + + return 0; +} + +static int uwsgi_api_signal_add_rb_timer(lua_State *L) { + uint8_t args = lua_gettop(L); + uint8_t sig; + int secs, itrs; + + if (args < 3 || !(lua_isnumber(L, 1) && lua_isnumber(L, 2) && lua_isnumber(L, 3))) { + return 0; + } + + sig = (uint8_t) lua_tonumber(L, 1); + secs = lua_tonumber(L, 2); + itrs = lua_tonumber(L, 3); + + if (!(uwsgi_signal_add_rb_timer(sig, secs, itrs))) { + lua_pushboolean(L, 1); + return 1; + } + + return 0; +} + +static int uwsgi_api_signal_add_cron(lua_State *L) { + int date[] = {-1, -1, -1, -1, -1}; + uint8_t args = lua_gettop(L); + int i; + + if (args < 1 || !(lua_isnumber(L, 1))) { + return 0; + } + + if (args > 6) args = 6; + + for (i = 2; i <= args; i++) { + if (lua_isnumber(L, i)) { + date[i-2] = lua_tonumber(L, i); + } + } + + if (!(uwsgi_signal_add_cron((uint8_t) lua_tonumber(L, 1), + date[0], date[1], date[2], date[3], date[4]))) + { + lua_pushboolean(L, 1); + return 1; + } + + return 0; +} + +static int uwsgi_api_alarm(lua_State *L) { + uint8_t args = lua_gettop(L); + const char *msg; + size_t len; + + if (args < 2 || !(lua_isstring(L, 1) && lua_isstring(L, 2))) { + return 0; + } + + msg = lua_tolstring(L, 2, &len); + + uwsgi_alarm_trigger((char *) lua_tostring(L, 1), (char *) msg, len); + + return 0; +} + + static int uwsgi_api_async_sleep(lua_State *L) { uint8_t argc = lua_gettop(L); if (argc == 0) goto end; @@ -830,9 +986,17 @@ static const luaL_Reg uwsgi_api[] = { {"cache_clear", uwsgi_api_cache_clear}, {"register_signal", uwsgi_api_register_signal}, + {"add_file_monitor", uwsgi_api_add_file_monitor}, + {"add_timer", uwsgi_api_signal_add_timer}, + {"add_rb_timer", uwsgi_api_signal_add_rb_timer}, + {"add_cron", uwsgi_api_signal_add_cron}, + {"alarm", uwsgi_api_alarm}, + {"register_rpc", uwsgi_api_register_rpc}, + {"rpc", uwsgi_api_rpc}, {"signal", uwsgi_api_signal}, + {"req_input_read", uwsgi_lua_input}, {"websocket_handshake", uwsgi_api_websocket_handshake}, @@ -994,11 +1158,11 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { lua_rawseti(L, LUA_REGISTRYINDEX, ULUA_WSAPI_REF); //init additional threads for current worker - if(cores > 0) { + if (cores > 0) { - lua_newtable(L); + lua_createtable(L, cores - 1, 0); - for(i=1;ivar_cnt + 2); + lua_pushstring(L, ""); lua_setfield(L, -2, "CONTENT_TYPE"); @@ -1074,7 +1239,7 @@ async_coroutine: } // put "input" table - lua_newtable(L); + lua_createtable(L, 0, 1); lua_pushcfunction(L, uwsgi_lua_input); lua_setfield(L, -2, "read"); lua_setfield(L, -2, "input"); From 377fc2d863abfb838397336c81178bb7dac6cc5b Mon Sep 17 00:00:00 2001 From: Hleran Date: Fri, 21 Aug 2015 01:25:12 +0300 Subject: [PATCH 07/17] lua_plugin: metric, cache, fixes, cleanups --- plugins/lua/lua_plugin.c | 906 +++++++++++++++++++++++++++++---------- 1 file changed, 675 insertions(+), 231 deletions(-) diff --git a/plugins/lua/lua_plugin.c b/plugins/lua/lua_plugin.c index 831f19b1..862a6b22 100644 --- a/plugins/lua/lua_plugin.c +++ b/plugins/lua/lua_plugin.c @@ -15,9 +15,11 @@ extern struct uwsgi_server uwsgi; struct uwsgi_lua { struct lua_State ***state; - char *shell; - char *filename; + uint8_t shell; + uint8_t shell_oneshot; struct uwsgi_string_list *load; + char *filename; + struct uwsgi_string_list *postload; int gc_freq; int gc_full; } ulua; @@ -30,29 +32,37 @@ struct uwsgi_lua { #define ULUA_RPC_REF 2 #define ULUA_SIGNAL_REF 3 +#define ULUA_METRIC_INC 1 +#define ULUA_METRIC_DIV 2 +#define ULUA_METRIC_MUL 3 +#define ULUA_METRIC_DEC 4 + #define ulua_log(c, ar...) uwsgi_log(ULUA_LOG_HEADER" "c"\n", ##ar) struct uwsgi_plugin lua_plugin; static void uwsgi_opt_luashell(char *opt, char *value, void *foobar) { - - uwsgi.honour_stdin = 1; - if (value) { - ulua.shell = value; - } - else { - ulua.shell = ""; - } + uwsgi.honour_stdin = 1; + ulua.shell = 1; } +static void uwsgi_opt_luashell_oneshot(char *opt, char *value, void *foobar) { + // enable shell + uwsgi_opt_luashell(NULL, NULL, NULL); + + ulua.shell_oneshot = 1; +} static struct uwsgi_option uwsgi_lua_options[] = { {"lua", required_argument, 0, "load lua wsapi app", uwsgi_opt_set_str, &ulua.filename, 0}, - {"lua-load", required_argument, 0, "load a lua file", uwsgi_opt_add_string_list, &ulua.load, 0}, + {"lua-load", required_argument, 0, "load a lua file before wsapi app", uwsgi_opt_add_string_list, &ulua.load, 0}, + {"lua-postload", required_argument, 0, "load a lua file after wsapi app", uwsgi_opt_add_string_list, &ulua.postload, 0}, {"lua-shell", no_argument, 0, "run the lua interactive shell (debug.debug())", uwsgi_opt_luashell, NULL, 0}, {"luashell", no_argument, 0, "run the lua interactive shell (debug.debug())", uwsgi_opt_luashell, NULL, 0}, - {"lua-gc-freq", no_argument, 0, "set the lua gc frequency (default: 0, runs after every request)", uwsgi_opt_set_int, &ulua.gc_freq, 0}, + {"lua-shell-oneshot", no_argument, 0, "run the lua interactive shell (debug.debug(), one-shot variant)", uwsgi_opt_luashell_oneshot, NULL, 0}, + {"luashell-oneshot", no_argument, 0, "run the lua interactive shell (debug.debug(), one-shot variant)", uwsgi_opt_luashell_oneshot, NULL, 0}, + {"lua-gc-freq", required_argument, 0, "set the lua gc frequency (default: 1, runs after every request)", uwsgi_opt_set_int, &ulua.gc_freq, 0}, {"lua-gc-full", no_argument, 0, "set the lua gc to perform a full garbage-collection cycle (default: 0, gc performs an incremental step of garbage collection)", uwsgi_opt_set_int, &ulua.gc_full, 0}, {0, 0, 0, 0}, @@ -74,7 +84,7 @@ static int uwsgi_lua_metatable_tostring(lua_State *L, int obj) { lua_pushvalue(L, --obj); - if (lua_pcall(L, 1, 1, 0) != 0) { + if (lua_pcall(L, 1, 1, 0)) { ulua_log("%s", lua_tostring(L, -1)); lua_pop(L, 1); return 0; @@ -109,6 +119,82 @@ static int uwsgi_lua_metatable_call(lua_State *L, int obj) { return 1; } +static int uwsgi_api_metric_get(lua_State *L) { + + if (!(lua_gettop(L)) || !(lua_isstring(L, 1))) { + return 0; + } + + lua_pushnumber(L, uwsgi_metric_get((char *) lua_tostring(L, 1), NULL)); + + return 1; +} + +static int uwsgi_api_metric_set(lua_State *L) { + + if ((lua_gettop(L) < 2) || + !(lua_isstring(L, 1)) || + !(lua_isnumber(L, 2)) || + uwsgi_metric_set((char *) lua_tostring(L, 1), NULL, lua_tonumber(L, 2))) + { + return 0; + } + + lua_pushboolean(L, 1); + + return 1; +} + +static int uwsgi_lua_metric_op(lua_State *L, uint8_t op) { + int64_t value = 1; + uint8_t argc = lua_gettop(L); + + int code = -1; + char *name; + + if (!(argc) || !(lua_isstring(L, 1))) { + return 0; + } + + if (argc > 1 && lua_isnumber(L, 2)) { + value = lua_tonumber(L, 2); + } + + name = (char *) lua_tostring(L, 1); + + switch(op) { + case ULUA_METRIC_INC: code = uwsgi_metric_inc(name, NULL, value); break; + case ULUA_METRIC_DIV: code = uwsgi_metric_div(name, NULL, value); break; + case ULUA_METRIC_MUL: code = uwsgi_metric_mul(name, NULL, value); break; + case ULUA_METRIC_DEC: code = uwsgi_metric_dec(name, NULL, value); break; + } + + if (code) { + return 0; + } + + lua_pushboolean(L, 1); + + return 1; +} + +static int uwsgi_api_metric_inc(lua_State *L) { + return uwsgi_lua_metric_op(L, ULUA_METRIC_INC); +} + +static int uwsgi_api_metric_div(lua_State *L) { + return uwsgi_lua_metric_op(L, ULUA_METRIC_DIV); +} + +static int uwsgi_api_metric_mul(lua_State *L) { + return uwsgi_lua_metric_op(L, ULUA_METRIC_MUL); +} + +static int uwsgi_api_metric_dec(lua_State *L) { + return uwsgi_lua_metric_op(L, ULUA_METRIC_DEC); +} + + static int uwsgi_api_signal(lua_State *L) { uint8_t argc = lua_gettop(L); @@ -126,7 +212,8 @@ static int uwsgi_api_signal(lua_State *L) { } static int uwsgi_api_log(lua_State *L) { - int argc = lua_gettop(L); + uint8_t argc = lua_gettop(L); + uint8_t i; unsigned long point; int type; @@ -136,20 +223,20 @@ static int uwsgi_api_log(lua_State *L) { uwsgi_log(ULUA_LOG_HEADER); - for(argc = -argc; argc < 0; argc++) { - type = lua_type(L, argc); + for(i = 1; i <= argc; i++) { + type = lua_type(L, i); switch(type) { case LUA_TNIL: uwsgi_log(" nil"); continue; - case LUA_TBOOLEAN: uwsgi_log(lua_toboolean(L, argc) ? " true" : " false"); continue; + case LUA_TBOOLEAN: uwsgi_log(lua_toboolean(L, i) ? " true" : " false"); continue; - case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, argc))) break; - case LUA_TNUMBER: - case LUA_TSTRING: uwsgi_log(" %s", lua_tostring(L, argc)); continue; + case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, i - argc - 1))) break; + case LUA_TSTRING: + case LUA_TNUMBER: uwsgi_log(" %s", lua_tostring(L, i)); continue; } - point = (unsigned long) (lua_topointer(L, argc)); + point = (unsigned long) (lua_topointer(L, i)); if (point) { uwsgi_log(" %s: 0x%.8x", lua_typename(L, type), point); @@ -164,29 +251,39 @@ static int uwsgi_api_log(lua_State *L) { } static int uwsgi_api_rpc(lua_State *L) { + uint8_t argc = lua_gettop(L); + uint8_t argnum; + uint8_t i; + uint64_t len; if (argc < 2) { return 0; } - argc-=2; + argnum = argc - 2; char **argv = NULL; uint16_t *argvs = NULL; - if (argc > 0) { - uint8_t i; - argv = (char **) uwsgi_malloc(sizeof(char *)*argc); - argvs = (uint16_t *) uwsgi_malloc(sizeof(uint16_t)*argc); + if (argnum > 0) { + argv = (char **) uwsgi_malloc(sizeof(char *)*argnum); + argvs = (uint16_t *) uwsgi_malloc(sizeof(uint16_t)*argnum); - for(i = 0; i < argc; i++) { - argv[i] = (char *) lua_tolstring(L, i + 3, (size_t *) &argvs[i]); + for(i = 0; i < argnum; i++) { + switch(lua_type(L, i + 3)) { + case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, i + 2 - argc))) break; + case LUA_TSTRING: + case LUA_TNUMBER: argv[i] = (char *) lua_tolstring(L, i + 3, (size_t *) &argvs[i]); continue; + } + + // default + argv[i] = NULL; + argvs[i] = 0; } } - uint64_t len; - char *str = uwsgi_do_rpc((char *) lua_tostring(L, 1), (char *) lua_tostring(L, 2), argc, argv, argvs, &len); + char *str = uwsgi_do_rpc((char *) lua_tostring(L, 1), (char *) lua_tostring(L, 2), argnum, argv, argvs, &len); if (!(len)) { // fail?? lua_pushnil(L); @@ -280,145 +377,370 @@ static int uwsgi_api_register_rpc_newindex(lua_State *L) { return 0; } -static int uwsgi_api_cache_set(lua_State *L) { - +static int uwsgi_lua_cache_set(lua_State *L, uint8_t flag) { + uint8_t argc = lua_gettop(L); - const char *key ; - const char *value ; + + char *cache = NULL; uint64_t expires = 0; - size_t vallen; + + char *key; size_t keylen; - const char *cache = NULL; - - if (argc < 2) goto error; - - key = lua_tolstring(L, 1, &keylen); - value = lua_tolstring(L, 2, &vallen); + + char *value = NULL; + size_t valuelen = 0; + + if (argc < 2) { + return 0; + } + + // key + key = (char *) lua_tolstring(L, 1, &keylen); + + // value + switch(lua_type(L, 2)) { + case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, -argc + 1))) break; + case LUA_TSTRING: + case LUA_TNUMBER: value = (char *) lua_tolstring(L, 2, &valuelen); + } + if (argc > 2) { expires = lua_tonumber(L, 3); if (argc > 3) { - cache = lua_tostring(L, 4); + cache = (char *) lua_tostring(L, 4); } } - - if (!uwsgi_cache_magic_set((char *)key, keylen, (char *)value, vallen, expires, 0, (char *) cache)) { + + if (!uwsgi_cache_magic_set(key, keylen, value, valuelen, expires, flag, cache)) { lua_pushboolean(L, 1); return 1; } -error: - - lua_pushnil(L); - return 1; + + return 0; +} +static int uwsgi_api_cache_set(lua_State *L) { + return uwsgi_lua_cache_set(L, 0); } static int uwsgi_api_cache_update(lua_State *L) { + return uwsgi_lua_cache_set(L, UWSGI_CACHE_FLAG_UPDATE); +} - uint8_t argc = lua_gettop(L); - const char *key ; - const char *value ; - uint64_t expires = 0; - size_t vallen; - size_t keylen; - const char *cache = NULL; +static int uwsgi_lua_cache_set_table(lua_State *L, uint8_t flag) { + + uint8_t argc = lua_gettop(L); + uint8_t error = 0; + + char *cache = NULL; + uint64_t expires = 0; + + char *key; + size_t keylen; + + char *value = NULL; + size_t valuelen = 0; + + if (argc < 1 || !lua_istable(L, 1)) { + return 0; + } + + if (argc > 1) { + expires = lua_tonumber(L, 2); + if (argc > 2) { + cache = (char *) lua_tostring(L, 3); + } + } + + lua_pushnil(L); + + while(lua_next(L, 1)) { + lua_pushvalue(L, -2); + + //key + key = (char *) lua_tolstring(L, -1, &keylen); + + //value + switch(lua_type(L, -2)) { + case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, -2))) break; + case LUA_TSTRING: + case LUA_TNUMBER: value = (char *) lua_tolstring(L, -2, &valuelen); + } + + if (uwsgi_cache_magic_set(key, keylen, value, valuelen, expires, flag, cache)) { + lua_pop(L, 2); + lua_pushvalue(L, -1); + ++error; + } else { + lua_pop(L, 2); + } + } + + if (!error) { + lua_pushboolean(L, 1); + return 1; + } + + lua_pushnumber(L, error); + lua_insert(L, -(++error)); + + lua_pushnil(L); + lua_insert(L, -(++error)); - if (argc < 2) goto error; + return error; + +} - key = lua_tolstring(L, 1, &keylen); - value = lua_tolstring(L, 2, &vallen); - if (argc > 2) { - expires = lua_tonumber(L, 3); - if (argc > 3) { - cache = lua_tostring(L, 4); - } - } +static int uwsgi_api_cache_set_table(lua_State *L) { + return uwsgi_lua_cache_set_table(L, 0); +} - if (!uwsgi_cache_magic_set((char *)key, keylen, (char *)value, vallen, expires, UWSGI_CACHE_FLAG_UPDATE, (char *)cache)) { - lua_pushboolean(L, 1); - return 1; - } -error: +static int uwsgi_api_cache_update_table(lua_State *L) { + return uwsgi_lua_cache_set_table(L, UWSGI_CACHE_FLAG_UPDATE); +} - lua_pushnil(L); - return 1; +static int uwsgi_lua_cache_set_multi(lua_State *L, uint8_t flag) { + + uint8_t argc = lua_gettop(L); + uint8_t error = 0; + uint8_t i; + + char *cache; + uint64_t expires; + + char *key; + size_t keylen; + + char *value = NULL; + size_t valuelen = 0; + + if (argc < 4) { + return 0; + } + + expires = lua_tonumber(L, 1); + cache = (char *) lua_tostring(L, 2); + + for (i = 4; i <= argc; i+=2) { + // key + key = (char *) lua_tolstring(L, i - 1, &keylen); + + // value + switch(lua_type(L, i)) { + case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, i - argc - 1 - error))) break; + case LUA_TSTRING: + case LUA_TNUMBER: value = (char *) lua_tolstring(L, i, &valuelen); + } + + if (uwsgi_cache_magic_set(key, keylen, value, valuelen, expires, flag, cache)) { + lua_pushnumber(L, ++error); + } + } + + if(!error) { + lua_pushboolean(L, 1); + return 1; + } + + lua_pushnil(L); + lua_insert(L, -(++error)); + + return error; +} + +static int uwsgi_api_cache_set_multi(lua_State *L) { + return uwsgi_lua_cache_set_multi(L, 0); +} + +static int uwsgi_api_cache_update_multi(lua_State *L) { + return uwsgi_lua_cache_set_multi(L, UWSGI_CACHE_FLAG_UPDATE); } static int uwsgi_api_cache_clear(lua_State *L) { - const char *cache = NULL; - uint8_t argc = lua_gettop(L); + char *cache = NULL; + uint8_t argc = lua_gettop(L); - if (argc > 0) { - cache = lua_tostring(L, 2); - } - if (!uwsgi_cache_magic_clear((char *)cache)) { - lua_pushboolean(L, 1); - return 1; - } - - lua_pushnil(L); - return 1; + if (argc > 0) { + cache = (char *) lua_tostring(L, 1); + } + + if (!uwsgi_cache_magic_clear(cache)) { + lua_pushboolean(L, 1); + return 1; + } + return 0; } static int uwsgi_api_cache_del(lua_State *L) { - size_t keylen; - const char *key ; - const char *cache = NULL; - uint8_t argc = lua_gettop(L); + size_t keylen; + char *key; + char *cache = NULL; + uint8_t argc = lua_gettop(L); - if (argc == 0) goto error; - - if (lua_isstring(L, 1)) { - // get the key - key = lua_tolstring(L, 1, &keylen); - if (argc > 1) { - cache = lua_tostring(L, 2); - } - if (!uwsgi_cache_magic_del((char *)key, keylen, (char *)cache)) { - lua_pushboolean(L, 1); - return 1; - } - } - -error: - lua_pushnil(L); - return 1; + if (!(argc)) { + return 0; + } + // get the key + key = (char *) lua_tolstring(L, 1, &keylen); + + if (argc > 1) { + cache = (char *) lua_tostring(L, 2); + } + + if (keylen && !uwsgi_cache_magic_del(key, keylen, cache)) { + lua_pushboolean(L, 1); + return 1; + } + + return 0; } +static int uwsgi_api_cache_del_multi(lua_State *L) { + + size_t keylen; + char *key; + char *cache; + uint8_t argc = lua_gettop(L); + uint8_t error = 0; + uint8_t i; + + if (argc < 1) { + return 0; + } + + cache = (char *) lua_tostring(L, 1); + + for (i = 2; i <= argc; i++) { + key = (char *) lua_tolstring(L, i, &keylen); + + if (!keylen || uwsgi_cache_magic_del(key, keylen, cache)) { + lua_pushnumber(L, ++error); + } + } + + if (!error) { + lua_pushboolean(L, 1); + return 1; + } + + lua_pushnil(L); + lua_insert(L, -(++error)); + + return error; +} static int uwsgi_api_cache_exists(lua_State *L) { - size_t keylen; - const char *key ; - const char *cache = NULL; - uint8_t argc = lua_gettop(L); + size_t keylen; + char *key; + char *cache = NULL; + uint8_t argc = lua_gettop(L); - if (argc == 0) goto error; + if (argc < 1) { + return 0; + } - if (lua_isstring(L, 1)) { - // get the key - key = lua_tolstring(L, 1, &keylen); - if (argc > 1) { - cache = lua_tostring(L, 2); - } - if (uwsgi_cache_magic_exists((char *)key, keylen,(char *)cache)) { - lua_pushboolean(L, 1); - return 1; - } - } + // get the key + key = (char *) lua_tolstring(L, 1, &keylen); + + if (argc > 1) { + cache = (char *) lua_tostring(L, 2); + } -error: - lua_pushnil(L); - return 1; + lua_pushboolean(L, keylen && uwsgi_cache_magic_exists(key, keylen, cache)); + return 1; } +static int uwsgi_api_cache_exists_multi(lua_State *L) { + + size_t keylen; + char *key; + char *cache; + uint8_t argc = lua_gettop(L); + uint8_t i; + + if (argc < 2) { + return 0; + } + + cache = (char *) lua_tostring(L, 1); + + for (i = 2; i <= argc; i++) { + + key = (char *) lua_tolstring(L, i, &keylen); + lua_pushboolean(L, keylen && uwsgi_cache_magic_exists(key, keylen, cache)); + + } + + return argc - 1; +} + + +static int uwsgi_api_signal_wait(lua_State *L) { + + struct wsgi_request *wsgi_req = current_wsgi_req(); + uint8_t args = lua_gettop(L); + int received_signal; + + wsgi_req->signal_received = -1; + + if (args > 0 && lua_isnumber(L, 1)) { + received_signal = uwsgi_signal_wait(wsgi_req, lua_tonumber(L, 1)); + } else { + received_signal = uwsgi_signal_wait(wsgi_req, -1); + } + + if (received_signal < 0) { + lua_pushnil(L); + } else { + wsgi_req->signal_received = received_signal; + lua_pushnumber(L, received_signal); + } + + return 1; +} + +static int uwsgi_api_signal_received(lua_State *L) { + + struct wsgi_request *wsgi_req = current_wsgi_req(); + + lua_pushnumber(L, wsgi_req->signal_received); + + return 1; +} + +static int uwsgi_api_signal_registered(lua_State *L) { + + uint8_t args = lua_gettop(L); + struct uwsgi_signal_entry *use; + uint8_t sig; + + if (args < 1 || !(lua_isnumber(L, 1))) { + return 0; + } + + sig = (uint8_t) lua_tonumber(L, 1); + use = &uwsgi.shared->signal_table[sig]; + + lua_pushboolean(L, use->handler ? 1 : 0); + lua_pushstring(L, use->receiver); + + if (uwsgi.mywid > 0) { + use = &uwsgi.shared->signal_table[sig + uwsgi.mywid*256]; + } + + lua_pushnumber(L, use->modifier1); + + return 3; +} static int uwsgi_api_register_signal(lua_State *L) { @@ -442,7 +764,7 @@ static int uwsgi_api_register_signal(lua_State *L) { who = lua_tolstring(L, 2, &len); use = &uwsgi.shared->signal_table[sig]; - if (len == 0) { + if (!len) { who = (const char *) &len; // len is zero anyway } else if (len > 63) { ulua_log("receiver is too long: %s", who); @@ -451,13 +773,14 @@ static int uwsgi_api_register_signal(lua_State *L) { if (use->handler && use->modifier1 != 6) { ulua_log("signal %s has already been taken, but not by lua-plugin", sig); - return 0; } + // register signal's receiver on master + // copy handlers and modifiers if calling from mywid == 0 if (!(use->handler) || strcmp(use->receiver, who)) { uwsgi_lock(uwsgi.signal_table_lock); - strncpy(use->receiver, who, len + 1); + strcpy(use->receiver, who); if (!(use->handler)) { use->handler = (void *) (1 /* unused */); @@ -475,6 +798,7 @@ static int uwsgi_api_register_signal(lua_State *L) { uwsgi_unlock(uwsgi.signal_table_lock); } + // worker, just register handler and modifier1 if (uwsgi.mywid > 0) { use = &uwsgi.shared->signal_table[sig + uwsgi.mywid*256]; @@ -487,7 +811,7 @@ static int uwsgi_api_register_signal(lua_State *L) { uwsgi_unlock(uwsgi.signal_table_lock); } } - + if (args > 2) { lua_rawgeti(L, LUA_REGISTRYINDEX, ULUA_SIGNAL_REF); @@ -495,7 +819,7 @@ static int uwsgi_api_register_signal(lua_State *L) { lua_rawseti(L, -2, sig); } - ulua_log("signum %d registered (by wid %d, target: %s)", sig, uwsgi.mywid, len != 0 ? who : "default"); + ulua_log("signum %d registered (by wid %d, target: %s)", sig, uwsgi.mywid, len ? who : "default"); lua_pushboolean(L, 1); return 1; @@ -514,7 +838,7 @@ static int uwsgi_api_add_file_monitor(lua_State *L) { sig = (uint8_t) lua_tonumber(L, 1); file = lua_tolstring(L, 2, &len); - if (len == 0) { + if (!len) { return 0; } @@ -859,35 +1183,75 @@ static int uwsgi_api_websocket_recv_nb(lua_State *L) { static int uwsgi_api_cache_get(lua_State *L) { - char *value ; - uint64_t valsize; + char *value; + uint64_t valsize; size_t keylen; - const char *key ; - const char *cache = NULL; + char *key; + char *cache = NULL; uint8_t argc = lua_gettop(L); if (argc == 0) goto error; - if (lua_isstring(L, 1)) { - // get the key - key = lua_tolstring(L, 1, &keylen); - if (argc > 1) { - cache = lua_tostring(L, 2); - } - value = uwsgi_cache_magic_get((char *)key, keylen, &valsize, NULL, (char *)cache); - if (value) { - lua_pushlstring(L, value, valsize); - free(value); - return 1; - } + // get the key + key = (char *) lua_tolstring(L, 1, &keylen); + + if (argc > 1) { + cache = (char *) lua_tostring(L, 2); + } + + if (!keylen) goto error; + + value = uwsgi_cache_magic_get(key, keylen, &valsize, NULL, cache); + + if (value) { + lua_pushlstring(L, value, valsize); + free(value); + return 1; } error: lua_pushnil(L); - return 1; + return 1; } +static int uwsgi_api_cache_get_multi(lua_State *L) { + + char *value ; + uint64_t valsize; + size_t keylen; + char *key; + char *cache; + + uint8_t argc = lua_gettop(L); + uint8_t i; + + if (argc < 2) { + return 0; + } + + cache = (char *) lua_tostring(L, 1); + + for (i = 2; i <= argc; i++) { + + value = NULL; + key = (char *) lua_tolstring(L, i, &keylen); + + if (keylen) { + value = uwsgi_cache_magic_get(key, keylen, &valsize, NULL, cache); + } + + if (value) { + lua_pushlstring(L, value, valsize); + free(value); + } else { + lua_pushnil(L); + } + } + + return argc - 1; +} + static int uwsgi_api_req_fd(lua_State *L) { struct wsgi_request *wsgi_req = current_wsgi_req(); @@ -965,6 +1329,7 @@ static int uwsgi_lua_input(lua_State *L) { return 0; } + static int uwsgi_api_async_id_get(lua_State *L) { struct wsgi_request *wsgi_req = current_wsgi_req(); @@ -974,30 +1339,81 @@ static int uwsgi_api_async_id_get(lua_State *L) { return 1; } +static int uwsgi_api_memory_usage(lua_State *L) { + + uint64_t rss = 0; + uint64_t vsz = 0; + + get_memusage(&rss, &vsz); + + lua_pushnumber(L, rss); + lua_pushnumber(L, vsz); + + return 2; +} + +static int uwsgi_api_pid(lua_State *L) { + + int id = 0; + + if (lua_gettop(L) > 0) { + id = lua_tonumber(L, 1); + } + + if (id <= uwsgi.numproc) { + lua_pushnumber(L, uwsgi.workers[id].pid); + return 1; + } + + return 0; + +} + static const luaL_Reg uwsgi_api[] = { {"log", uwsgi_api_log}, {"connection_fd", uwsgi_api_req_fd}, + {"metric_get", uwsgi_api_metric_get}, + {"metric_set", uwsgi_api_metric_set}, + {"metric_inc", uwsgi_api_metric_inc}, + {"metric_div", uwsgi_api_metric_div}, + {"metric_mul", uwsgi_api_metric_mul}, + {"metric_dec", uwsgi_api_metric_dec}, + {"cache_get", uwsgi_api_cache_get}, + {"cache_get_multi", uwsgi_api_cache_get_multi}, {"cache_set", uwsgi_api_cache_set}, + {"cache_set_table", uwsgi_api_cache_set_table}, + {"cache_set_multi", uwsgi_api_cache_set_multi}, {"cache_update", uwsgi_api_cache_update}, + {"cache_update_table", uwsgi_api_cache_update_table}, + {"cache_update_multi", uwsgi_api_cache_update_multi}, {"cache_del", uwsgi_api_cache_del}, + {"cache_del_multi", uwsgi_api_cache_del_multi}, {"cache_exists", uwsgi_api_cache_exists}, + {"cache_exists_multi", uwsgi_api_cache_exists_multi}, {"cache_clear", uwsgi_api_cache_clear}, {"register_signal", uwsgi_api_register_signal}, + {"signal_registered", uwsgi_api_signal_registered}, + {"signal_wait", uwsgi_api_signal_wait}, + {"signal_received", uwsgi_api_signal_received}, {"add_file_monitor", uwsgi_api_add_file_monitor}, {"add_timer", uwsgi_api_signal_add_timer}, {"add_rb_timer", uwsgi_api_signal_add_rb_timer}, {"add_cron", uwsgi_api_signal_add_cron}, + {"alarm", uwsgi_api_alarm}, {"register_rpc", uwsgi_api_register_rpc}, - + {"rpc", uwsgi_api_rpc}, {"signal", uwsgi_api_signal}, {"req_input_read", uwsgi_lua_input}, + + {"mem", uwsgi_api_memory_usage}, + {"pid", uwsgi_api_pid}, {"websocket_handshake", uwsgi_api_websocket_handshake}, {"websocket_recv", uwsgi_api_websocket_recv}, @@ -1036,7 +1452,7 @@ static int uwsgi_lua_init(){ uwsgi_log("%d lua_States (with %d lua_Threads)\n", uwsgi.numproc, uwsgi.cores); - if(ulua.gc_full == 0) { + if(!(ulua.gc_full)) { ulua.gc_full = LUA_GCSTEP; } else { ulua.gc_full = LUA_GCCOLLECT; @@ -1079,7 +1495,7 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { // rpc metatable ref 2 lua_newtable(L); - lua_newtable(L); + lua_createtable(L, 0, 1); lua_pushcfunction(L, uwsgi_api_register_rpc_newindex); lua_setfield(L, -2, "__newindex"); lua_setmetatable(L, -2); @@ -1099,6 +1515,7 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { uslnargs = lua_gettop(L); struct uwsgi_string_list *usl = ulua.load; + while(usl) { if (luaL_dofile(L, usl->value)) { ulua_log("unable to load Lua file %s: %s", usl->value, lua_tostring(L, -1)); @@ -1112,13 +1529,15 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { if (ulua.filename) { if (luaL_loadfile(L, ulua.filename)) { ulua_log("unable to load Lua file %s: %s", ulua.filename, lua_tostring(L, -1)); - lua_pop(L, 1); + lua_pop(L, uslnargs + 1); + uslnargs = 0; } else { + // put function before args if (uslnargs > 0) { - lua_insert(L, -uslnargs-1); + lua_insert(L, -uslnargs - 1); } - if (lua_pcall(L, uslnargs, 1, 0) != 0) { + if (lua_pcall(L, uslnargs, 1, 0)) { ulua_log("%s", lua_tostring(L, -1)); lua_pop(L, 1); uslnargs = 0; @@ -1126,31 +1545,22 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { uslnargs = 1; } } - } - - //we need only one, the last one - if (uslnargs > 1) { - lua_replace(L, -uslnargs); - - if (uslnargs > 2) { - lua_pop(L, uslnargs - 2); - } + } else { + lua_pop(L, uslnargs); + uslnargs = 0; } // table ?? - if (lua_istable(L, -1)) { + if (uslnargs > 0 && lua_istable(L, -1)) { lua_pushstring(L, "run"); lua_gettable(L, -1); lua_replace(L, -1); } // no app ??? - if (uslnargs == 0 || !lua_isfunction(L, -1)) { + if (!uslnargs || !lua_isfunction(L, -1)) { // loading dummy - if (uslnargs > 0) { - lua_pop(L, uslnargs); - } - + lua_pop(L, uslnargs); ulua_log("Can't find WSAPI entry point (no function, nor a table with function'run')."); lua_pushcfunction(L, uwsgi_lua_dummy_response); } @@ -1159,7 +1569,7 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { //init additional threads for current worker if (cores > 0) { - + lua_createtable(L, cores - 1, 0); for(i = 1; i < cores; i++) { @@ -1173,12 +1583,21 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { lua_setfield(L, -2, "luathreads"); } - // and the worker is ready! lua_pop(L, 1); + // post load + usl = ulua.postload; + + while(usl) { + if (luaL_loadfile(L, usl->value) || lua_pcall(L, 0, 0, 0)) { + ulua_log("unable to load Lua file %s: %s", usl->value, lua_tostring(L, -1)); + lua_pop(L, 1); + } + usl = usl->next; + } + + // and the worker is ready! lua_gc(L, LUA_GCCOLLECT, 0); - - ulua_log("inited lua_State %d for worker %d", sid, wid); } static int uwsgi_lua_request(struct wsgi_request *wsgi_req) { @@ -1195,7 +1614,7 @@ static int uwsgi_lua_request(struct wsgi_request *wsgi_req) { if (wsgi_req->async_status == UWSGI_AGAIN) { async_coroutine: - while (lua_pcall(L, 0, 1, 0) == 0) { + while (!lua_pcall(L, 0, 1, 0)) { switch(lua_type(L, -1)) { case LUA_TNIL: // posible dead coroutine @@ -1204,8 +1623,8 @@ async_coroutine: continue; // retry case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, -1))) break; - case LUA_TNUMBER: case LUA_TSTRING: + case LUA_TNUMBER: http = lua_tolstring(L, -1, &slen); uwsgi_response_write_body_do(wsgi_req, (char *)http, slen); @@ -1250,7 +1669,7 @@ async_coroutine: #endif // call function - if (lua_pcall(L, 1, 3, 0) != 0) { + if (lua_pcall(L, 1, 3, 0)) { ulua_log("%s", lua_tostring(L, -1)); lua_pop(L, 1); goto clear2; @@ -1263,14 +1682,9 @@ async_coroutine: // send status http = lua_tolstring(L, -3, &slen); - if (!(slen)) { + if (uwsgi_response_prepare_headers(wsgi_req, (char *) http, slen)) { ulua_log("invalid response status!!!"); // let's continue - } else { - if (uwsgi_response_prepare_headers(wsgi_req, (char *) http, slen)) { - lua_pop(L, 3); - goto clear2; - } } // send headers @@ -1278,14 +1692,18 @@ async_coroutine: lua_pushnil(L); - while(lua_next(L, -3) != 0) { - http = lua_tolstring(L, -2, &slen); + while(lua_next(L, -3)) { + + // lua_tolstring may change the 'lua_next' sequence, if the key is not a string, by modifying it + lua_pushvalue(L, -2); + // so -1 is key, -2 is value + http = lua_tolstring(L, -1, &slen); - if (lua_istable(L, -1)) { - tlen = lua_rawlen(L, -1); + if (lua_istable(L, -2)) { + tlen = lua_rawlen(L, -2); for (i = 1; i <= tlen; i++) { - lua_rawgeti(L, -1, i); + lua_rawgeti(L, -2, i); http2 = lua_tolstring(L, -1, &slen2); uwsgi_response_add_header(wsgi_req, (char *) http, slen, (char *) http2, slen2); @@ -1295,11 +1713,11 @@ async_coroutine: } else { - http2 = lua_tolstring(L, -1, &slen2); + http2 = lua_tolstring(L, -2, &slen2); uwsgi_response_add_header(wsgi_req, (char *) http, slen, (char *) http2, slen2); } - lua_pop(L, 1); + lua_pop(L, 2); } } @@ -1313,11 +1731,11 @@ async_coroutine: goto async_coroutine; } - while (lua_pcall(L, 0, 1, 0) == 0) { + while (!lua_pcall(L, 0, 1, 0)) { switch(lua_type(L, -1)) { case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, -1))) break; - case LUA_TNUMBER: case LUA_TSTRING: + case LUA_TNUMBER: http = lua_tolstring(L, -1, &slen); uwsgi_response_write_body_do(wsgi_req, (char *) http, slen); @@ -1330,8 +1748,8 @@ async_coroutine: break; case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, -1))) break; - case LUA_TNUMBER: case LUA_TSTRING: + case LUA_TNUMBER: http = lua_tolstring(L, -1, &slen); uwsgi_response_write_body_do(wsgi_req, (char *) http, slen); @@ -1341,9 +1759,10 @@ clear: lua_pop(L, 4); clear2: // set frequency - if (!ulua.gc_freq || + if (ulua.gc_freq && (ulua.gc_freq == 1 || (uwsgi.threads == 1 && uwsgi.workers[uwsgi.mywid].requests % ulua.gc_freq == 0) || - (uwsgi.threads > 1 && uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].requests % ulua.gc_freq == 0)) { + (uwsgi.threads > 1 && uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].requests % ulua.gc_freq == 0))) + { lua_gc(L, ulua.gc_full, 0); } @@ -1359,15 +1778,13 @@ static void uwsgi_lua_after_request(struct wsgi_request *wsgi_req) { static int uwsgi_lua_magic(char *mountpoint, char *lazy) { - if (!strcmp(lazy+strlen(lazy)-4, ".lua")) { - ulua.filename = lazy; - return 1; - } - else if (!strcmp(lazy+strlen(lazy)-3, ".ws")) { - ulua.filename = lazy; - return 1; - } - + if( !strcmp(lazy+strlen(lazy)-4, ".lua") || + !strcmp(lazy+strlen(lazy)-5, ".luac") || + !strcmp(lazy+strlen(lazy)-3, ".ws")) + { + ulua.filename = lazy; + return 1; + } return 0; } @@ -1405,7 +1822,7 @@ static char *uwsgi_lua_code_string(char *id, char *code, char *func, char *key, ulua_log("stack pos %d %.*s", lua_gettop(L), keylen, key); #endif - if (lua_pcall(L, 1, 1, 0) != 0) { + if (lua_pcall(L, 1, 1, 0)) { ulua_log("error running function `f': %s", lua_tostring(L, -1)); return NULL; @@ -1443,7 +1860,7 @@ static int uwsgi_lua_signal_handler(uint8_t sig, void *handler) { lua_pushnumber(L, sig); - if (lua_pcall(L, 1 + (type == LUA_TTABLE), 1, 0) != 0) { + if (lua_pcall(L, 1 + (type == LUA_TTABLE), 1, 0)) { ulua_log("signal: error running function `f': %s", lua_tostring(L, -1)); lua_pop(L, 2); @@ -1457,8 +1874,8 @@ static int uwsgi_lua_signal_handler(uint8_t sig, void *handler) { static uint64_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) { uint8_t i; - const char *sv; - size_t sl; + const char *sv = NULL; + size_t sl = 0; int type; struct wsgi_request *wsgi_req = current_wsgi_req(); @@ -1480,18 +1897,18 @@ static uint64_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t a for(i = 0; i < argc; i++) { lua_pushlstring(L, argv[i], argvs[i]); } - - if (type == LUA_TTABLE) { - ++argc; //table is the first arg - } - if (lua_pcall(L, argc, 1, 0) != 0) { + if (lua_pcall(L, argc + (type == LUA_TTABLE), 1, 0)) { ulua_log("rpc: error running function `f': %s", lua_tostring(L, -1)); lua_pop(L, 2); return 0; } - sv = lua_tolstring(L, -1, &sl); + switch(lua_type(L, -1)) { + case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, -1))) break; + case LUA_TSTRING: + case LUA_TNUMBER: sv = lua_tolstring(L, -1, &sl); + } if (sl > 0) { *buffer = uwsgi_malloc(sizeof(char) * sl); @@ -1576,37 +1993,62 @@ static void uwsgi_lua_configurator(char *filename, char *magic_table[]) { lua_close(L); } -static void uwsgi_register_lua_features() { +static void uwsgi_register_lua_features() { + uwsgi_register_configurator(".luac", uwsgi_lua_configurator); uwsgi_register_configurator(".lua", uwsgi_lua_configurator); + + // non zero defaults: + ulua.gc_freq = 1; } static void uwsgi_lua_hijack(void) { - if (ulua.shell && uwsgi.mywid == 1) { - uwsgi.workers[uwsgi.mywid].hijacked = 1; - uwsgi.workers[uwsgi.mywid].hijacked_count++; - // re-map stdin to stdout and stderr if we are logging to a file - if (uwsgi.logfile) { - if (dup2(0, 1) < 0) { - uwsgi_error("dup2()"); - } - if (dup2(0, 2) < 0) { - uwsgi_error("dup2()"); - } - } - int ret = -1; + + if (ulua.shell && uwsgi.mywid == 1) { + + if (ulua.shell_oneshot && uwsgi.workers[uwsgi.mywid].hijacked_count > 0) { + uwsgi.workers[uwsgi.mywid].hijacked = 0; + return; + } + + uwsgi.workers[uwsgi.mywid].hijacked = 1; + uwsgi.workers[uwsgi.mywid].hijacked_count++; + // re-map stdin to stdout and stderr if we are logging to a file + if (uwsgi.logfile) { + if (dup2(0, 1) < 0) { + uwsgi_error("dup2()"); + } + if (dup2(0, 2) < 0) { + uwsgi_error("dup2()"); + } + } + // run in the first state lua_State *L = ULUA_WORKER_STATE[0]; lua_getglobal(L, "debug"); lua_getfield(L, -1, "debug"); - ret = lua_pcall(L, 0, 0, 0); - if (ret == 0) { - exit(UWSGI_QUIET_CODE); - } - exit(0); - } + + ulua_log("Hallo, this is lua debug.debug() aka lua_debug, use CTRL+D to exit"); + + if (lua_pcall(L, 0, 0, 0)) { + ulua_log("unable to call 'debug.debug()': %s", lua_tostring(L, -1)); + } + if (ulua.shell_oneshot || uwsgi.master_process) { // master will respawn it anyway + + uwsgi.workers[uwsgi.mywid].hijacked = 0; + + uwsgi_log("\n"); + ulua_log("worker %d has been resumed...", uwsgi.mywid); + + return; + } + + exit(UWSGI_QUIET_CODE); + + } } + static void uwsgi_lua_init_apps() { int i,j,sid; @@ -1620,6 +2062,7 @@ static void uwsgi_lua_init_apps() { uwsgi_lua_init_state(&(ULUA_WORKER_STATE[i]), uwsgi.mywid, sid + i, cores); } + ulua_log("inited %d lua_State(s) for worker %d", uwsgi.threads, uwsgi.mywid); } else { for(j=0;j Date: Fri, 21 Aug 2015 18:29:04 +0300 Subject: [PATCH 08/17] lua_plugin: remove atexit, fixes don't spawn lua_states on workers, if nothing to run cache multi_set,update,del also returns number of bad keys remove atexit, does not work as expected --- plugins/lua/lua_plugin.c | 89 +++++++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 33 deletions(-) diff --git a/plugins/lua/lua_plugin.c b/plugins/lua/lua_plugin.c index 862a6b22..c1b9f689 100644 --- a/plugins/lua/lua_plugin.c +++ b/plugins/lua/lua_plugin.c @@ -18,7 +18,7 @@ struct uwsgi_lua { uint8_t shell; uint8_t shell_oneshot; struct uwsgi_string_list *load; - char *filename; + char *wsapi; struct uwsgi_string_list *postload; int gc_freq; int gc_full; @@ -39,6 +39,12 @@ struct uwsgi_lua { #define ulua_log(c, ar...) uwsgi_log(ULUA_LOG_HEADER" "c"\n", ##ar) +#define ULUA_WORKER_ANYAPP (ulua.wsapi ||\ + ulua.load ||\ + ulua.postload ||\ + ulua.shell ||\ + ulua.shell_oneshot) + struct uwsgi_plugin lua_plugin; static void uwsgi_opt_luashell(char *opt, char *value, void *foobar) { @@ -55,7 +61,7 @@ static void uwsgi_opt_luashell_oneshot(char *opt, char *value, void *foobar) { static struct uwsgi_option uwsgi_lua_options[] = { - {"lua", required_argument, 0, "load lua wsapi app", uwsgi_opt_set_str, &ulua.filename, 0}, + {"lua", required_argument, 0, "load lua wsapi app", uwsgi_opt_set_str, &ulua.wsapi, 0}, {"lua-load", required_argument, 0, "load a lua file before wsapi app", uwsgi_opt_add_string_list, &ulua.load, 0}, {"lua-postload", required_argument, 0, "load a lua file after wsapi app", uwsgi_opt_add_string_list, &ulua.postload, 0}, {"lua-shell", no_argument, 0, "run the lua interactive shell (debug.debug())", uwsgi_opt_luashell, NULL, 0}, @@ -534,7 +540,8 @@ static int uwsgi_lua_cache_set_multi(lua_State *L, uint8_t flag) { } if (uwsgi_cache_magic_set(key, keylen, value, valuelen, expires, flag, cache)) { - lua_pushnumber(L, ++error); + ++error; + lua_pushnumber(L, (i/2) - 1); } } @@ -543,9 +550,12 @@ static int uwsgi_lua_cache_set_multi(lua_State *L, uint8_t flag) { return 1; } - lua_pushnil(L); + lua_pushnumber(L, error); lua_insert(L, -(++error)); + lua_pushnil(L); + lua_insert(L, -(++error)); + return error; } @@ -621,7 +631,8 @@ static int uwsgi_api_cache_del_multi(lua_State *L) { key = (char *) lua_tolstring(L, i, &keylen); if (!keylen || uwsgi_cache_magic_del(key, keylen, cache)) { - lua_pushnumber(L, ++error); + ++error; + lua_pushnumber(L, i - 1); } } @@ -630,8 +641,13 @@ static int uwsgi_api_cache_del_multi(lua_State *L) { return 1; } + lua_pushnumber(L, error); + lua_insert(L, -(++error)); + lua_pushnil(L); lua_insert(L, -(++error)); + + return error; return error; } @@ -687,6 +703,7 @@ static int uwsgi_api_cache_exists_multi(lua_State *L) { static int uwsgi_api_signal_wait(lua_State *L) { struct wsgi_request *wsgi_req = current_wsgi_req(); + ulua_log("%d", wsgi_req); uint8_t args = lua_gettop(L); int received_signal; @@ -697,7 +714,7 @@ static int uwsgi_api_signal_wait(lua_State *L) { } else { received_signal = uwsgi_signal_wait(wsgi_req, -1); } - + ulua_log("%d", received_signal); if (received_signal < 0) { lua_pushnil(L); } else { @@ -1369,7 +1386,7 @@ static int uwsgi_api_pid(lua_State *L) { } -static const luaL_Reg uwsgi_api[] = { +static const luaL_Reg uwsgi_api_worker[] = { {"log", uwsgi_api_log}, {"connection_fd", uwsgi_api_req_fd}, @@ -1440,6 +1457,11 @@ static const luaL_Reg uwsgi_api[] = { static int uwsgi_lua_init(){ + + if (!ULUA_WORKER_ANYAPP) { + return 0; + } + int i; uwsgi_log(ULUA_LOG_HEADER " Initializing Lua environment... "); @@ -1462,12 +1484,12 @@ static int uwsgi_lua_init(){ return 0; } -static int uwsgi_lua_dummy_response(lua_State *L) { - lua_pushstring(L, "500"); - return 1; -} - static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { + + if (!ULUA_WORKER_ANYAPP) { + return; + } + int i; int uslnargs; lua_State *L; @@ -1478,7 +1500,7 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { // init worker state luaL_openlibs(L); - ulua_pushapi(L, "uwsgi", uwsgi_api); + ulua_pushapi(L, "uwsgi", uwsgi_api_worker); lua_pushstring(L, UWSGI_VERSION); lua_setfield(L, -2, "version"); @@ -1490,7 +1512,7 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { lua_setfield(L, -2, "mysid"); // reserve ref 1 for ws func - lua_pushvalue(L, -1); + lua_pushboolean(L, 0); luaL_ref(L, LUA_REGISTRYINDEX); // rpc metatable ref 2 @@ -1526,9 +1548,9 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { uslnargs = lua_gettop(L) - uslnargs; - if (ulua.filename) { - if (luaL_loadfile(L, ulua.filename)) { - ulua_log("unable to load Lua file %s: %s", ulua.filename, lua_tostring(L, -1)); + if (ulua.wsapi) { + if (luaL_loadfile(L, ulua.wsapi)) { + ulua_log("unable to load Lua file %s: %s", ulua.wsapi, lua_tostring(L, -1)); lua_pop(L, uslnargs + 1); uslnargs = 0; } else { @@ -1562,10 +1584,9 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { // loading dummy lua_pop(L, uslnargs); ulua_log("Can't find WSAPI entry point (no function, nor a table with function'run')."); - lua_pushcfunction(L, uwsgi_lua_dummy_response); + } else { + lua_rawseti(L, LUA_REGISTRYINDEX, ULUA_WSAPI_REF); } - - lua_rawseti(L, LUA_REGISTRYINDEX, ULUA_WSAPI_REF); //init additional threads for current worker if (cores > 0) { @@ -1604,6 +1625,12 @@ static int uwsgi_lua_request(struct wsgi_request *wsgi_req) { const char *http, *http2; size_t i, tlen, slen, slen2; + + if(!ulua.wsapi) { + ulua_log("No WSAPI App. skip."); + return -1; + } + lua_State *L = ULUA_WORKER_STATE[wsgi_req->async_id]; /* Standard WSAPI request */ @@ -1782,7 +1809,7 @@ static int uwsgi_lua_magic(char *mountpoint, char *lazy) { !strcmp(lazy+strlen(lazy)-5, ".luac") || !strcmp(lazy+strlen(lazy)-3, ".ws")) { - ulua.filename = lazy; + ulua.wsapi = lazy; return 1; } @@ -1997,7 +2024,7 @@ static void uwsgi_register_lua_features() { uwsgi_register_configurator(".luac", uwsgi_lua_configurator); uwsgi_register_configurator(".lua", uwsgi_lua_configurator); - // non zero defaults: + // non zero or non inited defaults: ulua.gc_freq = 1; } @@ -2027,7 +2054,8 @@ static void uwsgi_lua_hijack(void) { lua_getglobal(L, "debug"); lua_getfield(L, -1, "debug"); - ulua_log("Hallo, this is lua debug.debug() aka lua_debug, use CTRL+D to exit"); + ulua_log("Hallo, this is lua debug.debug() aka lua_debug, use CTRL+D to %s", + (ulua.shell_oneshot || uwsgi.master_process) ? "resume" : "exit"); if (lua_pcall(L, 0, 0, 0)) { ulua_log("unable to call 'debug.debug()': %s", lua_tostring(L, -1)); @@ -2050,6 +2078,11 @@ static void uwsgi_lua_hijack(void) { static void uwsgi_lua_init_apps() { + + if (!ULUA_WORKER_ANYAPP) { + return; + } + int i,j,sid; //cores per lua thread @@ -2076,15 +2109,6 @@ static void uwsgi_lua_init_apps() { } } -static void uwsgi_lua_atexit() { - lua_State **Ls = ULUA_WORKER_STATE; - int i; - - for (i = 0; i < uwsgi.threads; i++) { - lua_close(Ls[i]); - } -} - struct uwsgi_plugin lua_plugin = { .name = "lua", @@ -2104,7 +2128,6 @@ struct uwsgi_plugin lua_plugin = { .code_string = uwsgi_lua_code_string, .rpc = uwsgi_lua_rpc, - .atexit = uwsgi_lua_atexit, .on_load = uwsgi_register_lua_features, }; From 94ccb6b0303cb9fba62d00d6d97aa5e032481929 Mon Sep 17 00:00:00 2001 From: Hleran Date: Sat, 22 Aug 2015 18:42:41 +0300 Subject: [PATCH 09/17] lua_plugin: mules separate api, mules --- plugins/lua/lua_plugin.c | 289 ++++++++++++++++++++++++++++++++++----- 1 file changed, 258 insertions(+), 31 deletions(-) diff --git a/plugins/lua/lua_plugin.c b/plugins/lua/lua_plugin.c index c1b9f689..4add0687 100644 --- a/plugins/lua/lua_plugin.c +++ b/plugins/lua/lua_plugin.c @@ -5,10 +5,7 @@ #include #if LUA_VERSION_NUM < 502 -# define ulua_pushapi luaL_register # define lua_rawlen lua_objlen -#else -# define ulua_pushapi(L,key,api) lua_newtable(L);luaL_setfuncs(L,api,0);lua_pushvalue(L,-1);lua_setglobal(L,key) #endif extern struct uwsgi_server uwsgi; @@ -703,7 +700,6 @@ static int uwsgi_api_cache_exists_multi(lua_State *L) { static int uwsgi_api_signal_wait(lua_State *L) { struct wsgi_request *wsgi_req = current_wsgi_req(); - ulua_log("%d", wsgi_req); uint8_t args = lua_gettop(L); int received_signal; @@ -714,7 +710,7 @@ static int uwsgi_api_signal_wait(lua_State *L) { } else { received_signal = uwsgi_signal_wait(wsgi_req, -1); } - ulua_log("%d", received_signal); + if (received_signal < 0) { lua_pushnil(L); } else { @@ -781,7 +777,7 @@ static int uwsgi_api_register_signal(lua_State *L) { who = lua_tolstring(L, 2, &len); use = &uwsgi.shared->signal_table[sig]; - if (!len) { + if (len == 0) { who = (const char *) &len; // len is zero anyway } else if (len > 63) { ulua_log("receiver is too long: %s", who); @@ -804,6 +800,13 @@ static int uwsgi_api_register_signal(lua_State *L) { use->modifier1 = 6; if (uwsgi.mywid == 0) { + if (uwsgi.muleid > 0) { + // ok we done + uwsgi_unlock(uwsgi.signal_table_lock); + lua_pushboolean(L, 1); + return 1; + } + for(i = 1; i <= uwsgi.numproc; i++) { use = &uwsgi.shared->signal_table[sig + i*256]; use->handler = (void *) (1 /* unused */); @@ -1386,9 +1389,121 @@ static int uwsgi_api_pid(lua_State *L) { } -static const luaL_Reg uwsgi_api_worker[] = { +static int uwsgi_api_mule_msg_get(lua_State *L) { + + uint8_t argc = lua_gettop(L); + + int manage_signals = 1; + int manage_farms = 1; + int timeout = -1; + + char *msg; + + size_t buffer_size = 65536; + ssize_t len = 0; + + if (argc > 0 && lua_istable(L, 1)) { + lua_pop(L, argc - 1); + + lua_getfield(L, 1, "signals"); + lua_getfield(L, 1, "farms"); + lua_getfield(L, 1, "timeout"); + lua_getfield(L, 1, "buffer_size"); + + lua_remove(L, -5); + argc = 4; + } + + switch(argc > 4 ? 4 : argc) { + case 4: buffer_size = lua_isnumber(L, 4) ? lua_tonumber(L, 4) : 65536; + case 3: timeout = lua_isnumber(L, 3) ? lua_tonumber(L, 3) : -1; + case 2: manage_farms = !lua_isnil(L, 2) ? lua_toboolean(L, 2) : 1; + case 1: manage_signals = !lua_isnil(L, 1) ? lua_toboolean(L, 1) : 1; + } + + msg = (char *) uwsgi_malloc(buffer_size); + + len = uwsgi_mule_get_msg(manage_signals, manage_farms, msg, buffer_size, timeout); + + if (len < 0) { + lua_pushnil(L); + } else { + lua_pushlstring(L, msg, len); + } + + free(msg); + + return 1; +} + +static int uwsgi_api_mule_msg(lua_State *L) { + + int fd; + int mule_id; + int type; + + size_t msglen; + char *msg; + + uint8_t argc = lua_gettop(L); + + if (argc < 1 || !lua_isstring(L, 1)) { + return 0; + } + + if (uwsgi.mules_cnt < 1) { + ulua_log("mule_msg: no mules. no send"); + return 0; + } + + msg = (char *) lua_tolstring(L, 1, &msglen); + + if (argc == 1) { + mule_send_msg(uwsgi.shared->mule_queue_pipe[0], msg, msglen); + } else { + fd = -1; + mule_id = -1; + type = lua_type(L, 2); + + if (type == LUA_TSTRING) { + struct uwsgi_farm *uf = get_farm_by_name((char *)lua_tostring(L, 2)); + + if (!uf) { + ulua_log("mule_msg: unknown farm"); + return 0; + } + + fd = uf->queue_pipe[0]; + + } else if (type == LUA_TNUMBER) { + mule_id = lua_tonumber(L, 2); + + if (mule_id < 0 && mule_id > uwsgi.mules_cnt) { + ulua_log("mule_msg: mule_id is out of range"); + return 0; + } + + if (mule_id == 0) { + fd = uwsgi.shared->mule_queue_pipe[0]; + } else { + fd = uwsgi.mules[mule_id-1].queue_pipe[0]; + } + + } else { + ulua_log("mule_msg: invalid mule"); + } + + if (fd > -1) { + mule_send_msg(fd, msg, msglen); + } + } + + return 0; +} + +// basic api list +static const luaL_Reg uwsgi_api_base[] = { {"log", uwsgi_api_log}, - {"connection_fd", uwsgi_api_req_fd}, {"metric_get", uwsgi_api_metric_get}, {"metric_set", uwsgi_api_metric_set}, @@ -1421,17 +1536,36 @@ static const luaL_Reg uwsgi_api_worker[] = { {"add_cron", uwsgi_api_signal_add_cron}, {"alarm", uwsgi_api_alarm}, - - {"register_rpc", uwsgi_api_register_rpc}, - - {"rpc", uwsgi_api_rpc}, {"signal", uwsgi_api_signal}, - {"req_input_read", uwsgi_lua_input}, - {"mem", uwsgi_api_memory_usage}, {"pid", uwsgi_api_pid}, + {"lock", uwsgi_api_lock}, + {"unlock", uwsgi_api_unlock}, + + {"mule_msg", uwsgi_api_mule_msg}, + + {0, 0} +}; + +// worker only adds +static const luaL_Reg uwsgi_api_worker[] = { + + {"connection_fd", uwsgi_api_req_fd}, + + {"register_rpc", uwsgi_api_register_rpc}, + {"rpc", uwsgi_api_rpc}, + + {"req_input_read", uwsgi_lua_input}, + + {"async_sleep", uwsgi_api_async_sleep}, + {"async_connect", uwsgi_api_async_connect}, + {"async_id_get", uwsgi_api_async_id_get}, + {"is_connected", uwsgi_api_is_connected}, + {"wait_fd_read", uwsgi_api_wait_fd_read}, + {"wait_fd_write", uwsgi_api_wait_fd_write}, + {"websocket_handshake", uwsgi_api_websocket_handshake}, {"websocket_recv", uwsgi_api_websocket_recv}, {"websocket_recv_nb", uwsgi_api_websocket_recv_nb}, @@ -1439,24 +1573,36 @@ static const luaL_Reg uwsgi_api_worker[] = { {"websocket_send_from_sharedarea", uwsgi_api_websocket_send_from_sharedarea}, {"websocket_send_binary", uwsgi_api_websocket_send_binary}, {"websocket_send_binary_from_sharedarea", uwsgi_api_websocket_send_binary_from_sharedarea}, - - {"lock", uwsgi_api_lock}, - {"unlock", uwsgi_api_unlock}, - - {"async_sleep", uwsgi_api_async_sleep}, - {"async_connect", uwsgi_api_async_connect}, - {"async_id_get", uwsgi_api_async_id_get}, - {"is_connected", uwsgi_api_is_connected}, + {"close", uwsgi_api_close}, - {"wait_fd_read", uwsgi_api_wait_fd_read}, - {"wait_fd_write", uwsgi_api_wait_fd_write}, {"ready_fd", uwsgi_api_ready_fd}, - {NULL, NULL} + {0, 0} }; +// mule only adds +static const luaL_Reg uwsgi_api_mule[] = { -static int uwsgi_lua_init(){ + {"mule_msg_get", uwsgi_api_mule_msg_get}, + + {0, 0} +}; + +static void uwsgi_lua_api_newtable(lua_State *L, const char *name) { + lua_newtable(L); + lua_pushvalue(L, -1); + lua_setglobal(L, name); +} + +static void uwsgi_lua_api_push(lua_State *L, int target, const luaL_Reg *api) { + for (; api->name; api++) { + lua_pushstring(L, api->name); + lua_pushcfunction(L, api->func); + lua_rawset(L, target - 2); + } +} + +static int uwsgi_lua_init() { if (!ULUA_WORKER_ANYAPP) { return 0; @@ -1500,7 +1646,10 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { // init worker state luaL_openlibs(L); - ulua_pushapi(L, "uwsgi", uwsgi_api_worker); + + uwsgi_lua_api_newtable(L, "uwsgi"); + uwsgi_lua_api_push(L, -1, uwsgi_api_base); + uwsgi_lua_api_push(L, -1, uwsgi_api_worker); lua_pushstring(L, UWSGI_VERSION); lua_setfield(L, -2, "version"); @@ -1581,9 +1730,9 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { // no app ??? if (!uslnargs || !lua_isfunction(L, -1)) { - // loading dummy lua_pop(L, uslnargs); ulua_log("Can't find WSAPI entry point (no function, nor a table with function'run')."); + ulua.wsapi = 0; } else { lua_rawseti(L, LUA_REGISTRYINDEX, ULUA_WSAPI_REF); } @@ -1865,6 +2014,17 @@ static char *uwsgi_lua_code_string(char *id, char *code, char *func, char *key, static int uwsgi_lua_signal_handler(uint8_t sig, void *handler) { + // only workers can handle this + if (uwsgi.mywid == 0) { + return 0; + } + + // a worker without lua app + if (!ulua.state) { + ulua_log("can't handle signal without lua_State(s)", handler); + return -1; + } + int type; struct wsgi_request *wsgi_req = current_wsgi_req(); @@ -1887,9 +2047,8 @@ static int uwsgi_lua_signal_handler(uint8_t sig, void *handler) { lua_pushnumber(L, sig); - if (lua_pcall(L, 1 + (type == LUA_TTABLE), 1, 0)) { - ulua_log("signal: error running function `f': %s", - lua_tostring(L, -1)); + if (lua_pcall(L, 1 + (type == LUA_TTABLE), 0, 0)) { + ulua_log("signal: error running function `f': %s", lua_tostring(L, -1)); lua_pop(L, 2); return -1; } @@ -2026,6 +2185,7 @@ static void uwsgi_register_lua_features() { // non zero or non inited defaults: ulua.gc_freq = 1; + ulua.state = 0; } static void uwsgi_lua_hijack(void) { @@ -2108,6 +2268,71 @@ static void uwsgi_lua_init_apps() { } } } + +static int uwsgi_lua_mule(char *file) { + + int type_code; + lua_State *L; + char *load; + + if (!uwsgi_endswith(file, ".lua") && !uwsgi_endswith(file, ".luac")) { + return 0; + } + + load = strchr(file, '/'); + + if (load) { + *(load++) = 0; + } else { + load = file; + } + + L = luaL_newstate(); + + luaL_openlibs(L); + + uwsgi_lua_api_newtable(L, "uwsgi"); + uwsgi_lua_api_push(L, -1, uwsgi_api_base); + uwsgi_lua_api_push(L, -1, uwsgi_api_mule); + + lua_pushnumber(L, uwsgi.muleid); + lua_setfield(L, -2, "muleid"); + + if (file != load) { + lua_pushstring(L, file); + lua_setfield(L, -2, "mulefunc"); + } + + if (luaL_loadfile(L, load) || lua_pcall(L, 0, 1, 0)) { + ulua_log("mule%d: unable to load Lua file %s: %s", uwsgi.muleid, load, lua_tostring(L, -1)); + lua_close(L); + return 0; + } + + if (file != load) { + lua_pop(L, 1); + lua_getglobal(L, file); + } + + type_code = lua_type(L, -1); + + if (!(type_code == LUA_TFUNCTION) && !(type_code == LUA_TTABLE && uwsgi_lua_metatable_call(L, -1))) { + ulua_log("mule%d: attempt to call a %s value", uwsgi.muleid, lua_typename(L, type_code)); + lua_close(L); + return 0; + } + + if (lua_pcall(L, (type_code == LUA_TTABLE), 1, 0)) { + ulua_log("mule%d: error running function `f': %s", uwsgi.muleid, lua_tostring(L, -1)); + lua_pushnil(L); + } + + // do not respawn ?? + type_code = !(lua_isboolean(L, -1) && lua_toboolean(L, -1)); + lua_close(L); + + return type_code; +} struct uwsgi_plugin lua_plugin = { @@ -2120,6 +2345,8 @@ struct uwsgi_plugin lua_plugin = { .init_apps = uwsgi_lua_init_apps, + .mule = uwsgi_lua_mule, + .magic = uwsgi_lua_magic, .signal_handler = uwsgi_lua_signal_handler, From a7181572e671b315ed9bd3d538b878e50458f9bd Mon Sep 17 00:00:00 2001 From: Hleran Date: Wed, 26 Aug 2015 19:36:59 +0300 Subject: [PATCH 10/17] lua_plugin: queues, extend wsapi dunno why so many additions and deletions basic queues, remove cache_set_tables (cache_set will do it now) extend wsapi with 4th argument without breaking it --- plugins/lua/lua_plugin.c | 394 ++++++++++++++++++++++++++++++++------- 1 file changed, 324 insertions(+), 70 deletions(-) diff --git a/plugins/lua/lua_plugin.c b/plugins/lua/lua_plugin.c index 4add0687..efeee110 100644 --- a/plugins/lua/lua_plugin.c +++ b/plugins/lua/lua_plugin.c @@ -18,7 +18,8 @@ struct uwsgi_lua { char *wsapi; struct uwsgi_string_list *postload; int gc_freq; - int gc_full; + uint8_t gc_full; + size_t mule_msg_get_buffer_size; } ulua; #define ULUA_MYWID (uwsgi.mywid-1) @@ -34,6 +35,12 @@ struct uwsgi_lua { #define ULUA_METRIC_MUL 3 #define ULUA_METRIC_DEC 4 +#define ULUA_QUEUE_POP 1 +#define ULUA_QUEUE_PULL 2 + +#define ULUA_OPTDEF_GC_FREQ 1 +#define ULUA_OPTDEF_MULE_MSG_GET_BUFFER_SIZE 65536 + #define ulua_log(c, ar...) uwsgi_log(ULUA_LOG_HEADER" "c"\n", ##ar) #define ULUA_WORKER_ANYAPP (ulua.wsapi ||\ @@ -52,10 +59,15 @@ static void uwsgi_opt_luashell(char *opt, char *value, void *foobar) { static void uwsgi_opt_luashell_oneshot(char *opt, char *value, void *foobar) { // enable shell uwsgi_opt_luashell(NULL, NULL, NULL); - ulua.shell_oneshot = 1; } +static void uwsgi_opt_lua_set_long(char *opt, char *value, void *lvalue) { + long *v = (long *) lvalue; + *v = (value) ? atol(value) : 0; + if (*v < 0) *v = 0; +} + static struct uwsgi_option uwsgi_lua_options[] = { {"lua", required_argument, 0, "load lua wsapi app", uwsgi_opt_set_str, &ulua.wsapi, 0}, @@ -67,6 +79,7 @@ static struct uwsgi_option uwsgi_lua_options[] = { {"luashell-oneshot", no_argument, 0, "run the lua interactive shell (debug.debug(), one-shot variant)", uwsgi_opt_luashell_oneshot, NULL, 0}, {"lua-gc-freq", required_argument, 0, "set the lua gc frequency (default: 1, runs after every request)", uwsgi_opt_set_int, &ulua.gc_freq, 0}, {"lua-gc-full", no_argument, 0, "set the lua gc to perform a full garbage-collection cycle (default: 0, gc performs an incremental step of garbage collection)", uwsgi_opt_set_int, &ulua.gc_full, 0}, + {"lua-mule-msg-get-buffer-size", required_argument, 0, "set default buffer size for mule's message (default: 64k)", uwsgi_opt_lua_set_long, &ulua.mule_msg_get_buffer_size, 0}, {0, 0, 0, 0}, @@ -380,10 +393,8 @@ static int uwsgi_api_register_rpc_newindex(lua_State *L) { return 0; } -static int uwsgi_lua_cache_set(lua_State *L, uint8_t flag) { - - uint8_t argc = lua_gettop(L); - +static int uwsgi_lua_cache_set(lua_State *L, uint8_t argc, uint8_t flag) { + char *cache = NULL; uint64_t expires = 0; @@ -393,10 +404,6 @@ static int uwsgi_lua_cache_set(lua_State *L, uint8_t flag) { char *value = NULL; size_t valuelen = 0; - if (argc < 2) { - return 0; - } - // key key = (char *) lua_tolstring(L, 1, &keylen); @@ -422,17 +429,8 @@ static int uwsgi_lua_cache_set(lua_State *L, uint8_t flag) { return 0; } -static int uwsgi_api_cache_set(lua_State *L) { - return uwsgi_lua_cache_set(L, 0); -} - -static int uwsgi_api_cache_update(lua_State *L) { - return uwsgi_lua_cache_set(L, UWSGI_CACHE_FLAG_UPDATE); -} - -static int uwsgi_lua_cache_set_table(lua_State *L, uint8_t flag) { +static int uwsgi_lua_cache_set_table(lua_State *L, uint8_t argc, uint8_t flag) { - uint8_t argc = lua_gettop(L); uint8_t error = 0; char *cache = NULL; @@ -444,10 +442,6 @@ static int uwsgi_lua_cache_set_table(lua_State *L, uint8_t flag) { char *value = NULL; size_t valuelen = 0; - if (argc < 1 || !lua_istable(L, 1)) { - return 0; - } - if (argc > 1) { expires = lua_tonumber(L, 2); if (argc > 2) { @@ -494,14 +488,29 @@ static int uwsgi_lua_cache_set_table(lua_State *L, uint8_t flag) { } -static int uwsgi_api_cache_set_table(lua_State *L) { - return uwsgi_lua_cache_set_table(L, 0); +static int uwsgi_api_cache_set(lua_State *L) { + uint8_t argc = lua_gettop(L); + + if (argc > 0 && lua_istable(L, 1)) { + return uwsgi_lua_cache_set_table(L, argc, 0); + } else if (argc > 1) { + return uwsgi_lua_cache_set(L, argc, 0); + } + + return 0; } -static int uwsgi_api_cache_update_table(lua_State *L) { - return uwsgi_lua_cache_set_table(L, UWSGI_CACHE_FLAG_UPDATE); -} +static int uwsgi_api_cache_update(lua_State *L) { + uint8_t argc = lua_gettop(L); + if (argc > 0 && lua_istable(L, 1)) { + return uwsgi_lua_cache_set_table(L, argc, UWSGI_CACHE_FLAG_UPDATE); + } else if (argc > 1) { + return uwsgi_lua_cache_set(L, argc, UWSGI_CACHE_FLAG_UPDATE); + } + + return 0; +} static int uwsgi_lua_cache_set_multi(lua_State *L, uint8_t flag) { @@ -1372,6 +1381,15 @@ static int uwsgi_api_memory_usage(lua_State *L) { return 2; } +static int uwsgi_api_setprocname(lua_State *L) { + + if (lua_gettop(L) > 0 && lua_isstring(L, 1)) { + uwsgi_set_processname((char *) lua_tostring(L, 1)); + } + + return 0; +} + static int uwsgi_api_pid(lua_State *L) { int id = 0; @@ -1380,7 +1398,7 @@ static int uwsgi_api_pid(lua_State *L) { id = lua_tonumber(L, 1); } - if (id <= uwsgi.numproc) { + if (id >= 0 && id <= uwsgi.numproc) { lua_pushnumber(L, uwsgi.workers[id].pid); return 1; } @@ -1399,7 +1417,7 @@ static int uwsgi_api_mule_msg_get(lua_State *L) { char *msg; - size_t buffer_size = 65536; + size_t buffer_size = ulua.mule_msg_get_buffer_size; ssize_t len = 0; if (argc > 0 && lua_istable(L, 1)) { @@ -1415,10 +1433,10 @@ static int uwsgi_api_mule_msg_get(lua_State *L) { } switch(argc > 4 ? 4 : argc) { - case 4: buffer_size = lua_isnumber(L, 4) ? lua_tonumber(L, 4) : 65536; - case 3: timeout = lua_isnumber(L, 3) ? lua_tonumber(L, 3) : -1; - case 2: manage_farms = !lua_isnil(L, 2) ? lua_toboolean(L, 2) : 1; - case 1: manage_signals = !lua_isnil(L, 1) ? lua_toboolean(L, 1) : 1; + case 4: if (lua_isnumber(L, 4)) buffer_size = lua_tonumber(L, 4); + case 3: if (lua_isnumber(L, 3)) timeout = lua_tonumber(L, 3); + case 2: if (!lua_isnil(L, 2)) manage_farms = lua_toboolean(L, 2); + case 1: if (!lua_isnil(L, 1)) manage_signals = lua_toboolean(L, 1); } msg = (char *) uwsgi_malloc(buffer_size); @@ -1501,6 +1519,196 @@ static int uwsgi_api_mule_msg(lua_State *L) { return 0; } +static int uwsgi_api_queue_push(lua_State *L) { + + size_t len; + const char *str; + + if (!(lua_gettop(L))) { + return 0; + } + + str = lua_tolstring(L, 1, &len); + + if (len && uwsgi.queue_size) { + uwsgi_wlock(uwsgi.queue_lock); + + if (uwsgi_queue_push((char *)str, len)) { + uwsgi_rwunlock(uwsgi.queue_lock); + lua_pushboolean(L, 1); + return 1; + } + + uwsgi_rwunlock(uwsgi.queue_lock); + } + + return 0; +} + +static int uwsgi_api_queue_set(lua_State *L) { + + uint64_t len; + const char *str; + uint64_t pos; + + if (lua_gettop(L) < 2) { + return 0; + } + + pos = lua_tonumber(L, 1); + str = lua_tolstring(L, 2, &len); + + if (len && uwsgi.queue_size) { + uwsgi_wlock(uwsgi.queue_lock); + + if (uwsgi_queue_set(pos, (char *)str, len)) { + uwsgi_rwunlock(uwsgi.queue_lock); + lua_pushboolean(L, 1); + return 1; + } + + uwsgi_rwunlock(uwsgi.queue_lock); + } + + return 0; +} + +static int uwsgi_api_queue_slot(lua_State *L) { + + lua_pushnumber(L, uwsgi.queue_header->pos); + + return 1; +} + +static int uwsgi_api_queue_pull_slot(lua_State *L) { + + lua_pushnumber(L, uwsgi.queue_header->pull_pos); + + return 1; +} + +static int uwsgi_lua_queue_pull_pop(lua_State *L, uint8_t op) { + + char *str; + size_t len; + + if (uwsgi.queue_size) { + uwsgi_wlock(uwsgi.queue_lock); + + str = op == ULUA_QUEUE_POP ? uwsgi_queue_pop(&len) : uwsgi_queue_pull(&len); + + if (len) { + lua_pushlstring(L, str, len); + uwsgi_rwunlock(uwsgi.queue_lock); + return 1; + } + + uwsgi_rwunlock(uwsgi.queue_lock); + } + + return 0; +} + +static int uwsgi_api_queue_pull(lua_State *L) { + return uwsgi_lua_queue_pull_pop(L, ULUA_QUEUE_PULL); +} + +static int uwsgi_api_queue_pop(lua_State *L) { + return uwsgi_lua_queue_pull_pop(L, ULUA_QUEUE_POP); +} + +static int uwsgi_api_queue_get(lua_State *L) { + + char *str; + size_t len; + uint64_t index; + + if (!(lua_gettop(L))) { + return 0; + } + + index = lua_tonumber(L, 1); + + if (uwsgi.queue_size) { + uwsgi_rlock(uwsgi.queue_lock); + + str = uwsgi_queue_get(index, &len); + + if (len) { + lua_pushlstring(L, str, len); + uwsgi_rwunlock(uwsgi.queue_lock); + return 1; + } + + uwsgi_rwunlock(uwsgi.queue_lock); + } + + return 0; +} + +static int uwsgi_api_queue_last(lua_State *L) { + + char *str; + size_t len; + uint64_t base; + + unsigned int left; + unsigned int count = lua_gettop(L) ? lua_tonumber(L, 1) : 0; + + if (uwsgi.queue_size) { + uwsgi_rlock(uwsgi.queue_lock); + + base = uwsgi.queue_header->pos > 0 ? uwsgi.queue_header->pos-1 : uwsgi.queue_size-1; + + if (!(count)) { + + str = uwsgi_queue_get(base, &len); + + if (len) { + lua_pushlstring(L, str, len); + uwsgi_rwunlock(uwsgi.queue_lock); + return 1; + } + + uwsgi_rwunlock(uwsgi.queue_lock); + return 0; + } + + if (count > uwsgi.queue_size) count = uwsgi.queue_size; + + if (!lua_checkstack(L, count)) { + ulua_log("queue_last: too many items (%u) in the stack", count); + uwsgi_rwunlock(uwsgi.queue_lock); + return 0; + } + + left = count; + + while(left) { + str = uwsgi_queue_get(base, &len); + + if(len) { + lua_pushlstring(L, str, len); + } else { + lua_pushnil(L); + } + + if (base > 0) { + --base; + } else { + base = uwsgi.queue_size-1; + } + + --left; + } + + uwsgi_rwunlock(uwsgi.queue_lock); + return count; + } + + return 0; +} + // basic api list static const luaL_Reg uwsgi_api_base[] = { {"log", uwsgi_api_log}, @@ -1515,17 +1723,24 @@ static const luaL_Reg uwsgi_api_base[] = { {"cache_get", uwsgi_api_cache_get}, {"cache_get_multi", uwsgi_api_cache_get_multi}, {"cache_set", uwsgi_api_cache_set}, - {"cache_set_table", uwsgi_api_cache_set_table}, {"cache_set_multi", uwsgi_api_cache_set_multi}, {"cache_update", uwsgi_api_cache_update}, - {"cache_update_table", uwsgi_api_cache_update_table}, {"cache_update_multi", uwsgi_api_cache_update_multi}, {"cache_del", uwsgi_api_cache_del}, {"cache_del_multi", uwsgi_api_cache_del_multi}, {"cache_exists", uwsgi_api_cache_exists}, {"cache_exists_multi", uwsgi_api_cache_exists_multi}, {"cache_clear", uwsgi_api_cache_clear}, - + + {"queue_push", uwsgi_api_queue_push}, + {"queue_set", uwsgi_api_queue_set}, + {"queue_slot", uwsgi_api_queue_slot}, + {"queue_pull_slot", uwsgi_api_queue_pull_slot}, + {"queue_pop",uwsgi_api_queue_pop}, + {"queue_get",uwsgi_api_queue_get}, + {"queue_pull",uwsgi_api_queue_pull}, + {"queue_last",uwsgi_api_queue_last}, + {"register_signal", uwsgi_api_register_signal}, {"signal_registered", uwsgi_api_signal_registered}, {"signal_wait", uwsgi_api_signal_wait}, @@ -1540,13 +1755,15 @@ static const luaL_Reg uwsgi_api_base[] = { {"mem", uwsgi_api_memory_usage}, {"pid", uwsgi_api_pid}, + + {"setprocname", uwsgi_api_setprocname}, {"lock", uwsgi_api_lock}, {"unlock", uwsgi_api_unlock}, {"mule_msg", uwsgi_api_mule_msg}, - {0, 0} + {NULL, NULL} }; // worker only adds @@ -1577,7 +1794,7 @@ static const luaL_Reg uwsgi_api_worker[] = { {"close", uwsgi_api_close}, {"ready_fd", uwsgi_api_ready_fd}, - {0, 0} + {NULL, NULL} }; // mule only adds @@ -1585,7 +1802,7 @@ static const luaL_Reg uwsgi_api_mule[] = { {"mule_msg_get", uwsgi_api_mule_msg_get}, - {0, 0} + {NULL, NULL} }; static void uwsgi_lua_api_newtable(lua_State *L, const char *name) { @@ -1603,7 +1820,17 @@ static void uwsgi_lua_api_push(lua_State *L, int target, const luaL_Reg *api) { } static int uwsgi_lua_init() { + + if (!ulua.mule_msg_get_buffer_size) { + ulua.mule_msg_get_buffer_size = ULUA_OPTDEF_MULE_MSG_GET_BUFFER_SIZE; + } + if(!(ulua.gc_full)) { + ulua.gc_full = LUA_GCSTEP; + } else { + ulua.gc_full = LUA_GCCOLLECT; + } + if (!ULUA_WORKER_ANYAPP) { return 0; } @@ -1620,12 +1847,6 @@ static int uwsgi_lua_init() { uwsgi_log("%d lua_States (with %d lua_Threads)\n", uwsgi.numproc, uwsgi.cores); - if(!(ulua.gc_full)) { - ulua.gc_full = LUA_GCSTEP; - } else { - ulua.gc_full = LUA_GCCOLLECT; - } - // ok the lua engine is ready return 0; } @@ -1709,7 +1930,7 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { } if (lua_pcall(L, uslnargs, 1, 0)) { - ulua_log("%s", lua_tostring(L, -1)); + ulua_log("unable to load Lua file %s: %s", ulua.wsapi, lua_tostring(L, -1)); lua_pop(L, 1); uslnargs = 0; } else { @@ -1789,7 +2010,6 @@ static int uwsgi_lua_request(struct wsgi_request *wsgi_req) { } if (wsgi_req->async_status == UWSGI_AGAIN) { -async_coroutine: while (!lua_pcall(L, 0, 1, 0)) { switch(lua_type(L, -1)) { case LUA_TNIL: // posible dead coroutine @@ -1845,30 +2065,30 @@ async_coroutine: #endif // call function - if (lua_pcall(L, 1, 3, 0)) { - ulua_log("%s", lua_tostring(L, -1)); + if (lua_pcall(L, 1, 4, 0)) { + ulua_log("wsapi: %s", lua_tostring(L, -1)); lua_pop(L, 1); goto clear2; } #ifdef UWSGI_DEBUG - ulua_log("%d %s %s %s",i,lua_typename(L, lua_type(L, -3)), lua_typename(L, lua_type(L, -2)) , lua_typename(L, lua_type(L, -1))); + ulua_log("%s %s %s %s", lua_typename(L, lua_type(L, -4)), lua_typename(L, lua_type(L, -3)), lua_typename(L, lua_type(L, -2)) , lua_typename(L, lua_type(L, -1))); #endif // send status - http = lua_tolstring(L, -3, &slen); + http = lua_tolstring(L, -4, &slen); if (uwsgi_response_prepare_headers(wsgi_req, (char *) http, slen)) { - ulua_log("invalid response status!!!"); - // let's continue + goto clear; + return -1; } // send headers - if (lua_istable(L, -2)) { + if (lua_istable(L, -3)) { lua_pushnil(L); - while(lua_next(L, -3)) { + while(lua_next(L, -4)) { // lua_tolstring may change the 'lua_next' sequence, if the key is not a string, by modifying it lua_pushvalue(L, -2); @@ -1898,23 +2118,51 @@ async_coroutine: } // send body with coroutine or copy from string - lua_pushvalue(L, -1); - - switch(lua_type(L, -1)) { + + switch(lua_type(L, -2)) { case LUA_TFUNCTION: + // initing coroutine: + // pushing first argument of coroutine and call it fisrt time: + + lua_pushvalue(L, -2); + lua_pushvalue(L, -2); + + if(!lua_pcall(L, 1, 1, 0)) { + switch(lua_type(L, -1)) { + case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, -1))) break; + case LUA_TSTRING: + case LUA_TNUMBER: + + http = lua_tolstring(L, -1, &slen); + uwsgi_response_write_body_do(wsgi_req, (char *) http, slen); + + } + } else { + ulua_log("coroutine: %s", lua_tostring(L, -1)); + lua_pop(L, 1); + break; + } + + lua_pop(L, 2); + lua_pushvalue(L, -1); + + // continue coroutine + if (uwsgi.async > 0) { - goto async_coroutine; + return UWSGI_AGAIN; } while (!lua_pcall(L, 0, 1, 0)) { switch(lua_type(L, -1)) { + case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, -1))) break; case LUA_TSTRING: case LUA_TNUMBER: http = lua_tolstring(L, -1, &slen); uwsgi_response_write_body_do(wsgi_req, (char *) http, slen); + } lua_pop(L, 1); @@ -1923,11 +2171,11 @@ async_coroutine: break; - case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, -1))) break; + case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, -2))) break; case LUA_TSTRING: case LUA_TNUMBER: - http = lua_tolstring(L, -1, &slen); + http = lua_tolstring(L, -2, &slen); uwsgi_response_write_body_do(wsgi_req, (char *) http, slen); } @@ -2014,6 +2262,8 @@ static char *uwsgi_lua_code_string(char *id, char *code, char *func, char *key, static int uwsgi_lua_signal_handler(uint8_t sig, void *handler) { + ulua_log("man_signal"); + // only workers can handle this if (uwsgi.mywid == 0) { return 0; @@ -2184,8 +2434,7 @@ static void uwsgi_register_lua_features() { uwsgi_register_configurator(".lua", uwsgi_lua_configurator); // non zero or non inited defaults: - ulua.gc_freq = 1; - ulua.state = 0; + ulua.gc_freq = ULUA_OPTDEF_GC_FREQ; } static void uwsgi_lua_hijack(void) { @@ -2214,7 +2463,7 @@ static void uwsgi_lua_hijack(void) { lua_getglobal(L, "debug"); lua_getfield(L, -1, "debug"); - ulua_log("Hallo, this is lua debug.debug() aka lua_debug, use CTRL+D to %s", + ulua_log("Hallo, this is lua debug.debug() aka lua_debug, use Control+D to %s", (ulua.shell_oneshot || uwsgi.master_process) ? "resume" : "exit"); if (lua_pcall(L, 0, 0, 0)) { @@ -2279,7 +2528,7 @@ static int uwsgi_lua_mule(char *file) { return 0; } - load = strchr(file, '/'); + load = strchr(file, '@'); if (load) { *(load++) = 0; @@ -2300,9 +2549,11 @@ static int uwsgi_lua_mule(char *file) { if (file != load) { lua_pushstring(L, file); - lua_setfield(L, -2, "mulefunc"); + lua_setfield(L, -2, "mulecallme"); } + lua_pop(L, 1); + if (luaL_loadfile(L, load) || lua_pcall(L, 0, 1, 0)) { ulua_log("mule%d: unable to load Lua file %s: %s", uwsgi.muleid, load, lua_tostring(L, -1)); lua_close(L); @@ -2322,9 +2573,11 @@ static int uwsgi_lua_mule(char *file) { return 0; } + // cleanup the mess + lua_gc(L, LUA_GCCOLLECT, 0); + if (lua_pcall(L, (type_code == LUA_TTABLE), 1, 0)) { - ulua_log("mule%d: error running function `f': %s", uwsgi.muleid, lua_tostring(L, -1)); - lua_pushnil(L); + ulua_log("mule%d: error running loop function: %s", uwsgi.muleid, lua_tostring(L, -1)); } // do not respawn ?? @@ -2338,6 +2591,7 @@ struct uwsgi_plugin lua_plugin = { .name = "lua", .modifier1 = 6, + .init = uwsgi_lua_init, .options = uwsgi_lua_options, .request = uwsgi_lua_request, From 1d595be2d9c73226bc30c8fc706e1fe916b9fa3f Mon Sep 17 00:00:00 2001 From: Hleran Date: Thu, 27 Aug 2015 23:15:29 +0300 Subject: [PATCH 11/17] lua_plugin: cleanup, more queues, more cache and loop of nested tables inside headers --- plugins/lua/lua_plugin.c | 580 +++++++++++++++++++++++++-------------- 1 file changed, 370 insertions(+), 210 deletions(-) diff --git a/plugins/lua/lua_plugin.c b/plugins/lua/lua_plugin.c index efeee110..5decfd06 100644 --- a/plugins/lua/lua_plugin.c +++ b/plugins/lua/lua_plugin.c @@ -18,7 +18,7 @@ struct uwsgi_lua { char *wsapi; struct uwsgi_string_list *postload; int gc_freq; - uint8_t gc_full; + uint8_t gc_perform; size_t mule_msg_get_buffer_size; } ulua; @@ -30,14 +30,6 @@ struct uwsgi_lua { #define ULUA_RPC_REF 2 #define ULUA_SIGNAL_REF 3 -#define ULUA_METRIC_INC 1 -#define ULUA_METRIC_DIV 2 -#define ULUA_METRIC_MUL 3 -#define ULUA_METRIC_DEC 4 - -#define ULUA_QUEUE_POP 1 -#define ULUA_QUEUE_PULL 2 - #define ULUA_OPTDEF_GC_FREQ 1 #define ULUA_OPTDEF_MULE_MSG_GET_BUFFER_SIZE 65536 @@ -78,7 +70,7 @@ static struct uwsgi_option uwsgi_lua_options[] = { {"lua-shell-oneshot", no_argument, 0, "run the lua interactive shell (debug.debug(), one-shot variant)", uwsgi_opt_luashell_oneshot, NULL, 0}, {"luashell-oneshot", no_argument, 0, "run the lua interactive shell (debug.debug(), one-shot variant)", uwsgi_opt_luashell_oneshot, NULL, 0}, {"lua-gc-freq", required_argument, 0, "set the lua gc frequency (default: 1, runs after every request)", uwsgi_opt_set_int, &ulua.gc_freq, 0}, - {"lua-gc-full", no_argument, 0, "set the lua gc to perform a full garbage-collection cycle (default: 0, gc performs an incremental step of garbage collection)", uwsgi_opt_set_int, &ulua.gc_full, 0}, + {"lua-gc-full", no_argument, 0, "set the lua gc to perform a full garbage-collection cycle (default: 0, gc performs an incremental step of garbage collection)", uwsgi_opt_set_int, &ulua.gc_perform, 0}, {"lua-mule-msg-get-buffer-size", required_argument, 0, "set default buffer size for mule's message (default: 64k)", uwsgi_opt_lua_set_long, &ulua.mule_msg_get_buffer_size, 0}, {0, 0, 0, 0}, @@ -161,13 +153,10 @@ static int uwsgi_api_metric_set(lua_State *L) { return 1; } -static int uwsgi_lua_metric_op(lua_State *L, uint8_t op) { +static int uwsgi_lua_metric_do(lua_State *L, int metric_do(char*, char*, int64_t)) { int64_t value = 1; uint8_t argc = lua_gettop(L); - int code = -1; - char *name; - if (!(argc) || !(lua_isstring(L, 1))) { return 0; } @@ -175,17 +164,8 @@ static int uwsgi_lua_metric_op(lua_State *L, uint8_t op) { if (argc > 1 && lua_isnumber(L, 2)) { value = lua_tonumber(L, 2); } - - name = (char *) lua_tostring(L, 1); - - switch(op) { - case ULUA_METRIC_INC: code = uwsgi_metric_inc(name, NULL, value); break; - case ULUA_METRIC_DIV: code = uwsgi_metric_div(name, NULL, value); break; - case ULUA_METRIC_MUL: code = uwsgi_metric_mul(name, NULL, value); break; - case ULUA_METRIC_DEC: code = uwsgi_metric_dec(name, NULL, value); break; - } - - if (code) { + + if (metric_do((char *) lua_tostring(L, 1), NULL, value)) { return 0; } @@ -195,19 +175,19 @@ static int uwsgi_lua_metric_op(lua_State *L, uint8_t op) { } static int uwsgi_api_metric_inc(lua_State *L) { - return uwsgi_lua_metric_op(L, ULUA_METRIC_INC); + return uwsgi_lua_metric_do(L, uwsgi_metric_inc); } static int uwsgi_api_metric_div(lua_State *L) { - return uwsgi_lua_metric_op(L, ULUA_METRIC_DIV); + return uwsgi_lua_metric_do(L, uwsgi_metric_div); } static int uwsgi_api_metric_mul(lua_State *L) { - return uwsgi_lua_metric_op(L, ULUA_METRIC_MUL); + return uwsgi_lua_metric_do(L, uwsgi_metric_mul); } static int uwsgi_api_metric_dec(lua_State *L) { - return uwsgi_lua_metric_op(L, ULUA_METRIC_DEC); + return uwsgi_lua_metric_do(L, uwsgi_metric_dec); } @@ -286,16 +266,12 @@ static int uwsgi_api_rpc(lua_State *L) { argv = (char **) uwsgi_malloc(sizeof(char *)*argnum); argvs = (uint16_t *) uwsgi_malloc(sizeof(uint16_t)*argnum); - for(i = 0; i < argnum; i++) { - switch(lua_type(L, i + 3)) { - case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, i + 2 - argc))) break; - case LUA_TSTRING: - case LUA_TNUMBER: argv[i] = (char *) lua_tolstring(L, i + 3, (size_t *) &argvs[i]); continue; + for(i = 0; i < argnum; i++) { + if (lua_istable(L, i + 3)) { + uwsgi_lua_metatable_tostring(L, i + 2 - argc); } - // default - argv[i] = NULL; - argvs[i] = 0; + argv[i] = (char *) lua_tolstring(L, i + 3, (size_t *) &argvs[i]); } } @@ -401,19 +377,19 @@ static int uwsgi_lua_cache_set(lua_State *L, uint8_t argc, uint8_t flag) { char *key; size_t keylen; - char *value = NULL; - size_t valuelen = 0; + char *value; + size_t valuelen; // key key = (char *) lua_tolstring(L, 1, &keylen); // value - switch(lua_type(L, 2)) { - case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, -argc + 1))) break; - case LUA_TSTRING: - case LUA_TNUMBER: value = (char *) lua_tolstring(L, 2, &valuelen); + if (lua_istable(L, 2)) { + uwsgi_lua_metatable_tostring(L, -argc + 1); } + value = (char *) lua_tolstring(L, 2, &valuelen); + if (argc > 2) { expires = lua_tonumber(L, 3); if (argc > 3) { @@ -431,7 +407,7 @@ static int uwsgi_lua_cache_set(lua_State *L, uint8_t argc, uint8_t flag) { static int uwsgi_lua_cache_set_table(lua_State *L, uint8_t argc, uint8_t flag) { - uint8_t error = 0; + size_t error = 0; char *cache = NULL; uint64_t expires = 0; @@ -439,8 +415,8 @@ static int uwsgi_lua_cache_set_table(lua_State *L, uint8_t argc, uint8_t flag) { char *key; size_t keylen; - char *value = NULL; - size_t valuelen = 0; + char *value; + size_t valuelen; if (argc > 1) { expires = lua_tonumber(L, 2); @@ -458,33 +434,28 @@ static int uwsgi_lua_cache_set_table(lua_State *L, uint8_t argc, uint8_t flag) { key = (char *) lua_tolstring(L, -1, &keylen); //value - switch(lua_type(L, -2)) { - case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, -2))) break; - case LUA_TSTRING: - case LUA_TNUMBER: value = (char *) lua_tolstring(L, -2, &valuelen); + if (lua_istable(L, -2)) { + uwsgi_lua_metatable_tostring(L, -2); } + value = (char *) lua_tolstring(L, -2, &valuelen); + if (uwsgi_cache_magic_set(key, keylen, value, valuelen, expires, flag, cache)) { - lua_pop(L, 2); - lua_pushvalue(L, -1); ++error; - } else { - lua_pop(L, 2); } + + lua_pop(L, 2); } if (!error) { lua_pushboolean(L, 1); return 1; } - - lua_pushnumber(L, error); - lua_insert(L, -(++error)); - + lua_pushnil(L); - lua_insert(L, -(++error)); + lua_pushnumber(L, error); - return error; + return 2; } @@ -514,9 +485,9 @@ static int uwsgi_api_cache_update(lua_State *L) { static int uwsgi_lua_cache_set_multi(lua_State *L, uint8_t flag) { - uint8_t argc = lua_gettop(L); - uint8_t error = 0; - uint8_t i; + int argc = lua_gettop(L); + int error = 0; + int i; char *cache; uint64_t expires; @@ -524,8 +495,8 @@ static int uwsgi_lua_cache_set_multi(lua_State *L, uint8_t flag) { char *key; size_t keylen; - char *value = NULL; - size_t valuelen = 0; + char *value; + size_t valuelen; if (argc < 4) { return 0; @@ -539,15 +510,14 @@ static int uwsgi_lua_cache_set_multi(lua_State *L, uint8_t flag) { key = (char *) lua_tolstring(L, i - 1, &keylen); // value - switch(lua_type(L, i)) { - case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, i - argc - 1 - error))) break; - case LUA_TSTRING: - case LUA_TNUMBER: value = (char *) lua_tolstring(L, i, &valuelen); + if (lua_istable(L, i)) { + uwsgi_lua_metatable_tostring(L, i - argc - 1); } + value = (char *) lua_tolstring(L, i, &valuelen); + if (uwsgi_cache_magic_set(key, keylen, value, valuelen, expires, flag, cache)) { ++error; - lua_pushnumber(L, (i/2) - 1); } } @@ -556,13 +526,10 @@ static int uwsgi_lua_cache_set_multi(lua_State *L, uint8_t flag) { return 1; } - lua_pushnumber(L, error); - lua_insert(L, -(++error)); - lua_pushnil(L); - lua_insert(L, -(++error)); + lua_pushnumber(L, error); - return error; + return 2; } static int uwsgi_api_cache_set_multi(lua_State *L) { @@ -577,9 +544,8 @@ static int uwsgi_api_cache_update_multi(lua_State *L) { static int uwsgi_api_cache_clear(lua_State *L) { char *cache = NULL; - uint8_t argc = lua_gettop(L); - if (argc > 0) { + if (lua_gettop(L)) { cache = (char *) lua_tostring(L, 1); } @@ -592,30 +558,66 @@ static int uwsgi_api_cache_clear(lua_State *L) { } -static int uwsgi_api_cache_del(lua_State *L) { +static int uwsgi_lua_cache_del_exists(lua_State *L, int cache_do(char *, uint16_t, char *), uint8_t reverse) { size_t keylen; char *key; char *cache = NULL; + + size_t i, tlen; + size_t error = 0; + uint8_t argc = lua_gettop(L); - + if (!(argc)) { return 0; } - // get the key - key = (char *) lua_tolstring(L, 1, &keylen); - if (argc > 1) { cache = (char *) lua_tostring(L, 2); } - - if (keylen && !uwsgi_cache_magic_del(key, keylen, cache)) { + + // get the key + if (lua_istable(L, 1)) { + tlen = lua_rawlen(L, 1); + + for(i = 1; i <= tlen; i++) { + lua_rawgeti(L, 1, i); + + key = (char *) lua_tolstring(L, -1, &keylen); + + if (!keylen || !cache_do(key, keylen, cache)) { + ++error; + } + + lua_pop(L, 1); + } + + } else { + key = (char *) lua_tolstring(L, 1, &keylen); + + if (!keylen || (cache_do(key, keylen, cache) - reverse)) { + ++error; + } + } + + if (!error) { lua_pushboolean(L, 1); return 1; } - return 0; + lua_pushnil(L); + lua_pushnumber(L, error); + + return 2; +} + +static int uwsgi_api_cache_del(lua_State *L) { + return uwsgi_lua_cache_del_exists(L, uwsgi_cache_magic_del, 0); +} + +static int uwsgi_api_cache_exists(lua_State *L) { + return uwsgi_lua_cache_del_exists(L, uwsgi_cache_magic_exists, 1); } static int uwsgi_api_cache_del_multi(lua_State *L) { @@ -623,9 +625,10 @@ static int uwsgi_api_cache_del_multi(lua_State *L) { size_t keylen; char *key; char *cache; - uint8_t argc = lua_gettop(L); - uint8_t error = 0; - uint8_t i; + + int argc = lua_gettop(L); + int error = 0; + int i; if (argc < 1) { return 0; @@ -638,7 +641,6 @@ static int uwsgi_api_cache_del_multi(lua_State *L) { if (!keylen || uwsgi_cache_magic_del(key, keylen, cache)) { ++error; - lua_pushnumber(L, i - 1); } } @@ -647,38 +649,11 @@ static int uwsgi_api_cache_del_multi(lua_State *L) { return 1; } - lua_pushnumber(L, error); - lua_insert(L, -(++error)); - lua_pushnil(L); - lua_insert(L, -(++error)); + lua_pushnumber(L, error); - return error; - - return error; -} + return 2; -static int uwsgi_api_cache_exists(lua_State *L) { - - size_t keylen; - char *key; - char *cache = NULL; - uint8_t argc = lua_gettop(L); - - if (argc < 1) { - return 0; - } - - // get the key - key = (char *) lua_tolstring(L, 1, &keylen); - - if (argc > 1) { - cache = (char *) lua_tostring(L, 2); - } - - lua_pushboolean(L, keylen && uwsgi_cache_magic_exists(key, keylen, cache)); - - return 1; } static int uwsgi_api_cache_exists_multi(lua_State *L) { @@ -686,8 +661,9 @@ static int uwsgi_api_cache_exists_multi(lua_State *L) { size_t keylen; char *key; char *cache; - uint8_t argc = lua_gettop(L); - uint8_t i; + + int argc = lua_gettop(L); + int i; if (argc < 2) { return 0; @@ -1252,13 +1228,18 @@ static int uwsgi_api_cache_get_multi(lua_State *L) { char *key; char *cache; - uint8_t argc = lua_gettop(L); - uint8_t i; + int argc = lua_gettop(L); + int i; if (argc < 2) { return 0; } + if (!lua_checkstack(L, argc - 1)) { + ulua_log("cache_get_multi: too many items (%u) in the stack", argc - 1); + return 0; + } + cache = (char *) lua_tostring(L, 1); for (i = 2; i <= argc; i++) { @@ -1522,55 +1503,171 @@ static int uwsgi_api_mule_msg(lua_State *L) { static int uwsgi_api_queue_push(lua_State *L) { size_t len; - const char *str; + char *str; - if (!(lua_gettop(L))) { + int argc = lua_gettop(L); + int error = 0; + + char **list; + size_t *slen; + int i; + + + if (!argc || !uwsgi.queue_size) { return 0; } - str = lua_tolstring(L, 1, &len); + if (argc == 1) { - if (len && uwsgi.queue_size) { + if (lua_istable(L, 1)) { + uwsgi_lua_metatable_tostring(L, -1); + } + + str = (char *) lua_tolstring(L, 1, &len); + + if (len) { + uwsgi_wlock(uwsgi.queue_lock); + + if (uwsgi_queue_push(str, len)) { + ++error; + } + + uwsgi_rwunlock(uwsgi.queue_lock); + } else { + ++error; + } + + } else { + + list = (char **) uwsgi_malloc(sizeof(char *) * argc); + slen = (size_t *) uwsgi_malloc(sizeof(size_t) * argc); + + for (i = 1; i <= argc; ++i) { + + if (lua_istable(L, i)) { + uwsgi_lua_metatable_tostring(L, i - argc - 1); + } + + list[i] = (char *) lua_tolstring(L, i, &slen[i]); + + } + uwsgi_wlock(uwsgi.queue_lock); - if (uwsgi_queue_push((char *)str, len)) { - uwsgi_rwunlock(uwsgi.queue_lock); - lua_pushboolean(L, 1); - return 1; + for (i = 1; i <= argc; ++i) { + + if (!slen[i] || uwsgi_queue_push(list[i], slen[i])) { + ++error; + } + } uwsgi_rwunlock(uwsgi.queue_lock); + + free(list); + free(slen); + } - return 0; + if (!error) { + lua_pushboolean(L, 1); + return 1; + } + + lua_pushnil(L); + lua_pushnumber(L, error); + + return 2; + } static int uwsgi_api_queue_set(lua_State *L) { + uint64_t key; uint64_t len; - const char *str; - uint64_t pos; - - if (lua_gettop(L) < 2) { + char *str; + int i; + + int error = 0; + int argc = lua_gettop(L); + + if (!(argc && uwsgi.queue_size)) { return 0; } - - pos = lua_tonumber(L, 1); - str = lua_tolstring(L, 2, &len); - - if (len && uwsgi.queue_size) { - uwsgi_wlock(uwsgi.queue_lock); - if (uwsgi_queue_set(pos, (char *)str, len)) { - uwsgi_rwunlock(uwsgi.queue_lock); - lua_pushboolean(L, 1); - return 1; + if (lua_istable(L, 1)) { + + lua_pushnil(L); + + while(lua_next(L, 1)) { + if (lua_isnumber(L, -2)) { + + if (lua_istable(L, -1)) { + uwsgi_lua_metatable_tostring(L, -1); + } + + str = (char *) lua_tolstring(L, -1, &len); + key = lua_tonumber(L, -2); + + if (len) { + uwsgi_wlock(uwsgi.queue_lock); + + if (!uwsgi_queue_set(key, str, len)) { + error++; + } + + uwsgi_rwunlock(uwsgi.queue_lock); + } else { + error++; + } + + } else { + error++; + } + + lua_pop(L, 1); } + + } else { - uwsgi_rwunlock(uwsgi.queue_lock); + for (i = 2; i <= argc; i+=2) { + if (lua_isnumber(L, i - 1)) { + + if (lua_istable(L, i)) { + uwsgi_lua_metatable_tostring(L, i - argc - 1); + } + + key = lua_tonumber(L, i - 1); + str = (char *) lua_tolstring(L, i, &len); + + if (len) { + uwsgi_wlock(uwsgi.queue_lock); + + if (!uwsgi_queue_set(key, str, len)) { + error++; + } + + uwsgi_rwunlock(uwsgi.queue_lock); + } else { + error++; + } + + } else { + error++; + } + } + } - return 0; + if (!error) { + lua_pushboolean(L, 1); + return 1; + } + + lua_pushnil(L); + lua_pushnumber(L, error); + + return 2; } static int uwsgi_api_queue_slot(lua_State *L) { @@ -1587,63 +1684,107 @@ static int uwsgi_api_queue_pull_slot(lua_State *L) { return 1; } -static int uwsgi_lua_queue_pull_pop(lua_State *L, uint8_t op) { +static int uwsgi_lua_queue_pull_pop(lua_State *L, char* queue(uint64_t*)) { char *str; size_t len; + int i; + + int num = (lua_gettop(L) > 0) ? lua_tonumber(L, 1) : 1; - if (uwsgi.queue_size) { - uwsgi_wlock(uwsgi.queue_lock); - - str = op == ULUA_QUEUE_POP ? uwsgi_queue_pop(&len) : uwsgi_queue_pull(&len); - - if (len) { - lua_pushlstring(L, str, len); - uwsgi_rwunlock(uwsgi.queue_lock); - return 1; - } - - uwsgi_rwunlock(uwsgi.queue_lock); + if (!uwsgi.queue_size) { + return 0; } - return 0; + if (!lua_checkstack(L, num)) { + ulua_log("queue_pop(pull): too many items (%u) in the stack", num); + return 0; + } + + uwsgi_wlock(uwsgi.queue_lock); + + for(i = num; i > 0; --i) { + + len = 0; + str = queue(&len); + + if (len) { + lua_pushlstring(L, str, len); + } else { + lua_pushnil(L); + } + } + + uwsgi_rwunlock(uwsgi.queue_lock); + + return num; } static int uwsgi_api_queue_pull(lua_State *L) { - return uwsgi_lua_queue_pull_pop(L, ULUA_QUEUE_PULL); + return uwsgi_lua_queue_pull_pop(L, uwsgi_queue_pull); } static int uwsgi_api_queue_pop(lua_State *L) { - return uwsgi_lua_queue_pull_pop(L, ULUA_QUEUE_POP); + return uwsgi_lua_queue_pull_pop(L, uwsgi_queue_pop); } static int uwsgi_api_queue_get(lua_State *L) { char *str; size_t len; - uint64_t index; - - if (!(lua_gettop(L))) { + int i; + + int argc = lua_gettop(L); + + uint64_t key; + uint64_t *list; + + if (!argc || !uwsgi.queue_size) { return 0; } - - index = lua_tonumber(L, 1); - if (uwsgi.queue_size) { + if (argc == 1) { + key = lua_tonumber(L, 1); + uwsgi_rlock(uwsgi.queue_lock); - - str = uwsgi_queue_get(index, &len); - + + str = uwsgi_queue_get(key, &len); + if (len) { lua_pushlstring(L, str, len); - uwsgi_rwunlock(uwsgi.queue_lock); - return 1; + } else { + lua_pushnil(L); } uwsgi_rwunlock(uwsgi.queue_lock); + } else { + + list = (uint64_t *) uwsgi_malloc(sizeof(uint64_t) * argc); + + for (i = 1; i <= argc; ++i) { + list[i] = lua_tonumber(L, i); + } + + lua_pop(L, argc); + + uwsgi_rlock(uwsgi.queue_lock); + + for (i = 1; i <= argc; ++i) { + str = uwsgi_queue_get(list[i], &len); + + if (len) { + lua_pushlstring(L, str, len); + } else { + lua_pushnil(L); + } + } + + uwsgi_rwunlock(uwsgi.queue_lock); + + free(list); } - return 0; + return argc; } static int uwsgi_api_queue_last(lua_State *L) { @@ -1656,8 +1797,9 @@ static int uwsgi_api_queue_last(lua_State *L) { unsigned int count = lua_gettop(L) ? lua_tonumber(L, 1) : 0; if (uwsgi.queue_size) { - uwsgi_rlock(uwsgi.queue_lock); + uwsgi_rlock(uwsgi.queue_lock); + base = uwsgi.queue_header->pos > 0 ? uwsgi.queue_header->pos-1 : uwsgi.queue_size-1; if (!(count)) { @@ -1672,9 +1814,11 @@ static int uwsgi_api_queue_last(lua_State *L) { uwsgi_rwunlock(uwsgi.queue_lock); return 0; + } + + if (count > uwsgi.queue_size) { + count = uwsgi.queue_size; } - - if (count > uwsgi.queue_size) count = uwsgi.queue_size; if (!lua_checkstack(L, count)) { ulua_log("queue_last: too many items (%u) in the stack", count); @@ -1825,10 +1969,10 @@ static int uwsgi_lua_init() { ulua.mule_msg_get_buffer_size = ULUA_OPTDEF_MULE_MSG_GET_BUFFER_SIZE; } - if(!(ulua.gc_full)) { - ulua.gc_full = LUA_GCSTEP; + if(!(ulua.gc_perform)) { + ulua.gc_perform = LUA_GCSTEP; } else { - ulua.gc_full = LUA_GCCOLLECT; + ulua.gc_perform = LUA_GCCOLLECT; } if (!ULUA_WORKER_ANYAPP) { @@ -1991,13 +2135,15 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { lua_gc(L, LUA_GCCOLLECT, 0); } +static void uwsgi_lua_request_headers_nested_tables(lua_State *, int8_t, struct wsgi_request *, char *, size_t); + static int uwsgi_lua_request(struct wsgi_request *wsgi_req) { const char *http, *http2; - size_t i, tlen, slen, slen2; + size_t i, slen, slen2; if(!ulua.wsapi) { - ulua_log("No WSAPI App. skip."); + ulua_log("wsapi[%d][%d]: No WSAPI App. skip.", uwsgi.mywid, wsgi_req->async_id); return -1; } @@ -2005,7 +2151,7 @@ static int uwsgi_lua_request(struct wsgi_request *wsgi_req) { /* Standard WSAPI request */ if (!wsgi_req->len) { - ulua_log("Empty lua request. skip."); + ulua_log("wsapi[%d][%d]: Empty lua request. skip.", uwsgi.mywid, wsgi_req->async_id); return -1; } @@ -2066,7 +2212,7 @@ static int uwsgi_lua_request(struct wsgi_request *wsgi_req) { // call function if (lua_pcall(L, 1, 4, 0)) { - ulua_log("wsapi: %s", lua_tostring(L, -1)); + ulua_log("wsapi[%d][%d]: %s", uwsgi.mywid, wsgi_req->async_id, lua_tostring(L, -1)); lua_pop(L, 1); goto clear2; } @@ -2078,8 +2224,12 @@ static int uwsgi_lua_request(struct wsgi_request *wsgi_req) { // send status http = lua_tolstring(L, -4, &slen); + if (!slen) { + ulua_log("wsapi[%d][%d]: invalid response status!", uwsgi.mywid, wsgi_req->async_id); + } + if (uwsgi_response_prepare_headers(wsgi_req, (char *) http, slen)) { - goto clear; + lua_pop(L, 4); return -1; } @@ -2096,17 +2246,8 @@ static int uwsgi_lua_request(struct wsgi_request *wsgi_req) { http = lua_tolstring(L, -1, &slen); if (lua_istable(L, -2)) { - tlen = lua_rawlen(L, -2); - for (i = 1; i <= tlen; i++) { - lua_rawgeti(L, -2, i); - - http2 = lua_tolstring(L, -1, &slen2); - uwsgi_response_add_header(wsgi_req, (char *) http, slen, (char *) http2, slen2); - - lua_pop(L, 1); - } - + uwsgi_lua_request_headers_nested_tables(L, -2, wsgi_req, (char *) http, slen); } else { http2 = lua_tolstring(L, -2, &slen2); @@ -2139,7 +2280,7 @@ static int uwsgi_lua_request(struct wsgi_request *wsgi_req) { } } else { - ulua_log("coroutine: %s", lua_tostring(L, -1)); + ulua_log("wsapi-coroutine[%d][%d]: %s", uwsgi.mywid, wsgi_req->async_id, lua_tostring(L, -1)); lua_pop(L, 1); break; } @@ -2187,13 +2328,34 @@ clear2: (uwsgi.threads == 1 && uwsgi.workers[uwsgi.mywid].requests % ulua.gc_freq == 0) || (uwsgi.threads > 1 && uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].requests % ulua.gc_freq == 0))) { - lua_gc(L, ulua.gc_full, 0); + lua_gc(L, ulua.gc_perform, 0); } return UWSGI_OK; } +static void uwsgi_lua_request_headers_nested_tables(lua_State *L, int8_t table, struct wsgi_request *wsgi_req, char *header, size_t len) { + + size_t i, rlen; + char *rheader; + + size_t tlen = lua_rawlen(L, table); + + for (i = 1; i <= tlen; i++) { + lua_rawgeti(L, table, i); + + if (lua_istable(L, -1)) { + uwsgi_lua_request_headers_nested_tables(L, -1, wsgi_req, header, len); + } else { + rheader = (char *) lua_tolstring(L, -1, &rlen); + uwsgi_response_add_header(wsgi_req, header, len, rheader, rlen); + } + + lua_pop(L, 1); + } +} + static void uwsgi_lua_after_request(struct wsgi_request *wsgi_req) { log_request(wsgi_req); @@ -2262,8 +2424,6 @@ static char *uwsgi_lua_code_string(char *id, char *code, char *func, char *key, static int uwsgi_lua_signal_handler(uint8_t sig, void *handler) { - ulua_log("man_signal"); - // only workers can handle this if (uwsgi.mywid == 0) { return 0; @@ -2298,7 +2458,7 @@ static int uwsgi_lua_signal_handler(uint8_t sig, void *handler) { lua_pushnumber(L, sig); if (lua_pcall(L, 1 + (type == LUA_TTABLE), 0, 0)) { - ulua_log("signal: error running function `f': %s", lua_tostring(L, -1)); + ulua_log("signal: error running signal function: %s", lua_tostring(L, -1)); lua_pop(L, 2); return -1; } @@ -2310,8 +2470,8 @@ static int uwsgi_lua_signal_handler(uint8_t sig, void *handler) { static uint64_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) { uint8_t i; - const char *sv = NULL; - size_t sl = 0; + const char *sv; + size_t sl; int type; struct wsgi_request *wsgi_req = current_wsgi_req(); @@ -2335,16 +2495,16 @@ static uint64_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t a } if (lua_pcall(L, argc + (type == LUA_TTABLE), 1, 0)) { - ulua_log("rpc: error running function `f': %s", lua_tostring(L, -1)); + ulua_log("rpc: error running rpc function: %s", lua_tostring(L, -1)); lua_pop(L, 2); return 0; } - switch(lua_type(L, -1)) { - case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, -1))) break; - case LUA_TSTRING: - case LUA_TNUMBER: sv = lua_tolstring(L, -1, &sl); + if (lua_istable(L, -1)) { + uwsgi_lua_metatable_tostring(L, -1); } + + sv = lua_tolstring(L, -1, &sl); if (sl > 0) { *buffer = uwsgi_malloc(sizeof(char) * sl); @@ -2545,11 +2705,11 @@ static int uwsgi_lua_mule(char *file) { uwsgi_lua_api_push(L, -1, uwsgi_api_mule); lua_pushnumber(L, uwsgi.muleid); - lua_setfield(L, -2, "muleid"); + lua_setfield(L, -2, "mymid"); if (file != load) { lua_pushstring(L, file); - lua_setfield(L, -2, "mulecallme"); + lua_setfield(L, -2, "mule_callme"); } lua_pop(L, 1); From 72ae69090a9e54d328225bc083efe9e6c6ff66fb Mon Sep 17 00:00:00 2001 From: Hleran Date: Sun, 30 Aug 2015 02:01:59 +0300 Subject: [PATCH 12/17] lua_plugin: cache_get, cache_get_tmulti cache_get, cache_get_tmulti returns key-value table --- plugins/lua/lua_plugin.c | 185 +++++++++++++++++++++++++++++---------- 1 file changed, 137 insertions(+), 48 deletions(-) diff --git a/plugins/lua/lua_plugin.c b/plugins/lua/lua_plugin.c index 5decfd06..40987e13 100644 --- a/plugins/lua/lua_plugin.c +++ b/plugins/lua/lua_plugin.c @@ -597,7 +597,8 @@ static int uwsgi_lua_cache_del_exists(lua_State *L, int cache_do(char *, uint16_ key = (char *) lua_tolstring(L, 1, &keylen); if (!keylen || (cache_do(key, keylen, cache) - reverse)) { - ++error; + lua_pushnil(L); + return 1; } } @@ -742,6 +743,8 @@ static int uwsgi_api_signal_registered(lua_State *L) { static int uwsgi_api_register_signal(lua_State *L) { + // !! This is plugin specific function !! + uint8_t args = lua_gettop(L); uint8_t sig; struct uwsgi_signal_entry *use; @@ -765,7 +768,7 @@ static int uwsgi_api_register_signal(lua_State *L) { if (len == 0) { who = (const char *) &len; // len is zero anyway } else if (len > 63) { - ulua_log("receiver is too long: %s", who); + ulua_log("receiver lengh overflow: %s", who); return 0; } @@ -774,27 +777,25 @@ static int uwsgi_api_register_signal(lua_State *L) { } // register signal's receiver on master - // copy handlers and modifiers if calling from mywid == 0 if (!(use->handler) || strcmp(use->receiver, who)) { uwsgi_lock(uwsgi.signal_table_lock); + // master-proc checks receiver strcpy(use->receiver, who); + // if master has not any handler + // if has, then only update receiver if (!(use->handler)) { - use->handler = (void *) (1 /* unused */); - use->modifier1 = 6; - - if (uwsgi.mywid == 0) { - if (uwsgi.muleid > 0) { - // ok we done - uwsgi_unlock(uwsgi.signal_table_lock); - lua_pushboolean(L, 1); - return 1; - } - - for(i = 1; i <= uwsgi.numproc; i++) { - use = &uwsgi.shared->signal_table[sig + i*256]; - use->handler = (void *) (1 /* unused */); + use->handler = (void *) (1 /* unused */); // unsupported + use->modifier1 = 6; // for future checks + } + + // from non-lazy worker + if (uwsgi.mywid == 0 && uwsgi.muleid == 0) { + for(i = 1; i <= uwsgi.numproc; i++) { + use = &uwsgi.shared->signal_table[sig + i*256]; + if (!(use->handler)) { + use->handler = (void *) (1 /* unused */); // unsupported use->modifier1 = 6; } } @@ -803,14 +804,14 @@ static int uwsgi_api_register_signal(lua_State *L) { uwsgi_unlock(uwsgi.signal_table_lock); } - // worker, just register handler and modifier1 + // lazy (or runtime) worker, just register handler and modifier1 if (uwsgi.mywid > 0) { use = &uwsgi.shared->signal_table[sig + uwsgi.mywid*256]; if (use->modifier1 != 6) { uwsgi_lock(uwsgi.signal_table_lock); - use->handler = (void *) (1 /* unused */); + use->handler = (void *) (1 /* unused */); // unsupported use->modifier1 = 6; uwsgi_unlock(uwsgi.signal_table_lock); @@ -1188,44 +1189,85 @@ static int uwsgi_api_websocket_recv_nb(lua_State *L) { static int uwsgi_api_cache_get(lua_State *L) { - char *value; - uint64_t valsize; - size_t keylen; - char *key; - char *cache = NULL; uint8_t argc = lua_gettop(L); - if (argc == 0) goto error; + char *value; + uint64_t valsize; + + char *key; + size_t keylen; - // get the key - key = (char *) lua_tolstring(L, 1, &keylen); + char *cache = NULL; + + size_t error; + size_t tlen; + size_t i; if (argc > 1) { cache = (char *) lua_tostring(L, 2); + } else if (!argc) { + return 0; } - if (!keylen) goto error; - - value = uwsgi_cache_magic_get(key, keylen, &valsize, NULL, cache); + if (lua_istable(L, 1)) { + + error = 0; + tlen = lua_rawlen(L, 1); + + lua_createtable(L, 0, tlen); + + for(i = 1; i <= tlen; i++) { + + lua_rawgeti(L, 1, i); + + key = (char *) lua_tolstring(L, -1, &keylen); + + value = (keylen) ? uwsgi_cache_magic_get(key, keylen, &valsize, NULL, cache) : NULL; + + if (value) { + lua_pushlstring(L, value, valsize); + free(value); + lua_rawset(L, -3); + } else { + ++error; + lua_pop(L, 1); + } + + } + + if (!error) { + return 1; + } + + lua_pushnumber(L, error); + return 2; + + } + key = (char *) lua_tolstring(L, 1, &keylen); + + value = (keylen) ? uwsgi_cache_magic_get(key, keylen, &valsize, NULL, cache) : NULL; + if (value) { lua_pushlstring(L, value, valsize); free(value); - return 1; + } else { + lua_pushnil(L); } - -error: - lua_pushnil(L); + return 1; } + static int uwsgi_api_cache_get_multi(lua_State *L) { char *value ; uint64_t valsize; - size_t keylen; + char *key; + size_t keylen; + char *cache; int argc = lua_gettop(L); @@ -1244,12 +1286,9 @@ static int uwsgi_api_cache_get_multi(lua_State *L) { for (i = 2; i <= argc; i++) { - value = NULL; key = (char *) lua_tolstring(L, i, &keylen); - if (keylen) { - value = uwsgi_cache_magic_get(key, keylen, &valsize, NULL, cache); - } + value = (keylen) ? uwsgi_cache_magic_get(key, keylen, &valsize, NULL, cache) : NULL; if (value) { lua_pushlstring(L, value, valsize); @@ -1262,6 +1301,54 @@ static int uwsgi_api_cache_get_multi(lua_State *L) { return argc - 1; } +static int uwsgi_api_cache_get_tmulti(lua_State *L) { + + char *value ; + uint64_t valsize; + + char *key; + size_t keylen; + + char *cache; + + int argc = lua_gettop(L); + int error = 0; + int i; + + if (argc < 2) { + return 0; + } + + cache = (char *) lua_tostring(L, 1); + + lua_createtable(L, 0, argc - 1); + + for (i = 2; i <= argc; i++) { + + key = (char *) lua_tolstring(L, i, &keylen); + + value = (keylen) ? uwsgi_cache_magic_get(key, keylen, &valsize, NULL, cache) : NULL; + + if (value) { + lua_pushlstring(L, value, valsize); + free(value); + lua_setfield(L, -2, key); + } else { + ++error; + } + + } + + if (!error) { + return 1; + } + + lua_pushnumber(L, error); + return 2; + +} + + static int uwsgi_api_req_fd(lua_State *L) { struct wsgi_request *wsgi_req = current_wsgi_req(); @@ -1460,35 +1547,36 @@ static int uwsgi_api_mule_msg(lua_State *L) { if (argc == 1) { mule_send_msg(uwsgi.shared->mule_queue_pipe[0], msg, msglen); } else { - fd = -1; - mule_id = -1; type = lua_type(L, 2); - + if (type == LUA_TSTRING) { + struct uwsgi_farm *uf = get_farm_by_name((char *)lua_tostring(L, 2)); if (!uf) { ulua_log("mule_msg: unknown farm"); return 0; } - + fd = uf->queue_pipe[0]; - + } else if (type == LUA_TNUMBER) { + mule_id = lua_tonumber(L, 2); if (mule_id < 0 && mule_id > uwsgi.mules_cnt) { ulua_log("mule_msg: mule_id is out of range"); return 0; } - + if (mule_id == 0) { fd = uwsgi.shared->mule_queue_pipe[0]; } else { fd = uwsgi.mules[mule_id-1].queue_pipe[0]; } - + } else { + fd = -1; ulua_log("mule_msg: invalid mule"); } @@ -1656,7 +1744,7 @@ static int uwsgi_api_queue_set(lua_State *L) { error++; } } - + } if (!error) { @@ -1866,6 +1954,7 @@ static const luaL_Reg uwsgi_api_base[] = { {"cache_get", uwsgi_api_cache_get}, {"cache_get_multi", uwsgi_api_cache_get_multi}, + {"cache_get_tmulti", uwsgi_api_cache_get_tmulti}, {"cache_set", uwsgi_api_cache_set}, {"cache_set_multi", uwsgi_api_cache_set_multi}, {"cache_update", uwsgi_api_cache_update}, @@ -1985,7 +2074,7 @@ static int uwsgi_lua_init() { ulua.state = uwsgi_malloc(sizeof(lua_State**) * uwsgi.numproc); - for (i=0;i Date: Mon, 31 Aug 2015 21:49:13 +0300 Subject: [PATCH 13/17] lua_plugin: mules, cache som fixes --- plugins/lua/lua_plugin.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/plugins/lua/lua_plugin.c b/plugins/lua/lua_plugin.c index 40987e13..892e72a7 100644 --- a/plugins/lua/lua_plugin.c +++ b/plugins/lua/lua_plugin.c @@ -586,7 +586,7 @@ static int uwsgi_lua_cache_del_exists(lua_State *L, int cache_do(char *, uint16_ key = (char *) lua_tolstring(L, -1, &keylen); - if (!keylen || !cache_do(key, keylen, cache)) { + if (!keylen || (cache_do(key, keylen, cache) - reverse)) { ++error; } @@ -818,7 +818,7 @@ static int uwsgi_api_register_signal(lua_State *L) { } } - if (args > 2) { + if (args > 2 && uwsgi.muleid == 0) { lua_rawgeti(L, LUA_REGISTRYINDEX, ULUA_SIGNAL_REF); lua_pushvalue(L, 3); @@ -1475,6 +1475,13 @@ static int uwsgi_api_pid(lua_State *L) { } +static int uwsgi_api_mypid(lua_State *L) { + + lua_pushnumber(L, uwsgi.mypid); + + return 1; +} + static int uwsgi_api_mule_msg_get(lua_State *L) { uint8_t argc = lua_gettop(L); @@ -1988,6 +1995,7 @@ static const luaL_Reg uwsgi_api_base[] = { {"mem", uwsgi_api_memory_usage}, {"pid", uwsgi_api_pid}, + {"mypid", uwsgi_api_mypid}, {"setprocname", uwsgi_api_setprocname}, @@ -2796,10 +2804,8 @@ static int uwsgi_lua_mule(char *file) { lua_pushnumber(L, uwsgi.muleid); lua_setfield(L, -2, "mymid"); - if (file != load) { - lua_pushstring(L, file); - lua_setfield(L, -2, "mule_callme"); - } + lua_pushstring(L, (file != load) ? file : ""); + lua_setfield(L, -2, "mule_param"); lua_pop(L, 1); @@ -2809,11 +2815,6 @@ static int uwsgi_lua_mule(char *file) { return 0; } - if (file != load) { - lua_pop(L, 1); - lua_getglobal(L, file); - } - type_code = lua_type(L, -1); if (!(type_code == LUA_TFUNCTION) && !(type_code == LUA_TTABLE && uwsgi_lua_metatable_call(L, -1))) { From 5ebc399cce6988acbc285419879888ca3a37df6b Mon Sep 17 00:00:00 2001 From: Hleran Date: Thu, 3 Sep 2015 00:45:51 +0300 Subject: [PATCH 14/17] lua_plugin: better mules --- plugins/lua/lua_plugin.c | 200 +++++++++++++++++++++++++++------------ 1 file changed, 142 insertions(+), 58 deletions(-) diff --git a/plugins/lua/lua_plugin.c b/plugins/lua/lua_plugin.c index 892e72a7..4d758bca 100644 --- a/plugins/lua/lua_plugin.c +++ b/plugins/lua/lua_plugin.c @@ -12,6 +12,7 @@ extern struct uwsgi_server uwsgi; struct uwsgi_lua { struct lua_State ***state; + struct lua_State **mulestate; uint8_t shell; uint8_t shell_oneshot; struct uwsgi_string_list *load; @@ -23,12 +24,15 @@ struct uwsgi_lua { } ulua; #define ULUA_MYWID (uwsgi.mywid-1) +#define ULUA_MYMID (uwsgi.muleid-1) #define ULUA_WORKER_STATE ulua.state[ULUA_MYWID] +#define ULUA_MULE_STATE ulua.mulestate[ULUA_MYMID] #define ULUA_LOG_HEADER "[uwsgi-lua]" #define ULUA_WSAPI_REF 1 -#define ULUA_RPC_REF 2 -#define ULUA_SIGNAL_REF 3 +#define ULUA_MULE_MSG_REF 1 +#define ULUA_SIGNAL_REF 2 +#define ULUA_RPC_REF 3 #define ULUA_OPTDEF_GC_FREQ 1 #define ULUA_OPTDEF_MULE_MSG_GET_BUFFER_SIZE 65536 @@ -818,14 +822,15 @@ static int uwsgi_api_register_signal(lua_State *L) { } } - if (args > 2 && uwsgi.muleid == 0) { + if (args > 2) { lua_rawgeti(L, LUA_REGISTRYINDEX, ULUA_SIGNAL_REF); lua_pushvalue(L, 3); lua_rawseti(L, -2, sig); } - ulua_log("signum %d registered (by wid %d, target: %s)", sig, uwsgi.mywid, len ? who : "default"); + ulua_log("signum %d registered (by %s %d, target: %s)", sig, + !uwsgi.muleid ? "wid" : "mule", uwsgi.muleid || uwsgi.mywid, len ? who : "default"); lua_pushboolean(L, 1); return 1; @@ -1948,6 +1953,19 @@ static int uwsgi_api_queue_last(lua_State *L) { return 0; } +static int uwsgi_api_mule_msg_hook(lua_State *L) { + + if (!lua_gettop(L)) { + lua_pushnil(L); + } else { + lua_pushvalue(L, 1); + } + + lua_rawseti(L, LUA_REGISTRYINDEX, ULUA_MULE_MSG_REF); + + return 0; +} + // basic api list static const luaL_Reg uwsgi_api_base[] = { {"log", uwsgi_api_log}, @@ -2042,6 +2060,7 @@ static const luaL_Reg uwsgi_api_worker[] = { static const luaL_Reg uwsgi_api_mule[] = { {"mule_msg_get", uwsgi_api_mule_msg_get}, + {"mule_msg_hook", uwsgi_api_mule_msg_hook}, {NULL, NULL} }; @@ -2061,6 +2080,8 @@ static void uwsgi_lua_api_push(lua_State *L, int target, const luaL_Reg *api) { } static int uwsgi_lua_init() { + + int i; if (!ulua.mule_msg_get_buffer_size) { ulua.mule_msg_get_buffer_size = ULUA_OPTDEF_MULE_MSG_GET_BUFFER_SIZE; @@ -2071,22 +2092,30 @@ static int uwsgi_lua_init() { } else { ulua.gc_perform = LUA_GCCOLLECT; } - - if (!ULUA_WORKER_ANYAPP) { - return 0; - } - int i; - - uwsgi_log(ULUA_LOG_HEADER " Initializing Lua environment... "); - - ulua.state = uwsgi_malloc(sizeof(lua_State**) * uwsgi.numproc); - - for (i = 0; i 0) { + uwsgi_log(ULUA_LOG_HEADER " Initializing Mule's Lua environment... "); + + ulua.mulestate = uwsgi_malloc(sizeof(lua_State*) * uwsgi.mules_cnt); + + for (i = 0; iasync_id]; + +#ifdef UWSGI_DEBUG + ulua_log("managing signal handler on core %d", wsgi_req->async_id); +#endif } int type; - struct wsgi_request *wsgi_req = current_wsgi_req(); - - lua_State *L = ULUA_WORKER_STATE[wsgi_req->async_id]; lua_rawgeti(L, LUA_REGISTRYINDEX, ULUA_SIGNAL_REF); lua_rawgeti(L, -1, sig); -#ifdef UWSGI_DEBUG - ulua_log("managing signal handler on core %d", wsgi_req->async_id); -#endif - type = lua_type(L, -1); if (!(type == LUA_TFUNCTION) && !(type == LUA_TTABLE && uwsgi_lua_metatable_call(L, -1))) { @@ -2775,9 +2816,36 @@ static void uwsgi_lua_init_apps() { } } +static int uwsgi_lua_mule_msg(char *msg, size_t len) { + + lua_State *L = ULUA_MULE_STATE; + + if (!L) { + return 0; + } + + lua_rawgeti(L, LUA_REGISTRYINDEX, ULUA_MULE_MSG_REF); + + int type = lua_type(L, -1); + + if (!(type == LUA_TFUNCTION) && !(type == LUA_TTABLE && uwsgi_lua_metatable_call(L, -1))) { + lua_pop(L, 1); + return 0; + } + + lua_pushlstring(L, msg, len); + + if (lua_pcall(L, 1 + (type == LUA_TTABLE), 0, 0)) { + ulua_log("mule%d: error running msg hook function: %s", uwsgi.muleid, lua_tostring(L, -1)); + lua_pop(L, 1); + } + + return 1; +} + static int uwsgi_lua_mule(char *file) { - int type_code; + int type; lua_State *L; char *load; @@ -2793,7 +2861,8 @@ static int uwsgi_lua_mule(char *file) { load = file; } - L = luaL_newstate(); + ULUA_MULE_STATE = luaL_newstate(); + L = ULUA_MULE_STATE; luaL_openlibs(L); @@ -2807,18 +2876,23 @@ static int uwsgi_lua_mule(char *file) { lua_pushstring(L, (file != load) ? file : ""); lua_setfield(L, -2, "mule_param"); + // reserve ref 1 for mule_msg_hook func + lua_pushboolean(L, 0); + luaL_ref(L, LUA_REGISTRYINDEX); + + // signal table ref 2 + lua_newtable(L); + lua_pushvalue(L, -1); + + luaL_ref(L, LUA_REGISTRYINDEX); + lua_setfield(L, -2, "signal_ref"); + lua_pop(L, 1); if (luaL_loadfile(L, load) || lua_pcall(L, 0, 1, 0)) { ulua_log("mule%d: unable to load Lua file %s: %s", uwsgi.muleid, load, lua_tostring(L, -1)); - lua_close(L); - return 0; - } - - type_code = lua_type(L, -1); - - if (!(type_code == LUA_TFUNCTION) && !(type_code == LUA_TTABLE && uwsgi_lua_metatable_call(L, -1))) { - ulua_log("mule%d: attempt to call a %s value", uwsgi.muleid, lua_typename(L, type_code)); + + // init error close the state lua_close(L); return 0; } @@ -2826,15 +2900,24 @@ static int uwsgi_lua_mule(char *file) { // cleanup the mess lua_gc(L, LUA_GCCOLLECT, 0); - if (lua_pcall(L, (type_code == LUA_TTABLE), 1, 0)) { - ulua_log("mule%d: error running loop function: %s", uwsgi.muleid, lua_tostring(L, -1)); + for (;;) { + type = lua_type(L, -1); + + if (!(type == LUA_TFUNCTION) && !(type == LUA_TTABLE && uwsgi_lua_metatable_call(L, -1))) { + lua_pop(L, 1); + break; + } + + if (lua_pcall(L, (type == LUA_TTABLE), 1, 0)) { + ulua_log("mule%d: error running loop function: %s", uwsgi.muleid, lua_tostring(L, -1)); + + // loop exeption close the state + lua_close(L); + return 1; // respawn pls + } } - // do not respawn ?? - type_code = !(lua_isboolean(L, -1) && lua_toboolean(L, -1)); - lua_close(L); - - return type_code; + return 0; } struct uwsgi_plugin lua_plugin = { @@ -2850,6 +2933,7 @@ struct uwsgi_plugin lua_plugin = { .init_apps = uwsgi_lua_init_apps, .mule = uwsgi_lua_mule, + .mule_msg = uwsgi_lua_mule_msg, .magic = uwsgi_lua_magic, .signal_handler = uwsgi_lua_signal_handler, From 637ead553ae02c51d7bfe6e838d635df99e25aa5 Mon Sep 17 00:00:00 2001 From: Hleran Date: Fri, 4 Sep 2015 01:55:34 +0300 Subject: [PATCH 15/17] lua_plugin: mule: posible segfault, chunked_read websocket_send __tostring metatable --- plugins/lua/lua_plugin.c | 45 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/plugins/lua/lua_plugin.c b/plugins/lua/lua_plugin.c index 4d758bca..e95d2826 100644 --- a/plugins/lua/lua_plugin.c +++ b/plugins/lua/lua_plugin.c @@ -1083,10 +1083,15 @@ error: } static int uwsgi_api_websocket_send(lua_State *L) { - uint8_t argc = lua_gettop(L); + int argc = lua_gettop(L); if (argc == 0) goto error; size_t message_len = 0; + + if (lua_istable(L, 1)) { + uwsgi_lua_metatable_tostring(L, -argc); + } + const char *message = lua_tolstring(L, 1, &message_len); struct wsgi_request *wsgi_req = current_wsgi_req(); @@ -1102,10 +1107,15 @@ error: } static int uwsgi_api_websocket_send_binary(lua_State *L) { - uint8_t argc = lua_gettop(L); + int argc = lua_gettop(L); if (argc == 0) goto error; size_t message_len = 0; + + if (lua_istable(L, 1)) { + uwsgi_lua_metatable_tostring(L, -argc); + } + const char *message = lua_tolstring(L, 1, &message_len); struct wsgi_request *wsgi_req = current_wsgi_req(); @@ -1192,6 +1202,33 @@ static int uwsgi_api_websocket_recv_nb(lua_State *L) { return 1; } +static int uwsgi_api_chunked_read(lua_State *L) { + size_t len = 0; + int timeout = lua_gettop(L) ? lua_tonumber(L, 1) : 0; + struct wsgi_request *wsgi_req = current_wsgi_req(); + char *chunk = uwsgi_chunked_read(wsgi_req, &len, timeout, 0); + if (!chunk) { + lua_pushstring(L, "unable to receive chunked part"); + lua_error(L); + return 0; + } + lua_pushlstring(L, chunk, len); + return 1; +} + +static int uwsgi_api_chunked_read_nb(lua_State *L) { + size_t len = 0; + struct wsgi_request *wsgi_req = current_wsgi_req(); + char *chunk = uwsgi_chunked_read(wsgi_req, &len, 0, 1); + if (!chunk) { + lua_pushstring(L, "unable to receive chunked part"); + lua_error(L); + return 0; + } + lua_pushlstring(L, chunk, len); + return 1; +} + static int uwsgi_api_cache_get(lua_State *L) { uint8_t argc = lua_gettop(L); @@ -2034,6 +2071,8 @@ static const luaL_Reg uwsgi_api_worker[] = { {"rpc", uwsgi_api_rpc}, {"req_input_read", uwsgi_lua_input}, + {"chunked_read", uwsgi_api_chunked_read}, + {"chunked_read_nb", uwsgi_api_chunked_read_nb}, {"async_sleep", uwsgi_api_async_sleep}, {"async_connect", uwsgi_api_async_connect}, @@ -2894,6 +2933,7 @@ static int uwsgi_lua_mule(char *file) { // init error close the state lua_close(L); + ULUA_MULE_STATE = NULL; return 0; } @@ -2913,6 +2953,7 @@ static int uwsgi_lua_mule(char *file) { // loop exeption close the state lua_close(L); + ULUA_MULE_STATE = NULL; return 1; // respawn pls } } From c2e83fe01d078c114d3cb8b7c1d399b78b1dacf5 Mon Sep 17 00:00:00 2001 From: Hleran Date: Sun, 13 Sep 2015 06:24:26 +0300 Subject: [PATCH 16/17] lua_plugin: last fixes, fixes, removing unnecessary stuff --- plugins/lua/lua_plugin.c | 324 ++++++++++++++++++++------------------- 1 file changed, 165 insertions(+), 159 deletions(-) diff --git a/plugins/lua/lua_plugin.c b/plugins/lua/lua_plugin.c index e95d2826..9064abc4 100644 --- a/plugins/lua/lua_plugin.c +++ b/plugins/lua/lua_plugin.c @@ -20,7 +20,6 @@ struct uwsgi_lua { struct uwsgi_string_list *postload; int gc_freq; uint8_t gc_perform; - size_t mule_msg_get_buffer_size; } ulua; #define ULUA_MYWID (uwsgi.mywid-1) @@ -29,13 +28,16 @@ struct uwsgi_lua { #define ULUA_MULE_STATE ulua.mulestate[ULUA_MYMID] #define ULUA_LOG_HEADER "[uwsgi-lua]" -#define ULUA_WSAPI_REF 1 +#define ULUA_MULE_MSG_GET_BUFFER_SIZE 65536 + #define ULUA_MULE_MSG_REF 1 + +#define ULUA_WSAPI_REF 1 #define ULUA_SIGNAL_REF 2 #define ULUA_RPC_REF 3 +#define ULUA_THREAD_REF 4 #define ULUA_OPTDEF_GC_FREQ 1 -#define ULUA_OPTDEF_MULE_MSG_GET_BUFFER_SIZE 65536 #define ulua_log(c, ar...) uwsgi_log(ULUA_LOG_HEADER" "c"\n", ##ar) @@ -58,12 +60,6 @@ static void uwsgi_opt_luashell_oneshot(char *opt, char *value, void *foobar) { ulua.shell_oneshot = 1; } -static void uwsgi_opt_lua_set_long(char *opt, char *value, void *lvalue) { - long *v = (long *) lvalue; - *v = (value) ? atol(value) : 0; - if (*v < 0) *v = 0; -} - static struct uwsgi_option uwsgi_lua_options[] = { {"lua", required_argument, 0, "load lua wsapi app", uwsgi_opt_set_str, &ulua.wsapi, 0}, @@ -75,7 +71,6 @@ static struct uwsgi_option uwsgi_lua_options[] = { {"luashell-oneshot", no_argument, 0, "run the lua interactive shell (debug.debug(), one-shot variant)", uwsgi_opt_luashell_oneshot, NULL, 0}, {"lua-gc-freq", required_argument, 0, "set the lua gc frequency (default: 1, runs after every request)", uwsgi_opt_set_int, &ulua.gc_freq, 0}, {"lua-gc-full", no_argument, 0, "set the lua gc to perform a full garbage-collection cycle (default: 0, gc performs an incremental step of garbage collection)", uwsgi_opt_set_int, &ulua.gc_perform, 0}, - {"lua-mule-msg-get-buffer-size", required_argument, 0, "set default buffer size for mule's message (default: 64k)", uwsgi_opt_lua_set_long, &ulua.mule_msg_get_buffer_size, 0}, {0, 0, 0, 0}, @@ -159,7 +154,7 @@ static int uwsgi_api_metric_set(lua_State *L) { static int uwsgi_lua_metric_do(lua_State *L, int metric_do(char*, char*, int64_t)) { int64_t value = 1; - uint8_t argc = lua_gettop(L); + uint16_t argc = lua_gettop(L); if (!(argc) || !(lua_isstring(L, 1))) { return 0; @@ -196,7 +191,7 @@ static int uwsgi_api_metric_dec(lua_State *L) { static int uwsgi_api_signal(lua_State *L) { - uint8_t argc = lua_gettop(L); + uint16_t argc = lua_gettop(L); if (argc > 0 && lua_isnumber(L, 1)) { if (argc > 1 && lua_isstring(L, 2)) { @@ -212,9 +207,10 @@ static int uwsgi_api_signal(lua_State *L) { } static int uwsgi_api_log(lua_State *L) { - uint8_t argc = lua_gettop(L); - uint8_t i; - unsigned long point; + uint16_t argc = lua_gettop(L); + uint16_t i; + + const void *point; int type; if (!(argc)) { @@ -228,20 +224,19 @@ static int uwsgi_api_log(lua_State *L) { switch(type) { case LUA_TNIL: uwsgi_log(" nil"); continue; - + case LUA_TNONE: uwsgi_log(" none"); continue; case LUA_TBOOLEAN: uwsgi_log(lua_toboolean(L, i) ? " true" : " false"); continue; - case LUA_TTABLE: if(!(uwsgi_lua_metatable_tostring(L, i - argc - 1))) break; case LUA_TSTRING: case LUA_TNUMBER: uwsgi_log(" %s", lua_tostring(L, i)); continue; } - point = (unsigned long) (lua_topointer(L, i)); + point = lua_topointer(L, i); if (point) { - uwsgi_log(" %s: 0x%.8x", lua_typename(L, type), point); + uwsgi_log(" <%s: %p>", lua_typename(L, type), point); } else { - uwsgi_log(" %s", lua_typename(L, type)); + uwsgi_log(" <%s>", lua_typename(L, type)); } } @@ -252,7 +247,7 @@ static int uwsgi_api_log(lua_State *L) { static int uwsgi_api_rpc(lua_State *L) { - uint8_t argc = lua_gettop(L); + uint16_t argc = lua_gettop(L); uint8_t argnum; uint8_t i; uint64_t len; @@ -261,12 +256,14 @@ static int uwsgi_api_rpc(lua_State *L) { return 0; } - argnum = argc - 2; + // take first 256 + argnum = (argc <= 256) ? (argc - 2) : 255; char **argv = NULL; uint16_t *argvs = NULL; if (argnum > 0) { + argv = (char **) uwsgi_malloc(sizeof(char *)*argnum); argvs = (uint16_t *) uwsgi_malloc(sizeof(uint16_t)*argnum); @@ -287,7 +284,7 @@ static int uwsgi_api_rpc(lua_State *L) { lua_pushlstring(L, str, len); } - if (argc > 0) { + if (argnum > 0) { free(argv); free(argvs); } @@ -327,37 +324,10 @@ static int uwsgi_api_rpc_register_key(const char *key, size_t len) { return 1; } -static int uwsgi_api_register_rpc(lua_State *L) { - // legacy rpc register func - - uint8_t argc = lua_gettop(L); - - if (argc < 2) { - lua_pushnil(L); - return 1; - } - - lua_rawgeti(L, LUA_REGISTRYINDEX, ULUA_RPC_REF); - - lua_pushvalue(L, 1); - lua_pushvalue(L, 2); - - lua_settable(L, -3); - - lua_pushvalue(L, 1); - lua_rawget(L, -2); - - if (!(lua_isnil(L, -1))) { - lua_pushboolean(L, 1); - } - - return 1; -} - static int uwsgi_api_register_rpc_newindex(lua_State *L) { // 3 args: table, key(string or number), value(not nil) - uint8_t argc = lua_gettop(L); + uint16_t argc = lua_gettop(L); size_t len; if (argc != 3) { @@ -373,7 +343,35 @@ static int uwsgi_api_register_rpc_newindex(lua_State *L) { return 0; } -static int uwsgi_lua_cache_set(lua_State *L, uint8_t argc, uint8_t flag) { +static int uwsgi_api_register_rpc(lua_State *L) { + // legacy rpc register func + + uint16_t argc = lua_gettop(L); + + if (argc < 2) { + return 0; + } + + lua_rawgeti(L, LUA_REGISTRYINDEX, ULUA_RPC_REF); + lua_pushcfunction(L, uwsgi_api_register_rpc_newindex); + + lua_pushvalue(L, -2); + lua_pushvalue(L, 1); + lua_pushvalue(L, 2); + + lua_call(L, 3, 0); + + lua_pushvalue(L, 1); + lua_rawget(L, -2); + + if (!lua_isnil(L, -1)) { + lua_pushboolean(L, 1); + } + + return 1; +} + +static int uwsgi_lua_cache_set(lua_State *L, uint16_t argc, uint8_t flag) { char *cache = NULL; uint64_t expires = 0; @@ -409,7 +407,7 @@ static int uwsgi_lua_cache_set(lua_State *L, uint8_t argc, uint8_t flag) { return 0; } -static int uwsgi_lua_cache_set_table(lua_State *L, uint8_t argc, uint8_t flag) { +static int uwsgi_lua_cache_set_table(lua_State *L, uint16_t argc, uint8_t flag) { size_t error = 0; @@ -464,7 +462,7 @@ static int uwsgi_lua_cache_set_table(lua_State *L, uint8_t argc, uint8_t flag) { } static int uwsgi_api_cache_set(lua_State *L) { - uint8_t argc = lua_gettop(L); + uint16_t argc = lua_gettop(L); if (argc > 0 && lua_istable(L, 1)) { return uwsgi_lua_cache_set_table(L, argc, 0); @@ -476,7 +474,7 @@ static int uwsgi_api_cache_set(lua_State *L) { } static int uwsgi_api_cache_update(lua_State *L) { - uint8_t argc = lua_gettop(L); + uint16_t argc = lua_gettop(L); if (argc > 0 && lua_istable(L, 1)) { return uwsgi_lua_cache_set_table(L, argc, UWSGI_CACHE_FLAG_UPDATE); @@ -489,9 +487,9 @@ static int uwsgi_api_cache_update(lua_State *L) { static int uwsgi_lua_cache_set_multi(lua_State *L, uint8_t flag) { - int argc = lua_gettop(L); - int error = 0; - int i; + uint16_t argc = lua_gettop(L); + uint16_t error = 0; + uint16_t i; char *cache; uint64_t expires; @@ -571,7 +569,7 @@ static int uwsgi_lua_cache_del_exists(lua_State *L, int cache_do(char *, uint16_ size_t i, tlen; size_t error = 0; - uint8_t argc = lua_gettop(L); + uint16_t argc = lua_gettop(L); if (!(argc)) { return 0; @@ -631,9 +629,9 @@ static int uwsgi_api_cache_del_multi(lua_State *L) { char *key; char *cache; - int argc = lua_gettop(L); - int error = 0; - int i; + uint16_t argc = lua_gettop(L); + uint16_t error = 0; + uint16_t i; if (argc < 1) { return 0; @@ -667,8 +665,8 @@ static int uwsgi_api_cache_exists_multi(lua_State *L) { char *key; char *cache; - int argc = lua_gettop(L); - int i; + uint16_t argc = lua_gettop(L); + uint16_t i; if (argc < 2) { return 0; @@ -676,6 +674,11 @@ static int uwsgi_api_cache_exists_multi(lua_State *L) { cache = (char *) lua_tostring(L, 1); + if (!lua_checkstack(L, argc - 1)) { + ulua_log("cache_exists_multi: too many items (%u) in the stack", argc - 1); + return 0; + } + for (i = 2; i <= argc; i++) { key = (char *) lua_tolstring(L, i, &keylen); @@ -690,7 +693,7 @@ static int uwsgi_api_cache_exists_multi(lua_State *L) { static int uwsgi_api_signal_wait(lua_State *L) { struct wsgi_request *wsgi_req = current_wsgi_req(); - uint8_t args = lua_gettop(L); + uint16_t args = lua_gettop(L); int received_signal; wsgi_req->signal_received = -1; @@ -722,7 +725,7 @@ static int uwsgi_api_signal_received(lua_State *L) { static int uwsgi_api_signal_registered(lua_State *L) { - uint8_t args = lua_gettop(L); + uint16_t args = lua_gettop(L); struct uwsgi_signal_entry *use; uint8_t sig; @@ -749,7 +752,7 @@ static int uwsgi_api_register_signal(lua_State *L) { // !! This is plugin specific function !! - uint8_t args = lua_gettop(L); + uint16_t args = lua_gettop(L); uint8_t sig; struct uwsgi_signal_entry *use; const char *who; @@ -824,9 +827,9 @@ static int uwsgi_api_register_signal(lua_State *L) { if (args > 2) { lua_rawgeti(L, LUA_REGISTRYINDEX, ULUA_SIGNAL_REF); - + lua_pushvalue(L, 1); lua_pushvalue(L, 3); - lua_rawseti(L, -2, sig); + lua_settable(L, -3); } ulua_log("signum %d registered (by %s %d, target: %s)", sig, @@ -837,7 +840,7 @@ static int uwsgi_api_register_signal(lua_State *L) { } static int uwsgi_api_add_file_monitor(lua_State *L) { - uint8_t args = lua_gettop(L); + uint16_t args = lua_gettop(L); uint8_t sig; const char *file; size_t len; @@ -863,7 +866,7 @@ static int uwsgi_api_add_file_monitor(lua_State *L) { } static int uwsgi_api_signal_add_timer(lua_State *L) { - uint8_t args = lua_gettop(L); + uint16_t args = lua_gettop(L); uint8_t sig; int secs; @@ -883,7 +886,7 @@ static int uwsgi_api_signal_add_timer(lua_State *L) { } static int uwsgi_api_signal_add_rb_timer(lua_State *L) { - uint8_t args = lua_gettop(L); + uint16_t args = lua_gettop(L); uint8_t sig; int secs, itrs; @@ -905,7 +908,7 @@ static int uwsgi_api_signal_add_rb_timer(lua_State *L) { static int uwsgi_api_signal_add_cron(lua_State *L) { int date[] = {-1, -1, -1, -1, -1}; - uint8_t args = lua_gettop(L); + uint16_t args = lua_gettop(L); int i; if (args < 1 || !(lua_isnumber(L, 1))) { @@ -931,24 +934,30 @@ static int uwsgi_api_signal_add_cron(lua_State *L) { } static int uwsgi_api_alarm(lua_State *L) { - uint8_t args = lua_gettop(L); + uint16_t args = lua_gettop(L); const char *msg; size_t len; - if (args < 2 || !(lua_isstring(L, 1) && lua_isstring(L, 2))) { + if (args < 2 || !(lua_isstring(L, 1))) { return 0; } + if (lua_istable(L, 2)) { + uwsgi_lua_metatable_tostring(L, 1 - args); + } + msg = lua_tolstring(L, 2, &len); - uwsgi_alarm_trigger((char *) lua_tostring(L, 1), (char *) msg, len); + if (len) { + uwsgi_alarm_trigger((char *) lua_tostring(L, 1), (char *) msg, len); + } return 0; } static int uwsgi_api_async_sleep(lua_State *L) { - uint8_t argc = lua_gettop(L); + uint16_t argc = lua_gettop(L); if (argc == 0) goto end; struct wsgi_request *wsgi_req = current_wsgi_req(); @@ -964,7 +973,7 @@ end: } static int uwsgi_api_wait_fd_read(lua_State *L) { - uint8_t argc = lua_gettop(L); + uint16_t argc = lua_gettop(L); if (argc == 0) goto end; struct wsgi_request *wsgi_req = current_wsgi_req(); @@ -986,7 +995,7 @@ end: } static int uwsgi_api_wait_fd_write(lua_State *L) { - uint8_t argc = lua_gettop(L); + uint16_t argc = lua_gettop(L); if (argc == 0) goto end; struct wsgi_request *wsgi_req = current_wsgi_req(); @@ -1008,7 +1017,7 @@ end: } static int uwsgi_api_async_connect(lua_State *L) { - uint8_t argc = lua_gettop(L); + uint16_t argc = lua_gettop(L); if (argc == 0) goto end; int fd = uwsgi_connect((char *)lua_tostring(L, 1), 0, 1); @@ -1020,7 +1029,7 @@ end: } static int uwsgi_api_is_connected(lua_State *L) { - uint8_t argc = lua_gettop(L); + uint16_t argc = lua_gettop(L); if (argc == 0) goto end; int fd = lua_tonumber(L, 1); if (uwsgi_is_connected(fd)) { @@ -1035,7 +1044,7 @@ end: } static int uwsgi_api_close(lua_State *L) { - uint8_t argc = lua_gettop(L); + uint16_t argc = lua_gettop(L); if (argc == 0) goto end; int fd = lua_tonumber(L, 1); close(fd); @@ -1053,7 +1062,7 @@ static int uwsgi_api_ready_fd(lua_State *L) { } static int uwsgi_api_websocket_handshake(lua_State *L) { - uint8_t argc = lua_gettop(L); + uint16_t argc = lua_gettop(L); const char *key = NULL, *origin = NULL, *proto = NULL; size_t key_len = 0, origin_len = 0, proto_len = 0; @@ -1083,7 +1092,7 @@ error: } static int uwsgi_api_websocket_send(lua_State *L) { - int argc = lua_gettop(L); + uint16_t argc = lua_gettop(L); if (argc == 0) goto error; size_t message_len = 0; @@ -1107,7 +1116,7 @@ error: } static int uwsgi_api_websocket_send_binary(lua_State *L) { - int argc = lua_gettop(L); + uint16_t argc = lua_gettop(L); if (argc == 0) goto error; size_t message_len = 0; @@ -1131,7 +1140,7 @@ error: } static int uwsgi_api_websocket_send_from_sharedarea(lua_State *L) { - uint8_t argc = lua_gettop(L); + uint16_t argc = lua_gettop(L); if (argc < 2) goto error; int id = lua_tonumber(L, 1); @@ -1154,7 +1163,7 @@ error: } static int uwsgi_api_websocket_send_binary_from_sharedarea(lua_State *L) { - uint8_t argc = lua_gettop(L); + uint16_t argc = lua_gettop(L); if (argc < 2) goto error; int id = lua_tonumber(L, 1); @@ -1231,7 +1240,7 @@ static int uwsgi_api_chunked_read_nb(lua_State *L) { static int uwsgi_api_cache_get(lua_State *L) { - uint8_t argc = lua_gettop(L); + uint16_t argc = lua_gettop(L); char *value; uint64_t valsize; @@ -1312,8 +1321,8 @@ static int uwsgi_api_cache_get_multi(lua_State *L) { char *cache; - int argc = lua_gettop(L); - int i; + uint16_t argc = lua_gettop(L); + uint16_t i; if (argc < 2) { return 0; @@ -1353,9 +1362,9 @@ static int uwsgi_api_cache_get_tmulti(lua_State *L) { char *cache; - int argc = lua_gettop(L); - int error = 0; - int i; + uint16_t argc = lua_gettop(L); + uint16_t error = 0; + uint16_t i; if (argc < 2) { return 0; @@ -1526,7 +1535,7 @@ static int uwsgi_api_mypid(lua_State *L) { static int uwsgi_api_mule_msg_get(lua_State *L) { - uint8_t argc = lua_gettop(L); + uint16_t argc = lua_gettop(L); int manage_signals = 1; int manage_farms = 1; @@ -1534,7 +1543,7 @@ static int uwsgi_api_mule_msg_get(lua_State *L) { char *msg; - size_t buffer_size = ulua.mule_msg_get_buffer_size; + size_t buffer_size = ULUA_MULE_MSG_GET_BUFFER_SIZE; ssize_t len = 0; if (argc > 0 && lua_istable(L, 1)) { @@ -1580,7 +1589,7 @@ static int uwsgi_api_mule_msg(lua_State *L) { size_t msglen; char *msg; - uint8_t argc = lua_gettop(L); + uint16_t argc = lua_gettop(L); if (argc < 1 || !lua_isstring(L, 1)) { return 0; @@ -1642,12 +1651,12 @@ static int uwsgi_api_queue_push(lua_State *L) { size_t len; char *str; - int argc = lua_gettop(L); - int error = 0; + uint16_t argc = lua_gettop(L); + uint16_t error = 0; char **list; size_t *slen; - int i; + uint16_t i; if (!argc || !uwsgi.queue_size) { @@ -1723,10 +1732,10 @@ static int uwsgi_api_queue_set(lua_State *L) { uint64_t key; uint64_t len; char *str; - int i; + uint16_t i; - int error = 0; - int argc = lua_gettop(L); + uint16_t error = 0; + uint16_t argc = lua_gettop(L); if (!(argc && uwsgi.queue_size)) { return 0; @@ -1869,9 +1878,9 @@ static int uwsgi_api_queue_get(lua_State *L) { char *str; size_t len; - int i; - int argc = lua_gettop(L); + uint16_t i; + uint16_t argc = lua_gettop(L); uint64_t key; uint64_t *list; @@ -2104,7 +2113,7 @@ static const luaL_Reg uwsgi_api_mule[] = { {NULL, NULL} }; -static void uwsgi_lua_api_newtable(lua_State *L, const char *name) { +static void uwsgi_lua_api_newglobaltable(lua_State *L, const char *name) { lua_newtable(L); lua_pushvalue(L, -1); lua_setglobal(L, name); @@ -2121,10 +2130,6 @@ static void uwsgi_lua_api_push(lua_State *L, int target, const luaL_Reg *api) { static int uwsgi_lua_init() { int i; - - if (!ulua.mule_msg_get_buffer_size) { - ulua.mule_msg_get_buffer_size = ULUA_OPTDEF_MULE_MSG_GET_BUFFER_SIZE; - } if(!(ulua.gc_perform)) { ulua.gc_perform = LUA_GCSTEP; @@ -2177,7 +2182,7 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { // init worker state luaL_openlibs(L); - uwsgi_lua_api_newtable(L, "uwsgi"); + uwsgi_lua_api_newglobaltable(L, "uwsgi"); uwsgi_lua_api_push(L, -1, uwsgi_api_base); uwsgi_lua_api_push(L, -1, uwsgi_api_worker); @@ -2212,6 +2217,27 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { luaL_ref(L, LUA_REGISTRYINDEX); lua_setfield(L, -2, "rpc_ref"); + lua_pop(L, 1); + + //init additional threads for current worker + if (cores > 0) { + + lua_createtable(L, cores - 1, 0); + + for(i = 1; i < cores; i++) { + + // create thread and save it + Ls[i] = lua_newthread(L); + lua_rawseti(L, -2, i); + + } + + } else { + lua_pushboolean(L, 0); + } + + luaL_ref(L, LUA_REGISTRYINDEX); // ref 4 for threads + // init main app uslnargs = lua_gettop(L); @@ -2266,24 +2292,6 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { } else { lua_rawseti(L, LUA_REGISTRYINDEX, ULUA_WSAPI_REF); } - - //init additional threads for current worker - if (cores > 0) { - - lua_createtable(L, cores - 1, 0); - - for(i = 1; i < cores; i++) { - - // create thread and save it - Ls[i] = lua_newthread(L); - lua_rawseti(L, -2, i); - - } - - lua_setfield(L, -2, "luathreads"); - } - - lua_pop(L, 1); // post load usl = ulua.postload; @@ -2300,7 +2308,26 @@ static void uwsgi_lua_init_state(lua_State **Ls, int wid, int sid, int cores) { lua_gc(L, LUA_GCCOLLECT, 0); } -static void uwsgi_lua_request_headers_nested_tables(lua_State *, int8_t, struct wsgi_request *, char *, size_t); +static void uwsgi_lua_request_headers_nested_tables(lua_State *L, int8_t table, struct wsgi_request *wsgi_req, char *header, size_t len) { + + size_t i, rlen; + char *rheader; + + size_t tlen = lua_rawlen(L, table); + + for (i = 1; i <= tlen; i++) { + lua_rawgeti(L, table, i); + + if (lua_istable(L, -1)) { + uwsgi_lua_request_headers_nested_tables(L, -1, wsgi_req, header, len); + } else { + rheader = (char *) lua_tolstring(L, -1, &rlen); + uwsgi_response_add_header(wsgi_req, header, len, rheader, rlen); + } + + lua_pop(L, 1); + } +} static int uwsgi_lua_request(struct wsgi_request *wsgi_req) { @@ -2308,7 +2335,7 @@ static int uwsgi_lua_request(struct wsgi_request *wsgi_req) { size_t i, slen, slen2; if(!ulua.wsapi) { - ulua_log("wsapi[%d][%d]: No WSAPI App. skip.", uwsgi.mywid, wsgi_req->async_id); + ulua_log("worker%d[%d]: No WSAPI App. skip.", uwsgi.mywid, wsgi_req->async_id); return -1; } @@ -2316,7 +2343,7 @@ static int uwsgi_lua_request(struct wsgi_request *wsgi_req) { /* Standard WSAPI request */ if (!wsgi_req->len) { - ulua_log("wsapi[%d][%d]: Empty lua request. skip.", uwsgi.mywid, wsgi_req->async_id); + ulua_log("worker%d[%d]: Empty lua request. skip.", uwsgi.mywid, wsgi_req->async_id); return -1; } @@ -2377,7 +2404,7 @@ static int uwsgi_lua_request(struct wsgi_request *wsgi_req) { // call function if (lua_pcall(L, 1, 4, 0)) { - ulua_log("wsapi[%d][%d]: %s", uwsgi.mywid, wsgi_req->async_id, lua_tostring(L, -1)); + ulua_log("worker%d[%d]: %s", uwsgi.mywid, wsgi_req->async_id, lua_tostring(L, -1)); lua_pop(L, 1); goto clear2; } @@ -2390,7 +2417,7 @@ static int uwsgi_lua_request(struct wsgi_request *wsgi_req) { http = lua_tolstring(L, -4, &slen); if (!slen) { - ulua_log("wsapi[%d][%d]: invalid response status!", uwsgi.mywid, wsgi_req->async_id); + ulua_log("worker%d[%d]: invalid response status!", uwsgi.mywid, wsgi_req->async_id); } if (uwsgi_response_prepare_headers(wsgi_req, (char *) http, slen)) { @@ -2445,7 +2472,7 @@ static int uwsgi_lua_request(struct wsgi_request *wsgi_req) { } } else { - ulua_log("wsapi-coroutine[%d][%d]: %s", uwsgi.mywid, wsgi_req->async_id, lua_tostring(L, -1)); + ulua_log("worker%d[%d]: init-coroutine: %s", uwsgi.mywid, wsgi_req->async_id, lua_tostring(L, -1)); lua_pop(L, 1); break; } @@ -2500,27 +2527,6 @@ clear2: } -static void uwsgi_lua_request_headers_nested_tables(lua_State *L, int8_t table, struct wsgi_request *wsgi_req, char *header, size_t len) { - - size_t i, rlen; - char *rheader; - - size_t tlen = lua_rawlen(L, table); - - for (i = 1; i <= tlen; i++) { - lua_rawgeti(L, table, i); - - if (lua_istable(L, -1)) { - uwsgi_lua_request_headers_nested_tables(L, -1, wsgi_req, header, len); - } else { - rheader = (char *) lua_tolstring(L, -1, &rlen); - uwsgi_response_add_header(wsgi_req, header, len, rheader, rlen); - } - - lua_pop(L, 1); - } -} - static void uwsgi_lua_after_request(struct wsgi_request *wsgi_req) { log_request(wsgi_req); @@ -2622,7 +2628,8 @@ static int uwsgi_lua_signal_handler(uint8_t sig, void *handler) { int type; lua_rawgeti(L, LUA_REGISTRYINDEX, ULUA_SIGNAL_REF); - lua_rawgeti(L, -1, sig); + lua_pushnumber(L, sig); + lua_gettable(L, -2); type = lua_type(L, -1); @@ -2656,8 +2663,7 @@ static uint64_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t a lua_State *L = ULUA_WORKER_STATE[wsgi_req->async_id]; lua_rawgeti(L, LUA_REGISTRYINDEX, ULUA_RPC_REF); - lua_pushstring(L, (char *) func); - lua_rawget(L, -2); + lua_getfield(L, -1, (const char *) func); type = lua_type(L, -1); @@ -2905,7 +2911,7 @@ static int uwsgi_lua_mule(char *file) { luaL_openlibs(L); - uwsgi_lua_api_newtable(L, "uwsgi"); + uwsgi_lua_api_newglobaltable(L, "uwsgi"); uwsgi_lua_api_push(L, -1, uwsgi_api_base); uwsgi_lua_api_push(L, -1, uwsgi_api_mule); From 7e601d6d8ddbaf09640cb752f85df8f9526dd10f Mon Sep 17 00:00:00 2001 From: Hleran Date: Sun, 13 Sep 2015 07:01:12 +0300 Subject: [PATCH 17/17] lua_plugin: cache_exists_multi, no false pls return nil instead of false --- plugins/lua/lua_plugin.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/lua/lua_plugin.c b/plugins/lua/lua_plugin.c index 9064abc4..d52d3959 100644 --- a/plugins/lua/lua_plugin.c +++ b/plugins/lua/lua_plugin.c @@ -682,7 +682,12 @@ static int uwsgi_api_cache_exists_multi(lua_State *L) { for (i = 2; i <= argc; i++) { key = (char *) lua_tolstring(L, i, &keylen); - lua_pushboolean(L, keylen && uwsgi_cache_magic_exists(key, keylen, cache)); + + if (keylen && uwsgi_cache_magic_exists(key, keylen, cache)) { + lua_pushboolean(L, 1); + } else { + lua_pushnil(L); + } }