From f9b07d1b34e2828ac7f11a3742b67bba579ca3e3 Mon Sep 17 00:00:00 2001 From: Daniel Gruno Date: Sun, 29 Jul 2012 19:07:38 +0000 Subject: [PATCH] Add LuaCodeCache directive for controlling in-memory caching. This might need some tweaking on the hash key generation for the mtime lookups, ideas are welcome. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1366890 13f79535-47bb-0310-9956-ffa450edef68 --- modules/lua/lua_vmprep.c | 41 ++++++++++++++++++++++++++++++++++++++-- modules/lua/lua_vmprep.h | 8 ++++++++ modules/lua/mod_lua.c | 29 ++++++++++++++++++++++++++++ modules/lua/mod_lua.h | 5 +++++ 4 files changed, 81 insertions(+), 2 deletions(-) diff --git a/modules/lua/lua_vmprep.c b/modules/lua/lua_vmprep.c index e821fee3d1..21fbf20734 100644 --- a/modules/lua/lua_vmprep.c +++ b/modules/lua/lua_vmprep.c @@ -341,7 +341,7 @@ AP_LUA_DECLARE(lua_State*)ap_lua_get_lua_state(apr_pool_t *lifecycle_pool, ap_lua_vm_spec *spec) { lua_State *L = NULL; - + int tryCache = 0; if (apr_pool_userdata_get((void **)&L, spec->file, lifecycle_pool) == APR_SUCCESS) { @@ -360,6 +360,43 @@ AP_LUA_DECLARE(lua_State*)ap_lua_get_lua_state(apr_pool_t *lifecycle_pool, } } /*}*/ - + if (spec->codecache == AP_LUA_CACHE_FOREVER || (spec->bytecode && spec->bytecode_len > 0)) { + tryCache = 1; + } + else if (spec->codecache == AP_LUA_CACHE_STAT) { + apr_time_t modified; + char* mkey = apr_psprintf(lifecycle_pool, "ap_lua_modified:%s", spec->file); + if (apr_pool_userdata_get((void **)&modified, mkey, + lifecycle_pool) == APR_SUCCESS) { + apr_finfo_t lua_finfo; + apr_stat(&lua_finfo, spec->file, APR_FINFO_MTIME, lifecycle_pool); + + /* On first visit, modified will be zero, but that's fine - The file is + loaded in the vm_construct function. + */ + if (modified == lua_finfo.mtime || modified == 0) tryCache = 1; + modified = lua_finfo.mtime; + } + else { + tryCache = 1; + } + apr_pool_userdata_set((void*) modified, mkey, NULL, lifecycle_pool); + } + if (tryCache == 0) { + int rc; + ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, lifecycle_pool, APLOGNO(01481) + "(re)loading lua file %s", spec->file); + rc = luaL_loadfile(L, spec->file); + if (rc != 0) { + ap_log_perror(APLOG_MARK, APLOG_ERR, 0, lifecycle_pool, APLOGNO(01482) + "Error loading %s: %s", spec->file, + rc == LUA_ERRMEM ? "memory allocation error" + : lua_tostring(L, 0)); + return 0; + } + lua_pcall(L, 0, LUA_MULTRET, 0); + } + + return L; } diff --git a/modules/lua/lua_vmprep.h b/modules/lua/lua_vmprep.h index 1d3758ca8e..c3b5376664 100644 --- a/modules/lua/lua_vmprep.h +++ b/modules/lua/lua_vmprep.h @@ -40,6 +40,11 @@ #define AP_LUA_SCOPE_CONN 3 #define AP_LUA_SCOPE_THREAD 4 +#define AP_LUA_CACHE_UNSET 0 +#define AP_LUA_CACHE_NEVER 1 +#define AP_LUA_CACHE_STAT 2 +#define AP_LUA_CACHE_FOREVER 3 + typedef void (*ap_lua_state_open_callback) (lua_State *L, apr_pool_t *p, void *ctx); @@ -71,6 +76,8 @@ typedef struct */ const char *bytecode; apr_size_t bytecode_len; + + int codecache; } ap_lua_vm_spec; typedef struct @@ -81,6 +88,7 @@ typedef struct ap_regex_t *uri_pattern; const char *bytecode; apr_size_t bytecode_len; + int codecache; } ap_lua_mapped_handler_spec; /* remove and make static once out of mod_wombat.c */ diff --git a/modules/lua/mod_lua.c b/modules/lua/mod_lua.c index cb28137d66..3881f532d8 100644 --- a/modules/lua/mod_lua.c +++ b/modules/lua/mod_lua.c @@ -130,6 +130,7 @@ static ap_lua_vm_spec *create_vm_spec(apr_pool_t **lifecycle_pool, spec->cb_arg = NULL; spec->bytecode = bytecode; spec->bytecode_len = bytecode_len; + spec->codecache = (cfg->codecache == AP_LUA_CACHE_UNSET) ? AP_LUA_CACHE_STAT : cfg->codecache; if (filename) { char *file; @@ -910,6 +911,29 @@ static const char *register_lua_inherit(cmd_parms *cmd, } return NULL; } +static const char *register_lua_codecache(cmd_parms *cmd, + void *_cfg, + const char *arg) +{ + ap_lua_dir_cfg *cfg = (ap_lua_dir_cfg *) _cfg; + + if (strcasecmp("never", arg) == 0) { + cfg->codecache = AP_LUA_CACHE_NEVER; + } + else if (strcasecmp("stat", arg) == 0) { + cfg->codecache = AP_LUA_CACHE_STAT; + } + else if (strcasecmp("forever", arg) == 0) { + cfg->codecache = AP_LUA_CACHE_FOREVER; + } + else { + return apr_psprintf(cmd->pool, + "LuaCodeCache type of '%s' not recognized, valid " + "options are 'never', 'stat', and 'forever'", + arg); + } + return NULL; +} static const char *register_lua_scope(cmd_parms *cmd, void *_cfg, const char *scope, @@ -1184,6 +1208,10 @@ command_rec lua_commands[] = { AP_INIT_TAKE1("LuaInherit", register_lua_inherit, NULL, OR_ALL, "Controls how Lua scripts in parent contexts are merged with the current " " context: none|parent-last|parent-first (default: parent-first) "), + + AP_INIT_TAKE1("LuaCodeCache", register_lua_codecache, NULL, OR_ALL, + "Controls the behavior of the in-memory code cache " + " context: stat|forever|never (default: stat) "), AP_INIT_TAKE2("LuaQuickHandler", register_quick_hook, NULL, OR_ALL, "Provide a hook for the quick handler of request processing"), @@ -1270,6 +1298,7 @@ static void *merge_dir_config(apr_pool_t *p, void *basev, void *overridesv) a->vm_scope = (overrides->vm_scope == AP_LUA_SCOPE_UNSET) ? base->vm_scope: overrides->vm_scope; a->inherit = (overrides->inherit== AP_LUA_INHERIT_UNSET) ? base->inherit : overrides->inherit; + a->codecache = (overrides->codecache== AP_LUA_CACHE_UNSET) ? base->codecache : overrides->codecache; if (a->inherit == AP_LUA_INHERIT_UNSET || a->inherit == AP_LUA_INHERIT_PARENT_FIRST) { a->package_paths = apr_array_append(p, base->package_paths, overrides->package_paths); diff --git a/modules/lua/mod_lua.h b/modules/lua/mod_lua.h index 40add31290..b737c0b672 100644 --- a/modules/lua/mod_lua.h +++ b/modules/lua/mod_lua.h @@ -120,6 +120,11 @@ typedef struct /* Whether Lua scripts in a sub-dir are run before parents */ ap_lua_inherit_t inherit; + + /** + * AP_LUA_CACHE_NEVER | AP_LUA_CACHE_STAT | AP_LUA_CACHE_FOREVER + */ + unsigned int codecache; } ap_lua_dir_cfg; -- 2.49.0