mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-06 10:46:21 +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 "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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user