diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c
index 8177972d9d..10a728b32b 100644
--- a/modules/proxy/mod_proxy.c
+++ b/modules/proxy/mod_proxy.c
@@ -189,11 +189,15 @@ static const char *set_worker_param(apr_pool_t *p,
else if (!strcasecmp(key, "route")) {
/* Worker route.
*/
+ if (strlen(val) > PROXY_WORKER_MAX_ROUTE_SIZ)
+ return "Route length must be < 64 characters";
worker->route = apr_pstrdup(p, val);
}
else if (!strcasecmp(key, "redirect")) {
/* Worker redirection route.
*/
+ if (strlen(val) > PROXY_WORKER_MAX_ROUTE_SIZ)
+ return "Redirect length must be < 64 characters";
worker->redirect = apr_pstrdup(p, val);
}
else {
@@ -1194,9 +1198,6 @@ static const char *
psf->forward->name = "proxy:forward";
psf->forward->hostname = "*";
psf->forward->scheme = "*";
-
- /* Do not disable worker in case of errors */
- psf->forward->status = PROXY_WORKER_IGNORE_ERRORS;
}
return NULL;
}
@@ -1663,24 +1664,10 @@ PROXY_DECLARE(int) ap_proxy_ssl_disable(conn_rec *c)
static int proxy_post_config(apr_pool_t *pconf, apr_pool_t *plog,
apr_pool_t *ptemp, server_rec *s)
{
- proxy_server_conf *conf =
- (proxy_server_conf *) ap_get_module_config(s->module_config, &proxy_module);
- proxy_worker *worker;
- int i;
proxy_ssl_enable = APR_RETRIEVE_OPTIONAL_FN(ssl_proxy_enable);
proxy_ssl_disable = APR_RETRIEVE_OPTIONAL_FN(ssl_engine_disable);
- /* Initialize workers */
- worker = (proxy_worker *)conf->workers->elts;
- for (i = 0; i < conf->workers->nelts; i++) {
- ap_proxy_initialize_worker(worker, s);
- worker++;
- }
- /* Initialize forward worker if defined */
- if (conf->forward)
- ap_proxy_initialize_worker(conf->forward, s);
-
return OK;
}
@@ -1713,7 +1700,7 @@ static int proxy_status_hook(request_rec *r, int flags)
proxy_server_conf *conf = (proxy_server_conf *)
ap_get_module_config(sconf, &proxy_module);
proxy_balancer *balancer = NULL;
- proxy_runtime_worker *worker = NULL;
+ proxy_worker *worker = NULL;
if (flags & AP_STATUS_SHORT || conf->balancers->nelts == 0 ||
conf->proxy_status == status_off)
@@ -1736,26 +1723,26 @@ static int proxy_status_hook(request_rec *r, int flags)
"
F | Acc | Wr | Rd | "
"\n", r);
- worker = (proxy_runtime_worker *)balancer->workers->elts;
+ worker = (proxy_worker *)balancer->workers->elts;
for (n = 0; n < balancer->workers->nelts; n++) {
- ap_rvputs(r, "\n", worker->w->scheme, " | ", NULL);
- ap_rvputs(r, "", worker->w->hostname, " | ", NULL);
- if (worker->w->status & PROXY_WORKER_DISABLED)
+ ap_rvputs(r, " |
\n", worker->scheme, " | ", NULL);
+ ap_rvputs(r, "", worker->hostname, " | ", NULL);
+ if (worker->s->status & PROXY_WORKER_DISABLED)
ap_rputs("Dis", r);
- else if (worker->w->status & PROXY_WORKER_IN_ERROR)
+ else if (worker->s->status & PROXY_WORKER_IN_ERROR)
ap_rputs("Err", r);
- else if (worker->w->status & PROXY_WORKER_INITIALIZED)
+ else if (worker->s->status & PROXY_WORKER_INITIALIZED)
ap_rputs("Ok", r);
else
ap_rputs("-", r);
- ap_rvputs(r, " | ", worker->w->route, NULL);
- ap_rvputs(r, " | ", worker->w->redirect, NULL);
- ap_rprintf(r, " | %.2f | ", worker->s->lbfactor);
+ ap_rvputs(r, "", worker->s->route, NULL);
+ ap_rvputs(r, " | ", worker->s->redirect, NULL);
+ ap_rprintf(r, " | %d | ", worker->s->lbfactor);
ap_rprintf(r, "%d | ", (int)(worker->s->elected));
format_byte_out(r, worker->s->transfered);
ap_rputs(" | ", r);
- format_byte_out(r, worker->s->transfered);
+ format_byte_out(r, worker->s->readed);
ap_rputs(" | \n", r);
/* TODO: Add the rest of dynamic worker data */
@@ -1783,6 +1770,31 @@ static int proxy_status_hook(request_rec *r, int flags)
return OK;
}
+static void child_init(apr_pool_t *p, server_rec *s)
+{
+ void *sconf = s->module_config;
+ proxy_server_conf *conf = (proxy_server_conf *)
+ ap_get_module_config(sconf, &proxy_module);
+ proxy_worker *worker;
+ int i;
+
+ /* Initialize worker's shared scoreboard data */
+ worker = (proxy_worker *)conf->workers->elts;
+ for (i = 0; i < conf->workers->nelts; i++) {
+ ap_proxy_initialize_worker_share(conf, worker);
+ ap_proxy_initialize_worker(worker, s);
+ worker++;
+ }
+ /* Initialize forward worker if defined */
+ if (conf->forward) {
+ ap_proxy_initialize_worker_share(conf, conf->forward);
+ ap_proxy_initialize_worker(conf->forward, s);
+ /* Do not disable worker in case of errors */
+ conf->forward->s->status |= PROXY_WORKER_IGNORE_ERRORS;
+ }
+
+}
+
/*
* This routine is called before the server processes the configuration
* files. There is no return value.
@@ -1803,6 +1815,11 @@ static void register_hooks(apr_pool_t *p)
#ifndef FIX_15207
static const char * const aszSucc[]={ "mod_rewrite.c", NULL };
#endif
+ /* Only the mpm_winnt has child init hook handler.
+ * make sure that we are called after the mpm
+ * initializes.
+ */
+ static const char *const aszPred[] = { "mpm_winnt.c", NULL};
APR_REGISTER_OPTIONAL_FN(ap_proxy_lb_workers);
/* handler */
@@ -1821,6 +1838,9 @@ static void register_hooks(apr_pool_t *p)
ap_hook_pre_config(proxy_pre_config, NULL, NULL, APR_HOOK_MIDDLE);
/* post config handling */
ap_hook_post_config(proxy_post_config, NULL, NULL, APR_HOOK_MIDDLE);
+ /* child init handling */
+ ap_hook_child_init(child_init, aszPred, NULL, APR_HOOK_MIDDLE);
+
}
module AP_MODULE_DECLARE_DATA proxy_module =
diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h
index b9273314a8..a510d2e8d3 100644
--- a/modules/proxy/mod_proxy.h
+++ b/modules/proxy/mod_proxy.h
@@ -218,7 +218,6 @@ struct proxy_conn_pool {
#if APR_HAS_THREADS
apr_reslist_t *res; /* Connection resource list */
#endif
- int nfree; /* Balancer free count number */
proxy_conn_rec *conn; /* Single connection for prefork mpm's */
};
@@ -229,17 +228,30 @@ struct proxy_conn_pool {
#define PROXY_WORKER_DISABLED 0x0020
#define PROXY_WORKER_IN_ERROR 0x0040
-#define PROXY_WORKER_IS_USABLE(f) (!((f)->status & 0x00F0))
+#define PROXY_WORKER_IS_USABLE(f) (!((f)->s->status & 0x00F0))
/* default worker retry timeout in seconds */
#define PROXY_WORKER_DEFAULT_RETRY 60
+#define PROXY_WORKER_MAX_ROUTE_SIZ 63
+
+/* Runtime worker status informations. Shared in scoreboard */
+typedef struct {
+ int status;
+ apr_time_t error_time; /* time of the last error */
+ int retries; /* number of retries on this worker */
+ int lbstatus; /* Current lbstatus */
+ int lbfactor; /* dynamic lbfactor */
+ apr_off_t transfered; /* Number of bytes transfered to remote */
+ apr_off_t readed; /* Number of bytes readed from remote */
+ apr_size_t elected; /* Number of times the worker was elected */
+ char route[PROXY_WORKER_MAX_ROUTE_SIZ+1];
+ char redirect[PROXY_WORKER_MAX_ROUTE_SIZ+1];
+} proxy_worker_stat;
/* Worker configuration */
struct proxy_worker {
- int status;
- apr_time_t error_time; /* time of the last error */
+ int id; /* scoreboard id */
apr_interval_time_t retry; /* retry interval */
- int retries; /* number of retries on this worker */
int lbfactor; /* initial load balancing factor */
const char *name;
const char *scheme; /* scheme to use ajp|http|https */
@@ -262,29 +274,13 @@ struct proxy_worker {
char io_buffer_size_set;
char keepalive;
char keepalive_set;
- proxy_conn_pool *cp; /* Connection pool to use */
- void *opaque; /* per scheme worker data */
+ proxy_conn_pool *cp; /* Connection pool to use */
+ proxy_worker_stat *s; /* Shared data */
+ void *opaque; /* per scheme worker data */
};
-/* Runtime worker status informations. Shared in scoreboard */
-typedef struct {
- double lbstatus; /* Current lbstatus */
- double lbfactor; /* dynamic lbfactor */
- apr_size_t transfered; /* Number of bytes transfered to remote */
- apr_size_t readed; /* Number of bytes readed from remote */
- apr_size_t elected; /* Number of times the worker was elected */
-} proxy_runtime_stat;
-
-/* Runtime worker. */
-typedef struct {
- int id; /* scoreboard id */
- proxy_balancer *b; /* balancer containing this worker */
- proxy_worker *w;
- proxy_runtime_stat *s;
-} proxy_runtime_worker;
-
struct proxy_balancer {
- apr_array_header_t *workers; /* array of proxy_runtime_workers */
+ apr_array_header_t *workers; /* array of proxy_workers */
const char *name; /* name of the load balancer */
const char *sticky; /* sticky session identifier */
int sticky_force; /* Disable failover for sticky sessions */
@@ -421,9 +417,19 @@ PROXY_DECLARE(const char *) ap_proxy_add_worker(proxy_worker **worker,
*/
PROXY_DECLARE(proxy_worker *) ap_proxy_create_worker(apr_pool_t *p);
+/**
+ * Initize the worker's shared data
+ * @param conf current proxy server configuration
+ * @param s current server record
+ * @param worker worker to initialize
+ */
+PROXY_DECLARE(void) ap_proxy_initialize_worker_share(proxy_server_conf *conf,
+ proxy_worker *worker);
+
+
/**
* Initize the worker
- * @param worker the new worker
+ * @param worker worker to initialize
* @param p memory pool to allocate worker from
* @param s current server record
* @return APR_SUCCESS or error code
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
index 32a47c462f..b82c979602 100644
--- a/modules/proxy/proxy_util.c
+++ b/modules/proxy/proxy_util.c
@@ -16,6 +16,7 @@
/* Utility routines for Apache proxy */
#include "mod_proxy.h"
#include "ap_mpm.h"
+#include "scoreboard.h"
#include "apr_version.h"
#if APR_HAVE_UNISTD_H
@@ -1038,7 +1039,7 @@ PROXY_DECLARE(const char *) ap_proxy_add_balancer(proxy_balancer **balancer,
memset(*balancer, 0, sizeof(proxy_balancer));
(*balancer)->name = uri;
- (*balancer)->workers = apr_array_make(p, 5, sizeof(proxy_runtime_worker));
+ (*balancer)->workers = apr_array_make(p, 5, sizeof(proxy_worker));
/* XXX Is this a right place to create mutex */
#if APR_HAS_THREADS
if (apr_thread_mutex_create(&((*balancer)->mutex),
@@ -1141,7 +1142,9 @@ PROXY_DECLARE(const char *) ap_proxy_add_worker(proxy_worker **worker,
if (port == -1)
port = apr_uri_port_of_scheme((*worker)->scheme);
(*worker)->port = port;
-
+ (*worker)->id = lb_workers;
+ /* Increase the total worker count */
+ ++lb_workers;
init_conn_pool(p, *worker);
return NULL;
@@ -1152,15 +1155,19 @@ PROXY_DECLARE(proxy_worker *) ap_proxy_create_worker(apr_pool_t *p)
proxy_worker *worker;
worker = (proxy_worker *)apr_pcalloc(p, sizeof(proxy_worker));
+ worker->id = lb_workers;
+ /* Increase the total worker count */
+ ++lb_workers;
init_conn_pool(p, worker);
return worker;
}
PROXY_DECLARE(void)
-ap_proxy_add_worker_to_balancer(apr_pool_t *pool, proxy_balancer *balancer, proxy_worker *worker)
+ap_proxy_add_worker_to_balancer(apr_pool_t *pool, proxy_balancer *balancer,
+ proxy_worker *worker)
{
- proxy_runtime_worker *runtime;
+ proxy_worker *runtime;
#if PROXY_HAS_SCOREBOARD
int mpm_daemons;
@@ -1179,10 +1186,8 @@ ap_proxy_add_worker_to_balancer(apr_pool_t *pool, proxy_balancer *balancer, prox
}
#endif
runtime = apr_array_push(balancer->workers);
- runtime->w = worker;
- runtime->b = balancer;
+ memcpy(runtime, worker, sizeof(proxy_worker));
runtime->id = lb_workers;
- runtime->s = NULL;
/* Increase the total runtime count */
++lb_workers;
@@ -1374,6 +1379,28 @@ static apr_status_t connection_destructor(void *resource, void *params,
return APR_SUCCESS;
}
+PROXY_DECLARE(void) ap_proxy_initialize_worker_share(proxy_server_conf *conf,
+ proxy_worker *worker)
+{
+#if PROXY_HAS_SCOREBOARD
+ lb_score *score = NULL;
+#else
+ void *score = NULL;
+#endif
+#if PROXY_HAS_SCOREBOARD
+ /* Get scoreboard slot */
+ if (ap_scoreboard_image)
+ score = ap_get_scoreboard_lb(worker->id);
+#endif
+ if (!score)
+ score = apr_pcalloc(conf->pool, sizeof(proxy_worker_stat));
+ worker->s = (proxy_worker_stat *)score;
+ if (worker->route)
+ strcpy(worker->s->route, worker->route);
+ if (worker->redirect)
+ strcpy(worker->s->redirect, worker->redirect);
+}
+
PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker, server_rec *s)
{
apr_status_t rv;
@@ -1391,7 +1418,6 @@ PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker, ser
/* Set min to be lower then smax */
if (worker->min > worker->smax)
worker->min = worker->smax;
- worker->cp->nfree = worker->hmax;
}
else {
/* This will supress the apr_reslist creation */
@@ -1428,7 +1454,7 @@ PROXY_DECLARE(apr_status_t) ap_proxy_initialize_worker(proxy_worker *worker, ser
worker->hostname);
}
if (rv == APR_SUCCESS)
- worker->status |= PROXY_WORKER_INITIALIZED;
+ worker->s->status |= PROXY_WORKER_INITIALIZED;
/* Set default parameters */
if (!worker->retry)
worker->retry = apr_time_from_sec(PROXY_WORKER_DEFAULT_RETRY);
@@ -1439,13 +1465,13 @@ PROXY_DECLARE(int) ap_proxy_retry_worker(const char *proxy_function,
proxy_worker *worker,
server_rec *s)
{
- if (worker->status & PROXY_WORKER_IN_ERROR) {
+ if (worker->s->status & PROXY_WORKER_IN_ERROR) {
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
"proxy: %s: retrying the worker for (%s)",
proxy_function, worker->hostname);
- if (apr_time_now() > worker->error_time + worker->retry) {
- ++worker->retries;
- worker->status &= ~PROXY_WORKER_IN_ERROR;
+ if (apr_time_now() > worker->s->error_time + worker->retry) {
+ ++worker->s->retries;
+ worker->s->status &= ~PROXY_WORKER_IN_ERROR;
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
"proxy: %s: worker for (%s) has been marked for retry",
proxy_function, worker->hostname);
@@ -1739,16 +1765,16 @@ PROXY_DECLARE(int) ap_proxy_connect_backend(const char *proxy_function,
* no further connections to the worker could be made
*/
if (!connected && PROXY_WORKER_IS_USABLE(worker) &&
- !(worker->status & PROXY_WORKER_IGNORE_ERRORS)) {
- worker->status |= PROXY_WORKER_IN_ERROR;
- worker->error_time = apr_time_now();
+ !(worker->s->status & PROXY_WORKER_IGNORE_ERRORS)) {
+ worker->s->status |= PROXY_WORKER_IN_ERROR;
+ worker->s->error_time = apr_time_now();
ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
"ap_proxy_connect_backend disabling worker for (%s)",
worker->hostname);
}
else {
- worker->error_time = 0;
- worker->retries = 0;
+ worker->s->error_time = 0;
+ worker->s->retries = 0;
}
return connected ? OK : DECLINED;
}