better async connection and partial error handling

This commit is contained in:
Pierangelo Masarati 2007-01-07 22:06:13 +00:00
parent 9b5ea6a205
commit 671330a051
4 changed files with 105 additions and 56 deletions

View file

@ -194,6 +194,7 @@ struct metainfo_t;
#define META_NOT_CANDIDATE ((ber_tag_t)0x0)
#define META_CANDIDATE ((ber_tag_t)0x1)
#define META_BINDING ((ber_tag_t)0x2)
#define META_RETRYING ((ber_tag_t)0x4)
typedef struct metasingleconn_t {
#define META_CND_ISSET(rs,f) ( ( (rs)->sr_tag & (f) ) == (f) )
@ -207,6 +208,9 @@ typedef struct metasingleconn_t {
#define META_IS_BINDING(rs) META_CND_ISSET( (rs), META_BINDING )
#define META_BINDING_SET(rs) META_CND_SET( (rs), META_BINDING )
#define META_BINDING_CLEAR(rs) META_CND_CLEAR( (rs), META_BINDING )
#define META_IS_RETRYING(rs) META_CND_ISSET( (rs), META_RETRYING )
#define META_RETRYING_SET(rs) META_CND_SET( (rs), META_RETRYING )
#define META_RETRYING_CLEAR(rs) META_CND_CLEAR( (rs), META_RETRYING )
LDAP *msc_ld;
time_t msc_time;

View file

@ -407,7 +407,7 @@ retry:;
break;
case -1:
ldap_get_option( msc->msc_ld, LDAP_OPT_RESULT_CODE,
ldap_get_option( msc->msc_ld, LDAP_OPT_ERROR_NUMBER,
&rs->sr_err );
snprintf( buf, sizeof( buf ),
@ -493,9 +493,15 @@ meta_back_single_bind(
* and more in case of failure ... */
/* FIXME: should we check if at least some of the op->o_ctrls
* can/should be passed? */
rs->sr_err = ldap_sasl_bind( msc->msc_ld, mdn.bv_val,
for (;;) {
rs->sr_err = ldap_sasl_bind( msc->msc_ld, mdn.bv_val,
LDAP_SASL_SIMPLE, &op->orb_cred,
op->o_ctrls, NULL, &msgid );
if ( rs->sr_err != LDAP_X_CONNECTING ) {
break;
}
ldap_pvt_thread_yield();
}
meta_back_bind_op_result( op, rs, mc, candidate, msgid, LDAP_BACK_DONTSEND );
if ( rs->sr_err != LDAP_SUCCESS ) {
goto return_results;
@ -564,7 +570,6 @@ meta_back_single_dobind(
metatarget_t *mt = mi->mi_targets[ candidate ];
metaconn_t *mc = *mcp;
metasingleconn_t *msc = &mc->mc_conns[ candidate ];
int rc;
static struct berval cred = BER_BVC( "" );
int msgid;
@ -579,19 +584,25 @@ meta_back_single_dobind(
( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) )
{
(void)meta_back_proxy_authz_bind( mc, candidate, op, rs, sendok );
rc = rs->sr_err;
goto done;
} else {
/* FIXME: should we check if at least some of the op->o_ctrls
* can/should be passed? */
for (;;) {
rs->sr_err = ldap_sasl_bind( msc->msc_ld,
"", LDAP_SASL_SIMPLE, &cred,
NULL, NULL, &msgid );
if ( rs->sr_err != LDAP_X_CONNECTING ) {
break;
}
ldap_pvt_thread_yield();
}
rs->sr_err = meta_back_bind_op_result( op, rs, mc, candidate, msgid, sendok );
}
/* FIXME: should we check if at least some of the op->o_ctrls
* can/should be passed? */
rs->sr_err = ldap_sasl_bind( msc->msc_ld, "", LDAP_SASL_SIMPLE, &cred,
NULL, NULL, &msgid );
rc = meta_back_bind_op_result( op, rs, mc, candidate, msgid, sendok );
done:;
rs->sr_err = rc;
if ( rc != LDAP_SUCCESS ) {
if ( rs->sr_err != LDAP_SUCCESS ) {
if ( dolock ) {
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
}
@ -614,7 +625,7 @@ done:;
meta_back_quarantine( op, rs, candidate );
}
return rc;
return rs->sr_err;
}
/*
@ -1457,9 +1468,15 @@ meta_back_proxy_authz_bind( metaconn_t *mc, int candidate, Operation *op, SlapRe
switch ( method ) {
case LDAP_AUTH_NONE:
case LDAP_AUTH_SIMPLE:
rs->sr_err = ldap_sasl_bind( msc->msc_ld,
for (;;) {
rs->sr_err = ldap_sasl_bind( msc->msc_ld,
binddn.bv_val, LDAP_SASL_SIMPLE,
&cred, NULL, NULL, &msgid );
if ( rs->sr_err != LDAP_X_CONNECTING ) {
break;
}
ldap_pvt_thread_yield();
}
rc = meta_back_bind_op_result( op, rs, mc, candidate, msgid, sendok );
if ( rc == LDAP_SUCCESS ) {
/* set rebind stuff in case of successful proxyAuthz bind,

View file

@ -644,7 +644,8 @@ meta_back_retry(
metaconn_t *mc = *mcp;
metasingleconn_t *msc = &mc->mc_conns[ candidate ];
int rc = LDAP_UNAVAILABLE,
binding;
binding,
quarantine = 1;
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
@ -687,6 +688,7 @@ meta_back_retry(
}
if ( rc == LDAP_SUCCESS ) {
quarantine = 0;
rc = meta_back_single_dobind( op, rs, mcp, candidate,
sendok, mt->mt_nretries, 0 );
@ -776,7 +778,7 @@ meta_back_retry(
}
}
if ( META_BACK_TGT_QUARANTINE( mt ) ) {
if ( quarantine && META_BACK_TGT_QUARANTINE( mt ) ) {
meta_back_quarantine( op, rs, candidate );
}
@ -1451,9 +1453,9 @@ retry_lock2:;
int lerr = meta_back_init_one_conn( op, rs, mc, i,
LDAP_BACK_CONN_ISPRIV( &mc_curr ),
LDAP_BACK_DONTSEND, !new_conn );
candidates[ i ].sr_err = lerr;
if ( lerr == LDAP_SUCCESS ) {
META_CANDIDATE_SET( &candidates[ i ] );
candidates[ i ].sr_err = LDAP_SUCCESS;
ncandidates++;
Debug( LDAP_DEBUG_TRACE, "%s: meta_back_getconn[%d]\n",
@ -1461,7 +1463,6 @@ retry_lock2:;
} else if ( lerr == LDAP_UNAVAILABLE && !META_BACK_ONERR_STOP( mi ) ) {
META_CANDIDATE_SET( &candidates[ i ] );
candidates[ i ].sr_err = LDAP_UNAVAILABLE;
Debug( LDAP_DEBUG_TRACE, "%s: meta_back_getconn[%d] %s\n",
op->o_log_prefix, i,
@ -1478,7 +1479,6 @@ retry_lock2:;
( void )meta_clear_one_candidate( op, mc, i );
}
/* leave the target candidate, but record the error for later use */
candidates[ i ].sr_err = lerr;
err = lerr;
if ( lerr == LDAP_UNAVAILABLE && mt->mt_isquarantined != LDAP_BACK_FQ_NO ) {

View file

@ -229,6 +229,10 @@ meta_search_dobind_init(
assert( msc->msc_ld != NULL );
/* connect must be async */
retry:;
ldap_set_option( msc->msc_ld, LDAP_OPT_CONNECT_ASYNC, LDAP_OPT_ON );
rc = ldap_sasl_bind( msc->msc_ld, binddn.bv_val, LDAP_SASL_SIMPLE, &cred,
NULL, NULL, &candidates[ candidate ].sr_msgid );
@ -249,13 +253,55 @@ meta_search_dobind_init(
META_BINDING_SET( &candidates[ candidate ] );
return META_SEARCH_BINDING;
case LDAP_X_CONNECTING:
/* must retry, same conn */
candidates[ candidate ].sr_msgid = META_MSGID_NEED_BIND;
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
LDAP_BACK_CONN_BINDING_CLEAR( msc );
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
return META_SEARCH_NEED_BIND;
case LDAP_SERVER_DOWN:
down:;
/* This is the worst thing that could happen:
* the search will wait until the retry is over. */
if ( meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND ) ) {
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
return META_SEARCH_CANDIDATE;
if ( !META_IS_RETRYING( &candidates[ candidate ] ) ) {
META_RETRYING_SET( &candidates[ candidate ] );
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
assert( mc->mc_refcnt > 0 );
if ( LogTest( LDAP_DEBUG_ANY ) ) {
char buf[ SLAP_TEXT_BUFLEN ];
/* this lock is required; however,
* it's invoked only when logging is on */
ldap_pvt_thread_mutex_lock( &mt->mt_uri_mutex );
snprintf( buf, sizeof( buf ),
"retrying URI=\"%s\" DN=\"%s\"",
mt->mt_uri,
BER_BVISNULL( &msc->msc_bound_ndn ) ?
"" : msc->msc_bound_ndn.bv_val );
ldap_pvt_thread_mutex_unlock( &mt->mt_uri_mutex );
Debug( LDAP_DEBUG_ANY,
"%s meta_search_dobind_init[%d]: %s.\n",
op->o_log_prefix, candidate, buf );
}
meta_clear_one_candidate( op, mc, candidate );
LDAP_BACK_CONN_ISBOUND_CLEAR( msc );
( void )rewrite_session_delete( mt->mt_rwmap.rwm_rw, op->o_conn );
/* mc here must be the regular mc, reset and ready for init */
rc = meta_back_init_one_conn( op, rs, mc, candidate,
LDAP_BACK_CONN_ISPRIV( mc ), LDAP_BACK_DONTSEND, 0 );
LDAP_BACK_CONN_BINDING_SET( msc );
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
goto retry;
}
if ( *mcp == NULL ) {
@ -272,6 +318,7 @@ other:;
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
meta_clear_one_candidate( op, mc, candidate );
candidates[ candidate ].sr_err = rc;
if ( META_BACK_ONERR_STOP( mi ) ) {
LDAP_BACK_CONN_TAINTED_SET( mc );
meta_back_release_conn_lock( op, mc, 0 );
@ -280,10 +327,6 @@ other:;
retcode = META_SEARCH_ERR;
} else {
if ( META_BACK_ONERR_REPORT( mi ) ) {
candidates[ candidate ].sr_err = rc;
}
retcode = META_SEARCH_NOT_CANDIDATE;
}
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
@ -326,16 +369,14 @@ meta_search_dobind_result(
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
LDAP_BACK_CONN_BINDING_CLEAR( msc );
if ( rc != LDAP_SUCCESS ) {
meta_clear_one_candidate( op, mc, candidate );
candidates[ candidate ].sr_err = rc;
if ( META_BACK_ONERR_STOP( mi ) ) {
LDAP_BACK_CONN_TAINTED_SET( mc );
meta_clear_one_candidate( op, mc, candidate );
meta_back_release_conn_lock( op, mc, 0 );
*mcp = NULL;
retcode = META_SEARCH_ERR;
rs->sr_err = rc;
} else if ( META_BACK_ONERR_REPORT( mi ) ) {
candidates[ candidate ].sr_err = rc;
}
} else {
@ -349,6 +390,9 @@ meta_search_dobind_result(
LDAP_BACK_CONN_ISBOUND_SET( msc );
}
retcode = META_SEARCH_CANDIDATE;
/* connect must be async */
ldap_set_option( msc->msc_ld, LDAP_OPT_CONNECT_ASYNC, LDAP_OPT_OFF );
}
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
@ -388,12 +432,10 @@ meta_back_search_start(
"%s: meta_back_search_start candidate=%d ld=NULL%s.\n",
op->o_log_prefix, candidate,
META_BACK_ONERR_STOP( mi ) ? "" : " (ignored)" );
candidates[ candidate ].sr_err = LDAP_OTHER;
if ( META_BACK_ONERR_STOP( mi ) ) {
return META_SEARCH_ERR;
}
if ( META_BACK_ONERR_REPORT( mi ) ) {
candidates[ candidate ].sr_err = LDAP_OTHER;
}
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
return META_SEARCH_NOT_CANDIDATE;
}
@ -846,6 +888,7 @@ getconn:;
break;
case META_SEARCH_ERR:
candidates[ i ].sr_err = rs->sr_err;
if ( META_BACK_ONERR_STOP( mi ) ) {
savepriv = op->o_private;
op->o_private = (void *)i;
@ -853,9 +896,6 @@ getconn:;
op->o_private = savepriv;
goto finish;
}
if ( META_BACK_ONERR_REPORT( mi ) ) {
candidates[ i ].sr_err = rs->sr_err;
}
/* fallthru */
case META_SEARCH_NOT_CANDIDATE:
@ -877,6 +917,7 @@ getconn:;
break;
case META_SEARCH_ERR:
candidates[ i ].sr_err = rs->sr_err;
if ( META_BACK_ONERR_STOP( mi ) ) {
savepriv = op->o_private;
op->o_private = (void *)i;
@ -884,9 +925,6 @@ getconn:;
op->o_private = savepriv;
goto finish;
}
if ( META_BACK_ONERR_REPORT( mi ) ) {
candidates[ i ].sr_err = rs->sr_err;
}
/* fallthru */
case META_SEARCH_NOT_CANDIDATE:
@ -970,6 +1008,7 @@ really_bad:;
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
--ncandidates;
candidates[ i ].sr_err = rs->sr_err;
if ( META_BACK_ONERR_STOP( mi ) ) {
savepriv = op->o_private;
op->o_private = (void *)i;
@ -977,9 +1016,6 @@ really_bad:;
op->o_private = savepriv;
goto finish;
}
if ( META_BACK_ONERR_REPORT( mi ) ) {
candidates[ i ].sr_err = rs->sr_err;
}
break;
case META_SEARCH_BINDING:
@ -994,6 +1030,7 @@ really_bad:;
}
}
candidates[ i ].sr_err = rs->sr_err;
if ( META_BACK_ONERR_STOP( mi ) ) {
savepriv = op->o_private;
op->o_private = (void *)i;
@ -1001,9 +1038,6 @@ really_bad:;
op->o_private = savepriv;
goto finish;
}
if ( META_BACK_ONERR_REPORT( mi ) ) {
candidates[ i ].sr_err = rs->sr_err;
}
}
/*
@ -1270,6 +1304,7 @@ really_bad:;
* the target enforced a limit lower
* than what requested by the proxy;
* ignore it */
candidates[ i ].sr_err = rs->sr_err;
if ( rs->sr_nentries == op->ors_slimit
|| META_BACK_ONERR_STOP( mi ) )
{
@ -1281,12 +1316,10 @@ really_bad:;
res = NULL;
goto finish;
}
if ( META_BACK_ONERR_REPORT( mi ) ) {
candidates[ i ].sr_err = rs->sr_err;
}
break;
default:
candidates[ i ].sr_err = rs->sr_err;
if ( META_BACK_ONERR_STOP( mi ) ) {
savepriv = op->o_private;
op->o_private = (void *)i;
@ -1296,9 +1329,6 @@ really_bad:;
res = NULL;
goto finish;
}
if ( META_BACK_ONERR_REPORT( mi ) ) {
candidates[ i ].sr_err = rs->sr_err;
}
break;
}
@ -1331,6 +1361,7 @@ really_bad:;
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
--ncandidates;
candidates[ i ].sr_err = rs->sr_err;
if ( META_BACK_ONERR_STOP( mi ) ) {
savepriv = op->o_private;
op->o_private = (void *)i;
@ -1340,9 +1371,6 @@ really_bad:;
res = NULL;
goto finish;
}
if ( META_BACK_ONERR_REPORT( mi ) ) {
candidates[ i ].sr_err = rs->sr_err;
}
break;
default: