]> granicus.if.org Git - apache/commitdiff
* mod_proxy: Allow setting options to globally defined balancer from
authorJan Kaluža <jkaluza@apache.org>
Thu, 19 Mar 2015 11:29:55 +0000 (11:29 +0000)
committerJan Kaluža <jkaluza@apache.org>
Thu, 19 Mar 2015 11:29:55 +0000 (11:29 +0000)
  ProxyPass used in VirtualHost. Balancers are now merged using the new
  merge_balancers method which merges the balancers options.

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1667707 13f79535-47bb-0310-9956-ffa450edef68

modules/proxy/mod_proxy.c
modules/proxy/mod_proxy.h

index a1403e1e80681ee07986097aae1b444a3f07ab2a..3c6dce3469e68efd98e31c4266a89ff5a3168e18 100644 (file)
@@ -315,6 +315,7 @@ static const char *set_balancer_param(proxy_server_conf *conf,
         }
         else
             balancer->s->sticky_separator = *val;
+        balancer->s->sticky_separator_set = 1;
     }
     else if (!strcasecmp(key, "nofailover")) {
         /* If set to 'on' the session will break
@@ -327,6 +328,7 @@ static const char *set_balancer_param(proxy_server_conf *conf,
             balancer->s->sticky_force = 0;
         else
             return "failover must be On|Off";
+        balancer->s->sticky_force_set = 1;
     }
     else if (!strcasecmp(key, "timeout")) {
         /* Balancer timeout in seconds.
@@ -357,6 +359,7 @@ static const char *set_balancer_param(proxy_server_conf *conf,
         if (provider) {
             balancer->lbmethod = provider;
             if (PROXY_STRNCPY(balancer->s->lbpname, val) == APR_SUCCESS) {
+                balancer->lbmethod_set = 1;
                 return NULL;
             }
             else {
@@ -376,6 +379,7 @@ static const char *set_balancer_param(proxy_server_conf *conf,
             balancer->s->scolonsep = 0;
         else
             return "scolonpathdelim must be On|Off";
+        balancer->s->scolonsep_set = 1;
     }
     else if (!strcasecmp(key, "failonstatus")) {
         char *val_split;
@@ -406,6 +410,7 @@ static const char *set_balancer_param(proxy_server_conf *conf,
             balancer->failontimeout = 0;
         else
             return "failontimeout must be On|Off";
+        balancer->failontimeout_set = 1;
     }
     else if (!strcasecmp(key, "nonce")) {
         if (!strcasecmp(val, "None")) {
@@ -416,12 +421,14 @@ static const char *set_balancer_param(proxy_server_conf *conf,
                 return "Provided nonce is too large";
             }
         }
+        balancer->s->nonce_set = 1;
     }
     else if (!strcasecmp(key, "growth")) {
         ival = atoi(val);
         if (ival < 1 || ival > 100)   /* arbitrary limit here */
             return "growth must be between 1 and 100";
         balancer->growth = ival;
+        balancer->growth_set = 1;
     }
     else if (!strcasecmp(key, "forcerecovery")) {
         if (!strcasecmp(val, "on"))
@@ -430,6 +437,7 @@ static const char *set_balancer_param(proxy_server_conf *conf,
             balancer->s->forcerecovery = 0;
         else
             return "forcerecovery must be On|Off";
+        balancer->s->forcerecovery_set = 1;
     }
     else {
         return "unknown Balancer parameter";
@@ -1279,6 +1287,99 @@ static void * create_proxy_config(apr_pool_t *p, server_rec *s)
     return ps;
 }
 
+static apr_array_header_t *merge_balancers(apr_pool_t *p,
+                                           apr_array_header_t *base,
+                                           apr_array_header_t *overrides)
+{
+    proxy_balancer *b1;
+    proxy_balancer *b2;
+    proxy_balancer tmp;
+    int x, y, found;
+    apr_array_header_t *tocopy = apr_array_make(p, 1, sizeof(proxy_balancer));
+
+    /* Check if the balancer is defined in both override and base configs:
+     * a) If it is, Create copy of base balancer and change the configuration
+     *    which can be changed by ProxyPass.
+     * b) Otherwise, copy the balancer to tocopy array and merge it later.
+     */
+    b1 = (proxy_balancer *) base->elts;
+    for (y = 0; y < base->nelts; y++) {
+        b2 = (proxy_balancer *) overrides->elts;
+        for (x = 0, found = 0; x < overrides->nelts; x++) {
+            if (b1->hash.def == b2->hash.def && b1->hash.fnv == b2->hash.fnv) {
+                tmp = *b2;
+                *b2 = *b1;
+                b2->s = tmp.s;
+
+                /* For shared memory entries, b2->s belongs to override
+                 * balancer, so if some entry is not set there, we have to
+                 * update it according to the base balancer. */
+                if (*b2->s->sticky == 0 && *b1->s->sticky) {
+                    PROXY_STRNCPY(b2->s->sticky_path, b1->s->sticky_path);
+                    PROXY_STRNCPY(b2->s->sticky, b1->s->sticky);
+                }
+                if (!b2->s->sticky_separator_set
+                    && b1->s->sticky_separator_set) {
+                    b2->s->sticky_separator_set = b1->s->sticky_separator_set;
+                    b2->s->sticky_separator = b1->s->sticky_separator;
+                }
+                if (!b2->s->timeout && b1->s->timeout) {
+                    b2->s->timeout = b1->s->timeout;
+                }
+                if (!b2->s->max_attempts_set && b1->s->max_attempts_set) {
+                    b2->s->max_attempts_set = b1->s->max_attempts_set;
+                    b2->s->max_attempts = b1->s->max_attempts;
+                }
+                if (!b2->s->nonce_set && b1->s->nonce_set) {
+                    b2->s->nonce_set = b1->s->nonce_set;
+                    PROXY_STRNCPY(b2->s->nonce, b1->s->nonce);
+                }
+                if (!b2->s->sticky_force_set && b1->s->sticky_force_set) {
+                    b2->s->sticky_force_set = b1->s->sticky_force_set;
+                    b2->s->sticky_force = b1->s->sticky_force;
+                }
+                if (!b2->s->scolonsep_set && b1->s->scolonsep_set) {
+                    b2->s->scolonsep_set = b1->s->scolonsep_set;
+                    b2->s->scolonsep = b1->s->scolonsep;
+                }
+                if (!b2->s->forcerecovery_set && b1->s->forcerecovery_set) {
+                    b2->s->forcerecovery_set = b1->s->forcerecovery_set;
+                    b2->s->forcerecovery = b1->s->forcerecovery;
+                }
+
+                /* For non-shared memory entries, b2 is copy of b1, so we have
+                 * to use tmp copy of b1 to detect changes done in override. */
+                if (tmp.lbmethod_set) {
+                    b2->lbmethod_set = tmp.lbmethod_set;
+                    b2->lbmethod = tmp.lbmethod;
+                }
+                if (tmp.growth_set) {
+                    b2->growth_set = tmp.growth_set;
+                    b2->growth = tmp.growth;
+                }
+                if (tmp.failontimeout_set) {
+                    b2->failontimeout_set = tmp.failontimeout_set;
+                    b2->failontimeout = tmp.failontimeout;
+                }
+                if (!apr_is_empty_array(tmp.errstatuses)) {
+                    apr_array_cat(tmp.errstatuses, b2->errstatuses);
+                    b2->errstatuses = tmp.errstatuses;
+                }
+
+                found = 1;
+                break;
+            }
+            b2++;
+        }
+        if (!found) {
+            *(proxy_balancer *)apr_array_push(tocopy) = *b1;
+        }
+        b1++;
+    }
+
+    return apr_array_append(p, tocopy, overrides);
+}
+
 static void * merge_proxy_config(apr_pool_t *p, void *basev, void *overridesv)
 {
     proxy_server_conf *ps = apr_pcalloc(p, sizeof(proxy_server_conf));
@@ -1303,7 +1404,7 @@ static void * merge_proxy_config(apr_pool_t *p, void *basev, void *overridesv)
     ps->dirconn = apr_array_append(p, base->dirconn, overrides->dirconn);
     if (ps->inherit || ps->ppinherit) {
         ps->workers = apr_array_append(p, base->workers, overrides->workers);
-        ps->balancers = apr_array_append(p, base->balancers, overrides->balancers);
+        ps->balancers = merge_balancers(p, base->balancers, overrides->balancers);
     }
     else {
         ps->workers = overrides->workers;
index 9a5bb673835bb29571c4bd3242117e32b65da076..f97d336f038f94cba43ece43ad94c03ee6486f62 100644 (file)
@@ -443,6 +443,11 @@ typedef struct {
     unsigned int    inactive:1;
     unsigned int    forcerecovery:1;
     char      sticky_separator;                                /* separator for sessionid/route */
+    unsigned int    forcerecovery_set:1;
+    unsigned int    scolonsep_set:1;
+    unsigned int    sticky_force_set:1; 
+    unsigned int    nonce_set:1;
+    unsigned int    sticky_separator_set:1;
 } proxy_balancer_shared;
 
 #define ALIGNED_PROXY_BALANCER_SHARED_SIZE (APR_ALIGN_DEFAULT(sizeof(proxy_balancer_shared)))
@@ -463,6 +468,9 @@ struct proxy_balancer {
     void            *context;    /* general purpose storage */
     proxy_balancer_shared *s;    /* Shared data */
     int failontimeout;           /* Whether to mark a member in Err if IO timeout occurs */
+    unsigned int failontimeout_set:1;
+    unsigned int growth_set:1;
+    unsigned int lbmethod_set:1;
 };
 
 struct proxy_balancer_method {