From 2d56a2215a102330771e75bd31d4eb1b5794d608 Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Sat, 19 Apr 2014 16:47:52 +0800 Subject: [PATCH 1/5] optimize global unique service query --- lualib/skynet.lua | 22 ++-------- service/service_mgr.lua | 93 +++++++++++++++++++++++++++++------------ 2 files changed, 70 insertions(+), 45 deletions(-) diff --git a/lualib/skynet.lua b/lualib/skynet.lua index 139a5b29..77d9ab12 100644 --- a/lualib/skynet.lua +++ b/lualib/skynet.lua @@ -410,26 +410,12 @@ function skynet.newservice(name, ...) end end -function skynet.uniqueservice(global, ...) - local handle - if global == true then - handle = skynet.call("SERVICE", "lua", "LAUNCH", ...) - else - handle = skynet.call(".service", "lua", "LAUNCH", global, ...) - end - assert(handle , "Unique service launch failed") - return handle +function skynet.uniqueservice(...) + return assert(skynet.call(".service", "lua", "LAUNCH", ...)) end -function skynet.queryservice(global, ...) - local handle - if global == true then - handle = skynet.call("SERVICE", "lua", "QUERY", ...) - else - handle = skynet.call(".service", "lua", "QUERY", global, ...) - end - assert(handle , "Unique service query failed") - return handle +function skynet.queryservice(global, name) + return assert(skynet.call(".service", "lua", "QUERY", global, name)) end local function group_command(cmd, handle, address) diff --git a/service/service_mgr.lua b/service/service_mgr.lua index 7f771f3f..44d85d5b 100644 --- a/service/service_mgr.lua +++ b/service/service_mgr.lua @@ -3,53 +3,91 @@ local skynet = require "skynet" local cmd = {} local service = {} -function cmd.LAUNCH(service_name, ...) - local s = service[service_name] - if type(s) == "number" then - return s +local GLOBAL = false + +local function request(name, func, ...) + local ok, handle = pcall(func, ...) + local s = service[name] + assert(type(s) == "table") + if ok then + service[name] = handle + else + service[name] = tostring(handle) end - if s == nil then - s = { launch = true } - service[service_name] = s - elseif s.launch then - assert(type(s) == "table") - local co = coroutine.running() - table.insert(s, co) - skynet.wait() - s = service[service_name] - assert(type(s) == "number") - return s - end - - local handle = skynet.newservice(service_name, ...) for _,v in ipairs(s) do skynet.wakeup(v) end - service[service_name] = handle - - return handle + if ok then + return handle + else + error(tostring(handle)) + end end -function cmd.QUERY(service_name) - local s = service[service_name] +local function waitfor(name , func, ...) + local s = service[name] if type(s) == "number" then return s end + local co = coroutine.running() + if s == nil then s = {} - service[service_name] = s + service[name] = s + elseif type(s) == "string" then + error(s) end + assert(type(s) == "table") - local co = coroutine.running() + + if not s.launch and func then + s.launch = true + return request(name, func, ...) + end + table.insert(s, co) skynet.wait() - s = service[service_name] + s = service[name] + if type(s) == "string" then + error(s) + end assert(type(s) == "number") return s end +local function GQUERY(service_name) + if GLOBAL then + return cmd.QUERY(service_name) + else + return waitfor(service_name, skynet.call, "SERVICE", "lua", "QUERY", service_name) + end +end + +local function GLAUNCH(service_name, ...) + if GLOBAL then + return cmd.LAUNCH(service_name, ...) + else + return waitfor(service_name, skynet.call, "SERVICE", "lua", "LAUNCH", service_name, ...) + end +end + +function cmd.LAUNCH(global, service_name, ...) + if global == true then + return GLAUNCH(service_name, ...) + else + return waitfor(global, skynet.newservice, global, service_name, ...) + end +end + +function cmd.QUERY(global, service_name) + if global == true then + return GQUERY(service_name) + end + return waitfor(global) +end + skynet.start(function() skynet.dispatch("lua", function(session, address, command, service_name , ...) local f = cmd[command] @@ -62,11 +100,12 @@ skynet.start(function() if ok then skynet.ret(skynet.pack(r)) else - skynet.ret(skynet.pack(nil)) + skynet.ret(skynet.pack(nil, r)) end end) skynet.register(".service") if skynet.getenv "standalone" then + GLOBAL = true skynet.register("SERVICE") end end) From 93cb091894f917b84fd945aba5394ffa6814ca03 Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Sat, 19 Apr 2014 16:51:12 +0800 Subject: [PATCH 2/5] assert service name is string --- service/service_mgr.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/service/service_mgr.lua b/service/service_mgr.lua index 44d85d5b..09994d0f 100644 --- a/service/service_mgr.lua +++ b/service/service_mgr.lua @@ -77,6 +77,7 @@ function cmd.LAUNCH(global, service_name, ...) if global == true then return GLAUNCH(service_name, ...) else + assert(type(global) == "string") return waitfor(global, skynet.newservice, global, service_name, ...) end end @@ -84,8 +85,10 @@ end function cmd.QUERY(global, service_name) if global == true then return GQUERY(service_name) + else + assert(type(global) == "string") + return waitfor(global) end - return waitfor(global) end skynet.start(function() From ba27feee3562bf82279f81140b9deab76e9e7624 Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Sat, 19 Apr 2014 17:03:58 +0800 Subject: [PATCH 3/5] make service mgr simple --- lualib/skynet.lua | 4 ++-- service/service_mgr.lua | 51 +++++++++++++++-------------------------- 2 files changed, 20 insertions(+), 35 deletions(-) diff --git a/lualib/skynet.lua b/lualib/skynet.lua index 77d9ab12..a6b46720 100644 --- a/lualib/skynet.lua +++ b/lualib/skynet.lua @@ -414,8 +414,8 @@ function skynet.uniqueservice(...) return assert(skynet.call(".service", "lua", "LAUNCH", ...)) end -function skynet.queryservice(global, name) - return assert(skynet.call(".service", "lua", "QUERY", global, name)) +function skynet.queryservice(...) + return assert(skynet.call(".service", "lua", "QUERY", ...)) end local function group_command(cmd, handle, address) diff --git a/service/service_mgr.lua b/service/service_mgr.lua index 09994d0f..7b5f5b12 100644 --- a/service/service_mgr.lua +++ b/service/service_mgr.lua @@ -57,49 +57,34 @@ local function waitfor(name , func, ...) return s end -local function GQUERY(service_name) - if GLOBAL then - return cmd.QUERY(service_name) - else - return waitfor(service_name, skynet.call, "SERVICE", "lua", "QUERY", service_name) - end +function cmd.LAUNCH(service_name, ...) + return waitfor(service_name, skynet.newservice, service_name, ...) end -local function GLAUNCH(service_name, ...) - if GLOBAL then - return cmd.LAUNCH(service_name, ...) - else - return waitfor(service_name, skynet.call, "SERVICE", "lua", "LAUNCH", service_name, ...) - end -end - -function cmd.LAUNCH(global, service_name, ...) - if global == true then - return GLAUNCH(service_name, ...) - else - assert(type(global) == "string") - return waitfor(global, skynet.newservice, global, service_name, ...) - end -end - -function cmd.QUERY(global, service_name) - if global == true then - return GQUERY(service_name) - else - assert(type(global) == "string") - return waitfor(global) - end +function cmd.QUERY(service_name) + return waitfor(service_name) end skynet.start(function() - skynet.dispatch("lua", function(session, address, command, service_name , ...) + skynet.dispatch("lua", function(session, address, command, global, service_name , ...) local f = cmd[command] if f == nil then - skynet.ret(skynet.pack(nil)) + skynet.ret(skynet.pack(nil, "Invalid command " .. command)) return end - local ok, r = pcall(f, service_name, ...) + local ok, r + if global == true then + if GLOBAL then + ok, r = pcall(f, service_name, ...) + else + return waitfor(service_name, skynet.call, "SERVICE", "lua", command, service_name, ...) + end + else + assert(type(global) == "string") -- global is service_name + ok, r = pcall(f, global, service_name, ...) + end + if ok then skynet.ret(skynet.pack(r)) else From ddd0b1301381683bc60dbd7e2397b2a667990d80 Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Sat, 19 Apr 2014 17:53:50 +0800 Subject: [PATCH 4/5] add snax.uniqueservice (and others) --- lualib/skynet.lua | 16 ++++++++++---- lualib/snax.lua | 39 ++++++++++++++++++++++++++++++---- service/service_mgr.lua | 47 +++++++++++++++++++++++++++-------------- 3 files changed, 78 insertions(+), 24 deletions(-) diff --git a/lualib/skynet.lua b/lualib/skynet.lua index a6b46720..b6bdde48 100644 --- a/lualib/skynet.lua +++ b/lualib/skynet.lua @@ -410,12 +410,20 @@ function skynet.newservice(name, ...) end end -function skynet.uniqueservice(...) - return assert(skynet.call(".service", "lua", "LAUNCH", ...)) +function skynet.uniqueservice(global, ...) + if global == true then + return assert(skynet.call(".service", "lua", "GLAUNCH", ...)) + else + return assert(skynet.call(".service", "lua", "LAUNCH", global, ...)) + end end -function skynet.queryservice(...) - return assert(skynet.call(".service", "lua", "QUERY", ...)) +function skynet.queryservice(global, ...) + if global == true then + return assert(skynet.call(".service", "lua", "GQUERY", ...)) + else + return assert(skynet.call(".service", "lua", "QUERY", global, ...)) + end end local function group_command(cmd, handle, address) diff --git a/lualib/snax.lua b/lualib/snax.lua index e60aa293..7612f1d9 100644 --- a/lualib/snax.lua +++ b/lualib/snax.lua @@ -64,16 +64,14 @@ end local handle_cache = setmetatable( {} , { __mode = "kv" } ) -function snax.newservice(name, ...) +function snax.rawnewservice(name, ...) local t = snax.interface(name) local handle = skynet.newservice("snaxd", name) assert(handle_cache[handle] == nil) if t.system.init then skynet.call(handle, "lua", t.system.init, ...) end - local ret = wrapper(handle, name, t) - handle_cache[handle] = ret - return ret + return handle end function snax.bind(handle, type) @@ -88,6 +86,39 @@ function snax.bind(handle, type) return ret end +function snax.newservice(name, ...) + local handle = snax.rawnewservice(name, ...) + return snax.bind(handle, name) +end + +local function service_name(global, name, ...) + if global == true then + return name + else + return global + end +end + +function snax.uniqueservice(name, ...) + local handle = assert(skynet.call(".service", "lua", "LAUNCH", "snaxd", name, ...)) + return snax.bind(handle, name) +end + +function snax.globalservice(name, ...) + local handle = assert(skynet.call(".service", "lua", "GLAUNCH", "snaxd", name, ...)) + return snax.bind(handle, name) +end + +function snax.queryservice(name) + local handle = assert(skynet.call(".service", "lua", "QUERY", "snaxd", name)) + return snax.bind(handle, name) +end + +function snax.queryglobal(name) + local handle = assert(skynet.call(".service", "lua", "GQUERY", "snaxd", name)) + return snax.bind(handle, name) +end + function snax.kill(obj, ...) local t = snax.interface(obj.type) skynet_call(obj.handle, "lua", t.system.exit, ...) diff --git a/service/service_mgr.lua b/service/service_mgr.lua index 7b5f5b12..2d3fc899 100644 --- a/service/service_mgr.lua +++ b/service/service_mgr.lua @@ -1,4 +1,5 @@ local skynet = require "skynet" +local snax = require "snax" local cmd = {} local service = {} @@ -57,33 +58,47 @@ local function waitfor(name , func, ...) return s end -function cmd.LAUNCH(service_name, ...) - return waitfor(service_name, skynet.newservice, service_name, ...) +function cmd.LAUNCH(service_name, subname, ...) + if service_name == "snaxd" then + return waitfor("snax."..subname, snax.rawnewservice, subname, ...) + else + return waitfor(service_name, skynet.newservice, service_name, subname, ...) + end end -function cmd.QUERY(service_name) - return waitfor(service_name) +function cmd.QUERY(service_name, subname) + if service_name == "snaxd" then + return waitfor("snax."..subname) + else + return waitfor(service_name) + end +end + +function cmd.GLAUNCH(...) + if GLOBAL then + return cmd.LAUNCH(...) + else + return waitfor(service_name, skynet.call, "SERVICE", "lua", "LAUNCH", ...) + end +end + +function cmd.GQUERY(...) + if GLOBAL then + return cmd.QUERY(...) + else + return waitfor(service_name, skynet.call, "SERVICE", "lua", "QUERY", ...) + end end skynet.start(function() - skynet.dispatch("lua", function(session, address, command, global, service_name , ...) + skynet.dispatch("lua", function(session, address, command, ...) local f = cmd[command] if f == nil then skynet.ret(skynet.pack(nil, "Invalid command " .. command)) return end - local ok, r - if global == true then - if GLOBAL then - ok, r = pcall(f, service_name, ...) - else - return waitfor(service_name, skynet.call, "SERVICE", "lua", command, service_name, ...) - end - else - assert(type(global) == "string") -- global is service_name - ok, r = pcall(f, global, service_name, ...) - end + local ok, r = pcall(f, ...) if ok then skynet.ret(skynet.pack(r)) From 8840c0fe3e31476699c05da6aefddd10bc5683b9 Mon Sep 17 00:00:00 2001 From: Cloud Wu Date: Sat, 19 Apr 2014 20:45:40 +0800 Subject: [PATCH 5/5] service_mgr support list, add a debug command to debug_console --- examples/config_log | 1 + examples/main.lua | 2 +- service/debug_console.lua | 5 +- service/service_mgr.lua | 106 ++++++++++++++++++++++++++++++++------ test/testping.lua | 4 +- 5 files changed, 98 insertions(+), 20 deletions(-) diff --git a/examples/config_log b/examples/config_log index e7ba2eb4..9261e435 100644 --- a/examples/config_log +++ b/examples/config_log @@ -7,3 +7,4 @@ address = "127.0.0.1:2527" master = "127.0.0.1:2013" start = "main_log" luaservice ="./service/?.lua;./test/?.lua;./examples/?.lua" +snax = "./examples/?.lua;./test/?.lua" diff --git a/examples/main.lua b/examples/main.lua index e95f05c2..fa0b33c0 100644 --- a/examples/main.lua +++ b/examples/main.lua @@ -8,7 +8,7 @@ skynet.start(function() skynet.monitor "simplemonitor" local lualog = skynet.newservice("lualog") local console = skynet.newservice("console") --- skynet.newservice("debug_console",8000) + skynet.newservice("debug_console",8000) skynet.newservice("simpledb") local watchdog = skynet.newservice("watchdog") skynet.call(watchdog, "lua", "start", { diff --git a/service/debug_console.lua b/service/debug_console.lua index 7e743617..9543d97c 100644 --- a/service/debug_console.lua +++ b/service/debug_console.lua @@ -110,6 +110,7 @@ function COMMAND.help() gc = "gc : force every lua service do garbage collect", start = "lanuch a new lua service", clearcache = "clear lua code cache", + service = "List unique service", } end @@ -126,4 +127,6 @@ function COMMAND.start(...) end end - +function COMMAND.service() + return skynet.call("SERVICE", "lua", "LIST") +end diff --git a/service/service_mgr.lua b/service/service_mgr.lua index 2d3fc899..2fbb0026 100644 --- a/service/service_mgr.lua +++ b/service/service_mgr.lua @@ -58,36 +58,107 @@ local function waitfor(name , func, ...) return s end -function cmd.LAUNCH(service_name, subname, ...) - if service_name == "snaxd" then - return waitfor("snax."..subname, snax.rawnewservice, subname, ...) +local function read_name(service_name) + if string.byte(service_name) == 64 then -- '@' + return string.sub(service_name , 2) else - return waitfor(service_name, skynet.newservice, service_name, subname, ...) + return service_name + end +end + +function cmd.LAUNCH(service_name, subname, ...) + local realname = read_name(service_name) + + if realname == "snaxd" then + return waitfor(service_name.."."..subname, snax.rawnewservice, subname, ...) + else + return waitfor(service_name, skynet.newservice, realname, subname, ...) end end function cmd.QUERY(service_name, subname) - if service_name == "snaxd" then - return waitfor("snax."..subname) + local realname = read_name(service_name) + + if realname == "snaxd" then + return waitfor(service_name.."."..subname) else return waitfor(service_name) end end -function cmd.GLAUNCH(...) - if GLOBAL then - return cmd.LAUNCH(...) - else - return waitfor(service_name, skynet.call, "SERVICE", "lua", "LAUNCH", ...) +local function list_service() + local result = {} + for k,v in pairs(service) do + if type(v) == "string" then + v = "Error: " .. v + elseif type(v) == "table" then + v = "Querying" + else + v = skynet.address(v) + end + + result[k] = v + end + + return result +end + + +local function register_global() + function cmd.GLAUNCH(name, ...) + local global_name = "@" .. name + return cmd.LAUNCH(global_name, ...) + end + + function cmd.GQUERY(name, ...) + local global_name = "@" .. name + return cmd.QUERY(global_name, ...) + end + + local mgr = {} + + function cmd.REPORT(m) + mgr[m] = true + skynet.watch(m) + end + + local function add_list(all, m) + local harbor = "@" .. skynet.harbor(m) + local result = skynet.call(m, "lua", "LIST") + for k,v in pairs(result) do + all[k .. harbor] = v + end + end + + function cmd.LIST() + local result = {} + for k in pairs(mgr) do + pcall(add_list, result, k) + end + local l = list_service() + for k, v in pairs(l) do + result[k] = v + end + return result end end -function cmd.GQUERY(...) - if GLOBAL then - return cmd.QUERY(...) - else - return waitfor(service_name, skynet.call, "SERVICE", "lua", "QUERY", ...) +local function register_local() + function cmd.GLAUNCH(name, ...) + local global_name = "@" .. name + return waitfor(global_name, skynet.call, "SERVICE", "lua", "LAUNCH", global_name, ...) end + + function cmd.GQUERY(name, ...) + local global_name = "@" .. name + return waitfor(global_name, skynet.call, "SERVICE", "lua", "QUERY", global_name, ...) + end + + function cmd.LIST() + return list_service() + end + + skynet.call("SERVICE", "lua", "REPORT", skynet.self()) end skynet.start(function() @@ -110,5 +181,8 @@ skynet.start(function() if skynet.getenv "standalone" then GLOBAL = true skynet.register("SERVICE") + register_global() + else + register_local() end end) diff --git a/test/testping.lua b/test/testping.lua index 1244551e..cbe198ff 100644 --- a/test/testping.lua +++ b/test/testping.lua @@ -2,7 +2,7 @@ local skynet = require "skynet" local snax = require "snax" skynet.start(function() - local ps = snax.newservice ("pingserver", "hello world") + local ps = snax.uniqueservice ("pingserver", "hello world") print(ps.req.ping("foobar")) print(ps.pub.hello()) print(pcall(ps.req.error)) @@ -24,6 +24,6 @@ end ]])) print(ps.pub.hello()) - print(snax.kill(ps,"exit")) +-- print(snax.kill(ps,"exit")) skynet.exit() end)