Blame view

publish/skynet/service/launcher.lua 3.68 KB
4d6f285d   zhouhaihai   增加发布功能
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
  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
  
  function command.STAT()
  	local list = {}
  	for k,v in pairs(services) do
  		local ok, stat = pcall(skynet.call,k,"debug","STAT")
  		if not ok then
  			stat = string.format("ERROR (%s)",v)
  		end
  		list[skynet.address(k)] = stat
  	end
  	return list
  end
  
  function command.KILL(_, handle)
  	handle = handle_to_address(handle)
  	skynet.kill(handle)
  	local ret = { [skynet.address(handle)] = tostring(services[handle]) }
  	services[handle] = nil
  	return ret
  end
  
  function command.MEM()
  	local list = {}
  	for k,v in pairs(services) do
  		local ok, kb = pcall(skynet.call,k,"debug","MEM")
  		if not ok then
  			list[skynet.address(k)] = string.format("ERROR (%s)",v)
  		else
  			list[skynet.address(k)] = string.format("%.2f Kb (%s)",kb,v)
  		end
  	end
  	return list
  end
  
  function command.GC()
  	for k,v in pairs(services) do
  		skynet.send(k,"debug","GC")
  	end
  	return command.MEM()
  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)