diff --git a/CHANGES b/CHANGES
index 5cc374d3a7..5f5da5276f 100644
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,10 @@
Changes with Apache 2.3.0
[Remove entries to the current 2.0 and 2.2 section below, when backported]
+ *) mod_proxy_balancer: Workers can now be defined as part of
+ a balancer cluster "set" in which members of a lower-numbered set
+ are preferred over higher numbered ones. [Jim Jagielski]
+
*) SECURITY: CVE-2006-3747 (cve.mitre.org)
mod_rewrite: Fix an off-by-one security problem in the ldap scheme
handling. For some RewriteRules this could lead to a pointer being
diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c
index 2b1a9ba3d0..10865704fb 100644
--- a/modules/proxy/mod_proxy.c
+++ b/modules/proxy/mod_proxy.c
@@ -253,6 +253,12 @@ static const char *set_worker_param(apr_pool_t *p,
worker->ping_timeout = apr_time_from_sec(ival);
worker->ping_timeout_set = 1;
}
+ else if (!strcasecmp(key, "lbset")) {
+ ival = atoi(val);
+ if (ival < 0 || ival > 99)
+ return "lbset must be between 0 and 99";
+ worker->lbset = ival;
+ }
else {
return "unknown Worker parameter";
}
@@ -1898,7 +1904,7 @@ static int proxy_status_hook(request_rec *r, int flags)
ap_rputs("\n\n
"
"Sch | Host | Stat | "
"Route | Redir | "
- "F | Acc | Wr | Rd | "
+ "F | Set | Acc | Wr | Rd | "
"
\n", r);
worker = (proxy_worker *)balancer->workers->elts;
@@ -1917,6 +1923,7 @@ static int proxy_status_hook(request_rec *r, int flags)
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 | ", worker->s->lbset);
ap_rprintf(r, "%" APR_SIZE_T_FMT " | ", worker->s->elected);
ap_rputs(apr_strfsize(worker->s->transferred, fbuf), r);
ap_rputs(" | ", r);
diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h
index c6f8077af8..413953e65b 100644
--- a/modules/proxy/mod_proxy.h
+++ b/modules/proxy/mod_proxy.h
@@ -289,6 +289,8 @@ typedef struct {
char route[PROXY_WORKER_MAX_ROUTE_SIZ+1];
char redirect[PROXY_WORKER_MAX_ROUTE_SIZ+1];
void *context; /* general purpose storage */
+ apr_size_t busy; /* busyness factor */
+ int lbset; /* load balancer cluster set */
} proxy_worker_stat;
/* Worker configuration */
@@ -309,31 +311,32 @@ struct proxy_worker {
apr_interval_time_t ttl; /* maximum amount of time in seconds a connection
* may be available while exceeding the soft limit */
apr_interval_time_t timeout; /* connection timeout */
- char timeout_set;
+ char timeout_set;
apr_interval_time_t acquire; /* acquire timeout when the maximum number of connections is exceeded */
- char acquire_set;
- apr_size_t recv_buffer_size;
- char recv_buffer_size_set;
- apr_size_t io_buffer_size;
- char io_buffer_size_set;
- char keepalive;
- char keepalive_set;
+ char acquire_set;
+ apr_size_t recv_buffer_size;
+ char recv_buffer_size_set;
+ apr_size_t io_buffer_size;
+ char io_buffer_size_set;
+ char keepalive;
+ char keepalive_set;
proxy_conn_pool *cp; /* Connection pool to use */
proxy_worker_stat *s; /* Shared data */
- void *opaque; /* per scheme worker data */
- int is_address_reusable;
+ void *opaque; /* per scheme worker data */
+ int is_address_reusable;
#if APR_HAS_THREADS
apr_thread_mutex_t *mutex; /* Thread lock for updating address cache */
#endif
- void *context; /* general purpose storage */
+ void *context; /* general purpose storage */
enum {
flush_off,
flush_on,
flush_auto
} flush_packets; /* control AJP flushing */
- int flush_wait; /* poll wait time in microseconds if flush_auto */
+ int flush_wait; /* poll wait time in microseconds if flush_auto */
apr_interval_time_t ping_timeout;
char ping_timeout_set;
+ int lbset; /* load balancer cluster set */
};
/*
diff --git a/modules/proxy/mod_proxy_balancer.c b/modules/proxy/mod_proxy_balancer.c
index ff0322f663..27b43cb7cf 100644
--- a/modules/proxy/mod_proxy_balancer.c
+++ b/modules/proxy/mod_proxy_balancer.c
@@ -100,6 +100,7 @@ static int init_balancer_members(proxy_server_conf *conf, server_rec *s,
/* Set to the original configuration */
workers[i].s->lbstatus = workers[i].s->lbfactor =
(workers[i].lbfactor ? workers[i].lbfactor : 1);
+ workers[i].s->lbset = workers[i].lbset;
}
/* Set default number of attempts to the number of
* workers.
@@ -622,6 +623,12 @@ static int balancer_handler(request_rec *r)
else if (!strcasecmp(val, "Enable"))
wsel->s->status &= ~PROXY_WORKER_DISABLED;
}
+ if ((val = apr_table_get(params, "ls"))) {
+ int ival = atoi(val);
+ if (ival >= 0 && ival <= 99) {
+ wsel->s->lbset = ival;
+ }
+ }
}
if (apr_table_get(params, "xml")) {
@@ -684,13 +691,13 @@ static int balancer_handler(request_rec *r)
ap_rputs("\n\n"
"Worker URL | "
"Route | RouteRedir | "
- "Factor | Status | "
+ "Factor | Set | Status | "
"Elected | To | From | "
" \n", r);
worker = (proxy_worker *)balancer->workers->elts;
for (n = 0; n < balancer->workers->nelts; n++) {
-
+ char fbuf[50];
ap_rvputs(r, "\nuri, "?b=",
balancer->name + sizeof("balancer://") - 1, "&w=",
ap_escape_uri(r->pool, worker->name),
@@ -698,7 +705,8 @@ static int balancer_handler(request_rec *r)
ap_rvputs(r, worker->name, " | ", NULL);
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 | ", worker->s->lbfactor);
+ ap_rprintf(r, "%d | ", worker->s->lbset);
if (worker->s->status & PROXY_WORKER_DISABLED)
ap_rputs("Dis ", r);
if (worker->s->status & PROXY_WORKER_IN_ERROR)
@@ -712,10 +720,11 @@ static int balancer_handler(request_rec *r)
if (!PROXY_WORKER_IS_INITIALIZED(worker))
ap_rputs("-", r);
ap_rputs(" | ", r);
- ap_rprintf(r, "%" APR_SIZE_T_FMT " | ", worker->s->elected);
- ap_rprintf(r, "%" APR_OFF_T_FMT " | ", worker->s->transferred);
- ap_rprintf(r, "%" APR_OFF_T_FMT " | ", worker->s->read);
- ap_rputs(" \n", r);
+ ap_rprintf(r, "%" APR_SIZE_T_FMT " | ", worker->s->elected);
+ ap_rputs(apr_strfsize(worker->s->transferred, fbuf), r);
+ ap_rputs(" | ", r);
+ ap_rputs(apr_strfsize(worker->s->read, fbuf), r);
+ ap_rputs(" | \n", r);
++worker;
}
@@ -729,20 +738,22 @@ static int balancer_handler(request_rec *r)
ap_rvputs(r, "
|