]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-meta/conn.c
use result of validation (ITS#4028)
[openldap] / servers / slapd / back-meta / conn.c
index f1f80d72e379d30bfe73ed59064fcfb4a2198ae5..a0ae2801249fe69e0b607e747dff707e43900006 100644 (file)
@@ -178,16 +178,7 @@ meta_back_freeconn(
 
        assert( mc != NULL );
 
-retry_lock:;
-       switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
-       case LDAP_PVT_THREAD_EBUSY:
-       default:
-               ldap_pvt_thread_yield();
-               goto retry_lock;
-
-       case 0:
-               break;
-       }
+       ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
 
        if ( --mc->mc_refcnt == 0 ) {
                meta_back_conn_free( mc );
@@ -412,20 +403,16 @@ meta_back_retry(
        metasingleconn_t        *msc = &mc->mc_conns[ candidate ];
 
 retry_lock:;
-       switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
-       case LDAP_PVT_THREAD_EBUSY:
-       default:
-               ldap_pvt_thread_yield();
-               goto retry_lock;
-
-       case 0:
-               break;
-       }
+       ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
 
        assert( mc->mc_refcnt > 0 );
 
        if ( mc->mc_refcnt == 1 ) {
-               ldap_pvt_thread_mutex_lock( &mc->mc_mutex );
+               while ( ldap_pvt_thread_mutex_trylock( &mc->mc_mutex ) ) {
+                       ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );
+                       ldap_pvt_thread_yield();
+                       goto retry_lock;
+               }
 
                ldap_unbind_ext_s( msc->msc_ld, NULL, NULL );
                msc->msc_ld = NULL;
@@ -539,6 +526,7 @@ meta_back_get_candidate(
                         * a candidate, try using it (FIXME: YMMV) */
                        if ( mi->mi_defaulttarget != META_DEFAULT_TARGET_NONE
                                && meta_back_is_candidate( &mi->mi_targets[ mi->mi_defaulttarget ].mt_nsuffix,
+                                               mi->mi_targets[ mi->mi_defaulttarget ].mt_scope,
                                                ndn, op->o_tag == LDAP_REQ_SEARCH ? op->ors_scope : LDAP_SCOPE_BASE ) )
                        {
                                candidate = mi->mi_defaulttarget;
@@ -551,11 +539,16 @@ meta_back_get_candidate(
                        }
                        break;
                }
+
+       } else {
+               rs->sr_err = LDAP_SUCCESS;
        }
 
        return candidate;
 }
 
+static void    *meta_back_candidates_dummy;
+
 static void
 meta_back_candidates_keyfree(
        void            *key,
@@ -577,7 +570,7 @@ meta_back_candidates_get( Operation *op )
                void            *data = NULL;
 
                ldap_pvt_thread_pool_getkey( op->o_threadctx,
-                               meta_back_candidates_keyfree, &data, NULL );
+                               &meta_back_candidates_dummy, &data, NULL );
                mc = (metacandidates_t *)data;
 
        } else {
@@ -593,7 +586,7 @@ meta_back_candidates_get( Operation *op )
 
                        data = (void *)mc;
                        ldap_pvt_thread_pool_setkey( op->o_threadctx,
-                                       meta_back_candidates_keyfree, data,
+                                       &meta_back_candidates_dummy, data,
                                        meta_back_candidates_keyfree );
 
                } else {
@@ -671,16 +664,7 @@ meta_back_getconn(
 
        /* Searches for a metaconn in the avl tree */
        mc_curr.mc_conn = op->o_conn;
-retry_lock:;
-       switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
-       case LDAP_PVT_THREAD_EBUSY:
-       default:
-               ldap_pvt_thread_yield();
-               goto retry_lock;
-
-       case 0:
-               break;
-       }
+       ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
        mc = (metaconn_t *)avl_find( mi->mi_conntree, 
                (caddr_t)&mc_curr, meta_back_conn_cmp );
        if ( mc ) {
@@ -746,9 +730,11 @@ retry_lock:;
                         * The target is activated; if needed, it is
                         * also init'd
                         */
-                       int lerr = meta_back_init_one_conn( op, rs, &mi->mi_targets[ i ],
-                                       &mc->mc_conns[ i ], sendok );
-                       if ( lerr == LDAP_SUCCESS ) {
+                       candidates[ i ].sr_err =
+                               meta_back_init_one_conn( op, rs,
+                                               &mi->mi_targets[ i ],
+                                               &mc->mc_conns[ i ], sendok );
+                       if ( candidates[ i ].sr_err == LDAP_SUCCESS ) {
                                candidates[ i ].sr_tag = META_CANDIDATE;
                                ncandidates++;
                                
@@ -760,7 +746,7 @@ retry_lock:;
                                 * be tried?
                                 */
                                candidates[ i ].sr_tag = META_NOT_CANDIDATE;
-                               err = lerr;
+                               err = candidates[ i ].sr_err;
                                continue;
                        }
                }
@@ -817,6 +803,10 @@ retry_lock:;
                        }
        
                        if ( rs->sr_err != LDAP_SUCCESS ) {
+                               if ( mc != NULL ) {
+                                       meta_back_release_conn( op, mc );
+                               }
+
                                if ( sendok & LDAP_BACK_SENDERR ) {
                                        if ( rs->sr_err == LDAP_NO_SUCH_OBJECT ) {
                                                rs->sr_matched = op->o_bd->be_suffix[ 0 ].bv_val;
@@ -825,18 +815,24 @@ retry_lock:;
                                        rs->sr_text = NULL;
                                        rs->sr_matched = NULL;
                                }
+                       
                                return NULL;
                        }
                }
 
                if ( newparent && meta_back_get_candidate( op, rs, op->orr_nnewSup ) != i )
                {
+                       if ( mc != NULL ) {
+                               meta_back_release_conn( op, mc );
+                       }
+
                        rs->sr_err = LDAP_UNWILLING_TO_PERFORM;
                        rs->sr_text = "cross-target rename not supported";
                        if ( sendok & LDAP_BACK_SENDERR ) {
                                send_ldap_result( op, rs );
                                rs->sr_text = NULL;
                        }
+
                        return NULL;
                }
 
@@ -849,16 +845,7 @@ retry_lock:;
                         * the reason is that the connection might have been
                         * created by meta_back_get_candidate() */
                        mc_curr.mc_conn = op->o_conn;
-retry_lock2:;
-                       switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
-                       case LDAP_PVT_THREAD_EBUSY:
-                       default:
-                               ldap_pvt_thread_yield();
-                               goto retry_lock2;
-
-                       case 0:
-                               break;
-                       }
+                       ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
                        mc = (metaconn_t *)avl_find( mi->mi_conntree, 
                                (caddr_t)&mc_curr, meta_back_conn_cmp );
                        if ( mc != NULL ) {
@@ -903,6 +890,7 @@ retry_lock2:;
                        return NULL;
                }
 
+               candidates[ i ].sr_err = LDAP_SUCCESS;
                candidates[ i ].sr_tag = META_CANDIDATE;
                ncandidates++;
 
@@ -925,6 +913,7 @@ retry_lock2:;
                for ( i = 0; i < mi->mi_ntargets; i++ ) {
                        if ( i == cached 
                                || meta_back_is_candidate( &mi->mi_targets[ i ].mt_nsuffix,
+                                               mi->mi_targets[ i ].mt_scope,
                                                &op->o_req_ndn, LDAP_SCOPE_SUBTREE ) )
                        {
 
@@ -937,6 +926,7 @@ retry_lock2:;
                                                &mc->mc_conns[ i ], sendok );
                                if ( lerr == LDAP_SUCCESS ) {
                                        candidates[ i ].sr_tag = META_CANDIDATE;
+                                       candidates[ i ].sr_err = LDAP_SUCCESS;
                                        ncandidates++;
 
                                        Debug( LDAP_DEBUG_TRACE, "%s: meta_back_init_one_conn(%d)\n",
@@ -952,7 +942,8 @@ retry_lock2:;
                                        if ( new_conn ) {
                                                ( void )meta_clear_one_candidate( &mc->mc_conns[ i ] );
                                        }
-                                       candidates[ i ].sr_tag = META_NOT_CANDIDATE;
+                                       /* leave the target candidate, but record the error for later use */
+                                       candidates[ i ].sr_err = lerr;
                                        err = lerr;
 
                                        Debug( LDAP_DEBUG_ANY, "%s: meta_back_init_one_conn(%d) failed: %d\n",
@@ -1003,16 +994,7 @@ done:;
                /*
                 * Inserts the newly created metaconn in the avl tree
                 */
-retry_lock3:;
-               switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
-               case LDAP_PVT_THREAD_EBUSY:
-               default:
-                       ldap_pvt_thread_yield();
-                       goto retry_lock3;
-
-               case 0:
-                       break;
-               }
+               ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
                err = avl_insert( &mi->mi_conntree, ( caddr_t )mc,
                                meta_back_conn_cmp, meta_back_conn_dup );
 
@@ -1065,17 +1047,7 @@ meta_back_release_conn(
 
        assert( mc != NULL );
 
-retry_lock:;
-       switch ( ldap_pvt_thread_mutex_trylock( &mi->mi_conn_mutex ) ) {
-       case LDAP_PVT_THREAD_EBUSY:
-       default:
-               ldap_pvt_thread_yield();
-               goto retry_lock;
-
-       case 0:
-               break;
-       }
-
+       ldap_pvt_thread_mutex_lock( &mi->mi_conn_mutex );
        assert( mc->mc_refcnt > 0 );
        mc->mc_refcnt--;
        ldap_pvt_thread_mutex_unlock( &mi->mi_conn_mutex );