Author: mturk
Date: Fri Apr 11 02:13:07 2008
New Revision: 647085

URL: http://svn.apache.org/viewvc?rev=647085&view=rev
Log:
Fix lb node in-error setting (see changelog)

Modified:
    tomcat/connectors/trunk/jk/native/common/jk_lb_worker.c
    tomcat/connectors/trunk/jk/native/common/jk_lb_worker.h
    tomcat/connectors/trunk/jk/native/common/jk_shm.h
    tomcat/connectors/trunk/jk/xdocs/miscellaneous/changelog.xml

Modified: tomcat/connectors/trunk/jk/native/common/jk_lb_worker.c
URL: 
http://svn.apache.org/viewvc/tomcat/connectors/trunk/jk/native/common/jk_lb_worker.c?rev=647085&r1=647084&r2=647085&view=diff
==============================================================================
--- tomcat/connectors/trunk/jk/native/common/jk_lb_worker.c (original)
+++ tomcat/connectors/trunk/jk/native/common/jk_lb_worker.c Fri Apr 11 02:13:07 
2008
@@ -50,8 +50,8 @@
  * Note: activation == JK_LB_ACTIVATION_ACTIVE is equivalent to
  *       activation is none of JK_LB_ACTIVATION_STOPPED, 
JK_LB_ACTIVATION_DISABLED
  */
-#define JK_WORKER_USABLE(s, activation)   ((s)->state <= JK_LB_STATE_FORCE && 
activation == JK_LB_ACTIVATION_ACTIVE)
-#define JK_WORKER_USABLE_STICKY(s, activation)   ((s)->state <= 
JK_LB_STATE_BUSY && activation != JK_LB_ACTIVATION_STOPPED)
+#define JK_WORKER_USABLE(s, activation)   ((s) <= JK_LB_STATE_FORCE && 
activation == JK_LB_ACTIVATION_ACTIVE)
+#define JK_WORKER_USABLE_STICKY(s, activation)   ((s) <= JK_LB_STATE_BUSY && 
activation != JK_LB_ACTIVATION_STOPPED)
 
 static const char *lb_locking_type[] = {
     JK_LB_LOCK_TEXT_OPTIMISTIC,
@@ -657,7 +657,7 @@
 
 static int find_by_session(jk_ws_service_t *s,
                            lb_worker_t *p,
-                           const char *name,
+                           const char *name,                           
                            jk_logger_t *l)
 {
 
@@ -676,6 +676,7 @@
 static int find_best_bydomain(jk_ws_service_t *s,
                               lb_worker_t *p,
                               const char *domain,
+                              int *states,
                               jk_logger_t *l)
 {
     unsigned int i;
@@ -701,7 +702,7 @@
                      JK_LB_ACTIVATION_UNSET;
         if (activation == JK_LB_ACTIVATION_UNSET)
             activation = wr.activation;
-        if (JK_WORKER_USABLE(wr.s, activation)) {
+        if (JK_WORKER_USABLE(states[wr.i], activation)) {
             if (candidate < 0 || wr.distance < d ||
                 (wr.s->lb_value < curmin &&
                 wr.distance == d)) {
@@ -718,6 +719,7 @@
 
 static int find_best_byvalue(jk_ws_service_t *s,
                              lb_worker_t *p,
+                             int *states,
                              jk_logger_t *l)
 {
     unsigned int i;
@@ -746,7 +748,7 @@
         /* Take into calculation only the workers that are
          * not in error state, stopped, disabled or busy.
          */
-        if (JK_WORKER_USABLE(wr.s, activation)) {
+        if (JK_WORKER_USABLE(states[wr.i], activation)) {
             if (candidate < 0 || wr.distance < d ||
                 (wr.s->lb_value < curmin &&
                 wr.distance == d)) {
@@ -763,6 +765,7 @@
 static int find_bysession_route(jk_ws_service_t *s,
                                 lb_worker_t *p,
                                 const char *name,
+                                int *states,
                                 jk_logger_t *l)
 {
     int uses_domain  = 0;
@@ -771,7 +774,7 @@
     candidate = find_by_session(s, p, name, l);
     if (candidate < 0) {
         uses_domain = 1;
-        candidate = find_best_bydomain(s, p, name, l);
+        candidate = find_best_bydomain(s, p, name, states, l);
     }
     if (candidate >= 0) {
         lb_sub_worker_t wr = p->lb_workers[candidate];
@@ -783,7 +786,7 @@
                      JK_LB_ACTIVATION_UNSET;
         if (activation == JK_LB_ACTIVATION_UNSET)
             activation = wr.activation;
-        if (!JK_WORKER_USABLE_STICKY(wr.s, activation)) {
+        if (!JK_WORKER_USABLE_STICKY(states[wr.i], activation)) {
             /* We have a worker that is error state or stopped.
              * If it has a redirection set use that redirection worker.
              * This enables to safely remove the member from the
@@ -797,7 +800,7 @@
                 s->route = NULL;
             }
             else if (*wr.domain && !uses_domain) {
-                candidate = find_best_bydomain(s, p, wr.domain, l);
+                candidate = find_best_bydomain(s, p, wr.domain, states, l);
                 s->route = wr.domain;
             }
             if (candidate >= 0) {
@@ -807,7 +810,7 @@
                              JK_LB_ACTIVATION_UNSET;
                 if (activation == JK_LB_ACTIVATION_UNSET)
                     activation = wr.activation;
-                if (!JK_WORKER_USABLE_STICKY(wr.s, activation))
+                if (!JK_WORKER_USABLE_STICKY(states[wr.i], activation))
                     candidate = -1;
             }
         }
@@ -817,6 +820,7 @@
 
 static int find_failover_worker(jk_ws_service_t *s,
                                 lb_worker_t * p,
+                                int *states,
                                 jk_logger_t *l)
 {
     int rc = -1;
@@ -830,26 +834,28 @@
         }
     }
     if (redirect)
-        rc = find_bysession_route(s, p, redirect, l);
+        rc = find_bysession_route(s, p, redirect, states, l);
     return rc;
 }
 
 static int find_best_worker(jk_ws_service_t *s,
                             lb_worker_t * p,
+                            int *states,
                             jk_logger_t *l)
 {
     int rc = -1;
 
-    rc = find_best_byvalue(s, p, l);
+    rc = find_best_byvalue(s, p, states, l);
     /* By default use worker route as session route */
     if (rc < 0)
-        rc = find_failover_worker(s, p, l);
+        rc = find_failover_worker(s, p, states, l);
     return rc;
 }
 
 static lb_sub_worker_t *get_most_suitable_worker(jk_ws_service_t *s,
                                                  lb_worker_t * p,
                                                  char *sessionid,
+                                                 int *states,
                                                  jk_logger_t *l)
 {
     int rc = -1;
@@ -865,7 +871,7 @@
                          JK_LB_ACTIVATION_UNSET;
         if (activation == JK_LB_ACTIVATION_UNSET)
             activation = p->lb_workers[0].activation;
-        if (JK_WORKER_USABLE_STICKY(p->lb_workers[0].s, activation)) {
+        if (JK_WORKER_USABLE_STICKY(states[0], activation)) {
             if (activation != JK_LB_ACTIVATION_DISABLED) {
                 JK_TRACE_EXIT(l);
                 return p->lb_workers;
@@ -907,7 +913,7 @@
                            session_route);
 
                 /* We have a session route. Whow! */
-                rc = find_bysession_route(s, p, session_route, l);
+                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)
@@ -940,7 +946,7 @@
             return NULL;
         }
     }
-    rc = find_best_worker(s, p, l);
+    rc = find_best_worker(s, p, states, l);
     if (p->lblock == JK_LB_LOCK_PESSIMISTIC)
         jk_shm_unlock();
     else {
@@ -1014,6 +1020,8 @@
     int recoverable = JK_TRUE;
     int rc = JK_UNSET;
     char *sessionid = NULL;
+    int  *states = NULL;
+    int i;
 
     JK_TRACE_ENTER(l);
 
@@ -1030,11 +1038,22 @@
 
     /* Set returned error to OK */
     *is_error = JK_HTTP_OK;
+    if (!(states = (int *)malloc(num_of_workers * sizeof(int)))) {
+        *is_error = JK_HTTP_SERVER_ERROR;
+        jk_log(l, JK_LOG_ERROR,
+               "Failed allocating private worker state memory");
+        JK_TRACE_EXIT(l);
+        return JK_SERVER_ERROR;        
+    }
 
     jk_shm_lock();
     if (p->worker->sequence != p->worker->s->h.sequence)
         jk_lb_pull(p->worker, l);
     jk_shm_unlock();
+    for (i = 0; i < num_of_workers; i++) {
+        /* Copy the shared state info */
+        states[i] = p->worker->lb_workers[i].s->state;
+    }
 
     /* set the recovery post, for LB mode */
     s->reco_buf = jk_b_new(s->pool);
@@ -1068,7 +1087,7 @@
 
     while (attempt <= num_of_workers && recoverable == JK_TRUE) {
         lb_sub_worker_t *rec =
-            get_most_suitable_worker(s, p->worker, sessionid, l);
+            get_most_suitable_worker(s, p->worker, sessionid, states, l);
         rc = JK_FALSE;
         *is_error = JK_HTTP_SERVER_BUSY;
         /* Do not reuse previous worker, because
@@ -1093,8 +1112,10 @@
 
             if (p->worker->lblock == JK_LB_LOCK_PESSIMISTIC)
                 jk_shm_lock();
-            if (rec->s->state == JK_LB_STATE_RECOVER)
-                rec->s->state = JK_LB_STATE_PROBE;
+            if (rec->s->state == JK_LB_STATE_RECOVER) {
+                rec->s->state  = JK_LB_STATE_PROBE;
+                states[rec->i] = JK_LB_STATE_PROBE;
+            }
             if (p->worker->lblock == JK_LB_LOCK_PESSIMISTIC)
                 jk_shm_unlock();
                        
@@ -1124,8 +1145,10 @@
                  */
                 if (p->worker->lblock == JK_LB_LOCK_PESSIMISTIC)
                     jk_shm_lock();
-                if (rec->s->state != JK_LB_STATE_ERROR)
-                    rec->s->state = JK_LB_STATE_BUSY;
+                if (rec->s->state != JK_LB_STATE_ERROR) {
+                    rec->s->state  = JK_LB_STATE_BUSY;
+                    states[rec->i] = JK_LB_STATE_BUSY;
+                }
                 if (p->worker->lblock == JK_LB_LOCK_PESSIMISTIC)
                     jk_shm_unlock();
                 jk_log(l, JK_LOG_INFO,
@@ -1146,6 +1169,7 @@
 
                 /* Increment the number of workers serving request */
                 p->worker->s->busy++;
+                rec->s->busy++;
                 if (p->worker->s->busy > p->worker->s->max_busy)
                     p->worker->s->max_busy = p->worker->s->busy;
                 if ( (p->worker->lbmethod == JK_LB_METHOD_REQUESTS) ||
@@ -1194,14 +1218,18 @@
                 /* When returning the endpoint mark the worker as not busy.
                  * We have at least one endpoint free
                  */
-                if (rec->s->state == JK_LB_STATE_BUSY)
-                    rec->s->state = JK_LB_STATE_OK;
+                if (rec->s->state == JK_LB_STATE_BUSY) {
+                    rec->s->state  = JK_LB_STATE_OK;
+                    states[rec->i] = JK_LB_STATE_OK;
+                }
                 /* Decrement the busy worker count.
                  * Check if the busy was reset to zero by graceful
                  * restart of the server.
                  */
                 if (p->worker->s->busy)
                     p->worker->s->busy--;
+                if (rec->s->busy)
+                    rec->s->busy--;
                 if (service_stat == JK_TRUE) {
                     rec->s->state = JK_LB_STATE_OK;
                     rec->s->error_time = 0;
@@ -1213,7 +1241,8 @@
                     * Client error !!!
                     * Since this is bad request do not fail over.
                     */
-                    rec->s->state = JK_LB_STATE_OK;
+                    rec->s->state  = JK_LB_STATE_OK;
+                    states[rec->i] = JK_LB_STATE_ERROR;
                     rec->s->error_time = 0;
                     rc = JK_CLIENT_ERROR;
                     recoverable = JK_FALSE;
@@ -1224,7 +1253,8 @@
                     * Don't mark the node as bad.
                     * Failing over to another node could help.
                     */
-                    rec->s->state = JK_LB_STATE_OK;
+                    rec->s->state  = JK_LB_STATE_OK;
+                    states[rec->i] = JK_LB_STATE_ERROR;
                     rec->s->error_time = 0;
                     rc = JK_FALSE;
                 }
@@ -1234,7 +1264,8 @@
                     * Don't mark the node as bad.
                     * Failing over to another node could help.
                     */
-                    rec->s->state = JK_LB_STATE_OK;
+                    rec->s->state  = JK_LB_STATE_OK;
+                    states[rec->i] = JK_LB_STATE_ERROR;
                     rec->s->error_time = 0;
                     rc = JK_FALSE;
                 }
@@ -1245,46 +1276,66 @@
                     * Failing over to another node could help.
                     */
                     rec->s->errors++;
-                    rec->s->state = JK_LB_STATE_ERROR;
+                    if (rec->s->busy) {
+                        rec->s->state = JK_LB_STATE_OK;
+                    }
+                    else {
+                        rec->s->state = JK_LB_STATE_ERROR;
+                    }
+                    states[rec->i] = JK_LB_STATE_ERROR;
                     rec->s->error_time = time(NULL);
                     rc = JK_FALSE;
                 }
                 else if (service_stat == JK_REPLY_TIMEOUT) {
                     if (aw->s->reply_timeouts > 
(unsigned)p->worker->max_reply_timeouts) {
                         /*
-                        * Service failed - to many reply timeouts
-                        * Take this node out of service.
-                        */
+                         * Service failed - to many reply timeouts
+                         * Take this node out of service.
+                         */
                         rec->s->errors++;
-                        rec->s->state = JK_LB_STATE_ERROR;
+                        if (rec->s->busy) {
+                            rec->s->state = JK_LB_STATE_OK;
+                        }
+                        else {
+                            rec->s->state = JK_LB_STATE_ERROR;
+                        }
+                        states[rec->i] = JK_LB_STATE_ERROR;
                         rec->s->error_time = time(NULL);
                     }
                     else {
-                    /*
-                    * XXX: if we want to be able to failover
-                    * to other nodes after a reply timeout,
-                    * but we do not put the timeout node into error,
-                    * how can we make sure, that we actually fail over
-                    * to other nodes?
-                    */
-                        rec->s->state = JK_LB_STATE_OK;
+                        /*
+                         * XXX: if we want to be able to failover
+                         * to other nodes after a reply timeout,
+                         * but we do not put the timeout node into error,
+                         * how can we make sure, that we actually fail over
+                         * to other nodes?
+                         */
+                        rec->s->state  = JK_LB_STATE_OK;
+                        states[rec->i] = JK_LB_STATE_ERROR;
                         rec->s->error_time = 0;
                     }
                     rc = JK_FALSE;
                 }
                 else {
                     /*
-                    * Service failed !!!
-                    * Time for fault tolerance (if possible)...
-                    */
+                     * Service failed !!!
+                     * Time for fault tolerance (if possible)...
+                     */
                     rec->s->errors++;
-                    rec->s->state = JK_LB_STATE_ERROR;
+                    if (rec->s->busy) {
+                        rec->s->state = JK_LB_STATE_OK;
+                    }
+                    else {
+                        rec->s->state = JK_LB_STATE_ERROR;
+                    }
+                    states[rec->i] = JK_LB_STATE_ERROR;
                     rec->s->error_time = time(NULL);
                     rc = JK_FALSE;
                 }
-                if (rec->s->state == JK_LB_STATE_ERROR)
+                if (states[rec->i] == JK_LB_STATE_ERROR)
                     jk_log(l, JK_LOG_INFO,
-                           "service failed, worker %s is in error state",
+                           "service failed, %sworker %s is in error state",
+                           rec->s->state == JK_LB_STATE_ERROR ? "entire " : "",
                            rec->name);
                 if (p->worker->lblock == JK_LB_LOCK_PESSIMISTIC)
                     jk_shm_unlock();
@@ -1368,6 +1419,8 @@
         lb_add_log_items(s, lb_last_log_names, prec, l);
     }
 
+    /* Free any private memory used */
+    free(states);
     JK_TRACE_EXIT(l);
     return rc;
 }
@@ -1434,6 +1487,8 @@
             for (i = 0; i < num_of_workers; i++) {
                 const char *s;
                 unsigned int ms;
+
+                p->lb_workers[i].i = i;
                 strncpy(p->lb_workers[i].name, worker_names[i],
                         JK_SHM_STR_SIZ);
                 strncpy(p->lb_workers[i].s->h.name, worker_names[i],

Modified: tomcat/connectors/trunk/jk/native/common/jk_lb_worker.h
URL: 
http://svn.apache.org/viewvc/tomcat/connectors/trunk/jk/native/common/jk_lb_worker.h?rev=647085&r1=647084&r2=647085&view=diff
==============================================================================
--- tomcat/connectors/trunk/jk/native/common/jk_lb_worker.h (original)
+++ tomcat/connectors/trunk/jk/native/common/jk_lb_worker.h Fri Apr 11 02:13:07 
2008
@@ -158,6 +158,8 @@
     int activation;
     /* Current lb factor */
     int lb_factor;
+    /* Current worker index */
+    int i;
     /* Current lb reciprocal factor */
     jk_uint64_t lb_mult;
 };

Modified: tomcat/connectors/trunk/jk/native/common/jk_shm.h
URL: 
http://svn.apache.org/viewvc/tomcat/connectors/trunk/jk/native/common/jk_shm.h?rev=647085&r1=647084&r2=647085&view=diff
==============================================================================
--- tomcat/connectors/trunk/jk/native/common/jk_shm.h (original)
+++ tomcat/connectors/trunk/jk/native/common/jk_shm.h Fri Apr 11 02:13:07 2008
@@ -124,6 +124,8 @@
     char    domain[JK_SHM_STR_SIZ+1];
     /* worker redirect route */
     char    redirect[JK_SHM_STR_SIZ+1];
+    /* Number of currently busy channels */
+    volatile int busy;
     /* worker distance */
     volatile int distance;
     /* current activation state (config) of the worker */

Modified: tomcat/connectors/trunk/jk/xdocs/miscellaneous/changelog.xml
URL: 
http://svn.apache.org/viewvc/tomcat/connectors/trunk/jk/xdocs/miscellaneous/changelog.xml?rev=647085&r1=647084&r2=647085&view=diff
==============================================================================
--- tomcat/connectors/trunk/jk/xdocs/miscellaneous/changelog.xml (original)
+++ tomcat/connectors/trunk/jk/xdocs/miscellaneous/changelog.xml Fri Apr 11 
02:13:07 2008
@@ -48,6 +48,15 @@
         preprocessor defines. (rjung)
       </update>
       <fix>
+        Do not put loadbalancer node in error state if there is opened
+        channel. This fixes the bug when new new connection fails due to
+        bussines, causing opened connections fail stickyness.
+        This brings back per-node busy counter and private state array
+        for each request. We can mark the state as error for failover to
+        work while still operating and reporting node as OK if there are
+        opened working connections. (mturk)
+      </fix>
+      <fix>
         <bug>44738</bug>: Fix merging of JkOption ForwardURI* between virtual 
hosts.
         Patch contributed by Toshihiro Sasajima. (rjung)
       </fix>



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to