HI all,


Attached is a patch that adds more dynamic configuration.
It places some of the MPM variables such as 'ap_max_daemons_limit',
'ap_daemons_limit', 'ap_daemons_min_free' and 'ap_daemons_max_free' 
in the scoreboard. This enables management modules to do
dynamic (runtime) configuration without requiring a restart of the
Apache HTTP server.


How is it done:
1) The patch adds a hook after the creation of the scoreboard
        which is used by the MPM to transfer the variables in
        the scoreboard and allows a management modules to change
        those.
2) The MPM during its server maintenance (or spawning of extra
processes)
        use the variables that are now in the scoreboard.
        The children are not influenced in performance from this
        for the variables: 'ap_max_daemons_limit',
        'ap_daemons_limit', 'ap_daemons_min_free' and 'ap_daemons_max_free'.
3) The a child uses now the 'max_requests_per_child' from the
scoreboard.
        Which is has little or no impact on the request processing.

This patch works only for the PREFORK MPM. If it is seen as usefull,
we can do the same with the other MPMs and, for instance, add
'ap_threads_min_spare' in the scoreboard as well to allow dynamic
configuration.

Let me know what you think of it.

Harrie
-- 
address: Covalent Technologies, 645 Howard St, San Francisco, CA - 94105
phone: +1-415-536-5221                               fax:+1-415-536-5210
personal website: http://www.lisanza.net/
diff -ru ../httpd-2.0/include/ap_mpm.h ./include/ap_mpm.h
--- ../httpd-2.0/include/ap_mpm.h       Wed Jun 27 10:43:28 2001
+++ ./include/ap_mpm.h  Tue Jul  3 14:18:43 2001
@@ -169,6 +169,7 @@
 #define AP_MPMQ_MAX_SPARE_DAEMONS     9  /* Max # of spare daemons       */
 #define AP_MPMQ_MAX_SPARE_THREADS    10  /* Max # of spare threads       */
 #define AP_MPMQ_MAX_REQUESTS_DEAMON  11  /* Max # of requests per daemon */
+#define AP_MPMQ_DAEMONS_USED         12  /* Used # of scoreboard slots   */
 
 
 /**
diff -ru ../httpd-2.0/include/scoreboard.h ./include/scoreboard.h
--- ../httpd-2.0/include/scoreboard.h   Sat Jun  9 17:37:59 2001
+++ ./include/scoreboard.h      Thu Jul  5 09:09:19 2001
@@ -73,6 +73,8 @@
 #include "apr_thread_proc.h"
 #include "apr_portable.h"
 
+AP_DECLARE_HOOK(void,setup_shared_info,(apr_pool_t *pconf,apr_pool_t *plog,server_rec 
+*s));
+
 /* Scoreboard info on a process is, for now, kept very brief --- 
  * just status value and pid (the latter so that the caretaker process
  * can properly update the scoreboard when a process dies).  We may want
@@ -169,6 +171,11 @@
     ap_scoreboard_e sb_type;
     ap_generation_t running_generation;        /* the generation of children which
                                          * should still be serving requests. */
+    int ap_max_daemons_limit;           /* used # of scoreboard slots        */
+    int ap_daemons_limit;               /* max # of clients                  */
+    int ap_daemons_max_free;            /* max # of spare servers            */
+    int ap_daemons_min_free;            /* min # of spare servers            */
+    int ap_max_requests_per_child;      /* max # of requests per child       */
 } global_score;
 
 /* stuff which the parent generally writes and the children rarely read */
diff -ru ../httpd-2.0/server/mpm/prefork/mpm.h ./server/mpm/prefork/mpm.h
--- ../httpd-2.0/server/mpm/prefork/mpm.h       Wed Jun  6 17:09:16 2001
+++ ./server/mpm/prefork/mpm.h  Tue Jul  3 13:56:27 2001
@@ -75,7 +75,6 @@
 #define MPM_NOTE_CHILD_KILLED(i) (MPM_CHILD_PID(i) = 0)
 
 extern int ap_threads_per_child;
-extern int ap_max_daemons_limit;
 extern server_rec *ap_server_conf;
 extern char ap_coredump_dir[MAX_STRING_LEN];
 #endif /* APACHE_MPM_PREFORK_H */
diff -ru ../httpd-2.0/server/mpm/prefork/prefork.c ./server/mpm/prefork/prefork.c
--- ../httpd-2.0/server/mpm/prefork/prefork.c   Wed Jun 27 10:43:39 2001
+++ ./server/mpm/prefork/prefork.c      Thu Jul  5 11:37:25 2001
@@ -151,7 +151,6 @@
  * to deal with MaxClients changes across SIGWINCH restarts.  We use this
  * value to optimize routines that have to scan the entire scoreboard.
  */
-int ap_max_daemons_limit = -1;
 server_rec *ap_server_conf;
 
 char ap_coredump_dir[MAX_STRING_LEN];
@@ -316,7 +315,10 @@
 {
     switch(query_code){
         case AP_MPMQ_MAX_DAEMONS:
-            *result = ap_daemons_limit;
+            *result = ap_scoreboard_image->global.ap_daemons_limit;
+            return APR_SUCCESS;
+        case AP_MPMQ_DAEMONS_USED:
+            *result = ap_scoreboard_image->global.ap_max_daemons_limit;
             return APR_SUCCESS;
         case AP_MPMQ_IS_THREADED:
             *result = AP_MPMQ_NOT_SUPPORTED;
@@ -334,19 +336,19 @@
             *result = 0;
             return APR_SUCCESS;
         case AP_MPMQ_MIN_SPARE_DEAMONS:
-            *result = ap_daemons_min_free;
+            *result = ap_scoreboard_image->global.ap_daemons_min_free;
             return APR_SUCCESS;
         case AP_MPMQ_MIN_SPARE_THREADS:
             *result = 0;
             return APR_SUCCESS;
         case AP_MPMQ_MAX_SPARE_DAEMONS:
-            *result = ap_daemons_max_free;
+            *result = ap_scoreboard_image->global.ap_daemons_max_free;
             return APR_SUCCESS;
         case AP_MPMQ_MAX_SPARE_THREADS:
             *result = 0;
             return APR_SUCCESS;
         case AP_MPMQ_MAX_REQUESTS_DEAMON:
-            *result = ap_max_requests_per_child;
+            *result = ap_scoreboard_image->global.ap_max_requests_per_child;
             return APR_SUCCESS;
     }
     return APR_ENOTIMPL;
@@ -361,7 +363,7 @@
 {
     int n, pid;
 
-    for (n = 0; n < ap_max_daemons_limit; ++n) {
+    for (n = 0; n < ap_scoreboard_image->global.ap_max_daemons_limit; ++n) {
         ap_sync_scoreboard_image();
        if (ap_scoreboard_image->servers[n][0].status != SERVER_DEAD &&
                kill((pid = ap_scoreboard_image->parent[n].pid), 0) == -1) {
@@ -598,8 +600,8 @@
 
        apr_pool_clear(ptrans);
 
-       if ((ap_max_requests_per_child > 0
-            && requests_this_child++ >= ap_max_requests_per_child)) {
+       if ((ap_scoreboard_image->global.ap_max_requests_per_child > 0
+            && requests_this_child++ >= 
+ap_scoreboard_image->global.ap_max_requests_per_child)) {
            clean_child_exit(0);
        }
 
@@ -836,8 +838,8 @@
 {
     int pid;
 
-    if (slot + 1 > ap_max_daemons_limit) {
-       ap_max_daemons_limit = slot + 1;
+    if (slot + 1 > ap_scoreboard_image->global.ap_max_daemons_limit) {
+       ap_scoreboard_image->global.ap_max_daemons_limit = slot + 1;
     }
 
     if (one_process) {
@@ -920,7 +922,7 @@
 {
     int i;
 
-    for (i = 0; number_to_start && i < ap_daemons_limit; ++i) {
+    for (i = 0; number_to_start && i < ap_scoreboard_image->global.ap_daemons_limit; 
+++i) {
        if (ap_scoreboard_image->servers[i][0].status != SERVER_DEAD) {
            continue;
        }
@@ -964,10 +966,10 @@
     total_non_dead = 0;
 
     ap_sync_scoreboard_image();
-    for (i = 0; i < ap_daemons_limit; ++i) {
+    for (i = 0; i < ap_scoreboard_image->global.ap_daemons_limit; ++i) {
        int status;
 
-       if (i >= ap_max_daemons_limit && free_length == idle_spawn_rate)
+       if (i >= ap_scoreboard_image->global.ap_max_daemons_limit && free_length == 
+idle_spawn_rate)
            break;
        ws = &ap_scoreboard_image->servers[i][0];
        status = ws->status;
@@ -1000,8 +1002,8 @@
            last_non_dead = i;
        }
     }
-    ap_max_daemons_limit = last_non_dead + 1;
-    if (idle_count > ap_daemons_max_free) {
+    ap_scoreboard_image->global.ap_max_daemons_limit = last_non_dead + 1;
+    if (idle_count > ap_scoreboard_image->global.ap_daemons_max_free) {
        /* kill off one child... we use the pod because that'll cause it to
         * shut down gracefully, in case it happened to pick up a request
         * while we were counting
@@ -1009,7 +1011,7 @@
        ap_mpm_pod_signal(pod);
        idle_spawn_rate = 1;
     }
-    else if (idle_count < ap_daemons_min_free) {
+    else if (idle_count < ap_scoreboard_image->global.ap_daemons_min_free) {
        /* terminate the free list */
        if (free_length == 0) {
            /* only report this condition once */
@@ -1110,9 +1112,13 @@
         return 1;
     }
 
+    if (ap_daemons_max_free < ap_daemons_min_free + 1) /* Don't thrash... */
+       ap_daemons_max_free = ap_daemons_min_free + 1;
+
     SAFE_ACCEPT(accept_mutex_init(pconf));
     if (!is_graceful) {
         ap_create_scoreboard(pconf, SB_SHARED);
+        ap_run_setup_shared_info(pconf, plog, s);
     }
 #ifdef SCOREBOARD_FILE
     else {
@@ -1123,9 +1129,6 @@
 
     set_signals();
 
-    if (ap_daemons_max_free < ap_daemons_min_free + 1) /* Don't thrash... */
-       ap_daemons_max_free = ap_daemons_min_free + 1;
-
     /* If we're doing a graceful_restart then we're going to see a lot
        * of children exiting immediately when we get into the main loop
        * below (because we just sent them SIGWINCH).  This happens pretty
@@ -1135,8 +1138,8 @@
        * supposed to start up without the 1 second penalty between each fork.
        */
     remaining_children_to_start = ap_daemons_to_start;
-    if (remaining_children_to_start > ap_daemons_limit) {
-       remaining_children_to_start = ap_daemons_limit;
+    if (remaining_children_to_start > ap_scoreboard_image->global.ap_daemons_limit) {
+       remaining_children_to_start = ap_scoreboard_image->global.ap_daemons_limit;
     }
     if (!is_graceful) {
        startup_children(remaining_children_to_start);
@@ -1176,7 +1179,7 @@
                (void) ap_update_child_status(AP_CHILD_THREAD_FROM_ID(child_slot), 
SERVER_DEAD,
                                            (request_rec *) NULL);
                if (remaining_children_to_start
-                   && child_slot < ap_daemons_limit) {
+                   && child_slot < ap_scoreboard_image->global.ap_daemons_limit) {
                    /* we're still doing a 1-for-1 replacement of dead
                        * children with new children
                        */
@@ -1267,7 +1270,7 @@
     ap_scoreboard_image->global.running_generation = ap_my_generation;
     update_scoreboard_global();
     
-    for (index = 0; index < ap_daemons_limit; ++index) {
+    for (index = 0; index < ap_scoreboard_image->global.ap_daemons_limit; ++index) {
         ap_scoreboard_image->parent[index].process_status = SB_IDLE_DIE;
     }
 
@@ -1276,7 +1279,7 @@
                    "Graceful restart requested, doing restart");
 
        /* kill off the idle ones */
-        ap_mpm_pod_killpg(pod, ap_daemons_limit);
+        ap_mpm_pod_killpg(pod, ap_scoreboard_image->global.ap_daemons_limit);
 
 #ifndef SCOREBOARD_FILE
        /* This is mostly for debugging... so that we know what is still
@@ -1285,7 +1288,7 @@
            * corruption too easily.
            */
        ap_sync_scoreboard_image();
-       for (index = 0; index < ap_daemons_limit; ++index) {
+       for (index = 0; index < ap_scoreboard_image->global.ap_daemons_limit; ++index) 
+{
            if (ap_scoreboard_image->servers[index][0].status != SERVER_DEAD) {
                ap_scoreboard_image->servers[index][0].status = SERVER_GRACEFUL;
            }
@@ -1339,6 +1342,15 @@
     apr_cpystrn(ap_coredump_dir, ap_server_root, sizeof(ap_coredump_dir));
 }
 
+static void prefork_init_shared(apr_pool_t *pconf, apr_pool_t *plog, server_rec *s)
+{
+    ap_scoreboard_image->global.ap_max_daemons_limit = -1;
+    ap_scoreboard_image->global.ap_daemons_limit = ap_daemons_limit;
+    ap_scoreboard_image->global.ap_daemons_max_free = ap_daemons_max_free;
+    ap_scoreboard_image->global.ap_daemons_min_free = ap_daemons_min_free;
+    ap_scoreboard_image->global.ap_max_requests_per_child = ap_max_requests_per_child;
+}
+
 static void prefork_hooks(apr_pool_t *p)
 {
 #ifdef AUX3
@@ -1346,6 +1358,7 @@
 #endif
 
     ap_hook_pre_config(prefork_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
+    ap_hook_setup_shared_info(prefork_init_shared, NULL, NULL, APR_HOOK_MIDDLE);
 }
 
 static const char *set_pidfile(cmd_parms *cmd, void *dummy, const char *arg) 
diff -ru ../httpd-2.0/server/scoreboard.c ./server/scoreboard.c
--- ../httpd-2.0/server/scoreboard.c    Mon May 21 18:31:12 2001
+++ ./server/scoreboard.c       Tue Jul  3 13:30:35 2001
@@ -84,6 +84,14 @@
 AP_DECLARE_DATA int ap_extended_status = 0;
 AP_DECLARE_DATA apr_time_t ap_restart_time = 0;
 
+APR_HOOK_STRUCT(
+                   APR_HOOK_LINK(setup_shared_info)
+)
+
+AP_IMPLEMENT_HOOK_VOID(setup_shared_info,
+                       (apr_pool_t *pconf, apr_pool_t *plog, server_rec *s),
+                       (pconf,plog,s))
+
 #if APR_HAS_SHARED_MEMORY
 #include "apr_shmem.h"
 static apr_shmem_t *scoreboard_shm = NULL;

Reply via email to