rework compare

fix several minor issues with using dangling pointers and uninitialized data
fix caching of privileged connections
fix issues with unresponsive target failures during search
This commit is contained in:
Pierangelo Masarati 2006-11-05 12:05:47 +00:00
parent fd0176e49c
commit efb04832bd
7 changed files with 256 additions and 349 deletions

View File

@ -494,11 +494,6 @@ meta_clear_one_candidate(
metaconn_t *mc,
int candidate );
extern int
meta_clear_candidates(
Operation *op,
metaconn_t *mc );
/*
* Dn cache stuff (experimental)
*/

View File

@ -253,6 +253,7 @@ retry_lock:;
ber_bvreplace( &mc->mc_local_ndn, &op->o_req_ndn );
if ( isroot ) {
LDAP_BACK_CONN_ISPRIV_SET( mc );
mc->mc_conn = LDAP_BACK_PCONN_SET( op );
}
lerr = avl_insert( &mi->mi_conninfo.lai_tree, (caddr_t)mc,
@ -262,9 +263,8 @@ retry_lock:;
#endif /* META_BACK_PRINT_CONNTREE */
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
if ( lerr == -1 ) {
meta_clear_candidates( op, mc );
/* we can do this because mc_refcnt == 1 */
assert( mc->mc_refcnt == 1 );
mc->mc_refcnt = 0;
meta_back_conn_free( mc );
mc = NULL;
@ -396,10 +396,10 @@ retry:;
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
assert( LDAP_BACK_CONN_BINDING( msc ) );
#if 0
#ifdef DEBUG_205
Debug( LDAP_DEBUG_ANY, "### %s meta_back_bind_op_result ldap_unbind_ext[%d] ld=%p\n",
op->o_log_prefix, candidate, (void *)msc->msc_ld );
#endif
#endif /* DEBUG_205 */
ldap_unbind_ext( msc->msc_ld, NULL, NULL );
msc->msc_ld = NULL;
@ -575,7 +575,7 @@ meta_back_single_dobind(
!op->o_do_not_cache &&
( BER_BVISNULL( &msc->msc_bound_ndn ) ||
BER_BVISEMPTY( &msc->msc_bound_ndn ) ||
( LDAP_BACK_CONN_ISPRIV( msc ) && dn_match( &msc->msc_bound_ndn, &mt->mt_idassert_authcDN ) ) ||
( LDAP_BACK_CONN_ISPRIV( mc ) && dn_match( &msc->msc_bound_ndn, &mt->mt_idassert_authcDN ) ) ||
( mt->mt_idassert_flags & LDAP_BACK_AUTH_OVERRIDE ) ) )
{
(void)meta_back_proxy_authz_bind( mc, candidate, op, rs, sendok );

View File

@ -189,10 +189,14 @@ meta_clear_one_candidate(
if ( msc->msc_ld ) {
#if 0
Debug( LDAP_DEBUG_ANY, "### %s meta_clear_one_candidate ldap_unbind_ext[%d] mc=%p\n",
op ? op->o_log_prefix : "", candidate, (void *)mc );
#endif
#ifdef DEBUG_205
char buf[ BUFSIZ ];
snprintf( buf, sizeof( buf ), "meta_clear_one_candidate ldap_unbind_ext[%d] mc=%p ld=%p",
candidate, (void *)mc, (void *)msc->msc_ld );
Debug( LDAP_DEBUG_ANY, "### %s %s\n",
op ? op->o_log_prefix : "", buf, 0 );
#endif /* DEBUG_205 */
ldap_unbind_ext( msc->msc_ld, NULL, NULL );
msc->msc_ld = NULL;
@ -212,20 +216,3 @@ meta_clear_one_candidate(
return 0;
}
/*
* meta_clear_candidates
*
* clears all candidates
*/
int
meta_clear_candidates( Operation *op, metaconn_t *mc )
{
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
int c;
for ( c = 0; c < mi->mi_ntargets; c++ ) {
meta_clear_one_candidate( op, mc, c );
}
return 0;
}

View File

@ -34,319 +34,122 @@
int
meta_back_compare( Operation *op, SlapReply *rs )
{
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
metaconn_t *mc = NULL;
char *match = NULL,
*err = NULL;
struct berval mmatch = BER_BVNULL;
int ncandidates = 0,
last = 0,
i,
count = 0,
rc,
cres = LDAP_SUCCESS,
rres = LDAP_SUCCESS,
*msgid;
dncookie dc;
metainfo_t *mi = ( metainfo_t * )op->o_bd->be_private;
metatarget_t *mt;
metaconn_t *mc;
int rc = 0;
int candidate = -1;
struct berval mdn = BER_BVNULL;
dncookie dc;
struct berval mapped_attr = op->orc_ava->aa_desc->ad_cname;
struct berval mapped_value = op->orc_ava->aa_value;
int msgid;
int do_retry = 1;
LDAPControl **ctrls = NULL;
SlapReply *candidates = meta_back_candidates_get( op );
mc = meta_back_getconn( op, rs, NULL, LDAP_BACK_SENDERR );
mc = meta_back_getconn( op, rs, &candidate, LDAP_BACK_SENDERR );
if ( !mc || !meta_back_dobind( op, rs, mc, LDAP_BACK_SENDERR ) ) {
return rs->sr_err;
}
msgid = ch_calloc( sizeof( int ), mi->mi_ntargets );
if ( msgid == NULL ) {
send_ldap_error( op, rs, LDAP_OTHER, NULL );
rc = LDAP_OTHER;
goto done;
}
assert( mc->mc_conns[ candidate ].msc_ld != NULL );
/*
* start an asynchronous compare for each candidate target
* Rewrite the modify dn, if needed
*/
mt = mi->mi_targets[ candidate ];
dc.target = mt;
dc.conn = op->o_conn;
dc.rs = rs;
dc.ctx = "compareDN";
for ( i = 0; i < mi->mi_ntargets; i++ ) {
struct berval mdn = BER_BVNULL;
struct berval mapped_attr = op->orc_ava->aa_desc->ad_cname;
struct berval mapped_value = op->orc_ava->aa_value;
metatarget_t *mt = mi->mi_targets[ i ];
LDAPControl **ctrls = NULL;
switch ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
case LDAP_UNWILLING_TO_PERFORM:
rc = 1;
goto cleanup;
if ( ! META_IS_CANDIDATE( &candidates[ i ] ) ) {
msgid[ i ] = -1;
continue;
}
/*
* Rewrite the compare dn, if needed
*/
dc.target = mt;
switch ( ldap_back_dn_massage( &dc, &op->o_req_dn, &mdn ) ) {
case LDAP_UNWILLING_TO_PERFORM:
rc = 1;
goto finish;
default:
break;
}
/*
* if attr is objectClass, try to remap the value
*/
if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass ) {
ldap_back_map( &mt->mt_rwmap.rwm_oc,
&op->orc_ava->aa_value,
&mapped_value, BACKLDAP_MAP );
if ( BER_BVISNULL( &mapped_value ) || mapped_value.bv_val[0] == '\0' ) {
continue;
}
/*
* else try to remap the attribute
*/
} else {
ldap_back_map( &mt->mt_rwmap.rwm_at,
&op->orc_ava->aa_desc->ad_cname,
&mapped_attr, BACKLDAP_MAP );
if ( BER_BVISNULL( &mapped_attr ) || mapped_attr.bv_val[0] == '\0' ) {
continue;
}
if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
{
dc.ctx = "compareAttrDN";
switch ( ldap_back_dn_massage( &dc, &op->orc_ava->aa_value, &mapped_value ) )
{
case LDAP_UNWILLING_TO_PERFORM:
rc = 1;
goto finish;
default:
break;
}
}
}
ctrls = op->o_ctrls;
if ( ldap_back_proxy_authz_ctrl( &mc->mc_conns[ i ].msc_bound_ndn,
mt->mt_version, &mt->mt_idassert, op, rs, &ctrls ) != LDAP_SUCCESS )
{
continue;
}
/*
* the compare op is spawned across the targets and the first
* that returns determines the result; a constraint on unicity
* of the result ought to be enforced
*/
rc = ldap_compare_ext( mc->mc_conns[ i ].msc_ld, mdn.bv_val,
mapped_attr.bv_val, &mapped_value,
ctrls, NULL, &msgid[ i ] );
(void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
free( mdn.bv_val );
BER_BVZERO( &mdn );
}
if ( mapped_attr.bv_val != op->orc_ava->aa_desc->ad_cname.bv_val ) {
free( mapped_attr.bv_val );
BER_BVZERO( &mapped_attr );
}
if ( mapped_value.bv_val != op->orc_ava->aa_value.bv_val ) {
free( mapped_value.bv_val );
BER_BVZERO( &mapped_value );
}
if ( rc != LDAP_SUCCESS ) {
/* FIXME: what should we do with the error? */
continue;
}
++ncandidates;
default:
break;
}
/*
* wait for replies
* if attr is objectClass, try to remap the value
*/
for ( rc = 0, count = 0; ncandidates > 0; ) {
if ( op->orc_ava->aa_desc == slap_schema.si_ad_objectClass ) {
ldap_back_map( &mt->mt_rwmap.rwm_oc,
&op->orc_ava->aa_value,
&mapped_value, BACKLDAP_MAP );
/*
* FIXME: should we check for abandon?
*/
for ( i = 0; i < mi->mi_ntargets; i++ ) {
metasingleconn_t *msc = &mc->mc_conns[ i ];
int lrc;
LDAPMessage *res = NULL;
struct timeval tv;
if ( BER_BVISNULL( &mapped_value ) || BER_BVISEMPTY( &mapped_value ) ) {
goto cleanup;
}
LDAP_BACK_TV_SET( &tv );
/*
* else try to remap the attribute
*/
} else {
ldap_back_map( &mt->mt_rwmap.rwm_at,
&op->orc_ava->aa_desc->ad_cname,
&mapped_attr, BACKLDAP_MAP );
if ( BER_BVISNULL( &mapped_attr ) || BER_BVISEMPTY( &mapped_attr ) ) {
goto cleanup;
}
if ( msgid[ i ] == -1 ) {
continue;
}
if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
{
dc.ctx = "compareAttrDN";
lrc = ldap_result( msc->msc_ld, msgid[ i ],
LDAP_MSG_ALL, &tv, &res );
switch ( lrc ) {
case 0:
assert( res == NULL );
continue;
case -1:
/* we do not retry in this case;
* only for unique operations... */
ldap_get_option( msc->msc_ld,
LDAP_OPT_RESULT_CODE, &rs->sr_err );
rres = slap_map_api2result( rs );
rres = rc;
rc = -1;
goto finish;
switch ( ldap_back_dn_massage( &dc, &op->orc_ava->aa_value, &mapped_value ) )
{
case LDAP_UNWILLING_TO_PERFORM:
rc = 1;
goto cleanup;
default:
/* only touch when activity actually took place... */
/* NOTE: no mutex because there's only a loose requirement
* to bump it up... */
if ( mi->mi_idle_timeout != 0 && msc->msc_time < op->o_time ) {
msc->msc_time = op->o_time;
}
break;
}
if ( lrc == LDAP_RES_COMPARE ) {
if ( count > 0 ) {
rres = LDAP_OTHER;
rc = -1;
goto finish;
}
/* FIXME: matched? referrals? response controls? */
rc = ldap_parse_result( msc->msc_ld, res,
&rs->sr_err,
NULL, NULL, NULL, NULL, 1 );
if ( rc != LDAP_SUCCESS ) {
rres = rc;
rc = -1;
goto finish;
}
switch ( rs->sr_err ) {
case LDAP_COMPARE_TRUE:
case LDAP_COMPARE_FALSE:
/*
* true or false, got it;
* sending to cache ...
*/
if ( mi->mi_cache.ttl != META_DNCACHE_DISABLED ) {
( void )meta_dncache_update_entry( &mi->mi_cache, &op->o_req_ndn, i );
}
count++;
rc = 0;
break;
default:
rres = slap_map_api2result( rs );
if ( err != NULL ) {
free( err );
}
ldap_get_option( msc->msc_ld,
LDAP_OPT_DIAGNOSTIC_MESSAGE, &err );
if ( match != NULL ) {
free( match );
}
ldap_get_option( msc->msc_ld,
LDAP_OPT_MATCHED_DN, &match );
last = i;
break;
}
msgid[ i ] = -1;
--ncandidates;
} else {
msgid[ i ] = -1;
--ncandidates;
if ( res ) {
ldap_msgfree( res );
}
break;
}
}
}
finish:;
retry:;
ctrls = op->o_ctrls;
rc = ldap_back_proxy_authz_ctrl( &mc->mc_conns[ candidate ].msc_bound_ndn,
mt->mt_version, &mt->mt_idassert, op, rs, &ctrls );
if ( rc != LDAP_SUCCESS ) {
send_ldap_result( op, rs );
goto cleanup;
}
/*
* Rewrite the matched portion of the search base, if required
*
* FIXME: only the last one gets caught!
*/
if ( count == 1 ) {
if ( match != NULL ) {
free( match );
match = NULL;
}
/*
* the result of the compare is assigned to the res code
* that will be returned
*/
rres = cres;
/*
* At least one compare failed with matched portion,
* and none was successful
*/
} else if ( match != NULL && match[ 0 ] != '\0' ) {
struct berval matched, pmatched;
rs->sr_err = ldap_compare_ext( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
mapped_attr.bv_val, &mapped_value,
ctrls, NULL, &msgid );
ber_str2bv( match, 0, 0, &matched );
dc.ctx = "matchedDN";
ldap_back_dn_massage( &dc, &matched, &mmatch );
if ( dnPretty( NULL, &mmatch, &pmatched, NULL ) == LDAP_SUCCESS ) {
if ( mmatch.bv_val != match ) {
free( mmatch.bv_val );
}
mmatch = pmatched;
rs->sr_err = meta_back_op_result( mc, op, rs, candidate, msgid,
mt->mt_timeout[ SLAP_OP_COMPARE ], LDAP_BACK_SENDRESULT );
if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
do_retry = 0;
if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
/* if the identity changed, there might be need to re-authz */
(void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
goto retry;
}
}
if ( rres != LDAP_SUCCESS ) {
rs->sr_err = rres;
}
rs->sr_matched = mmatch.bv_val;
send_ldap_result( op, rs );
rs->sr_matched = NULL;
cleanup:;
(void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
if ( match != NULL ) {
if ( mmatch.bv_val != match ) {
free( mmatch.bv_val );
}
free( match );
if ( mdn.bv_val != op->o_req_dn.bv_val ) {
free( mdn.bv_val );
}
if ( msgid ) {
free( msgid );
if ( op->orc_ava->aa_value.bv_val != mapped_value.bv_val ) {
free( mapped_value.bv_val );
}
done:;
meta_back_release_conn( op, mc );
if ( mc ) {
meta_back_release_conn( op, mc );
}
return rc;
return rs->sr_err;
}

View File

@ -156,11 +156,12 @@ ravl_print( Avlnode *root, int depth )
}
mc = (metaconn_t *)root->avl_data;
fprintf( stderr, "mc=%p local=\"%s\" conn=%p %s refcnt=%d\n",
fprintf( stderr, "mc=%p local=\"%s\" conn=%p %s refcnt=%d%s\n",
(void *)mc,
mc->mc_local_ndn.bv_val ? mc->mc_local_ndn.bv_val : "",
(void *)mc->mc_conn,
avl_bf2str( root->avl_bf ), mc->mc_refcnt );
avl_bf2str( root->avl_bf ), mc->mc_refcnt,
LDAP_BACK_CONN_TAINTED( mc ) ? " tainted" : "" );
ravl_print( root->avl_left, depth + 1 );
}
@ -424,10 +425,10 @@ retry:;
|| ( rs->sr_err != LDAP_SUCCESS && LDAP_BACK_TLS_CRITICAL( mi ) ) )
{
#if 0
#ifdef DEBUG_205
Debug( LDAP_DEBUG_ANY, "### %s meta_back_init_one_conn(TLS) ldap_unbind_ext[%d] ld=%p\n",
op->o_log_prefix, candidate, (void *)msc->msc_ld );
#endif
#endif /* DEBUG_205 */
ldap_unbind_ext( msc->msc_ld, NULL, NULL );
msc->msc_ld = NULL;
@ -464,8 +465,6 @@ retry:;
ber_bvreplace( &msc->msc_bound_ndn, &slap_empty_bv );
}
LDAP_BACK_CONN_ISPRIV_SET( msc );
} else {
if ( !BER_BVISNULL( &msc->msc_cred ) ) {
memset( msc->msc_cred.bv_val, 0, msc->msc_cred.bv_len );
@ -492,10 +491,10 @@ retry:;
&msc->msc_bound_ndn ) )
{
#if 0
#ifdef DEBUG_205
Debug( LDAP_DEBUG_ANY, "### %s meta_back_init_one_conn(rewrite) ldap_unbind_ext[%d] ld=%p\n",
op->o_log_prefix, candidate, (void *)msc->msc_ld );
#endif
#endif /* DEBUG_205 */
ldap_unbind_ext( msc->msc_ld, NULL, NULL );
msc->msc_ld = NULL;
@ -872,7 +871,7 @@ meta_back_getconn(
META_DNTYPE_ENTRY,
META_DNTYPE_PARENT,
META_DNTYPE_NEWPARENT
} dn_type = META_DNTYPE_ENTRY;
} dn_type = META_DNTYPE_ENTRY;
struct berval ndn = op->o_req_ndn,
pndn;
@ -923,7 +922,8 @@ retry_lock:;
op->o_log_prefix, (void *)mc, LDAP_BACK_PCONN_ID( mc ) );
}
/* Don't reuse connections while they're still binding */
/* 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();
@ -959,12 +959,12 @@ retry_lock:;
}
break;
case LDAP_REQ_COMPARE:
case LDAP_REQ_DELETE:
case LDAP_REQ_MODIFY:
/* just a unique candidate */
break;
case LDAP_REQ_COMPARE:
case LDAP_REQ_SEARCH:
/* allow multiple candidates for the searchBase */
op_type = META_OP_ALLOW_MULTIPLE;
@ -990,6 +990,13 @@ retry_lock:;
if ( sendok & LDAP_BACK_BINDING ) {
LDAP_BACK_CONN_BINDING_SET( mc );
}
if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
LDAP_BACK_CONN_ISPRIV_SET( mc );
}
} else if ( 0 ) {
/* TODO: if any of the connections is binding,
* release mc and create a new one */
}
for ( i = 0; i < mi->mi_ntargets; i++ ) {
@ -1121,12 +1128,11 @@ retry_lock2:;
(caddr_t)&mc_curr, meta_back_conndn_cmp );
if ( mc != NULL ) {
/* Don't reuse connections while they're still binding */
if ( LDAP_BACK_CONN_BINDING( mc ) ) {
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;
}
mc->mc_refcnt++;
}
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
@ -1142,6 +1148,9 @@ retry_lock2:;
if ( sendok & LDAP_BACK_BINDING ) {
LDAP_BACK_CONN_BINDING_SET( mc );
}
if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
LDAP_BACK_CONN_ISPRIV_SET( mc );
}
}
}
@ -1197,8 +1206,8 @@ retry_lock2:;
mc->mc_conn = mc_curr.mc_conn;
ber_dupbv( &mc->mc_local_ndn, &mc_curr.mc_local_ndn );
new_conn = 1;
if ( sendok & LDAP_BACK_BINDING ) {
LDAP_BACK_CONN_BINDING_SET( mc );
if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
LDAP_BACK_CONN_ISPRIV_SET( mc );
}
}
@ -1404,7 +1413,6 @@ meta_back_release_conn_lock(
}
assert( mc->mc_refcnt > 0 );
mc->mc_refcnt--;
LDAP_BACK_CONN_BINDING_CLEAR( mc );
/* NOTE: the connection is removed if either it is tainted
* or if it is shared and no one else is using it. This needs
* to occur because for intrinsic reasons cached connections
@ -1428,8 +1436,14 @@ meta_back_release_conn_lock(
#endif /* META_BACK_PRINT_CONNTREE */
if ( mc->mc_refcnt == 0 ) {
meta_back_conn_free( mc );
mc = NULL;
}
}
if ( mc != NULL ) {
LDAP_BACK_CONN_BINDING_CLEAR( mc );
}
if ( dolock ) {
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
}

View File

@ -170,7 +170,6 @@ meta_back_conn_free(
{
metaconn_t *mc = v_mc;
int ntargets;
Operation op;
assert( mc != NULL );
assert( mc->mc_refcnt == 0 );

View File

@ -85,7 +85,8 @@ meta_search_dobind_init(
meta_search_candidate_t retcode;
Debug( LDAP_DEBUG_TRACE, "%s >>> meta_search_dobind_init[%d]\n", op->o_log_prefix, candidate, 0 );
Debug( LDAP_DEBUG_TRACE, "%s >>> meta_search_dobind_init[%d]\n",
op->o_log_prefix, candidate, 0 );
/*
* all the targets are already bound as pseudoroot
@ -98,17 +99,55 @@ meta_search_dobind_init(
ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
if ( LDAP_BACK_CONN_ISBOUND( msc ) || LDAP_BACK_CONN_ISANON( msc ) ) {
/* already bound (or anonymous) */
#ifdef DEBUG_205
char buf[ SLAP_TEXT_BUFLEN ] = { '\0' };
int bound = 0;
if ( LDAP_BACK_CONN_ISBOUND( msc ) ) {
bound = 1;
}
snprintf( buf, sizeof( buf ), " mc=%p lc=%p%s DN=\"%s\"",
(void *)mc, (void *)msc->msc_ld,
bound ? " bound" : " anonymous",
bound == 0 ? "" : msc->msc_bound_ndn.bv_val );
Debug( LDAP_DEBUG_ANY, "### %s meta_search_dobind_init[%d]%s\n",
op->o_log_prefix, candidate, buf );
#endif /* DEBUG_205 */
retcode = META_SEARCH_CANDIDATE;
} else if ( 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",
(void *)mc, (void *)msc->msc_ld );
Debug( LDAP_DEBUG_ANY, "### %s meta_search_dobind_init[%d]%s\n",
op->o_log_prefix, candidate, buf );
#endif /* DEBUG_205 */
candidates[ candidate ].sr_msgid = META_MSGID_NEED_BIND;
retcode = META_SEARCH_NEED_BIND;
} else {
/* we'll need to bind the target for this conn */
#ifdef DEBUG_205
char buf[ SLAP_TEXT_BUFLEN ];
snprintf( buf, sizeof( buf ), " mc=%p ld=%p binding",
(void *)mc, (void *)msc->msc_ld );
Debug( LDAP_DEBUG_ANY, "### %s meta_search_dobind_init[%d]%s\n",
op->o_log_prefix, candidate, buf );
#endif /* DEBUG_205 */
LDAP_BACK_CONN_BINDING_SET( msc );
}
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
if ( retcode != META_SEARCH_BINDING ) {
@ -120,8 +159,8 @@ meta_search_dobind_init(
* state, with eventual connection expiration or invalidation)
* it was not initialized as expected */
Debug( LDAP_DEBUG_ANY, "%s meta_search_dobind_init[%d] ld=NULL\n",
op->o_log_prefix, candidate, 0 );
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 );
@ -185,6 +224,18 @@ meta_search_dobind_init(
rc = ldap_sasl_bind( msc->msc_ld, binddn.bv_val, LDAP_SASL_SIMPLE, &cred,
NULL, NULL, &candidates[ candidate ].sr_msgid );
#ifdef DEBUG_205
{
char buf[ SLAP_TEXT_BUFLEN ];
snprintf( buf, sizeof( buf ), "meta_search_dobind_init[%d] mc=%p ld=%p rc=%d",
candidate, (void *)mc, (void *)mc->mc_conns[ candidate ].msc_ld, rc );
Debug( LDAP_DEBUG_ANY, "### %s %s\n",
op->o_log_prefix, buf, 0 );
}
#endif /* DEBUG_205 */
switch ( rc ) {
case LDAP_SUCCESS:
assert( candidates[ candidate ].sr_msgid >= 0 );
@ -222,9 +273,9 @@ other:;
retcode = META_SEARCH_ERR;
} else {
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
retcode = META_SEARCH_NOT_CANDIDATE;
}
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
break;
}
@ -271,17 +322,22 @@ meta_search_dobind_result(
} else {
/* FIXME: check if bound as idassert authcDN! */
if ( be_isroot( op ) ) {
LDAP_BACK_CONN_ISBOUND_SET( msc );
} else {
if ( BER_BVISNULL( &msc->msc_bound_ndn )
|| BER_BVISEMPTY( &msc->msc_bound_ndn ) )
{
LDAP_BACK_CONN_ISANON_SET( msc );
} else {
LDAP_BACK_CONN_ISBOUND_SET( msc );
}
retcode = META_SEARCH_CANDIDATE;
}
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
META_BINDING_CLEAR( &candidates[ candidate ] );
ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
return retcode;
}
@ -317,6 +373,7 @@ meta_back_search_start(
if ( META_BACK_ONERR_STOP( mi ) ) {
return META_SEARCH_ERR;
}
candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
return META_SEARCH_NOT_CANDIDATE;
}
@ -567,8 +624,17 @@ getconn:;
* Inits searches
*/
for ( i = 0; i < mi->mi_ntargets; i++ ) {
/* reset sr_msgid; it is used in most loops
* to check if that target is still to be considered */
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
/* a target is marked as candidate by meta_back_getconn();
* if for any reason (an error, it's over or so) it is
* no longer active, sr_msgid is set to META_MSGID_IGNORE
* but it remains candidate, which means it has been active
* at some point during the operation. This allows to
* use its response code and more to compute the final
* response */
if ( !META_IS_CANDIDATE( &candidates[ i ] ) ) {
continue;
}
@ -589,6 +655,7 @@ getconn:;
switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )
{
case META_SEARCH_NOT_CANDIDATE:
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
break;
case META_SEARCH_NEED_BIND:
@ -612,15 +679,31 @@ getconn:;
}
if ( ncandidates > 0 && needbind == ncandidates ) {
assert( ( sendok & LDAP_BACK_BINDING ) == 0 );
/*
* give up the second time...
*
* NOTE: this should not occur the second time, since a fresh
* connection has ben created; however, targets may also
* need bind because the bind timed out or so.
*/
if ( sendok & LDAP_BACK_BINDING ) {
Debug( LDAP_DEBUG_ANY,
"%s meta_back_search: unable to initialize conn\n",
op->o_log_prefix, 0, 0 );
rs->sr_err = LDAP_UNAVAILABLE;
rs->sr_text = "unable to initialize connection to remote targets";
send_ldap_result( op, rs );
rc = -1;
goto finish;
}
/* FIXME: better create a separate connection? */
sendok |= LDAP_BACK_BINDING;
#if 0
Debug( LDAP_DEBUG_TRACE, "*** %s drop mc=%p create new connection\n",
op->o_log_prefix, mc, 0 );
#endif
#ifdef DEBUG_205
Debug( LDAP_DEBUG_ANY, "*** %s drop mc=%p create new connection\n",
op->o_log_prefix, (void *)mc, 0 );
#endif /* DEBUG_205 */
meta_back_release_conn( op, mc );
mc = NULL;
@ -634,7 +717,7 @@ getconn:;
initial_candidates = ncandidates;
if ( LogTest( LDAP_DEBUG_TRACE ) ) {
char cnd[ BUFSIZ ];
char cnd[ SLAP_TEXT_BUFLEN ];
int c;
for ( c = 0; c < mi->mi_ntargets; c++ ) {
@ -719,10 +802,12 @@ getconn:;
metasingleconn_t *msc = &mc->mc_conns[ i ];
LDAPMessage *res = NULL, *msg;
/* if msgid is invalid, don't ldap_result() */
if ( candidates[ i ].sr_msgid == META_MSGID_IGNORE ) {
continue;
}
/* if target still needs bind, retry */
if ( candidates[ i ].sr_msgid == META_MSGID_NEED_BIND ) {
meta_search_candidate_t retcode;
@ -805,6 +890,23 @@ getconn:;
if ( op->o_abandon ) {
break;
}
#ifdef DEBUG_205
if ( msc->msc_ld == NULL ) {
char buf[ SLAP_TEXT_BUFLEN ];
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",
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_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
Debug( LDAP_DEBUG_ANY, "!!! %s\n", buf, 0, 0 );
}
#endif /* DEBUG_205 */
/*
* FIXME: handle time limit as well?
@ -833,7 +935,8 @@ really_bad:;
switch ( meta_back_search_start( op, rs, &dc, &mc, i, candidates ) )
{
case META_SEARCH_CANDIDATE:
break;
/* get back into business... */
continue;
/* means that failed but onerr == continue */
case META_SEARCH_NOT_CANDIDATE:
@ -855,6 +958,7 @@ really_bad:;
default:
/* unrecoverable error */
candidates[ i ].sr_msgid = META_MSGID_IGNORE;
rc = rs->sr_err = LDAP_OTHER;
goto finish;
}
@ -1225,11 +1329,16 @@ really_bad:;
if ( LDAP_BACK_CONN_BINDING( &mc->mc_conns[ i ] ) ) {
/* if still binding, destroy */
#if 0
Debug( LDAP_DEBUG_ANY, "### %s meta_back_search(abandon) "
"ldap_unbind_ext[%ld] ld=%p\n",
op->o_log_prefix, i, (void *)mc->mc_conns[i].msc_ld );
#endif
#ifdef DEBUG_205
char buf[ SLAP_TEXT_BUFLEN ];
snprintf( buf, sizeof( buf), "%s meta_back_search(abandon) "
"ldap_unbind_ext[%ld] mc=%p ld=%p",
op->o_log_prefix, i, (void *)mc,
(void *)mc->mc_conns[i].msc_ld );
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;
@ -1273,7 +1382,7 @@ really_bad:;
#if 0
if ( LogTest( LDAP_DEBUG_TRACE ) ) {
char buf[ BUFSIZ ];
char buf[ SLAP_TEXT_BUFLEN ];
snprintf( buf, sizeof( buf ), "%s %ld.%06ld %d/%d mc=%p",
op->o_log_prefix, save_tv.tv_sec, save_tv.tv_usec,
@ -1390,8 +1499,8 @@ really_bad:;
#if 0
{
char buf[BUFSIZ];
char cnd[BUFSIZ];
char buf[ SLAP_TEXT_BUFLEN ];
char cnd[ SLAP_TEXT_BUFLEN ];
int i;
for ( i = 0; i < mi->mi_ntargets; i++ ) {
@ -1449,11 +1558,11 @@ finish:;
assert( candidates[ i ].sr_msgid >= 0 );
assert( mc->mc_conns[ i ].msc_ld != NULL );
#if 0
#ifdef DEBUG_205
Debug( LDAP_DEBUG_ANY, "### %s meta_back_search(cleanup) "
"ldap_unbind_ext[%ld] ld=%p\n",
op->o_log_prefix, i, (void *)mc->mc_conns[i].msc_ld );
#endif
#endif /* DEBUG_205 */
/* if still binding, destroy */
ldap_unbind_ext( mc->mc_conns[ i ].msc_ld, NULL, NULL );