mirror of
https://git.openldap.org/openldap/openldap.git
synced 2024-12-21 03:10:25 +08:00
gracefully handle server down while initiating a search (ITS#4518)
This commit is contained in:
parent
4934a7ab00
commit
9447b9fff4
@ -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();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user