Compare commits

..

31 Commits

Author SHA1 Message Date
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
22 changed files with 481 additions and 237 deletions

View File

@@ -1012,10 +1012,9 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data,
return status; 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 */ /* copy constants and nested proto */
int i,n; int i,n;
Proto *f = luaF_newproto(L, src->sp);
n = src->sp->sizek; n = src->sp->sizek;
f->k=luaM_newvector(L,n,TValue); f->k=luaM_newvector(L,n,TValue);
for (i=0; i<n; i++) setnilvalue(&f->k[i]); 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 *); 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]=NULL;
for (i=0; i<n; i++) { 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) { 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; return;
} }
cl = luaF_newLclosure(L,f->nupvalues); cl = luaF_newLclosure(L,f->nupvalues);
cl->p = cloneproto(L, f->p);
setclLvalue(L,L->top,cl); setclLvalue(L,L->top,cl);
api_incr_top(L); api_incr_top(L);
cl->p = luaF_newproto(L, f->p->sp);
cloneproto(L, cl->p, f->p);
luaF_initupvals(L, cl); luaF_initupvals(L, cl);
if (cl->nupvalues >= 1) { /* does it have an upvalue? */ 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 ** Code generator for Lua
** See Copyright Notice in lua.h ** 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: case OPR_MINUS: case OPR_BNOT:
if (constfolding(fs, op + LUA_OPUNM, e, &ef)) if (constfolding(fs, op + LUA_OPUNM, e, &ef))
break; break;
/* else go through */ /* FALLTHROUGH */
case OPR_LEN: case OPR_LEN:
codeunexpval(fs, cast(OpCode, op + OP_UNM), e, line); codeunexpval(fs, cast(OpCode, op + OP_UNM), e, line);
break; break;

View File

@@ -492,15 +492,19 @@ static int marksharedproto (global_State *g, SharedProto *f) {
** NULL, so the use of 'markobjectN') ** NULL, so the use of 'markobjectN')
*/ */
static int traverseproto (global_State *g, Proto *f) { static int traverseproto (global_State *g, Proto *f) {
int i; int i,nk,np;
if (f->cache && iswhite(f->cache)) if (f->cache && iswhite(f->cache))
f->cache = NULL; /* allow cache to be collected */ 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]); 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]); markobjectN(g, f->p[i]);
return sizeof(Proto) + sizeof(Proto *) * f->sp->sizep + return sizeof(Proto) + sizeof(Proto *) * np +
sizeof(TValue) * f->sp->sizek + sizeof(TValue) * nk +
marksharedproto(g, f->sp); 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 ** Some generic functions over Lua objects
** See Copyright Notice in lua.h ** 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) { static const char *l_str2int (const char *s, lua_Integer *result) {
lua_Unsigned a = 0; lua_Unsigned a = 0;
int empty = 1; int empty = 1;
@@ -309,7 +312,10 @@ static const char *l_str2int (const char *s, lua_Integer *result) {
} }
else { /* decimal */ else { /* decimal */
for (; lisdigit(cast_uchar(*s)); s++) { 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; 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 ** Lua Parser
** See Copyright Notice in lua.h ** 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 Find variable with given name 'n'. If it is an upvalue, add this
upvalue into all intermediate functions. 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? */ if (fs == NULL) /* no more levels? */
return VVOID; /* default is global */ init_exp(var, VVOID, 0); /* default is global */
else { else {
int v = searchvar(fs, n); /* look up locals at current level */ int v = searchvar(fs, n); /* look up locals at current level */
if (v >= 0) { /* found? */ if (v >= 0) { /* found? */
init_exp(var, VLOCAL, v); /* variable is local */ init_exp(var, VLOCAL, v); /* variable is local */
if (!base) if (!base)
markupval(fs, v); /* local will be used as an upval */ markupval(fs, v); /* local will be used as an upval */
return VLOCAL;
} }
else { /* not found as local at current level; try upvalues */ else { /* not found as local at current level; try upvalues */
int idx = searchupvalue(fs, n); /* try existing upvalues */ int idx = searchupvalue(fs, n); /* try existing upvalues */
if (idx < 0) { /* not found? */ if (idx < 0) { /* not found? */
if (singlevaraux(fs->prev, n, var, 0) == VVOID) /* try upper levels */ singlevaraux(fs->prev, n, var, 0); /* try upper levels */
return VVOID; /* not found; is a global */ if (var->k == VVOID) /* not found? */
return; /* it is a global */
/* else was LOCAL or UPVAL */ /* else was LOCAL or UPVAL */
idx = newupvalue(fs, n, var); /* will be a new upvalue */ idx = newupvalue(fs, n, var); /* will be a new upvalue */
} }
init_exp(var, VUPVAL, idx); init_exp(var, VUPVAL, idx); /* new or old upvalue */
return VUPVAL;
} }
} }
} }
@@ -298,10 +297,11 @@ static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) {
static void singlevar (LexState *ls, expdesc *var) { static void singlevar (LexState *ls, expdesc *var) {
TString *varname = str_checkname(ls); TString *varname = str_checkname(ls);
FuncState *fs = ls->fs; 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; expdesc key;
singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ 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 */ codestring(ls, &key, varname); /* key is variable name */
luaK_indexed(fs, var, &key); /* env[varname] */ luaK_indexed(fs, var, &key); /* env[varname] */
} }

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 ** Standard library for string operations and pattern-matching
** See Copyright Notice in lua.h ** 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 ** Ensures the 'buff' string uses a dot as the radix character.
** format. Ensures the resulting string uses a dot as the radix
** character.
*/ */
static void addliteralnum (lua_State *L, luaL_Buffer *b, lua_Number n) { static void checkdp (char *buff, int nb) {
char *buff = luaL_prepbuffsize(b, MAX_ITEM);
int nb = lua_number2strx(L, buff, MAX_ITEM,
"%" LUA_NUMBER_FRMLEN "a", n);
if (memchr(buff, '.', nb) == NULL) { /* no dot? */ if (memchr(buff, '.', nb) == NULL) { /* no dot? */
char point = lua_getlocaledecpoint(); /* try locale point */ char point = lua_getlocaledecpoint(); /* try locale point */
char *ppoint = memchr(buff, point, nb); char *ppoint = memchr(buff, point, nb);
if (ppoint) *ppoint = '.'; /* change it to a dot */ 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; break;
} }
case LUA_TNUMBER: { case LUA_TNUMBER: {
if (!lua_isinteger(L, arg)) { /* write floats as hexa ('%a') */ char *buff = luaL_prepbuffsize(b, MAX_ITEM);
addliteralnum(L, b, lua_tonumber(L, arg)); int nb;
break; 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: { case LUA_TNIL: case LUA_TBOOLEAN: {
luaL_tolstring(L, arg, NULL); luaL_tolstring(L, arg, NULL);
@@ -1369,13 +1374,11 @@ static int str_pack (lua_State *L) {
case Kchar: { /* fixed-size string */ case Kchar: { /* fixed-size string */
size_t len; size_t len;
const char *s = luaL_checklstring(L, arg, &len); const char *s = luaL_checklstring(L, arg, &len);
if ((size_t)size <= len) /* string larger than (or equal to) needed? */ luaL_argcheck(L, len <= (size_t)size, arg,
luaL_addlstring(&b, s, size); /* truncate string to asked size */ "string longer than given size");
else { /* string smaller than needed */ luaL_addlstring(&b, s, len); /* add string */
luaL_addlstring(&b, s, len); /* add it all */ while (len++ < (size_t)size) /* pad extra space */
while (len++ < (size_t)size) /* pad extra space */ luaL_addchar(&b, LUAL_PACKPADBYTE);
luaL_addchar(&b, LUAL_PACKPADBYTE);
}
break; break;
} }
case Kstring: { /* strings with length count */ 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 - A Scripting Language
** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** Lua.org, PUC-Rio, Brazil (http://www.lua.org)
** See Copyright Notice at the end of this file ** 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_pushliteral(L, s) lua_pushstring(L, "" s)
#define lua_pushglobaltable(L) \ #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) #define lua_tostring(L,i) lua_tolstring(L, (i), NULL)

View File

@@ -1,3 +1,12 @@
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) v1.0.0-rc3 (2016-5-9)
----------- -----------
* Update jemalloc 4.1.1 * Update jemalloc 4.1.1

View File

@@ -26,13 +26,13 @@ Run these in different consoles:
./3rd/lua/lua examples/client.lua # Launch a client, and try to input hello. ./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 ( http://www.lua.org/ftp/lua-5.3.3.tar.gz ) .
For details: http://lua-users.org/lists/lua-l/2014-03/msg00489.html 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) ## How To Use (Sorry, Only in Chinese now)

View File

@@ -6,7 +6,17 @@ skynet.register_protocol {
id = skynet.PTYPE_TEXT, id = skynet.PTYPE_TEXT,
unpack = skynet.tostring, unpack = skynet.tostring,
dispatch = function(_, address, msg) 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 end
} }

View File

@@ -409,7 +409,44 @@ bson_numstr( char *str, unsigned int i ) {
} }
static void static void
pack_dict(lua_State *L, struct bson *b, bool isarray, int depth) { pack_dict_data(lua_State *L, struct bson *b, bool isarray, int depth, int kt) {
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;
}
}
}
static void
pack_simple_dict(lua_State *L, struct bson *b, bool isarray, int depth) {
if (depth > MAX_DEPTH) { if (depth > MAX_DEPTH) {
luaL_error(L, "Too depth while encoding bson"); luaL_error(L, "Too depth while encoding bson");
} }
@@ -418,44 +455,49 @@ pack_dict(lua_State *L, struct bson *b, bool isarray, int depth) {
lua_pushnil(L); lua_pushnil(L);
while(lua_next(L,-2) != 0) { while(lua_next(L,-2) != 0) {
int kt = lua_type(L, -2); int kt = lua_type(L, -2);
char numberkey[32]; pack_dict_data(L, b, isarray, depth, kt);
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;
}
}
} }
write_byte(b,0); write_byte(b,0);
write_length(b, b->size - length, length); write_length(b, b->size - length, length);
} }
static void
pack_meta_dict(lua_State *L, struct bson *b, bool isarray, 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
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, isarray, depth, kt);
}
write_byte(b,0);
write_length(b, b->size - length, length);
}
static void
pack_dict(lua_State *L, struct bson *b, bool isarray, int depth) {
if (luaL_getmetafield(L, -1, "__pairs") != LUA_TNIL) {
pack_meta_dict(L, b, isarray, depth);
} else {
pack_simple_dict(L, b, isarray, depth);
}
}
static void static void
pack_ordered_dict(lua_State *L, struct bson *b, int n, int depth) { pack_ordered_dict(lua_State *L, struct bson *b, int n, int depth) {
int length = reserve_length(b); int length = reserve_length(b);

View File

@@ -8,7 +8,43 @@ local socket_error = setmetatable({} , { __tostring = function() return "[Socket
sockethelper.socket_error = socket_error 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) return function (sz)
local ret = readbytes(fd, sz) local ret = readbytes(fd, sz)
if ret then if ret then

View File

@@ -318,30 +318,73 @@ function mongo_cursor:count(with_limit_and_skip)
end end
-- For compatibility.
-- collection:createIndex({username = 1}, {unique = true}) -- collection:createIndex({username = 1}, {unique = true})
function mongo_collection:createIndex(keys, option) local function createIndex_onekey(self, key, option)
local name = option.name local doc = {}
option.name = nil for k,v in pairs(option) do
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
doc[k] = v doc[k] = v
end 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}) return self.database:runCommand("createIndexes", self.name, "indexes", {doc})
end 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() function mongo_collection:drop()
return self.database:runCommand("drop", self.name) 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() function command:disconnect()
self[1]:close() self[1]:close()
setmetatable(self, nil) setmetatable(self, nil)
@@ -149,6 +123,32 @@ local function compose_message(cmd, msg)
return lines return lines
end 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) setmetatable(command, { __index = function(t,k)
local cmd = string.upper(k) local cmd = string.upper(k)
local f = function (self, v, ...) local f = function (self, v, ...)
@@ -233,7 +233,7 @@ local watchmeta = {
local function watch_login(obj, auth) local function watch_login(obj, auth)
return function(so) return function(so)
if auth then if auth then
so:request("AUTH "..auth.."\r\n", read_response) so:request(compose_message("AUTH", auth), read_response)
end end
for k in pairs(obj.__psubscribe) do for k in pairs(obj.__psubscribe) do
so:request(compose_message ("PSUBSCRIBE", k)) so:request(compose_message ("PSUBSCRIBE", k))

View File

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

View File

@@ -1,89 +1,105 @@
local table = table 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
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))
end 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 end
function dbgcmd.EXIT() local function reg_debugcmd(name, fn)
skynet.exit() extern_dbgcmd[name] = fn
end end
function dbgcmd.RUN(source, filename) return {
local inject = require "skynet.inject" init = init,
local output = inject(skynet, source, filename , export.dispatch, skynet.register_protocol) reg_debugcmd = reg_debugcmd,
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,
} }
end

View File

@@ -328,7 +328,8 @@ local function block_connect(self, once)
r = check_connection(self) r = check_connection(self)
if r == nil then 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 else
return r return r
end end

View File

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

View File

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

@@ -16,6 +16,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <signal.h>
struct monitor { struct monitor {
int count; int count;
@@ -32,6 +33,15 @@ struct worker_parm {
int weight; 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; #define CHECK_ABORT if (skynet_context_total()==0) break;
static void static void
@@ -100,6 +110,21 @@ thread_monitor(void *p) {
return NULL; 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 * static void *
thread_timer(void *p) { thread_timer(void *p) {
struct monitor * m = p; struct monitor * m = p;
@@ -109,6 +134,10 @@ thread_timer(void *p) {
CHECK_ABORT CHECK_ABORT
wakeup(m,m->count-1); wakeup(m,m->count-1);
usleep(2500); usleep(2500);
if (SIG) {
signal_hup();
SIG = 0;
}
} }
// wakeup socket thread // wakeup socket thread
skynet_socket_exit(); skynet_socket_exit();
@@ -216,6 +245,13 @@ bootstrap(struct skynet_context * logger, const char * cmdline) {
void void
skynet_start(struct skynet_config * config) { 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 (config->daemon) {
if (daemon_init(config->daemon)) { if (daemon_init(config->daemon)) {
exit(1); exit(1);

View File

@@ -1,17 +1,26 @@
local skynet = require "skynet" 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) -- set sandbox memory limit to 1M, must set here (at start, out of skynet.start)
skynet.memlimit(1 * 1024 * 1024) skynet.memlimit(1 * 1024 * 1024)
skynet.start(function() skynet.start(function()
local a = {} local a = {}
local limit local limit
local ok, err = pcall(function() local ok, err = pcall(function()
for i=1, 1000000 do for i=1, 12355 do
limit = i limit = i
table.insert(a, {}) table.insert(a, {})
end end
end) end)
skynet.error(limit, err) local libs = {}
skynet.exit() 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) end)