]> git.sur5r.net Git - openldap/commitdiff
fix retry; add per-target configurable number of retries; addresses ITS#3672, ITS...
authorPierangelo Masarati <ando@openldap.org>
Mon, 25 Apr 2005 18:56:56 +0000 (18:56 +0000)
committerPierangelo Masarati <ando@openldap.org>
Mon, 25 Apr 2005 18:56:56 +0000 (18:56 +0000)
doc/man/man5/slapd-meta.5
servers/slapd/back-meta/back-meta.h
servers/slapd/back-meta/bind.c
servers/slapd/back-meta/config.c
servers/slapd/back-meta/conn.c
tests/data/slapd-meta.conf
tests/scripts/test036-meta-concurrency

index 1916b6905da1f5d513f8f9660256e29887b7138f..316c49ac480fb7fd6a1add67a137106bb17675e1 100644 (file)
@@ -93,6 +93,14 @@ This caches the target that holds a given DN to speed up target
 selection in case multiple targets would result from an uncached
 search; forever means cache never expires; disabled means no DN
 caching; otherwise a valid ( > 0 ) ttl in seconds is required.
+.TP
+.B nretries {forever|never|<nretries>}
+This directive defines how many times a bind should be retried
+in case of temporary failure in contacting a target.  If defined
+before any target specification, it applies to all targets (by default,
+.BR never );
+the global value can be overridden by redefinitions inside each target
+specification.
 .SH TARGET SPECIFICATION
 Target specification starts with a "uri" directive:
 .TP
index d6ff6be16bed6fec715672080b9cf8ef9ccfffb2..7d4d91490a9264a729a06ba07fb9cf498681b997 100644 (file)
@@ -82,7 +82,7 @@ typedef struct dncookie {
 #endif
 } dncookie;
 
-#define META_BIND_NRETRIES     3
+/* TODO: allow to define it on a per-target basis */
 #define META_BIND_TIMEOUT      10000
 
 int ldap_back_dn_massage(dncookie *dc, struct berval *dn,
@@ -198,6 +198,11 @@ typedef struct metatarget_t {
        struct berval           mt_pseudorootdn;
        struct berval           mt_pseudorootpw;
 
+       int                     mt_nretries;
+#define META_RETRY_UNDEFINED   (-2)
+#define META_RETRY_FOREVER     (-1)
+#define META_RETRY_NEVER       (0)
+
        struct ldaprwmap        mt_rwmap;
 } metatarget_t;
 
@@ -215,6 +220,8 @@ typedef struct metainfo_t {
        int                     mi_defaulttarget;
        int                     mi_network_timeout;
 #define META_DEFAULT_TARGET_NONE       (-1)
+       int                     mi_nretries;
+
        metatarget_t            **mi_targets;
        SlapReply               *mi_candidates;
 
index a16256efe4256a5b695f43937fe72aefb890263a..ef8484172ae346c2464ce3c181b9b209831d4920 100644 (file)
@@ -207,21 +207,26 @@ rebind:;
                        op->o_ctrls, NULL, &msgid );
        if ( rs->sr_err == LDAP_SUCCESS ) {
                LDAPMessage     *res;
-               struct timeval  tv = { 0, 0 };
+               struct timeval  tv;
                int             rc;
-               int             nretries = META_BIND_NRETRIES;
+               int             nretries = mt->mt_nretries;
 
                /*
                 * handle response!!!
                 */
 retry:;
+               tv.tv_sec = 0;
+               tv.tv_usec = META_BIND_TIMEOUT;
                switch ( ldap_result( msc->msc_ld, msgid, 0, &tv, &res ) ) {
                case 0:
-                       if ( nretries > 0 ) {
+                       Debug( LDAP_DEBUG_ANY, "%s meta_back_single_bind: ldap_result=%d nretries=%d\n",
+                               op->o_log_prefix, 0, nretries );
+
+                       if ( nretries != META_RETRY_NEVER ) {
                                ldap_pvt_thread_yield();
-                               tv.tv_sec = 0;
-                               tv.tv_usec = META_BIND_TIMEOUT;
-                               nretries--;
+                               if ( nretries > 0 ) {
+                                       nretries--;
+                               }
                                goto retry;
                        }
                        rs->sr_err = LDAP_BUSY;
@@ -231,10 +236,11 @@ retry:;
                        ldap_get_option( msc->msc_ld, LDAP_OPT_ERROR_NUMBER,
                                        &rs->sr_err );
 
-                       Debug( LDAP_DEBUG_ANY, "### %s meta_back_single_bind(%s) err=%d\n",
-                               op->o_log_prefix, mdn.bv_val, rs->sr_err );
+                       Debug( LDAP_DEBUG_ANY, "### %s meta_back_single_bind: err=%d nretries=%d\n",
+                               op->o_log_prefix, rs->sr_err, nretries );
 
-                       if ( rs->sr_err == LDAP_UNAVAILABLE && nretries > 0 ) {
+                       rc = slap_map_api2result( rs );
+                       if ( rs->sr_err == LDAP_UNAVAILABLE && nretries != META_RETRY_NEVER ) {
                                ldap_unbind_ext_s( msc->msc_ld, NULL, NULL );
                                msc->msc_ld = NULL;
                                msc->msc_bound = 0;
@@ -243,7 +249,9 @@ retry:;
                                rc = meta_back_init_one_conn( op, rs, mt, msc,
                                                LDAP_BACK_DONTSEND );
                                if ( rc ) {
-                                       nretries--;
+                                       if ( nretries > 0 ) {
+                                               nretries--;
+                                       }
                                        ldap_pvt_thread_yield();
                                        goto rebind;
                                }
@@ -299,7 +307,7 @@ meta_back_single_dobind(
        metaconn_t              *mc,
        int                     candidate,
        ldap_back_send_t        sendok,
-       int                     retries )
+       int                     nretries )
 {
        metainfo_t              *mi = ( metainfo_t * )op->o_bd->be_private;
        metatarget_t            *mt = mi->mi_targets[ candidate ];
@@ -332,7 +340,7 @@ rebind:;
                        NULL, NULL, &msgid );
        if ( rc == LDAP_SUCCESS ) {
                LDAPMessage     *res;
-               struct timeval  tv = { 0, 0 };
+               struct timeval  tv;
 
                /*
                 * handle response!!!
@@ -342,9 +350,14 @@ retry:;
                tv.tv_usec = META_BIND_TIMEOUT;
                switch ( ldap_result( msc->msc_ld, msgid, 0, &tv, &res ) ) {
                case 0:
-                       if ( retries > 0 ) {
+                       Debug( LDAP_DEBUG_ANY, "%s meta_back_single_dobind: ldap_result=%d nretries=%d\n",
+                               op->o_log_prefix, 0, nretries );
+
+                       if ( nretries != META_RETRY_NEVER ) {
                                ldap_pvt_thread_yield();
-                               retries--;
+                               if ( nretries > 0 ) {
+                                       nretries--;
+                               }
                                goto retry;
                        }
 
@@ -355,11 +368,11 @@ retry:;
                        ldap_get_option( msc->msc_ld,
                                        LDAP_OPT_ERROR_NUMBER, &rs->sr_err );
 
-                       Debug( LDAP_DEBUG_ANY, "### %s meta_back_single_dobind(\"\") err=%d\n",
-                               op->o_log_prefix, rs->sr_err, 0 );
+                       Debug( LDAP_DEBUG_ANY, "### %s meta_back_single_dobind: err=%d nretries=%d\n",
+                                       op->o_log_prefix, rs->sr_err, nretries );
 
                        rc = slap_map_api2result( rs );
-                       if ( rc == LDAP_UNAVAILABLE && retries > 0 ) {
+                       if ( rc == LDAP_UNAVAILABLE && nretries != META_RETRY_NEVER ) {
                                ldap_unbind_ext_s( msc->msc_ld, NULL, NULL );
                                msc->msc_ld = NULL;
                                msc->msc_bound = 0;
@@ -367,9 +380,11 @@ retry:;
                                /* mc here must be the regular mc, reset and ready for init */
                                rc = meta_back_init_one_conn( op, rs, mt, msc, LDAP_BACK_DONTSEND );
 
-                               if ( rc ) {
+                               if ( rc == LDAP_SUCCESS ) {
                                        ldap_pvt_thread_yield();
-                                       retries--;
+                                       if ( nretries > 0 ) {
+                                               nretries--;
+                                       }
                                        goto rebind;
                                }
                        }
@@ -385,8 +400,8 @@ retry:;
                }
        }
 
+       rs->sr_err = rc;
        if ( rc != LDAP_SUCCESS && ( sendok & LDAP_BACK_SENDERR ) ) {
-               rs->sr_err = rc;
                send_ldap_result( op, rs );
        }
 
@@ -403,6 +418,8 @@ meta_back_dobind(
        metaconn_t              *mc,
        ldap_back_send_t        sendok )
 {
+       metainfo_t              *mi = ( metainfo_t * )op->o_bd->be_private;
+
        metasingleconn_t        *msc;
        int                     bound = 0, i;
 
@@ -419,6 +436,7 @@ meta_back_dobind(
        }
 
        for ( i = 0, msc = &mc->mc_conns[ 0 ]; !META_LAST( msc ); ++i, ++msc ) {
+               metatarget_t    *mt = mi->mi_targets[ i ];
                int             rc;
 
                /*
@@ -437,7 +455,7 @@ meta_back_dobind(
                }
 
                rc = meta_back_single_dobind( op, rs, mc, i,
-                       LDAP_BACK_DONTSEND, META_BIND_NRETRIES );
+                               LDAP_BACK_DONTSEND, mt->mt_nretries );
                if ( rc != LDAP_SUCCESS ) {
                        Debug( LDAP_DEBUG_ANY, "%s meta_back_dobind[%d]: "
                                        "(anonymous) err=%d\n",
index e89ed175808933fa218e79e1d20aa21e762d5dd6..a5ec9a63a8a4e8a753d7d560e6e5341a23f4d8d6 100644 (file)
@@ -75,6 +75,8 @@ new_target( void )
 
        ldap_back_map_init( &mt->mt_rwmap.rwm_at, &mapping );
 
+       mt->mt_nretries = META_RETRY_UNDEFINED;
+
        return mt;
 }
 
@@ -134,6 +136,8 @@ meta_back_db_config(
                        return 1;
                }
 
+               mi->mi_targets[ i ]->mt_nretries = mi->mi_nretries;
+
                /*
                 * uri MUST be legal!
                 */
@@ -618,6 +622,43 @@ meta_back_db_config(
                return ldap_back_map_config( &mi->mi_targets[ i ]->mt_rwmap.rwm_oc, 
                                &mi->mi_targets[ i ]->mt_rwmap.rwm_at,
                                fname, lineno, argc, argv );
+
+       } else if ( strcasecmp( argv[ 0 ], "nretries" ) == 0 ) {
+               int             i = mi->mi_ntargets - 1;
+               int             nretries = META_RETRY_UNDEFINED;
+
+               if ( argc != 2 ) {
+                       fprintf( stderr,
+       "%s: line %d: need value in \"nretries <value>\"\n",
+                               fname, lineno );
+                       return 1;
+               }
+
+               if ( strcasecmp( argv[ 1 ], "forever" ) == 0 ) {
+                       nretries = META_RETRY_FOREVER;
+
+               } else if ( strcasecmp( argv[ 1 ], "never" ) == 0 ) {
+                       nretries = META_RETRY_NEVER;
+
+               } else {
+                       char    *next;
+
+                       nretries = strtol( argv[ 1 ], &next, 10 );
+                       if ( next == argv[ 1 ] || next[ 0 ] != '\0' ) {
+                               fprintf( stderr,
+       "%s: line %d: unable to parse value \"%s\" in \"nretries <value>\"\n",
+                                       fname, lineno, argv[ 1 ] );
+                               return 1;
+                       }
+               }
+
+               if ( i < 0 ) {
+                       mi->mi_nretries = nretries;
+
+               } else {
+                       mi->mi_targets[ i ]->mt_nretries = nretries;
+               }
+
        /* anything else */
        } else {
                return SLAP_CONF_UNKNOWN;
index 4d4bf13ed4f3198e4cefe563ce8375aaad5dadb9..ebf63df8397b932633aeb1189936b56b53a276ba 100644 (file)
@@ -230,7 +230,7 @@ meta_back_init_one_conn(
                rs->sr_err = ldap_start_tls( msc->msc_ld, NULL, NULL, &msgid );
                if ( rs->sr_err == LDAP_SUCCESS ) {
                        LDAPMessage     *res = NULL;
-                       int             rc, retries = 1;
+                       int             rc, nretries = mt->mt_nretries;
                        struct timeval  tv = { 0, 0 };
 
 retry:;
@@ -239,8 +239,10 @@ retry:;
                                rs->sr_err = LDAP_OTHER;
 
                        } else if ( rc == 0 ) {
-                               if ( retries ) {
-                                       retries--;
+                               if ( nretries != 0 ) {
+                                       if ( nretries > 0 ) {
+                                               nretries--;
+                                       }
                                        tv.tv_sec = 0;
                                        tv.tv_usec = 100000;
                                        goto retry;
@@ -393,8 +395,8 @@ meta_back_retry(
         rc = meta_back_init_one_conn( op, rs, mt, msc, sendok );
 
        if ( rc == LDAP_SUCCESS ) {
-               rc = meta_back_single_dobind( op, rs, mc, candidate, sendok,
-                               META_BIND_NRETRIES );
+               rc = meta_back_single_dobind( op, rs, mc, candidate,
+                               sendok, mt->mt_nretries );
         }
 
        ldap_pvt_thread_mutex_unlock( &mc->mc_mutex );
@@ -787,6 +789,8 @@ meta_back_getconn(
         */
        } else {
 
+               int     ncandidates = 0;
+
                /* Looks like we didn't get a bind. Open a new session... */
                if ( !mc ) {
                        mc = metaconn_alloc( mi->mi_ntargets );
@@ -809,6 +813,7 @@ meta_back_getconn(
                                                &mc->mc_conns[ i ], sendok );
                                if ( lerr == LDAP_SUCCESS ) {
                                        candidates[ i ].sr_tag = META_CANDIDATE;
+                                       ncandidates++;
 
                                } else {
                                
@@ -817,6 +822,9 @@ meta_back_getconn(
                                         * be init'd, should the other ones
                                         * be tried?
                                         */
+                                       if ( new_conn ) {
+                                               ( void )meta_clear_one_candidate( &mc->mc_conns[ i ] );
+                                       }
                                        candidates[ i ].sr_tag = META_NOT_CANDIDATE;
                                        err = lerr;
 
@@ -827,9 +835,28 @@ meta_back_getconn(
                                }
 
                        } else {
+                               if ( new_conn ) {
+                                       ( void )meta_clear_one_candidate( &mc->mc_conns[ i ] );
+                               }
                                candidates[ i ].sr_tag = META_NOT_CANDIDATE;
                        }
                }
+
+               if ( ncandidates == 0 ) {
+                       if ( new_conn ) {
+                               meta_back_conn_free( mc );
+                       }
+
+                       rs->sr_err = LDAP_NO_SUCH_OBJECT;
+                       rs->sr_text = "Unable to select valid candidates";
+
+                       if ( sendok & LDAP_BACK_SENDERR ) {
+                               send_ldap_result( op, rs );
+                               rs->sr_text = NULL;
+                       }
+
+                       return NULL;
+               }
        }
 
 done:;
index 78a1e4a947dd3db7dd07bc7c54f2630551ed81b6..f98a5abf449a75cf09ae3f6d9eeb870b45bb0ae9 100644 (file)
@@ -43,6 +43,7 @@ database      meta
 suffix         "o=Example,c=US"
 rootdn         "cn=Manager,o=Example,c=US"
 rootpw         secret
+nretries       forever
 
 # local
 uri            "@URI2@ou=Meta,o=Example,c=US"
index 57e28743e1d485d23b99540559a6d0d9764373b4..dd5218bd314c0340f3500ec0449a284d9177dd3d 100755 (executable)
@@ -198,7 +198,7 @@ echo "Filtering original ldif used to create database..."
 . $LDIFFILTER < $METACONCURRENCYOUT > $LDIFFLT
 echo "Comparing filter output..."
 $CMP $SEARCHFLT $LDIFFLT > $CMPOUT
-       
+
 if test $? != 0 ; then
        echo "comparison failed - meta search/modification didn't succeed"
        exit 1