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 2010-12-28 17:19:19.000000000 -0200
@@ -227,6 +227,7 @@
typedef struct
{
+ int id;
int processor_id;
const char *name; /* Server environment's unique string identifier */
@@ -258,6 +259,11 @@
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;
} server_env_t;
typedef struct
@@ -897,78 +903,90 @@
return 0;
}
-static int total_processors(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)
- total++;
- }
-
- return total;
-}
-
-static int active_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
- && CHILD_INFO_TABLE[i].pid > 0) {
- total++;
- }
+ if (env_num >= NUM_SENV) {
+ return -1;
}
-
- return total;
+ return SENV[env_num].active_processors;
}
-static int active_env_processors(int env_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;
- 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++;
+ /* 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++;
}
}
- return 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;
+
+ return;
}
-static int idle_processors(int child_num)
+static void update_all_counters()
{
- int i, total;
+ int i, tmp_id;
+ int *tmp_total_processors;
+ int *tmp_idle_processors;
+ int *tmp_active_processors;
- 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;
-}
+ _DBG("function entered", 0);
-static int idle_env_processors(int env_num)
-{
- int i, 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));
+
+ /* resetting counters */
+ for (i = 0; i < NUM_SENV; ++i) {
+ tmp_total_processors[i] = 0;
+ tmp_idle_processors[i] = 0;
+ tmp_active_processors[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]++;
}
}
- 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];
+ }
+
+ /* free-up resources */
+ free(tmp_total_processors);
+ free(tmp_idle_processors);
+ free(tmp_active_processors);
+
+ return;
}
static int wait_for_workers(child_info_t *processor)
@@ -978,8 +996,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");
@@ -1006,9 +1025,10 @@
usleep(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");
@@ -2083,19 +2103,21 @@
_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");
@@ -2221,6 +2243,9 @@
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++];
}
@@ -2230,8 +2255,13 @@
int i;
child_info_t *this;
child_info_t *new;
+ int start = 0;
- for (i = 0; i < NUM_CHILDS; i++) {
+ /* 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) {
break;
@@ -2449,7 +2479,8 @@
{
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_processors <= child->senv->min_processors) {
/* We will not kill a child, if the senv needs live workers */
return 0;
}
@@ -2457,12 +2488,6 @@
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) {
- /* We will not kill a child, if the senv needs idle workers */
- return 0;
- }
-
if (expire_timeout > 0 && idle_time > expire_timeout) {
/* Child has not handled a request for some time now, stop it */
_DBG("Expire timeout reached for child #%d", childnum);
@@ -2476,8 +2501,14 @@
return 1;
}
+ if (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;
+ }
+
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);
@@ -2497,7 +2528,7 @@
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 +2536,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 +2547,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 +2582,13 @@
}
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--;
+ child->senv->total_processors--;
+
child->status = CHILD_STATUS_STANDBY;
if (kill(ap_scoreboard_image->parent[i].pid, SIGTERM) == -1) {
@@ -3327,6 +3390,9 @@
return OK;
}
+ /* counting processors */
+ update_all_counters();
+
if (flags & AP_STATUS_PERUSER_STATS) {
int *sorted_senv;
int i;
@@ -3346,7 +3412,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 +3424,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 +3461,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);
}
@@ -3456,6 +3523,9 @@
senv->stats_connections = 0;
senv->stats_requests = 0;
senv->stats_dropped = 0;
+ senv->total_processors = 0;
+ senv->idle_processors = 0;
+ senv->active_processors = 0;
}
static const char *cf_Processor(cmd_parms *cmd, void *dummy, const char *arg)
---|