Index: mod_lua.c
===================================================================
--- mod_lua.c	(revision 741109)
+++ mod_lua.c	(working copy)
@@ -19,7 +19,7 @@
 #include <string.h>
 #include <stdlib.h>
 #include <ctype.h>
-
+#include "ap_mpm.h"
 #include "lua_apr.h"
 #include "lua_config.h"
 
@@ -33,6 +33,10 @@
 
      module AP_MODULE_DECLARE_DATA lua_module;
 
+static int threads_per_child = 0;
+static apr_array_header_t *server_scoped_handlers = NULL;
+static apr_pool_t **server_scoped_pools = NULL;
+
 /**
  * error reporting if lua has an error. 
  * Extracts the error from lua stack and prints
@@ -224,6 +228,7 @@
     if (hook_specs) {
         int i;
         for (i = 0; i < hook_specs->nelts; i++) {
+	    apr_pool_t *pool = r->pool;
             apl_mapped_handler_spec *hook_spec =
                 ((apl_mapped_handler_spec **) hook_specs->elts)[i];
 
@@ -241,7 +246,17 @@
 
             apr_filepath_merge(&spec->file, server_cfg->root_path,
                                spec->file, APR_FILEPATH_NOTRELATIVE, r->pool);
-            L = apl_get_lua_state(r->pool,
+
+	    if(APL_SCOPE_SERVER == spec->scope) {
+		/*see worker.c for how connection->id is calculated*/
+		int t = r->connection->id % threads_per_child;
+		pool = server_scoped_pools[t];
+	    }
+	    
+	    /* when using server scoped, package paths are ignored.
+	     * see not in post_config
+	     */
+            L = apl_get_lua_state(pool,
                                   spec,
                                   cfg->package_paths,
                                   cfg->package_cpaths,
@@ -527,11 +542,11 @@
                                                      cmd_parms *cmd,
                                                      void *_cfg,
                                                      const char *file,
-                                                     const char *function)
+                                                     const char *function,
+						     const char *scope)
 {
     apl_mapped_handler_spec *spec;
     apl_dir_cfg *cfg = (apl_dir_cfg *) _cfg;
-
     apr_array_header_t *hook_specs =
         apr_hash_get(cfg->hooks, name, APR_HASH_KEY_STRING);
     if (!hook_specs) {
@@ -546,6 +561,26 @@
     spec->function_name = apr_pstrdup(cmd->pool, function);
     spec->scope = cfg->vm_scope;
     spec->code_cache_style = APL_CODE_CACHE_STAT;
+
+    if(scope) {
+	if (apr_strnatcmp("once", scope) == 0) {
+	     spec->scope = APL_SCOPE_ONCE;
+	}
+	else if (apr_strnatcmp("request", scope) == 0) {
+	    spec->scope = APL_SCOPE_REQUEST;
+	}
+	else if (apr_strnatcmp("conn", scope) == 0) {
+	    spec->scope = APL_SCOPE_CONN;
+	}
+	else if (apr_strnatcmp("server", scope) == 0) {
+	    spec->scope = APL_SCOPE_SERVER;
+	}
+	else {
+	    return apr_psprintf(cmd->pool,
+				"Invalid value for scope, '%s', acceptable values are %s",
+				scope, "'once', 'request', 'conn', and 'server'");
+	}
+    }
     /*
        int code_cache_style;
        char *function_name;
@@ -553,6 +588,9 @@
        int scope;
      */
     *(apl_mapped_handler_spec **) apr_array_push(hook_specs) = spec;
+    if(APL_SCOPE_SERVER == spec->scope) {
+	*(apl_mapped_handler_spec **) apr_array_push(server_scoped_handlers) = spec;
+    }
     return NULL;
 }
 
@@ -606,10 +644,11 @@
 
 static const char *register_translate_name_hook(cmd_parms *cmd, void *_cfg,
                                                 const char *file,
-                                                const char *function)
+                                                const char *function,
+						const char *scope)
 {
     return register_named_file_function_hook("translate_name", cmd, _cfg,
-                                             file, function);
+                                             file, function, scope);
 }
 
 static const char *register_translate_name_block(cmd_parms *cmd, void *_cfg,
@@ -622,10 +661,11 @@
 
 static const char *register_fixups_hook(cmd_parms *cmd, void *_cfg,
                                         const char *file,
-                                        const char *function)
+                                        const char *function,
+						const char *scope)
 {
     return register_named_file_function_hook("fixups", cmd, _cfg, file,
-                                             function);
+                                             function, scope);
 }
 static const char *register_fixups_block(cmd_parms *cmd, void *_cfg,
                                          const char *line)
@@ -635,10 +675,11 @@
 
 static const char *register_map_to_storage_hook(cmd_parms *cmd, void *_cfg,
                                                 const char *file,
-                                                const char *function)
+                                                const char *function,
+						const char *scope)
 {
     return register_named_file_function_hook("map_to_storage", cmd, _cfg,
-                                             file, function);
+                                             file, function, scope);
 }
 static const char *register_map_to_storage_block(cmd_parms *cmd, void *_cfg,
                                                  const char *line)
@@ -649,10 +690,11 @@
 
 static const char *register_check_user_id_hook(cmd_parms *cmd, void *_cfg,
                                                const char *file,
-                                               const char *function)
+                                               const char *function,
+						const char *scope)
 {
     return register_named_file_function_hook("check_user_id", cmd, _cfg, file,
-                                             function);
+                                             function, scope);
 }
 static const char *register_check_user_id_block(cmd_parms *cmd, void *_cfg,
                                                 const char *line)
@@ -663,10 +705,11 @@
 
 static const char *register_type_checker_hook(cmd_parms *cmd, void *_cfg,
                                               const char *file,
-                                              const char *function)
+                                              const char *function,
+						const char *scope)
 {
     return register_named_file_function_hook("type_checker", cmd, _cfg, file,
-                                             function);
+                                             function, scope);
 }
 static const char *register_type_checker_block(cmd_parms *cmd, void *_cfg,
                                                const char *line)
@@ -677,10 +720,11 @@
 
 static const char *register_access_checker_hook(cmd_parms *cmd, void *_cfg,
                                                 const char *file,
-                                                const char *function)
+                                                const char *function,
+						const char *scope)
 {
     return register_named_file_function_hook("access_checker", cmd, _cfg,
-                                             file, function);
+                                             file, function, scope);
 }
 static const char *register_access_checker_block(cmd_parms *cmd, void *_cfg,
                                                  const char *line)
@@ -691,10 +735,11 @@
 
 static const char *register_auth_checker_hook(cmd_parms *cmd, void *_cfg,
                                               const char *file,
-                                              const char *function)
+                                              const char *function,
+						const char *scope)
 {
     return register_named_file_function_hook("auth_checker", cmd, _cfg, file,
-                                             function);
+                                             function, scope);
 }
 static const char *register_auth_checker_block(cmd_parms *cmd, void *_cfg,
                                                const char *line)
@@ -705,16 +750,18 @@
 
 static const char *register_insert_filter_hook(cmd_parms *cmd, void *_cfg,
                                                const char *file,
-                                               const char *function)
+                                               const char *function,
+						const char *scope)
 {
     return "LuaHookInsertFilter not yet implemented";
 }
 
 static const char *register_quick_hook(cmd_parms *cmd, void *_cfg,
-                                       const char *file, const char *function)
+                                       const char *file, const char *function,
+						const char *scope)
 {
     return register_named_file_function_hook("quick", cmd, _cfg, file,
-                                             function);
+                                             function, scope);
 }
 static const char *register_quick_block(cmd_parms *cmd, void *_cfg,
                                         const char *line)
@@ -872,7 +919,7 @@
     AP_INIT_TAKE23("LuaMapHandler", lua_map_handler, NULL, OR_ALL,
                    "Map a path to a lua handler"),
 
-    AP_INIT_TAKE2("LuaHookTranslateName", register_translate_name_hook, NULL,
+    AP_INIT_TAKE23("LuaHookTranslateName", register_translate_name_hook, NULL,
                   OR_ALL,
                   "Provide a hook for the translate name phase of request processing"),
     AP_INIT_RAW_ARGS("<LuaHookTranslateName", register_translate_name_block,
@@ -880,14 +927,14 @@
                      EXEC_ON_READ | OR_ALL,
                      "Provide a hook for the translate name phase of request processing"),
 
-    AP_INIT_TAKE2("LuaHookFixups", register_fixups_hook, NULL, OR_ALL,
+    AP_INIT_TAKE23("LuaHookFixups", register_fixups_hook, NULL, OR_ALL,
                   "Provide a hook for the fixups phase of request processing"),
     AP_INIT_RAW_ARGS("<LuaHookFixups", register_fixups_block, NULL,
                      EXEC_ON_READ | OR_ALL,
                      "Provide a inline hook for the fixups phase of request processing"),
 
 /* todo: test */
-    AP_INIT_TAKE2("LuaHookMapToStorage", register_map_to_storage_hook, NULL,
+    AP_INIT_TAKE23("LuaHookMapToStorage", register_map_to_storage_hook, NULL,
                   OR_ALL,
                   "Provide a hook for the map_to_storage phase of request processing"),
     AP_INIT_RAW_ARGS("<LuaHookMapToStorage", register_map_to_storage_block,
@@ -896,7 +943,7 @@
                      "Provide a hook for the map_to_storage phase of request processing"),
 
     /* todo: test */
-    AP_INIT_TAKE2("LuaHookCheckUserID", register_check_user_id_hook, NULL,
+    AP_INIT_TAKE23("LuaHookCheckUserID", register_check_user_id_hook, NULL,
                   OR_ALL,
                   "Provide a hook for the check_user_id phase of request processing"),
     AP_INIT_RAW_ARGS("<LuaHookCheckUserID", register_check_user_id_block,
@@ -905,7 +952,7 @@
                      "Provide a hook for the check_user_id phase of request processing"),
 
     /* todo: test */
-    AP_INIT_TAKE2("LuaHookTypeChecker", register_type_checker_hook, NULL,
+    AP_INIT_TAKE23("LuaHookTypeChecker", register_type_checker_hook, NULL,
                   OR_ALL,
                   "Provide a hook for the type_checker phase of request processing"),
     AP_INIT_RAW_ARGS("<LuaHookTypeChecker", register_type_checker_block, NULL,
@@ -913,7 +960,7 @@
                      "Provide a hook for the type_checker phase of request processing"),
 
     /* todo: test */
-    AP_INIT_TAKE2("LuaHookAccessChecker", register_access_checker_hook, NULL,
+    AP_INIT_TAKE23("LuaHookAccessChecker", register_access_checker_hook, NULL,
                   OR_ALL,
                   "Provide a hook for the access_checker phase of request processing"),
     AP_INIT_RAW_ARGS("<LuaHookAccessChecker", register_access_checker_block,
@@ -922,7 +969,7 @@
                      "Provide a hook for the access_checker phase of request processing"),
 
     /* todo: test */
-    AP_INIT_TAKE2("LuaHookAuthChecker", register_auth_checker_hook, NULL,
+    AP_INIT_TAKE23("LuaHookAuthChecker", register_auth_checker_hook, NULL,
                   OR_ALL,
                   "Provide a hook for the auth_checker phase of request processing"),
     AP_INIT_RAW_ARGS("<LuaHookAuthChecker", register_auth_checker_block, NULL,
@@ -930,7 +977,7 @@
                      "Provide a hook for the auth_checker phase of request processing"),
 
     /* todo: test */
-    AP_INIT_TAKE2("LuaHookInsertFilter", register_insert_filter_hook, NULL,
+    AP_INIT_TAKE23("LuaHookInsertFilter", register_insert_filter_hook, NULL,
                   OR_ALL,
                   "Provide a hook for the insert_filter phase of request processing"),
 
@@ -999,6 +1046,55 @@
     return OK;
 }
 
+static int lua_post_config(apr_pool_t * pconf, apr_pool_t * plog,
+                                  apr_pool_t * ptemp, server_rec *s)
+{
+    char *data = NULL;
+    int i;
+    apr_status_t rv;
+    
+    apr_pool_userdata_get((void *) &data, __FILE__,
+                          s->process->pool);
+
+    if (!data) {
+        apr_pool_userdata_set((const void *) 1, __FILE__,
+                              apr_pool_cleanup_null, s->process->pool);
+        return OK;
+    }
+
+    /*see worker.c for how connection->id is calculated*/
+    if((rv = ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &threads_per_child)) != APR_SUCCESS) {
+	ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s,
+		     "mod_lua: ap_mpm_query failed");
+	return rv;
+    }
+
+    server_scoped_pools = apr_pcalloc(pconf, sizeof(apr_pool_t*));
+    for(i = 0; i < threads_per_child; i++) {
+	apr_pool_t *pool;
+	int j;
+	/*create a pool for each thread*/
+	apr_pool_create(&pool, pconf);
+	server_scoped_pools[i] = pool;
+
+	for (j = 0; j < server_scoped_handlers->nelts; j++) {
+	    /*"precompile" each server scoped handler*/
+	    lua_State *L;
+	    const apl_mapped_handler_spec *cnd =
+		((const apl_mapped_handler_spec **) server_scoped_handlers->elts)[j];
+
+	    /*XXX: the package_paths are in dir - which I think they should be server - so I can't get at them here, so just pass null for now :(*/
+	    
+	    L = apl_get_lua_state(pool,
+				  cnd,
+				  NULL,
+				  NULL,
+				  &lua_open_callback, NULL);
+	}
+    }
+    return OK;
+}
+
 static void lua_register_hooks(apr_pool_t *p)
 {
     /* ap_register_output_filter("luahood", luahood, NULL, AP_FTYPE_RESOURCE); */
@@ -1032,6 +1128,8 @@
 
     APR_OPTIONAL_HOOK(apl, lua_request, lua_request_hook, NULL, NULL,
                       APR_HOOK_REALLY_FIRST);
+    server_scoped_handlers = apr_array_make(p, 5, sizeof(apl_mapped_handler_spec*));
+    ap_hook_post_config(lua_post_config, NULL, NULL, APR_HOOK_MIDDLE);
 }
 
 module AP_MODULE_DECLARE_DATA lua_module = {
