From: Jim Jagielski Date: Mon, 31 Jan 2011 20:28:52 +0000 (+0000) Subject: Move some "nice to be able to change" balancer stuff to shm X-Git-Tag: 2.3.11~129 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=12ae415dbed436d71942f1cd123103b746557bc4;p=thirdparty%2Fapache%2Fhttpd.git Move some "nice to be able to change" balancer stuff to shm git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1065748 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/configure.in b/configure.in index bdb6b7c2652..88ef769121d 100644 --- a/configure.in +++ b/configure.in @@ -529,7 +529,7 @@ AC_ARG_ENABLE(maintainer-mode,APACHE_HELP_STRING(--enable-maintainer-mode,Turn o [ APR_ADDTO(CPPFLAGS, -DAP_DEBUG) if test "$GCC" = "yes"; then - APR_ADDTO(CFLAGS,[-Wall -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations -Wpointer-arith]) + APR_ADDTO(CFLAGS,[-Wall -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations -Wpointer-arith -O0]) AC_CACHE_CHECK([whether gcc accepts -Wdeclaration-after-statement], [ap_cv_cc_Wdas], [ save_CFLAGS=$CFLAGS CFLAGS="$CFLAGS -Wdeclaration-after-statement" diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c index 490e54c7f31..97e0ccc6b3f 100644 --- a/modules/proxy/mod_proxy.c +++ b/modules/proxy/mod_proxy.c @@ -316,11 +316,14 @@ static const char *set_balancer_param(proxy_server_conf *conf, * Set to something like JSESSIONID or * PHPSESSIONID, etc.., */ - path = apr_pstrdup(p, val); - balancer->sticky = balancer->sticky_path = path; - if ((path = strchr(path, '|'))) { + if (strlen(val) > (PROXY_BALANCER_MAX_STICKY_SIZE-1)) + return "stickysession length must be < 64 characters"; + PROXY_STRNCPY(balancer->s->sticky_path, val); + PROXY_STRNCPY(balancer->s->sticky, val); + + if ((path = strchr((char *)val, '|'))) { *path++ = '\0'; - balancer->sticky_path = path; + PROXY_STRNCPY(balancer->s->sticky_path, path); } } else if (!strcasecmp(key, "nofailover")) { @@ -329,9 +332,9 @@ static const char *set_balancer_param(proxy_server_conf *conf, * disabled. */ if (!strcasecmp(val, "on")) - balancer->sticky_force = 1; + balancer->s->sticky_force = 1; else if (!strcasecmp(val, "off")) - balancer->sticky_force = 0; + balancer->s->sticky_force = 0; else return "failover must be On|Off"; } @@ -344,7 +347,7 @@ static const char *set_balancer_param(proxy_server_conf *conf, ival = atoi(val); if (ival < 1) return "timeout must be at least one second"; - balancer->timeout = apr_time_from_sec(ival); + balancer->s->timeout = apr_time_from_sec(ival); } else if (!strcasecmp(key, "maxattempts")) { /* Maximum number of failover attempts before @@ -353,8 +356,8 @@ static const char *set_balancer_param(proxy_server_conf *conf, ival = atoi(val); if (ival < 0) return "maximum number of attempts must be a positive number"; - balancer->max_attempts = ival; - balancer->max_attempts_set = 1; + balancer->s->max_attempts = ival; + balancer->s->max_attempts_set = 1; } else if (!strcasecmp(key, "lbmethod")) { proxy_balancer_method *provider; @@ -371,9 +374,9 @@ static const char *set_balancer_param(proxy_server_conf *conf, * mod_jk) */ if (!strcasecmp(val, "on")) - balancer->scolonsep = 1; + balancer->s->scolonsep = 1; else if (!strcasecmp(val, "off")) - balancer->scolonsep = 0; + balancer->s->scolonsep = 0; else return "scolonpathdelim must be On|Off"; } @@ -401,14 +404,14 @@ static const char *set_balancer_param(proxy_server_conf *conf, } else if (!strcasecmp(key, "nonce")) { if (!strcasecmp(val, "None")) { - *balancer->nonce = '\0'; + *balancer->s->nonce = '\0'; } else { - if (strlen(val) > sizeof(balancer->nonce)-1) { + if (strlen(val) > sizeof(balancer->s->nonce)-1) { return "Provided nonce is too large"; } else { - apr_cpystrn(balancer->nonce, val, sizeof(balancer->nonce)); + PROXY_STRNCPY(balancer->s->nonce, val); } } } @@ -1007,8 +1010,8 @@ static int proxy_handler(request_rec *r) ap_proxy_initialize_worker(worker, r->server, conf->pool); } - if (balancer && balancer->max_attempts_set && !max_attempts) - max_attempts = balancer->max_attempts; + if (balancer && balancer->s->max_attempts_set && !max_attempts) + max_attempts = balancer->s->max_attempts; /* firstly, try a proxy, unless a NoProxy directive is active */ if (!direct_connect) { for (i = 0; i < proxies->nelts; i++) { @@ -1150,6 +1153,7 @@ static void * create_proxy_config(apr_pool_t *p, server_rec *s) ps->forward = NULL; ps->reverse = NULL; ps->domain = NULL; + ps->id = apr_psprintf(p, "%pp", ps->noproxies); ps->viaopt = via_off; /* initially backward compatible with 1.3.1 */ ps->viaopt_set = 0; /* 0 means default */ ps->req = 0; @@ -1188,6 +1192,7 @@ static void * merge_proxy_config(apr_pool_t *p, void *basev, void *overridesv) ps->reverse = overrides->reverse ? overrides->reverse : base->reverse; ps->domain = (overrides->domain == NULL) ? base->domain : overrides->domain; + ps->id = (overrides->id == NULL) ? base->id : overrides->id; ps->viaopt = (overrides->viaopt_set == 0) ? base->viaopt : overrides->viaopt; ps->viaopt_set = overrides->viaopt_set || base->viaopt_set; ps->req = (overrides->req_set == 0) ? base->req : overrides->req; @@ -1466,7 +1471,7 @@ static const char * if (ap_proxy_valid_balancer_name(r, 9)) { proxy_balancer *balancer = ap_proxy_get_balancer(cmd->pool, conf, r); if (!balancer) { - const char *err = ap_proxy_define_balancer(cmd->pool, &balancer, conf, r); + const char *err = ap_proxy_define_balancer(cmd->pool, &balancer, conf, r, 0); if (err) return apr_pstrcat(cmd->temp_pool, "ProxyPass ", err, NULL); } @@ -1481,7 +1486,7 @@ static const char * proxy_worker *worker = ap_proxy_get_worker(cmd->temp_pool, NULL, conf, r); int reuse = 0; if (!worker) { - const char *err = ap_proxy_define_worker(cmd->pool, &worker, NULL, conf, r); + const char *err = ap_proxy_define_worker(cmd->pool, &worker, NULL, conf, r, 0); if (err) return apr_pstrcat(cmd->temp_pool, "ProxyPass ", err, NULL); @@ -1901,7 +1906,7 @@ static const char *add_member(cmd_parms *cmd, void *dummy, const char *arg) /* Try to find the balancer */ balancer = ap_proxy_get_balancer(cmd->temp_pool, conf, path); if (!balancer) { - err = ap_proxy_define_balancer(cmd->pool, &balancer, conf, path); + err = ap_proxy_define_balancer(cmd->pool, &balancer, conf, path, 0); if (err) return apr_pstrcat(cmd->temp_pool, "BalancerMember ", err, NULL); } @@ -1912,7 +1917,7 @@ static const char *add_member(cmd_parms *cmd, void *dummy, const char *arg) ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, "Defining worker '%s' for balancer '%s'", name, balancer->name); - if ((err = ap_proxy_define_worker(cmd->pool, &worker, balancer, conf, name)) != NULL) + if ((err = ap_proxy_define_worker(cmd->pool, &worker, balancer, conf, name, 0)) != NULL) return apr_pstrcat(cmd->temp_pool, "BalancerMember ", err, NULL); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, "Defined worker '%s' for balancer '%s'", @@ -1979,7 +1984,7 @@ static const char * balancer = ap_proxy_get_balancer(cmd->pool, conf, name); if (!balancer) { if (in_proxy_section) { - err = ap_proxy_define_balancer(cmd->pool, &balancer, conf, name); + err = ap_proxy_define_balancer(cmd->pool, &balancer, conf, name, 0); if (err) return apr_pstrcat(cmd->temp_pool, "ProxySet ", err, NULL); @@ -1994,7 +1999,7 @@ static const char * if (!worker) { if (in_proxy_section) { err = ap_proxy_define_worker(cmd->pool, &worker, NULL, - conf, name); + conf, name, 0); if (err) return apr_pstrcat(cmd->temp_pool, "ProxySet ", err, NULL); @@ -2128,7 +2133,7 @@ static const char *proxysection(cmd_parms *cmd, void *mconfig, const char *arg) balancer = ap_proxy_get_balancer(cmd->pool, sconf, conf->p); if (!balancer) { err = ap_proxy_define_balancer(cmd->pool, &balancer, - sconf, conf->p); + sconf, conf->p, 0); if (err) return apr_pstrcat(cmd->temp_pool, thiscmd->name, " ", err, NULL); @@ -2139,7 +2144,7 @@ static const char *proxysection(cmd_parms *cmd, void *mconfig, const char *arg) conf->p); if (!worker) { err = ap_proxy_define_worker(cmd->pool, &worker, NULL, - sconf, conf->p); + sconf, conf->p, 0); if (err) return apr_pstrcat(cmd->temp_pool, thiscmd->name, " ", err, NULL); @@ -2322,20 +2327,20 @@ static int proxy_status_hook(request_rec *r, int flags) ap_rputs("\n\n" "" "\n", r); - if (balancer->sticky) { - if (strcmp(balancer->sticky, balancer->sticky_path)) { - ap_rvputs(r, "", - apr_time_sec(balancer->timeout)); + apr_time_sec(balancer->s->timeout)); ap_rprintf(r, "\n", balancer->lbmethod->name); ap_rputs("
SSesTimeoutMethod
", balancer->sticky, " | ", - balancer->sticky_path, NULL); + if (*balancer->s->sticky) { + if (strcmp(balancer->s->sticky, balancer->s->sticky_path)) { + ap_rvputs(r, "", balancer->s->sticky, " | ", + balancer->s->sticky_path, NULL); } else { - ap_rvputs(r, "", balancer->sticky, NULL); + ap_rvputs(r, "", balancer->s->sticky, NULL); } } else { ap_rputs(" - ", r); } ap_rprintf(r, "%" APR_TIME_T_FMT "%s
\n", r); @@ -2416,7 +2421,7 @@ static void child_init(apr_pool_t *p, server_rec *s) /* Create and initialize forward worker if defined */ if (conf->req_set && conf->req) { proxy_worker *forward; - ap_proxy_define_worker(p, &forward, NULL, NULL, "http://www.apache.org"); + ap_proxy_define_worker(p, &forward, NULL, NULL, "http://www.apache.org", 0); conf->forward = forward; PROXY_STRNCPY(conf->forward->s->name, "proxy:forward"); PROXY_STRNCPY(conf->forward->s->hostname, "*"); @@ -2430,7 +2435,7 @@ static void child_init(apr_pool_t *p, server_rec *s) ap_proxy_initialize_worker(conf->forward, s, conf->pool); } if (!reverse) { - ap_proxy_define_worker(p, &reverse, NULL, NULL, "http://www.apache.org"); + ap_proxy_define_worker(p, &reverse, NULL, NULL, "http://www.apache.org", 0); PROXY_STRNCPY(reverse->s->name, "proxy:reverse"); PROXY_STRNCPY(reverse->s->hostname, "*"); PROXY_STRNCPY(reverse->s->scheme, "*"); diff --git a/modules/proxy/mod_proxy.h b/modules/proxy/mod_proxy.h index d394f7279ef..558a441ece9 100644 --- a/modules/proxy/mod_proxy.h +++ b/modules/proxy/mod_proxy.h @@ -135,6 +135,7 @@ typedef struct { proxy_worker *forward; /* forward proxy worker */ proxy_worker *reverse; /* reverse "module-driven" proxy worker */ const char *domain; /* domain name to use in absence of a domain name in the request */ + const char *id; apr_pool_t *pool; /* Pool used for allocating this struct */ int req; /* true if proxy requests are enabled */ enum { @@ -159,6 +160,7 @@ typedef struct { } proxy_status; /* Status display options */ apr_sockaddr_t *source_address; apr_global_mutex_t *mutex; /* global lock (needed??) */ + ap_slotmem_instance_t *slot; /* balancers shm data - runtime */ int req_set:1; int viaopt_set:1; @@ -275,10 +277,13 @@ PROXY_WORKER_DISABLED | PROXY_WORKER_STOPPED | PROXY_WORKER_IN_ERROR ) PROXY_WORKER_IS_INITIALIZED(f) ) /* default worker retry timeout in seconds */ -#define PROXY_WORKER_DEFAULT_RETRY 60 -#define PROXY_WORKER_MAX_SCHEME_SIZE 16 -#define PROXY_WORKER_MAX_ROUTE_SIZE 64 -#define PROXY_WORKER_MAX_NAME_SIZE 96 +#define PROXY_WORKER_DEFAULT_RETRY 60 + +/* Some max char string sizes, for shm fields */ +#define PROXY_WORKER_MAX_SCHEME_SIZE 16 +#define PROXY_WORKER_MAX_ROUTE_SIZE 64 +#define PROXY_WORKER_MAX_NAME_SIZE 96 +#define PROXY_BALANCER_MAX_STICKY_SIZE 64 #define PROXY_STRNCPY(dst, src) apr_cpystrn((dst), (src), sizeof(dst)) @@ -306,6 +311,7 @@ typedef struct { flush_on, flush_auto } flush_packets; /* control AJP flushing */ + apr_time_t updated; /* timestamp of last update */ apr_time_t error_time; /* time of the last error */ apr_interval_time_t ttl; /* maximum amount of time in seconds a connection * may be available while exceeding the soft limit */ @@ -334,13 +340,13 @@ typedef struct { unsigned int io_buffer_size_set:1; unsigned int keepalive_set:1; unsigned int disablereuse_set:1; + unsigned int was_malloced:1; } proxy_worker_shared; #define ALIGNED_PROXY_WORKER_SHARED_SIZE (APR_ALIGN_DEFAULT(sizeof(proxy_worker_shared))) /* Worker configuration */ struct proxy_worker { - int index; /* shm array index */ unsigned int hash; /* hash of worker name */ proxy_conn_pool *cp; /* Connection pool to use */ proxy_worker_shared *s; /* Shared data */ @@ -356,29 +362,35 @@ struct proxy_worker { */ #define PROXY_FLUSH_WAIT 10000 +typedef struct { + char sticky_path[PROXY_BALANCER_MAX_STICKY_SIZE]; /* URL sticky session identifier */ + char sticky[PROXY_BALANCER_MAX_STICKY_SIZE]; /* sticky session identifier */ + char nonce[APR_UUID_FORMATTED_LENGTH + 1]; + apr_interval_time_t timeout; /* Timeout for waiting on free connection */ + apr_time_t updated; /* timestamp of last update */ + int max_attempts; /* Number of attempts before failing */ + int index; /* shm array index */ + int sticky_force:1; /* Disable failover for sticky sessions */ + int scolonsep:1; /* true if ';' seps sticky session paths */ + int max_attempts_set:1; + unsigned int was_malloced:1; +} proxy_balancer_shared; + +#define ALIGNED_PROXY_BALANCER_SHARED_SIZE (APR_ALIGN_DEFAULT(sizeof(proxy_balancer_shared))) + struct proxy_balancer { apr_array_header_t *workers; /* initially configured workers */ + apr_array_header_t *errstatuses; /* statuses to force members into error */ ap_slotmem_instance_t *slot; /* worker shm data - runtime */ + proxy_balancer_method *lbmethod; int growth; /* number of post-config workers can added */ int max_workers; /* maximum number of allowed workers */ const char *name; /* name of the load balancer */ const char *sname; /* filesystem safe balancer name */ - apr_interval_time_t timeout; /* Timeout for waiting on free connection */ - const char *lbprovider; /* name of the lbmethod provider to use */ - proxy_balancer_method *lbmethod; - - const char *sticky_path; /* URL sticky session identifier */ - apr_array_header_t *errstatuses; /* statuses to force members into error */ - const char *sticky; /* sticky session identifier */ - int max_attempts; /* Number of attempts before failing */ - apr_time_t updated; /* timestamp of last update */ - char nonce[APR_UUID_FORMATTED_LENGTH + 1]; apr_global_mutex_t *mutex; /* global lock for updating lb params */ void *context; /* general purpose storage */ - int sticky_force:1; /* Disable failover for sticky sessions */ - int scolonsep:1; /* true if ';' seps sticky session paths */ - int max_attempts_set:1; + proxy_balancer_shared *s; /* Shared data */ }; struct proxy_balancer_method { @@ -537,13 +549,15 @@ PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p, * @param balancer the balancer that the worker belongs to * @param conf current proxy server configuration * @param url url containing worker name + * @param do_malloc true if shared struct should be malloced * @return error message or NULL if successful (*worker is new worker) */ PROXY_DECLARE(char *) ap_proxy_define_worker(apr_pool_t *p, - proxy_worker **worker, - proxy_balancer *balancer, - proxy_server_conf *conf, - const char *url); + proxy_worker **worker, + proxy_balancer *balancer, + proxy_server_conf *conf, + const char *url, + int do_malloc); /** * Share a defined proxy worker via shm @@ -591,12 +605,36 @@ PROXY_DECLARE(proxy_balancer *) ap_proxy_get_balancer(apr_pool_t *p, * @param balancer the new balancer * @param conf current proxy server configuration * @param url url containing balancer name + * @param do_malloc true if shared struct should be malloced * @return error message or NULL if successfull */ PROXY_DECLARE(char *) ap_proxy_define_balancer(apr_pool_t *p, - proxy_balancer **balancer, - proxy_server_conf *conf, - const char *url); + proxy_balancer **balancer, + proxy_server_conf *conf, + const char *url, + int do_malloc); + +/** + * Share a defined proxy balancer via shm + * @param balancer balancer to be shared + * @param shm location of shared info + * @param i index into shm + * @return APR_SUCCESS or error code + */ +PROXY_DECLARE(apr_status_t) ap_proxy_share_balancer(proxy_balancer *balancer, + proxy_balancer_shared *shm, + int i); + +/** + * Initialize the balancer as needed + * @param balancer balancer to initialize + * @param s current server record + * @param p memory pool used for mutex and connection pool + * @return APR_SUCCESS or error code + */ +PROXY_DECLARE(apr_status_t) ap_proxy_initialize_balancer(proxy_balancer *balancer, + server_rec *s, + apr_pool_t *p); /** * Get the most suitable worker and/or balancer for the request diff --git a/modules/proxy/mod_proxy_balancer.c b/modules/proxy/mod_proxy_balancer.c index 0923253ed28..36825cb6385 100644 --- a/modules/proxy/mod_proxy_balancer.c +++ b/modules/proxy/mod_proxy_balancer.c @@ -127,9 +127,9 @@ static void init_balancer_members(proxy_server_conf *conf, server_rec *s, /* Set default number of attempts to the number of * workers. */ - if (!balancer->max_attempts_set && balancer->workers->nelts > 1) { - balancer->max_attempts = balancer->workers->nelts - 1; - balancer->max_attempts_set = 1; + if (!balancer->s->max_attempts_set && balancer->workers->nelts > 1) { + balancer->s->max_attempts = balancer->workers->nelts - 1; + balancer->s->max_attempts_set = 1; } } @@ -271,23 +271,23 @@ static proxy_worker *find_session_route(proxy_balancer *balancer, { proxy_worker *worker = NULL; - if (!balancer->sticky) + if (!*balancer->s->sticky) return NULL; /* Try to find the sticky route inside url */ - *route = get_path_param(r->pool, *url, balancer->sticky_path, balancer->scolonsep); + *route = get_path_param(r->pool, *url, balancer->s->sticky_path, balancer->s->scolonsep); if (*route) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: BALANCER: Found value %s for " - "stickysession %s", *route, balancer->sticky_path); - *sticky_used = balancer->sticky_path; + "stickysession %s", *route, balancer->s->sticky_path); + *sticky_used = balancer->s->sticky_path; } else { - *route = get_cookie_param(r, balancer->sticky); + *route = get_cookie_param(r, balancer->s->sticky); if (*route) { - *sticky_used = balancer->sticky; + *sticky_used = balancer->s->sticky; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: BALANCER: Found value %s for " - "stickysession %s", *route, balancer->sticky); + "stickysession %s", *route, balancer->s->sticky); } } /* @@ -354,18 +354,18 @@ static proxy_worker *find_best_worker(proxy_balancer *balancer, * By default the timeout is not set, and the server * returns SERVER_BUSY. */ - if (balancer->timeout) { + if (balancer->s->timeout) { /* XXX: This can perhaps be build using some * smarter mechanism, like tread_cond. * But since the statuses can came from * different childs, use the provided algo. */ - apr_interval_time_t timeout = balancer->timeout; + apr_interval_time_t timeout = balancer->s->timeout; apr_interval_time_t step, tval = 0; /* Set the timeout to 0 so that we don't * end in infinite loop */ - balancer->timeout = 0; + balancer->s->timeout = 0; step = timeout / 100; while (tval < timeout) { apr_sleep(step); @@ -375,7 +375,7 @@ static proxy_worker *find_best_worker(proxy_balancer *balancer, tval += step; } /* restore the timeout */ - balancer->timeout = timeout; + balancer->s->timeout = timeout; } } @@ -509,7 +509,7 @@ static int proxy_balancer_pre_request(proxy_worker **worker, *worker = runtime; } - else if (route && (*balancer)->sticky_force) { + else if (route && (*balancer)->s->sticky_force) { int i, member_of = 0; proxy_worker **workers; /* @@ -558,7 +558,7 @@ static int proxy_balancer_pre_request(proxy_worker **worker, return HTTP_SERVICE_UNAVAILABLE; } - if ((*balancer)->sticky && runtime) { + if (*(*balancer)->s->sticky && runtime) { /* * This balancer has sticky sessions and the client either has not * supplied any routing information or all workers for this route @@ -694,10 +694,12 @@ static apr_status_t lock_remove(void *data) static int balancer_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) { + apr_status_t rv; void *data; void *sconf = s->module_config; proxy_server_conf *conf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); const char *userdata_key = "mod_proxy_balancer_init"; + ap_slotmem_instance_t *new = NULL; /* balancer_post_config() will be called twice during startup. So, only * set up the static data the 1st time through. */ @@ -709,7 +711,7 @@ static int balancer_post_config(apr_pool_t *pconf, apr_pool_t *plog, } /* - * Get worker slotmem setup + * Get slotmem setups */ storage = ap_lookup_provider(AP_SLOTMEM_PROVIDER_GROUP, "shared", "0"); if (!storage) { @@ -717,23 +719,40 @@ static int balancer_post_config(apr_pool_t *pconf, apr_pool_t *plog, "ap_lookup_provider %s failed", AP_SLOTMEM_PROVIDER_GROUP); return !OK; } + + /* * Go thru each Vhost and create the shared mem slotmem for * each balancer's workers */ while (s) { int i,j; - apr_status_t rv; proxy_balancer *balancer; sconf = s->module_config; conf = (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module); + if (conf->balancers->nelts) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Doing balancers create: %d, %d", + (int)ALIGNED_PROXY_BALANCER_SHARED_SIZE, + (int)conf->balancers->nelts); + + rv = storage->create(&new, conf->id, + ALIGNED_PROXY_BALANCER_SHARED_SIZE, + conf->balancers->nelts, AP_SLOTMEM_TYPE_PREGRAB, pconf); + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, "balancer slotmem_create failed"); + return !OK; + } + conf->slot = new; + } + /* Initialize shared scoreboard data */ balancer = (proxy_balancer *)conf->balancers->elts; for (i = 0; i < conf->balancers->nelts; i++, balancer++) { proxy_worker **workers; proxy_worker *worker; - ap_slotmem_instance_t *new = NULL; + proxy_balancer_shared *bshm; + unsigned int index; balancer->max_workers = balancer->workers->nelts + balancer->growth; ap_pstr2_alnum(pconf, balancer->name, &balancer->sname); @@ -751,7 +770,23 @@ static int balancer_post_config(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_cleanup_register(pconf, (void *)s, lock_remove, apr_pool_cleanup_null); - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Doing create: %s (%s), %d, %d", + /* setup shm for balancers */ + if ((rv = storage->grab(conf->slot, &index)) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, "balancer slotmem_grab failed"); + return !OK; + + } + if ((rv = storage->dptr(conf->slot, index, (void *)&bshm)) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, "balancer slotmem_dptr failed"); + return !OK; + } + if ((rv = ap_proxy_share_balancer(balancer, bshm, index)) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, "Cannot share balancer"); + return !OK; + } + + /* create slotmem slots for workers */ + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Doing workers create: %s (%s), %d, %d", balancer->name, balancer->sname, (int)ALIGNED_PROXY_WORKER_SHARED_SIZE, (int)balancer->max_workers); @@ -760,24 +795,24 @@ static int balancer_post_config(apr_pool_t *pconf, apr_pool_t *plog, ALIGNED_PROXY_WORKER_SHARED_SIZE, balancer->max_workers, AP_SLOTMEM_TYPE_PREGRAB, pconf); if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, "slotmem_create failed"); + ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, "worker slotmem_create failed"); return !OK; } balancer->slot = new; + /* now go thru each worker */ workers = (proxy_worker **)balancer->workers->elts; for (j = 0; j < balancer->workers->nelts; j++, workers++) { proxy_worker_shared *shm; - unsigned int index; worker = *workers; if ((rv = storage->grab(balancer->slot, &index)) != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, "slotmem_grab failed"); + ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, "worker slotmem_grab failed"); return !OK; } if ((rv = storage->dptr(balancer->slot, index, (void *)&shm)) != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, "slotmem_dptr failed"); + ap_log_error(APLOG_MARK, APLOG_EMERG, rv, s, "worker slotmem_dptr failed"); return !OK; } if ((rv = ap_proxy_share_worker(worker, shm, index)) != APR_SUCCESS) { @@ -854,10 +889,10 @@ static int balancer_handler(request_rec *r) /* Check that the supplied nonce matches this server's nonce; * otherwise ignore all parameters, to prevent a CSRF attack. */ if (!bsel || - (*bsel->nonce && + (*bsel->s->nonce && ( (name = apr_table_get(params, "nonce")) == NULL || - strcmp(bsel->nonce, name) != 0 + strcmp(bsel->s->nonce, name) != 0 ) ) ) { @@ -954,21 +989,21 @@ static int balancer_handler(request_rec *r) "MaxMembersStickySessionTimeoutFailoverAttemptsMethod" "\n", r); ap_rprintf(r, "%d\n", balancer->max_workers); - if (balancer->sticky) { - if (strcmp(balancer->sticky, balancer->sticky_path)) { - ap_rvputs(r, "", balancer->sticky, " | ", - balancer->sticky_path, NULL); + if (*balancer->s->sticky) { + if (strcmp(balancer->s->sticky, balancer->s->sticky_path)) { + ap_rvputs(r, "", balancer->s->sticky, " | ", + balancer->s->sticky_path, NULL); } else { - ap_rvputs(r, "", balancer->sticky, NULL); + ap_rvputs(r, "", balancer->s->sticky, NULL); } } else { ap_rputs(" - ", r); } ap_rprintf(r, "%" APR_TIME_T_FMT "", - apr_time_sec(balancer->timeout)); - ap_rprintf(r, "%d\n", balancer->max_attempts); + apr_time_sec(balancer->s->timeout)); + ap_rprintf(r, "%d\n", balancer->s->max_attempts); ap_rprintf(r, "%s\n", balancer->lbmethod->name); ap_rputs("\n
", r); @@ -986,7 +1021,7 @@ static int balancer_handler(request_rec *r) ap_rvputs(r, "\nuri, "?b=", balancer->name + sizeof(BALANCER_PREFIX) - 1, "&w=", ap_escape_uri(r->pool, worker->s->name), - "&nonce=", balancer->nonce, + "&nonce=", balancer->s->nonce, "\">", NULL); ap_rvputs(r, worker->s->name, "", NULL); ap_rvputs(r, "", ap_escape_html(r->pool, worker->s->route), @@ -1051,7 +1086,7 @@ static int balancer_handler(request_rec *r) ap_rvputs(r, "value=\"", bsel->name + sizeof(BALANCER_PREFIX) - 1, "\">\n", NULL); ap_rvputs(r, "nonce, "\">\n", NULL); + bsel->s->nonce, "\">\n", NULL); ap_rvputs(r, "\n", NULL); ap_rputs("
\n", r); } @@ -1068,12 +1103,20 @@ static void balancer_child_init(apr_pool_t *p, server_rec *s) int i; void *sconf = s->module_config; proxy_server_conf *conf = (proxy_server_conf *)ap_get_module_config(sconf, &proxy_module); + apr_size_t size; + unsigned int num; apr_status_t rv; + if (conf->balancers->nelts) { + storage->attach(&(conf->slot), conf->id, &size, &num, p); + if (!conf->slot) { + ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, 0, s, "slotmem_attach failed"); + exit(1); /* Ugly, but what else? */ + } + } + balancer = (proxy_balancer *)conf->balancers->elts; for (i = 0; i < conf->balancers->nelts; i++) { - apr_size_t size; - unsigned int num; /* * for each balancer we need to init the global diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c index cf81e2474c4..4c075a3dae5 100644 --- a/modules/proxy/proxy_util.c +++ b/modules/proxy/proxy_util.c @@ -1326,13 +1326,16 @@ PROXY_DECLARE(proxy_balancer *) ap_proxy_get_balancer(apr_pool_t *p, } PROXY_DECLARE(char *) ap_proxy_define_balancer(apr_pool_t *p, - proxy_balancer **balancer, - proxy_server_conf *conf, - const char *url) + proxy_balancer **balancer, + proxy_server_conf *conf, + const char *url, + int do_malloc) { - char *c, *q, *uri = apr_pstrdup(p, url); + char nonce[APR_UUID_FORMATTED_LENGTH + 1]; proxy_balancer_method *lbmethod; apr_uuid_t uuid; + proxy_balancer_shared *bshared; + char *c, *q, *uri = apr_pstrdup(p, url); /* We should never get here without a valid BALANCER_PREFIX... */ @@ -1357,33 +1360,55 @@ PROXY_DECLARE(char *) ap_proxy_define_balancer(apr_pool_t *p, } (*balancer)->name = uri; - (*balancer)->lbmethod = lbmethod; (*balancer)->workers = apr_array_make(p, 5, sizeof(proxy_worker *)); - (*balancer)->updated = apr_time_now(); (*balancer)->mutex = NULL; + + if (do_malloc) + bshared = malloc(sizeof(proxy_balancer_shared)); + else + bshared = apr_palloc(p, sizeof(proxy_balancer_shared)); + + memset(bshared, 0, sizeof(proxy_balancer_shared)); + + (*balancer)->lbmethod = lbmethod; + bshared->updated = apr_time_now(); + bshared->was_malloced = (do_malloc != 0); + /* Retrieve a UUID and store the nonce for the lifetime of * the process. */ apr_uuid_get(&uuid); - apr_uuid_format((*balancer)->nonce, &uuid); + apr_uuid_format(nonce, &uuid); + PROXY_STRNCPY(bshared->nonce, nonce); + + (*balancer)->s = bshared; return NULL; } -#if 0 /* * Create an already defined balancer and free up memory. - * Placeholder for when we make +/- of balancers runtime as well */ -PROXY_DECLARE(void) ap_proxy_share_balancer(TODO) +PROXY_DECLARE(apr_status_t) ap_proxy_share_balancer(proxy_balancer *balancer, + proxy_balancer_shared *shm, + int i) { + if (!shm || !balancer->s) + return APR_EINVAL; + + memcpy(shm, balancer->s, sizeof(proxy_balancer_shared)); + if (balancer->s->was_malloced) + free(balancer->s); + balancer->s = shm; + balancer->s->index = i; + return APR_SUCCESS; } -PROXY_DECLARE(void) ap_proxy_initialize_balancer(TODO) +PROXY_DECLARE(apr_status_t) ap_proxy_initialize_balancer(proxy_balancer *balancer, server_rec *s, apr_pool_t *p) { + apr_status_t rv = APR_SUCCESS; + return rv; } -#endif - /* * CONNECTION related... */ @@ -1652,14 +1677,15 @@ PROXY_DECLARE(proxy_worker *) ap_proxy_get_worker(apr_pool_t *p, * config and runtime. */ PROXY_DECLARE(char *) ap_proxy_define_worker(apr_pool_t *p, - proxy_worker **worker, - proxy_balancer *balancer, - proxy_server_conf *conf, - const char *url) + proxy_worker **worker, + proxy_balancer *balancer, + proxy_server_conf *conf, + const char *url, + int do_malloc) { int rv; apr_uri_t uri; - proxy_worker_shared *wstatus; + proxy_worker_shared *wshared; rv = apr_uri_parse(p, url, &uri); @@ -1697,30 +1723,31 @@ PROXY_DECLARE(char *) ap_proxy_define_worker(apr_pool_t *p, /* right here we just want to tuck away the worker info. * if called during config, we don't have shm setup yet, * so just note the info for later. */ -#if 0 - wstatus = malloc(sizeof(proxy_worker_shared)); /* will be freed ap_proxy_share_worker */ -#else - wstatus = apr_palloc(p, sizeof(proxy_worker_shared)); -#endif - memset(wstatus, 0, sizeof(proxy_worker_shared)); - - PROXY_STRNCPY(wstatus->name, apr_uri_unparse(p, &uri, APR_URI_UNP_REVEALPASSWORD)); - PROXY_STRNCPY(wstatus->scheme, uri.scheme); - PROXY_STRNCPY(wstatus->hostname, uri.hostname); - wstatus->port = uri.port; - wstatus->flush_packets = flush_off; - wstatus->flush_wait = PROXY_FLUSH_WAIT; - wstatus->is_address_reusable = 1; - wstatus->lbfactor = 1; - wstatus->smax = -1; - wstatus->hash = ap_proxy_hashfunc(wstatus->name, PROXY_HASHFUNC_DEFAULT); - - (*worker)->hash = wstatus->hash; + if (do_malloc) + wshared = malloc(sizeof(proxy_worker_shared)); /* will be freed ap_proxy_share_worker */ + else + wshared = apr_palloc(p, sizeof(proxy_worker_shared)); + + memset(wshared, 0, sizeof(proxy_worker_shared)); + + PROXY_STRNCPY(wshared->name, apr_uri_unparse(p, &uri, APR_URI_UNP_REVEALPASSWORD)); + PROXY_STRNCPY(wshared->scheme, uri.scheme); + PROXY_STRNCPY(wshared->hostname, uri.hostname); + wshared->port = uri.port; + wshared->flush_packets = flush_off; + wshared->flush_wait = PROXY_FLUSH_WAIT; + wshared->is_address_reusable = 1; + wshared->lbfactor = 1; + wshared->smax = -1; + wshared->hash = ap_proxy_hashfunc(wshared->name, PROXY_HASHFUNC_DEFAULT); + wshared->was_malloced = (do_malloc != 0); + + (*worker)->hash = wshared->hash; (*worker)->context = NULL; (*worker)->cp = NULL; (*worker)->mutex = NULL; (*worker)->balancer = balancer; - (*worker)->s = wstatus; + (*worker)->s = wshared; return NULL; } @@ -1728,15 +1755,15 @@ PROXY_DECLARE(char *) ap_proxy_define_worker(apr_pool_t *p, /* * Create an already defined worker and free up memory */ -PROXY_DECLARE(apr_status_t) ap_proxy_share_worker(proxy_worker *worker, proxy_worker_shared *shm, int i) +PROXY_DECLARE(apr_status_t) ap_proxy_share_worker(proxy_worker *worker, proxy_worker_shared *shm, + int i) { if (!shm || !worker->s) return APR_EINVAL; memcpy(shm, worker->s, sizeof(proxy_worker_shared)); -#if 0 - free(worker->s); /* was malloced in ap_proxy_define_worker */ -#endif + if (worker->s->was_malloced) + free(worker->s); /* was malloced in ap_proxy_define_worker */ worker->s = shm; worker->s->index = i; return APR_SUCCESS;