mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
fix retry; add per-target configurable number of retries; addresses ITS#3672, ITS#3676 & ITS#3680
This commit is contained in:
parent
0ec5e2df77
commit
fa49a73fc4
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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;
|
||||
|
@ -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:;
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user