From: Paul Querna Date: Sun, 29 May 2005 21:39:39 +0000 (+0000) Subject: - Use a hash for the configuration command lookup implementation. Now modules can... X-Git-Tag: 2.1.5~61 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3a4de8d171c371badb3e22d098e7bece24717bab;p=apache - Use a hash for the configuration command lookup implementation. Now modules can properly directives without dependence on the LoadModule order. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@178990 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index cb3b91c80a..b333020ba7 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,9 @@ Changes with Apache 2.1.5 [Remove entries to the current 2.0 section below, when backported] + *) core: Allow multiple modules to register interest in a single + configuration command. [Paul Querna] + *) EBCDIC: Handle chunked input from client or, with proxy, origin server. [Jeff Trawick] diff --git a/server/config.c b/server/config.c index 3b6af6fb20..808724f701 100644 --- a/server/config.c +++ b/server/config.c @@ -182,6 +182,8 @@ static int dynamic_modules = 0; AP_DECLARE_DATA module *ap_top_module = NULL; AP_DECLARE_DATA module **ap_loaded_modules=NULL; +static apr_hash_t *ap_config_hash = NULL; + typedef int (*handler_func)(request_rec *); typedef void *(*dir_maker_func)(apr_pool_t *, char *); typedef void *(*merger_func)(apr_pool_t *, void *, void *); @@ -408,6 +410,40 @@ AP_DECLARE(void) ap_register_hooks(module *m, apr_pool_t *p) } } + +typedef struct ap_mod_list_struct ap_mod_list; +struct ap_mod_list_struct { + struct ap_mod_list_struct *next; + module *m; + const command_rec *cmd; +}; + +static void ap_add_module_commands(module *m) +{ + apr_pool_t* tpool; + ap_mod_list* mln; + const command_rec *cmd; + char* dir; + + cmd = m->cmds; + + tpool = apr_hash_pool_get(ap_config_hash); + + while (cmd && cmd->name) { + mln = apr_palloc(tpool, sizeof(ap_mod_list)); + mln->cmd = cmd; + mln->m = m; + dir = apr_pstrdup(tpool, cmd->name); + + ap_str_tolower(dir); + + mln->next = apr_hash_get(ap_config_hash, dir, APR_HASH_KEY_STRING); + apr_hash_set(ap_config_hash, dir, APR_HASH_KEY_STRING, mln); + ++cmd; + } +} + + /* One-time setup for precompiled modules --- NOT to be done on restart */ AP_DECLARE(const char *) ap_add_module(module *m, apr_pool_t *p) @@ -465,6 +501,7 @@ AP_DECLARE(const char *) ap_add_module(module *m, apr_pool_t *p) } #endif /*_OSD_POSIX*/ + ap_add_module_commands(m); /* FIXME: is this the right place to call this? * It doesn't appear to be */ @@ -585,6 +622,8 @@ AP_DECLARE(const char *) ap_setup_prelinked_modules(process_rec *process) apr_hook_global_pool=process->pconf; + ap_config_hash = apr_hash_make(process->pool); + /* * Initialise total_modules variable and module indices */ @@ -1042,54 +1081,53 @@ static const char *ap_walk_config_sub(const ap_directive_t *current, cmd_parms *parms, ap_conf_vector_t *section_vector) { - module *mod = ap_top_module; + const command_rec *cmd; + ap_mod_list* ml; + char* dir = apr_pstrdup(parms->pool, current->directive); - while (1) { - const command_rec *cmd; + ap_str_tolower(dir); - if (!(cmd = ap_find_command_in_modules(current->directive, &mod))) { - parms->err_directive = current; - return apr_pstrcat(parms->pool, "Invalid command '", - current->directive, - "', perhaps misspelled or defined by a module " - "not included in the server configuration", - NULL); - } - else { - void *dir_config = ap_set_config_vectors(parms->server, - section_vector, - parms->path, - mod, - parms->pool); - const char *retval; - - /* Once was enough? */ - if (cmd->req_override & EXEC_ON_READ) { - return NULL; - } + ml = apr_hash_get(ap_config_hash, dir, APR_HASH_KEY_STRING); - retval = invoke_cmd(cmd, parms, dir_config, current->args); - if (retval == NULL) { - return NULL; - } + if (ml == NULL) { + parms->err_directive = current; + return apr_pstrcat(parms->pool, "Invalid command '", + current->directive, + "', perhaps misspelled or defined by a module " + "not included in the server configuration", + NULL); + } - if (strcmp(retval, DECLINE_CMD) != 0) { - /* If the directive in error has already been set, don't - * replace it. Otherwise, an error inside a container - * will be reported as occuring on the first line of the - * container. - */ - if (!parms->err_directive) { - parms->err_directive = current; - } + for ( ; ml != NULL; ml = ml->next) { + void *dir_config = ap_set_config_vectors(parms->server, + section_vector, + parms->path, + ml->m, + parms->pool); + const char *retval; + cmd = ml->cmd; - return retval; - } + /* Once was enough? */ + if (cmd->req_override & EXEC_ON_READ) { + continue; + } - mod = mod->next; /* Next time around, skip this one */ + retval = invoke_cmd(cmd, parms, dir_config, current->args); + + if (retval != NULL && strcmp(retval, DECLINE_CMD) != 0) { + /* If the directive in error has already been set, don't + * replace it. Otherwise, an error inside a container + * will be reported as occuring on the first line of the + * container. + */ + if (!parms->err_directive) { + parms->err_directive = current; + } + return retval; } } - /* NOTREACHED */ + + return NULL; } AP_DECLARE(const char *) ap_walk_config(ap_directive_t *current, @@ -1332,19 +1370,34 @@ static const char *execute_now(char *cmd_line, const char *args, ap_directive_t **sub_tree, ap_directive_t *parent) { - module *mod = ap_top_module; const command_rec *cmd; + ap_mod_list* ml; + char* dir = apr_pstrdup(parms->pool, cmd_line); - if (!(cmd = ap_find_command_in_modules(cmd_line, &mod))) { + ap_str_tolower(dir); + + ml = apr_hash_get(ap_config_hash, dir, APR_HASH_KEY_STRING); + + if (ml == NULL) { return apr_pstrcat(parms->pool, "Invalid command '", cmd_line, "', perhaps misspelled or defined by a module " "not included in the server configuration", NULL); } - else { - return invoke_cmd(cmd, parms, sub_tree, args); + + for ( ; ml != NULL; ml = ml->next) { + const char *retval; + cmd = ml->cmd; + + retval = invoke_cmd(cmd, parms, sub_tree, args); + + if (retval != NULL) { + return retval; + } } + + return NULL; } /* This structure and the following functions are needed for the