--- mod_proxy_cluster.c.original	2011-08-26 14:48:15.000000000 -0400
+++ mod_cluster/native/mod_proxy_cluster/mod_proxy_cluster.c	2011-08-26 15:10:51.000000000 -0400
@@ -1099,6 +1099,53 @@
     return 0;
 }
 
+
+// VHost table copy for local use
+struct proxy_vhost_table
+{
+	int sizevhost;
+	int* vhosts;
+	hostinfo_t* vhost_info;
+};
+typedef struct proxy_vhost_table proxy_vhost_table;
+
+static void *read_vhost_table(request_rec *r, proxy_vhost_table *vhost_table)
+{
+    int i;
+    vhost_table->vhosts =  apr_palloc(r->pool, sizeof(int) * host_storage->get_max_size_host());
+    vhost_table->sizevhost = host_storage->get_ids_used_host(vhost_table->vhosts);
+    vhost_table->vhost_info = apr_palloc(r->pool, sizeof(hostinfo_t) * vhost_table->sizevhost);
+    for (i = 0; i < vhost_table->sizevhost; i++) {
+        hostinfo_t* h;
+        int host_index = vhost_table->vhosts[i];
+        host_storage->read_host(host_index, &h);
+        vhost_table->vhost_info[i] = *h;
+    }
+}
+
+// Context table copy for local use
+struct proxy_context_table
+{
+	int sizecontext;
+	int* contexts;
+	contextinfo_t* context_info;
+};
+typedef struct proxy_context_table proxy_context_table;
+
+static void *read_context_table(request_rec *r, proxy_context_table *context_table)
+{
+    int i;
+    context_table->contexts =  apr_palloc(r->pool, sizeof(int) * context_storage->get_max_size_context());
+    context_table->sizecontext = context_storage->get_ids_used_context(context_table->contexts);
+    context_table->context_info = apr_palloc(r->pool, sizeof(contextinfo_t) * context_table->sizecontext);
+    for (i = 0; i < context_table->sizecontext; i++) {
+        contextinfo_t* h;
+        int context_index = context_table->contexts[i];
+        context_storage->read_context(context_index, &h);
+        context_table->context_info[i] = *h;
+    }
+}
+
 /**
  * Find/Check the balancer corresponding to the request and the node.
  * @param r the request_rec.
@@ -1107,34 +1154,25 @@
  * @param balance the balancer (balancer to use in that case we check it).
  * @return the name of the balancer or NULL if not found/not corresponding
  */
-
-
-static char *get_balancer_by_node(request_rec *r, nodeinfo_t *node, proxy_server_conf *conf, proxy_balancer *balance)
+static char *get_balancer_by_node(request_rec *r, nodeinfo_t *node, proxy_server_conf *conf,
+		proxy_balancer *balance, proxy_vhost_table* vhost_table, proxy_context_table* context_table)
 { 
     int i;
-    int sizevhost;
-    int *vhosts;
 
     /*
      * check the hosts and contexts
      * A node may have several virtual hosts and
      * each virtual hosts may have several context
      */
-    sizevhost = host_storage->get_max_size_host();
-    vhosts =  apr_palloc(r->pool, sizeof(int)*sizevhost);
-    sizevhost = host_storage->get_ids_used_host(vhosts);
 #if HAVE_CLUSTER_EX_DEBUG
     ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
                  "get_balancer_by_node testing node %s for %s", node->mess.JVMRoute, r->uri);
 #endif
-    for (i=0; i<sizevhost; i++) {
-        hostinfo_t *vhost;
-        host_storage->read_host(vhosts[i], &vhost);
+    for (i=0; i<vhost_table->sizevhost; i++) {
+        hostinfo_t *vhost = vhost_table->vhost_info + vhost_table->vhosts[i];
         if (vhost->node == node->mess.id) {
             int j;
-            int sizecontext = context_storage->get_max_size_context();
-            int *contexts =  apr_palloc(r->pool, sizeof(int)*sizecontext);
-            int *root =  apr_palloc(r->pool, sizeof(int)*sizevhost);
+            int *root =  apr_palloc(r->pool, sizeof(int)*vhost_table->sizevhost);
             int froot = 0;
             int hasnonroot = 0;
 
@@ -1149,15 +1187,13 @@
             }
 
             /* Check the contexts */
-            sizecontext = context_storage->get_ids_used_context(contexts);
 #if HAVE_CLUSTER_EX_DEBUG
             ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,
                          "get_balancer_by_node testing host %s", vhost->host);
 #endif
-            for (j=0; j<sizecontext; j++) {
-                contextinfo_t *context;
+            for (j=0; j<context_table->sizecontext; j++) {
+                contextinfo_t *context = context_table->context_info + j;
                 int len;
-                context_storage->read_context(contexts[j], &context);
                 if (context->vhost != vhost->vhost || (context->node != node->mess.id))
                     continue;
 #if HAVE_CLUSTER_EX_DEBUG
@@ -1167,8 +1203,8 @@
 
                 /* check for /context[/] in the URL */
                 len = strlen(context->context);
-                if (len==1 && context->context[0] == '/' && froot<sizevhost) {
-                    root[froot] = contexts[j];
+                if (len==1 && context->context[0] == '/' && froot<vhost_table->sizevhost) {
+                    root[froot] = context_table->contexts[j];
                     froot++;
                     continue;
                 }
@@ -1236,7 +1272,8 @@
  * @balancer proxy_ ARF....
  * @return the balancer or NULL if not found.
  */ 
-static char *get_context_host_balancer(request_rec *r)
+static char *get_context_host_balancer(request_rec *r,
+		proxy_vhost_table *vhost_table, proxy_context_table *context_table)
 {
     void *sconf = r->server->module_config;
     proxy_server_conf *conf = (proxy_server_conf *)
@@ -1251,7 +1288,7 @@
         char *ret;
         if (node_storage->read_node(nodes[n], &node) != APR_SUCCESS)
             continue;
-        ret = get_balancer_by_node(r, node, conf, NULL);
+        ret = get_balancer_by_node(r, node, conf, NULL, vhost_table, context_table);
         if (ret) {
             /* Check that it is in our proxy_server_conf */
             char *name = apr_pstrcat(r->pool, "balancer://", ret, NULL);
@@ -1271,9 +1308,10 @@
  * memory.
  * (See get_context_host_balancer too).
  */ 
-static int iscontext_host_ok(request_rec *r, proxy_balancer *balancer, nodeinfo_t *node)
+static int iscontext_host_ok(request_rec *r, proxy_balancer *balancer, nodeinfo_t *node,
+		proxy_vhost_table *vhost_table, proxy_context_table *context_table)
 {
-    char *balancername = get_balancer_by_node(r, node, NULL, balancer);
+    char *balancername = get_balancer_by_node(r, node, NULL, balancer, vhost_table, context_table);
     if (balancername != NULL) {
         return 1; /* Found */
     }
@@ -1305,7 +1343,9 @@
  * We also try the domain.
  */
 static proxy_worker *internal_find_best_byrequests(proxy_balancer *balancer, proxy_server_conf *conf,
-                                         request_rec *r, const char *domain, int failoverdomain)
+                                         request_rec *r, const char *domain, int failoverdomain,
+                                         proxy_vhost_table *vhost_table,
+                                         proxy_context_table *context_table)
 {
     int i;
     proxy_worker *worker;
@@ -1353,7 +1393,8 @@
             if (node_storage->read_node(worker->id, &node) != APR_SUCCESS)
                 continue; /* Can't read node */
 
-            if (PROXY_WORKER_IS_USABLE(worker) && iscontext_host_ok(r, balancer, node)) {
+            if (PROXY_WORKER_IS_USABLE(worker) 
+                && iscontext_host_ok(r, balancer, node, vhost_table, context_table)) {
                 if (!checked_domain) {
                     /* First try only nodes in the domain */
                     if (!isnode_domain_ok(r, node, domain)) {
@@ -1382,6 +1423,7 @@
                 }
             }
         }
+
         if (mycandidate)
             break;
         if (checked_domain) {
@@ -1408,13 +1450,18 @@
 /*
  * Wrapper to mod_balancer "standard" interface.
  */
-static proxy_worker *find_best_byrequests(proxy_balancer *balancer,
-                                         request_rec *r)
+static proxy_worker *find_best_byrequests(proxy_balancer *balancer, request_rec *r)
 {
     void *sconf = r->server->module_config;
     proxy_server_conf *conf = (proxy_server_conf *)
         ap_get_module_config(sconf, &proxy_module);
-    return internal_find_best_byrequests(balancer, conf, r, NULL, 0);
+
+    proxy_vhost_table vhost_table;
+    proxy_context_table context_table;
+    read_vhost_table(r, &vhost_table);
+    read_context_table(r, &context_table);
+
+    return internal_find_best_byrequests(balancer, conf, r, NULL, 0, &vhost_table, &context_table);
 }
 
 /*
@@ -1929,6 +1976,11 @@
     proxy_server_conf *conf = (proxy_server_conf *)
         ap_get_module_config(sconf, &proxy_module);
 
+    proxy_vhost_table vhost_table;
+    proxy_context_table context_table;
+    read_vhost_table(r, &vhost_table);
+    read_context_table(r, &context_table);
+
 #if HAVE_CLUSTER_EX_DEBUG
     ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_DEBUG, 0, r->server,
                 "proxy_cluster_trans for %d %s %s uri: %s args: %s unparsed_uri: %s",
@@ -1942,11 +1994,11 @@
         balancer = get_route_balancer(r, conf);
     }
     if (!balancer)
-        balancer = get_context_host_balancer(r);
+        balancer = get_context_host_balancer(r, &vhost_table, &context_table);
     if (!balancer) {
         /* May be the balancer has not been created (we use shared memory to find the balancer name) */
         update_workers_node(conf, r->pool, r->server, 1);
-        balancer = get_context_host_balancer(r);
+        balancer = get_context_host_balancer(r, &vhost_table, &context_table);
     }
     
 
@@ -2058,8 +2110,9 @@
  * (Should we also find the domain corresponding to it).
  */
 static proxy_worker *find_route_worker(request_rec *r,
-                                       proxy_balancer *balancer,
-                                       const char *route)
+                                       proxy_balancer *balancer, const char *route,
+                                       proxy_vhost_table *vhost_table,
+                                       proxy_context_table *context_table)
 {
     int i;
     int checking_standby;
@@ -2083,7 +2136,7 @@
                     nodeinfo_t *node;
                     if (node_storage->read_node(worker->id, &node) != APR_SUCCESS)
                         return NULL; /* can't read node */
-                    if (iscontext_host_ok(r, balancer, node))
+                    if (iscontext_host_ok(r, balancer, node, vhost_table, context_table))
                        return worker;
                     else
                        return NULL; /* application has been removed from the node */
@@ -2109,7 +2162,8 @@
                          */
                         if (*worker->s->redirect) {
                             proxy_worker *rworker = NULL;
-                            rworker = find_route_worker(r, balancer, worker->s->redirect);
+                            rworker = find_route_worker(r, balancer, worker->s->redirect,
+                            		vhost_table, context_table);
                             /* Check if the redirect worker is usable */
                             if (rworker && !PROXY_WORKER_IS_USABLE(rworker)) {
                                 /*
@@ -2141,7 +2195,9 @@
                                         const char **route,
                                         const char **sticky_used,
                                         char **url,
-                                        const char **domain)
+                                        const char **domain,
+                                        proxy_vhost_table *vhost_table,
+                                        proxy_context_table *context_table)
 {
     proxy_worker *worker = NULL;
 
@@ -2166,7 +2222,7 @@
     /* We have a route in path or in cookie
      * Find the worker that has this route defined.
      */
-    worker = find_route_worker(r, balancer, *route);
+    worker = find_route_worker(r, balancer, *route, vhost_table, context_table);
     if (worker && strcmp(*route, worker->s->route)) {
         /*
          * Notice that the route of the worker chosen is different from
@@ -2181,7 +2237,9 @@
 }
 
 static proxy_worker *find_best_worker(proxy_balancer *balancer, proxy_server_conf *conf,
-                                      request_rec *r, const char *domain, int failoverdomain)
+                                      request_rec *r, const char *domain, int failoverdomain,
+                                      proxy_vhost_table *vhost_table,
+                                      proxy_context_table *context_table)
 {
     proxy_worker *candidate = NULL;
     apr_status_t rv;
@@ -2193,7 +2251,8 @@
     }
 
     /* XXX: candidate = (*balancer->lbmethod->finder)(balancer, r); */
-    candidate = internal_find_best_byrequests(balancer, conf, r, domain, failoverdomain);
+    candidate = internal_find_best_byrequests(balancer, conf, r, domain, failoverdomain,
+    		vhost_table, context_table);
 
     if ((rv = PROXY_THREAD_UNLOCK(balancer)) != APR_SUCCESS) {
         ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server,
@@ -2225,7 +2284,8 @@
             while (tval < timeout) {
                 apr_sleep(step);
                 /* Try again */
-                if ((candidate = find_best_worker(balancer, conf, r, domain, failoverdomain)))
+                if ((candidate = find_best_worker(balancer, conf, r,
+                		domain, failoverdomain, vhost_table, context_table)))
                     break;
                 tval += step;
             }
@@ -2358,6 +2418,12 @@
     proxy_cluster_helper *helper;
     const char *context_id;
 
+    proxy_vhost_table vhost_table;
+    proxy_context_table context_table;
+
+    read_vhost_table(r, &vhost_table);
+    read_context_table(r, &context_table);
+
     *worker = NULL;
 #if HAVE_CLUSTER_EX_DEBUG
      if (*balancer) {
@@ -2416,7 +2482,8 @@
 
     /* Step 2: find the session route */
 
-    runtime = find_session_route(*balancer, r, &route, &sticky, url, &domain);
+    runtime = find_session_route(*balancer, r, &route, &sticky, url, &domain,
+    		&vhost_table, &context_table);
     apr_thread_mutex_unlock(lock);
 
     /* Lock the LoadBalancer
@@ -2463,7 +2530,8 @@
         /* 
          * We have to failover (in domain only may be) or we don't use sticky sessions
          */
-        runtime = find_best_worker(*balancer, conf, r, domain, failoverdomain);
+        runtime = find_best_worker(*balancer, conf, r, domain, failoverdomain,
+        		&vhost_table, &context_table);
         if (!runtime) {
             ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
                          "proxy: CLUSTER: (%s). All workers are in error state",
