]> git.sur5r.net Git - openldap/commitdiff
rework compare
authorPierangelo Masarati <ando@openldap.org>
Sun, 5 Nov 2006 12:05:47 +0000 (12:05 +0000)
committerPierangelo Masarati <ando@openldap.org>
Sun, 5 Nov 2006 12:05:47 +0000 (12:05 +0000)
fix several minor issues with using dangling pointers and uninitialized data
fix caching of privileged connections
fix issues with unresponsive target failures during search

servers/slapd/back-meta/back-meta.h
servers/slapd/back-meta/bind.c
servers/slapd/back-meta/candidates.c
servers/slapd/back-meta/compare.c
servers/slapd/back-meta/conn.c
servers/slapd/back-meta/init.c
servers/slapd/back-meta/search.c

index 3f3c933bcab3776c752c37c9f63d222daae47ae9..b7a8079d5ba1ac4202d88709c593a082d515d81a 100644 (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)
  */
index f96c60cadff202c35b974ae1edfe39fd310e54af..84bd5ec45b18dc3aa4bf3a3ae92091a54362b38c 100644 (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 );
index 878e6aee587b8b7c9f3cbcc7e733dbec3d9491e3..4a7ba3b3e267a5d87d0abe3f23516557d3f96f59 100644 (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;
-}
index be48b0a03abf000340c3688f6ee0a728af244e26..408021de4ff4c5355f64992876683912c778fbe9 100644 (file)
 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;
 }
 
index 8d226df8ada646df085cbed6ae89dc725c4085d6..4d2ddc454433f2923f0d187f5eb869c40dfdbdd8 100644 (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 );
        }
index 8bec4e3fe26bbae5e530bdafdedb25628be9bfbf..46f18cb20075ffb0e06d214124d2dd5c08c6a912 100644 (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 );
index 3c34c3aa658f36d85f084e4eeccae466af7361fe..04aa880f04d7a4f6d3a118719e94c51a7cf5c394 100644 (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 );