gracefully handle server down while initiating a search (ITS#4518)

This commit is contained in:
Pierangelo Masarati 2006-05-04 08:37:31 +00:00
parent 4934a7ab00
commit 9447b9fff4

View File

@ -35,6 +35,12 @@
#include "ldap_log.h" #include "ldap_log.h"
#include "../../../libraries/libldap/ldap-int.h" #include "../../../libraries/libldap/ldap-int.h"
/* IGNORE means that target does not (no longer) participate
* in the search;
* NOTREADY means the search on that target has not been initialized yet
*/
#define META_MSGID_IGNORE (-1)
static int static int
meta_send_entry( meta_send_entry(
Operation *op, Operation *op,
@ -54,21 +60,24 @@ meta_back_search_start(
Operation *op, Operation *op,
SlapReply *rs, SlapReply *rs,
dncookie *dc, dncookie *dc,
metasingleconn_t *msc, metaconn_t **mcp,
int candidate, int candidate,
SlapReply *candidates SlapReply *candidates )
)
{ {
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private; metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
struct berval realbase = op->o_req_dn; metatarget_t *mt = &mi->mi_targets[ candidate ];
int realscope = op->ors_scope; metaconn_t *mc = *mcp;
ber_len_t suffixlen = 0; metasingleconn_t *msc = &mc->mc_conns[ candidate ];
struct berval mbase = BER_BVNULL; struct berval realbase = op->o_req_dn;
struct berval mfilter = BER_BVNULL; int realscope = op->ors_scope;
char **mapped_attrs = NULL; ber_len_t suffixlen = 0;
int rc; struct berval mbase = BER_BVNULL;
struct berval mfilter = BER_BVNULL;
char **mapped_attrs = NULL;
int rc;
meta_search_candidate_t retcode; meta_search_candidate_t retcode;
struct timeval tv, *tvp = NULL; struct timeval tv, *tvp = NULL;
int nretries = 1;
/* should we check return values? */ /* should we check return values? */
if ( op->ors_deref != -1 ) { if ( op->ors_deref != -1 ) {
@ -78,15 +87,16 @@ meta_back_search_start(
if ( op->ors_tlimit != SLAP_NO_LIMIT ) { if ( op->ors_tlimit != SLAP_NO_LIMIT ) {
tv.tv_sec = op->ors_tlimit > 0 ? op->ors_tlimit : 1; tv.tv_sec = op->ors_tlimit > 0 ? op->ors_tlimit : 1;
tv.tv_usec = 0;
tvp = &tv; tvp = &tv;
} }
dc->target = &mi->mi_targets[ candidate ]; dc->target = mt;
/* /*
* modifies the base according to the scope, if required * modifies the base according to the scope, if required
*/ */
suffixlen = mi->mi_targets[ candidate ].mt_nsuffix.bv_len; suffixlen = mt->mt_nsuffix.bv_len;
if ( suffixlen > op->o_req_ndn.bv_len ) { if ( suffixlen > op->o_req_ndn.bv_len ) {
switch ( op->ors_scope ) { switch ( op->ors_scope ) {
case LDAP_SCOPE_SUBTREE: case LDAP_SCOPE_SUBTREE:
@ -98,11 +108,9 @@ meta_back_search_start(
* the requested searchBase already passed * the requested searchBase already passed
* thru the candidate analyzer... * thru the candidate analyzer...
*/ */
if ( dnIsSuffix( &mi->mi_targets[ candidate ].mt_nsuffix, if ( dnIsSuffix( &mt->mt_nsuffix, &op->o_req_ndn ) ) {
&op->o_req_ndn ) ) realbase = mt->mt_nsuffix;
{ if ( mt->mt_scope == LDAP_SCOPE_SUBORDINATE ) {
realbase = mi->mi_targets[ candidate ].mt_nsuffix;
if ( mi->mi_targets[ candidate ].mt_scope == LDAP_SCOPE_SUBORDINATE ) {
realscope = LDAP_SCOPE_SUBORDINATE; realscope = LDAP_SCOPE_SUBORDINATE;
} }
@ -117,19 +125,19 @@ meta_back_search_start(
case LDAP_SCOPE_SUBORDINATE: case LDAP_SCOPE_SUBORDINATE:
case LDAP_SCOPE_ONELEVEL: case LDAP_SCOPE_ONELEVEL:
{ {
struct berval rdn = mi->mi_targets[ candidate ].mt_nsuffix; struct berval rdn = mt->mt_nsuffix;
rdn.bv_len -= op->o_req_ndn.bv_len + STRLENOF( "," ); rdn.bv_len -= op->o_req_ndn.bv_len + STRLENOF( "," );
if ( dnIsOneLevelRDN( &rdn ) if ( dnIsOneLevelRDN( &rdn )
&& dnIsSuffix( &mi->mi_targets[ candidate ].mt_nsuffix, &op->o_req_ndn ) ) && dnIsSuffix( &mt->mt_nsuffix, &op->o_req_ndn ) )
{ {
/* /*
* if there is exactly one level, * if there is exactly one level,
* make the target suffix the new * make the target suffix the new
* base, and make scope "base" * base, and make scope "base"
*/ */
realbase = mi->mi_targets[ candidate ].mt_nsuffix; realbase = mt->mt_nsuffix;
if ( op->ors_scope == LDAP_SCOPE_SUBORDINATE ) { if ( op->ors_scope == LDAP_SCOPE_SUBORDINATE ) {
if ( mi->mi_targets[ candidate ].mt_scope == LDAP_SCOPE_SUBORDINATE ) { if ( mt->mt_scope == LDAP_SCOPE_SUBORDINATE ) {
realscope = LDAP_SCOPE_SUBORDINATE; realscope = LDAP_SCOPE_SUBORDINATE;
} else { } else {
realscope = LDAP_SCOPE_SUBTREE; realscope = LDAP_SCOPE_SUBTREE;
@ -192,7 +200,7 @@ meta_back_search_start(
/* /*
* Maps required attributes * Maps required attributes
*/ */
rc = ldap_back_map_attrs( &mi->mi_targets[ candidate ].mt_rwmap.rwm_at, rc = ldap_back_map_attrs( &mt->mt_rwmap.rwm_at,
op->ors_attrs, BACKLDAP_MAP, &mapped_attrs ); op->ors_attrs, BACKLDAP_MAP, &mapped_attrs );
if ( rc != LDAP_SUCCESS ) { if ( rc != LDAP_SUCCESS ) {
/* /*
@ -205,16 +213,31 @@ meta_back_search_start(
/* /*
* Starts the search * Starts the search
*/ */
retry:;
rc = ldap_search_ext( msc->msc_ld, rc = ldap_search_ext( msc->msc_ld,
mbase.bv_val, realscope, mfilter.bv_val, mbase.bv_val, realscope, mfilter.bv_val,
mapped_attrs, op->ors_attrsonly, mapped_attrs, op->ors_attrsonly,
op->o_ctrls, NULL, tvp, op->ors_slimit, op->o_ctrls, NULL, tvp, op->ors_slimit,
&candidates[ candidate ].sr_msgid ); &candidates[ candidate ].sr_msgid );
if ( rc == LDAP_SUCCESS ) { switch ( rc ) {
case LDAP_SUCCESS:
retcode = META_SEARCH_CANDIDATE; retcode = META_SEARCH_CANDIDATE;
break;
case LDAP_SERVER_DOWN:
if ( nretries && meta_back_retry( op, rs, mcp, candidate, LDAP_BACK_DONTSEND ) ) {
nretries = 0;
goto retry;
}
} else { if ( *mcp == NULL ) {
candidates[ candidate ].sr_msgid = -1; retcode = META_SEARCH_ERR;
break;
}
/* fall thru */
default:
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
retcode = META_SEARCH_NOT_CANDIDATE; retcode = META_SEARCH_NOT_CANDIDATE;
} }
@ -268,9 +291,7 @@ meta_back_search( Operation *op, SlapReply *rs )
* Inits searches * Inits searches
*/ */
for ( i = 0; i < mi->mi_ntargets; i++ ) { for ( i = 0; i < mi->mi_ntargets; i++ ) {
metasingleconn_t *msc = &mc->mc_conns[ i ]; candidates[ i ].sr_msgid = META_MSGID_IGNORE;
candidates[ i ].sr_msgid = -1;
candidates[ i ].sr_matched = NULL; candidates[ i ].sr_matched = NULL;
candidates[ i ].sr_text = NULL; candidates[ i ].sr_text = NULL;
candidates[ i ].sr_ref = NULL; candidates[ i ].sr_ref = NULL;
@ -282,7 +303,7 @@ meta_back_search( Operation *op, SlapReply *rs )
continue; continue;
} }
switch ( meta_back_search_start( op, rs, &dc, msc, i, candidates ) ) switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )
{ {
case META_SEARCH_NOT_CANDIDATE: case META_SEARCH_NOT_CANDIDATE:
break; break;
@ -371,7 +392,7 @@ meta_back_search( Operation *op, SlapReply *rs )
for ( i = 0; i < mi->mi_ntargets; i++ ) { for ( i = 0; i < mi->mi_ntargets; i++ ) {
metasingleconn_t *msc = &mc->mc_conns[ i ]; metasingleconn_t *msc = &mc->mc_conns[ i ];
if ( candidates[ i ].sr_msgid == -1 ) { if ( candidates[ i ].sr_msgid == META_MSGID_IGNORE ) {
continue; continue;
} }
@ -417,7 +438,7 @@ really_bad:;
candidates[ i ].sr_type = REP_RESULT; candidates[ i ].sr_type = REP_RESULT;
if ( meta_back_retry( op, rs, &mc, i, LDAP_BACK_DONTSEND ) ) { if ( meta_back_retry( op, rs, &mc, i, LDAP_BACK_DONTSEND ) ) {
switch ( meta_back_search_start( op, rs, &dc, msc, i, candidates ) ) switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )
{ {
case META_SEARCH_CANDIDATE: case META_SEARCH_CANDIDATE:
goto get_result; goto get_result;
@ -431,18 +452,20 @@ really_bad:;
} }
} }
savepriv = op->o_private; if ( META_BACK_ONERR_STOP( mi ) ) {
op->o_private = (void *)i; savepriv = op->o_private;
send_ldap_result( op, rs ); op->o_private = (void *)i;
op->o_private = savepriv; send_ldap_result( op, rs );
goto finish; op->o_private = savepriv;
goto finish;
}
} }
/* /*
* When no candidates are left, * When no candidates are left,
* the outer cycle finishes * the outer cycle finishes
*/ */
candidates[ i ].sr_msgid = -1; candidates[ i ].sr_msgid = META_MSGID_IGNORE;
--ncandidates; --ncandidates;
rs->sr_err = candidates[ i ].sr_err = LDAP_OTHER; rs->sr_err = candidates[ i ].sr_err = LDAP_OTHER;
rs->sr_text = "remote server unavailable"; rs->sr_text = "remote server unavailable";
@ -733,7 +756,7 @@ really_bad:;
* When no candidates are left, * When no candidates are left,
* the outer cycle finishes * the outer cycle finishes
*/ */
candidates[ i ].sr_msgid = -1; candidates[ i ].sr_msgid = META_MSGID_IGNORE;
--ncandidates; --ncandidates;
} else { } else {
@ -747,11 +770,12 @@ really_bad:;
for ( i = 0; i < mi->mi_ntargets; i++ ) { for ( i = 0; i < mi->mi_ntargets; i++ ) {
metasingleconn_t *msc = &mc->mc_conns[ i ]; metasingleconn_t *msc = &mc->mc_conns[ i ];
if ( candidates[ i ].sr_msgid != -1 ) { if ( candidates[ i ].sr_msgid != META_MSGID_IGNORE )
{
ldap_abandon_ext( msc->msc_ld, ldap_abandon_ext( msc->msc_ld,
candidates[ i ].sr_msgid, candidates[ i ].sr_msgid,
NULL, NULL ); NULL, NULL );
candidates[ i ].sr_msgid = -1; candidates[ i ].sr_msgid = META_MSGID_IGNORE;
} }
} }
@ -764,7 +788,10 @@ really_bad:;
/* if no entry was found during this loop, /* if no entry was found during this loop,
* set a minimal timeout */ * set a minimal timeout */
if ( gotit == 0 ) { if ( gotit == 0 ) {
LDAP_BACK_TV_SET( &tv ); /* make the entire wait last
* LDAP_BACK_RESULT_UTIMEOUT at worst */
tv.tv_sec = 0;
tv.tv_usec = LDAP_BACK_RESULT_UTIMEOUT/initial_candidates;
ldap_pvt_thread_yield(); ldap_pvt_thread_yield();
} }
} }