From: Pierangelo Masarati Date: Mon, 25 Apr 2005 18:56:56 +0000 (+0000) Subject: fix retry; add per-target configurable number of retries; addresses ITS#3672, ITS... X-Git-Tag: OPENLDAP_AC_BP~799 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=fa49a73fc491863249a82dc9cc27483bb33d9f1e;p=openldap fix retry; add per-target configurable number of retries; addresses ITS#3672, ITS#3676 & ITS#3680 --- diff --git a/doc/man/man5/slapd-meta.5 b/doc/man/man5/slapd-meta.5 index 1916b6905d..316c49ac48 100644 --- a/doc/man/man5/slapd-meta.5 +++ b/doc/man/man5/slapd-meta.5 @@ -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|} +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 diff --git a/servers/slapd/back-meta/back-meta.h b/servers/slapd/back-meta/back-meta.h index d6ff6be16b..7d4d91490a 100644 --- a/servers/slapd/back-meta/back-meta.h +++ b/servers/slapd/back-meta/back-meta.h @@ -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; diff --git a/servers/slapd/back-meta/bind.c b/servers/slapd/back-meta/bind.c index a16256efe4..ef8484172a 100644 --- a/servers/slapd/back-meta/bind.c +++ b/servers/slapd/back-meta/bind.c @@ -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", diff --git a/servers/slapd/back-meta/config.c b/servers/slapd/back-meta/config.c index e89ed17580..a5ec9a63a8 100644 --- a/servers/slapd/back-meta/config.c +++ b/servers/slapd/back-meta/config.c @@ -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 \"\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 \"\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; diff --git a/servers/slapd/back-meta/conn.c b/servers/slapd/back-meta/conn.c index 4d4bf13ed4..ebf63df839 100644 --- a/servers/slapd/back-meta/conn.c +++ b/servers/slapd/back-meta/conn.c @@ -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:; diff --git a/tests/data/slapd-meta.conf b/tests/data/slapd-meta.conf index 78a1e4a947..f98a5abf44 100644 --- a/tests/data/slapd-meta.conf +++ b/tests/data/slapd-meta.conf @@ -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" diff --git a/tests/scripts/test036-meta-concurrency b/tests/scripts/test036-meta-concurrency index 57e28743e1..dd5218bd31 100755 --- a/tests/scripts/test036-meta-concurrency +++ b/tests/scripts/test036-meta-concurrency @@ -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