mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-23 19:43:09 +00:00
cache lua code load
This commit is contained in:
2
Makefile
2
Makefile
@@ -71,7 +71,7 @@ service/harbor.so : service-src/service_harbor.c
|
||||
service/logger.so : skynet-src/skynet_logger.c
|
||||
gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src
|
||||
|
||||
service/snlua.so : service-src/service_lua.c
|
||||
service/snlua.so : service-src/service_lua.c service-src/luacode_cache.c
|
||||
gcc $(CFLAGS) $(SHARED) -Iluacompat $^ -o $@ -Iskynet-src
|
||||
|
||||
service/gate.so : service-src/service_gate.c
|
||||
|
||||
298
service-src/luacode_cache.c
Normal file
298
service-src/luacode_cache.c
Normal file
@@ -0,0 +1,298 @@
|
||||
#include "luacode_cache.h"
|
||||
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define LOCK(q) while (__sync_lock_test_and_set(&(q)->lock,1)) {}
|
||||
#define UNLOCK(q) __sync_lock_release(&(q)->lock);
|
||||
|
||||
struct codecache {
|
||||
int lock;
|
||||
lua_State *L;
|
||||
};
|
||||
|
||||
static struct codecache CC = { 0 , NULL };
|
||||
|
||||
static void
|
||||
_init() {
|
||||
CC.lock = 0;
|
||||
CC.L = luaL_newstate();
|
||||
}
|
||||
|
||||
static const char *
|
||||
_load(const char *key, size_t *sz) {
|
||||
if (CC.L == NULL)
|
||||
return NULL;
|
||||
LOCK(&CC)
|
||||
lua_State *L = CC.L;
|
||||
lua_getglobal(L, key);
|
||||
const char * result = NULL;
|
||||
if (lua_isstring(L,-1)) {
|
||||
result = lua_tolstring(L, -1, sz);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
UNLOCK(&CC)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char *
|
||||
_save(const char *key, const char * code, size_t *sz) {
|
||||
lua_State *L;
|
||||
const char * result = NULL;
|
||||
|
||||
LOCK(&CC)
|
||||
if (CC.L == NULL) {
|
||||
_init();
|
||||
L = CC.L;
|
||||
} else {
|
||||
L = CC.L;
|
||||
lua_getglobal(L, key);
|
||||
if (lua_isstring(L,-1)) {
|
||||
size_t code_sz = *sz;
|
||||
result = lua_tolstring(L, -1, sz);
|
||||
assert(code_sz == *sz);
|
||||
lua_pop(L, 1);
|
||||
goto _ret;
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pushlstring(L, code, *sz);
|
||||
result = lua_tostring(L, -1);
|
||||
lua_setglobal(L, key);
|
||||
_ret:
|
||||
UNLOCK(&CC)
|
||||
return result;
|
||||
}
|
||||
|
||||
const char *
|
||||
luacode_load(const char * key, const char * code, size_t *sz) {
|
||||
if (code == NULL) {
|
||||
return _load(key, sz);
|
||||
}
|
||||
const char * result = _load(key,sz);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
return _save(key, code, sz);
|
||||
}
|
||||
|
||||
/*
|
||||
static int
|
||||
cache_load(lua_State *L) {
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
// copy from lbaselib.c
|
||||
static int
|
||||
load_aux (lua_State *L, int status, int envidx) {
|
||||
if (status == LUA_OK) {
|
||||
if (envidx != 0) { /* 'env' parameter? */
|
||||
lua_pushvalue(L, envidx); /* environment for loaded function */
|
||||
if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */
|
||||
lua_pop(L, 1); /* remove 'env' if not used by previous call */
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else { /* error (message is on top of the stack) */
|
||||
lua_pushnil(L);
|
||||
lua_insert(L, -2); /* put before error message */
|
||||
return 2; /* return nil plus error message */
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
writer (lua_State *L, const void* b, size_t size, void* B) {
|
||||
(void)L;
|
||||
luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
str_dump (lua_State *L) {
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L,&b);
|
||||
if (lua_dump(L, writer, &b) != 0)
|
||||
luaL_error(L, "unable to dump given function");
|
||||
luaL_pushresult(&b);
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
cache_loadfile(lua_State *L) {
|
||||
const char *fname = luaL_optstring(L, 1, NULL);
|
||||
const char *mode = luaL_optstring(L, 2, NULL);
|
||||
int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */
|
||||
int status;
|
||||
if (fname == NULL) {
|
||||
status = luaL_loadfilex(L, fname, mode);
|
||||
} else {
|
||||
// read cache
|
||||
size_t sz = 0;
|
||||
const char * bytecode = luacode_load(fname, NULL, &sz);
|
||||
if (bytecode) {
|
||||
// load from cache
|
||||
status = luaL_loadbuffer(L, bytecode, sz, fname);
|
||||
} else {
|
||||
status = luaL_loadfilex(L, fname, mode);
|
||||
if (status == LUA_OK) {
|
||||
str_dump(L);
|
||||
const char * bytecode = lua_tolstring(L,-1,&sz);
|
||||
// update cache
|
||||
luacode_load(fname, bytecode, &sz);
|
||||
lua_pop(L,1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return load_aux(L, status, env);
|
||||
}
|
||||
|
||||
int
|
||||
luacode_loadfile(lua_State *L, const char *filename) {
|
||||
size_t sz = 0;
|
||||
const char * bytecode = luacode_load(filename, NULL, &sz);
|
||||
int status;
|
||||
if (bytecode) {
|
||||
status = luaL_loadbuffer(L, bytecode, sz, filename);
|
||||
} else {
|
||||
status = luaL_loadfile(L, filename);
|
||||
if (status == LUA_OK) {
|
||||
str_dump(L);
|
||||
const char * bytecode = lua_tolstring(L,-1,&sz);
|
||||
// update cache
|
||||
luacode_load(filename, bytecode, &sz);
|
||||
lua_pop(L,1);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// require loader, copy and modify from loadlib.c
|
||||
|
||||
#if !defined (LUA_PATH_SEP)
|
||||
#define LUA_PATH_SEP ";"
|
||||
#endif
|
||||
#if !defined (LUA_PATH_MARK)
|
||||
#define LUA_PATH_MARK "?"
|
||||
#endif
|
||||
#if !defined(LUA_LSUBSEP)
|
||||
#define LUA_LSUBSEP LUA_DIRSEP
|
||||
#endif
|
||||
|
||||
static int
|
||||
readable (const char *filename) {
|
||||
size_t sz = 0;
|
||||
const char * bytecode = luacode_load(filename, NULL, &sz);
|
||||
if (bytecode) {
|
||||
return 1;
|
||||
}
|
||||
FILE *f = fopen(filename, "r"); /* try to open file */
|
||||
if (f == NULL) return 0; /* open failed */
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const char *
|
||||
pushnexttemplate (lua_State *L, const char *path) {
|
||||
const char *l;
|
||||
while (*path == *LUA_PATH_SEP) path++; /* skip separators */
|
||||
if (*path == '\0') return NULL; /* no more templates */
|
||||
l = strchr(path, *LUA_PATH_SEP); /* find next separator */
|
||||
if (l == NULL) l = path + strlen(path);
|
||||
lua_pushlstring(L, path, l - path); /* template */
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
static const char *
|
||||
searchpath (lua_State *L, const char *name,
|
||||
const char *path,
|
||||
const char *sep,
|
||||
const char *dirsep) {
|
||||
luaL_Buffer msg; /* to build error message */
|
||||
luaL_buffinit(L, &msg);
|
||||
if (*sep != '\0') /* non-empty separator? */
|
||||
name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */
|
||||
while ((path = pushnexttemplate(L, path)) != NULL) {
|
||||
const char *filename = luaL_gsub(L, lua_tostring(L, -1),
|
||||
LUA_PATH_MARK, name);
|
||||
lua_remove(L, -2); /* remove path template */
|
||||
if (readable(filename)) /* does file exist and is readable? */
|
||||
return filename; /* return that file name */
|
||||
lua_pushfstring(L, "\n\tno file " LUA_QS, filename);
|
||||
lua_remove(L, -2); /* remove file name */
|
||||
luaL_addvalue(&msg); /* concatenate error msg. entry */
|
||||
}
|
||||
luaL_pushresult(&msg); /* create error message */
|
||||
return NULL; /* not found */
|
||||
}
|
||||
|
||||
static const char *
|
||||
findfile (lua_State *L, const char *name,
|
||||
const char *pname,
|
||||
const char *dirsep) {
|
||||
const char *path;
|
||||
lua_getfield(L, lua_upvalueindex(1), pname);
|
||||
path = lua_tostring(L, -1);
|
||||
if (path == NULL)
|
||||
luaL_error(L, LUA_QL("package.%s") " must be a string", pname);
|
||||
return searchpath(L, name, path, ".", dirsep);
|
||||
}
|
||||
|
||||
static int
|
||||
checkload (lua_State *L, int stat, const char *filename) {
|
||||
if (stat) { /* module loaded successfully? */
|
||||
lua_pushstring(L, filename); /* will be 2nd argument to module */
|
||||
return 2; /* return open function and file name */
|
||||
}
|
||||
else
|
||||
return luaL_error(L, "error loading module " LUA_QS
|
||||
" from file " LUA_QS ":\n\t%s",
|
||||
lua_tostring(L, 1), filename, lua_tostring(L, -1));
|
||||
}
|
||||
|
||||
static int
|
||||
searcher_cache (lua_State *L) {
|
||||
const char *filename;
|
||||
const char *name = luaL_checkstring(L, 1);
|
||||
filename = findfile(L, name, "path", LUA_LSUBSEP);
|
||||
if (filename == NULL) return 1; /* module not found in this path */
|
||||
return checkload(L, (luacode_loadfile(L, filename) == LUA_OK), filename);
|
||||
}
|
||||
|
||||
static void
|
||||
replace_searcher_lua(lua_State *L) {
|
||||
lua_getglobal(L, "package");
|
||||
if (!lua_istable(L,-1)) {
|
||||
luaL_error(L, "Can't find package");
|
||||
}
|
||||
lua_getfield(L, -1, "searchers");
|
||||
if (!lua_istable(L,-1)) {
|
||||
luaL_error(L, "Can't find package.searchers");
|
||||
}
|
||||
lua_pushvalue(L,-2);
|
||||
lua_pushcclosure(L, searcher_cache, 1);
|
||||
// package.searcher[2] is searcher_lua, replace it.
|
||||
lua_rawseti(L, -2, 2);
|
||||
lua_pop(L,2);
|
||||
}
|
||||
|
||||
//-------------------------
|
||||
|
||||
int
|
||||
luacode_lib(lua_State *L) {
|
||||
replace_searcher_lua(L);
|
||||
luaL_Reg l[] = {
|
||||
// { "load", cache_load },
|
||||
{ "loadfile", cache_loadfile },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
luaL_newlib(L,l);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
12
service-src/luacode_cache.h
Normal file
12
service-src/luacode_cache.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef lua_code_cache_h
|
||||
#define lua_code_cache_h
|
||||
|
||||
#include <lua.h>
|
||||
#include <stddef.h>
|
||||
|
||||
const char * luacode_load(const char * key, const char * code, size_t *sz);
|
||||
|
||||
int luacode_loadfile(lua_State *L, const char *filename);
|
||||
int luacode_lib(lua_State *);
|
||||
|
||||
#endif
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <assert.h>
|
||||
#include "luacompat52.h"
|
||||
#include "service_lua.h"
|
||||
#include "luacode_cache.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
@@ -66,38 +67,35 @@ _try_load(lua_State *L, const char * path, int pathlen, const char * name) {
|
||||
exit(1);
|
||||
}
|
||||
tmp[namelen+pathlen-1] = '\0';
|
||||
FILE *f = fopen(tmp,"rb");
|
||||
if (f == NULL) {
|
||||
return -1;
|
||||
} else {
|
||||
fclose(f);
|
||||
int r = luaL_loadfile(L,tmp);
|
||||
if (r == LUA_OK) {
|
||||
int i;
|
||||
for (i=namelen+pathlen-2;i>=0;i--) {
|
||||
if (tmp[i] == '/') {
|
||||
lua_pushlstring(L,tmp,i+1);
|
||||
lua_setglobal(L,"SERVICE_PATH");
|
||||
break;
|
||||
}
|
||||
// luacode_loadfile is the same with luaL_loadfile except cache.
|
||||
int r = luacode_loadfile(L,tmp);
|
||||
if (r == LUA_OK) {
|
||||
int i;
|
||||
for (i=namelen+pathlen-2;i>=0;i--) {
|
||||
if (tmp[i] == '/') {
|
||||
lua_pushlstring(L,tmp,i+1);
|
||||
lua_setglobal(L,"SERVICE_PATH");
|
||||
break;
|
||||
}
|
||||
if (i<0) {
|
||||
return 0;
|
||||
}
|
||||
lua_getglobal(L,"package");
|
||||
lua_getfield(L,-1,"path");
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L, &b);
|
||||
luaL_addlstring(&b, tmp, i+1);
|
||||
luaL_addstring(&b, "?.lua;");
|
||||
luaL_addvalue(&b);
|
||||
luaL_pushresult(&b);
|
||||
lua_setfield(L,-2,"path");
|
||||
lua_pop(L,1);
|
||||
}
|
||||
if (i<0) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
lua_getglobal(L,"package");
|
||||
lua_getfield(L,-1,"path");
|
||||
luaL_Buffer b;
|
||||
luaL_buffinit(L, &b);
|
||||
luaL_addlstring(&b, tmp, i+1);
|
||||
luaL_addstring(&b, "?.lua;");
|
||||
luaL_addvalue(&b);
|
||||
luaL_pushresult(&b);
|
||||
lua_setfield(L,-2,"path");
|
||||
lua_pop(L,1);
|
||||
return 0;
|
||||
} else if (r == LUA_ERRFILE) {
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -168,6 +166,8 @@ _init(struct snlua *l, struct skynet_context *ctx, const char * args) {
|
||||
luaL_openlibs(L);
|
||||
lua_pushlightuserdata(L, l);
|
||||
lua_setfield(L, LUA_REGISTRYINDEX, "skynet_lua");
|
||||
luaL_requiref(L, "skynet.codecache", luacode_lib , 0);
|
||||
lua_pop(L,1);
|
||||
lua_gc(L, LUA_GCRESTART, 0);
|
||||
|
||||
char tmp[strlen(args)+1];
|
||||
|
||||
@@ -31,6 +31,7 @@ _logger(struct skynet_context * context, void *ud, int type, int session, uint32
|
||||
fprintf(inst->handle, "[:%x] ",source);
|
||||
fwrite(msg, sz , 1, inst->handle);
|
||||
fprintf(inst->handle, "\n");
|
||||
fflush(inst->handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user