You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by co...@apache.org on 2011/08/11 22:05:18 UTC

svn commit: r1156790 - in /httpd/httpd/trunk: CHANGES include/ap_mmn.h include/util_ldap.h modules/ldap/util_ldap.c

Author: covener
Date: Thu Aug 11 20:05:18 2011
New Revision: 1156790

URL: http://svn.apache.org/viewvc?rev=1156790&view=rev
Log:
mod_ldap: remove hard-coded loops of 10 retries w/o delay with a configurable
number of retries (LDAPRetries, default 3) and configurable delay between 
retries (LDAPRetryDelay, no delay by default).

The LDAP connection is re-initted every other retry, instead of
on the fifth retry -- this was a much more recent addition then
the basic looping behavior.


Modified:
    httpd/httpd/trunk/CHANGES
    httpd/httpd/trunk/include/ap_mmn.h
    httpd/httpd/trunk/include/util_ldap.h
    httpd/httpd/trunk/modules/ldap/util_ldap.c

Modified: httpd/httpd/trunk/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=1156790&r1=1156789&r2=1156790&view=diff
==============================================================================
--- httpd/httpd/trunk/CHANGES [utf-8] (original)
+++ httpd/httpd/trunk/CHANGES [utf-8] Thu Aug 11 20:05:18 2011
@@ -1,6 +1,9 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.3.15
 
+  *) mod_ldap: Change default number of retries from 10 to 3, and add 
+     an LDAPRetries and LDAPRetryDelay directives. [Eric Covener]
+
   *) mod_authnz_ldap: Don't retry during authentication, because this just 
      multiplies the ample retries already being done by mod_ldap. [Eric Covener]
 

Modified: httpd/httpd/trunk/include/ap_mmn.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_mmn.h?rev=1156790&r1=1156789&r2=1156790&view=diff
==============================================================================
--- httpd/httpd/trunk/include/ap_mmn.h (original)
+++ httpd/httpd/trunk/include/ap_mmn.h Thu Aug 11 20:05:18 2011
@@ -346,6 +346,7 @@
  *                         Add member override_list to cmd_parms_struct,
  *                         core_dir_config and htaccess_result
  * 20110724.1 (2.3.15-dev) add NOT_IN_HTACCESS
+ * 20110724.2 (2.3.15-dev) retries and retry_delay in util_ldap_state_t
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
@@ -353,7 +354,7 @@
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20110724
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 1                    /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 2                    /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a

Modified: httpd/httpd/trunk/include/util_ldap.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/util_ldap.h?rev=1156790&r1=1156789&r2=1156790&view=diff
==============================================================================
--- httpd/httpd/trunk/include/util_ldap.h (original)
+++ httpd/httpd/trunk/include/util_ldap.h Thu Aug 11 20:05:18 2011
@@ -172,6 +172,8 @@ typedef struct util_ldap_state_t {
 
     int debug_level;                    /* SDK debug level */
     apr_interval_time_t connection_pool_ttl;
+    int retries;                        /* number of retries for failed bind/search/compare */
+    apr_interval_time_t retry_delay;    /* delay between retries of failed bind/search/compare */
 } util_ldap_state_t;
 
 /* Used to store arrays of attribute labels/values. */

Modified: httpd/httpd/trunk/modules/ldap/util_ldap.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ldap/util_ldap.c?rev=1156790&r1=1156789&r2=1156790&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/ldap/util_ldap.c (original)
+++ httpd/httpd/trunk/modules/ldap/util_ldap.c Thu Aug 11 20:05:18 2011
@@ -529,10 +529,9 @@ static int uldap_connection_open(request
     st = (util_ldap_state_t *)ap_get_module_config(r->server->module_config,
                                                    &ldap_module);
 
-    /* loop trying to bind up to 10 times if LDAP_SERVER_DOWN error is
-     * returned. If LDAP_TIMEOUT is returned on the first try, maybe the
-     * connection was idle for a long time and has been dropped by a firewall.
-     * In this case close the connection immediately and try again.
+    /* loop trying to bind up to st->retries times if LDAP_SERVER_DOWN or LDAP_TIMEOUT
+     * are returned.  Close the connection before the first retry, and then on every
+     * other retry.
      *
      * On Success or any other error, break out of the loop.
      *
@@ -541,34 +540,44 @@ static int uldap_connection_open(request
      * However, the original code looped and it only happens on
      * the error condition.
      */
-    for (failures=0; failures<10; failures++)
-    {
+
+    while (failures <= st->retries) {
+        if (failures > 0 && st->retry_delay > 0) { 
+            apr_sleep(st->retry_delay);
+        }
         rc = uldap_simple_bind(ldc, (char *)ldc->binddn, (char *)ldc->bindpw,
                                st->opTimeout);
-        if ((AP_LDAP_IS_SERVER_DOWN(rc) && failures == 5) ||
-            (rc == LDAP_TIMEOUT && failures == 0))
-        {
-            if (rc == LDAP_TIMEOUT && !new_connection) {
-                ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
-                              "ldap_simple_bind() timed out on reused "
-                              "connection, dropped by firewall?");
-            }
-            ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
+
+        if (rc == LDAP_SUCCESS) break;
+
+        failures++;
+
+        if (AP_LDAP_IS_SERVER_DOWN(rc)) { 
+             ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
+                          "ldap_simple_bind() failed with server down "
+                          "(try %d)", failures);
+        }
+        else if (rc == LDAP_TIMEOUT) {
+            ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
+                          "ldap_simple_bind() timed out on %s "
+                          "connection, dropped by firewall?", 
+                          new_connection ? "new" : "reused");
+        }
+        else { 
+            /* Other errors not retryable */
+            break;
+        }
+
+        if (!(failures % 2)) {
+            ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, 
                           "attempt to re-init the connection");
-            uldap_connection_unbind( ldc );
-            rc = uldap_connection_init( r, ldc );
-            if (LDAP_SUCCESS != rc)
-            {
+            uldap_connection_unbind(ldc);
+            if (LDAP_SUCCESS != uldap_connection_init(r, ldc)) { 
+                /* leave rc as the initial bind return code */
                 break;
             }
         }
-        else if (!AP_LDAP_IS_SERVER_DOWN(rc)) {
-            break;
-        }
-        ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r,
-                      "ldap_simple_bind() failed with server down "
-                      "(try %d)", failures + 1);
-    }
+    } 
 
     /* free the handle if there was an error
     */
@@ -878,11 +887,14 @@ static int uldap_cache_comparedn(request
     }
 
 start_over:
-    if (failures++ > 10) {
-        /* too many failures */
+    if (failures > st->retries) {
         return result;
     }
 
+    if (failures > 0 && st->retry_delay > 0) {
+        apr_sleep(st->retry_delay);
+    }
+
     /* make a server connection */
     if (LDAP_SUCCESS != (result = uldap_connection_open(r, ldc))) {
         /* connect to server failed */
@@ -898,6 +910,7 @@ start_over:
         ldc->reason = "DN Comparison ldap_search_ext_s() "
                       "failed with server down";
         uldap_connection_unbind(ldc);
+        failures++;
         goto start_over;
     }
     if (result == LDAP_TIMEOUT && failures == 0) {
@@ -908,6 +921,7 @@ start_over:
         ldc->reason = "DN Comparison ldap_search_ext_s() "
                       "failed with timeout";
         uldap_connection_unbind(ldc);
+        failures++;
         goto start_over;
     }
     if (result != LDAP_SUCCESS) {
@@ -1030,11 +1044,14 @@ static int uldap_cache_compare(request_r
     }
 
 start_over:
-    if (failures++ > 10) {
-        /* too many failures */
+    if (failures > st->retries) {
         return result;
     }
 
+    if (failures > 0 && st->retry_delay > 0) {
+        apr_sleep(st->retry_delay);
+    }
+
     if (LDAP_SUCCESS != (result = uldap_connection_open(r, ldc))) {
         /* connect failed */
         return result;
@@ -1048,6 +1065,7 @@ start_over:
         /* connection failed - try again */
         ldc->reason = "ldap_compare_s() failed with server down";
         uldap_connection_unbind(ldc);
+        failures++;
         goto start_over;
     }
     if (result == LDAP_TIMEOUT && failures == 0) {
@@ -1057,6 +1075,7 @@ start_over:
          */
         ldc->reason = "ldap_compare_s() failed with timeout";
         uldap_connection_unbind(ldc);
+        failures++;
         goto start_over;
     }
 
@@ -1127,6 +1146,9 @@ static util_compare_subgroup_t* uldap_ge
     LDAPMessage *sga_res, *entry;
     struct mod_auth_ldap_groupattr_entry_t *sgc_ents;
     apr_array_header_t *subgroups = apr_array_make(r->pool, 20, sizeof(char *));
+    util_ldap_state_t *st = (util_ldap_state_t *)
+                            ap_get_module_config(r->server->module_config,
+                                                 &ldap_module);
 
     sgc_ents = (struct mod_auth_ldap_groupattr_entry_t *) subgroupclasses->elts;
 
@@ -1138,11 +1160,15 @@ start_over:
     /*
      * 3.B. The cache didn't have any subgrouplist yet. Go check for subgroups.
      */
-    if (failures++ > 10) {
-        /* too many failures */
+    if (failures > st->retries) {
         return res;
     }
 
+    if (failures > 0 && st->retry_delay > 0) {
+        apr_sleep(st->retry_delay);
+    }
+
+
     if (LDAP_SUCCESS != (result = uldap_connection_open(r, ldc))) {
         /* connect failed */
         return res;
@@ -1156,6 +1182,7 @@ start_over:
         ldc->reason = "ldap_search_ext_s() for subgroups failed with server"
                       " down";
         uldap_connection_unbind(ldc);
+        failures++;
         goto start_over;
     }
     if (result == LDAP_TIMEOUT && failures == 0) {
@@ -1165,6 +1192,7 @@ start_over:
          */
         ldc->reason = "ldap_search_ext_s() for subgroups failed with timeout";
         uldap_connection_unbind(ldc);
+        failures++;
         goto start_over;
     }
 
@@ -1611,9 +1639,14 @@ static int uldap_cache_checkuserid(reque
      * If LDAP operation fails due to LDAP_SERVER_DOWN, control returns here.
      */
 start_over:
-    if (failures++ > 10) {
+    if (failures > st->retries) {
         return result;
     }
+
+    if (failures > 0 && st->retry_delay > 0) {
+        apr_sleep(st->retry_delay);
+    }
+
     if (LDAP_SUCCESS != (result = uldap_connection_open(r, ldc))) {
         return result;
     }
@@ -1627,6 +1660,7 @@ start_over:
     {
         ldc->reason = "ldap_search_ext_s() for user failed with server down";
         uldap_connection_unbind(ldc);
+        failures++;
         goto start_over;
     }
 
@@ -1689,6 +1723,7 @@ start_over:
                           "timed out";
         ldap_msgfree(res);
         uldap_connection_unbind(ldc);
+        failures++;
         goto start_over;
     }
 
@@ -1862,9 +1897,14 @@ static int uldap_cache_getuserdn(request
      * If LDAP operation fails due to LDAP_SERVER_DOWN, control returns here.
      */
 start_over:
-    if (failures++ > 10) {
+    if (failures > st->retries) {
         return result;
     }
+
+    if (failures > 0 && st->retry_delay > 0) {
+        apr_sleep(st->retry_delay);
+    }
+
     if (LDAP_SUCCESS != (result = uldap_connection_open(r, ldc))) {
         return result;
     }
@@ -1878,6 +1918,7 @@ start_over:
     {
         ldc->reason = "ldap_search_ext_s() for user failed with server down";
         uldap_connection_unbind(ldc);
+        failures++;
         goto start_over;
     }
 
@@ -2599,8 +2640,52 @@ static const char *util_ldap_set_conn_tt
     st->connection_pool_ttl = timeout;
     return NULL;
 }
+static const char *util_ldap_set_retry_delay(cmd_parms *cmd,
+                                            void *dummy,
+                                            const char *val)
+{
+    apr_interval_time_t timeout;
+    util_ldap_state_t *st =
+        (util_ldap_state_t *)ap_get_module_config(cmd->server->module_config,
+                                                  &ldap_module);
+    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+
+    if (err != NULL) {
+        return err;
+    }
+
+    if (ap_timeout_parameter_parse(val, &timeout, "s") != APR_SUCCESS) { 
+        return "LDAPRetryDelay has wrong format";
+    }
+
+    if (timeout < 0) { 
+        return "LDAPRetryDelay must be >= 0";
+    }
+
+    st->retry_delay = timeout;
+    return NULL;
+}
+
+static const char *util_ldap_set_retries(cmd_parms *cmd,
+                                            void *dummy,
+                                            const char *val)
+{
+    util_ldap_state_t *st =
+        (util_ldap_state_t *)ap_get_module_config(cmd->server->module_config,
+                                                  &ldap_module);
+    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
+
+    if (err != NULL) {
+        return err;
+    }
 
-     
+    st->retries = atoi(val);
+    if (val < 0) { 
+        return  "LDAPRetries must be >= 0";
+    }
+
+    return NULL; 
+}
 
 static void *util_ldap_create_config(apr_pool_t *p, server_rec *s)
 {
@@ -2631,6 +2716,8 @@ static void *util_ldap_create_config(apr
     st->opTimeout->tv_sec = 60;
     st->verify_svr_cert = 1;
     st->connection_pool_ttl = AP_LDAP_CONNPOOL_DEFAULT; /* no limit */
+    st->retries = 3;
+    st->retry_delay = 0; /* no delay */
 
     return st;
 }
@@ -2685,6 +2772,9 @@ static void *util_ldap_merge_config(apr_
     st->connection_pool_ttl = (overrides->connection_pool_ttl == AP_LDAP_CONNPOOL_DEFAULT) ? 
                                 base->connection_pool_ttl : overrides->connection_pool_ttl;
 
+    st->retries = base->retries;
+    st->retry_delay = base->retry_delay;
+
     return st;
 }
 
@@ -2967,6 +3057,15 @@ static const command_rec util_ldap_cmds[
                   "Specify the maximum amount of time a bound connection can sit "
                   "idle and still be considered valid for reuse"
                   "(0 = no pool, -1 = no limit, n = time in seconds). Default: -1"),
+    AP_INIT_TAKE1("LDAPRetries", util_ldap_set_retries,
+                  NULL, RSRC_CONF,
+                  "Specify the number of times a failed LDAP operation should be retried "
+                  "(0 = no retries). Default: 3"),
+    AP_INIT_TAKE1("LDAPRetryDelay", util_ldap_set_retry_delay,
+                  NULL, RSRC_CONF,
+                  "Specify the delay between retries of a failed LDAP operation "
+                  "(0 = no delay). Default: 0"),
+
 
     {NULL}
 };