Permalink
Browse files

cache lua code load

  • Loading branch information...
cloudwu committed Dec 17, 2013
1 parent 2bf6508 commit 8e031c1b214b4adcd1c419c2b52cdb94e8d7ef8d
Showing with 340 additions and 29 deletions.
  1. +1 −1 Makefile
  2. +298 −0 service-src/luacode_cache.c
  3. +12 −0 service-src/luacode_cache.h
  4. +28 −28 service-src/service_lua.c
  5. +1 −0 skynet-src/skynet_logger.c
View
@@ -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
View
@@ -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;
}
@@ -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
Oops, something went wrong.

0 comments on commit 8e031c1

Please sign in to comment.