--- mod_proxy.c.orig 2007-09-17 10:56:57.473461200 +0200 +++ mod_proxy.c.orig 2007-09-17 11:23:08.202263800 +0200 @@ -54,16 +54,6 @@ /* -------------------------------------------------------------- */ /* Translate the URL into a 'filename' */ -#define PROXY_COPY_CONF_PARAMS(w, c) \ - do { \ - (w)->timeout = (c)->timeout; \ - (w)->timeout_set = (c)->timeout_set; \ - (w)->recv_buffer_size = (c)->recv_buffer_size; \ - (w)->recv_buffer_size_set = (c)->recv_buffer_size_set; \ - (w)->io_buffer_size = (c)->io_buffer_size; \ - (w)->io_buffer_size_set = (c)->io_buffer_size_set; \ - } while (0) - static const char *set_worker_param(apr_pool_t *p, proxy_worker *worker, const char *key, @@ -871,6 +861,7 @@ ps->badopt = bad_error; ps->badopt_set = 0; ps->pool = p; + ps->maxaddtlworkers = 0; return ps; } @@ -904,6 +895,8 @@ ps->badopt = (overrides->badopt_set == 0) ? base->badopt : overrides->badopt; ps->proxy_status = (overrides->proxy_status_set == 0) ? base->proxy_status : overrides->proxy_status; ps->pool = p; + ps->maxaddtlworkers = (overrides->maxaddtlworkers == 0) ? base->maxaddtlworkers : overrides->maxaddtlworkers; + return ps; } @@ -1574,6 +1567,23 @@ return NULL; } +static const char* + set_proxy_maxaddtlworkers(cmd_parms *parms, void *dummy, const char *arg) +{ + proxy_server_conf *psf = + ap_get_module_config(parms->server->module_config, &proxy_module); + int maxworkers; + + maxworkers=atoi(arg); + if (maxworkers<1) { + return "Number of additional workers must be at least 0."; + } + psf->maxaddtlworkers=maxworkers; + proxy_lb_workers += maxworkers; + + return NULL; +} + static void ap_add_per_proxy_conf(server_rec *s, ap_conf_vector_t *dir_config) { proxy_server_conf *sconf = ap_get_module_config(s->module_config, @@ -1720,6 +1730,8 @@ "Configure Status: proxy status to one of: on | off | full"), AP_INIT_RAW_ARGS("ProxySet", set_proxy_param, NULL, RSRC_CONF|ACCESS_CONF, "A balancer or worker name with list of params"), + AP_INIT_TAKE1("ProxyMaxAddtlWorkers", set_proxy_maxaddtlworkers, NULL, RSRC_CONF, + "The maximum number of proxy workers that may be created implicitly."), {NULL} }; --- mod_proxy.h.orig 2007-09-17 10:56:57.535961600 +0200 +++ mod_proxy.h.orig 2007-09-17 09:25:33.532114200 +0200 @@ -186,6 +186,7 @@ } proxy_status; /* Status display options */ char proxy_status_set; apr_pool_t *pool; /* Pool used for allocating this struct */ + int maxaddtlworkers; } proxy_server_conf; @@ -266,6 +267,16 @@ #define PROXY_WORKER_DEFAULT_RETRY 60 #define PROXY_WORKER_MAX_ROUTE_SIZ 63 +#define PROXY_COPY_CONF_PARAMS(w, c) \ + do { \ + (w)->timeout = (c)->timeout; \ + (w)->timeout_set = (c)->timeout_set; \ + (w)->recv_buffer_size = (c)->recv_buffer_size; \ + (w)->recv_buffer_size_set = (c)->recv_buffer_size_set; \ + (w)->io_buffer_size = (c)->io_buffer_size; \ + (w)->io_buffer_size_set = (c)->io_buffer_size_set; \ + } while (0) + /* Runtime worker status informations. Shared in scoreboard */ typedef struct { int status; --- proxy_util.c.orig 2007-09-17 10:56:57.723462800 +0200 +++ proxy_util.c.orig 2007-09-17 10:42:50.202413700 +0200 @@ -32,6 +32,7 @@ /* Global balancer counter */ int PROXY_DECLARE_DATA proxy_lb_workers = 0; static int lb_workers_limit = 0; +static int addtl_workers = 0; static int proxy_match_ipaddr(struct dirconn_entry *This, request_rec *r); static int proxy_match_domainname(struct dirconn_entry *This, request_rec *r); @@ -1394,14 +1395,57 @@ } else if (r->proxyreq == PROXYREQ_REVERSE) { if (conf->reverse) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, - "proxy: *: found reverse proxy worker for %s", - *url); *balancer = NULL; - *worker = conf->reverse; - access_status = OK; + + char *c; + char url_copy[strlen(*url) + 1]; + + /* Make a copy of the URL where the path is truncated */ + strcpy(url_copy, *url); + c = ap_strchr_c(url_copy, ':'); + + if ( !(c == NULL || c[1] != '/' || c[2] != '/' || c[3] == '\0') ) { + c = ap_strchr_c(c+3, '/'); + if ( c[0] == '/' ) + c[1] = '\0'; + } + + if ( addtl_workers < conf->maxaddtlworkers ) { + const char *err = ap_proxy_add_worker(worker, conf->pool, conf, url_copy); + if (err) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + "proxy: unable to add new reverse proxy worker for %s - %s", + *url, err); + } + else + { + addtl_workers += 1; + PROXY_COPY_CONF_PARAMS((proxy_worker *) *worker, + (proxy_server_conf *) conf); + + ap_proxy_initialize_worker_share(conf, *worker, r->server); + ap_proxy_initialize_worker(*worker, r->server); + /* Do not disable worker in case of errors */ + (*worker)->s->status |= PROXY_WORKER_IGNORE_ERRORS; + (*worker)->is_address_reusable = 1; + *worker = ap_proxy_get_worker(r->pool, conf, *url); + } + } + else { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + "proxy: cannot create additional worker %s - ProxyMaxAddtlWorkers limit reached (%d)", + url_copy, conf->maxaddtlworkers); + } + + if (!*worker) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, + "proxy: *: found reverse proxy worker for %s", + *url); + *worker = conf->reverse; + } + access_status = OK; } - } + } } else if (access_status == DECLINED && *balancer != NULL) { /* All the workers are busy */