You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
186 lines
4.0 KiB
Lua
186 lines
4.0 KiB
Lua
local skynet = require "skynet"
|
|
local core = require "skynet.core"
|
|
require "skynet.manager" -- import manager apis
|
|
local string = string
|
|
|
|
local services = {}
|
|
local command = {}
|
|
local instance = {} -- for confirm (function command.LAUNCH / command.ERROR / command.LAUNCHOK)
|
|
local launch_session = {} -- for command.QUERY, service_address -> session
|
|
|
|
local function handle_to_address(handle)
|
|
return tonumber("0x" .. string.sub(handle , 2))
|
|
end
|
|
|
|
local NORET = {}
|
|
|
|
function command.LIST()
|
|
local list = {}
|
|
for k,v in pairs(services) do
|
|
list[skynet.address(k)] = v
|
|
end
|
|
return list
|
|
end
|
|
|
|
local function list_srv(ti, fmt_func, ...)
|
|
local list = {}
|
|
local sessions = {}
|
|
local req = skynet.request()
|
|
for addr in pairs(services) do
|
|
local r = { addr, "debug", ... }
|
|
req:add(r)
|
|
sessions[r] = addr
|
|
end
|
|
for req, resp in req:select(ti) do
|
|
local addr = req[1]
|
|
if resp then
|
|
local stat = resp[1]
|
|
list[skynet.address(addr)] = fmt_func(stat, addr)
|
|
else
|
|
list[skynet.address(addr)] = fmt_func("ERROR", addr)
|
|
end
|
|
sessions[req] = nil
|
|
end
|
|
for session, addr in pairs(sessions) do
|
|
list[skynet.address(addr)] = fmt_func("TIMEOUT", addr)
|
|
end
|
|
return list
|
|
end
|
|
|
|
function command.STAT(addr, ti)
|
|
return list_srv(ti, function(v) return v end, "STAT")
|
|
end
|
|
|
|
function command.KILL(_, handle)
|
|
skynet.kill(handle)
|
|
local ret = { [skynet.address(handle)] = tostring(services[handle]) }
|
|
services[handle] = nil
|
|
return ret
|
|
end
|
|
|
|
function command.MEM(addr, ti)
|
|
return list_srv(ti, function(kb, addr)
|
|
local v = services[addr]
|
|
if type(kb) == "string" then
|
|
return string.format("%s (%s)", kb, v)
|
|
else
|
|
return string.format("%.2f Kb (%s)",kb,v)
|
|
end
|
|
end, "MEM")
|
|
end
|
|
|
|
function command.GC(addr, ti)
|
|
for k,v in pairs(services) do
|
|
skynet.send(k,"debug","GC")
|
|
end
|
|
return command.MEM(addr, ti)
|
|
end
|
|
|
|
function command.REMOVE(_, handle, kill)
|
|
services[handle] = nil
|
|
local response = instance[handle]
|
|
if response then
|
|
-- instance is dead
|
|
response(not kill) -- return nil to caller of newservice, when kill == false
|
|
instance[handle] = nil
|
|
launch_session[handle] = nil
|
|
end
|
|
|
|
-- don't return (skynet.ret) because the handle may exit
|
|
return NORET
|
|
end
|
|
|
|
local function launch_service(service, ...)
|
|
local param = table.concat({...}, " ")
|
|
local inst = skynet.launch(service, param)
|
|
local session = skynet.context()
|
|
local response = skynet.response()
|
|
if inst then
|
|
services[inst] = service .. " " .. param
|
|
instance[inst] = response
|
|
launch_session[inst] = session
|
|
else
|
|
response(false)
|
|
return
|
|
end
|
|
return inst
|
|
end
|
|
|
|
function command.LAUNCH(_, service, ...)
|
|
launch_service(service, ...)
|
|
return NORET
|
|
end
|
|
|
|
function command.LOGLAUNCH(_, service, ...)
|
|
local inst = launch_service(service, ...)
|
|
if inst then
|
|
core.command("LOGON", skynet.address(inst))
|
|
end
|
|
return NORET
|
|
end
|
|
|
|
function command.ERROR(address)
|
|
-- see serivce-src/service_lua.c
|
|
-- init failed
|
|
local response = instance[address]
|
|
if response then
|
|
response(false)
|
|
launch_session[address] = nil
|
|
instance[address] = nil
|
|
end
|
|
services[address] = nil
|
|
return NORET
|
|
end
|
|
|
|
function command.LAUNCHOK(address)
|
|
-- init notice
|
|
local response = instance[address]
|
|
if response then
|
|
response(true, address)
|
|
instance[address] = nil
|
|
launch_session[address] = nil
|
|
end
|
|
|
|
return NORET
|
|
end
|
|
|
|
function command.QUERY(_, request_session)
|
|
for address, session in pairs(launch_session) do
|
|
if session == request_session then
|
|
return address
|
|
end
|
|
end
|
|
end
|
|
|
|
-- for historical reasons, launcher support text command (for C service)
|
|
|
|
skynet.register_protocol {
|
|
name = "text",
|
|
id = skynet.PTYPE_TEXT,
|
|
unpack = skynet.tostring,
|
|
dispatch = function(session, address , cmd)
|
|
if cmd == "" then
|
|
command.LAUNCHOK(address)
|
|
elseif cmd == "ERROR" then
|
|
command.ERROR(address)
|
|
else
|
|
error ("Invalid text command " .. cmd)
|
|
end
|
|
end,
|
|
}
|
|
|
|
skynet.dispatch("lua", function(session, address, cmd , ...)
|
|
cmd = string.upper(cmd)
|
|
local f = command[cmd]
|
|
if f then
|
|
local ret = f(address, ...)
|
|
if ret ~= NORET then
|
|
skynet.ret(skynet.pack(ret))
|
|
end
|
|
else
|
|
skynet.ret(skynet.pack {"Unknown command"} )
|
|
end
|
|
end)
|
|
|
|
skynet.start(function() end)
|