launcher.lua 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. local skynet = require "skynet"
  2. local core = require "skynet.core"
  3. require "skynet.manager" -- import manager apis
  4. local string = string
  5. local services = {}
  6. local command = {}
  7. local instance = {} -- for confirm (function command.LAUNCH / command.ERROR / command.LAUNCHOK)
  8. local function handle_to_address(handle)
  9. return tonumber("0x" .. string.sub(handle , 2))
  10. end
  11. local NORET = {}
  12. function command.LIST()
  13. local list = {}
  14. for k,v in pairs(services) do
  15. list[skynet.address(k)] = v
  16. end
  17. return list
  18. end
  19. function command.STAT()
  20. local list = {}
  21. for k,v in pairs(services) do
  22. local ok, stat = pcall(skynet.call,k,"debug","STAT")
  23. if not ok then
  24. stat = string.format("ERROR (%s)",v)
  25. end
  26. list[skynet.address(k)] = stat
  27. end
  28. return list
  29. end
  30. function command.KILL(_, handle)
  31. handle = handle_to_address(handle)
  32. skynet.kill(handle)
  33. local ret = { [skynet.address(handle)] = tostring(services[handle]) }
  34. services[handle] = nil
  35. return ret
  36. end
  37. function command.MEM()
  38. local list = {}
  39. for k,v in pairs(services) do
  40. local ok, kb, bytes = pcall(skynet.call,k,"debug","MEM")
  41. if not ok then
  42. list[skynet.address(k)] = string.format("ERROR (%s)",v)
  43. else
  44. list[skynet.address(k)] = string.format("%.2f Kb (%s)",kb,v)
  45. end
  46. end
  47. return list
  48. end
  49. function command.GC()
  50. for k,v in pairs(services) do
  51. skynet.send(k,"debug","GC")
  52. end
  53. return command.MEM()
  54. end
  55. function command.REMOVE(_, handle, kill)
  56. services[handle] = nil
  57. local response = instance[handle]
  58. if response then
  59. -- instance is dead
  60. response(not kill) -- return nil to caller of newservice, when kill == false
  61. instance[handle] = nil
  62. end
  63. -- don't return (skynet.ret) because the handle may exit
  64. return NORET
  65. end
  66. local function launch_service(service, ...)
  67. local param = table.concat({...}, " ")
  68. local inst = skynet.launch(service, param)
  69. local response = skynet.response()
  70. if inst then
  71. services[inst] = service .. " " .. param
  72. instance[inst] = response
  73. else
  74. response(false)
  75. return
  76. end
  77. return inst
  78. end
  79. function command.LAUNCH(_, service, ...)
  80. launch_service(service, ...)
  81. return NORET
  82. end
  83. function command.LOGLAUNCH(_, service, ...)
  84. local inst = launch_service(service, ...)
  85. if inst then
  86. core.command("LOGON", skynet.address(inst))
  87. end
  88. return NORET
  89. end
  90. function command.ERROR(address)
  91. -- see serivce-src/service_lua.c
  92. -- init failed
  93. local response = instance[address]
  94. if response then
  95. response(false)
  96. instance[address] = nil
  97. end
  98. services[address] = nil
  99. return NORET
  100. end
  101. function command.LAUNCHOK(address)
  102. -- init notice
  103. local response = instance[address]
  104. if response then
  105. response(true, address)
  106. instance[address] = nil
  107. end
  108. return NORET
  109. end
  110. -- for historical reasons, launcher support text command (for C service)
  111. skynet.register_protocol {
  112. name = "text",
  113. id = skynet.PTYPE_TEXT,
  114. unpack = skynet.tostring,
  115. dispatch = function(session, address , cmd)
  116. if cmd == "" then
  117. command.LAUNCHOK(address)
  118. elseif cmd == "ERROR" then
  119. command.ERROR(address)
  120. else
  121. error ("Invalid text command " .. cmd)
  122. end
  123. end,
  124. }
  125. skynet.dispatch("lua", function(session, address, cmd , ...)
  126. cmd = string.upper(cmd)
  127. local f = command[cmd]
  128. if f then
  129. local ret = f(address, ...)
  130. if ret ~= NORET then
  131. skynet.ret(skynet.pack(ret))
  132. end
  133. else
  134. skynet.ret(skynet.pack {"Unknown command"} )
  135. end
  136. end)
  137. skynet.start(function() end)