mod_proxy_balancer.c revision 4952d93743af3632518d1c925fac5227720cf64a
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* Licensed to the Apache Software Foundation (ASF) under one or more
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * contributor license agreements. See the NOTICE file distributed with
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * this work for additional information regarding copyright ownership.
b99dbaab171d91e1b664397cc40e039d0c087c65fielding * The ASF licenses this file to You under the Apache License, Version 2.0
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * (the "License"); you may not use this file except in compliance with
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * the License. You may obtain a copy of the License at
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Unless required by applicable law or agreed to in writing, software
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * distributed under the License is distributed on an "AS IS" BASIS,
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * See the License for the specific language governing permissions and
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * limitations under the License.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* Load balancer module for Apache proxy */
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fieldingstatic const char *balancer_mutex_type = "proxy-balancer-shm";
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fieldingmodule AP_MODULE_DECLARE_DATA proxy_balancer_module;
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding * Register our mutex type before the config is read so we
64185f9824e42f21ca7b9ae6c004484215c031a7rbb * can adjust the mutex settings using the Mutex directive.
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fieldingstatic int balancer_pre_config(apr_pool_t *pconf, apr_pool_t *plog,
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fielding rv = ap_mutex_register(pconf, balancer_mutex_type, NULL,
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fieldingextern void proxy_update_members(proxy_balancer **balancer, request_rec *r,
ab2c1c1c83ec91415565da5a71fbc15d9685caa6fieldingstatic int proxy_balancer_canon(request_rec *r, char *url)
3568de757bac0b47256647504c186d17ca272f85rbb const char *err;
3568de757bac0b47256647504c186d17ca272f85rbb /* TODO: offset of BALANCER_PREFIX ?? */
3568de757bac0b47256647504c186d17ca272f85rbb /* do syntatic check.
3568de757bac0b47256647504c186d17ca272f85rbb * We break the URL into host, port, path, search
3568de757bac0b47256647504c186d17ca272f85rbb err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port);
3568de757bac0b47256647504c186d17ca272f85rbb "error parsing URL %s: %s",
3568de757bac0b47256647504c186d17ca272f85rbb * now parse path/search args, according to rfc1738:
3568de757bac0b47256647504c186d17ca272f85rbb * process the path. With proxy-noncanon set (by
3568de757bac0b47256647504c186d17ca272f85rbb * mod_proxy) we use the raw, unparsed uri
3568de757bac0b47256647504c186d17ca272f85rbb path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0,
3568de757bac0b47256647504c186d17ca272f85rbb r->filename = apr_pstrcat(r->pool, "proxy:", BALANCER_PREFIX, host,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "/", path, (search) ? "?" : "", (search) ? search : "", NULL);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding r->path_info = apr_pstrcat(r->pool, "/", path, NULL);
3568de757bac0b47256647504c186d17ca272f85rbbstatic void init_balancer_members(apr_pool_t *p, server_rec *s,
3568de757bac0b47256647504c186d17ca272f85rbb "Looking at %s -> %s initialized?", balancer->name, worker->s->name);
3568de757bac0b47256647504c186d17ca272f85rbb worker_is_initialized = PROXY_WORKER_IS_INITIALIZED(worker);
3568de757bac0b47256647504c186d17ca272f85rbb /* Set default number of attempts to the number of
3568de757bac0b47256647504c186d17ca272f85rbb * workers.
3568de757bac0b47256647504c186d17ca272f85rbb if (!balancer->s->max_attempts_set && balancer->workers->nelts > 1) {
3568de757bac0b47256647504c186d17ca272f85rbb balancer->s->max_attempts = balancer->workers->nelts - 1;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding/* Retrieve the parameter with the given name
8f3ec4772d2aeb347cf40e87c77627bb784dd018rbb * Something like 'JSESSIONID=12345...N'
3d96ee83babeec32482c9082c9426340cee8c44dwrowestatic char *get_path_param(apr_pool_t *pool, char *url,
3568de757bac0b47256647504c186d17ca272f85rbb for (path = strstr(url, name); path; path = strstr(path + 1, name)) {
3568de757bac0b47256647504c186d17ca272f85rbb * Session path was found, get it's value
3568de757bac0b47256647504c186d17ca272f85rbb path = apr_strtok(apr_pstrdup(pool, path), pathdelims, &q);
3568de757bac0b47256647504c186d17ca272f85rbbstatic char *get_cookie_param(request_rec *r, const char *name)
3568de757bac0b47256647504c186d17ca272f85rbb const char *cookies;
3568de757bac0b47256647504c186d17ca272f85rbb const char *start_cookie;
3568de757bac0b47256647504c186d17ca272f85rbb if ((cookies = apr_table_get(r->headers_in, "Cookie"))) {
3568de757bac0b47256647504c186d17ca272f85rbb for (start_cookie = ap_strstr_c(cookies, name); start_cookie;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Session cookie was found, get it's value
3568de757bac0b47256647504c186d17ca272f85rbb/* Find the worker that has the 'route' defined
3568de757bac0b47256647504c186d17ca272f85rbbstatic proxy_worker *find_route_worker(proxy_balancer *balancer,
3568de757bac0b47256647504c186d17ca272f85rbb for (i = 0; i < balancer->workers->nelts; i++, workers++) {
3568de757bac0b47256647504c186d17ca272f85rbb if ( (checking_standby ? !PROXY_WORKER_IS_STANDBY(worker) : PROXY_WORKER_IS_STANDBY(worker)) )
3568de757bac0b47256647504c186d17ca272f85rbb if (*(worker->s->route) && strcmp(worker->s->route, route) == 0) {
3568de757bac0b47256647504c186d17ca272f85rbb * If the worker is in error state run
3568de757bac0b47256647504c186d17ca272f85rbb * retry on that worker. It will be marked as
3568de757bac0b47256647504c186d17ca272f85rbb * operational if the retry timeout is elapsed.
3568de757bac0b47256647504c186d17ca272f85rbb * The worker might still be unusable, but we try
239f998fbee5ac5b114b965bb76e217cce0003edstoddard * We have a worker that is unusable.
78ae889ffe0fdfab72f56c6993b0f302cb48da55rbb * It can be in error or disabled, but in case
3568de757bac0b47256647504c186d17ca272f85rbb * it has a redirection set use that redirection worker.
3568de757bac0b47256647504c186d17ca272f85rbb * This enables to safely remove the member from the
3568de757bac0b47256647504c186d17ca272f85rbb * balancer. Of course you will need some kind of
3568de757bac0b47256647504c186d17ca272f85rbb * session replication between those two remote.
3568de757bac0b47256647504c186d17ca272f85rbb rworker = find_route_worker(balancer, worker->s->redirect, r);
3568de757bac0b47256647504c186d17ca272f85rbb /* Check if the redirect worker is usable */
3568de757bac0b47256647504c186d17ca272f85rbb * If the worker is in error state run
3568de757bac0b47256647504c186d17ca272f85rbb * retry on that worker. It will be marked as
3568de757bac0b47256647504c186d17ca272f85rbb * operational if the retry timeout is elapsed.
3568de757bac0b47256647504c186d17ca272f85rbb * The worker might still be unusable, but we try
3568de757bac0b47256647504c186d17ca272f85rbbstatic proxy_worker *find_session_route(proxy_balancer *balancer,
3568de757bac0b47256647504c186d17ca272f85rbb const char **sticky_used,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* Try to find the sticky route inside url */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding *route = get_path_param(r->pool, *url, balancer->s->sticky_path, balancer->s->scolonsep);
3568de757bac0b47256647504c186d17ca272f85rbb "proxy: BALANCER: Found value %s for "
3568de757bac0b47256647504c186d17ca272f85rbb "proxy: BALANCER: Found value %s for "
3568de757bac0b47256647504c186d17ca272f85rbb * If we found a value for sticksession, find the first '.' within.
3568de757bac0b47256647504c186d17ca272f85rbb * Everything after '.' (if present) is our route.
3568de757bac0b47256647504c186d17ca272f85rbb if ((*route) && ((*route = strchr(*route, '.')) != NULL ))
3568de757bac0b47256647504c186d17ca272f85rbb /* We have a route in path or in cookie
3568de757bac0b47256647504c186d17ca272f85rbb * Find the worker that has this route defined.
3568de757bac0b47256647504c186d17ca272f85rbb * Notice that the route of the worker chosen is different from
3568de757bac0b47256647504c186d17ca272f85rbb * the route supplied by the client.
3568de757bac0b47256647504c186d17ca272f85rbb apr_table_setn(r->subprocess_env, "BALANCER_ROUTE_CHANGED", "1");
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding "proxy: BALANCER: Route changed from %s to %s",
3568de757bac0b47256647504c186d17ca272f85rbbstatic proxy_worker *find_best_worker(proxy_balancer *balancer,
3568de757bac0b47256647504c186d17ca272f85rbb if ((rv = PROXY_THREAD_LOCK(balancer)) != APR_SUCCESS) {
3568de757bac0b47256647504c186d17ca272f85rbb "proxy: BALANCER: (%s). Lock failed for find_best_worker()", balancer->name);
3568de757bac0b47256647504c186d17ca272f85rbb candidate = (*balancer->s->lbmethod->finder)(balancer, r);
3568de757bac0b47256647504c186d17ca272f85rbb if ((rv = PROXY_THREAD_UNLOCK(balancer)) != APR_SUCCESS) {
3568de757bac0b47256647504c186d17ca272f85rbb "proxy: BALANCER: (%s). Unlock failed for find_best_worker()", balancer->name);
3568de757bac0b47256647504c186d17ca272f85rbb /* All the workers are in error state or disabled.
3568de757bac0b47256647504c186d17ca272f85rbb * If the balancer has a timeout sleep for a while
3568de757bac0b47256647504c186d17ca272f85rbb * and try again to find the worker. The chances are
3568de757bac0b47256647504c186d17ca272f85rbb * that some other thread will release a connection.
3568de757bac0b47256647504c186d17ca272f85rbb * By default the timeout is not set, and the server
74fd6d9aeadb9022086259c5c1ae00bc0dda9c9astoddard * returns SERVER_BUSY.
3568de757bac0b47256647504c186d17ca272f85rbb /* XXX: This can perhaps be build using some
3568de757bac0b47256647504c186d17ca272f85rbb * smarter mechanism, like tread_cond.
3568de757bac0b47256647504c186d17ca272f85rbb * But since the statuses can came from
3568de757bac0b47256647504c186d17ca272f85rbb * different childs, use the provided algo.
3568de757bac0b47256647504c186d17ca272f85rbb /* Set the timeout to 0 so that we don't
3568de757bac0b47256647504c186d17ca272f85rbb * end in infinite loop
3568de757bac0b47256647504c186d17ca272f85rbb /* Try again */
3568de757bac0b47256647504c186d17ca272f85rbb /* restore the timeout */
3568de757bac0b47256647504c186d17ca272f85rbbstatic int rewrite_url(request_rec *r, proxy_worker *worker,
3568de757bac0b47256647504c186d17ca272f85rbb /* we break the URL into host, port, uri */
3568de757bac0b47256647504c186d17ca272f85rbb return ap_proxyerror(r, HTTP_BAD_REQUEST, apr_pstrcat(r->pool,
3568de757bac0b47256647504c186d17ca272f85rbb *url = apr_pstrcat(r->pool, worker->s->name, path, NULL);
3568de757bac0b47256647504c186d17ca272f85rbbstatic void force_recovery(proxy_balancer *balancer, server_rec *s)
3568de757bac0b47256647504c186d17ca272f85rbb for (i = 0; i < balancer->workers->nelts; i++, worker++) {
3568de757bac0b47256647504c186d17ca272f85rbb /* Try if we can recover */
3568de757bac0b47256647504c186d17ca272f85rbb /* If all workers are in error state force the recovery.
3568de757bac0b47256647504c186d17ca272f85rbb for (i = 0; i < balancer->workers->nelts; i++, worker++) {
3568de757bac0b47256647504c186d17ca272f85rbb "proxy: BALANCER: (%s). Forcing recovery for worker (%s)",
3568de757bac0b47256647504c186d17ca272f85rbbstatic int proxy_balancer_pre_request(proxy_worker **worker,
3568de757bac0b47256647504c186d17ca272f85rbb /* Step 1: check if the url is for us
3568de757bac0b47256647504c186d17ca272f85rbb * The url we can handle starts with 'balancer://'
3568de757bac0b47256647504c186d17ca272f85rbb * If balancer is already provided skip the search
3568de757bac0b47256647504c186d17ca272f85rbb * for balancer, because this is failover attempt.
3568de757bac0b47256647504c186d17ca272f85rbb !(*balancer = ap_proxy_get_balancer(r->pool, conf, *url)))
3568de757bac0b47256647504c186d17ca272f85rbb /* Step 2: Lock the LoadBalancer
3568de757bac0b47256647504c186d17ca272f85rbb * XXX: perhaps we need the process lock here
3568de757bac0b47256647504c186d17ca272f85rbb if ((rv = PROXY_THREAD_LOCK(*balancer)) != APR_SUCCESS) {
3568de757bac0b47256647504c186d17ca272f85rbb "proxy: BALANCER: (%s). Lock failed for pre_request",
3568de757bac0b47256647504c186d17ca272f85rbb /* Step 3: force recovery */
3568de757bac0b47256647504c186d17ca272f85rbb /* Step 3.5: Update member list for the balancer */
3568de757bac0b47256647504c186d17ca272f85rbb /* TODO: Implement as provider! */
8e9734d1a4af74c141e2a0f880bb51bb061fa03atrawick ap_proxy_update_members(*balancer, r->server, conf);
3568de757bac0b47256647504c186d17ca272f85rbb /* Step 4: find the session route */
3568de757bac0b47256647504c186d17ca272f85rbb runtime = find_session_route(*balancer, r, &route, &sticky, url);
8e9734d1a4af74c141e2a0f880bb51bb061fa03atrawick if ((*balancer)->s->lbmethod && (*balancer)->s->lbmethod->updatelbstatus) {
3568de757bac0b47256647504c186d17ca272f85rbb /* Call the LB implementation */
3568de757bac0b47256647504c186d17ca272f85rbb (*balancer)->s->lbmethod->updatelbstatus(*balancer, runtime, r->server);
3568de757bac0b47256647504c186d17ca272f85rbb else { /* Use the default one */
3568de757bac0b47256647504c186d17ca272f85rbb /* We have a sticky load balancer
8e9734d1a4af74c141e2a0f880bb51bb061fa03atrawick * Update the workers status
3568de757bac0b47256647504c186d17ca272f85rbb * so that even session routes get
3568de757bac0b47256647504c186d17ca272f85rbb * into account.
3568de757bac0b47256647504c186d17ca272f85rbb /* Take into calculation only the workers that are
3568de757bac0b47256647504c186d17ca272f85rbb * not in error state or not disabled.
3568de757bac0b47256647504c186d17ca272f85rbb int i, member_of = 0;
3568de757bac0b47256647504c186d17ca272f85rbb * We have a route provided that doesn't match the
3568de757bac0b47256647504c186d17ca272f85rbb * balancer name. See if the provider route is the
3568de757bac0b47256647504c186d17ca272f85rbb * member of the same balancer in which case return 503
3568de757bac0b47256647504c186d17ca272f85rbb if (*((*workers)->s->route) && strcmp((*workers)->s->route, route) == 0) {
ad83978f20c7d1a4323059d9af122e56fcd353bdstoddard "proxy: BALANCER: (%s). All workers are in error state for route (%s)",
3568de757bac0b47256647504c186d17ca272f85rbb if ((rv = PROXY_THREAD_UNLOCK(*balancer)) != APR_SUCCESS) {
3568de757bac0b47256647504c186d17ca272f85rbb "proxy: BALANCER: (%s). Unlock failed for pre_request",
3568de757bac0b47256647504c186d17ca272f85rbb if ((rv = PROXY_THREAD_UNLOCK(*balancer)) != APR_SUCCESS) {
3568de757bac0b47256647504c186d17ca272f85rbb "proxy: BALANCER: (%s). Unlock failed for pre_request",
3568de757bac0b47256647504c186d17ca272f85rbb "proxy: BALANCER: (%s). All workers are in error state",
3568de757bac0b47256647504c186d17ca272f85rbb "proxy: BALANCER: (%s). No workers in balancer",
3568de757bac0b47256647504c186d17ca272f85rbb * This balancer has sticky sessions and the client either has not
3568de757bac0b47256647504c186d17ca272f85rbb * supplied any routing information or all workers for this route
3568de757bac0b47256647504c186d17ca272f85rbb * including possible redirect and hotstandby workers are in error
3568de757bac0b47256647504c186d17ca272f85rbb * state, but we have found another working worker for this
3568de757bac0b47256647504c186d17ca272f85rbb * balancer where we can send the request. Thus notice that we have
3568de757bac0b47256647504c186d17ca272f85rbb * changed the route to the backend.
3568de757bac0b47256647504c186d17ca272f85rbb apr_table_setn(r->subprocess_env, "BALANCER_ROUTE_CHANGED", "1");
3568de757bac0b47256647504c186d17ca272f85rbb /* Add balancer/worker info to env. */
3568de757bac0b47256647504c186d17ca272f85rbb /* Rewrite the url from 'balancer://url'
3568de757bac0b47256647504c186d17ca272f85rbb * to the 'worker_scheme://worker_hostname[:worker_port]/url'
3568de757bac0b47256647504c186d17ca272f85rbb * This replaces the balancers fictional name with the
3568de757bac0b47256647504c186d17ca272f85rbb * real hostname of the elected worker.
3568de757bac0b47256647504c186d17ca272f85rbb /* Add the session route to request notes if present */
3568de757bac0b47256647504c186d17ca272f85rbb /* Add session info to env. */
ad83978f20c7d1a4323059d9af122e56fcd353bdstoddard ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
3568de757bac0b47256647504c186d17ca272f85rbb "proxy: BALANCER (%s) worker (%s) rewritten to %s",
3568de757bac0b47256647504c186d17ca272f85rbbstatic int proxy_balancer_post_request(proxy_worker *worker,
3568de757bac0b47256647504c186d17ca272f85rbb if ((rv = PROXY_THREAD_UNLOCK(balancer)) != APR_SUCCESS) {
3568de757bac0b47256647504c186d17ca272f85rbb "proxy: BALANCER: (%s). Lock failed for post_request",
3568de757bac0b47256647504c186d17ca272f85rbb "proxy: BALANCER: (%s). Forcing recovery for worker (%s), failonstatus %d",
3568de757bac0b47256647504c186d17ca272f85rbb if ((rv = PROXY_THREAD_UNLOCK(balancer)) != APR_SUCCESS) {
3568de757bac0b47256647504c186d17ca272f85rbb "proxy: BALANCER: (%s). Unlock failed for post_request",
3568de757bac0b47256647504c186d17ca272f85rbb "proxy_balancer_post_request for (%s)", balancer->name);
3568de757bac0b47256647504c186d17ca272f85rbb /* Recalculate lbfactors */
3568de757bac0b47256647504c186d17ca272f85rbb /* Special case if there is only one worker it's
3568de757bac0b47256647504c186d17ca272f85rbb * load factor will always be 1
3568de757bac0b47256647504c186d17ca272f85rbb /* Update the status entries */
3568de757bac0b47256647504c186d17ca272f85rbb proxy_server_conf *conf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
3568de757bac0b47256647504c186d17ca272f85rbb for (i = 0; i < conf->balancers->nelts; i++, balancer++) {
3568de757bac0b47256647504c186d17ca272f85rbb return(0);
3568de757bac0b47256647504c186d17ca272f85rbb/* post_config hook: */
3568de757bac0b47256647504c186d17ca272f85rbbstatic int balancer_post_config(apr_pool_t *pconf, apr_pool_t *plog,
3568de757bac0b47256647504c186d17ca272f85rbb proxy_server_conf *conf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);
3568de757bac0b47256647504c186d17ca272f85rbb /* balancer_post_config() will be called twice during startup. So, only
3568de757bac0b47256647504c186d17ca272f85rbb * set up the static data the 1st time through. */
3568de757bac0b47256647504c186d17ca272f85rbb apr_pool_userdata_get(&data, userdata_key, s->process->pool);
3568de757bac0b47256647504c186d17ca272f85rbb * Get slotmem setups
3568de757bac0b47256647504c186d17ca272f85rbb storage = ap_lookup_provider(AP_SLOTMEM_PROVIDER_GROUP, "shared", "0");
3568de757bac0b47256647504c186d17ca272f85rbb ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, 0, s,
3568de757bac0b47256647504c186d17ca272f85rbb "ap_lookup_provider %s failed", AP_SLOTMEM_PROVIDER_GROUP);
3568de757bac0b47256647504c186d17ca272f85rbb * Go thru each Vhost and create the shared mem slotmem for
3568de757bac0b47256647504c186d17ca272f85rbb * each balancer's workers
3568de757bac0b47256647504c186d17ca272f85rbb while (s) {
3568de757bac0b47256647504c186d17ca272f85rbb conf = (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module);
3568de757bac0b47256647504c186d17ca272f85rbb ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Doing balancers create: %d, %d",
3568de757bac0b47256647504c186d17ca272f85rbb conf->balancers->nelts, AP_SLOTMEM_TYPE_PREGRAB, pconf);
3568de757bac0b47256647504c186d17ca272f85rbb ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, "balancer slotmem_create failed");
3568de757bac0b47256647504c186d17ca272f85rbb /* Initialize shared scoreboard data */
3568de757bac0b47256647504c186d17ca272f85rbb for (i = 0; i < conf->balancers->nelts; i++, balancer++) {
3568de757bac0b47256647504c186d17ca272f85rbb unsigned int index;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding balancer->max_workers = balancer->workers->nelts + balancer->growth;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* no need for the 'balancer://' prefix */
3568de757bac0b47256647504c186d17ca272f85rbb ap_pstr2_alnum(pconf, balancer->name + sizeof(BALANCER_PREFIX) - 1,
3568de757bac0b47256647504c186d17ca272f85rbb balancer->sname = apr_pstrcat(pconf, conf->id, "_", balancer->sname, NULL);
3568de757bac0b47256647504c186d17ca272f85rbb /* Create global mutex */
3568de757bac0b47256647504c186d17ca272f85rbb rv = ap_global_mutex_create(&(balancer->gmutex), NULL, balancer_mutex_type,
3568de757bac0b47256647504c186d17ca272f85rbb "mutex creation of %s : %s failed", balancer_mutex_type,
3568de757bac0b47256647504c186d17ca272f85rbb apr_pool_cleanup_register(pconf, (void *)s, lock_remove,
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe /* setup shm for balancers */
3568de757bac0b47256647504c186d17ca272f85rbb if ((rv = storage->grab(conf->slot, &index)) != APR_SUCCESS) {
ca53a74f4012a45cbad48e940eddf27d866981f9dougm ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, "balancer slotmem_grab failed");
302dc1f7b3feee23a91ad8f3cf3cb2edd95a557bmanoj if ((rv = storage->dptr(conf->slot, index, (void *)&bshm)) != APR_SUCCESS) {
3568de757bac0b47256647504c186d17ca272f85rbb ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, "balancer slotmem_dptr failed");
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if ((rv = ap_proxy_share_balancer(balancer, bshm, index)) != APR_SUCCESS) {
3568de757bac0b47256647504c186d17ca272f85rbb ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, "Cannot share balancer");
return !OK;
return !OK;
return !OK;
return !OK;
s = s->next;
return OK;
if (flag)
if (!flag)
void *sconf;
int access_status;
const char *name;
return DECLINED;
return DECLINED;
if (r->args) {
return access_status;
return HTTP_BAD_REQUEST;
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;
++workers;
++balancer;
"<th>MaxMembers</th><th>StickySession</th><th>DisableFailover</th><th>Timeout</th><th>FailoverAttempts</th><th>Method</th>"
NULL);
ap_rprintf(r, "<td align='center'>%" APR_SIZE_T_FMT "</td><td align='center'>", worker->s->elected);
++workers;
++balancer;
NULL);
NULL);
ap_rputs("<td><table border='1'><tr><th>Ign</th><th>Drn</th><th>Dis</th><th>Stby</th></tr>\n<tr>", r);
} else if (bsel) {
if (provs) {
return OK;
unsigned int num;
s = s->next;
unsigned int index;
return APR_SUCCESS;
int found;
return APR_EGENERAL;
found = 0;
if (!found) {
return rv;
return APR_SUCCESS;