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:

" - "" + "
EnvironmentPss
" "" "", r); @@ -3358,11 +3424,12 @@ continue; } - ap_rprintf(r, "" + ap_rprintf(r, "" "", + 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)
IDEnvironmentPssConnectionsRequestsDropped (503)Avail
%s%d/%d/%d
%d%s%d/%d/%d%d%d%d%d%%