Compare commits

...

45 Commits

Author SHA1 Message Date
Cloud Wu
97538286fd 1.0.0 Released 2016-07-11 19:39:45 +08:00
Cloud Wu
fd1b230a54 1.0.0 rc5 2016-07-04 16:31:58 +08:00
Cloud Wu
33321e89a1 don't launch console service when in daemon mode 2016-06-28 18:31:12 +08:00
云风
b50e663a3a Merge pull request #525 from zxfishhack/master
auto determine primary host
2016-06-27 11:39:15 +08:00
zxfishhack
14a699cb85 auto determine primary host 2016-06-27 10:59:50 +08:00
Cloud Wu
098d44162b bson support meta array 2016-06-23 16:14:16 +08:00
Cloud Wu
16af94795e lua 5.3.3 bugfix 1 2016-06-22 22:28:54 +08:00
云风
00f41c6bc9 Merge pull request #521 from ahuang007/patch-1
Update lua-crypt.c
2016-06-21 15:37:56 +08:00
ahuang007
0465688403 Update lua-crypt.c
这个地方应该用G
2016-06-21 15:25:08 +08:00
Cloud Wu
8cd5834d28 Merge branch 'master' of github.com:cloudwu/skynet 2016-06-17 12:19:56 +08:00
Cloud Wu
040089639f memory leak bugfix in multicast, See issue #519 2016-06-17 12:17:53 +08:00
云风
81c4e47a6d Merge pull request #517 from cloudwu/mongoauth
Add mongo auth_scram_sha1 , See pr #492
2016-06-16 09:47:03 +08:00
Cloud Wu
2aef994aa4 add authmod in conf 2016-06-15 17:58:58 +08:00
Cloud Wu
ffa2bbf1e4 support mongo auth_scram_sha1 2016-06-15 16:49:58 +08:00
Cloud Wu
6a54fe8293 1.0.0 rc4 2016-06-13 15:13:17 +08:00
Cloud Wu
2020ce3c9c update jemalloc to 4.2.1 2016-06-13 15:08:33 +08:00
云风
2557559d5c Merge pull request #512 from cloudwu/createindex
add createindexes , for detail see pr #511
2016-06-13 13:12:57 +08:00
Cloud Wu
bb0143e476 add some assert 2016-06-13 12:29:01 +08:00
Cloud Wu
fd2c814fe0 default key ascending 2016-06-13 12:13:02 +08:00
Cloud Wu
bd3d9b70ec change arg name 2016-06-13 12:05:52 +08:00
Cloud Wu
ee1a218870 typo 2016-06-13 12:01:54 +08:00
Cloud Wu
84ee3da79a add mongo.createIndexs, and fix the bug in old API createIndex. For detail, see PR #511 2016-06-13 11:55:31 +08:00
云风
fdee7de36d Merge pull request #509 from dpull/master
重新设计debug.lua接口
2016-06-12 16:41:18 +08:00
dpull
bf5b74b6ca 重新设计debug.lua接口 2016-06-12 16:29:47 +08:00
Cloud Wu
d9b0347741 don't close fd twice 2016-06-12 15:07:56 +08:00
Cloud Wu
9546537256 debug console support simple http 2016-06-12 14:51:18 +08:00
Cloud Wu
f84fe84b96 update userlog 2016-06-12 13:48:53 +08:00
Cloud Wu
ea9bc53261 reopen log file when recv signal HUP 2016-06-12 13:40:23 +08:00
Cloud Wu
0edb839c95 Lua 5.3.3 released 2016-06-07 09:43:43 +08:00
Cloud Wu
b8bb327f98 make coroutine_pool weak would be better 2016-06-06 16:23:39 +08:00
cloudwu
27d69334ee Merge pull request #506 from rickone/master
Update socketchannel.lua
2016-06-05 01:07:42 +08:00
rickone
838e63ab62 Update socketchannel.lua
request的时候可能会连接失败,这时raise的不是socket_error,上层处理不太统一。
2016-06-04 16:26:07 +08:00
Cloud Wu
ba264700dc update jemalloc to 4.2.0 2016-05-31 09:36:21 +08:00
Cloud Wu
e00ad7ab79 update to lua 5.3.3 rc3 2016-05-31 09:30:21 +08:00
Cloud Wu
de176b735f update to lua 5.3.3 rc2 2016-05-19 13:16:19 +08:00
cloudwu
cc3e985834 Merge pull request #502 from pigparadise/cloudwu
lua_bson的encode方法增加对有自定义__pairs的table的支持
2016-05-19 13:19:21 +08:00
LiuYang
3b5f45eea2 lua_bson的encode方法增加对有自定义__pairs的table的支持 2016-05-19 13:10:33 +08:00
cloudwu
c3056b04c1 Merge pull request #498 from asanosoyokaze/patch-1
add vararg for INFO debug console command
2016-05-16 19:35:02 +08:00
David Feng
58755a6772 add vararg for INFO debug console command 2016-05-16 18:57:40 +08:00
Cloud Wu
1cf976c4e4 add debug console command : ping 2016-05-13 09:46:44 +08:00
Cloud Wu
5be836527c bugfix issue #494 2016-05-11 22:02:10 +08:00
Cloud Wu
e9f397945d bugfix issue #494 2016-05-10 16:59:34 +08:00
Cloud Wu
78df0b8161 refine code 2016-05-09 19:16:29 +08:00
cloudwu
db17245005 Merge pull request #493 from chenkete/master
修复redis auth操作没有进行compose_message的bug,该bug导致skynet连接twemproxy时,auth失败
2016-05-09 19:17:56 +08:00
chenkete
4edb586077 修复redis auth操作没有进行compose_message的bug,该bug导致skynet连接twemproxy时,auth失败 2016-05-09 17:16:37 +08:00
28 changed files with 781 additions and 295 deletions

View File

@@ -1012,10 +1012,9 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
return status;
}
static Proto * cloneproto (lua_State *L, const Proto *src) {
void cloneproto (lua_State *L, Proto *f, const Proto *src) {
/* copy constants and nested proto */
int i,n;
Proto *f = luaF_newproto(L, src->sp);
n = src->sp->sizek;
f->k=luaM_newvector(L,n,TValue);
for (i=0; i<n; i++) setnilvalue(&f->k[i]);
@@ -1033,9 +1032,9 @@ static Proto * cloneproto (lua_State *L, const Proto *src) {
f->p=luaM_newvector(L,n,struct Proto *);
for (i=0; i<n; i++) f->p[i]=NULL;
for (i=0; i<n; i++) {
f->p[i]=cloneproto(L, src->p[i]);
f->p[i]= luaF_newproto(L, src->p[i]->sp);
cloneproto(L, f->p[i], src->p[i]);
}
return f;
}
LUA_API void lua_clonefunction (lua_State *L, const void * fp) {
@@ -1049,9 +1048,10 @@ LUA_API void lua_clonefunction (lua_State *L, const void * fp) {
return;
}
cl = luaF_newLclosure(L,f->nupvalues);
cl->p = cloneproto(L, f->p);
setclLvalue(L,L->top,cl);
api_incr_top(L);
cl->p = luaF_newproto(L, f->p->sp);
cloneproto(L, cl->p, f->p);
luaF_initupvals(L, cl);
if (cl->nupvalues >= 1) { /* does it have an upvalue? */

View File

@@ -1,5 +1,5 @@
/*
** $Id: lcode.c,v 2.108 2016/01/05 16:22:37 roberto Exp $
** $Id: lcode.c,v 2.109 2016/05/13 19:09:21 roberto Exp $
** Code generator for Lua
** See Copyright Notice in lua.h
*/
@@ -1066,7 +1066,7 @@ void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) {
case OPR_MINUS: case OPR_BNOT:
if (constfolding(fs, op + LUA_OPUNM, e, &ef))
break;
/* else go through */
/* FALLTHROUGH */
case OPR_LEN:
codeunexpval(fs, cast(OpCode, op + OP_UNM), e, line);
break;

View File

@@ -492,15 +492,19 @@ static int marksharedproto (global_State *g, SharedProto *f) {
** NULL, so the use of 'markobjectN')
*/
static int traverseproto (global_State *g, Proto *f) {
int i;
int i,nk,np;
if (f->cache && iswhite(f->cache))
f->cache = NULL; /* allow cache to be collected */
for (i = 0; i < f->sp->sizek; i++) /* mark literals */
if (f->sp == NULL)
return sizeof(Proto);
nk = (f->k == NULL) ? 0 : f->sp->sizek;
np = (f->p == NULL) ? 0 : f->sp->sizep;
for (i = 0; i < nk; i++) /* mark literals */
markvalue(g, &f->k[i]);
for (i = 0; i < f->sp->sizep; i++) /* mark nested protos */
for (i = 0; i < np; i++) /* mark nested protos */
markobjectN(g, f->p[i]);
return sizeof(Proto) + sizeof(Proto *) * f->sp->sizep +
sizeof(TValue) * f->sp->sizek +
return sizeof(Proto) + sizeof(Proto *) * np +
sizeof(TValue) * nk +
marksharedproto(g, f->sp);
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: lobject.c,v 2.110 2016/05/02 14:00:32 roberto Exp $
** $Id: lobject.c,v 2.111 2016/05/20 14:07:48 roberto Exp $
** Some generic functions over Lua objects
** See Copyright Notice in lua.h
*/
@@ -293,6 +293,9 @@ static const char *l_str2d (const char *s, lua_Number *result) {
}
#define MAXBY10 cast(lua_Unsigned, LUA_MAXINTEGER / 10)
#define MAXLASTD cast_int(LUA_MAXINTEGER % 10)
static const char *l_str2int (const char *s, lua_Integer *result) {
lua_Unsigned a = 0;
int empty = 1;
@@ -309,7 +312,10 @@ static const char *l_str2int (const char *s, lua_Integer *result) {
}
else { /* decimal */
for (; lisdigit(cast_uchar(*s)); s++) {
a = a * 10 + *s - '0';
int d = *s - '0';
if (a >= MAXBY10 && (a > MAXBY10 || d > MAXLASTD + neg)) /* overflow? */
return NULL; /* do not accept it (as integer) */
a = a * 10 + d;
empty = 0;
}
}

View File

@@ -1,5 +1,5 @@
/*
** $Id: lparser.c,v 2.152 2016/03/07 19:25:39 roberto Exp $
** $Id: lparser.c,v 2.153 2016/05/13 19:10:16 roberto Exp $
** Lua Parser
** See Copyright Notice in lua.h
*/
@@ -269,27 +269,26 @@ static void markupval (FuncState *fs, int level) {
Find variable with given name 'n'. If it is an upvalue, add this
upvalue into all intermediate functions.
*/
static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
if (fs == NULL) /* no more levels? */
return VVOID; /* default is global */
init_exp(var, VVOID, 0); /* default is global */
else {
int v = searchvar(fs, n); /* look up locals at current level */
if (v >= 0) { /* found? */
init_exp(var, VLOCAL, v); /* variable is local */
if (!base)
markupval(fs, v); /* local will be used as an upval */
return VLOCAL;
}
else { /* not found as local at current level; try upvalues */
int idx = searchupvalue(fs, n); /* try existing upvalues */
if (idx < 0) { /* not found? */
if (singlevaraux(fs->prev, n, var, 0) == VVOID) /* try upper levels */
return VVOID; /* not found; is a global */
singlevaraux(fs->prev, n, var, 0); /* try upper levels */
if (var->k == VVOID) /* not found? */
return; /* it is a global */
/* else was LOCAL or UPVAL */
idx = newupvalue(fs, n, var); /* will be a new upvalue */
}
init_exp(var, VUPVAL, idx);
return VUPVAL;
init_exp(var, VUPVAL, idx); /* new or old upvalue */
}
}
}
@@ -298,10 +297,11 @@ static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
static void singlevar (LexState *ls, expdesc *var) {
TString *varname = str_checkname(ls);
FuncState *fs = ls->fs;
if (singlevaraux(fs, varname, var, 1) == VVOID) { /* global name? */
singlevaraux(fs, varname, var, 1);
if (var->k == VVOID) { /* global name? */
expdesc key;
singlevaraux(fs, ls->envn, var, 1); /* get environment variable */
lua_assert(var->k == VLOCAL || var->k == VUPVAL);
lua_assert(var->k != VVOID); /* this one must exist */
codestring(ls, &key, varname); /* key is variable name */
luaK_indexed(fs, var, &key); /* env[varname] */
}
@@ -325,6 +325,8 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) {
luaK_nil(fs, reg, extra);
}
}
if (nexps > nvars)
ls->fs->freereg -= nexps - nvars; /* remove extra values */
}
@@ -1163,11 +1165,8 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
int nexps;
checknext(ls, '=');
nexps = explist(ls, &e);
if (nexps != nvars) {
if (nexps != nvars)
adjust_assign(ls, nvars, nexps, &e);
if (nexps > nvars)
ls->fs->freereg -= nexps - nvars; /* remove extra values */
}
else {
luaK_setoneret(ls->fs, &e); /* close last expression */
luaK_storevar(ls->fs, &lh->v, &e);

View File

@@ -1,5 +1,5 @@
/*
** $Id: lstrlib.c,v 1.248 2016/05/02 13:58:01 roberto Exp $
** $Id: lstrlib.c,v 1.251 2016/05/20 14:13:21 roberto Exp $
** Standard library for string operations and pattern-matching
** See Copyright Notice in lua.h
*/
@@ -928,20 +928,14 @@ static void addquoted (luaL_Buffer *b, const char *s, size_t len) {
/*
** Convert a Lua number to a string in floating-point hexadecimal
** format. Ensures the resulting string uses a dot as the radix
** character.
** Ensures the 'buff' string uses a dot as the radix character.
*/
static void addliteralnum (lua_State *L, luaL_Buffer *b, lua_Number n) {
char *buff = luaL_prepbuffsize(b, MAX_ITEM);
int nb = lua_number2strx(L, buff, MAX_ITEM,
"%" LUA_NUMBER_FRMLEN "a", n);
static void checkdp (char *buff, int nb) {
if (memchr(buff, '.', nb) == NULL) { /* no dot? */
char point = lua_getlocaledecpoint(); /* try locale point */
char *ppoint = memchr(buff, point, nb);
if (ppoint) *ppoint = '.'; /* change it to a dot */
}
luaL_addsize(b, nb);
}
@@ -954,11 +948,22 @@ static void addliteral (lua_State *L, luaL_Buffer *b, int arg) {
break;
}
case LUA_TNUMBER: {
if (!lua_isinteger(L, arg)) { /* write floats as hexa ('%a') */
addliteralnum(L, b, lua_tonumber(L, arg));
break;
char *buff = luaL_prepbuffsize(b, MAX_ITEM);
int nb;
if (!lua_isinteger(L, arg)) { /* float? */
lua_Number n = lua_tonumber(L, arg); /* write as hexa ('%a') */
nb = lua_number2strx(L, buff, MAX_ITEM, "%" LUA_NUMBER_FRMLEN "a", n);
checkdp(buff, nb); /* ensure it uses a dot */
}
/* else integers; write in "native" format *//* FALLTHROUGH */
else { /* integers */
lua_Integer n = lua_tointeger(L, arg);
const char *format = (n == LUA_MININTEGER) /* corner case? */
? "0x%" LUA_INTEGER_FRMLEN "x" /* use hexa */
: LUA_INTEGER_FMT; /* else use default format */
nb = l_sprintf(buff, MAX_ITEM, format, n);
}
luaL_addsize(b, nb);
break;
}
case LUA_TNIL: case LUA_TBOOLEAN: {
luaL_tolstring(L, arg, NULL);
@@ -1369,13 +1374,11 @@ static int str_pack (lua_State *L) {
case Kchar: { /* fixed-size string */
size_t len;
const char *s = luaL_checklstring(L, arg, &len);
if ((size_t)size <= len) /* string larger than (or equal to) needed? */
luaL_addlstring(&b, s, size); /* truncate string to asked size */
else { /* string smaller than needed */
luaL_addlstring(&b, s, len); /* add it all */
while (len++ < (size_t)size) /* pad extra space */
luaL_addchar(&b, LUAL_PACKPADBYTE);
}
luaL_argcheck(L, len <= (size_t)size, arg,
"string longer than given size");
luaL_addlstring(&b, s, len); /* add string */
while (len++ < (size_t)size) /* pad extra space */
luaL_addchar(&b, LUAL_PACKPADBYTE);
break;
}
case Kstring: { /* strings with length count */

View File

@@ -1,5 +1,5 @@
/*
** $Id: lua.h,v 1.330 2016/01/13 17:55:19 roberto Exp $
** $Id: lua.h,v 1.331 2016/05/30 15:53:28 roberto Exp $
** Lua - A Scripting Language
** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
** See Copyright Notice at the end of this file
@@ -363,7 +363,7 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud);
#define lua_pushliteral(L, s) lua_pushstring(L, "" s)
#define lua_pushglobaltable(L) \
lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)
((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS))
#define lua_tostring(L,i) lua_tolstring(L, (i), NULL)

View File

@@ -1,3 +1,24 @@
v1.0.0 (2016-7-11)
-----------
* Version 1.0.0 Released
v1.0.0-rc5 (2016-7-4)
-----------
* MongoDB : Support auth_scram_sha1
* MongoDB : Auto determine primary host
* Bugfix : memory leak in multicast
* Bugfix : Lua 5.3.3
* Bson : support meta array
v1.0.0-rc4 (2016-6-13)
-----------
* Update lua to 5.3.3
* Update jemalloc to 4.2.1
* Add debug console command ping
* Lua bson support __pairs
* Add mongo.createIndexes and fix bug in old mongo.createIndex
* Handle signal HUP to reopen log file (for logrotate)
v1.0.0-rc3 (2016-5-9)
-----------
* Update jemalloc 4.1.1

View File

@@ -1,3 +1,7 @@
## Skynet
Skynet is a lightweight online game framework, and it can be used in many other fields.
## Build
For Linux, install autoconf first for jemalloc:
@@ -26,15 +30,13 @@ Run these in different consoles:
./3rd/lua/lua examples/client.lua # Launch a client, and try to input hello.
```
## About Lua
## About Lua version
Skynet now uses a modified version of lua 5.3.2 ( http://www.lua.org/ftp/lua-5.3.2.tar.gz ) .
Skynet now uses a modified version of lua 5.3.3 ( https://github.com/ejoy/lua/tree/skynet ) for multiple lua states.
For details: http://lua-users.org/lists/lua-l/2014-03/msg00489.html
You can also use other official Lua versions, just edit the Makefile by yourself.
You can also use official Lua versions, just edit the Makefile by yourself.
## How To Use (Sorry, Only in Chinese now)
* Read Wiki https://github.com/cloudwu/skynet/wiki
* Read Wiki for documents https://github.com/cloudwu/skynet/wiki
* The FAQ in wiki https://github.com/cloudwu/skynet/wiki/FAQ

View File

@@ -9,7 +9,9 @@ start = "main" -- main script
bootstrap = "snlua bootstrap" -- The service for bootstrap
standalone = "0.0.0.0:2013"
luaservice = root.."service/?.lua;"..root.."test/?.lua;"..root.."examples/?.lua"
lualoader = "lualib/loader.lua"
lualoader = root .. "lualib/loader.lua"
lua_path = root.."lualib/?.lua;"..root.."lualib/?/init.lua"
lua_cpath = root .. "luaclib/?.so"
-- preload = "./examples/preload.lua" -- run preload.lua before every lua service run
snax = root.."examples/?.lua;"..root.."test/?.lua"
-- snax_interface_g = "snax_g"

View File

@@ -6,7 +6,9 @@ local max_client = 64
skynet.start(function()
skynet.error("Server start")
skynet.uniqueservice("protoloader")
local console = skynet.newservice("console")
if not skynet.getenv "daemon" then
local console = skynet.newservice("console")
end
skynet.newservice("debug_console",8000)
skynet.newservice("simpledb")
local watchdog = skynet.newservice("watchdog")

View File

@@ -6,7 +6,17 @@ skynet.register_protocol {
id = skynet.PTYPE_TEXT,
unpack = skynet.tostring,
dispatch = function(_, address, msg)
print(string.format("%x(%.2f): %s", address, skynet.time(), msg))
print(string.format(":%08x(%.2f): %s", address, skynet.time(), msg))
end
}
skynet.register_protocol {
name = "SYSTEM",
id = skynet.PTYPE_SYSTEM,
unpack = function(...) return ... end,
dispatch = function()
-- reopen signal
print("SIGHUP")
end
}

View File

@@ -238,8 +238,6 @@ write_double(struct bson *b, lua_Number d) {
}
}
static void pack_dict(lua_State *L, struct bson *b, bool array, int depth);
static inline void
append_key(struct bson *bs, int type, const char *key, size_t sz) {
write_byte(bs, type);
@@ -269,25 +267,7 @@ append_number(struct bson *bs, lua_State *L, const char *key, size_t sz) {
}
}
static void
append_table(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth) {
size_t len = lua_rawlen(L, -1);
bool isarray = false;
if (len > 0) {
lua_pushinteger(L, len);
if (lua_next(L,-2) == 0) {
isarray = true;
} else {
lua_pop(L,2);
}
}
if (isarray) {
append_key(bs, BSON_ARRAY, key, sz);
} else {
append_key(bs, BSON_DOCUMENT, key, sz);
}
pack_dict(L, bs, isarray, depth);
}
static void append_table(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth);
static void
write_binary(struct bson *b, const void * buffer, size_t sz) {
@@ -409,53 +389,122 @@ bson_numstr( char *str, unsigned int i ) {
}
static void
pack_dict(lua_State *L, struct bson *b, bool isarray, int depth) {
if (depth > MAX_DEPTH) {
luaL_error(L, "Too depth while encoding bson");
pack_array(lua_State *L, struct bson *b, int depth, size_t len) {
int length = reserve_length(b);
size_t i;
for (i=1;i<=len;i++) {
char numberkey[32];
size_t sz = bson_numstr(numberkey, i - 1);
const char * key = numberkey;
lua_geti(L, -1, i);
append_one(b, L, key, sz, depth);
lua_pop(L, 1);
}
luaL_checkstack(L, 16, NULL); // reserve enough stack space to pack table
write_byte(b,0);
write_length(b, b->size - length, length);
}
static void
pack_dict_data(lua_State *L, struct bson *b, int depth, int kt) {
const char * key = NULL;
size_t sz;
switch(kt) {
case LUA_TNUMBER:
// copy key, don't change key type
lua_pushvalue(L,-2);
lua_insert(L,-2);
key = lua_tolstring(L,-2,&sz);
append_one(b, L, key, sz, depth);
lua_pop(L,2);
break;
case LUA_TSTRING:
key = lua_tolstring(L,-2,&sz);
append_one(b, L, key, sz, depth);
lua_pop(L,1);
break;
default:
luaL_error(L, "Invalid key type : %s", lua_typename(L, kt));
return;
}
}
static void
pack_simple_dict(lua_State *L, struct bson *b, int depth) {
int length = reserve_length(b);
lua_pushnil(L);
while(lua_next(L,-2) != 0) {
int kt = lua_type(L, -2);
char numberkey[32];
const char * key = NULL;
size_t sz;
if (isarray) {
if (kt != LUA_TNUMBER) {
luaL_error(L, "Invalid array key type : %s", lua_typename(L, kt));
return;
}
sz = bson_numstr(numberkey, (unsigned int)lua_tointeger(L,-2)-1);
key = numberkey;
append_one(b, L, key, sz, depth);
lua_pop(L,1);
} else {
switch(kt) {
case LUA_TNUMBER:
// copy key, don't change key type
lua_pushvalue(L,-2);
lua_insert(L,-2);
key = lua_tolstring(L,-2,&sz);
append_one(b, L, key, sz, depth);
lua_pop(L,2);
break;
case LUA_TSTRING:
key = lua_tolstring(L,-2,&sz);
append_one(b, L, key, sz, depth);
lua_pop(L,1);
break;
default:
luaL_error(L, "Invalid key type : %s", lua_typename(L, kt));
return;
}
}
pack_dict_data(L, b, depth, kt);
}
write_byte(b,0);
write_length(b, b->size - length, length);
}
static void
pack_meta_dict(lua_State *L, struct bson *b, int depth) {
int length = reserve_length(b);
lua_pushvalue(L, -2); // push meta_obj
lua_call(L, 1, 3); // call __pairs_func => next_func, t_data, first_k
for(;;) {
lua_pushvalue(L, -2); // copy data
lua_pushvalue(L, -2); // copy k
lua_copy(L, -5, -3); // copy next_func replace old_k
lua_call(L, 2, 2); // call next_func
int kt = lua_type(L, -2);
if (kt == LUA_TNIL) {
lua_pop(L, 4); // pop all k, v, next_func, obj
break;
}
pack_dict_data(L, b, depth, kt);
}
write_byte(b,0);
write_length(b, b->size - length, length);
}
static bool
is_rawarray(lua_State *L) {
size_t len = lua_rawlen(L, -1);
if (len > 0) {
lua_pushinteger(L, len);
if (lua_next(L,-2) == 0) {
return true;
} else {
lua_pop(L,2);
}
}
return false;
}
static void
append_table(struct bson *bs, lua_State *L, const char *key, size_t sz, int depth) {
if (depth > MAX_DEPTH) {
luaL_error(L, "Too depth while encoding bson");
}
luaL_checkstack(L, 16, NULL); // reserve enough stack space to pack table
if (luaL_getmetafield(L, -1, "__len") != LUA_TNIL) {
lua_pushvalue(L, -2);
lua_call(L, 1, 1);
if (!lua_isinteger(L, -1)) {
luaL_error(L, "__len should return integer");
}
size_t len = lua_tointeger(L, -1);
lua_pop(L, 1);
append_key(bs, BSON_ARRAY, key, sz);
pack_array(L, bs, depth, len);
} else if (luaL_getmetafield(L, -1, "__pairs") != LUA_TNIL) {
append_key(bs, BSON_DOCUMENT, key, sz);
pack_meta_dict(L, bs, depth);
} else if (is_rawarray(L)) {
append_key(bs, BSON_ARRAY, key, sz);
pack_array(L, bs, depth, lua_rawlen(L, -1));
} else {
append_key(bs, BSON_DOCUMENT, key, sz);
pack_simple_dict(L, bs, depth);
}
}
static void
pack_ordered_dict(lua_State *L, struct bson *b, int n, int depth) {
int length = reserve_length(b);
@@ -853,7 +902,11 @@ lencode(lua_State *L) {
bson_create(&b);
lua_settop(L,1);
luaL_checktype(L, 1, LUA_TTABLE);
pack_dict(L, &b, false, 0);
if (luaL_getmetafield(L, -1, "__pairs") != LUA_TNIL) {
pack_meta_dict(L, &b, 0);
} else {
pack_simple_dict(L, &b, 0);
}
void * ud = lua_newuserdata(L, b.size);
memcpy(ud, b.ptr, b.size);
bson_destroy(&b);

View File

@@ -751,7 +751,7 @@ ldhexchange(lua_State *L) {
if (x64 == 0)
return luaL_error(L, "Can't be 0");
uint64_t r = powmodp(5, x64);
uint64_t r = powmodp(G, x64);
push64(L, r);
return 1;
}
@@ -878,6 +878,25 @@ lb64decode(lua_State *L) {
return 1;
}
static int
lxor_str(lua_State *L) {
size_t len1,len2;
const char *s1 = luaL_checklstring(L,1,&len1);
const char *s2 = luaL_checklstring(L,2,&len2);
if (len2 == 0) {
return luaL_error(L, "Can't xor empty string");
}
luaL_Buffer b;
char * buffer = luaL_buffinitsize(L, &b, len1);
int i;
for (i=0;i<len1;i++) {
buffer[i] = s1[i] ^ s2[i % len2];
}
luaL_addsize(&b, len1);
luaL_pushresult(&b);
return 1;
}
// defined in lsha1.c
int lsha1(lua_State *L);
int lhmac_sha1(lua_State *L);
@@ -906,6 +925,7 @@ luaopen_crypt(lua_State *L) {
{ "sha1", lsha1 },
{ "hmac_sha1", lhmac_sha1 },
{ "hmac_hash", lhmac_hash },
{ "xor_str", lxor_str },
{ NULL, NULL },
};
luaL_newlib(L,l);

View File

@@ -60,18 +60,6 @@ mc_packremote(lua_State *L) {
return pack(L, msg, size);
}
static int
mc_packstring(lua_State *L) {
size_t size;
const char * msg = luaL_checklstring(L, 1, &size);
if (size != (uint32_t)size) {
return luaL_error(L, "string is too long");
}
void * data = skynet_malloc(size);
memcpy(data, msg, size);
return pack(L, data, size);
}
/*
lightuserdata struct mc_package **
integer size (must be sizeof(struct mc_package *)
@@ -82,7 +70,7 @@ static int
mc_unpacklocal(lua_State *L) {
struct mc_package ** pack = lua_touserdata(L,1);
int sz = luaL_checkinteger(L,2);
if (sz != sizeof(*pack)) {
if (sz != sizeof(pack)) {
return luaL_error(L, "Invalid multicast package size %d", sz);
}
lua_pushlightuserdata(L, *pack);
@@ -108,6 +96,8 @@ mc_bindrefer(lua_State *L) {
lua_pushlightuserdata(L, *pack);
skynet_free(pack);
return 1;
}
@@ -161,7 +151,6 @@ luaopen_multicast_core(lua_State *L) {
{ "bind", mc_bindrefer },
{ "close", mc_closelocal },
{ "remote", mc_remote },
{ "packstring", mc_packstring },
{ "packremote", mc_packremote },
{ "nextid", mc_nextid },
{ NULL, NULL },

View File

@@ -8,7 +8,43 @@ local socket_error = setmetatable({} , { __tostring = function() return "[Socket
sockethelper.socket_error = socket_error
function sockethelper.readfunc(fd)
local function preread(fd, str)
return function (sz)
if str then
if sz == #str or sz == nil then
local ret = str
str = nil
return ret
else
if sz < #str then
local ret = str:sub(1,sz)
str = str:sub(sz + 1)
return ret
else
sz = sz - #str
local ret = readbytes(fd, sz)
if ret then
return str .. ret
else
error(socket_error)
end
end
end
else
local ret = readbytes(fd, sz)
if ret then
return ret
else
error(socket_error)
end
end
end
end
function sockethelper.readfunc(fd, pre)
if pre then
return preread(fd, pre)
end
return function (sz)
local ret = readbytes(fd, sz)
if ret then

View File

@@ -4,6 +4,7 @@ local socketchannel = require "socketchannel"
local skynet = require "skynet"
local driver = require "mongo.driver"
local md5 = require "md5"
local crypt = require "crypt"
local rawget = rawget
local assert = assert
@@ -83,10 +84,15 @@ end
local function mongo_auth(mongoc)
local user = rawget(mongoc, "username")
local pass = rawget(mongoc, "password")
local authmod = rawget(mongoc, "authmod") or "scram_sha1"
authmod = "auth_" .. authmod
return function()
if user ~= nil and pass ~= nil then
assert(mongoc:auth(user, pass))
-- autmod can be "mongodb_cr" or "scram_sha1"
local auth_func = mongoc[authmod]
assert(auth_func , "Invalid authmod")
assert(auth_func(mongoc,user, pass))
end
local rs_data = mongoc:runCommand("ismaster")
if rs_data.ok == 1 then
@@ -99,12 +105,38 @@ local function mongo_auth(mongoc)
mongoc.__sock:changebackup(backup)
end
if rs_data.ismaster then
if rawget(mongoc, "__pickserver") then
rawset(mongoc, "__pickserver", nil)
end
return
else
local host, port = __parse_addr(rs_data.primary)
mongoc.host = host
mongoc.port = port
mongoc.__sock:changehost(host, port)
if rs_data.primary then
local host, port = __parse_addr(rs_data.primary)
mongoc.host = host
mongoc.port = port
mongoc.__sock:changehost(host, port)
else
skynet.error("WARNING: NO PRIMARY RETURN " .. rs_data.me)
-- determine the primary db using hosts
local pickserver = {}
if rawget(mongoc, "__pickserver") == nil then
for _, v in ipairs(rs_data.hosts) do
if v ~= rs_data.me then
table.insert(pickserver, v)
end
rawset(mongoc, "__pickserver", pickserver)
end
end
if #mongoc.__pickserver <= 0 then
error("CAN NOT DETERMINE THE PRIMARY DB")
end
skynet.error("INFO: TRY TO CONNECT " .. mongoc.__pickserver[1])
local host, port = __parse_addr(mongoc.__pickserver[1])
table.remove(mongoc.__pickserver, 1)
mongoc.host = host
mongoc.port = port
mongoc.__sock:changehost(host, port)
end
end
end
end
@@ -122,6 +154,7 @@ function mongo.client( conf )
port = first.port or 27017,
username = first.username,
password = first.password,
authmod = first.authmod,
}
obj.__id = 0
@@ -172,7 +205,7 @@ function mongo_client:runCommand(...)
return self.admin:runCommand(...)
end
function mongo_client:auth(user,password)
function mongo_client:auth_mongodb_cr(user,password)
local password = md5.sumhexa(string.format("%s:mongo:%s",user,password))
local result= self:runCommand "getnonce"
if result.ok ~=1 then
@@ -184,6 +217,83 @@ function mongo_client:auth(user,password)
return result.ok == 1
end
local function salt_password(password, salt, iter)
salt = salt .. "\0\0\0\1"
local output = crypt.hmac_sha1(password, salt)
local inter = output
for i=2,iter do
inter = crypt.hmac_sha1(password, inter)
output = crypt.xor_str(output, inter)
end
return output
end
function mongo_client:auth_scram_sha1(username,password)
local user = string.gsub(string.gsub(username, '=', '=3D'), ',' , '=2C')
local nonce = crypt.base64encode(crypt.randomkey())
local first_bare = "n=" .. user .. ",r=" .. nonce
local sasl_start_payload = crypt.base64encode("n,," .. first_bare)
local r
r = self:runCommand("saslStart",1,"autoAuthorize",1,"mechanism","SCRAM-SHA-1","payload",sasl_start_payload)
if r.ok ~= 1 then
return false
end
local conversationId = r['conversationId']
local server_first = r['payload']
local parsed_s = crypt.base64decode(server_first)
local parsed_t = {}
for k, v in string.gmatch(parsed_s, "(%w+)=([^,]*)") do
parsed_t[k] = v
end
local iterations = tonumber(parsed_t['i'])
local salt = parsed_t['s']
local rnonce = parsed_t['r']
if not string.sub(rnonce, 1, 12) == nonce then
skynet.error("Server returned an invalid nonce.")
return false
end
local without_proof = "c=biws,r=" .. rnonce
local pbkdf2_key = md5.sumhexa(string.format("%s:mongo:%s",username,password))
local salted_pass = salt_password(pbkdf2_key, crypt.base64decode(salt), iterations)
local client_key = crypt.hmac_sha1(salted_pass, "Client Key")
local stored_key = crypt.sha1(client_key)
local auth_msg = first_bare .. ',' .. parsed_s .. ',' .. without_proof
local client_sig = crypt.hmac_sha1(stored_key, auth_msg)
local client_key_xor_sig = crypt.xor_str(client_key, client_sig)
local client_proof = "p=" .. crypt.base64encode(client_key_xor_sig)
local client_final = crypt.base64encode(without_proof .. ',' .. client_proof)
local server_key = crypt.hmac_sha1(salted_pass, "Server Key")
local server_sig = crypt.base64encode(crypt.hmac_sha1(server_key, auth_msg))
r = self:runCommand("saslContinue",1,"conversationId",conversationId,"payload",client_final)
if r.ok ~= 1 then
return false
end
parsed_s = crypt.base64decode(r['payload'])
parsed_t = {}
for k, v in string.gmatch(parsed_s, "(%w+)=([^,]*)") do
parsed_t[k] = v
end
if parsed_t['v'] ~= server_sig then
skynet.error("Server returned an invalid signature.")
return false
end
if not r.done then
r = self:runCommand("saslContinue",1,"conversationId",conversationId,"payload","")
if r.ok ~= 1 then
return false
end
if not r.done then
skynet.error("SASL conversation failed to complete.")
return false
end
end
return true
end
function mongo_client:logout()
local result = self:runCommand "logout"
return result.ok == 1
@@ -318,30 +428,73 @@ function mongo_cursor:count(with_limit_and_skip)
end
-- For compatibility.
-- collection:createIndex({username = 1}, {unique = true})
function mongo_collection:createIndex(keys, option)
local name = option.name
option.name = nil
if not name then
for k, v in pairs(keys) do
name = (name == nil) and k or (name .. "_" .. k)
name = name .. "_" .. v
end
end
local doc = {};
doc.name = name
doc.key = keys
for k, v in pairs(option) do
local function createIndex_onekey(self, key, option)
local doc = {}
for k,v in pairs(option) do
doc[k] = v
end
local k,v = next(key) -- support only one key
assert(next(key,k) == nil, "Use new api for multi-keys")
doc.name = doc.name or (k .. "_" .. v)
doc.key = key
return self.database:runCommand("createIndexes", self.name, "indexes", {doc})
end
mongo_collection.ensureIndex = mongo_collection.createIndex;
local function IndexModel(option)
local doc = {}
for k,v in pairs(option) do
if type(k) == "string" then
doc[k] = v
end
end
local keys = {}
local name
for _, kv in ipairs(option) do
local k,v
if type(kv) == "string" then
k = kv
v = 1
else
k,v = next(kv)
end
table.insert(keys, k)
table.insert(keys, v)
name = (name == nil) and k or (name .. "_" .. k)
name = name .. "_" .. v
end
assert(name, "Need keys")
doc.name = doc.name or name
doc.key = bson_encode_order(table.unpack(keys))
return doc
end
-- collection:createIndex { { key1 = 1}, { key2 = 1 }, unique = true }
-- or collection:createIndex { "key1", "key2", unique = true }
-- or collection:createIndex( { key1 = 1} , { unique = true } ) -- For compatibility
function mongo_collection:createIndex(arg1 , arg2)
if arg2 then
return createIndex_onekey(self, arg1, arg2)
else
return self.database:runCommand("createIndexes", self.name, "indexes", { IndexModel(arg1) })
end
end
function mongo_collection:createIndexes(...)
local idx = { ... }
for k,v in ipairs(idx) do
idx[k] = IndexModel(v)
end
return self.database:runCommand("createIndexes", self.name, "indexes", idx)
end
mongo_collection.ensureIndex = mongo_collection.createIndex
function mongo_collection:drop()
return self.database:runCommand("drop", self.name)

View File

@@ -64,32 +64,6 @@ end
-------------------
local function redis_login(auth, db)
if auth == nil and db == nil then
return
end
return function(so)
if auth then
so:request("AUTH "..auth.."\r\n", read_response)
end
if db then
so:request("SELECT "..db.."\r\n", read_response)
end
end
end
function redis.connect(db_conf)
local channel = socketchannel.channel {
host = db_conf.host,
port = db_conf.port or 6379,
auth = redis_login(db_conf.auth, db_conf.db),
nodelay = true,
}
-- try connect first only once
channel:connect(true)
return setmetatable( { channel }, meta )
end
function command:disconnect()
self[1]:close()
setmetatable(self, nil)
@@ -149,6 +123,32 @@ local function compose_message(cmd, msg)
return lines
end
local function redis_login(auth, db)
if auth == nil and db == nil then
return
end
return function(so)
if auth then
so:request(compose_message("AUTH", auth), read_response)
end
if db then
so:request(compose_message("SELECT", db), read_response)
end
end
end
function redis.connect(db_conf)
local channel = socketchannel.channel {
host = db_conf.host,
port = db_conf.port or 6379,
auth = redis_login(db_conf.auth, db_conf.db),
nodelay = true,
}
-- try connect first only once
channel:connect(true)
return setmetatable( { channel }, meta )
end
setmetatable(command, { __index = function(t,k)
local cmd = string.upper(k)
local f = function (self, v, ...)
@@ -233,7 +233,7 @@ local watchmeta = {
local function watch_login(obj, auth)
return function(so)
if auth then
so:request("AUTH "..auth.."\r\n", read_response)
so:request(compose_message("AUTH", auth), read_response)
end
for k in pairs(obj.__psubscribe) do
so:request(compose_message ("PSUBSCRIBE", k))

View File

@@ -95,7 +95,7 @@ end
-- coroutine reuse
local coroutine_pool = {}
local coroutine_pool = setmetatable({}, { __mode = "kv" })
local function co_create(f)
local co = table.remove(coroutine_pool)
@@ -661,15 +661,10 @@ function skynet.memlimit(bytes)
skynet.memlimit = nil -- set only once
end
local function clear_pool()
coroutine_pool = {}
end
-- Inject internal debug framework
local debug = require "skynet.debug"
debug(skynet, {
debug.init(skynet, {
dispatch = skynet.dispatch_message,
clear = clear_pool,
suspend = suspend,
})

View File

@@ -1,89 +1,105 @@
local table = table
local extern_dbgcmd = {};
local extern_dbgcmd = {}
return function (skynet, export)
local function init(skynet, export)
local internal_info_func
local internal_info_func
function skynet.info_func(func)
internal_info_func = func
end
local dbgcmd
local function init_dbgcmd()
dbgcmd = extern_dbgcmd
function dbgcmd.MEM()
local kb, bytes = collectgarbage "count"
skynet.ret(skynet.pack(kb,bytes))
end
function dbgcmd.GC()
export.clear()
collectgarbage "collect"
end
function dbgcmd.STAT()
local stat = {}
stat.mqlen = skynet.mqlen()
stat.task = skynet.task()
skynet.ret(skynet.pack(stat))
end
function dbgcmd.TASK()
local task = {}
skynet.task(task)
skynet.ret(skynet.pack(task))
end
function dbgcmd.INFO()
if internal_info_func then
skynet.ret(skynet.pack(internal_info_func()))
else
skynet.ret(skynet.pack(nil))
function skynet.info_func(func)
internal_info_func = func
end
local dbgcmd
local function init_dbgcmd()
dbgcmd = {}
function dbgcmd.MEM()
local kb, bytes = collectgarbage "count"
skynet.ret(skynet.pack(kb,bytes))
end
function dbgcmd.GC()
collectgarbage "collect"
end
function dbgcmd.STAT()
local stat = {}
stat.mqlen = skynet.mqlen()
stat.task = skynet.task()
skynet.ret(skynet.pack(stat))
end
function dbgcmd.TASK()
local task = {}
skynet.task(task)
skynet.ret(skynet.pack(task))
end
function dbgcmd.INFO(...)
if internal_info_func then
skynet.ret(skynet.pack(internal_info_func(...)))
else
skynet.ret(skynet.pack(nil))
end
end
function dbgcmd.EXIT()
skynet.exit()
end
function dbgcmd.RUN(source, filename)
local inject = require "skynet.inject"
local output = inject(skynet, source, filename , export.dispatch, skynet.register_protocol)
collectgarbage "collect"
skynet.ret(skynet.pack(table.concat(output, "\n")))
end
function dbgcmd.TERM(service)
skynet.term(service)
end
function dbgcmd.REMOTEDEBUG(...)
local remotedebug = require "skynet.remotedebug"
remotedebug.start(export, ...)
end
function dbgcmd.SUPPORT(pname)
return skynet.ret(skynet.pack(skynet.dispatch(pname) ~= nil))
end
function dbgcmd.PING()
return skynet.ret()
end
function dbgcmd.LINK()
-- no return, raise error when exit
end
return dbgcmd
end -- function init_dbgcmd
local function _debug_dispatch(session, address, cmd, ...)
dbgcmd = dbgcmd or init_dbgcmd() -- lazy init dbgcmd
local f = dbgcmd[cmd] or extern_dbgcmd[cmd]
assert(f, cmd)
f(...)
end
skynet.register_protocol {
name = "debug",
id = assert(skynet.PTYPE_DEBUG),
pack = assert(skynet.pack),
unpack = assert(skynet.unpack),
dispatch = _debug_dispatch,
}
end
function dbgcmd.EXIT()
skynet.exit()
local function reg_debugcmd(name, fn)
extern_dbgcmd[name] = fn
end
function dbgcmd.RUN(source, filename)
local inject = require "skynet.inject"
local output = inject(skynet, source, filename , export.dispatch, skynet.register_protocol)
collectgarbage "collect"
skynet.ret(skynet.pack(table.concat(output, "\n")))
end
function dbgcmd.TERM(service)
skynet.term(service)
end
function dbgcmd.REMOTEDEBUG(...)
local remotedebug = require "skynet.remotedebug"
remotedebug.start(export, ...)
end
function dbgcmd.SUPPORT(pname)
return skynet.ret(skynet.pack(skynet.dispatch(pname) ~= nil))
end
return dbgcmd
end -- function init_dbgcmd
local function _debug_dispatch(session, address, cmd, ...)
local f = (dbgcmd or init_dbgcmd())[cmd] -- lazy init dbgcmd
assert(f, cmd)
f(...)
end
skynet.register_protocol {
name = "debug",
id = assert(skynet.PTYPE_DEBUG),
pack = assert(skynet.pack),
unpack = assert(skynet.unpack),
dispatch = _debug_dispatch,
return {
init = init,
reg_debugcmd = reg_debugcmd,
}
end

View File

@@ -328,7 +328,8 @@ local function block_connect(self, once)
r = check_connection(self)
if r == nil then
error(string.format("Connect to %s:%d failed (%s)", self.__host, self.__port, err))
skynet.error(string.format("Connect to %s:%d failed (%s)", self.__host, self.__port, err))
error(socket_error)
else
return r
end

View File

@@ -3,9 +3,11 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
struct logger {
FILE * handle;
char * filename;
int close;
};
@@ -14,6 +16,8 @@ logger_create(void) {
struct logger * inst = skynet_malloc(sizeof(*inst));
inst->handle = NULL;
inst->close = 0;
inst->filename = NULL;
return inst;
}
@@ -22,16 +26,26 @@ logger_release(struct logger * inst) {
if (inst->close) {
fclose(inst->handle);
}
skynet_free(inst->filename);
skynet_free(inst);
}
static int
_logger(struct skynet_context * context, void *ud, int type, int session, uint32_t source, const void * msg, size_t sz) {
logger_cb(struct skynet_context * context, void *ud, int type, int session, uint32_t source, const void * msg, size_t sz) {
struct logger * inst = ud;
fprintf(inst->handle, "[:%08x] ",source);
fwrite(msg, sz , 1, inst->handle);
fprintf(inst->handle, "\n");
fflush(inst->handle);
switch (type) {
case PTYPE_SYSTEM:
if (inst->filename) {
inst->handle = freopen(inst->filename, "a", inst->handle);
}
break;
case PTYPE_TEXT:
fprintf(inst->handle, "[:%08x] ",source);
fwrite(msg, sz , 1, inst->handle);
fprintf(inst->handle, "\n");
fflush(inst->handle);
break;
}
return 0;
}
@@ -43,12 +57,14 @@ logger_init(struct logger * inst, struct skynet_context *ctx, const char * parm)
if (inst->handle == NULL) {
return 1;
}
inst->filename = skynet_malloc(strlen(parm)+1);
strcpy(inst->filename, parm);
inst->close = 1;
} else {
inst->handle = stdout;
}
if (inst->handle) {
skynet_callback(ctx, inst, _logger);
skynet_callback(ctx, inst, logger_cb);
skynet_command(ctx, "REG", ".logger");
return 0;
}

View File

@@ -4,6 +4,8 @@ local core = require "skynet.core"
local socket = require "socket"
local snax = require "snax"
local memory = require "memory"
local httpd = require "http.httpd"
local sockethelper = require "http.sockethelper"
local port = tonumber(...)
local COMMAND = {}
@@ -84,6 +86,13 @@ local function console_main_loop(stdin, print)
if not cmdline then
break
end
if cmdline:sub(1,4) == "GET " then
-- http
local code, url = httpd.read_request(sockethelper.readfunc(stdin, cmdline.. "\n"), 8192)
local cmdline = url:sub(2):gsub("/"," ")
docmd(cmdline, print, stdin)
break
end
if cmdline ~= "" then
docmd(cmdline, print, stdin)
end
@@ -115,7 +124,7 @@ function COMMAND.help()
help = "This help message",
list = "List all the service",
stat = "Dump all stats",
info = "Info address : get service infomation",
info = "info address : get service infomation",
exit = "exit address : kill a lua service",
kill = "kill address : kill service",
mem = "mem : show memory status",
@@ -133,6 +142,7 @@ function COMMAND.help()
signal = "signal address sig",
cmem = "Show C memory info",
shrtbl = "Show shared short string table info",
ping = "ping address",
}
end
@@ -227,9 +237,9 @@ function COMMAND.task(fd, address)
return skynet.call(address,"debug","TASK")
end
function COMMAND.info(fd, address)
function COMMAND.info(fd, address, ...)
address = adjust_address(address)
return skynet.call(address,"debug","INFO")
return skynet.call(address,"debug","INFO", ...)
end
function COMMAND.debug(fd, address)
@@ -283,3 +293,11 @@ function COMMAND.shrtbl()
local n, total, longest, space = memory.ssinfo()
return { n = n, total = total, longest = longest, space = space }
end
function COMMAND.ping(fd, address)
address = adjust_address(address)
local ti = skynet.now()
skynet.call(address, "debug", "PING")
ti = skynet.now() - ti
return tostring(ti)
end

View File

@@ -78,13 +78,13 @@ local function publish(c , source, pack, size)
local group = channel[c]
if group == nil or next(group) == nil then
-- dead channel, delete the pack. mc.bind returns the pointer in pack
-- dead channel, delete the pack. mc.bind returns the pointer in pack and free the pack (struct mc_package **)
local pack = mc.bind(pack, 1)
mc.close(pack)
return
end
mc.bind(pack, channel_n[c])
local msg = skynet.tostring(pack, size)
local msg = skynet.tostring(pack, size) -- copy (pack,size) to a string
mc.bind(pack, channel_n[c]) -- mc.bind will free the pack(struct mc_package **)
for k in pairs(group) do
-- the msg is a pointer to the real message, publish pointer in local is ok.
skynet.redirect(k, source, "multicast", c , msg)

View File

@@ -16,6 +16,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
struct monitor {
int count;
@@ -32,6 +33,15 @@ struct worker_parm {
int weight;
};
static int SIG = 0;
static void
handle_hup(int signal) {
if (signal == SIGHUP) {
SIG = 1;
}
}
#define CHECK_ABORT if (skynet_context_total()==0) break;
static void
@@ -100,6 +110,21 @@ thread_monitor(void *p) {
return NULL;
}
static void
signal_hup() {
// make log file reopen
struct skynet_message smsg;
smsg.source = 0;
smsg.session = 0;
smsg.data = NULL;
smsg.sz = (size_t)PTYPE_SYSTEM << MESSAGE_TYPE_SHIFT;
uint32_t logger = skynet_handle_findname("logger");
if (logger) {
skynet_context_push(logger, &smsg);
}
}
static void *
thread_timer(void *p) {
struct monitor * m = p;
@@ -109,6 +134,10 @@ thread_timer(void *p) {
CHECK_ABORT
wakeup(m,m->count-1);
usleep(2500);
if (SIG) {
signal_hup();
SIG = 0;
}
}
// wakeup socket thread
skynet_socket_exit();
@@ -216,6 +245,13 @@ bootstrap(struct skynet_context * logger, const char * cmdline) {
void
skynet_start(struct skynet_config * config) {
// register SIGHUP for log file reopen
struct sigaction sa;
sa.sa_handler = &handle_hup;
sa.sa_flags = SA_RESTART;
sigfillset(&sa.sa_mask);
sigaction(SIGHUP, &sa, NULL);
if (config->daemon) {
if (daemon_init(config->daemon)) {
exit(1);

95
test/testbson.lua Normal file
View File

@@ -0,0 +1,95 @@
local bson = require "bson"
sub = bson.encode_order( "hello", 1, "world", 2 )
local function tbl_next(...)
print("--- next.a", ...)
local k, v = next(...)
print("--- next.b", k, v)
return k, v
end
local function tbl_pairs(obj)
return tbl_next, obj.__data, nil
end
local obj_a = {
__data = {
[1] = 2,
[3] = 4,
[5] = 6,
}
}
setmetatable(
obj_a,
{
__index = obj_a.__data,
__pairs = tbl_pairs,
}
)
local obj_b = {
__data = {
[7] = 8,
[9] = 10,
[11] = obj_a,
}
}
setmetatable(
obj_b,
{
__index = obj_b.__data,
__pairs = tbl_pairs,
}
)
local metaarray = setmetatable({ n = 5 }, {
__len = function(self) return self.n end,
__index = function(self, idx) return tostring(idx) end,
})
b = bson.encode {
a = 1,
b = true,
c = bson.null,
d = { 1,2,3,4 },
e = bson.binary "hello",
f = bson.regex ("*","i"),
g = bson.regex "hello",
h = bson.date (os.time()),
i = bson.timestamp(os.time()),
j = bson.objectid(),
k = { a = false, b = true },
l = {},
m = bson.minkey,
n = bson.maxkey,
o = sub,
p = 2^32-1,
q = obj_b,
r = metaarray,
}
print "\n[before replace]"
t = b:decode()
for k, v in pairs(t) do
print(k,type(v))
end
for k,v in ipairs(t.r) do
print(k,v)
end
b:makeindex()
b.a = 2
b.b = false
b.h = bson.date(os.time())
b.i = bson.timestamp(os.time())
b.j = bson.objectid()
print "\n[after replace]"
t = b:decode()
print("o.hello", bson.type(t.o.hello))

View File

@@ -1,17 +1,26 @@
local skynet = require "skynet"
local names = {"cluster", "dns", "mongo", "mysql", "redis", "sharedata", "socket", "sproto"}
-- set sandbox memory limit to 1M, must set here (at start, out of skynet.start)
skynet.memlimit(1 * 1024 * 1024)
skynet.start(function()
local a = {}
local limit
local ok, err = pcall(function()
for i=1, 1000000 do
limit = i
table.insert(a, {})
end
end)
skynet.error(limit, err)
skynet.exit()
local a = {}
local limit
local ok, err = pcall(function()
for i=1, 12355 do
limit = i
table.insert(a, {})
end
end)
local libs = {}
for k,v in ipairs(names) do
local ok, m = pcall(require, v)
if ok then
libs[v] = m
end
end
skynet.error(limit, err)
skynet.exit()
end)