metaconn_t *mc,
int candidate );
-extern int
-meta_clear_candidates(
- Operation *op,
- metaconn_t *mc );
-
/*
* Dn cache stuff (experimental)
*/
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,
#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;
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;
!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 );
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;
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;
-}
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;
-
- SlapReply *candidates = meta_back_candidates_get( op );
-
- mc = meta_back_getconn( op, rs, NULL, LDAP_BACK_SENDERR );
+ 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;
+
+ 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;
-
- 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->o_req_dn, &mdn ) ) {
+ case LDAP_UNWILLING_TO_PERFORM:
+ rc = 1;
+ goto cleanup;
- 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; ) {
-
- /*
- * 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 ( 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 );
- LDAP_BACK_TV_SET( &tv );
-
- if ( msgid[ i ] == -1 ) {
- continue;
- }
+ if ( BER_BVISNULL( &mapped_value ) || BER_BVISEMPTY( &mapped_value ) ) {
+ goto cleanup;
+ }
- lrc = ldap_result( msc->msc_ld, msgid[ i ],
- LDAP_MSG_ALL, &tv, &res );
+ /*
+ * 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;
+ }
- switch ( lrc ) {
- case 0:
- assert( res == NULL );
- continue;
+ if ( op->orc_ava->aa_desc->ad_type->sat_syntax == slap_schema.si_syn_distinguishedName )
+ {
+ dc.ctx = "compareAttrDN";
- 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:;
-
- /*
- * 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;
-
- ber_str2bv( match, 0, 0, &matched );
+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;
+ }
- 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 = ldap_compare_ext( mc->mc_conns[ candidate ].msc_ld, mdn.bv_val,
+ mapped_attr.bv_val, &mapped_value,
+ ctrls, NULL, &msgid );
+
+ 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;
}
}
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 );
}
|| ( 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;
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 );
&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;
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;
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();
}
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;
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++ ) {
(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 );
if ( sendok & LDAP_BACK_BINDING ) {
LDAP_BACK_CONN_BINDING_SET( mc );
}
+ if ( LDAP_BACK_CONN_ISPRIV( &mc_curr ) ) {
+ LDAP_BACK_CONN_ISPRIV_SET( mc );
+ }
}
}
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 );
}
}
}
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
#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 );
}
{
metaconn_t *mc = v_mc;
int ntargets;
- Operation op;
assert( mc != NULL );
assert( mc->mc_refcnt == 0 );
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
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 ) {
* 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 );
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 );
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;
}
} 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;
}
if ( META_BACK_ONERR_STOP( mi ) ) {
return META_SEARCH_ERR;
}
+ candidates[ candidate ].sr_msgid = META_MSGID_IGNORE;
return META_SEARCH_NOT_CANDIDATE;
}
* 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;
}
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:
}
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;
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++ ) {
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;
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?
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:
default:
/* unrecoverable error */
+ candidates[ i ].sr_msgid = META_MSGID_IGNORE;
rc = rs->sr_err = LDAP_OTHER;
goto finish;
}
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;
#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,
#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++ ) {
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 );