File 0018-Optimize-finding-a-module.-ap_find_linked_module-was.patch of Package ea-apache2

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: "J. Nick Koston" <nick@cpanel.net>
Date: Fri, 13 Dec 2019 10:57:41 -0600
Subject: [PATCH 18/21] Optimize finding a module. ap_find_linked_module was
 not performing well when there a lot of IfModule statements in httpd.conf.
 This change uses a hash to keep track of modules which cut the startup time
 from 3s to 1.5s on a large configuration file. This also makes find_module
 module simpler.

---
 server/config.c | 37 +++++++++++++++++++++++++++++--------
 server/core.c   | 42 +-----------------------------------------
 2 files changed, 30 insertions(+), 49 deletions(-)

diff --git a/server/config.c b/server/config.c
index 3d11ff5..62421b9 100644
--- a/server/config.c
+++ b/server/config.c
@@ -229,6 +229,7 @@ AP_DECLARE_DATA module *ap_top_module = NULL;
 AP_DECLARE_DATA module **ap_loaded_modules=NULL;
 
 static apr_hash_t *ap_config_hash = NULL;
+static apr_hash_t *ap_module_hash = NULL;
 
 /* a list of the module symbol names with the trailing "_module"removed */
 static char **ap_module_short_names = NULL;
@@ -513,9 +514,13 @@ static void rebuild_conf_hash(apr_pool_t *p, int add_prelinked)
     module **m;
 
     ap_config_hash = apr_hash_make(p);
+    ap_module_hash = apr_hash_make(p);
 
     apr_pool_cleanup_register(p, &ap_config_hash, ap_pool_cleanup_set_null,
                               apr_pool_cleanup_null);
+    apr_pool_cleanup_register(p, &ap_module_hash, ap_pool_cleanup_set_null,
+                              apr_pool_cleanup_null);
+
     if (add_prelinked) {
         for (m = ap_prelinked_modules; *m != NULL; m++) {
             ap_add_module_commands(*m, p);
@@ -526,9 +531,11 @@ static void rebuild_conf_hash(apr_pool_t *p, int add_prelinked)
 static void ap_add_module_commands(module *m, apr_pool_t *p)
 {
     apr_pool_t *tpool;
+    apr_pool_t *mpool;
     ap_mod_list *mln;
     const command_rec *cmd;
     char *dir;
+    char *module_identifier;
 
     cmd = m->cmds;
 
@@ -537,6 +544,15 @@ static void ap_add_module_commands(module *m, apr_pool_t *p)
     }
 
     tpool = apr_hash_pool_get(ap_config_hash);
+    apr_hash_set(ap_module_hash, m->name, APR_HASH_KEY_STRING, m);
+
+    /* We need to add the module identifier so both <IfModule mod_ssl.c> and <IfModule ssl_module> work */
+    if (ap_module_short_names[m->module_index]) {
+        mpool = apr_hash_pool_get(ap_module_hash);
+        /* ap_module_short_names has the trailing "_module" removed so we have to put it back */
+        module_identifier = apr_pstrcat(mpool, ap_module_short_names[m->module_index], "_module", NULL);
+        apr_hash_set(ap_module_hash, module_identifier, APR_HASH_KEY_STRING, m);
+    }
 
     while (cmd && cmd->name) {
         mln = apr_palloc(tpool, sizeof(ap_mod_list));
@@ -662,6 +678,8 @@ AP_DECLARE(const char *) ap_add_module(module *m, apr_pool_t *p,
 AP_DECLARE(void) ap_remove_module(module *m)
 {
     module *modp;
+    apr_pool_t *mpool;
+    char *module_identifier;
 
     modp = ap_top_module;
     if (modp == m) {
@@ -690,6 +708,16 @@ AP_DECLARE(void) ap_remove_module(module *m)
         modp->next = modp->next->next;
     }
 
+    apr_hash_set(ap_module_hash, m->name, APR_HASH_KEY_STRING, NULL);
+
+    /* We need to remove the module identifier so both <IfModule mod_ssl.c> and <IfModule ssl_module> work */
+    if (ap_module_short_names[m->module_index]) {
+        mpool = apr_hash_pool_get(ap_module_hash);
+        /* ap_module_short_names has the trailing "_module" removed so we have to put it back */
+        module_identifier = apr_pstrcat(mpool, ap_module_short_names[m->module_index], "_module", NULL);
+        apr_hash_set(ap_module_hash, module_identifier, APR_HASH_KEY_STRING, NULL);
+    }
+
     free(ap_module_short_names[m->module_index]);
     ap_module_short_names[m->module_index] = NULL;
     merger_func_cache[m->module_index] = NULL;
@@ -829,14 +857,7 @@ AP_DECLARE(const char *) ap_find_module_short_name(int module_index)
 
 AP_DECLARE(module *) ap_find_linked_module(const char *name)
 {
-    module *modp;
-
-    for (modp = ap_top_module; modp; modp = modp->next) {
-        if (strcmp(modp->name, name) == 0)
-            return modp;
-    }
-
-    return NULL;
+    return apr_hash_get(ap_module_hash, name, APR_HASH_KEY_STRING);
 }
 
 /*****************************************************************
diff --git a/server/core.c b/server/core.c
index 900606f..481da18 100644
--- a/server/core.c
+++ b/server/core.c
@@ -2811,47 +2811,7 @@ static const char *ifsection(cmd_parms *cmd, void *mconfig, const char *arg)
 
 static module *find_module(server_rec *s, const char *name)
 {
-    module *found = ap_find_linked_module(name);
-
-    /* search prelinked stuff */
-    if (!found) {
-        ap_module_symbol_t *current = ap_prelinked_module_symbols;
-
-        for (; current->name; ++current) {
-            if (!strcmp(current->name, name)) {
-                found = current->modp;
-                break;
-            }
-        }
-    }
-
-    /* search dynamic stuff */
-    if (!found) {
-        APR_OPTIONAL_FN_TYPE(ap_find_loaded_module_symbol) *check_symbol =
-            APR_RETRIEVE_OPTIONAL_FN(ap_find_loaded_module_symbol);
-
-        if (check_symbol) {
-            /*
-             * There are two phases where calling ap_find_loaded_module_symbol
-             * is problematic:
-             *
-             * During reading of the config, ap_server_conf is invalid but s
-             * points to the main server config, if passed from cmd->server
-             * of an EXEC_ON_READ directive.
-             *
-             * During config parsing, s may be a virtual host that would cause
-             * a segfault in mod_so if passed to ap_find_loaded_module_symbol,
-             * because mod_so's server config for vhosts is initialized later.
-             * But ap_server_conf is already set at this time.
-             *
-             * Therefore we use s if it is not virtual and ap_server_conf if
-             * s is virtual.
-             */
-            found = check_symbol(s->is_virtual ? ap_server_conf : s, name);
-        }
-    }
-
-    return found;
+    return ap_find_linked_module(name);
 }
 
 /* Callback function type used by start_cond_section. */
openSUSE Build Service is sponsored by