in native/common/jk_lb_worker.c [1035:1150]
static int get_most_suitable_worker(jk_ws_service_t *s,
lb_worker_t *p,
char *sessionid,
int *states,
jk_log_context_t *l)
{
int rc = -1;
JK_TRACE_ENTER(l);
s->sticky = JK_FALSE;
if (p->num_of_workers == 1) {
/* No need to find the best worker
* if there is a single one
*/
int activation = s->extension.activation ?
s->extension.activation[0] :
JK_LB_ACTIVATION_UNSET;
if (activation == JK_LB_ACTIVATION_UNSET)
activation = p->lb_workers[0].activation;
if (JK_WORKER_USABLE_STICKY(states[0], activation)) {
if (activation != JK_LB_ACTIVATION_DISABLED) {
s->sticky = JK_TRUE;
JK_TRACE_EXIT(l);
return 0;
}
}
else {
JK_TRACE_EXIT(l);
return -1;
}
}
if (p->lblock == JK_LB_LOCK_PESSIMISTIC) {
if (!jk_shm_lock()) {
jk_log(l, JK_LOG_ERROR, "locking failed (errno=%d)", errno);
JK_TRACE_EXIT(l);
return -1;
}
}
else {
JK_ENTER_CS(&p->cs);
}
if (sessionid) {
char *session = sessionid;
while (sessionid) {
char *next = strchr(sessionid, ';');
char *session_route = NULL;
if (next)
*next++ = '\0';
if (JK_IS_DEBUG_LEVEL(l))
jk_log(l, JK_LOG_DEBUG,
"searching worker for partial sessionid %s",
sessionid);
session_route = strchr(sessionid, '.');
if (session_route) {
++session_route;
if (JK_IS_DEBUG_LEVEL(l))
jk_log(l, JK_LOG_DEBUG,
"searching worker for session route %s",
session_route);
/* We have a session route. Whow! */
rc = find_bysession_route(s, p, session_route, states, l);
if (rc >= 0) {
lb_sub_worker_t *wr = &(p->lb_workers[rc]);
if (p->lblock == JK_LB_LOCK_PESSIMISTIC) {
jk_shm_unlock();
}
else {
JK_LEAVE_CS(&p->cs);
}
if (JK_IS_DEBUG_LEVEL(l))
jk_log(l, JK_LOG_DEBUG,
"found worker %s (%s) for route %s and partial sessionid %s",
wr->name, wr->route, session_route, sessionid);
JK_TRACE_EXIT(l);
return rc;
}
}
/* Try next partial sessionid if present */
sessionid = next;
rc = -1;
}
if (rc < 0 && p->sticky_session_force) {
if (p->lblock == JK_LB_LOCK_PESSIMISTIC) {
jk_shm_unlock();
}
else {
JK_LEAVE_CS(&p->cs);
}
jk_log(l, JK_LOG_INFO,
"all workers are in error state for session %s",
session);
JK_TRACE_EXIT(l);
return -1;
}
}
rc = find_best_worker(s, p, states, l);
if (p->lblock == JK_LB_LOCK_PESSIMISTIC) {
jk_shm_unlock();
}
else {
JK_LEAVE_CS(&p->cs);
}
if (rc >= 0) {
lb_sub_worker_t *wr = &(p->lb_workers[rc]);
if (JK_IS_DEBUG_LEVEL(l))
jk_log(l, JK_LOG_DEBUG,
"found best worker %s (%s) using method '%s'",
wr->name, wr->route, jk_lb_get_method(p, l));
JK_TRACE_EXIT(l);
return rc;
}
JK_TRACE_EXIT(l);
return -1;
}