mod_proxy_balancer.c revision 6fb984bb49f217c3b76cdbe864f105d2e74e52ed
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny/* Licensed to the Apache Software Foundation (ASF) under one or more
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * contributor license agreements. See the NOTICE file distributed with
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * this work for additional information regarding copyright ownership.
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * The ASF licenses this file to You under the Apache License, Version 2.0
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * (the "License"); you may not use this file except in compliance with
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * the License. You may obtain a copy of the License at
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * Unless required by applicable law or agreed to in writing, software
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * distributed under the License is distributed on an "AS IS" BASIS,
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * See the License for the specific language governing permissions and
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * limitations under the License.
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny/* Load balancer module for Apache proxy */
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zelenystatic const char *balancer_mutex_type = "proxy-balancer-shm";
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zelenymodule AP_MODULE_DECLARE_DATA proxy_balancer_module;
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zelenystatic int (*ap_proxy_retry_worker_fn)(const char *proxy_function,
204cfc89a076fd32bf34f2abb3f809304aaa88abSimo Sorce * Register our mutex type before the config is read so we
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * can adjust the mutex settings using the Mutex directive.
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zelenystatic int balancer_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny rv = ap_mutex_register(pconf, balancer_mutex_type, NULL,
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zelenyextern void proxy_update_members(proxy_balancer **balancer, request_rec *r,
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zelenystatic int proxy_balancer_canon(request_rec *r, char *url)
6a8999bf933f72923a271831d85a01ef88a81f39Jakub Hrozek const char *err;
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny /* TODO: offset of BALANCER_PREFIX ?? */
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r, "canonicalising URL %s", url);
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny /* do syntatic check.
7fe69bb6ec70bce439c6b975a9a0044c98ff502bSimo Sorce * We break the URL into host, port, path, search
7fe69bb6ec70bce439c6b975a9a0044c98ff502bSimo Sorce err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port);
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01157)
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny "error parsing URL %s: %s",
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * now parse path/search args, according to rfc1738:
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * process the path. With proxy-noncanon set (by
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * mod_proxy) we use the raw, unparsed uri
204cfc89a076fd32bf34f2abb3f809304aaa88abSimo Sorce path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny r->filename = apr_pstrcat(r->pool, "proxy:", BALANCER_PREFIX, host,
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny "/", path, (search) ? "?" : "", (search) ? search : "", NULL);
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny r->path_info = apr_pstrcat(r->pool, "/", path, NULL);
7fe69bb6ec70bce439c6b975a9a0044c98ff502bSimo Sorcestatic void init_balancer_members(apr_pool_t *p, server_rec *s,
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny workers = (proxy_worker **)balancer->workers->elts;
6a8999bf933f72923a271831d85a01ef88a81f39Jakub Hrozek ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01158)
6a8999bf933f72923a271831d85a01ef88a81f39Jakub Hrozek "Looking at %s -> %s initialized?", balancer->s->name, worker->s->name);
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny worker_is_initialized = PROXY_WORKER_IS_INITIALIZED(worker);
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny /* Set default number of attempts to the number of
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny if (!balancer->s->max_attempts_set && balancer->workers->nelts > 1) {
0754ff886f909f0404038eb9c99dd61be1acf5b9Simo Sorce balancer->s->max_attempts = balancer->workers->nelts - 1;
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny/* Retrieve the parameter with the given name
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * Something like 'JSESSIONID=12345...N'
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zelenystatic char *get_path_param(apr_pool_t *pool, char *url,
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny for (path = strstr(url, name); path; path = strstr(path + 1, name)) {
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * Session path was found, get its value
0754ff886f909f0404038eb9c99dd61be1acf5b9Simo Sorce path = apr_strtok(apr_pstrdup(pool, path), pathdelims, &q);
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zelenystatic char *get_cookie_param(request_rec *r, const char *name)
cb388d52f49f54963379cc20a25e14d17fe6e9a3Simo Sorce if ((cookies = apr_table_get(r->headers_in, "Cookie"))) {
cb388d52f49f54963379cc20a25e14d17fe6e9a3Simo Sorce for (start_cookie = ap_strstr_c(cookies, name); start_cookie;
cb388d52f49f54963379cc20a25e14d17fe6e9a3Simo Sorce start_cookie = ap_strstr_c(start_cookie + 1, name)) {
204cfc89a076fd32bf34f2abb3f809304aaa88abSimo Sorce * Session cookie was found, get its value
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny/* Find the worker that has the 'route' defined
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zelenystatic proxy_worker *find_route_worker(proxy_balancer *balancer,
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny workers = (proxy_worker **)balancer->workers->elts;
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny for (i = 0; i < balancer->workers->nelts; i++, workers++) {
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny if ( (checking_standby ? !PROXY_WORKER_IS_STANDBY(worker) : PROXY_WORKER_IS_STANDBY(worker)) )
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny if (*(worker->s->route) && strcmp(worker->s->route, route) == 0) {
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * If the worker is in error state run
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * retry on that worker. It will be marked as
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * operational if the retry timeout is elapsed.
b58460076fe843c11d736ae244c1ac979a6473a4Simo Sorce * The worker might still be unusable, but we try
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny ap_proxy_retry_worker_fn("BALANCER", worker, r->server);
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * We have a worker that is unusable.
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * It can be in error or disabled, but in case
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * it has a redirection set use that redirection worker.
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * This enables to safely remove the member from the
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * balancer. Of course you will need some kind of
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * session replication between those two remote.
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny rworker = find_route_worker(balancer, worker->s->redirect, r);
0754ff886f909f0404038eb9c99dd61be1acf5b9Simo Sorce /* Check if the redirect worker is usable */
0754ff886f909f0404038eb9c99dd61be1acf5b9Simo Sorce if (rworker && !PROXY_WORKER_IS_USABLE(rworker)) {
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * If the worker is in error state run
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * retry on that worker. It will be marked as
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * operational if the retry timeout is elapsed.
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * The worker might still be unusable, but we try
204cfc89a076fd32bf34f2abb3f809304aaa88abSimo Sorce ap_proxy_retry_worker_fn("BALANCER", rworker, r->server);
204cfc89a076fd32bf34f2abb3f809304aaa88abSimo Sorcestatic proxy_worker *find_session_route(proxy_balancer *balancer,
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny /* Try to find the sticky route inside url */
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny *route = get_path_param(r->pool, *url, balancer->s->sticky_path, balancer->s->scolonsep);
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01159)
7616a65d63d3bd0f669a871fd0ed89185956e9ceSimo Sorce "Found value %s for stickysession %s",
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny *route = get_cookie_param(r, balancer->s->sticky);
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01160)
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny "Found value %s for stickysession %s",
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * If we found a value for stickysession, find the first '.' (or whatever
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * sticky_separator is set to) within. Everything after '.' (if present)
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * is our route.
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny if ((*route) && (balancer->s->sticky_separator != 0) && ((*route = strchr(*route, balancer->s->sticky_separator)) != NULL ))
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01161) "Found route %s", *route);
c03b28a38b14fdb59f74864ae4dc56affe256508Simo Sorce /* We have a route in path or in cookie
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * Find the worker that has this route defined.
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny if (worker && strcmp(*route, worker->s->route)) {
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * Notice that the route of the worker chosen is different from
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny * the route supplied by the client.
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny apr_table_setn(r->subprocess_env, "BALANCER_ROUTE_CHANGED", "1");
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01162)
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny "Route changed from %s to %s",
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zelenystatic proxy_worker *find_best_worker(proxy_balancer *balancer,
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny if ((rv = PROXY_THREAD_LOCK(balancer)) != APR_SUCCESS) {
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01163)
84c611c1b7c04cc7735ab54d4e5f48284b79e6fbJan Zeleny "%s: Lock failed for find_best_worker()",
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny candidate = (*balancer->lbmethod->finder)(balancer, r);
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny if ((rv = PROXY_THREAD_UNLOCK(balancer)) != APR_SUCCESS) {
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01164)
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny "%s: Unlock failed for find_best_worker()",
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny /* All the workers are in error state or disabled.
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * If the balancer has a timeout sleep for a while
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * and try again to find the worker. The chances are
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * that some other thread will release a connection.
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * By default the timeout is not set, and the server
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * returns SERVER_BUSY.
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny /* XXX: This can perhaps be build using some
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * smarter mechanism, like tread_cond.
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * But since the statuses can came from
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * different childs, use the provided algo.
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny apr_interval_time_t timeout = balancer->s->timeout;
7616a65d63d3bd0f669a871fd0ed89185956e9ceSimo Sorce /* Set the timeout to 0 so that we don't
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * end in infinite loop
204cfc89a076fd32bf34f2abb3f809304aaa88abSimo Sorce /* Try again */
204cfc89a076fd32bf34f2abb3f809304aaa88abSimo Sorce /* restore the timeout */
204cfc89a076fd32bf34f2abb3f809304aaa88abSimo Sorcestatic int rewrite_url(request_rec *r, proxy_worker *worker,
7616a65d63d3bd0f669a871fd0ed89185956e9ceSimo Sorce /* we break the URL into host, port, uri */
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny return ap_proxyerror(r, HTTP_BAD_REQUEST, apr_pstrcat(r->pool,
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny *url = apr_pstrcat(r->pool, worker->s->name, path, NULL);
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zelenystatic void force_recovery(proxy_balancer *balancer, server_rec *s)
c03b28a38b14fdb59f74864ae4dc56affe256508Simo Sorce worker = (proxy_worker **)balancer->workers->elts;
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny for (i = 0; i < balancer->workers->nelts; i++, worker++) {
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny if (!((*worker)->s->status & PROXY_WORKER_IN_ERROR)) {
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny /* Try if we can recover */
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny ap_proxy_retry_worker_fn("BALANCER", *worker, s);
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny if (!((*worker)->s->status & PROXY_WORKER_IN_ERROR)) {
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny /* If all workers are in error state force the recovery.
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny worker = (proxy_worker **)balancer->workers->elts;
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny for (i = 0; i < balancer->workers->nelts; i++, worker++) {
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01165)
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny "%s: Forcing recovery for worker (%s)",
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zelenystatic apr_status_t decrement_busy_count(void *worker_)
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zelenystatic int proxy_balancer_pre_request(proxy_worker **worker,
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny /* Step 1: check if the url is for us
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * The url we can handle starts with 'balancer://'
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * If balancer is already provided skip the search
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * for balancer, because this is failover attempt.
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny !(*balancer = ap_proxy_get_balancer(r->pool, conf, *url, 1)))
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny /* Step 2: Lock the LoadBalancer
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * XXX: perhaps we need the process lock here
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny if ((rv = PROXY_THREAD_LOCK(*balancer)) != APR_SUCCESS) {
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01166)
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny "%s: Lock failed for pre_request", (*balancer)->s->name);
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce /* Step 3: force recovery */
7fe69bb6ec70bce439c6b975a9a0044c98ff502bSimo Sorce /* Step 3.5: Update member list for the balancer */
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny /* TODO: Implement as provider! */
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny ap_proxy_sync_balancer(*balancer, r->server, conf);
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny /* Step 4: find the session route */
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny runtime = find_session_route(*balancer, r, &route, &sticky, url);
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny if ((*balancer)->lbmethod && (*balancer)->lbmethod->updatelbstatus) {
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny /* Call the LB implementation */
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce (*balancer)->lbmethod->updatelbstatus(*balancer, runtime, r->server);
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny else { /* Use the default one */
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny /* We have a sticky load balancer
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * Update the workers status
efea50efda58be66638e5d38c8e57fdf9992f204Simo Sorce * so that even session routes get
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * into account.
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny workers = (proxy_worker **)(*balancer)->workers->elts;
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny for (i = 0; i < (*balancer)->workers->nelts; i++) {
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny /* Take into calculation only the workers that are
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * not in error state or not disabled.
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny (*workers)->s->lbstatus += (*workers)->s->lbfactor;
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny else if (route && (*balancer)->s->sticky_force) {
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * We have a route provided that doesn't match the
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * balancer name. See if the provider route is the
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * member of the same balancer in which case return 503
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny workers = (proxy_worker **)(*balancer)->workers->elts;
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny for (i = 0; i < (*balancer)->workers->nelts; i++) {
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny if (*((*workers)->s->route) && strcmp((*workers)->s->route, route) == 0) {
3a59cbd0b7b9c5dd3c62ac1679876070c264d80fMichal Zidek ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01167)
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny "%s: All workers are in error state for route (%s)",
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny if ((rv = PROXY_THREAD_UNLOCK(*balancer)) != APR_SUCCESS) {
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01168)
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny "%s: Unlock failed for pre_request",
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny if ((rv = PROXY_THREAD_UNLOCK(*balancer)) != APR_SUCCESS) {
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01169)
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny "%s: Unlock failed for pre_request",
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01170)
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny "%s: All workers are in error state",
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01171)
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny "%s: No workers in balancer",
e76d78338026fa47dca32eaf7f5c15eabb1b951aJan Zeleny * This balancer has sticky sessions and the client either has not
if (route) {
return access_status;
request_rec *r,
return HTTP_INTERNAL_SERVER_ERROR;
return OK;
return OK;
if (!ap_proxy_retry_worker_fn) {
if (!ap_proxy_retry_worker_fn) {
return !OK;
if (!storage) {
return !OK;
char *id;
(int)s->port,
s->defn_line_number,
s = s->next;
return !OK;
const char *sname;
unsigned int index;
&sname);
return HTTP_INTERNAL_SERVER_ERROR;
if (bshm) {
return !OK;
return !OK;
return !OK;
return !OK;
ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, APLOGNO(01184) "Doing workers create: %s (%s), %d, %d [%u]",
return !OK;
if (shm) {
return !OK;
return !OK;
return !OK;
return !OK;
s = s->next;
return OK;
if (flag)
if (!flag)
char *args;
char *key;
while (key) {
if (val) {
while (*ok) {
ok++;
void *sconf;
const char *name;
const char *action;
return DECLINED;
r->allowed = 0
return DECLINED;
return HTTP_INTERNAL_SERVER_ERROR;
if (!bsel ||
ok2change = 0;
const char *val;
if (bsel)
const char *val;
int ival;
if (lbmethod) {
char *path;
char *ret;
if (!ret) {
unsigned int index;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
ap_rprintf(r,
ap_rprintf(r,
ap_rprintf(r,
ap_rprintf(r,
ap_rprintf(r,
ap_rprintf(r,
ap_rprintf(r,
ap_rprintf(r,
ap_rprintf(r,
ap_rprintf(r,
ap_rprintf(r,
ap_rprintf(r,
ap_rprintf(r,
ap_rprintf(r,
ap_rprintf(r,
ap_rprintf(r,
ap_rprintf(r,
ap_rprintf(r,
case flush_off:
case flush_on:
case flush_auto:
ap_rprintf(r,
ap_rprintf(r,
ap_rprintf(r,
ap_rprintf(r,
ap_rprintf(r,
++workers;
++balancer;
"<th>MaxMembers</th><th>StickySession</th><th>DisableFailover</th><th>Timeout</th><th>FailoverAttempts</th><th>Method</th>"
NULL);
++workers;
++balancer;
NULL);
NULL);
} else if (bsel) {
if (provs) {
ap_rflush(r);
return DONE;
unsigned int num;
s = s->next;