From 8049067196b215e8b82742ed5e6c8736791250fb Mon Sep 17 00:00:00 2001 From: Daniel Gruno Date: Fri, 19 Apr 2013 08:46:28 +0000 Subject: [PATCH] Remove lua_ap_banner, as it's no longer being used. Add ivm_get/ivm_set for Inter-VM data transfer. This allows multiple VMs across a process to share data without having to resort to external databases or filesystems. This is a work in progress, and I have yet to work out a proper way of resetting a variable without causing a memory leak (this could be done by allocating a new pool for each object, but I'm trying to see if there's a more efficient way). Comments, ideas etc are most welcome. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1469744 13f79535-47bb-0310-9956-ffa450edef68 --- docs/manual/mod/mod_lua.xml | 9 +++++ modules/lua/lua_request.c | 65 +++++++++++++++++++++++++++++++------ modules/lua/lua_request.h | 6 ++++ 3 files changed, 70 insertions(+), 10 deletions(-) diff --git a/docs/manual/mod/mod_lua.xml b/docs/manual/mod/mod_lua.xml index 203b9d2467..7765931aa4 100644 --- a/docs/manual/mod/mod_lua.xml +++ b/docs/manual/mod/mod_lua.xml @@ -889,6 +889,15 @@ r:dbacquire(dbType[, dbParams]) -- Acquires a connection to a database and retur -- See 'Database connectivity' for details. + +r:ivm_set("key", value) -- Set an Inter-VM variable to hold a specific value. + -- These values persist even though the VM is gone or not being used, + -- and so should only be used if MaxConnectionsPerChild is > 0 + -- Values can be numbers, strings and booleans. + +r:ivm_get("key") -- Fetches a variable set by ivm_set. Returns the contents of the variable + -- if it exists or nil if no such variable exists. + diff --git a/modules/lua/lua_request.c b/modules/lua/lua_request.c index 4b57b9f876..34940ceeb5 100644 --- a/modules/lua/lua_request.c +++ b/modules/lua/lua_request.c @@ -15,6 +15,11 @@ * limitations under the License. */ +#include + + +#include + #include "mod_lua.h" #include "util_script.h" #include "lua_apr.h" @@ -33,6 +38,7 @@ typedef char *(*req_field_string_f) (request_rec * r); typedef int (*req_field_int_f) (request_rec * r); typedef apr_table_t *(*req_field_apr_table_f) (request_rec * r); + void ap_lua_rstack_dump(lua_State *L, request_rec *r, const char *msg) { int i; @@ -823,16 +829,6 @@ static int lua_apr_sha1(lua_State *L) } - -/* - * lua_ap_banner; r:banner() - Returns the current server banner - */ -static int lua_ap_banner(lua_State *L) -{ - lua_pushstring(L, ap_get_server_banner()); - return 1; -} - /* * lua_ap_mpm_query; r:mpm_query(info) - Queries for MPM info */ @@ -1665,6 +1661,49 @@ static int req_debug(lua_State *L) return req_log_at(L, APLOG_DEBUG); } +static int lua_ivm_get(lua_State *L) { + const char *key, *raw_key; + lua_ivm_object *object = NULL; + request_rec *r = ap_lua_check_request_rec(L, 1); + key = luaL_checkstring(L, 2); + raw_key = apr_pstrcat(r->pool, "lua_ivm_", key, NULL); + apr_pool_userdata_get((void **)&object, raw_key, r->server->process->pool); + if (object) { + if (object->type == LUA_TBOOLEAN) lua_pushboolean(L, object->number); + else if (object->type == LUA_TBOOLEAN) lua_pushboolean(L, object->number); + else if (object->type == LUA_TNUMBER) lua_pushnumber(L, object->number); + else if (object->type == LUA_TSTRING) lua_pushlstring(L, object->string, object->size); + return 1; + } + else { + return 0; + } +} + + +static int lua_ivm_set(lua_State *L) { + const char *key, *raw_key; + const char *value = NULL; + lua_ivm_object *object = NULL; + request_rec *r = ap_lua_check_request_rec(L, 1); + key = luaL_checkstring(L, 2); + luaL_checkany(L, 3); + raw_key = apr_pstrcat(r->pool, "lua_ivm_", key, NULL); + + /* This will require MaxConnectionsPerChild to be > 0, since it's + * essentially leaking memory as values are being overridden */ + object = apr_pcalloc(r->server->process->pool, sizeof(lua_ivm_object)); + object->type = lua_type(L, 3); + if (object->type == LUA_TNUMBER) object->number = lua_tonumber(L, 3); + else if (object->type == LUA_TBOOLEAN) object->number = lua_tonumber(L, 3); + else if (object->type == LUA_TSTRING) { + value = lua_tolstring(L, 3, &object->size); + object->string = apr_pstrmemdup(r->server->process->pool, value, object->size); + } + apr_pool_userdata_set(object, raw_key, NULL, r->server->process->pool); + return 0; +} + #define APLUA_REQ_TRACE(lev) static int req_trace##lev(lua_State *L) \ { \ return req_log_at(L, APLOG_TRACE##lev); \ @@ -1770,6 +1809,8 @@ static const char* lua_ap_get_server_name(request_rec* r) return name ? name : "localhost"; } + + static const struct luaL_Reg server_methods[] = { {NULL, NULL} }; @@ -1996,6 +2037,10 @@ AP_LUA_DECLARE(void) ap_lua_load_request_lmodule(lua_State *L, apr_pool_t *p) makefun(&lua_ap_state_query, APL_REQ_FUNTYPE_LUACFUN, p)); apr_hash_set(dispatch, "get_server_name_for_url", APR_HASH_KEY_STRING, makefun(&lua_ap_get_server_name_for_url, APL_REQ_FUNTYPE_LUACFUN, p)); + apr_hash_set(dispatch, "ivm_get", APR_HASH_KEY_STRING, + makefun(&lua_ivm_get, APL_REQ_FUNTYPE_LUACFUN, p)); + apr_hash_set(dispatch, "ivm_set", APR_HASH_KEY_STRING, + makefun(&lua_ivm_set, APL_REQ_FUNTYPE_LUACFUN, p)); lua_pushlightuserdata(L, dispatch); lua_setfield(L, LUA_REGISTRYINDEX, "Apache2.Request.dispatch"); diff --git a/modules/lua/lua_request.h b/modules/lua/lua_request.h index ad272dc98e..460e2c1824 100644 --- a/modules/lua/lua_request.h +++ b/modules/lua/lua_request.h @@ -37,5 +37,11 @@ typedef struct int type; } req_fun_t; +typedef struct { + int type; + size_t size; + void* string; + lua_Number number; +} lua_ivm_object; #endif /* !_LUA_REQUEST_H_ */ -- 2.40.0