fix retry; add per-target configurable number of retries; addresses ITS#3672, ITS#3676 & ITS#3680

This commit is contained in:
Pierangelo Masarati 2005-04-25 18:56:56 +00:00
parent 0ec5e2df77
commit fa49a73fc4
7 changed files with 130 additions and 28 deletions

View 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

View 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;

View 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",

View 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;

View 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:;

View 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"

View File

@ -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