diff -Nur httpd-2.2.17-peruser-rc2/server/mpm/experimental/peruser/mpm.h httpd-2.2.17-peruser/server/mpm/experimental/peruser/mpm.h
--- httpd-2.2.17-peruser-rc2/server/mpm/experimental/peruser/mpm.h 2010-12-28 13:10:02.000000000 -0200
+++ httpd-2.2.17-peruser/server/mpm/experimental/peruser/mpm.h 2011-01-03 16:15:07.000000000 -0200
@@ -69,7 +69,6 @@
#define MPM_NAME "Peruser"
#define AP_MPM_WANT_RECLAIM_CHILD_PROCESSES
-#define AP_MPM_WANT_WAIT_OR_TIMEOUT
#define AP_MPM_WANT_PROCESS_CHILD_STATUS
#define AP_MPM_WANT_SET_PIDFILE
#define AP_MPM_WANT_SET_SCOREBOARD
@@ -96,7 +95,7 @@
#define SERVER_DYING 1
#define SERVER_ALIVE 2
-static const char* child_clone();
+static void child_clone(int child_num);
#endif /* APACHE_MPM_PERUSER_H */
diff -Nur httpd-2.2.17-peruser-rc2/server/mpm/experimental/peruser/mpm_default.h httpd-2.2.17-peruser/server/mpm/experimental/peruser/mpm_default.h
--- httpd-2.2.17-peruser-rc2/server/mpm/experimental/peruser/mpm_default.h 2010-12-28 13:10:02.000000000 -0200
+++ httpd-2.2.17-peruser/server/mpm/experimental/peruser/mpm_default.h 2010-12-30 16:26:27.000000000 -0200
@@ -62,7 +62,7 @@
/* Number of processors to spawn off for each ServerEnvironment by default */
#ifndef DEFAULT_START_PROCESSORS
-#define DEFAULT_START_PROCESSORS 0
+#define DEFAULT_START_PROCESSORS 1
#endif
/* Minimum number of running processors per ServerEnvironment */
diff -Nur httpd-2.2.17-peruser-rc2/server/mpm/experimental/peruser/peruser.c httpd-2.2.17-peruser/server/mpm/experimental/peruser/peruser.c
--- httpd-2.2.17-peruser-rc2/server/mpm/experimental/peruser/peruser.c 2010-12-28 13:10:02.000000000 -0200
+++ httpd-2.2.17-peruser/server/mpm/experimental/peruser/peruser.c 2011-01-03 17:16:24.000000000 -0200
@@ -185,6 +185,7 @@
#define HARD_THREAD_LIMIT 1
#endif
+#define CHILD_TYPE_RESERVED -1
#define CHILD_TYPE_UNKNOWN 0
#define CHILD_TYPE_MULTIPLEXER 1
#define CHILD_TYPE_PROCESSOR 2
@@ -204,6 +205,7 @@
int ap_threads_per_child = 0; /* Worker threads per child */
static apr_proc_mutex_t *accept_mutex;
+static int ap_start_processors = DEFAULT_START_PROCESSORS;
static int ap_min_processors = DEFAULT_MIN_PROCESSORS;
static int ap_min_free_processors = DEFAULT_MIN_FREE_PROCESSORS;
static int ap_max_free_processors = DEFAULT_MAX_FREE_PROCESSORS;
@@ -227,6 +229,7 @@
typedef struct
{
+ int id;
int processor_id;
const char *name; /* Server environment's unique string identifier */
@@ -239,6 +242,7 @@
const char *cgroup; /* cgroup directory, can be null */
/* resource settings */
+ int start_processors;
int min_processors;
int min_free_processors;
int max_free_processors;
@@ -258,6 +262,12 @@
unsigned long stats_requests; /* requests handled */
unsigned long stats_connections; /* connections handled */
unsigned long stats_dropped; /* connections dropped because multiplexer was not able to pass */
+
+ /* counters */
+ int total_processors;
+ int idle_processors;
+ int active_processors;
+ int total_processes;
} server_env_t;
typedef struct
@@ -290,6 +300,7 @@
typedef struct
{
apr_size_t num;
+ int new;
} child_info_control;
typedef struct
@@ -426,6 +437,8 @@
return "PROCESSOR";
case CHILD_TYPE_WORKER:
return "WORKER";
+ case CHILD_TYPE_RESERVED:
+ return "RESERVED";
}
return "UNKNOWN";
@@ -552,6 +565,43 @@
exit(code);
}
+/* number of calls to wait_or_timeout between writable probes */
+#ifndef INTERVAL_OF_WRITABLE_PROBES
+#define INTERVAL_OF_WRITABLE_PROBES 10
+#endif
+static int wait_or_timeout_counter;
+
+void ap_wait_or_timeout(apr_exit_why_e *status, int *exitcode, apr_proc_t *ret,
+ apr_pool_t *p)
+{
+ apr_status_t rv;
+
+ ++wait_or_timeout_counter;
+ if (wait_or_timeout_counter == INTERVAL_OF_WRITABLE_PROBES) {
+ wait_or_timeout_counter = 0;
+ ap_run_monitor(p);
+ }
+
+ rv = apr_proc_wait_all_procs(ret, exitcode, status, APR_NOWAIT, p);
+ if (APR_STATUS_IS_EINTR(rv)) {
+ ret->pid = -1;
+ return;
+ }
+
+ if (APR_STATUS_IS_CHILD_DONE(rv)) {
+ return;
+ }
+
+#ifdef NEED_WAITPID
+ if ((ret = reap_children(exitcode, status)) > 0) {
+ return;
+ }
+#endif
+
+ ret->pid = -1;
+ return;
+}
+
static void accept_mutex_on(void)
{
apr_status_t rv = apr_proc_mutex_lock(accept_mutex);
@@ -897,78 +947,98 @@
return 0;
}
-static int total_processors(int child_num)
+static int active_env_processors(int env_num)
{
- int i, total;
-
- for (i = 0, total = 0; i < NUM_CHILDS; ++i) {
- if (CHILD_INFO_TABLE[i].senv == CHILD_INFO_TABLE[child_num].senv)
- total++;
+ if (env_num >= NUM_SENV) {
+ return -1;
}
-
- return total;
+ return SENV[env_num].active_processors;
}
-static int active_processors(int child_num)
+static void update_single_processor_counters(int child_num)
{
- int i, total;
+ int i;
+ int tmp_total_processors = 0;
+ int tmp_idle_processors = 0;
+ int tmp_active_processors = 0;
+ int tmp_total_processes = 0;
- for (i = 0, total = 0; i < NUM_CHILDS; ++i) {
- if (CHILD_INFO_TABLE[i].senv == CHILD_INFO_TABLE[child_num].senv
- && CHILD_INFO_TABLE[i].pid > 0) {
- total++;
+ /* counting processors */
+ for (i = 0; i < NUM_CHILDS; ++i) {
+ if (CHILD_INFO_TABLE[i].senv == CHILD_INFO_TABLE[child_num].senv) {
+ tmp_total_processors++;
+ if (CHILD_INFO_TABLE[i].status == CHILD_STATUS_READY
+ || CHILD_INFO_TABLE[i].status == CHILD_STATUS_STARTING)
+ tmp_idle_processors++;
+ if (CHILD_INFO_TABLE[i].pid > 0)
+ tmp_active_processors++;
+ if (CHILD_INFO_TABLE[i].status != CHILD_STATUS_STANDBY)
+ tmp_total_processes++;
}
}
- return total;
-}
-
-static int active_env_processors(int env_num)
-{
- int i, total;
-
- if (env_num >= NUM_SENV) {
- return -1;
- }
-
- for (i = 0, total = 0; i < NUM_CHILDS; ++i) {
- if (CHILD_INFO_TABLE[i].senv == &SENV[env_num]
- && CHILD_INFO_TABLE[i].pid > 0) {
- total++;
- }
- }
+ /* updating counters */
+ CHILD_INFO_TABLE[child_num].senv->total_processors = tmp_total_processors;
+ CHILD_INFO_TABLE[child_num].senv->idle_processors = tmp_idle_processors;
+ CHILD_INFO_TABLE[child_num].senv->active_processors = tmp_active_processors;
+ CHILD_INFO_TABLE[child_num].senv->total_processes = tmp_total_processes;
- return total;
+ return;
}
-static int idle_processors(int child_num)
+static void update_all_counters()
{
- int i, total;
+ int i, tmp_id;
+ static int *tmp_total_processors;
+ static int *tmp_idle_processors;
+ static int *tmp_active_processors;
+ static int *tmp_total_processes;
- for (i = 0, total = 0; i < NUM_CHILDS; ++i) {
- if (CHILD_INFO_TABLE[i].senv == CHILD_INFO_TABLE[child_num].senv
- && (CHILD_INFO_TABLE[i].status == CHILD_STATUS_READY
- || CHILD_INFO_TABLE[i].status == CHILD_STATUS_STARTING)) {
- total++;
- }
- }
+ if (!NUM_SENV) return;
- return total;
-}
+ tmp_total_processors = (int*) malloc(NUM_SENV * sizeof(int));
+ tmp_idle_processors = (int*) malloc(NUM_SENV * sizeof(int));
+ tmp_active_processors = (int*) malloc(NUM_SENV * sizeof(int));
+ tmp_total_processes = (int*) malloc(NUM_SENV * sizeof(int));
-static int idle_env_processors(int env_num)
-{
- int i, total;
+ /* resetting counters */
+ for (i = 0; i < NUM_SENV; ++i) {
+ tmp_total_processors[i] = 0;
+ tmp_idle_processors[i] = 0;
+ tmp_active_processors[i] = 0;
+ tmp_total_processes[i] = 0;
+ }
- for (i = 0, total = 0; i < NUM_CHILDS; ++i) {
- if (CHILD_INFO_TABLE[i].senv == &SENV[env_num]
- && (CHILD_INFO_TABLE[i].status == CHILD_STATUS_READY
- || CHILD_INFO_TABLE[i].status == CHILD_STATUS_STARTING)) {
- total++;
+ /* counting processors */
+ for (i = 0; i < NUM_CHILDS; ++i) {
+ if (CHILD_INFO_TABLE[i].senv != NULL) {
+ tmp_id = CHILD_INFO_TABLE[i].senv->id;
+ tmp_total_processors[tmp_id]++;
+ if (CHILD_INFO_TABLE[i].status == CHILD_STATUS_READY
+ || CHILD_INFO_TABLE[i].status == CHILD_STATUS_STARTING)
+ tmp_idle_processors[tmp_id]++;
+ if (CHILD_INFO_TABLE[i].pid > 0)
+ tmp_active_processors[tmp_id]++;
+ if (CHILD_INFO_TABLE[i].status != CHILD_STATUS_STANDBY)
+ tmp_total_processes[tmp_id]++;
}
}
- return total;
+ /* updating counters */
+ for (i = 0; i < NUM_SENV; ++i) {
+ SENV[i].total_processors = tmp_total_processors[i];
+ SENV[i].idle_processors = tmp_idle_processors[i];
+ SENV[i].active_processors = tmp_active_processors[i];
+ SENV[i].total_processes = tmp_total_processes[i];
+ }
+
+ /* free-up resources */
+ free(tmp_total_processors);
+ free(tmp_idle_processors);
+ free(tmp_active_processors);
+ free(tmp_total_processes);
+
+ return;
}
static int wait_for_workers(child_info_t *processor)
@@ -978,8 +1048,9 @@
wait_step_size = 100 / processor_wait_steps;
/* Check if the processor is available */
- if (total_processors(processor->id) == processor->senv->max_processors
- && idle_processors(processor->id) == 0 && processor_wait_timeout > 0) {
+ update_single_processor_counters(processor->id);
+ if (processor->senv->total_processors == processor->senv->max_processors
+ && processor->senv->idle_processors == 0 && processor_wait_timeout > 0) {
/* The processor is currently busy, try to wait (a little) */
_DBG("processor seems to be busy, trying to wait for it");
@@ -1000,15 +1071,16 @@
}
/* We sleep a little (depending how available the processor is) */
- wait_time = (processor_wait_timeout / processor_wait_steps) * 1000000;
+ wait_time = (float) processor_wait_timeout / processor_wait_steps * 1000000;
for (i = 0; i <= processor->senv->availability; i += wait_step_size) {
- usleep(wait_time);
+ apr_sleep(wait_time);
/* Check if the processor is ready */
- if (total_processors(processor->id)
+ update_single_processor_counters(processor->id);
+ if (processor->senv->total_processors
< processor->senv->max_processors
- || idle_processors(processor->id) > 0)
+ || processor->senv->idle_processors > 0)
{
/* The processor has freed - lets use it */
_DBG("processor freed before wait time expired");
@@ -1123,6 +1195,10 @@
if (processor->status == CHILD_STATUS_STANDBY) {
_DBG("Activating child #%d", processor->id);
processor->status = CHILD_STATUS_STARTING;
+ child_info_image->control->new = 1;
+ processor->senv->total_processors++;
+ processor->senv->idle_processors++;
+ processor->senv->total_processes++;
}
_DBG("Writing message to %d, passing sock_fd: %d", processor->senv->output,
@@ -1195,6 +1271,10 @@
if (processor->status == CHILD_STATUS_STANDBY) {
_DBG("Activating child #%d", processor->id);
processor->status = CHILD_STATUS_STARTING;
+ child_info_image->control->new = 1;
+ processor->senv->total_processors++;
+ processor->senv->idle_processors++;
+ processor->senv->total_processes++;
}
_DBG("Creating new pool",0);
@@ -1454,6 +1534,10 @@
if (child->status == CHILD_STATUS_STANDBY) {
_DBG("Activating child #%d", child->id);
child->status = CHILD_STATUS_STARTING;
+ child_info_image->control->new = 1;
+ child->senv->total_processors++;
+ child->senv->idle_processors++;
+ child->senv->total_processes++;
}
_DBG("Writing message to %d, passing sock_fd: %d", child->senv->output,
@@ -2073,6 +2157,7 @@
if (CHILD_INFO_TABLE[my_child_num].status == CHILD_STATUS_READY) {
CHILD_INFO_TABLE[my_child_num].status = CHILD_STATUS_ACTIVE;
+ CHILD_INFO_TABLE[my_child_num].senv->idle_processors--;
_DBG("Child %d (%s) is now active", my_child_num,
child_type_string(CHILD_INFO_TABLE[my_child_num].type));
}
@@ -2083,23 +2168,25 @@
_DBG("CHECKING IF WE SHOULD CLONE A CHILD...");
+ update_single_processor_counters(my_child_num);
+
_DBG("total_processors = %d, max_processors = %d",
- total_processors(my_child_num),
+ CHILD_INFO_TABLE[my_child_num].senv->total_processors,
CHILD_INFO_TABLE[my_child_num].senv->max_processors);
_DBG("idle_processors = %d, min_free_processors = %d",
- idle_processors(my_child_num),
+ CHILD_INFO_TABLE[my_child_num].senv->idle_processors,
CHILD_INFO_TABLE[my_child_num].senv->min_free_processors);
- if (total_processors(my_child_num)
+ if (CHILD_INFO_TABLE[my_child_num].senv->total_processors
< CHILD_INFO_TABLE[my_child_num].senv->max_processors
- && (idle_processors(my_child_num)
+ && (CHILD_INFO_TABLE[my_child_num].senv->idle_processors
<= CHILD_INFO_TABLE[my_child_num].senv->min_free_processors
- || total_processors(my_child_num)
+ || CHILD_INFO_TABLE[my_child_num].senv->total_processors
< CHILD_INFO_TABLE[my_child_num].senv->min_processors)) {
_DBG("CLONING CHILD");
- child_clone();
+ child_clone(-1); // -1 => this child
}
}
@@ -2221,19 +2308,33 @@
SENV[NUM_SENV].input = socks[0];
SENV[NUM_SENV].output = socks[1];
+ _DBG("New senv id %d", NUM_SENV);
+ SENV[NUM_SENV].id = NUM_SENV;
+
senv = &SENV[NUM_SENV];
return &SENV[server_env_image->control->num++];
}
-static const char* child_clone()
+static void child_clone(int child_num)
{
- int i;
+ int i, child_to_clone;
child_info_t *this;
child_info_t *new;
+ int start = 0;
- for (i = 0; i < NUM_CHILDS; i++) {
+ if (child_num == -1)
+ child_to_clone = my_child_num;
+ else
+ child_to_clone = child_num;
+
+ /* Why search from 0 index? */
+ if (!is_graceful)
+ start = (NUM_SENV - 1);
+
+ for (i = start; i < NUM_CHILDS; i++) {
if (CHILD_INFO_TABLE[i].pid == 0
&& CHILD_INFO_TABLE[i].type == CHILD_TYPE_UNKNOWN) {
+ CHILD_INFO_TABLE[i].type = CHILD_TYPE_RESERVED;
break;
}
}
@@ -2241,12 +2342,12 @@
if (i == NUM_CHILDS && NUM_CHILDS >= server_limit) {
_DBG("Trying to use more child ID's than ServerLimit. "
"Increase ServerLimit in your config file.");
- return NULL;
+ return;
}
- _DBG("cloning child #%d from #%d", i, my_child_num);
+ _DBG("cloning child #%d from #%d", i, child_to_clone);
- this = &CHILD_INFO_TABLE[my_child_num];
+ this = &CHILD_INFO_TABLE[child_to_clone];
new = &CHILD_INFO_TABLE[i];
new->senv = this->senv;
@@ -2260,12 +2361,16 @@
new->sock_fd = this->sock_fd;
new->status = CHILD_STATUS_STARTING;
+ if (child_num == -1) child_info_image->control->new = 1;
+ new->senv->total_processors++;
+ new->senv->idle_processors++;
+ new->senv->total_processes++;
if (i == NUM_CHILDS) {
child_info_image->control->num++;
}
- return NULL;
+ return;
}
static const char* child_add(int type, int status, apr_pool_t *pool,
@@ -2273,9 +2378,16 @@
{
int i;
+ if (senv->chroot && !ap_is_directory(pool, senv->chroot)) {
+ return apr_psprintf(pool,
+ "Error: chroot directory [%s] does not exist",
+ senv->chroot);
+ }
+
for (i = 0; i < NUM_CHILDS; i++) {
if (CHILD_INFO_TABLE[i].pid == 0
&& CHILD_INFO_TABLE[i].type == CHILD_TYPE_UNKNOWN) {
+ CHILD_INFO_TABLE[i].type = CHILD_TYPE_RESERVED;
break;
}
}
@@ -2287,15 +2399,11 @@
"Increase ServerLimit in your config file.";
}
- if (senv->chroot && !ap_is_directory(pool, senv->chroot)) {
- return apr_psprintf(pool,
- "Error: chroot directory [%s] does not exist",
- senv->chroot);
- }
-
CHILD_INFO_TABLE[i].senv = senv_add(senv);
if (CHILD_INFO_TABLE[i].senv == NULL) {
+ // Changing back to UNKNOWN type
+ CHILD_INFO_TABLE[i].type = CHILD_TYPE_UNKNOWN;
return "Trying to use more server environments than ServerLimit. "
"Increase ServerLimit in your config file.";
}
@@ -2416,6 +2524,7 @@
ap_scoreboard_image->parent[slot].pid = pid;
CHILD_INFO_TABLE[slot].pid = pid;
+ CHILD_INFO_TABLE[slot].senv->active_processors++;
return 0;
}
@@ -2430,26 +2539,14 @@
#ifndef MAX_SPAWN_RATE
#define MAX_SPAWN_RATE (32)
#endif
-static int total_processes(int child_num)
-{
- int i, total;
-
- for (i = 0, total = 0; i < NUM_CHILDS; ++i) {
- if (CHILD_INFO_TABLE[i].senv == CHILD_INFO_TABLE[child_num].senv
- && CHILD_INFO_TABLE[i].status != CHILD_STATUS_STANDBY) {
- total++;
- }
- }
-
- return total;
-}
-static int determine_child_fate(int childnum, child_info_t *child,
+static inline int determine_child_fate(int childnum, child_info_t *child,
worker_score *child_sb, apr_time_t now)
{
time_t idle_time = apr_time_sec(now - child_sb->last_used);
- if (total_processes(childnum) <= child->senv->min_processors) {
+ if (child->senv->min_processors > 0 &&
+ child->senv->total_processes <= child->senv->min_processors) {
/* We will not kill a child, if the senv needs live workers */
return 0;
}
@@ -2457,8 +2554,15 @@
if (child->type == CHILD_TYPE_PROCESSOR ||
child->type == CHILD_TYPE_WORKER) {
- if (idle_processors(childnum) <= child->senv->min_free_processors ||
- child->senv->min_free_processors == 0) {
+ /*
+ If MinProcessors AND MinSpareProcessors are set to a positive
+ value, server will keep idle processors, regardless IdleTimeout
+ configuration, but if MinProcessors is 0, server will keep idle
+ processors UNTIL IdleTimeout.
+ */
+ if (child->senv->min_processors > 0 &&
+ child->senv->min_free_processors > 0 &&
+ child->senv->idle_processors <= child->senv->min_free_processors) {
/* We will not kill a child, if the senv needs idle workers */
return 0;
}
@@ -2477,7 +2581,7 @@
}
if (child->senv->max_free_processors > 0
- && idle_processors(childnum) >= child->senv->max_free_processors) {
+ && child->senv->idle_processors >= child->senv->max_free_processors) {
/* Too many spare workers available */
_DBG("Too many spare workers for processor %s, stopping child #%d",
child->senv->name, childnum);
@@ -2495,9 +2599,19 @@
return 0;
}
+static void create_new_childs()
+{
+ int i;
+
+ for (i = 0; i < NUM_CHILDS; ++i) {
+ if (CHILD_INFO_TABLE[i].status == CHILD_STATUS_STARTING)
+ make_child(ap_server_conf, i);
+ }
+}
+
static void perform_idle_server_maintenance(apr_pool_t *p)
{
- int i, stop_child;
+ int i, stop_child, retval;
time_t idle_time;
child_info_t *child;
worker_score *child_sb;
@@ -2505,6 +2619,8 @@
now = apr_time_now();
+ update_all_counters();
+
for (i = 0; i < NUM_CHILDS; ++i) {
child = &CHILD_INFO_TABLE[i];
child_sb = &ap_scoreboard_image->servers[i][0];
@@ -2514,6 +2630,29 @@
}
if (child->pid == 0) {
+
+ /* If some child unexpectedly dies, we should free this child */
+ if (child->type > CHILD_TYPE_UNKNOWN &&
+ (child->status == CHILD_STATUS_ACTIVE || child->status == CHILD_STATUS_READY)
+ && child_sb->status == SERVER_DEAD) {
+ _DBG("Something is wrong with child #%d", child->id);
+ if (child->type != CHILD_TYPE_MULTIPLEXER && child->senv) {
+ retval = close(child->senv->input);
+ _DBG("close(CHILD_INFO_TABLE[%d].senv->input) = %d",
+ i, retval);
+ retval = close(child->senv->output);
+ _DBG("close(CHILD_INFO_TABLE[%d].senv->output) = %d",
+ i, retval);
+ }
+ if (child->type != CHILD_TYPE_PROCESSOR) {
+ /* completely free up this slot */
+ child->senv = (server_env_t*) NULL;
+ child->type = CHILD_TYPE_UNKNOWN;
+ child->sock_fd = -3; /* -1 and -2 are taken */
+ }
+ child->status = CHILD_STATUS_STANDBY;
+ }
+
if (child->status == CHILD_STATUS_STARTING) {
make_child(ap_server_conf, i);
}
@@ -2526,6 +2665,15 @@
}
if (determine_child_fate(i, child, child_sb, now) == 1) {
+ /* updating counters */
+ if (child->status == CHILD_STATUS_READY)
+ child->senv->idle_processors--;
+ if (child->pid > 0)
+ child->senv->active_processors--;
+ if (child->status != CHILD_STATUS_STANDBY)
+ child->senv->total_processes--;
+ child->senv->total_processors--;
+
child->status = CHILD_STATUS_STANDBY;
if (kill(ap_scoreboard_image->parent[i].pid, SIGTERM) == -1) {
@@ -2710,7 +2858,7 @@
}
else if (child_slot < ap_daemons_limit
&& CHILD_INFO_TABLE[child_slot].type
- != CHILD_TYPE_UNKNOWN)
+ > CHILD_TYPE_UNKNOWN)
{
/* we're still doing a 1-for-1 replacement of dead
* children with new children
@@ -2742,9 +2890,20 @@
* finite number of children can die, and it's pretty
* pathological for a lot to die suddenly.
*/
+ if (child_info_image->control->new) {
+ child_info_image->control->new = 0;
+ create_new_childs();
+ }
continue;
}
+ for (i = 0; i < 20; ++i) {
+ if (child_info_image->control->new) {
+ child_info_image->control->new = 0;
+ create_new_childs();
+ }
+ apr_sleep(SCOREBOARD_MAINTENANCE_INTERVAL / 20);
+ }
perform_idle_server_maintenance(pconf);
#ifdef TPF
@@ -2947,10 +3106,15 @@
unixd_pre_config(ptemp);
ap_listen_pre_config();
+ ap_start_processors = DEFAULT_START_PROCESSORS;
+ if (ap_start_processors < 1) ap_start_processors = 1;
ap_min_processors = DEFAULT_MIN_PROCESSORS;
ap_min_free_processors = DEFAULT_MIN_FREE_PROCESSORS;
ap_max_free_processors = DEFAULT_MAX_FREE_PROCESSORS;
ap_max_processors = DEFAULT_MAX_PROCESSORS;
+ if (ap_max_processors < 1) ap_max_processors = 1;
+ if (ap_start_processors > ap_max_processors)
+ ap_start_processors = ap_max_processors;
ap_min_multiplexers = DEFAULT_MIN_MULTIPLEXERS;
ap_max_multiplexers = DEFAULT_MAX_MULTIPLEXERS;
ap_daemons_limit = server_limit;
@@ -3112,16 +3276,37 @@
senv.stats_connections = 0;
senv.stats_requests = 0;
senv.stats_dropped = 0;
+ senv.total_processors = 0;
+ senv.idle_processors = 0;
+ senv.active_processors = 0;
+ senv.total_processes = 0;
+ senv.start_processors = ap_start_processors;
senv.min_processors = ap_min_multiplexers;
senv.min_free_processors = ap_min_free_processors;
senv.max_free_processors = ap_max_free_processors;
senv.max_processors = ap_max_multiplexers;
+ if (senv.start_processors > senv.max_processors)
+ senv.start_processors = senv.max_processors;
+
r = child_add(CHILD_TYPE_MULTIPLEXER, CHILD_STATUS_STARTING, p,
&senv);
- if (r != NULL) {
+ if (r == NULL) {
+ if (multiplexer_senv != NULL) {
+ /* first multiplexer */
+ multiplexer_senv->total_processors++;
+ multiplexer_senv->idle_processors++;
+ multiplexer_senv->total_processes++;
+ if (multiplexer_senv->start_processors > 1) {
+ int x;
+ for (x = 1; x < multiplexer_senv->start_processors; ++x)
+ child_clone(multiplexer_senv->processor_id);
+ }
+ child_info_image->control->new = 1;
+ }
+ } else {
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, r);
return -1;
}
@@ -3187,6 +3372,13 @@
if (processor->status == CHILD_STATUS_STANDBY) {
_DBG("Activating child #%d", processor->id);
processor->status = CHILD_STATUS_STARTING;
+ if (processor->senv->start_processors > 1) {
+ int x;
+ for (x = 1; x < processor->senv->start_processors; ++x)
+ child_clone(processor->id);
+ }
+ child_info_image->control->new = 1;
+ _DBG("New processor %s started", processor->senv->name);
}
_DBG("Passing request.",0);
@@ -3346,7 +3538,7 @@
qsort(sorted_senv, NUM_SENV, sizeof(int), senv_active_cmp);
ap_rputs("
Processors statistics:
"
- "Environment | Pss | "
+ "ID | Environment | Pss | "
"Connections | Requests | Dropped (503) | "
"Avail |
", r);
@@ -3358,11 +3550,12 @@
continue;
}
- ap_rprintf(r, "%s | %d/%d/%d | "
+ ap_rprintf(r, "
%d | %s | %d/%d/%d | "
"%d | %d | %d | %d%% |
",
+ senv->id,
senv->name == NULL ? "" : senv->name,
active_env_processors(sorted_senv[x]),
- idle_env_processors(sorted_senv[x]),
+ senv->idle_processors,
senv->max_processors, senv->stats_connections,
senv->stats_requests, senv->stats_dropped,
senv->availability);
@@ -3394,8 +3587,8 @@
child_type_string(child->type),
senv == NULL ? NULL : (senv->name == NULL ? "" :
senv->name),
- active_processors(x),
- idle_processors(x),
+ senv == NULL ? 0 : senv->active_processors,
+ senv == NULL ? 0 : senv->idle_processors,
senv == NULL ? 0 : senv->max_processors,
senv == NULL ? 0 : senv->availability);
}
@@ -3447,15 +3640,22 @@
senv->nice_lvl = 0;
senv->chroot = NULL;
senv->cgroup = NULL;
+ senv->start_processors = ap_start_processors;
senv->min_processors = ap_min_processors;
senv->min_free_processors = ap_min_free_processors;
senv->max_free_processors = ap_max_free_processors;
senv->max_processors = ap_max_processors;
+ if (senv->start_processors > senv->max_processors)
+ senv->start_processors = senv->max_processors;
senv->error_cgroup = 0;
senv->error_pass = 0;
senv->stats_connections = 0;
senv->stats_requests = 0;
senv->stats_dropped = 0;
+ senv->total_processors = 0;
+ senv->idle_processors = 0;
+ senv->active_processors = 0;
+ senv->total_processes = 0;
}
static const char *cf_Processor(cmd_parms *cmd, void *dummy, const char *arg)
@@ -3540,6 +3740,18 @@
senv.min_processors = proc_temp;
}
+ else if (!strcasecmp(directive, "startprocessors")) {
+ proc_temp = atoi(current->args);
+
+ if (proc_temp < 1) {
+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
+ "WARNING: Require StartProcessors > 0,"
+ "setting to 1");
+ proc_temp = 1;
+ }
+
+ senv.start_processors = proc_temp;
+ }
else if (!strcasecmp(directive, "minspareprocessors")) {
proc_temp = atoi(current->args);
@@ -3587,8 +3799,8 @@
senv.name, user_name, senv.uid, group_name, senv.gid, senv.chroot,
senv.nice_lvl);
- _DBG("min_processors=%d min_free_processors=%d max_spare_processors=%d "
- "max_processors=%d", senv.min_processors, senv.min_free_processors,
+ _DBG("start_processors=%d min_processors=%d min_free_processors=%d max_spare_processors=%d "
+ "max_processors=%d", senv.start_processors, senv.min_processors, senv.min_free_processors,
senv.max_free_processors, senv.max_processors);
return child_add(CHILD_TYPE_PROCESSOR, CHILD_STATUS_STANDBY, cmd->pool,
@@ -3754,6 +3966,43 @@
return NULL;
}
+static const char *set_start_processors(cmd_parms *cmd, void *dummy,
+ const char *arg)
+{
+ peruser_server_conf *sconf;
+ int start_procs;
+ const char *err = ap_check_cmd_context(cmd, NOT_IN_DIR_LOC_FILE
+ | NOT_IN_LIMIT);
+
+ if (err != NULL) {
+ return err;
+ }
+
+ start_procs = atoi(arg);
+
+ if (start_procs < 1) {
+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
+ "WARNING: Require StartProcessors > 0, setting to 1");
+ start_procs = 1;
+ }
+
+ if (ap_check_cmd_context(cmd, NOT_IN_VIRTUALHOST) != NULL) {
+ sconf = PERUSER_SERVER_CONF(cmd->server->module_config);
+
+ if (sconf->senv != NULL) {
+ sconf->senv->start_processors = start_procs;
+ } else {
+ ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL,
+ "WARNING: StartProcessors must be set"
+ "after ServerEnvironment to take effect");
+ }
+ } else {
+ ap_start_processors = start_procs;
+ }
+
+ return NULL;
+}
+
static const char *set_min_processors(cmd_parms *cmd, void *dummy,
const char *arg)
{
@@ -4068,6 +4317,8 @@
"Maximum number of idle children, 0 to disable"),
AP_INIT_TAKE1("MaxClients", set_max_clients, NULL, RSRC_CONF,
"Maximum number of children alive at the same time"),
+AP_INIT_TAKE1("StartProcessors", set_start_processors, NULL, RSRC_CONF,
+ "Number of child processors per vhost at startup"),
AP_INIT_TAKE1("MinProcessors", set_min_processors, NULL, RSRC_CONF,
"Minimum number of processors per vhost"),
AP_INIT_TAKE1("MaxProcessors", set_max_processors, NULL, RSRC_CONF,
---|