From 40d2f894430513ff1796e4071bc451a243e24da4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=91=E9=A3=8E?= Date: Sat, 27 Oct 2012 22:48:38 +0800 Subject: [PATCH] reload snlua service --- Makefile | 2 +- lualib-src/lua-skynet.c | 75 +++++++++++++++++++++++++++++--------- lualib/skynet.lua | 5 +++ service-src/service_lua.c | 30 +++++++++------ service-src/service_lua.h | 11 ++++++ service/launcher.lua | 12 ++++++ skynet-src/skynet_server.c | 1 - 7 files changed, 106 insertions(+), 30 deletions(-) create mode 100644 service-src/service_lua.h diff --git a/Makefile b/Makefile index 3c670f0e..dd326550 100644 --- a/Makefile +++ b/Makefile @@ -67,7 +67,7 @@ service/localcast.so : service-src/service_localcast.c gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src luaclib/skynet.so : lualib-src/lua-skynet.c lualib-src/lua-seri.c lualib-src/lua-remoteobj.c lualib-src/trace_service.c | luaclib - gcc $(CFLAGS) $(SHARED) -Iluacompat $^ -o $@ -Iskynet-src -Ilualib-src + gcc $(CFLAGS) $(SHARED) -Iluacompat $^ -o $@ -Iskynet-src -Iservice-src -Ilualib-src service/client.so : service-src/service_client.c gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src diff --git a/lualib-src/lua-skynet.c b/lualib-src/lua-skynet.c index 7fa8a28a..d37aaade 100644 --- a/lualib-src/lua-skynet.c +++ b/lualib-src/lua-skynet.c @@ -1,6 +1,7 @@ #include "skynet.h" #include "trace_service.h" #include "lua-seri.h" +#include "service_lua.h" #include "luacompat52.h" @@ -20,6 +21,7 @@ struct stat { uint32_t ti_sec; uint32_t ti_nsec; struct trace_pool *trace; + struct snlua *lua; }; static void @@ -81,8 +83,27 @@ _cb(struct skynet_context * context, void * ud, int type, int session, uint32_t int r = lua_pcall(L, 5, 0 , trace); _stat_end(S, &ti); - if (r == LUA_OK) + if (r == LUA_OK) { + if (S->lua->reload) { + skynet_callback(context, NULL, 0); + struct snlua * lua = S->lua; + assert(lua->L == L); + const char * cmd = lua->reload; + lua->reload = NULL; + lua->L = luaL_newstate(); + int err = lua->init(lua, context, cmd); + if (err) { + skynet_callback(context, S, _cb); + skynet_error(context, "lua reload failed : %s", cmd); + lua_close(lua->L); + lua->L = L; + } else { + skynet_error(context, "lua reload %s", cmd); + lua_close(L); + } + } return 0; + } const char * self = skynet_command(context, "REG", NULL); switch (r) { case LUA_ERRRUN: @@ -113,10 +134,11 @@ _delete_stat(lua_State *L) { static int _callback(lua_State *L) { - struct skynet_context * context = lua_touserdata(L, lua_upvalueindex(1)); - if (context == NULL) { + struct snlua *lua = lua_touserdata(L, lua_upvalueindex(1)); + if (lua == NULL || lua->ctx == NULL) { return luaL_error(L, "Init skynet context first"); } + struct skynet_context * context = lua->ctx; luaL_checktype(L,1,LUA_TFUNCTION); lua_settop(L,1); @@ -129,6 +151,7 @@ _callback(lua_State *L) { memset(S, 0, sizeof(*S)); S->L = gL; S->trace = trace_create(); + S->lua = lua; lua_createtable(L,0,1); lua_pushcfunction(L, _delete_stat); @@ -398,6 +421,15 @@ _trace_register(lua_State *L) { return 0; } +static int +_reload(lua_State *L) { + struct snlua *lua = lua_touserdata(L,lua_upvalueindex(1)); + lua->reload = luaL_checkstring(L,1); + lua_settop(L,1); + lua_replace(L,lua_upvalueindex(2)); + return 0; +} + // define in lua-remoteobj.c int remoteobj_init(lua_State *L); @@ -417,26 +449,12 @@ luaopen_skynet_c(lua_State *L) { { "redirect", _redirect }, { "forward", _forward }, { "command" , _command }, - { "callback" , _callback }, { "error", _error }, { "tostring", _tostring }, { "harbor", _harbor }, { NULL, NULL }, }; - lua_createtable(L, 0, (sizeof(pack) + sizeof(l))/sizeof(luaL_Reg)-2); - lua_newtable(L); - lua_pushstring(L,"__remote"); - luaL_setfuncs(L,pack,2); - - lua_getfield(L, LUA_REGISTRYINDEX, "skynet_context"); - struct skynet_context * ctx = lua_touserdata(L,-1); - if (ctx == NULL) { - return luaL_error(L, "Init skynet context first"); - } - - luaL_setfuncs(L,l,1); - luaL_Reg l2[] = { { "stat", _stat }, { "remote_init", remoteobj_init }, @@ -448,6 +466,29 @@ luaopen_skynet_c(lua_State *L) { { NULL, NULL }, }; + lua_createtable(L, 0, (sizeof(pack) + sizeof(l) + sizeof(l2))/sizeof(luaL_Reg)-1); + lua_newtable(L); + lua_pushstring(L,"__remote"); + luaL_setfuncs(L,pack,2); + + lua_getfield(L, LUA_REGISTRYINDEX, "skynet_lua"); + struct snlua *lua = lua_touserdata(L,-1); + if (lua == NULL || lua->ctx == NULL) { + return luaL_error(L, "Init skynet context first"); + } + assert(lua->L == L); + + lua_pushvalue(L,-1); + lua_pushcclosure(L,_callback,1); + lua_setfield(L, -3, "callback"); + + lua_pushnil(L); + lua_pushcclosure(L,_reload,2); + lua_setfield(L, -2, "reload"); + + lua_pushlightuserdata(L, lua->ctx); + luaL_setfuncs(L,l,1); + luaL_setfuncs(L,l2,0); return 1; diff --git a/lualib/skynet.lua b/lualib/skynet.lua index 366b35e4..700ce1d7 100644 --- a/lualib/skynet.lua +++ b/lualib/skynet.lua @@ -465,6 +465,11 @@ function dbgcmd.INFO() end end +function dbgcmd.RELOAD(...) + local cmd = table.concat({...}, " ") + c.reload(cmd) +end + local function _debug_dispatch(session, address, cmd, ...) local f = dbgcmd[cmd] assert(f, cmd) diff --git a/service-src/service_lua.c b/service-src/service_lua.c index a0124a11..ad637d7f 100644 --- a/service-src/service_lua.c +++ b/service-src/service_lua.c @@ -4,17 +4,13 @@ #include #include #include "luacompat52.h" +#include "service_lua.h" #include #include #include #include -lua_State * -snlua_create(void) { - return luaL_newstate(); -} - static int _try_load(lua_State *L, const char * path, int pathlen, const char * name) { int namelen = strlen(name); @@ -102,12 +98,14 @@ traceback (lua_State *L) { } int -snlua_init(lua_State *L, struct skynet_context *ctx, const char * args) { +snlua_init(struct snlua *l, struct skynet_context *ctx, const char * args) { + lua_State *L = l->L; + l->ctx = ctx; luaL_init(L); lua_gc(L, LUA_GCSTOP, 0); luaL_openlibs(L); - lua_pushlightuserdata(L, ctx); - lua_setfield(L, LUA_REGISTRYINDEX, "skynet_context"); + lua_pushlightuserdata(L, l); + lua_setfield(L, LUA_REGISTRYINDEX, "skynet_lua"); lua_gc(L, LUA_GCRESTART, 0); char tmp[strlen(args)+1]; @@ -159,7 +157,17 @@ snlua_init(lua_State *L, struct skynet_context *ctx, const char * args) { return 1; } -void -snlua_release(lua_State *L) { - lua_close(L); +struct snlua * +snlua_create(void) { + struct snlua * l = malloc(sizeof(*l)); + memset(l,0,sizeof(*l)); + l->L = luaL_newstate(); + l->init = snlua_init; + return l; +} + +void +snlua_release(struct snlua *l) { + lua_close(l->L); + free(l); } diff --git a/service-src/service_lua.h b/service-src/service_lua.h new file mode 100644 index 00000000..7c9b8dde --- /dev/null +++ b/service-src/service_lua.h @@ -0,0 +1,11 @@ +#ifndef SKYNET_SERVICE_LUA_H +#define SKYNET_SERVICE_LUA_H + +struct snlua { + lua_State * L; + const char * reload; + struct skynet_context * ctx; + int (*init)(struct snlua *l, struct skynet_context *ctx, const char * args); +}; + +#endif diff --git a/service/launcher.lua b/service/launcher.lua index 05912b3a..b9aaace6 100644 --- a/service/launcher.lua +++ b/service/launcher.lua @@ -17,6 +17,18 @@ function command.LIST() skynet.ret(skynet.pack(list)) end +function command.RELOAD(handle) + handle = handle_to_address(handle) + local cmd = string.match(services[handle], "snlua (.+)") + print(services[handle],cmd) + if cmd then + skynet.send(handle,"debug","RELOAD",cmd) + skynet.ret(skynet.pack({cmd})) + else + skynet.ret(skynet.pack({"Support only snlua"})) + end +end + function command.STAT() local list = {} for k,v in pairs(services) do diff --git a/skynet-src/skynet_server.c b/skynet-src/skynet_server.c index 19f11147..7383f732 100644 --- a/skynet-src/skynet_server.c +++ b/skynet-src/skynet_server.c @@ -588,7 +588,6 @@ skynet_context_init(struct skynet_context *ctx, uint32_t handle) { void skynet_callback(struct skynet_context * context, void *ud, skynet_cb cb) { - assert(context->cb == NULL); context->cb = cb; context->cb_ud = ud; }