Skip to content

Commit

Permalink
hotfix snax supported
Browse files Browse the repository at this point in the history
  • Loading branch information
cloudwu committed Apr 16, 2014
1 parent df5c619 commit 58dfe38
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 14 deletions.
27 changes: 19 additions & 8 deletions lualib/snax.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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 changes: 107 additions & 0 deletions lualib/snax_hotfix.lua
Original file line number Diff line number Diff line change
@@ -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
7 changes: 4 additions & 3 deletions lualib/snax_interface.lua
Original file line number Diff line number Diff line change
@@ -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)
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
13 changes: 12 additions & 1 deletion service/snaxd.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 5 additions & 1 deletion test/pingserver.lua
Original file line number Diff line number Diff line change
@@ -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()
Expand Down
4 changes: 3 additions & 1 deletion test/testping.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)

0 comments on commit 58dfe38

Please sign in to comment.