- add support for "use-temporary-conn" much like back-ldap

- fix various connection creation/setup concurrency issues
- use shared connection when always idasserting (similar to ITS#4781)
- reduce the impact of schema mapping when not used (tnx to gprof)
- fix temporary/tainted connection leak in abnormal conditions
This commit is contained in:
Pierangelo Masarati 2006-12-17 23:52:23 +00:00
parent 28793246e6
commit 4e11af075f
9 changed files with 337 additions and 120 deletions

View file

@ -176,6 +176,13 @@ is set to
.B single\-conn {NO|yes}
Discards current cached connection when the client rebinds.
.TP
.B use-temporary-conn {NO|yes}
when set to
.BR yes ,
create a temporary connection whenever competing with other threads
for a shared one; otherwise, wait until the shared connection is available.
.SH TARGET SPECIFICATION
Target specification starts with a "uri" directive:

View file

@ -160,6 +160,35 @@ ldap_dnattr_result_rewrite(
/* (end of) from back-ldap.h before rwm removal */
/*
* A metasingleconn_t can be in the following, mutually exclusive states:
*
* - none (0x0U)
* - creating META_BACK_FCONN_CREATING
* - initialized META_BACK_FCONN_INITED
* - binding LDAP_BACK_FCONN_BINDING
* - bound/anonymous LDAP_BACK_FCONN_ISBOUND/LDAP_BACK_FCONN_ISANON
*
* possible modifiers are:
*
* - privileged LDAP_BACK_FCONN_ISPRIV
* - privileged, TLS LDAP_BACK_FCONN_ISTLS
* - subjected to idassert LDAP_BACK_FCONN_ISIDASR
* - tainted LDAP_BACK_FCONN_TAINTED
*/
#define META_BACK_FCONN_INITED (0x00100000U)
#define META_BACK_FCONN_CREATING (0x00200000U)
#define META_BACK_CONN_INITED(lc) LDAP_BACK_CONN_ISSET((lc), META_BACK_FCONN_INITED)
#define META_BACK_CONN_INITED_SET(lc) LDAP_BACK_CONN_SET((lc), META_BACK_FCONN_INITED)
#define META_BACK_CONN_INITED_CLEAR(lc) LDAP_BACK_CONN_CLEAR((lc), META_BACK_FCONN_INITED)
#define META_BACK_CONN_INITED_CPY(lc, mlc) LDAP_BACK_CONN_CPY((lc), META_BACK_FCONN_INITED, (mlc))
#define META_BACK_CONN_CREATING(lc) LDAP_BACK_CONN_ISSET((lc), META_BACK_FCONN_CREATING)
#define META_BACK_CONN_CREATING_SET(lc) LDAP_BACK_CONN_SET((lc), META_BACK_FCONN_CREATING)
#define META_BACK_CONN_CREATING_CLEAR(lc) LDAP_BACK_CONN_CLEAR((lc), META_BACK_FCONN_CREATING)
#define META_BACK_CONN_CREATING_CPY(lc, mlc) LDAP_BACK_CONN_CPY((lc), META_BACK_FCONN_CREATING, (mlc))
struct metainfo_t;
#define META_NOT_CANDIDATE ((ber_tag_t)0x0)
@ -329,16 +358,18 @@ typedef struct metainfo_t {
unsigned mi_flags;
#define li_flags mi_flags
/* uses flags as defined in <back-ldap/back-ldap.h> */
#define META_BACK_F_ONERR_STOP (0x00010000U)
#define META_BACK_F_ONERR_REPORT (0x00020000U)
#define META_BACK_F_ONERR_STOP (0x00100000U)
#define META_BACK_F_ONERR_REPORT (0x00200000U)
#define META_BACK_F_ONERR_MASK (META_BACK_F_ONERR_STOP|META_BACK_F_ONERR_REPORT)
#define META_BACK_F_DEFER_ROOTDN_BIND (0x00040000U)
#define META_BACK_F_DEFER_ROOTDN_BIND (0x00400000U)
#define META_BACK_F_PROXYAUTHZ_ALWAYS (0x00800000U)
#define META_BACK_ONERR_STOP(mi) ( (mi)->mi_flags & META_BACK_F_ONERR_STOP )
#define META_BACK_ONERR_REPORT(mi) ( (mi)->mi_flags & META_BACK_F_ONERR_REPORT )
#define META_BACK_ONERR_CONTINUE(mi) ( !( (mi)->mi_flags & META_BACK_F_ONERR_MASK ) )
#define META_BACK_DEFER_ROOTDN_BIND(mi) ( (mi)->mi_flags & META_BACK_F_DEFER_ROOTDN_BIND )
#define META_BACK_PROXYAUTHZ_ALWAYS(mi) ( (mi)->mi_flags & META_BACK_F_PROXYAUTHZ_ALWAYS )
int mi_version;
time_t mi_network_timeout;
@ -397,7 +428,8 @@ meta_back_init_one_conn(
metaconn_t *mc,
int candidate,
int ispriv,
ldap_back_send_t sendok );
ldap_back_send_t sendok,
int dolock );
extern void
meta_back_quarantine(

View file

@ -399,9 +399,7 @@ retry:;
op->o_log_prefix, candidate, (void *)msc->msc_ld );
#endif /* DEBUG_205 */
ldap_unbind_ext( msc->msc_ld, NULL, NULL );
msc->msc_ld = NULL;
LDAP_BACK_CONN_BINDING_CLEAR( msc );
meta_clear_one_candidate( op, mc, candidate );
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
rs->sr_err = timeout_err;
@ -683,7 +681,8 @@ retry_binding:;
++bound;
continue;
} else if ( LDAP_BACK_CONN_BINDING( msc ) ) {
} else if ( META_BACK_CONN_CREATING( msc ) || LDAP_BACK_CONN_BINDING( msc ) )
{
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
ldap_pvt_thread_yield();
goto retry_binding;
@ -710,7 +709,7 @@ retry_binding:;
if ( rc == LDAP_UNAVAILABLE ) {
/* FIXME: meta_back_retry() already calls
/* FIXME: meta_back_retry() already re-calls
* meta_back_single_dobind() */
if ( meta_back_retry( op, rs, &mc, i, sendok ) ) {
goto retry_ok;
@ -720,6 +719,7 @@ retry_binding:;
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
LDAP_BACK_CONN_BINDING_CLEAR( msc );
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
meta_back_release_conn( op, mc );
}
return 0;

View file

@ -187,7 +187,7 @@ meta_clear_one_candidate(
{
metasingleconn_t *msc = &mc->mc_conns[ candidate ];
if ( msc->msc_ld ) {
if ( msc->msc_ld != NULL ) {
#ifdef DEBUG_205
char buf[ BUFSIZ ];
@ -213,6 +213,8 @@ meta_clear_one_candidate(
BER_BVZERO( &msc->msc_cred );
}
msc->msc_mscflags = 0;
return 0;
}

View file

@ -38,7 +38,6 @@ static int
meta_back_new_target(
metatarget_t **mtp )
{
struct ldapmapping *mapping;
char *rargv[ 3 ];
metatarget_t *mt;
@ -52,7 +51,6 @@ meta_back_new_target(
return -1;
}
/*
* the filter rewrite as a string must be disabled
* by default; it can be re-enabled by adding rules;
@ -68,8 +66,6 @@ meta_back_new_target(
rargv[ 2 ] = NULL;
rewrite_parse( mt->mt_rwmap.rwm_rw, "<suffix massage>", 1, 2, rargv );
ldap_back_map_init( &mt->mt_rwmap.rwm_at, &mapping );
ldap_pvt_thread_mutex_init( &mt->mt_uri_mutex );
mt->mt_idassert_mode = LDAP_BACK_IDASSERT_LEGACY;
@ -849,6 +845,38 @@ meta_back_db_config(
return 1;
}
/* use-temporaries? */
} else if ( strcasecmp( argv[ 0 ], "use-temporary-conn" ) == 0 ) {
if ( argc != 2 ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: \"use-temporary-conn {FALSE|true}\" takes 1 argument\n",
fname, lineno, 0 );
return( 1 );
}
if ( mi->mi_ntargets > 0 ) {
Debug( LDAP_DEBUG_ANY,
"%s: line %d: \"use-temporary-conn\" must appear before target definitions\n",
fname, lineno, 0 );
return( 1 );
}
switch ( check_true_false( argv[ 1 ] ) ) {
case 0:
mi->mi_flags &= ~LDAP_BACK_F_USE_TEMPORARIES;
break;
case 1:
mi->mi_flags |= LDAP_BACK_F_USE_TEMPORARIES;
break;
default:
Debug( LDAP_DEBUG_ANY,
"%s: line %d: \"use-temporary-conn {FALSE|true}\": invalid arg \"%s\".\n",
fname, lineno, argv[ 1 ] );
return 1;
}
} else if ( strcasecmp( argv[ 0 ], "cancel" ) == 0 ) {
unsigned flag = 0;
unsigned *flagsp = mi->mi_ntargets ?
@ -1402,7 +1430,7 @@ ldap_back_map_config(
if ( strcmp( argv[ 2 ], "*" ) == 0 ) {
if ( argc < 4 || strcmp( argv[ 3 ], "*" ) == 0 ) {
map->drop_missing = ( argc < 4 );
return 0;
goto success_return;
}
src = dst = argv[ 3 ];
@ -1416,7 +1444,7 @@ ldap_back_map_config(
}
if ( ( map == at_map )
&& ( strcasecmp( src, "objectclass" ) == 0
&& ( strcasecmp( src, "objectclass" ) == 0
|| strcasecmp( dst, "objectclass" ) == 0 ) )
{
Debug( LDAP_DEBUG_ANY,
@ -1544,6 +1572,12 @@ ldap_back_map_config(
avl_insert( &map->remap, (caddr_t)&mapping[ 1 ],
mapping_cmp, mapping_dup );
success_return:;
if ( !is_oc && map->map == NULL ) {
/* only init if required */
ldap_back_map_init( map, &mapping );
}
return 0;
error_return:;

View file

@ -202,7 +202,7 @@ metaconn_alloc(
/* malloc all in one */
mc = ( metaconn_t * )ch_calloc( 1, sizeof( metaconn_t )
+ sizeof( metasingleconn_t ) * ntargets );
+ sizeof( metasingleconn_t ) * ( ntargets - 1 ) );
if ( mc == NULL ) {
return NULL;
}
@ -227,7 +227,8 @@ meta_back_init_one_conn(
metaconn_t *mc,
int candidate,
int ispriv,
ldap_back_send_t sendok )
ldap_back_send_t sendok,
int dolock )
{
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
metatarget_t *mt = mi->mi_targets[ candidate ];
@ -235,6 +236,7 @@ meta_back_init_one_conn(
int version;
dncookie dc;
int isauthz = ( candidate == mc->mc_authz_target );
int do_return = 0;
#ifdef HAVE_TLS
int is_ldaps = 0;
#endif /* HAVE_TLS */
@ -275,14 +277,62 @@ meta_back_init_one_conn(
}
}
retry_lock:;
if ( dolock ) {
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
}
/*
* Already init'ed
*/
if ( msc->msc_ld != NULL ) {
return rs->sr_err = LDAP_SUCCESS;
if ( LDAP_BACK_CONN_ISBOUND( msc )
|| LDAP_BACK_CONN_ISANON( msc ) )
{
assert( msc->msc_ld != NULL );
rs->sr_err = LDAP_SUCCESS;
do_return = 1;
} else if ( META_BACK_CONN_CREATING( msc )
|| LDAP_BACK_CONN_BINDING( msc ) )
{
if ( !LDAP_BACK_USE_TEMPORARIES( mi ) ) {
if ( dolock ) {
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
}
ldap_pvt_thread_yield();
goto retry_lock;
}
/* sounds more appropriate */
rs->sr_err = LDAP_BUSY;
do_return = 1;
} else if ( META_BACK_CONN_INITED( msc ) ) {
assert( msc->msc_ld != NULL );
rs->sr_err = LDAP_SUCCESS;
do_return = 1;
} else {
/*
* creating...
*/
META_BACK_CONN_CREATING_SET( msc );
}
msc->msc_mscflags = 0;
if ( dolock ) {
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
}
if ( do_return ) {
if ( rs->sr_err != LDAP_SUCCESS && op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) {
send_ldap_result( op, rs );
}
return rs->sr_err;
}
assert( msc->msc_ld == NULL );
/*
* Attempts to initialize the connection to the target ds
@ -430,8 +480,8 @@ retry:;
op->o_log_prefix, candidate, (void *)msc->msc_ld );
#endif /* DEBUG_205 */
ldap_unbind_ext( msc->msc_ld, NULL, NULL );
msc->msc_ld = NULL;
/* need to trash a failed Start TLS */
meta_clear_one_candidate( op, mc, candidate );
goto error_return;
}
}
@ -500,8 +550,8 @@ retry:;
op->o_log_prefix, candidate, (void *)msc->msc_ld );
#endif /* DEBUG_205 */
ldap_unbind_ext( msc->msc_ld, NULL, NULL );
msc->msc_ld = NULL;
/* need to trash a connection not fully established */
meta_clear_one_candidate( op, mc, candidate );
goto error_return;
}
@ -510,6 +560,8 @@ retry:;
ber_dupbv( &msc->msc_bound_ndn, &op->o_conn->c_dn );
}
assert( !BER_BVISNULL( &msc->msc_bound_ndn ) );
} else {
ber_dupbv( &msc->msc_bound_ndn, (struct berval *)&slap_empty_bv );
}
@ -518,13 +570,22 @@ retry:;
assert( !BER_BVISNULL( &msc->msc_bound_ndn ) );
error_return:;
if ( dolock ) {
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
}
META_BACK_CONN_CREATING_CLEAR( msc );
if ( rs->sr_err == LDAP_SUCCESS ) {
/*
* Sets a cookie for the rewrite session
*/
( void )rewrite_session_init( mt->mt_rwmap.rwm_rw, op->o_conn );
META_BACK_CONN_INITED_SET( msc );
}
if ( dolock ) {
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
}
} else {
if ( rs->sr_err != LDAP_SUCCESS ) {
rs->sr_err = slap_map_api2result( rs );
if ( sendok & LDAP_BACK_SENDERR ) {
send_ldap_result( op, rs );
@ -556,13 +617,18 @@ meta_back_retry(
binding;
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
assert( !META_BACK_CONN_CREATING( msc ) );
binding = LDAP_BACK_CONN_BINDING( msc );
LDAP_BACK_CONN_BINDING_CLEAR( msc );
assert( mc->mc_refcnt > 0 );
if ( mc->mc_refcnt == 1 ) {
if ( LogTest( LDAP_DEBUG_ANY ) ) {
char buf[ SLAP_TEXT_BUFLEN ];
/* this lock is required; however,
* it's invoked only when logging is on */
ldap_pvt_thread_mutex_lock( &mt->mt_uri_mutex );
snprintf( buf, sizeof( buf ),
"retrying URI=\"%s\" DN=\"%s\"",
@ -583,7 +649,7 @@ meta_back_retry(
/* mc here must be the regular mc, reset and ready for init */
rc = meta_back_init_one_conn( op, rs, mc, candidate,
LDAP_BACK_CONN_ISPRIV( mc ), sendok );
LDAP_BACK_CONN_ISPRIV( mc ), sendok, 0 );
/* restore the "binding" flag, in case */
if ( binding ) {
@ -614,6 +680,9 @@ meta_back_retry(
}
}
}
/* don't send twice */
sendok &= ~LDAP_BACK_SENDERR;
}
if ( rc != LDAP_SUCCESS ) {
@ -622,9 +691,13 @@ meta_back_retry(
candidates[ candidate ].sr_err = rc;
if ( *mcp != NULL ) {
if ( binding ) {
LDAP_BACK_CONN_BINDING_CLEAR( msc );
if ( mc->mc_refcnt == 1 ) {
if ( binding ) {
LDAP_BACK_CONN_BINDING_CLEAR( msc );
}
(void)meta_clear_one_candidate( op, mc, candidate );
}
LDAP_BACK_CONN_TAINTED_SET( mc );
/* only release if mandatory; otherwise
* let the caller do what's best before
@ -632,10 +705,21 @@ meta_back_retry(
if ( META_BACK_ONERR_STOP( mi ) ) {
meta_back_release_conn_lock( op, mc, 0 );
*mcp = NULL;
} else {
#if META_BACK_PRINT_CONNTREE > 0
meta_back_print_conntree( mi->mi_conninfo.lai_tree, ">>> meta_back_retry" );
#endif /* META_BACK_PRINT_CONNTREE */
/* FIXME: could be done better, reworking meta_back_release_conn_lock() */
(void)avl_delete( &mi->mi_conninfo.lai_tree,
( caddr_t )mc, meta_back_conndnmc_cmp );
#if META_BACK_PRINT_CONNTREE > 0
meta_back_print_conntree( mi->mi_conninfo.lai_tree, "<<< meta_back_retry" );
#endif /* META_BACK_PRINT_CONNTREE */
}
}
if ( sendok ) {
if ( sendok & LDAP_BACK_SENDERR ) {
rs->sr_err = rc;
rs->sr_text = NULL;
send_ldap_result( op, rs );
@ -882,8 +966,8 @@ meta_back_getconn(
SlapReply *candidates = meta_back_candidates_get( op );
/* Internal searches are privileged and shared. So is root. */
/* FIXME: there seem to be concurrency issues */
if ( op->o_do_not_cache || be_isroot( op ) ) {
/* FIXME: there seems to be concurrency issues */
if ( META_BACK_PROXYAUTHZ_ALWAYS( mi ) || op->o_do_not_cache || be_isroot( op ) ) {
mc_curr.mc_local_ndn = op->o_bd->be_rootndn;
LDAP_BACK_CONN_ISPRIV_SET( &mc_curr );
mc_curr.mc_conn = LDAP_BACK_PCONN_SET( op );
@ -908,33 +992,45 @@ retry_lock:;
mc = (metaconn_t *)avl_find( mi->mi_conninfo.lai_tree,
(caddr_t)&mc_curr, meta_back_conndn_cmp );
if ( mc ) {
if ( ( mi->mi_conn_ttl != 0 && op->o_time > mc->mc_create_time + mi->mi_conn_ttl )
|| ( mi->mi_idle_timeout != 0 && op->o_time > mc->mc_time + mi->mi_idle_timeout ) )
{
#if META_BACK_PRINT_CONNTREE > 0
meta_back_print_conntree( mi->mi_conninfo.lai_tree, ">>> meta_back_getconn" );
#endif /* META_BACK_PRINT_CONNTREE */
/* don't let anyone else use this expired connection */
(void)avl_delete( &mi->mi_conninfo.lai_tree,
(caddr_t)mc, meta_back_conndnmc_cmp );
#if META_BACK_PRINT_CONNTREE > 0
meta_back_print_conntree( mi->mi_conninfo.lai_tree, "<<< meta_back_getconn" );
#endif /* META_BACK_PRINT_CONNTREE */
LDAP_BACK_CONN_TAINTED_SET( mc );
Debug( LDAP_DEBUG_TRACE, "%s meta_back_getconn: mc=%p conn=%ld expired.\n",
op->o_log_prefix, (void *)mc, LDAP_BACK_PCONN_ID( mc ) );
}
/* catch taint errors */
assert( !LDAP_BACK_CONN_TAINTED( mc ) );
/* Don't reuse connections while they're still binding
* NOTE: only makes sense for binds */
if ( LDAP_BACK_CONN_BINDING( mc ) ) {
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
ldap_pvt_thread_yield();
goto retry_lock;
}
if ( !LDAP_BACK_USE_TEMPORARIES( mi ) ) {
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
mc->mc_refcnt++;
ldap_pvt_thread_yield();
goto retry_lock;
}
/* release conn, and create a temporary */
mc = NULL;
} else {
if ( ( mi->mi_conn_ttl != 0 && op->o_time > mc->mc_create_time + mi->mi_conn_ttl )
|| ( mi->mi_idle_timeout != 0 && op->o_time > mc->mc_time + mi->mi_idle_timeout ) )
{
#if META_BACK_PRINT_CONNTREE > 0
meta_back_print_conntree( mi->mi_conninfo.lai_tree,
">>> meta_back_getconn(expired)" );
#endif /* META_BACK_PRINT_CONNTREE */
/* don't let anyone else use this expired connection */
(void)avl_delete( &mi->mi_conninfo.lai_tree,
(caddr_t)mc, meta_back_conndnmc_cmp );
#if META_BACK_PRINT_CONNTREE > 0
meta_back_print_conntree( mi->mi_conninfo.lai_tree,
"<<< meta_back_getconn(expired)" );
#endif /* META_BACK_PRINT_CONNTREE */
LDAP_BACK_CONN_TAINTED_SET( mc );
Debug( LDAP_DEBUG_TRACE, "%s meta_back_getconn: mc=%p conn=%ld expired (tainted).\n",
op->o_log_prefix, (void *)mc, LDAP_BACK_PCONN_ID( mc ) );
}
mc->mc_refcnt++;
}
}
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
}
@ -1010,7 +1106,7 @@ retry_lock:;
*/
candidates[ i ].sr_err = meta_back_init_one_conn( op,
rs, mc, i, LDAP_BACK_CONN_ISPRIV( &mc_curr ),
sendok );
LDAP_BACK_DONTSEND, !new_conn );
if ( candidates[ i ].sr_err == LDAP_SUCCESS ) {
META_CANDIDATE_SET( &candidates[ i ] );
ncandidates++;
@ -1131,13 +1227,24 @@ retry_lock2:;
mc = (metaconn_t *)avl_find( mi->mi_conninfo.lai_tree,
(caddr_t)&mc_curr, meta_back_conndn_cmp );
if ( mc != NULL ) {
/* catch taint errors */
assert( !LDAP_BACK_CONN_TAINTED( mc ) );
/* Don't reuse connections while they're still binding */
if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) ) {
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
ldap_pvt_thread_yield();
goto retry_lock2;
if ( META_BACK_CONN_CREATING( &mc->mc_conns[ i ] )
|| LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) )
{
if ( !LDAP_BACK_USE_TEMPORARIES( mi ) ) {
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
ldap_pvt_thread_yield();
goto retry_lock2;
}
mc = NULL;
} else {
mc->mc_refcnt++;
}
mc->mc_refcnt++;
}
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
}
@ -1172,7 +1279,7 @@ retry_lock2:;
* sends the appropriate result.
*/
err = meta_back_init_one_conn( op, rs, mc, i,
LDAP_BACK_CONN_ISPRIV( &mc_curr ), sendok );
LDAP_BACK_CONN_ISPRIV( &mc_curr ), sendok, !new_conn );
if ( err != LDAP_SUCCESS ) {
/*
* FIXME: in case one target cannot
@ -1230,7 +1337,8 @@ retry_lock2:;
* also init'd
*/
int lerr = meta_back_init_one_conn( op, rs, mc, i,
LDAP_BACK_CONN_ISPRIV( &mc_curr ), LDAP_BACK_DONTSEND );
LDAP_BACK_CONN_ISPRIV( &mc_curr ),
LDAP_BACK_DONTSEND, !new_conn );
if ( lerr == LDAP_SUCCESS ) {
META_CANDIDATE_SET( &candidates[ i ] );
candidates[ i ].sr_err = LDAP_SUCCESS;
@ -1262,11 +1370,11 @@ retry_lock2:;
err = lerr;
if ( lerr == LDAP_UNAVAILABLE && mt->mt_isquarantined != LDAP_BACK_FQ_NO ) {
Debug( LDAP_DEBUG_TRACE, "%s: meta_back_getconn[%d] quarantined: %d\n",
Debug( LDAP_DEBUG_TRACE, "%s: meta_back_getconn[%d] quarantined err=%d\n",
op->o_log_prefix, i, lerr );
} else {
Debug( LDAP_DEBUG_ANY, "%s: meta_back_getconn[%d] failed: %d\n",
Debug( LDAP_DEBUG_ANY, "%s: meta_back_getconn[%d] failed err=%d\n",
op->o_log_prefix, i, lerr );
}
@ -1362,10 +1470,14 @@ done:;
case -1:
/* duplicate: free and try to get the newly created one */
if ( !( sendok & LDAP_BACK_BINDING ) ) {
if ( !( sendok & LDAP_BACK_BINDING ) && !LDAP_BACK_USE_TEMPORARIES( mi ) ) {
mc->mc_refcnt = 0;
meta_back_conn_free( mc );
new_conn = 0;
goto retry_lock;
}
LDAP_BACK_CONN_TAINTED_SET( mc );
break;
@ -1398,7 +1510,7 @@ done:;
op->o_log_prefix, ncandidates,
LDAP_BACK_PCONN_ID( mc ) );
}
return mc;
}
@ -1424,27 +1536,34 @@ meta_back_release_conn_lock(
* the connection space (and eat up resources). Maybe this
* should be configurable... */
if ( LDAP_BACK_CONN_TAINTED( mc ) ||
( !LDAP_BACK_CONN_ISPRIV( mc ) &&
LDAP_BACK_PCONN_ISPRIV( mc ) &&
mc->mc_refcnt == 0 ) )
( !LDAP_BACK_CONN_ISPRIV( mc ) && LDAP_BACK_PCONN_ISPRIV( mc ) && mc->mc_refcnt == 0 ) )
{
metaconn_t *tmpmc;
Debug( LDAP_DEBUG_TRACE, "%s meta_back_release_conn: mc=%p conn=%ld tainted.\n",
op->o_log_prefix, (void *)mc, LDAP_BACK_PCONN_ID( mc ) );
#if META_BACK_PRINT_CONNTREE > 0
meta_back_print_conntree( mi->mi_conninfo.lai_tree, ">>> meta_back_release_conn" );
#endif /* META_BACK_PRINT_CONNTREE */
(void)avl_delete( &mi->mi_conninfo.lai_tree,
tmpmc = avl_delete( &mi->mi_conninfo.lai_tree,
( caddr_t )mc, meta_back_conndnmc_cmp );
#if META_BACK_PRINT_CONNTREE > 0
meta_back_print_conntree( mi->mi_conninfo.lai_tree, "<<< meta_back_release_conn" );
#endif /* META_BACK_PRINT_CONNTREE */
if ( tmpmc == NULL ) {
Debug( LDAP_DEBUG_TRACE, "%s: meta_back_release_conn: unable to find mc=%p\n",
op->o_log_prefix, (void *)mc, 0 );
} else {
assert( tmpmc == mc );
}
if ( mc->mc_refcnt == 0 ) {
meta_back_conn_free( mc );
mc = NULL;
}
}
if ( mc != NULL ) {
if ( mc != NULL && LDAP_BACK_CONN_BINDING( mc ) ) {
LDAP_BACK_CONN_BINDING_CLEAR( mc );
}

View file

@ -125,7 +125,9 @@ meta_back_db_open(
{
metainfo_t *mi = (metainfo_t *)be->be_private;
int i, rc;
int i,
not_always = 0,
rc;
for ( i = 0; i < mi->mi_ntargets; i++ ) {
slap_bindconf sb = { 0 };
@ -153,6 +155,18 @@ meta_back_db_open(
mt->mt_flags |= LDAP_BACK_F_CANCEL_EXOP;
}
}
if ( not_always == 0 ) {
if ( !( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE )
|| !( mt->mt_idassert_flags & LDAP_BACK_AUTH_AUTHZ_ALL ) )
{
not_always = 1;
}
}
}
if ( not_always == 0 ) {
mi->mi_flags |= META_BACK_F_PROXYAUTHZ_ALWAYS;
}
return 0;
@ -175,7 +189,6 @@ meta_back_conn_free(
assert( mc->mc_refcnt == 0 );
/* at least one must be present... */
assert( mc->mc_conns != NULL );
ntargets = mc->mc_info->mi_ntargets;
assert( ntargets > 0 );

View file

@ -90,19 +90,19 @@ ldap_back_map_init ( struct ldapmap *lm, struct ldapmapping **m )
assert( m != NULL );
*m = NULL;
mapping = (struct ldapmapping *)ch_calloc( 2,
sizeof( struct ldapmapping ) );
if ( mapping == NULL ) {
return;
}
ber_str2bv( "objectclass", sizeof("objectclass")-1, 1, &mapping->src);
ber_dupbv( &mapping->dst, &mapping->src );
mapping[1].src = mapping->src;
mapping[1].dst = mapping->dst;
ber_str2bv( "objectclass", STRLENOF("objectclass"), 1, &mapping[0].src);
ber_dupbv( &mapping[0].dst, &mapping[0].src );
mapping[1].src = mapping[0].src;
mapping[1].dst = mapping[0].dst;
avl_insert( &lm->map, (caddr_t)mapping,
avl_insert( &lm->map, (caddr_t)&mapping[0],
mapping_cmp, mapping_dup );
avl_insert( &lm->remap, (caddr_t)&mapping[1],
mapping_cmp, mapping_dup );
@ -120,6 +120,7 @@ ldap_back_mapping ( struct ldapmap *map, struct berval *s, struct ldapmapping **
if ( remap == BACKLDAP_REMAP ) {
tree = map->remap;
} else {
tree = map->map;
}
@ -139,6 +140,13 @@ ldap_back_map ( struct ldapmap *map, struct berval *s, struct berval *bv,
{
struct ldapmapping *mapping;
/* map->map may be NULL when mapping is configured,
* but map->remap can't */
if ( map->remap == NULL ) {
*bv = *s;
return;
}
BER_BVZERO( bv );
( void )ldap_back_mapping( map, s, &mapping, remap );
if ( mapping != NULL ) {

View file

@ -108,7 +108,7 @@ meta_search_dobind_init(
bound = 1;
}
snprintf( buf, sizeof( buf ), " mc=%p lc=%p%s DN=\"%s\"",
snprintf( buf, sizeof( buf ), " mc=%p ld=%p%s DN=\"%s\"",
(void *)mc, (void *)msc->msc_ld,
bound ? " bound" : " anonymous",
bound == 0 ? "" : msc->msc_bound_ndn.bv_val );
@ -118,13 +118,13 @@ meta_search_dobind_init(
retcode = META_SEARCH_CANDIDATE;
} else if ( LDAP_BACK_CONN_BINDING( msc ) ) {
} else if ( META_BACK_CONN_CREATING( msc ) || LDAP_BACK_CONN_BINDING( msc ) ) {
/* another thread is binding the target for this conn; wait */
#ifdef DEBUG_205
char buf[ SLAP_TEXT_BUFLEN ] = { '\0' };
snprintf( buf, sizeof( buf ), " mc=%p lc=%p needbind",
snprintf( buf, sizeof( buf ), " mc=%p ld=%p needbind",
(void *)mc, (void *)msc->msc_ld );
Debug( LDAP_DEBUG_ANY, "### %s meta_search_dobind_init[%d]%s\n",
op->o_log_prefix, candidate, buf );
@ -145,6 +145,32 @@ meta_search_dobind_init(
op->o_log_prefix, candidate, buf );
#endif /* DEBUG_205 */
if ( msc->msc_ld == NULL ) {
/* for some reason (e.g. because formerly in "binding"
* state, with eventual connection expiration or invalidation)
* it was not initialized as expected */
Debug( LDAP_DEBUG_ANY, "%s meta_search_dobind_init[%d] mc=%p ld=NULL\n",
op->o_log_prefix, candidate, (void *)mc );
rc = meta_back_init_one_conn( op, rs, *mcp, candidate,
LDAP_BACK_CONN_ISPRIV( *mcp ), LDAP_BACK_DONTSEND, 0 );
switch ( rc ) {
case LDAP_SUCCESS:
assert( msc->msc_ld != NULL );
break;
case LDAP_SERVER_DOWN:
case LDAP_UNAVAILABLE:
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
goto down;
default:
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
goto other;
}
}
LDAP_BACK_CONN_BINDING_SET( msc );
}
@ -154,29 +180,6 @@ meta_search_dobind_init(
return retcode;
}
if ( msc->msc_ld == NULL ) {
/* for some reason (e.g. because formerly in "binding"
* state, with eventual connection expiration or invalidation)
* it was not initialized as expected */
Debug( LDAP_DEBUG_ANY, "%s meta_search_dobind_init[%d] mc=%p ld=NULL\n",
op->o_log_prefix, candidate, (void *)mc );
rc = meta_back_init_one_conn( op, rs, *mcp, candidate,
LDAP_BACK_CONN_ISPRIV( *mcp ), LDAP_BACK_DONTSEND );
switch ( rc ) {
case LDAP_SUCCESS:
assert( msc->msc_ld != NULL );
break;
case LDAP_SERVER_DOWN:
goto down;
default:
goto other;
}
}
/* NOTE: this obsoletes pseudorootdn */
if ( op->o_conn != NULL &&
!op->o_do_not_cache &&
@ -268,7 +271,7 @@ other:;
rc = slap_map_api2result( rs );
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
LDAP_BACK_CONN_BINDING_CLEAR( msc );
meta_clear_one_candidate( op, mc, candidate );
if ( META_BACK_ONERR_STOP( mi ) ) {
LDAP_BACK_CONN_TAINTED_SET( mc );
meta_back_release_conn_lock( op, mc, 0 );
@ -315,14 +318,17 @@ meta_search_dobind_result(
NULL, NULL, NULL, NULL, 0 );
if ( rc != LDAP_SUCCESS ) {
candidates[ candidate ].sr_err = rc;
} else {
rc = slap_map_api2result( &candidates[ candidate ] );
}
rc = slap_map_api2result( &candidates[ candidate ] );
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
LDAP_BACK_CONN_BINDING_CLEAR( msc );
if ( rc != LDAP_SUCCESS ) {
if ( META_BACK_ONERR_STOP( mi ) ) {
LDAP_BACK_CONN_TAINTED_SET( mc );
meta_clear_one_candidate( op, mc, candidate );
meta_back_release_conn_lock( op, mc, 0 );
*mcp = NULL;
retcode = META_SEARCH_ERR;
@ -796,9 +802,8 @@ getconn:;
*/
for ( rc = 0; ncandidates > 0; ) {
int gotit = 0,
doabandon = 0;
needbind = ncandidates;
doabandon = 0,
alreadybound = ncandidates;
/* check time limit */
if ( op->ors_tlimit != SLAP_NO_LIMIT
@ -834,7 +839,7 @@ getconn:;
switch ( retcode ) {
case META_SEARCH_NEED_BIND:
needbind--;
alreadybound--;
/* fallthru */
case META_SEARCH_BINDING:
@ -918,11 +923,12 @@ getconn:;
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
snprintf( buf, sizeof( buf ),
"%s meta_back_search[%ld] mc=%p msgid=%d%s%s\n",
"%s meta_back_search[%ld] mc=%p msgid=%d%s%s%s\n",
op->o_log_prefix, (long)i, (void *)mc,
candidates[ i ].sr_msgid,
META_IS_BINDING( &candidates[ i ] ) ? " binding" : "",
LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) ? " connbinding" : "" );
LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) ? " connbinding" : "",
META_BACK_CONN_CREATING( &mc->mc_conns[ i ] ) ? " conncreating" : "" );
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
Debug( LDAP_DEBUG_ANY, "!!! %s\n", buf, 0, 0 );
@ -1376,9 +1382,7 @@ really_bad:;
Debug( LDAP_DEBUG_ANY, "### %s\n", buf, 0, 0 );
#endif /* DEBUG_205 */
ldap_unbind_ext( mc->mc_conns[ i ].msc_ld, NULL, NULL );
mc->mc_conns[ i ].msc_ld = NULL;
LDAP_BACK_CONN_BINDING_CLEAR( &mc->mc_conns[ i ] );
meta_clear_one_candidate( op, mc, i );
}
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
META_BINDING_CLEAR( &candidates[ i ] );
@ -1439,7 +1443,7 @@ really_bad:;
}
#endif
if ( needbind == 0 ) {
if ( alreadybound == 0 ) {
#if 0
Debug( LDAP_DEBUG_TRACE, "### %s select(%ld.%06ld)\n",
op->o_log_prefix, save_tv.tv_sec, save_tv.tv_usec );
@ -1622,9 +1626,7 @@ finish:;
#endif /* DEBUG_205 */
/* if still binding, destroy */
ldap_unbind_ext( mc->mc_conns[ i ].msc_ld, NULL, NULL );
mc->mc_conns[ i ].msc_ld = NULL;
LDAP_BACK_CONN_BINDING_CLEAR( &mc->mc_conns[ i ] );
meta_clear_one_candidate( op, mc, i );
}
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
META_BINDING_CLEAR( &candidates[ i ] );