Merge branch 'lua53'

This commit is contained in:
Cloud Wu
2015-03-09 13:01:37 +08:00
117 changed files with 8757 additions and 5215 deletions

View File

@@ -230,10 +230,10 @@ function mongo_collection:insert(doc)
end
function mongo_collection:safe_insert(doc)
return self.database:runCommand("insert", self.name, "documents", {bson_encode(doc)})
return self.database:runCommand("insert", self.name, "documents", {bson_encode(doc)})
end
function mongo_collection:batch_insert(docs)
function mongo_collection:batch_insert(docs)
for i=1,#docs do
if docs[i]._id == nil then
docs[i]._id = bson.objectid()
@@ -279,9 +279,45 @@ function mongo_collection:find(query, selector)
__cursor = nil,
__document = {},
__flags = 0,
__skip = 0,
__sortquery = nil,
__limit = 0,
} , cursor_meta)
end
function mongo_cursor:sort(key_list)
self.__sortquery = bson_encode {['$query'] = self.__query, ['$orderby'] = key_list}
return self
end
function mongo_cursor:skip(amount)
self.__skip = amount
return self
end
function mongo_cursor:limit(amount)
self.__limit = amount
return self
end
function mongo_cursor:count(with_limit_and_skip)
local cmd = {
'count', self.__collection.name,
'query', self.__query,
}
if with_limit_and_skip then
local len = #cmd
cmd[len+1] = 'limit'
cmd[len+2] = self.__limit
cmd[len+3] = 'skip'
cmd[len+4] = self.__skip
end
local ret = self.__collection.database:runCommand(table.unpack(cmd))
assert(ret and ret.ok == 1)
return ret.n
end
-- collection:createIndex({username = 1}, {unique = true})
function mongo_collection:createIndex(keys, option)
local name = option.name
@@ -291,7 +327,7 @@ function mongo_collection:createIndex(keys, option)
for k, v in pairs(keys) do
name = (name == nil) and k or (name .. "_" .. k)
name = name .. "_" .. v
end
end
end
@@ -319,13 +355,13 @@ end
-- collection:findAndModify({query = {name = "userid"}, update = {["$inc"] = {nextid = 1}}, })
-- keys, value type
-- query, table
-- query, table
-- sort, table
-- remove, bool
-- update, table
-- new, bool
-- fields, bool
-- upsert, boolean
-- remove, bool
-- update, table
-- new, bool
-- fields, bool
-- upsert, boolean
function mongo_collection:findAndModify(doc)
assert(doc.query)
assert(doc.update or doc.remove)
@@ -335,7 +371,7 @@ function mongo_collection:findAndModify(doc)
table.insert(cmd, k)
table.insert(cmd, v)
end
return self.database:runCommand(unpack(cmd))
return self.database:runCommand(table.unpack(cmd))
end
function mongo_cursor:hasNext()
@@ -348,10 +384,11 @@ function mongo_cursor:hasNext()
local sock = conn.__sock
local pack
if self.__data == nil then
pack = driver.query(request_id, self.__flags, self.__collection.full_name,0,0,self.__query,self.__selector)
local query = self.__sortquery or self.__query
pack = driver.query(request_id, self.__flags, self.__collection.full_name, self.__skip, -self.__limit, query, self.__selector)
else
if self.__cursor then
pack = driver.more(request_id, self.__collection.full_name,0,self.__cursor)
pack = driver.more(request_id, self.__collection.full_name, -self.__limit, self.__cursor)
else
-- no more
self.__document = nil

View File

@@ -2,27 +2,22 @@
-- Copyright (C) 2014 Chang Feng
-- This file is modified version from https://github.com/openresty/lua-resty-mysql
-- The license is under the BSD license.
-- Modified by Cloud Wu (remove bit32 for lua 5.3)
local socketchannel = require "socketchannel"
local bit = require "bit32"
local mysqlaux = require "mysqlaux.c"
local crypt = require "crypt"
local sub = string.sub
local strgsub = string.gsub
local strformat = string.format
local strbyte = string.byte
local strchar = string.char
local strfind = string.find
local strrep = string.rep
local null = nil
local band = bit.band
local bxor = bit.bxor
local bor = bit.bor
local lshift = bit.lshift
local rshift = bit.rshift
local strunpack = string.unpack
local strpack = string.pack
local sha1= crypt.sha1
local concat = table.concat
local unpack = unpack
local setmetatable = setmetatable
local error = error
local tonumber = tonumber
@@ -53,105 +48,53 @@ for i = 0x01, 0x05 do
-- tiny, short, long, float, double
converters[i] = tonumber
end
-- converters[0x08] = tonumber -- long long
converters[0x08] = tonumber -- long long
converters[0x09] = tonumber -- int24
converters[0x0d] = tonumber -- year
converters[0xf6] = tonumber -- newdecimal
local function _get_byte2(data, i)
local a, b = strbyte(data, i, i + 1)
return bor(a, lshift(b, 8)), i + 2
return strunpack("<I2",data,i)
end
local function _get_byte3(data, i)
local a, b, c = strbyte(data, i, i + 2)
return bor(a, lshift(b, 8), lshift(c, 16)), i + 3
return strunpack("<I3",data,i)
end
local function _get_byte4(data, i)
local a, b, c, d = strbyte(data, i, i + 3)
return bor(a, lshift(b, 8), lshift(c, 16), lshift(d, 24)), i + 4
return strunpack("<I4",data,i)
end
local function _get_byte8(data, i)
local a, b, c, d, e, f, g, h = strbyte(data, i, i + 7)
-- XXX workaround for the lack of 64-bit support in bitop:
local lo = bor(a, lshift(b, 8), lshift(c, 16), lshift(d, 24))
local hi = bor(e, lshift(f, 8), lshift(g, 16), lshift(h, 24))
return lo + hi * 4294967296, i + 8
-- return bor(a, lshift(b, 8), lshift(c, 16), lshift(d, 24), lshift(e, 32),
-- lshift(f, 40), lshift(g, 48), lshift(h, 56)), i + 8
return strunpack("<I8",data,i)
end
local function _set_byte2(n)
return strchar(band(n, 0xff), band(rshift(n, 8), 0xff))
return strpack("<I2", n)
end
local function _set_byte3(n)
return strchar(band(n, 0xff),
band(rshift(n, 8), 0xff),
band(rshift(n, 16), 0xff))
return strpack("<I3", n)
end
local function _set_byte4(n)
return strchar(band(n, 0xff),
band(rshift(n, 8), 0xff),
band(rshift(n, 16), 0xff),
band(rshift(n, 24), 0xff))
return strpack("<I4", n)
end
local function _from_cstring(data, i)
local last = strfind(data, "\0", i, true)
if not last then
return nil, nil
end
return sub(data, i, last), last + 1
return strunpack("z", data, i)
end
local function _to_cstring(data)
return data .. "\0"
end
local function _to_binary_coded_string(data)
return strchar(#data) .. data
end
local function _dump(data)
local len = #data
local bytes = new_tab(len, 0)
for i = 1, len do
bytes[i] = strbyte(data, i)
end
return concat(bytes, " ")
end
local function _dumphex(bytes)
local result ={}
for i = 1, string.len(bytes) do
local charcode = tonumber(strbyte(bytes, i, i))
local hexstr = string.format("%02X", charcode)
result[i]=hexstr
end
local res=table.concat(result, " ")
return res
return strgsub(bytes, ".", function(x) return strformat("%02x ", strbyte(x)) end)
end
@@ -159,19 +102,20 @@ local function _compute_token(password, scramble)
if password == "" then
return ""
end
--_dump(scramble)
--_dumphex(scramble)
local stage1 = sha1(password)
--print("stage1:", _dumphex(stage1) )
local stage2 = sha1(stage1)
local stage3 = sha1(scramble .. stage2)
local n = #stage1
local bytes = new_tab(n, 0)
for i = 1, n do
bytes[i] = strchar(bxor(strbyte(stage3, i), strbyte(stage1, i)))
end
return concat(bytes)
local i = 0
return strgsub(stage3,".",
function(x)
i = i + 1
-- ~ is xor in lua 5.3
return strchar(strbyte(x) ~ strbyte(stage1, i))
end)
end
local function _compose_packet(self, req, size)
@@ -253,7 +197,7 @@ local function _from_length_coded_bin(data, pos)
end
if first == 251 then
return null, pos + 1
return nil, pos + 1
end
if first == 252 then
@@ -278,8 +222,8 @@ end
local function _from_length_coded_str(data, pos)
local len
len, pos = _from_length_coded_bin(data, pos)
if len == nil or len == null then
return null, pos
if len == nil then
return nil, pos
end
return sub(data, pos, pos + len - 1), pos + len
@@ -401,7 +345,7 @@ local function _parse_row_data_packet(data, cols, compact)
local typ = col.type
local name = col.name
if value ~= null then
if value ~= nil then
local conv = converters[typ]
if conv then
value = conv(value)
@@ -457,7 +401,7 @@ local function _recv_auth_resp(self)
if typ == 'ERR' then
local errno, msg, sqlstate = _parse_err_packet(packet)
error( string.format("errno:%d, msg:%s,sqlstate:%s",errno,msg,sqlstate))
error( strformat("errno:%d, msg:%s,sqlstate:%s",errno,msg,sqlstate))
--return nil, errno,msg, sqlstate
end
@@ -484,7 +428,7 @@ local function _mysql_login(self,user,password,database)
if typ == "ERR" then
local errno, msg, sqlstate = _parse_err_packet(packet)
error( string.format("errno:%d, msg:%s,sqlstate:%s",errno,msg,sqlstate))
error( strformat("errno:%d, msg:%s,sqlstate:%s",errno,msg,sqlstate))
end
self.protocol_ver = strbyte(packet)
@@ -517,9 +461,7 @@ local function _mysql_login(self,user,password,database)
local more_capabilities
more_capabilities, pos = _get_byte2(packet, pos)
self._server_capabilities = bor(self._server_capabilities,
lshift(more_capabilities, 16))
self._server_capabilities = self._server_capabilities|more_capabilities<<16
local len = 21 - 8 - 1
@@ -536,16 +478,15 @@ local function _mysql_login(self,user,password,database)
local client_flags = 260047;
local req = _set_byte4(client_flags)
.. _set_byte4(self._max_packet_size)
.. "\0" -- TODO: add support for charset encoding
.. strrep("\0", 23)
.. _to_cstring(user)
.. _to_binary_coded_string(token)
.. _to_cstring(database)
local req = strpack("<I4I4c24zs1z",
client_flags,
self._max_packet_size,
strrep("\0", 24), -- TODO: add support for charset encoding
user,
token,
database)
local packet_len = 4 + 4 + 1 + 23 + #user + 1
+ #token + 1 + #database + 1
local packet_len = #req
local authpacket=_compose_packet(self,req,packet_len)
return sockchannel:request(authpacket,_recv_auth_resp(self))
@@ -576,12 +517,12 @@ local function read_result(self, sock)
if typ == "ERR" then
local errno, msg, sqlstate = _parse_err_packet(packet)
return nil, msg, errno, sqlstate
--error( string.format("errno:%d, msg:%s,sqlstate:%s",errno,msg,sqlstate))
--error( strformat("errno:%d, msg:%s,sqlstate:%s",errno,msg,sqlstate))
end
if typ == 'OK' then
local res = _parse_ok_packet(packet)
if res and band(res.server_status, SERVER_MORE_RESULTS_EXISTS) ~= 0 then
if res and res.server_status&SERVER_MORE_RESULTS_EXISTS ~= 0 then
return res, "again"
end
return res
@@ -601,7 +542,7 @@ local function read_result(self, sock)
local col, err, errno, sqlstate = _recv_field_packet(self, sock)
if not col then
return nil, err, errno, sqlstate
--error( string.format("errno:%d, msg:%s,sqlstate:%s",errno,msg,sqlstate))
--error( strformat("errno:%d, msg:%s,sqlstate:%s",errno,msg,sqlstate))
end
cols[i] = col
@@ -634,7 +575,7 @@ local function read_result(self, sock)
if typ == 'EOF' then
local warning_count, status_flags = _parse_eof_packet(packet)
if band(status_flags, SERVER_MORE_RESULTS_EXISTS) ~= 0 then
if status_flags&SERVER_MORE_RESULTS_EXISTS ~= 0 then
return rows, "again"
end

View File

@@ -1,7 +1,6 @@
local skynet = require "skynet"
local socket = require "socket"
local socketchannel = require "socketchannel"
local int64 = require "int64"
local table = table
local string = string
@@ -102,12 +101,8 @@ local function pack_value(lines, v)
return
end
local t = type(v)
if t == "number" then
v = tostring(v)
elseif t == "userdata" then
v = int64.tostring(int64.new(v),10)
end
v = tostring(v)
table.insert(lines,"$"..#v)
table.insert(lines,v)
end

View File

@@ -31,14 +31,14 @@ end
local function update(root, cobj, gcobj)
root.__obj = cobj
root.__gcobj = gcobj
-- don't use pairs
for k,v in next, root do
if type(v)=="table" and k~="__parent" then
local children = root.__cache
if children then
for k,v in pairs(children) do
local pointer = index(cobj, k)
if type(pointer) == "userdata" then
update(v, pointer, gcobj)
else
root[k] = nil
children[k] = nil
end
end
end
@@ -74,13 +74,22 @@ function meta:__index(key)
local obj = getcobj(self)
local v = index(obj, key)
if type(v) == "userdata" then
local r = setmetatable({
local children = self.__cache
if children == nil then
children = {}
self.__cache = children
end
local r = children[key]
if r then
return r
end
r = setmetatable({
__obj = v,
__gcobj = self.__gcobj,
__parent = self,
__key = key,
}, meta)
self[key] = r
children[key] = r
return r
else
return v
@@ -91,24 +100,6 @@ function meta:__len()
return len(getcobj(self))
end
local function conf_ipairs(self, index)
local obj = getcobj(self)
index = index + 1
local value = rawget(self, index)
if value then
return index, value
end
local sz = len(obj)
if sz < index then
return
end
return index, self[index]
end
function meta:__ipairs()
return conf_ipairs, self, 0
end
function meta:__pairs()
return conf.next, self, nil
end

69
lualib/sharemap.lua Normal file
View File

@@ -0,0 +1,69 @@
local stm = require "stm"
local sprotoloader = require "sprotoloader"
local sproto = require "sproto"
local setmetatable = setmetatable
local sharemap = {}
function sharemap.register(protofile)
-- use global slot 0 for type define
sprotoloader.register(protofile, 0)
end
local sprotoobj
local function loadsp()
if sprotoobj == nil then
sprotoobj = sprotoloader.load(0)
end
return sprotoobj
end
function sharemap:commit()
self.__obj(sprotoobj:encode(self.__typename, self.__data))
end
function sharemap:copy()
return stm.copy(self.__obj)
end
function sharemap.writer(typename, obj)
local sp = loadsp()
obj = obj or {}
local stmobj = stm.new(sp:encode(typename,obj))
obj.__typename = typename
obj.__obj = stmobj
obj.__data = obj
obj.commit = sharemap.commit
obj.copy = sharemap.copy
return setmetatable(obj, { __index = obj.__data, __newindex = obj.__data })
end
local function decode(msg, sz, self)
local data = self.__data
for k in pairs(data) do
data[k] = nil
end
return sprotoobj:decode(self.__typename, msg, sz, data)
end
function sharemap:update()
return self.__obj(decode, self)
end
function sharemap.reader(typename, stmcpy)
local sp = loadsp()
local stmobj = stm.newcopy(stmcpy)
local _, data = stmobj(function(msg, sz)
return sp:decode(typename, msg, sz)
end)
local obj = {
__typename = typename,
__obj = stmobj,
__data = data,
update = sharemap.update,
}
return setmetatable(obj, { __index = obj.__data, __newindex = error })
end
return sharemap

View File

@@ -22,7 +22,7 @@ local skynet = {
PTYPE_HARBOR = 5,
PTYPE_SOCKET = 6,
PTYPE_ERROR = 7,
PTYPE_QUEUE = 8, -- use in deprecated mqueue, use skynet.queue instead
PTYPE_QUEUE = 8, -- used in deprecated mqueue, use skynet.queue instead
PTYPE_DEBUG = 9,
PTYPE_LUA = 10,
PTYPE_SNAX = 11,
@@ -101,7 +101,6 @@ local coroutine_count = 0
local function co_create(f)
local co = table.remove(coroutine_pool)
if co == nil then
local print = print
co = coroutine.create(function(...)
f(...)
while true do
@@ -233,6 +232,9 @@ function suspend(co, result, command, param, size)
elseif command == "QUIT" then
-- service exit
return
elseif command == nil then
-- debug trace
return
else
error("Unknown command : " .. command .. "\n" .. debug.traceback(co))
end
@@ -339,7 +341,7 @@ end
function skynet.exit()
fork_queue = {} -- no fork coroutine can be execute after skynet.exit
skynet.send(".launcher","lua","REMOVE",skynet.self())
skynet.send(".launcher","lua","REMOVE",skynet.self(), false)
-- report the sources that call me
for co, session in pairs(session_coroutine_id) do
local address = session_coroutine_address[co]
@@ -362,7 +364,7 @@ end
function skynet.kill(name)
if type(name) == "number" then
skynet.send(".launcher","lua","REMOVE",name)
skynet.send(".launcher","lua","REMOVE",name, true)
name = skynet.address(name)
end
c.command("KILL",name)
@@ -461,7 +463,7 @@ function skynet.dispatch_unknown_request(unknown)
end
local function unknown_response(session, address, msg, sz)
print("Response message :" , c.tostring(msg,sz))
skynet.error(string.format("Response message :" , c.tostring(msg,sz)))
error(string.format("Unknown session : %d from %x", session, address))
end
@@ -719,6 +721,7 @@ local debug = require "skynet.debug"
debug(skynet, {
dispatch = dispatch_message,
clear = clear_pool,
suspend = suspend,
})
return skynet

View File

@@ -58,6 +58,11 @@ function dbgcmd.TERM(service)
skynet.term(service)
end
function dbgcmd.REMOTEDEBUG(...)
local remotedebug = require "skynet.remotedebug"
remotedebug.start(export, ...)
end
local function _debug_dispatch(session, address, cmd, ...)
local f = dbgcmd[cmd]
assert(f, cmd)

View File

@@ -0,0 +1,133 @@
local debug = debug
local table = table
local FUNC_TEMP=[[
local $ARGS
return function(...)
$SOURCE
end,
function()
return {$LOCALS}
end
]]
local temp = {}
local function wrap_locals(co, source, level, ext_funcs)
if co == coroutine.running() then
level = level + 3
end
local f = debug.getinfo(co, level,"f").func
if f == nil then
return false, "Invalid level"
end
local uv = {}
local locals = {}
local uv_id = {}
local local_id = {}
if ext_funcs then
for k,v in pairs(ext_funcs) do
table.insert(uv, k)
end
end
local i = 1
while true do
local name, value = debug.getlocal(co, level, i)
if name == nil then
break
end
if name:byte() ~= 40 then -- '('
table.insert(uv, name)
table.insert(locals, ("[%d]=%s,"):format(i,name))
local_id[name] = value
end
i = i + 1
end
local i = 1
while true do
local name = debug.getupvalue(f, i)
if name == nil then
break
end
uv_id[name] = i
table.insert(uv, name)
i = i + 1
end
temp.ARGS = table.concat(uv, ",")
temp.SOURCE = source
temp.LOCALS = table.concat(locals)
local full_source = FUNC_TEMP:gsub("%$(%w+)",temp)
local loader, err = load(full_source, "=(debug)")
if loader == nil then
return false, err
end
local func, update = loader()
-- join func's upvalues
local i = 1
while true do
local name = debug.getupvalue(func, i)
if name == nil then
break
end
if ext_funcs then
local v = ext_funcs[name]
if v then
debug.setupvalue(func, i, v)
end
end
local local_value = local_id[name]
if local_value then
debug.setupvalue(func, i, local_value)
end
local upvalue_id = uv_id[name]
if upvalue_id then
debug.upvaluejoin(func, i, f, upvalue_id)
end
i=i+1
end
local vararg, v = debug.getlocal(co, level, -1)
if vararg then
local vargs = { v }
local i = 2
while true do
local vararg,v = debug.getlocal(co, level, -i)
if vararg then
vargs[i] = v
else
break
end
i=i+1
end
return func, update, table.unpack(vargs)
else
return func, update
end
end
local function exec(co, level, func, update, ...)
if not func then
return false, update
end
if co == coroutine.running() then
level = level + 2
end
local rets = table.pack(pcall(func, ...))
if rets[1] then
local needupdate = update()
for k,v in pairs(needupdate) do
debug.setlocal(co, level,k,v)
end
return table.unpack(rets, 1, rets.n)
else
return false, rets[2]
end
end
return function (source, co, level, ext_funcs)
co = co or coroutine.running()
level = level or 0
return exec(co, level, wrap_locals(co, source, level, ext_funcs))
end

View File

@@ -0,0 +1,263 @@
local skynet = require "skynet"
local debugchannel = require "debugchannel"
local socket = require "socket"
local injectrun = require "skynet.injectcode"
local table = table
local debug = debug
local coroutine = coroutine
local sethook = debugchannel.sethook
local M = {}
local HOOK_FUNC = "raw_dispatch_message"
local raw_dispatcher
local print = _G.print
local skynet_suspend
local prompt
local newline
local function change_prompt(s)
newline = true
prompt = s
end
local function replace_upvalue(func, uvname, value)
local i = 1
while true do
local name, uv = debug.getupvalue(func, i)
if name == nil then
break
end
if name == uvname then
if value then
debug.setupvalue(func, i, value)
end
return uv
end
i = i + 1
end
end
local function remove_hook(dispatcher)
assert(raw_dispatcher, "Not in debug mode")
replace_upvalue(dispatcher, HOOK_FUNC, raw_dispatcher)
raw_dispatcher = nil
print = _G.print
skynet.error "Leave debug mode"
end
local function gen_print(fd)
-- redirect print to socket fd
return function(...)
local tmp = table.pack(...)
for i=1,tmp.n do
tmp[i] = tostring(tmp[i])
end
table.insert(tmp, "\n")
socket.write(fd, table.concat(tmp, "\t"))
end
end
local function run_exp(ok, ...)
if ok then
print(...)
end
return ok
end
local function run_cmd(cmd, env, co, level)
if not run_exp(injectrun("return "..cmd, co, level, env)) then
print(select(2, injectrun(cmd,co, level,env)))
end
end
local ctx_skynet = debug.getinfo(skynet.start,"S").short_src -- skip when enter this source file
local ctx_term = debug.getinfo(run_cmd, "S").short_src -- term when get here
local ctx_active = {}
local linehook
local function skip_hook(mode)
local co = coroutine.running()
local ctx = ctx_active[co]
if mode == "return" then
ctx.level = ctx.level - 1
if ctx.level == 0 then
ctx.needupdate = true
sethook(linehook, "crl")
end
else
ctx.level = ctx.level + 1
end
end
function linehook(mode, line)
local co = coroutine.running()
local ctx = ctx_active[co]
if mode ~= "line" then
ctx.needupdate = true
if mode ~= "return" then
if ctx.next_mode or debug.getinfo(2,"S").short_src == ctx_skynet then
ctx.level = 1
sethook(skip_hook, "cr")
end
end
else
if ctx.needupdate then
ctx.needupdate = false
ctx.filename = debug.getinfo(2, "S").short_src
if ctx.filename == ctx_term then
ctx_active[co] = nil
sethook()
change_prompt(string.format(":%08x>", skynet.self()))
return
end
end
change_prompt(string.format("%s(%d)>",ctx.filename, line))
return true -- yield
end
end
local function add_watch_hook()
local co = coroutine.running()
local ctx = {}
ctx_active[co] = ctx
local level = 1
sethook(function(mode)
if mode == "return" then
level = level - 1
else
level = level + 1
if level == 0 then
ctx.needupdate = true
sethook(linehook, "crl")
end
end
end, "cr")
end
local function watch_proto(protoname, cond)
local proto = assert(replace_upvalue(skynet.register_protocol, "proto"), "Can't find proto table")
local p = proto[protoname]
local dispatch = p.dispatch_origin or p.dispatch
if p == nil or dispatch == nil then
return "No " .. protoname
end
p.dispatch_origin = dispatch
p.dispatch = function(...)
if not cond or cond(...) then
p.dispatch = dispatch -- restore origin dispatch function
add_watch_hook()
end
dispatch(...)
end
end
local function remove_watch()
for co in pairs(ctx_active) do
sethook(co)
end
ctx_active = {}
end
local dbgcmd = {}
function dbgcmd.s(co)
local ctx = ctx_active[co]
ctx.next_mode = false
skynet_suspend(co, coroutine.resume(co))
end
function dbgcmd.n(co)
local ctx = ctx_active[co]
ctx.next_mode = true
skynet_suspend(co, coroutine.resume(co))
end
function dbgcmd.c(co)
sethook(co)
ctx_active[co] = nil
change_prompt(string.format(":%08x>", skynet.self()))
skynet_suspend(co, coroutine.resume(co))
end
local function hook_dispatch(dispatcher, resp, fd, channel)
change_prompt(string.format(":%08x>", skynet.self()))
print = gen_print(fd)
local env = {
print = print,
watch = watch_proto
}
local watch_env = {
print = print
}
local function watch_cmd(cmd)
local co = next(ctx_active)
watch_env._CO = co
if dbgcmd[cmd] then
dbgcmd[cmd](co)
else
run_cmd(cmd, watch_env, co, 0)
end
end
local function debug_hook()
while true do
if newline then
socket.write(fd, prompt)
newline = false
end
local cmd = channel:read()
if cmd then
if cmd == "cont" then
-- leave debug mode
break
end
if cmd ~= "" then
if next(ctx_active) then
watch_cmd(cmd)
else
run_cmd(cmd, env, coroutine.running(),2)
end
end
newline = true
else
-- no input
return
end
end
-- exit debug mode
remove_watch()
remove_hook(dispatcher)
resp(true)
end
local func
local function hook(...)
debug_hook()
return func(...)
end
func = replace_upvalue(dispatcher, HOOK_FUNC, hook)
if func then
local function idle()
skynet.timeout(10,idle) -- idle every 0.1s
end
skynet.timeout(0, idle)
end
return func
end
function M.start(import, fd, handle)
local dispatcher = import.dispatch
skynet_suspend = import.suspend
assert(raw_dispatcher == nil, "Already in debug mode")
skynet.error "Enter debug mode"
local channel = debugchannel.connect(handle)
raw_dispatcher = hook_dispatch(dispatcher, skynet.response(), fd, channel)
end
return M

View File

@@ -4,7 +4,9 @@ local snax_interface = require "snax.interface"
local snax = {}
local typeclass = {}
local G = { require = function() end }
local interface_g = skynet.getenv("snax_interface_g")
local G = interface_g and require (interface_g) or { require = function() end }
interface_g = nil
skynet.register_protocol {
name = "snax",

View File

@@ -12,8 +12,8 @@ function sproto_mt:__gc()
core.deleteproto(self.__cobj)
end
function sproto.new(pbin)
local cobj = assert(core.newproto(pbin))
function sproto.new(...)
local cobj = assert(core.newproto(...))
local self = {
__cobj = cobj,
__tcache = setmetatable( {} , weak_mt ),
@@ -53,9 +53,9 @@ function sproto:encode(typename, tbl)
return core.encode(st, tbl)
end
function sproto:decode(typename, bin)
function sproto:decode(typename, ...)
local st = querytype(self, typename)
return core.decode(st, bin)
return core.decode(st, ...)
end
function sproto:pencode(typename, tbl)

23
lualib/sprotoloader.lua Normal file
View File

@@ -0,0 +1,23 @@
local parser = require "sprotoparser"
local core = require "sproto.core"
local sproto = require "sproto"
local loader = {}
function loader.register(filename, index)
local f = assert(io.open(filename), "Can't open sproto file")
local data = f:read "a"
f:close()
local bin = parser.parse(data)
core.saveproto(bin, index)
end
loader.save = core.saveproto
function loader.load(index)
local bin, sz = core.loadproto(index)
return sproto.new(bin,sz)
end
return loader

View File

@@ -1,5 +1,4 @@
local lpeg = require "lpeg"
local bit32 = require "bit32"
local table = require "table"
local P = lpeg.P
@@ -196,18 +195,14 @@ end
]]
local function packbytes(str)
local size = #str
return string.char(bit32.extract(size,0,8))..
string.char(bit32.extract(size,8,8))..
string.char(bit32.extract(size,16,8))..
string.char(bit32.extract(size,24,8))..
str
str = string.pack("<s4",str)
return str
end
local function packvalue(id)
id = (id + 1) * 2
assert(id >=0 and id < 65536)
return string.char(bit32.extract(id, 0, 8)) .. string.char(bit32.extract(id, 8, 8))
local str = string.pack("<I2", id)
return str
end
local function packfield(f)