mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-22 02:53:09 +00:00
hotfix snax supported
This commit is contained in:
@@ -21,13 +21,7 @@ function snax.interface(name)
|
||||
|
||||
for _,v in ipairs(si) do
|
||||
local id, group, name, f = table.unpack(v)
|
||||
if group == "system" then
|
||||
if f then
|
||||
ret.system[name] = id
|
||||
end
|
||||
else
|
||||
ret[group][name] = id
|
||||
end
|
||||
ret[group][name] = id
|
||||
end
|
||||
|
||||
typeclass[name] = ret
|
||||
@@ -65,7 +59,6 @@ local function wrapper(handle, name, type)
|
||||
req = gen_req(type, handle),
|
||||
type = name,
|
||||
handle = handle,
|
||||
kill = function(...) return skynet_call(handle, "lua", type.system.exit, ...) end,
|
||||
}, meta)
|
||||
end
|
||||
|
||||
@@ -95,4 +88,22 @@ function snax.bind(handle, type)
|
||||
return ret
|
||||
end
|
||||
|
||||
function snax.kill(obj, ...)
|
||||
local t = snax.interface(obj.type)
|
||||
return skynet_call(obj.handle, "lua", t.system.exit, ...)
|
||||
end
|
||||
|
||||
local function test_result(ok, ...)
|
||||
if ok then
|
||||
return ...
|
||||
else
|
||||
error(...)
|
||||
end
|
||||
end
|
||||
|
||||
function snax.hotfix(obj, ...)
|
||||
local t = snax.interface(obj.type)
|
||||
test_result(skynet_call(obj.handle, "lua", t.system.hotfix, obj.type, ...))
|
||||
end
|
||||
|
||||
return snax
|
||||
|
||||
107
lualib/snax_hotfix.lua
Normal file
107
lualib/snax_hotfix.lua
Normal file
@@ -0,0 +1,107 @@
|
||||
local si = require "snax_interface"
|
||||
local io = io
|
||||
|
||||
local hotfix = {}
|
||||
|
||||
local function loader(filename, ...)
|
||||
local f = io.open(filename, "rb")
|
||||
if not f then
|
||||
return false, string.format("Can't open %s", filename)
|
||||
end
|
||||
local source = f:read "*a"
|
||||
f:close()
|
||||
|
||||
return load(source, "@"..filename, ...)
|
||||
end
|
||||
|
||||
local function check_funcs(f1,f2)
|
||||
for k,a in pairs(f1) do
|
||||
local b = f2[k]
|
||||
assert(a[1] == b[1] and a[2] == b[2] and a[3] == b[3] ,
|
||||
string.format("%s.%s %s.%s , function mismatch", a[2], a[3] , b[2], b[3]))
|
||||
end
|
||||
end
|
||||
|
||||
local function get_upvalues(f, global)
|
||||
local uv = {}
|
||||
local i = 1
|
||||
while true do
|
||||
local name = debug.getupvalue(f, i)
|
||||
if name then
|
||||
local uid = debug.upvalueid(f, i)
|
||||
uv[name] = i
|
||||
if global[name] and global[name][1] ~= uid then
|
||||
error(string.format("ambiguity upvalue %s", name))
|
||||
end
|
||||
global[name] = { uid , f , i }
|
||||
else
|
||||
break
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
return uv
|
||||
end
|
||||
|
||||
local function join_upvalues(f, new_f, uv)
|
||||
local i = 1
|
||||
while true do
|
||||
local name = debug.getupvalue(new_f, i)
|
||||
if name then
|
||||
if uv[name] then
|
||||
debug.upvaluejoin(new_f, i, f, uv[name])
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
local function join_global_upvalues(f, global)
|
||||
local i = 1
|
||||
while true do
|
||||
local name = debug.getupvalue(f, i)
|
||||
if name then
|
||||
local uv = global[name]
|
||||
if uv then
|
||||
debug.upvaluejoin(f, i, uv[2], uv[3])
|
||||
end
|
||||
else
|
||||
break
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
local function update_upvalues(funcs, newfuncs)
|
||||
local global = {}
|
||||
for id,v in pairs(funcs) do
|
||||
local f = v[4]
|
||||
local new_f = newfuncs[id][4]
|
||||
if f and new_f then
|
||||
local uv = get_upvalues(f, global)
|
||||
v[4] = new_f
|
||||
join_upvalues(f, new_f, uv)
|
||||
newfuncs[id] = nil
|
||||
end
|
||||
end
|
||||
for id,v in pairs(newfuncs) do
|
||||
if v[2] == "system" then
|
||||
funcs[id] = v
|
||||
local f = v[4]
|
||||
join_global_upvalues(f, global)
|
||||
else
|
||||
error(string.format("Detect unkown function %s.%s", v[2], v[3]))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function inject(funcs, new)
|
||||
check_funcs(funcs, new)
|
||||
update_upvalues(funcs, new)
|
||||
end
|
||||
|
||||
return function (funcs, modname)
|
||||
local new_funcs = si(modname, _ENV, loader)
|
||||
return pcall(inject, funcs, new_funcs)
|
||||
end
|
||||
@@ -1,6 +1,7 @@
|
||||
local skynet = require "skynet"
|
||||
|
||||
return function (name , G)
|
||||
return function (name , G, loader)
|
||||
loader = loader or loadfile
|
||||
local mainfunc
|
||||
|
||||
local function func_id(id, group)
|
||||
@@ -33,7 +34,7 @@ return function (name , G)
|
||||
local env = {}
|
||||
local func = {}
|
||||
|
||||
local system = { "init", "exit" }
|
||||
local system = { "init", "exit", "hotfix" }
|
||||
|
||||
do
|
||||
for k, v in ipairs(system) do
|
||||
@@ -62,7 +63,7 @@ return function (name , G)
|
||||
|
||||
for pat in string.gmatch(path,"[^;]+") do
|
||||
local filename = string.gsub(pat, "?", name)
|
||||
local f , err = loadfile(filename, "bt", G)
|
||||
local f , err = loader(filename, "bt", G)
|
||||
if f then
|
||||
mainfunc = f
|
||||
break
|
||||
|
||||
@@ -8,13 +8,24 @@ skynet.start(function()
|
||||
skynet.dispatch("lua", function ( _, _, id, ...)
|
||||
local method = func[id]
|
||||
if method[2] == "system" then
|
||||
if method[3] == "init" then
|
||||
local command = method[3]
|
||||
if command == "hotfix" then
|
||||
local hotfix = require "snax_hotfix"
|
||||
local ok, msg = hotfix(func, ...)
|
||||
if ok then
|
||||
local hf = func[id][4]
|
||||
skynet.ret(skynet.pack(pcall(hf, select(2,...))))
|
||||
else
|
||||
skynet.ret(skynet.pack(ok, msg))
|
||||
end
|
||||
elseif command == "init" then
|
||||
assert(not init, "Already init")
|
||||
local initfunc = method[4] or function() end
|
||||
skynet.ret(skynet.pack(initfunc(...)))
|
||||
init = true
|
||||
else
|
||||
assert(init, "Never init")
|
||||
assert(command == "exit")
|
||||
local exitfunc = method[4] or function() end
|
||||
skynet.ret(skynet.pack(exitfunc(...)))
|
||||
init = false
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
local skynet = require "skynet"
|
||||
|
||||
local i = 0
|
||||
local hello = "hello"
|
||||
|
||||
function response.ping(hello)
|
||||
skynet.sleep(100)
|
||||
return hello
|
||||
end
|
||||
|
||||
function subscribe.hello()
|
||||
print "hello"
|
||||
i = i + 1
|
||||
print (i, hello)
|
||||
end
|
||||
|
||||
function response.error()
|
||||
|
||||
@@ -6,6 +6,8 @@ skynet.start(function()
|
||||
print(ps.pub.hello())
|
||||
print(ps.req.ping("foobar"))
|
||||
print(pcall(ps.req.error))
|
||||
print(ps.kill("exit"))
|
||||
snax.hotfix(ps)
|
||||
print(ps.pub.hello())
|
||||
print(snax.kill(ps,"exit"))
|
||||
skynet.exit()
|
||||
end)
|
||||
|
||||
Reference in New Issue
Block a user