Skip to content

Commit

Permalink
Merge pull request modcluster#189 from Karm/MODCLUSTER-376-1.2.x
Browse files Browse the repository at this point in the history
MODCLUSTER-376 multiple workers with the same id following a tomcat c…
  • Loading branch information
jfclere committed Jun 2, 2016
2 parents 39a1314 + 6640736 commit 93192f3
Showing 1 changed file with 94 additions and 19 deletions.
113 changes: 94 additions & 19 deletions native/mod_proxy_cluster/mod_proxy_cluster.c
Expand Up @@ -35,6 +35,7 @@
#include "http_request.h"
#include "http_protocol.h"
#include "http_core.h"
#include "scoreboard.h"
#include "ap_mpm.h"
#include "mod_proxy.h"

Expand Down Expand Up @@ -862,7 +863,7 @@ static void add_balancers_workers(nodeinfo_t *node, apr_pool_t *pool)

/* the worker corresponding to the id, note that we need to compare the shared memory pointer too */
#if AP_MODULE_MAGIC_AT_LEAST(20101223,1)
static proxy_worker *get_worker_from_id_stat(proxy_server_conf *conf, int id, proxy_worker_shared *stat)
static proxy_worker *get_worker_from_id_stat(proxy_server_conf *conf, int id, proxy_worker_shared *stat, nodeinfo_t *node)
{
int i;
char *ptr = conf->balancers->elts;
Expand All @@ -878,14 +879,26 @@ static proxy_worker *get_worker_from_id_stat(proxy_server_conf *conf, int id, pr
proxy_worker **worker = (proxy_worker **) ptrw;
proxy_cluster_helper *helper = (proxy_cluster_helper *) (*worker)->context;
if ((*worker)->s == stat && helper->index == id) {

/* Check that the worker is really the one we need */
char sport[7];
apr_snprintf(sport, sizeof(sport), "%d", worker->port);
if (strcmp(worker->s->scheme, node->mess.Type) ||
strcmp(worker->s->hostname, node->mess.Host) ||
strcmp(sport, node->mess.Port)) {
worker->s->index = 0;
ap_my_generation--; /* mark old generation that will recreate the process */
continue; /* skip it */
}

return *worker;
}
}
}
return NULL;
}
#else
static proxy_worker *get_worker_from_id_stat(proxy_server_conf *conf, int id, proxy_worker_stat *stat)
static proxy_worker *get_worker_from_id_stat(proxy_server_conf *conf, int id, proxy_worker_stat *stat, nodeinfo_t *node)
{
int i;
int sizew = conf->workers->elt_size;
Expand All @@ -894,6 +907,18 @@ static proxy_worker *get_worker_from_id_stat(proxy_server_conf *conf, int id, pr
for (i = 0; i < conf->workers->nelts; i++, ptrw=ptrw+sizew) {
proxy_worker *worker = (proxy_worker *) ptrw;
if (worker->id == id && worker->s == stat) {

/* Check that the worker is really the one we need */
char sport[7];
apr_snprintf(sport, sizeof(sport), "%d", worker->port);
if (strcmp(worker->scheme, node->mess.Type) ||
strcmp(worker->hostname, node->mess.Host) ||
strcmp(sport, node->mess.Port)) {
worker->id = 0;
ap_my_generation--; /* mark old generation that will recreate the process */
continue; /* skip it */
}

return worker;
}
worker++;
Expand All @@ -902,6 +927,33 @@ static proxy_worker *get_worker_from_id_stat(proxy_server_conf *conf, int id, pr
}
#endif

/* read the node and check that it corresponds to the worker */
static apr_status_t read_node_worker(int id, nodeinfo_t **node, proxy_worker *worker)
{
char sport[7];
apr_status_t status = node_storage->read_node(id, node);
if (status != APR_SUCCESS)
return status;
#if AP_MODULE_MAGIC_AT_LEAST(20101223,1)
apr_snprintf(sport, sizeof(sport), "%d", worker->s->port);
if (strcmp(worker->s->scheme, (* node)->mess.Type) ||
strcmp(worker->-s->hostname, (* node)->mess.Host) ||
strcmp(sport, (* node)->mess.Port)) {
/* for some reasons it is not the right node */
return APR_NOTFOUND;
}
#else
apr_snprintf(sport, sizeof(sport), "%d", worker->port);
if (strcmp(worker->scheme, (* node)->mess.Type) ||
strcmp(worker->hostname, (* node)->mess.Host) ||
strcmp(sport, (* node)->mess.Port)) {
/* for some reasons it is not the right node */
return APR_NOTFOUND;
}
#endif
return APR_SUCCESS;
}

/*
* Remove a node from the worker conf
*/
Expand All @@ -914,9 +966,9 @@ static int remove_workers_node(nodeinfo_t *node, proxy_server_conf *conf, apr_po
pptr = pptr + node->offset;

#if AP_MODULE_MAGIC_AT_LEAST(20101223,1)
worker = get_worker_from_id_stat(conf, node->mess.id, (proxy_worker_shared *) pptr);
worker = get_worker_from_id_stat(conf, node->mess.id, (proxy_worker_shared *) pptr, node);
#else
worker = get_worker_from_id_stat(conf, node->mess.id, (proxy_worker_stat *) pptr);
worker = get_worker_from_id_stat(conf, node->mess.id, (proxy_worker_stat *) pptr, node);
#endif
if (!worker) {
/* XXX: Another process may use it, can't do: node_storage->remove_node(node); */
Expand All @@ -925,7 +977,7 @@ static int remove_workers_node(nodeinfo_t *node, proxy_server_conf *conf, apr_po
}

/* prevent other threads using it */
worker->s->status |= PROXY_WORKER_IN_ERROR;
worker->s->status = worker->s->status | PROXY_WORKER_IN_ERROR;

/* apr_reslist_acquired_count */
i = 0;
Expand Down Expand Up @@ -1474,21 +1526,40 @@ static void update_workers_lbstatus(proxy_server_conf *conf, apr_pool_t *pool, s
apr_status_t rv;
apr_pool_t *rrp;
request_rec *rnew;
proxy_worker *worker = get_worker_from_id_stat(conf, id[i], stat);
proxy_worker *worker;
apr_thread_mutex_lock(lock);
worker = get_worker_from_id_stat(conf, id[i], stat, ou);
apr_thread_mutex_unlock(lock);
if (worker == NULL)
continue; /* skip it */
#if AP_MODULE_MAGIC_AT_LEAST(20101223,1)
apr_snprintf(sport, sizeof(sport), ":%d", worker->s->port);
apr_snprintf(sport, sizeof(sport), "%d", worker->s->port);
if (strcmp(worker->s->scheme, ou->mess.Type) ||
strcmp(worker->s->hostname, ou->mess.Host) ||
strcmp(sport, ou->mess.Port)) {
/* the worker doesn't correspond to the node */
worker->s->index = 0;
ap_my_generation--; /* mark old generation that will recreate the process */
continue; /* skip it */
}
if (strchr(worker->s->hostname, ':') != NULL)
url = apr_pstrcat(pool, worker->s->scheme, "://[", worker->s->hostname, "]", sport, "/", NULL);
url = apr_pstrcat(pool, worker->s->scheme, "://[", worker->s->hostname, "]", ":", sport, "/", NULL);
else
url = apr_pstrcat(pool, worker->s->scheme, "://", worker->s->hostname, sport, "/", NULL);
url = apr_pstrcat(pool, worker->s->scheme, "://", worker->s->hostname, ":", sport, "/", NULL);
#else
apr_snprintf(sport, sizeof(sport), ":%d", worker->port);
apr_snprintf(sport, sizeof(sport), "%d", worker->port);
if (strcmp(worker->scheme, ou->mess.Type) ||
strcmp(worker->hostname, ou->mess.Host) ||
strcmp(sport, ou->mess.Port)) {
/* the worker doesn't correspond to the node */
worker->id = 0;
ap_my_generation--; /* mark old generation that will recreate the process */
continue; /* skip it */
}
if (strchr(worker->hostname, ':') != NULL)
url = apr_pstrcat(pool, worker->scheme, "://[", worker->hostname, "]", sport, "/", NULL);
url = apr_pstrcat(pool, worker->scheme, "://[", worker->hostname, "]", ":", sport, "/", NULL);
else
url = apr_pstrcat(pool, worker->scheme, "://", worker->hostname, sport, "/", NULL);
url = apr_pstrcat(pool, worker->scheme, "://", worker->hostname, ":", sport, "/", NULL);
#endif

apr_pool_create(&rrp, pool);
Expand All @@ -1509,6 +1580,10 @@ static void update_workers_lbstatus(proxy_server_conf *conf, apr_pool_t *pool, s
rnew->uri = "/";
rnew->headers_in = apr_table_make(rnew->pool, 1);
rv = proxy_cluster_try_pingpong(rnew, worker, url, conf, ou->mess.ping, ou->mess.timeout);

if (read_node_worker(id[i], &ou, worker) != APR_SUCCESS)
continue;

if (rv != APR_SUCCESS) {
/* We can't reach the node */
worker->s->status |= PROXY_WORKER_IN_ERROR;
Expand Down Expand Up @@ -2223,9 +2298,9 @@ static proxy_worker *internal_find_best_byrequests(proxy_balancer *balancer, pro
* and that can map the context.
*/
#if AP_MODULE_MAGIC_AT_LEAST(20101223,1)
if (node_storage->read_node(worker->s->index, &node) != APR_SUCCESS)
if (read_node_worker(worker->s->index, &node, worker) != APR_SUCCESS)
#else
if (node_storage->read_node(worker->id, &node) != APR_SUCCESS)
if (read_node_worker(worker->id, &node, worker) != APR_SUCCESS)
#endif
continue; /* Can't read node */

Expand Down Expand Up @@ -2253,9 +2328,9 @@ static proxy_worker *internal_find_best_byrequests(proxy_balancer *balancer, pro
int lbstatus, lbstatus1;

#if AP_MODULE_MAGIC_AT_LEAST(20101223,1)
if (node_storage->read_node(mycandidate->s->index, &node1) != APR_SUCCESS)
if (read_node_worker(mycandidate->s->index, &node1, mycandidate) != APR_SUCCESS)
#else
if (node_storage->read_node(mycandidate->id, &node1) != APR_SUCCESS)
if (read_node_worker(mycandidate->id, &node1, mycandidate) != APR_SUCCESS)
#endif
continue;
lbstatus1 = ((mycandidate->s->elected - node1->mess.oldelected) * 1000)/mycandidate->s->lbfactor;
Expand Down Expand Up @@ -2362,7 +2437,7 @@ static int proxy_node_isup(request_rec *r, int id, int load)
void *sconf = s->module_config;
conf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module);

worker = get_worker_from_id_stat(conf, id, stat);
worker = get_worker_from_id_stat(conf, id, stat, node);
if (worker != NULL)
break;
s = s->next;
Expand Down Expand Up @@ -3184,8 +3259,8 @@ static proxy_worker *find_route_worker(request_rec *r,
if (worker && PROXY_WORKER_IS_USABLE(worker)) {
/* The context may not be available */
nodeinfo_t *node;
if (node_storage->read_node(index, &node) != APR_SUCCESS)
return NULL; /* can't read node */
if (read_node_worker(worker->id, &node, worker) != APR_SUCCESS)
continue;
if ((nodecontext = context_host_ok(r, balancer, index, vhost_table, context_table, node_table)) != NULL) {
apr_table_setn(r->subprocess_env, "BALANCER_CONTEXT_ID", apr_psprintf(r->pool, "%d", (*nodecontext).context));
return worker;
Expand Down

0 comments on commit 93192f3

Please sign in to comment.