From 9447b9fff4cf01b57b7302a7a7afad779241b769 Mon Sep 17 00:00:00 2001 From: Pierangelo Masarati Date: Thu, 4 May 2006 08:37:31 +0000 Subject: [PATCH] gracefully handle server down while initiating a search (ITS#4518) --- servers/slapd/back-meta/search.c | 113 +++++++++++++++++++------------ 1 file changed, 70 insertions(+), 43 deletions(-) diff --git a/servers/slapd/back-meta/search.c b/servers/slapd/back-meta/search.c index 34ac69dc73..ef2a129912 100644 --- a/servers/slapd/back-meta/search.c +++ b/servers/slapd/back-meta/search.c @@ -35,6 +35,12 @@ #include "ldap_log.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 meta_send_entry( Operation *op, @@ -54,21 +60,24 @@ meta_back_search_start( Operation *op, SlapReply *rs, dncookie *dc, - metasingleconn_t *msc, + metaconn_t **mcp, int candidate, - SlapReply *candidates -) + SlapReply *candidates ) { - metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private; - struct berval realbase = op->o_req_dn; - int realscope = op->ors_scope; - ber_len_t suffixlen = 0; - struct berval mbase = BER_BVNULL; - struct berval mfilter = BER_BVNULL; - char **mapped_attrs = NULL; - int rc; + metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private; + metatarget_t *mt = &mi->mi_targets[ candidate ]; + metaconn_t *mc = *mcp; + metasingleconn_t *msc = &mc->mc_conns[ candidate ]; + struct berval realbase = op->o_req_dn; + int realscope = op->ors_scope; + ber_len_t suffixlen = 0; + struct berval mbase = BER_BVNULL; + struct berval mfilter = BER_BVNULL; + char **mapped_attrs = NULL; + int rc; meta_search_candidate_t retcode; - struct timeval tv, *tvp = NULL; + struct timeval tv, *tvp = NULL; + int nretries = 1; /* should we check return values? */ if ( op->ors_deref != -1 ) { @@ -78,15 +87,16 @@ meta_back_search_start( if ( op->ors_tlimit != SLAP_NO_LIMIT ) { tv.tv_sec = op->ors_tlimit > 0 ? op->ors_tlimit : 1; + tv.tv_usec = 0; tvp = &tv; } - dc->target = &mi->mi_targets[ candidate ]; + dc->target = mt; /* * 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 ) { switch ( op->ors_scope ) { case LDAP_SCOPE_SUBTREE: @@ -98,11 +108,9 @@ meta_back_search_start( * the requested searchBase already passed * thru the candidate analyzer... */ - if ( dnIsSuffix( &mi->mi_targets[ candidate ].mt_nsuffix, - &op->o_req_ndn ) ) - { - realbase = mi->mi_targets[ candidate ].mt_nsuffix; - if ( mi->mi_targets[ candidate ].mt_scope == LDAP_SCOPE_SUBORDINATE ) { + if ( dnIsSuffix( &mt->mt_nsuffix, &op->o_req_ndn ) ) { + realbase = mt->mt_nsuffix; + if ( mt->mt_scope == LDAP_SCOPE_SUBORDINATE ) { realscope = LDAP_SCOPE_SUBORDINATE; } @@ -117,19 +125,19 @@ meta_back_search_start( case LDAP_SCOPE_SUBORDINATE: 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( "," ); 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, * make the target suffix the new * base, and make scope "base" */ - realbase = mi->mi_targets[ candidate ].mt_nsuffix; + realbase = mt->mt_nsuffix; 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; } else { realscope = LDAP_SCOPE_SUBTREE; @@ -192,7 +200,7 @@ meta_back_search_start( /* * 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 ); if ( rc != LDAP_SUCCESS ) { /* @@ -205,16 +213,31 @@ meta_back_search_start( /* * Starts the search */ +retry:; rc = ldap_search_ext( msc->msc_ld, mbase.bv_val, realscope, mfilter.bv_val, mapped_attrs, op->ors_attrsonly, op->o_ctrls, NULL, tvp, op->ors_slimit, &candidates[ candidate ].sr_msgid ); - if ( rc == LDAP_SUCCESS ) { + switch ( rc ) { + case LDAP_SUCCESS: 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 { - candidates[ candidate ].sr_msgid = -1; + if ( *mcp == NULL ) { + retcode = META_SEARCH_ERR; + break; + } + /* fall thru */ + + default: + candidates[ candidate ].sr_msgid = META_MSGID_IGNORE; retcode = META_SEARCH_NOT_CANDIDATE; } @@ -268,9 +291,7 @@ meta_back_search( Operation *op, SlapReply *rs ) * Inits searches */ for ( i = 0; i < mi->mi_ntargets; i++ ) { - metasingleconn_t *msc = &mc->mc_conns[ i ]; - - candidates[ i ].sr_msgid = -1; + candidates[ i ].sr_msgid = META_MSGID_IGNORE; candidates[ i ].sr_matched = NULL; candidates[ i ].sr_text = NULL; candidates[ i ].sr_ref = NULL; @@ -282,7 +303,7 @@ meta_back_search( Operation *op, SlapReply *rs ) 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: break; @@ -371,7 +392,7 @@ meta_back_search( Operation *op, SlapReply *rs ) for ( i = 0; i < mi->mi_ntargets; i++ ) { metasingleconn_t *msc = &mc->mc_conns[ i ]; - if ( candidates[ i ].sr_msgid == -1 ) { + if ( candidates[ i ].sr_msgid == META_MSGID_IGNORE ) { continue; } @@ -417,7 +438,7 @@ really_bad:; candidates[ i ].sr_type = REP_RESULT; 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: goto get_result; @@ -431,18 +452,20 @@ really_bad:; } } - savepriv = op->o_private; - op->o_private = (void *)i; - send_ldap_result( op, rs ); - op->o_private = savepriv; - goto finish; + if ( META_BACK_ONERR_STOP( mi ) ) { + savepriv = op->o_private; + op->o_private = (void *)i; + send_ldap_result( op, rs ); + op->o_private = savepriv; + goto finish; + } } /* * When no candidates are left, * the outer cycle finishes */ - candidates[ i ].sr_msgid = -1; + candidates[ i ].sr_msgid = META_MSGID_IGNORE; --ncandidates; rs->sr_err = candidates[ i ].sr_err = LDAP_OTHER; rs->sr_text = "remote server unavailable"; @@ -733,7 +756,7 @@ really_bad:; * When no candidates are left, * the outer cycle finishes */ - candidates[ i ].sr_msgid = -1; + candidates[ i ].sr_msgid = META_MSGID_IGNORE; --ncandidates; } else { @@ -747,11 +770,12 @@ really_bad:; for ( i = 0; i < mi->mi_ntargets; 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, candidates[ i ].sr_msgid, 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, * set a minimal timeout */ 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(); } }