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 ),
* 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;
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;
( 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;
- }
- /* 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 );
+ } else {
-done:;
- rs->sr_err = rc;
- if ( rc != LDAP_SUCCESS ) {
+ /* 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 );
+ }
+
+ if ( rs->sr_err != LDAP_SUCCESS ) {
if ( dolock ) {
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
}
meta_back_quarantine( op, rs, candidate );
}
- return rc;
+ return rs->sr_err;
}
/*
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,
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 );
}
if ( rc == LDAP_SUCCESS ) {
+ quarantine = 0;
rc = meta_back_single_dobind( op, rs, mcp, candidate,
sendok, mt->mt_nretries, 0 );
}
}
- if ( META_BACK_TGT_QUARANTINE( mt ) ) {
+ if ( quarantine && META_BACK_TGT_QUARANTINE( mt ) ) {
meta_back_quarantine( op, rs, candidate );
}
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",
} 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,
( 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 ) {
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 );
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 ) {
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 );
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;
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 {
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;
"%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;
}
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;
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:
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;
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:
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;
op->o_private = savepriv;
goto finish;
}
- if ( META_BACK_ONERR_REPORT( mi ) ) {
- candidates[ i ].sr_err = rs->sr_err;
- }
break;
case META_SEARCH_BINDING:
}
}
+ candidates[ i ].sr_err = rs->sr_err;
if ( META_BACK_ONERR_STOP( mi ) ) {
savepriv = op->o_private;
op->o_private = (void *)i;
op->o_private = savepriv;
goto finish;
}
- if ( META_BACK_ONERR_REPORT( mi ) ) {
- candidates[ i ].sr_err = rs->sr_err;
- }
}
/*
* 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 ) )
{
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;
res = NULL;
goto finish;
}
- if ( META_BACK_ONERR_REPORT( mi ) ) {
- candidates[ i ].sr_err = rs->sr_err;
- }
break;
}
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;
res = NULL;
goto finish;
}
- if ( META_BACK_ONERR_REPORT( mi ) ) {
- candidates[ i ].sr_err = rs->sr_err;
- }
break;
default: