Commit ea30f9f9 authored by Brian McCallister's avatar Brian McCallister
Browse files

apply patch from zhiguo zhao <zhaozg@gmail.com> to significantly improve server scope handling

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1081611 13f79535-47bb-0310-9956-ffa450edef68
parent 79fb19dd
Loading
Loading
Loading
Loading
+83 −19
Changes for modules/lua/lua_vmprep.c: 83 added lines, 19 removed lines.
Original line number Diff line number Diff line
@@ -288,39 +288,30 @@ static int loadjitmodule(lua_State *L, apr_pool_t *lifecycle_pool) {

#endif

AP_LUA_DECLARE(lua_State*)ap_lua_get_lua_state(apr_pool_t *lifecycle_pool,
                                               ap_lua_vm_spec *spec,
                                               apr_array_header_t *package_paths,
                                               apr_array_header_t *package_cpaths,
                                               ap_lua_state_open_callback cb,
                                               void *btn)
static apr_status_t vm_construct(void **vm, void *params, apr_pool_t *lifecycle_pool)
{

    lua_State* L;
    
    if (!apr_pool_userdata_get((void **) &L, spec->file, lifecycle_pool)) {
        ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, lifecycle_pool,
                      "creating lua_State with file %s", spec->file);
        /* not available, so create */
    ap_lua_vm_spec *spec = params;

    L = luaL_newstate();
#ifdef AP_ENABLE_LUAJIT
    luaopen_jit(L);
#endif
    luaL_openlibs(L);
        if (package_paths) {
    if (spec->package_paths) {
        munge_path(L, "path", "?.lua", "./?.lua", lifecycle_pool,
                       package_paths, spec->file);
            spec->package_paths, spec->file);
    }
        if (package_cpaths) {
    if (spec->package_cpaths) {
        munge_path(L, "cpath", "?.so", "./?.so", lifecycle_pool,
                       package_cpaths, spec->file);
            spec->package_cpaths, spec->file);
    }

        if (cb) {
            cb(L, lifecycle_pool, btn);
    if (spec->cb) {
        spec->cb(L, lifecycle_pool, spec->cb_arg);
    }

        apr_pool_userdata_set(L, spec->file, &cleanup_lua, lifecycle_pool);

    if (spec->bytecode && spec->bytecode_len > 0) {
        luaL_loadbuffer(L, spec->bytecode, spec->bytecode_len, spec->file);
@@ -350,7 +341,7 @@ AP_LUA_DECLARE(lua_State*)ap_lua_get_lua_state(apr_pool_t *lifecycle_pool,
            ap_log_perror(APLOG_MARK, APLOG_ERR, 0, lifecycle_pool,
                "Loading lua file %s: %s",
                spec->file, err);
                return NULL;
            return APR_EBADF;
        }
        lua_pcall(L, 0, LUA_MULTRET, 0);
    }
@@ -360,6 +351,79 @@ AP_LUA_DECLARE(lua_State*)ap_lua_get_lua_state(apr_pool_t *lifecycle_pool,
#endif
    lua_pushlightuserdata(L, lifecycle_pool);
    lua_setfield(L, LUA_REGISTRYINDEX, "Apache2.Wombat.pool");
    *vm = L;

    return APR_SUCCESS;
}

static apr_status_t vm_destruct(void *vm, void *params, apr_pool_t *pool)
{
    lua_State *L = (lua_State *)vm; 

    (void*)params;
    (void*)pool;

    cleanup_lua(L);

    return APR_SUCCESS;
}

static apr_status_t vm_release(lua_State* vm)
{
    apr_reslist_t* reslist;
    lua_pushlightuserdata(vm,vm);
    lua_rawget(vm,LUA_REGISTRYINDEX);
    reslist = (apr_reslist_t*)lua_topointer(vm,-1);

    return apr_reslist_release(reslist, vm);
}

static apr_status_t vm_reslist_destroy(void *data)
{
    return apr_reslist_destroy(data);
}

AP_LUA_DECLARE(lua_State*)ap_lua_get_lua_state(apr_pool_t *lifecycle_pool,
                                               ap_lua_vm_spec *spec)
{
    lua_State *L = NULL;

    if (spec->scope == APL_SCOPE_SERVER) {
        apr_reslist_t *reslist;

        if (apr_pool_userdata_get(&reslist,"mod_lua",spec->pool)==APR_SUCCESS) {
            if(reslist==NULL) {
                if(apr_reslist_create(&reslist, 
                    spec->vm_server_pool_min, 
                    spec->vm_server_pool_max,
                    spec->vm_server_pool_max,
                    0,
                    vm_construct,
                    vm_destruct,
                    spec,
                    spec->pool)!=APR_SUCCESS)
                    return NULL;

                apr_pool_userdata_set(reslist, "mod_lua", vm_reslist_destroy, spec->pool);
            }
            apr_reslist_acquire(reslist, &L);
            lua_pushlightuserdata(L, L);
            lua_pushlightuserdata(L, reslist);
            lua_rawset(L,LUA_REGISTRYINDEX);
            apr_pool_userdata_set(L, spec->file, vm_release, lifecycle_pool);
        }
    } else {
        if (apr_pool_userdata_get((void **) &L, spec->file, lifecycle_pool)==APR_SUCCESS) {

            if(L==NULL) {
                ap_log_perror(APLOG_MARK, APLOG_DEBUG, 0, lifecycle_pool,
                    "creating lua_State with file %s", spec->file);
                /* not available, so create */

                if(!vm_construct(&L, spec, lifecycle_pool))
                    apr_pool_userdata_set(L, spec->file, &cleanup_lua, lifecycle_pool);
            }
        }
    }

    return L;
+22 −21
Changes for modules/lua/lua_vmprep.h: 22 added lines, 21 removed lines.
Original line number Diff line number Diff line
@@ -43,6 +43,23 @@
#define APL_SCOPE_CONN          3
#define APL_SCOPE_SERVER        4


/**
 * the ap_lua_?getvm family of functions is used to create and/or obtain
 * a handle to a lua state. If there is not an extant vm matching the
 * spec then a new one is created.
 */
/* lua_State* ap_lua_rgetvm(request_rec *r, ap_lua_vm_spec *spec); */

/* returns NULL if the spec requires a request scope */
/* lua_State* ap_lua_cgetvm(conn_rec *r, ap_lua_vm_spec *spec);*/

/* returns NULL if the spec requires a request scope or conn scope */
/* lua_State* ap_lua_sgetvm(server_rec *r, ap_lua_vm_spec *spec); */

typedef void (*ap_lua_state_open_callback) (lua_State *L, apr_pool_t *p,
                                             void *ctx);

/**
 * Specification for a lua virtual machine
 */
@@ -61,7 +78,11 @@ typedef struct

    /* APL_SCOPE_ONCE | APL_SCOPE_REQUEST | APL_SCOPE_CONN | APL_SCOPE_SERVER */
    int scope;
	unsigned int vm_server_pool_min;
	unsigned int vm_server_pool_max;

	ap_lua_state_open_callback cb;
	void* cb_arg;
    /* pool to use for lifecycle if APL_SCOPE_ONCE is set, otherwise unused */
    apr_pool_t *pool;

@@ -102,22 +123,6 @@ AP_LUA_DECLARE(void) ap_lua_registerlib(lua_State *L, char *name, lua_CFunction
 */
AP_LUA_DECLARE(void) ap_lua_load_apache2_lmodule(lua_State *L);

/**
 * the ap_lua_?getvm family of functions is used to create and/or obtain
 * a handle to a lua state. If there is not an extant vm matching the
 * spec then a new one is created.
 */
/* lua_State* ap_lua_rgetvm(request_rec *r, ap_lua_vm_spec *spec); */

/* returns NULL if the spec requires a request scope */
/* lua_State* ap_lua_cgetvm(conn_rec *r, ap_lua_vm_spec *spec);*/

/* returns NULL if the spec requires a request scope or conn scope */
/* lua_State* ap_lua_sgetvm(server_rec *r, ap_lua_vm_spec *spec); */

typedef void (*ap_lua_state_open_callback) (lua_State *L, apr_pool_t *p,
                                             void *ctx);

/*
 * alternate means of getting lua_State (preferred eventually)
 * Obtain a lua_State which has loaded file and is associated with lifecycle_pool
@@ -131,11 +136,7 @@ typedef void (*ap_lua_state_open_callback) (lua_State *L, apr_pool_t *p,
 * @ctx a baton passed to cb
 */
AP_LUA_DECLARE(lua_State*) ap_lua_get_lua_state(apr_pool_t *lifecycle_pool,
                                                ap_lua_vm_spec *spec,
                                                apr_array_header_t *package_paths,
                                                apr_array_header_t *package_cpaths,
                                                ap_lua_state_open_callback cb, 
                                                void *btn);
                                                ap_lua_vm_spec *spec);



+16 −10
Changes for modules/lua/mod_lua.c: 16 added lines, 10 removed lines.
Original line number Diff line number Diff line
@@ -121,9 +121,15 @@ static int lua_handler(request_rec *r)
            d = apr_palloc(r->pool, sizeof(mapped_request_details));
            spec = apr_pcalloc(r->pool, sizeof(ap_lua_vm_spec));
            spec->scope = dcfg->vm_scope;
            spec->pool = r->pool;
			spec->pool = spec->scope==APL_SCOPE_SERVER ? cfg->pool : r->pool;
            spec->file = r->filename;
            spec->code_cache_style = dcfg->code_cache_style;
			spec->package_paths = cfg->package_paths;
			spec->package_cpaths = cfg->package_cpaths;
			spec->vm_server_pool_min = cfg->vm_server_pool_min;
			spec->vm_server_pool_max = cfg->vm_server_pool_max;
			spec->cb = &lua_open_callback;
			spec->cb_arg = NULL;
            d->spec = spec;
            d->function_name = "handle";
        }
@@ -135,10 +141,7 @@ static int lua_handler(request_rec *r)
                      d->spec->file,
                      d->function_name);
        L = ap_lua_get_lua_state(r->pool,
                              d->spec,
                              cfg->package_paths,
                              cfg->package_cpaths,
                              &lua_open_callback, NULL);
                              d->spec);

        if (!L) {
            /* TODO annotate spec with failure reason */
@@ -246,17 +249,20 @@ static int lua_request_rec_hook_harness(request_rec *r, const char *name)
            spec->file = hook_spec->file_name;
            spec->code_cache_style = hook_spec->code_cache_style;
            spec->scope = hook_spec->scope;
			spec->vm_server_pool_min = cfg->vm_server_pool_min;
			spec->vm_server_pool_max = cfg->vm_server_pool_max;
            spec->bytecode = hook_spec->bytecode;
            spec->bytecode_len = hook_spec->bytecode_len;
            spec->pool = r->pool;
            spec->pool = spec->scope==APL_SCOPE_SERVER ? cfg->pool : r->pool;
			spec->package_paths = cfg->package_paths;
			spec->package_cpaths = cfg->package_cpaths;
			spec->cb = &lua_open_callback;
			spec->cb_arg = NULL;

            apr_filepath_merge(&spec->file, server_cfg->root_path,
                               spec->file, APR_FILEPATH_NOTRELATIVE, r->pool);
            L = ap_lua_get_lua_state(r->pool,
                                  spec,
                                  cfg->package_paths,
                                  cfg->package_cpaths,
                                  &lua_open_callback, NULL);
                                  spec);