mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-23 11:33:09 +00:00
Compare commits
31 Commits
v1.0.0-rc3
...
v1.0.0-rc4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a54fe8293 | ||
|
|
2020ce3c9c | ||
|
|
2557559d5c | ||
|
|
bb0143e476 | ||
|
|
fd2c814fe0 | ||
|
|
bd3d9b70ec | ||
|
|
ee1a218870 | ||
|
|
84ee3da79a | ||
|
|
fdee7de36d | ||
|
|
bf5b74b6ca | ||
|
|
d9b0347741 | ||
|
|
9546537256 | ||
|
|
f84fe84b96 | ||
|
|
ea9bc53261 | ||
|
|
0edb839c95 | ||
|
|
b8bb327f98 | ||
|
|
27d69334ee | ||
|
|
838e63ab62 | ||
|
|
ba264700dc | ||
|
|
e00ad7ab79 | ||
|
|
de176b735f | ||
|
|
cc3e985834 | ||
|
|
3b5f45eea2 | ||
|
|
c3056b04c1 | ||
|
|
58755a6772 | ||
|
|
1cf976c4e4 | ||
|
|
5be836527c | ||
|
|
e9f397945d | ||
|
|
78df0b8161 | ||
|
|
db17245005 | ||
|
|
4edb586077 |
Submodule 3rd/jemalloc updated: e02b83cc5e...3de0353352
@@ -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? */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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] */
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
-----------
|
||||
* Update jemalloc 4.1.1
|
||||
|
||||
@@ -26,13 +26,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 ( http://www.lua.org/ftp/lua-5.3.3.tar.gz ) .
|
||||
|
||||
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)
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -409,7 +409,44 @@ bson_numstr( char *str, unsigned int i ) {
|
||||
}
|
||||
|
||||
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) {
|
||||
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);
|
||||
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, isarray, depth, kt);
|
||||
}
|
||||
write_byte(b,0);
|
||||
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
|
||||
pack_ordered_dict(lua_State *L, struct bson *b, int n, int depth) {
|
||||
int length = reserve_length(b);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -318,30 +318,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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user