rework quarantine locking and so

This commit is contained in:
Pierangelo Masarati 2006-06-07 23:25:38 +00:00
parent 53175f7ba6
commit 740f196548
17 changed files with 116 additions and 92 deletions

View file

@ -251,14 +251,14 @@ typedef struct ldapinfo_t {
ldap_avl_info_t li_conninfo;
slap_retry_info_t li_quarantine;
/* NOTE: quarantine uses the connection mutex */
sig_atomic_t li_isquarantined;
#define LDAP_BACK_FQ_NO (0)
#define LDAP_BACK_FQ_YES (1)
#define LDAP_BACK_FQ_RETRYING (2)
slap_retry_info_t li_quarantine;
#define LDAP_BACK_QUARANTINE(li) ( (li)->li_quarantine.ri_num != NULL )
ldap_pvt_thread_mutex_t li_quarantine_mutex;
ldap_back_quarantine_f li_quarantine_f;
void *li_quarantine_p;

View file

@ -608,7 +608,7 @@ ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok )
slap_retry_info_t *ri = &li->li_quarantine;
int dont_retry = 1;
ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
ldap_pvt_thread_mutex_lock( &li->li_quarantine_mutex );
if ( li->li_isquarantined == LDAP_BACK_FQ_YES ) {
dont_retry = ( ri->ri_num[ ri->ri_idx ] == SLAP_RETRYNUM_TAIL
|| slap_get_time() < ri->ri_last + ri->ri_interval[ ri->ri_idx ] );
@ -620,7 +620,7 @@ ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok )
li->li_isquarantined = LDAP_BACK_FQ_RETRYING;
}
}
ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
ldap_pvt_thread_mutex_unlock( &li->li_quarantine_mutex );
if ( dont_retry ) {
rs->sr_err = LDAP_UNAVAILABLE;
@ -837,16 +837,13 @@ ldap_back_release_conn_lock(
void
ldap_back_quarantine(
Operation *op,
SlapReply *rs,
int dolock )
SlapReply *rs )
{
ldapinfo_t *li = (ldapinfo_t *)op->o_bd->be_private;
slap_retry_info_t *ri = &li->li_quarantine;
if ( dolock ) {
ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
}
ldap_pvt_thread_mutex_lock( &li->li_quarantine_mutex );
if ( rs->sr_err == LDAP_UNAVAILABLE ) {
switch ( li->li_isquarantined ) {
@ -894,9 +891,7 @@ ldap_back_quarantine(
li->li_isquarantined = LDAP_BACK_FQ_NO;
}
if ( dolock ) {
ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
}
ldap_pvt_thread_mutex_unlock( &li->li_quarantine_mutex );
}
/*
@ -1061,7 +1056,7 @@ retry_lock:;
}
if ( LDAP_BACK_QUARANTINE( li ) ) {
ldap_back_quarantine( op, rs, dolock );
ldap_back_quarantine( op, rs );
}
goto done;
@ -1120,7 +1115,7 @@ retry:;
rs->sr_err = slap_map_api2result( rs );
if ( LDAP_BACK_QUARANTINE( li ) ) {
ldap_back_quarantine( op, rs, dolock );
ldap_back_quarantine( op, rs );
}
return 0;
@ -1357,7 +1352,7 @@ retry:;
}
}
if ( LDAP_BACK_QUARANTINE( li ) ) {
ldap_back_quarantine( op, rs, 1 );
ldap_back_quarantine( op, rs );
}
if ( op->o_conn &&
( ( sendok & LDAP_BACK_SENDOK )
@ -1778,7 +1773,10 @@ ldap_back_proxy_authz_ctrl(
goto done;
}
if ( !BER_BVISNULL( &op->o_conn->c_ndn ) ) {
if ( op->o_tag == LDAP_REQ_BIND ) {
ndn = op->o_req_ndn;
} else if ( !BER_BVISNULL( &op->o_conn->c_ndn ) ) {
ndn = op->o_conn->c_ndn;
} else {

View file

@ -955,6 +955,7 @@ ldap_back_cf_gen( ConfigArgs *c )
}
slap_retry_info_destroy( &li->li_quarantine );
ldap_pvt_thread_mutex_destroy( &li->li_quarantine_mutex );
li->li_isquarantined = 0;
break;
@ -1654,10 +1655,13 @@ done_url:;
c->msg, sizeof( c->msg ) );
if ( rc ) {
Debug( LDAP_DEBUG_ANY, "%s: %s.\n", c->log, c->msg, 0 );
} else {
ldap_pvt_thread_mutex_init( &li->li_quarantine_mutex );
/* give it a chance to retry if the pattern gets reset
* via back-config */
li->li_isquarantined = 0;
}
/* give it a chance to retry if the pattern gets reset
* via back-config */
li->li_isquarantined = 0;
break;
case LDAP_BACK_CFG_REWRITE:

View file

@ -185,7 +185,7 @@ retry:
}
if ( LDAP_BACK_QUARANTINE( li ) ) {
ldap_back_quarantine( op, rs, 1 );
ldap_back_quarantine( op, rs );
}
if ( text ) rs->sr_text = text;
@ -194,7 +194,7 @@ retry:
rc = rs->sr_err = SLAPD_ABANDON;
} else if ( LDAP_BACK_QUARANTINE( li ) ) {
ldap_back_quarantine( op, rs, 1 );
ldap_back_quarantine( op, rs );
}
/* these have to be freed anyway... */
@ -281,7 +281,7 @@ retry:
}
if ( LDAP_BACK_QUARANTINE( li ) ) {
ldap_back_quarantine( op, rs, 1 );
ldap_back_quarantine( op, rs );
}
if ( text ) rs->sr_text = text;
@ -290,7 +290,7 @@ retry:
rc = rs->sr_err = SLAPD_ABANDON;
} else if ( LDAP_BACK_QUARANTINE( li ) ) {
ldap_back_quarantine( op, rs, 1 );
ldap_back_quarantine( op, rs );
}
/* these have to be freed anyway... */

View file

@ -319,6 +319,7 @@ ldap_back_db_destroy(
}
if ( LDAP_BACK_QUARANTINE( li ) ) {
slap_retry_info_destroy( &li->li_quarantine );
ldap_pvt_thread_mutex_destroy( &li->li_quarantine_mutex );
}
ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );

View file

@ -80,8 +80,7 @@ ldap_back_proxy_authz_ctrl_free(
extern void
ldap_back_quarantine(
Operation *op,
SlapReply *rs,
int dolock );
SlapReply *rs );
extern void slap_retry_info_destroy( slap_retry_info_t *ri );
extern int slap_retry_info_parse( char *in, slap_retry_info_t *ri,

View file

@ -467,7 +467,7 @@ retry:
finish:;
if ( LDAP_BACK_QUARANTINE( li ) ) {
ldap_back_quarantine( op, rs, 1 );
ldap_back_quarantine( op, rs );
}
if ( rc != SLAPD_ABANDON ) {

View file

@ -221,8 +221,8 @@ retry:;
} else {
send_ldap_result( op, rs );
if ( META_BACK_QUARANTINE( mi ) ) {
meta_back_quarantine( op, rs, candidate, 1 );
if ( META_BACK_TGT_QUARANTINE( mi->mi_targets[ candidate ] ) ) {
meta_back_quarantine( op, rs, candidate );
}
}

View file

@ -242,6 +242,8 @@ typedef struct metatarget_t {
sig_atomic_t mt_isquarantined;
slap_retry_info_t mt_quarantine;
ldap_pvt_thread_mutex_t mt_quarantine_mutex;
#define META_BACK_TGT_QUARANTINE(mt) ( (mt)->mt_quarantine.ri_num != NULL )
unsigned mt_flags;
#define META_BACK_TGT_ISSET(mt,f) ( ( (mt)->mt_flags & (f) ) == (f) )
@ -371,8 +373,7 @@ extern void
meta_back_quarantine(
Operation *op,
SlapReply *rs,
int candidate,
int dolock );
int candidate );
extern int
meta_back_single_bind(

View file

@ -78,17 +78,19 @@ meta_back_bind( Operation *op, SlapReply *rs )
* invalidCredentials */
mc = meta_back_getconn( op, rs, NULL, LDAP_BACK_BIND_DONTSEND );
if ( !mc ) {
char buf[ SLAP_TEXT_BUFLEN ];
if ( LogTest( LDAP_DEBUG_ANY ) ) {
char buf[ SLAP_TEXT_BUFLEN ];
snprintf( buf, sizeof( buf ),
"meta_back_bind: no target "
"for dn \"%s\" (%d%s%s).",
op->o_req_dn.bv_val, rs->sr_err,
rs->sr_text ? ". " : "",
rs->sr_text ? rs->sr_text : "" );
Debug( LDAP_DEBUG_ANY,
"%s %s\n",
op->o_log_prefix, buf, 0 );
snprintf( buf, sizeof( buf ),
"meta_back_bind: no target "
"for dn \"%s\" (%d%s%s).",
op->o_req_dn.bv_val, rs->sr_err,
rs->sr_text ? ". " : "",
rs->sr_text ? rs->sr_text : "" );
Debug( LDAP_DEBUG_ANY,
"%s %s\n",
op->o_log_prefix, buf, 0 );
}
/* FIXME: there might be cases where we don't want
* to map the error onto invalidCredentials */
@ -453,8 +455,8 @@ return_results:;
free( mdn.bv_val );
}
if ( META_BACK_QUARANTINE( mi ) ) {
meta_back_quarantine( op, rs, candidate, 1 );
if ( META_BACK_TGT_QUARANTINE( mt ) ) {
meta_back_quarantine( op, rs, candidate );
}
return rs->sr_err;
@ -659,8 +661,8 @@ done:;
}
}
if ( META_BACK_QUARANTINE( mi ) ) {
meta_back_quarantine( op, rs, candidate, dolock );
if ( META_BACK_TGT_QUARANTINE( mt ) ) {
meta_back_quarantine( op, rs, candidate );
}
return rc;
@ -982,15 +984,14 @@ meta_back_op_result(
rerr = rs->sr_err = slap_map_api2result( rs );
Debug(LDAP_DEBUG_ANY,
"==> meta_back_op_result: target"
" <%d> sending msg \"%s\""
" (matched \"%s\")\n",
"==> meta_back_op_result[%d] "
"text=\"%s\" matched=\"%s\"\n",
candidate, ( rmsg ? rmsg : "" ),
( rmatch ? rmatch : "" ) );
}
if ( META_BACK_QUARANTINE( mi ) ) {
meta_back_quarantine( op, rs, candidate, 1 );
if ( META_BACK_TGT_QUARANTINE( mi->mi_targets[ candidate ] ) ) {
meta_back_quarantine( op, rs, candidate );
}
} else {
@ -1026,9 +1027,8 @@ meta_back_op_result(
rs->sr_err = slap_map_api2result( rs );
Debug(LDAP_DEBUG_ANY,
"==> meta_back_op_result: target"
" <%d> sending msg \"%s\""
" (matched \"%s\")\n",
"==> meta_back_op_result[%d] "
"text=\"%s\" matched=\"%s\"\n",
i, ( msg ? msg : "" ),
( match ? match : "" ) );
@ -1064,8 +1064,8 @@ meta_back_op_result(
}
}
if ( META_BACK_QUARANTINE( mi ) ) {
meta_back_quarantine( op, rs, i, 1 );
if ( META_BACK_TGT_QUARANTINE( mi->mi_targets[ i ] ) ) {
meta_back_quarantine( op, rs, i );
}
}
}

View file

@ -172,6 +172,9 @@ meta_back_db_config(
mt->mt_nretries = mi->mi_nretries;
mt->mt_quarantine = mi->mi_quarantine;
if ( META_BACK_QUARANTINE( mi ) ) {
ldap_pvt_thread_mutex_init( &mt->mt_quarantine_mutex );
}
mt->mt_flags = mi->mi_flags;
mt->mt_version = mi->mi_version;
mt->mt_network_timeout = mi->mi_network_timeout;
@ -990,7 +993,9 @@ meta_back_db_config(
&mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_quarantine
: &mi->mi_quarantine;
if ( META_BACK_QUARANTINE( mi ) ) {
if ( ( mi->mi_ntargets == 0 && META_BACK_QUARANTINE( mi ) )
|| ( mi->mi_ntargets > 0 && META_BACK_TGT_QUARANTINE( mi->mi_targets[ mi->mi_ntargets - 1 ] ) ) )
{
Debug( LDAP_DEBUG_ANY,
"%s: line %d: quarantine already defined.\n",
fname, lineno, 0 );
@ -1019,6 +1024,10 @@ meta_back_db_config(
ri->ri_num = NULL;
}
if ( mi->mi_ntargets > 0 && !META_BACK_QUARANTINE( mi ) ) {
ldap_pvt_thread_mutex_init( &mi->mi_targets[ mi->mi_ntargets - 1 ]->mt_quarantine_mutex );
}
if ( slap_retry_info_parse( argv[ 1 ], ri, buf, sizeof( buf ) ) ) {
Debug( LDAP_DEBUG_ANY,
"%s line %d: %s.\n",

View file

@ -489,7 +489,7 @@ retry:;
goto error_return;
}
/* copy the DN if needed */
/* copy the DN idf needed */
if ( msc->msc_bound_ndn.bv_val == op->o_conn->c_dn.bv_val ) {
ber_dupbv( &msc->msc_bound_ndn, &op->o_conn->c_dn );
}
@ -615,8 +615,8 @@ meta_back_retry(
}
}
if ( META_BACK_QUARANTINE( mi ) ) {
meta_back_quarantine( op, rs, candidate, 0 );
if ( META_BACK_TGT_QUARANTINE( mt ) ) {
meta_back_quarantine( op, rs, candidate );
}
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
@ -876,8 +876,7 @@ meta_back_getconn(
/* Explicit Bind requests always get their own conn */
if ( !( sendok & LDAP_BACK_BINDING ) ) {
/* Searches for a metaconn in the avl tree */
retry_lock:
new_conn = 0;
retry_lock:;
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
mc = (metaconn_t *)avl_find( mi->mi_conninfo.lai_tree,
(caddr_t)&mc_curr, meta_back_conndn_cmp );
@ -1209,8 +1208,14 @@ retry_lock2:;
candidates[ i ].sr_err = lerr;
err = lerr;
Debug( LDAP_DEBUG_ANY, "%s: meta_back_getconn[%d] failed: %d\n",
op->o_log_prefix, i, lerr );
if ( lerr == LDAP_UNAVAILABLE && mt->mt_isquarantined != LDAP_BACK_FQ_NO ) {
Debug( LDAP_DEBUG_TRACE, "%s: meta_back_getconn[%d] quarantined: %d\n",
op->o_log_prefix, i, lerr );
} else {
Debug( LDAP_DEBUG_ANY, "%s: meta_back_getconn[%d] failed: %d\n",
op->o_log_prefix, i, lerr );
}
if ( META_BACK_ONERR_STOP( mi ) ) {
if ( sendok & LDAP_BACK_SENDERR ) {
@ -1299,8 +1304,9 @@ done:;
break;
case -1:
/* duplicate: free and try to get the newly created one */
if ( !( sendok & LDAP_BACK_BINDING ) ) {
/* duplicate: free and try to get the newly created one */
new_conn = 0;
goto retry_lock;
}
LDAP_BACK_CONN_TAINTED_SET( mc );
@ -1373,33 +1379,36 @@ void
meta_back_quarantine(
Operation *op,
SlapReply *rs,
int candidate,
int dolock )
int candidate )
{
metainfo_t *mi = (metainfo_t *)op->o_bd->be_private;
metatarget_t *mt = mi->mi_targets[ candidate ];
slap_retry_info_t *ri = &mt->mt_quarantine;
if ( dolock ) {
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
}
ldap_pvt_thread_mutex_lock( &mt->mt_quarantine_mutex );
if ( rs->sr_err == LDAP_UNAVAILABLE ) {
switch ( mt->mt_isquarantined ) {
case LDAP_BACK_FQ_NO:
Debug( LDAP_DEBUG_ANY,
"%s: meta_back_quarantine enter.\n",
op->o_log_prefix, 0, 0 );
"%s: meta_back_quarantine[%d] enter.\n",
op->o_log_prefix, candidate, 0 );
ri->ri_idx = 0;
ri->ri_count = 0;
break;
case LDAP_BACK_FQ_RETRYING:
Debug( LDAP_DEBUG_ANY,
"%s: meta_back_quarantine block #%d try #%d failed.\n",
op->o_log_prefix, ri->ri_idx, ri->ri_count );
if ( LogTest( LDAP_DEBUG_ANY ) ) {
char buf[ SLAP_TEXT_BUFLEN ];
snprintf( buf, sizeof( buf ),
"meta_back_quarantine[%d] block #%d try #%d failed",
candidate, ri->ri_idx, ri->ri_count );
Debug( LDAP_DEBUG_ANY, "%s: %s.\n",
op->o_log_prefix, buf, 0 );
}
++ri->ri_count;
if ( ri->ri_num[ ri->ri_idx ] != SLAP_RETRYNUM_FOREVER
@ -1417,10 +1426,10 @@ meta_back_quarantine(
mt->mt_isquarantined = LDAP_BACK_FQ_YES;
ri->ri_last = slap_get_time();
} else if ( mt->mt_isquarantined != LDAP_BACK_FQ_NO ) {
} else if ( mt->mt_isquarantined == LDAP_BACK_FQ_RETRYING ) {
Debug( LDAP_DEBUG_ANY,
"%s: meta_back_quarantine exit.\n",
op->o_log_prefix, ri->ri_idx, ri->ri_count );
"%s: meta_back_quarantine[%d] exit.\n",
op->o_log_prefix, candidate, 0 );
if ( mi->mi_quarantine_f ) {
(void)mi->mi_quarantine_f( mi, candidate,
@ -1432,8 +1441,6 @@ meta_back_quarantine(
mt->mt_isquarantined = LDAP_BACK_FQ_NO;
}
if ( dolock ) {
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
}
ldap_pvt_thread_mutex_unlock( &mt->mt_quarantine_mutex );
}

View file

@ -120,8 +120,8 @@ retry:;
} else {
send_ldap_result( op, rs );
if ( META_BACK_QUARANTINE( mi ) ) {
meta_back_quarantine( op, rs, candidate, 1 );
if ( META_BACK_TGT_QUARANTINE( mi->mi_targets[ candidate ] ) ) {
meta_back_quarantine( op, rs, candidate );
}
}

View file

@ -267,13 +267,18 @@ meta_back_db_destroy(
*/
if ( mi->mi_targets != NULL ) {
for ( i = 0; i < mi->mi_ntargets; i++ ) {
if ( META_BACK_QUARANTINE( mi )
&& mi->mi_targets[ i ]->mt_quarantine.ri_num != mi->mi_quarantine.ri_num )
{
slap_retry_info_destroy( &mi->mi_targets[ i ]->mt_quarantine );
metatarget_t *mt = mi->mi_targets[ i ];
if ( META_BACK_TGT_QUARANTINE( mt ) ) {
if ( mt->mt_quarantine.ri_num != mi->mi_quarantine.ri_num )
{
slap_retry_info_destroy( &mt->mt_quarantine );
}
ldap_pvt_thread_mutex_destroy( &mt->mt_quarantine_mutex );
}
target_free( mi->mi_targets[ i ] );
target_free( mt );
}
free( mi->mi_targets );

View file

@ -232,8 +232,8 @@ cleanup:;
} else {
send_ldap_result( op, rs );
if ( META_BACK_QUARANTINE( mi ) ) {
meta_back_quarantine( op, rs, candidate, 1 );
if ( META_BACK_TGT_QUARANTINE( mi->mi_targets[ candidate ] ) ) {
meta_back_quarantine( op, rs, candidate );
}
}

View file

@ -176,8 +176,8 @@ cleanup:;
} else {
send_ldap_result( op, rs );
if ( META_BACK_QUARANTINE( mi ) ) {
meta_back_quarantine( op, rs, candidate, 1 );
if ( META_BACK_TGT_QUARANTINE( mi->mi_targets[ candidate ] ) ) {
meta_back_quarantine( op, rs, candidate );
}
}

View file

@ -1271,8 +1271,8 @@ finish:;
candidates[ i ].sr_ctrls = NULL;
}
if ( META_BACK_QUARANTINE( mi ) ) {
meta_back_quarantine( op, &candidates[ i ], i, 1 );
if ( META_BACK_TGT_QUARANTINE( mi->mi_targets[ i ] ) ) {
meta_back_quarantine( op, &candidates[ i ], i );
}
}