]> git.sur5r.net Git - openldap/commitdiff
seems to fix the equivalent of ITS#4429 in back-meta; had to give up per-target conn...
authorPierangelo Masarati <ando@openldap.org>
Sat, 1 Apr 2006 18:56:39 +0000 (18:56 +0000)
committerPierangelo Masarati <ando@openldap.org>
Sat, 1 Apr 2006 18:56:39 +0000 (18:56 +0000)
servers/slapd/back-meta/add.c
servers/slapd/back-meta/back-meta.h
servers/slapd/back-meta/bind.c
servers/slapd/back-meta/config.c
servers/slapd/back-meta/conn.c
servers/slapd/back-meta/delete.c
servers/slapd/back-meta/init.c
servers/slapd/back-meta/modify.c
servers/slapd/back-meta/modrdn.c
servers/slapd/back-meta/search.c

index 0d32ac7eb93e1d86ddaf6e836595e8338dd41eb5..2b089583742fc88de2ad7b87d6acd7c4e9588099 100644 (file)
@@ -170,9 +170,10 @@ retry:;
                              attrs, op->o_ctrls, NULL, &msgid );
        if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
                do_retry = 0;
-               if ( meta_back_retry( op, rs, mc, candidate, LDAP_BACK_SENDERR ) ) {
+               if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
                        goto retry;
                }
+               goto cleanup;
 
        } else if ( rs->sr_err == LDAP_SUCCESS ) {
                struct timeval  tv, *tvp = NULL;
@@ -234,7 +235,9 @@ cleanup:;
        }
 
 done:;
-       meta_back_release_conn( op, mc );
+       if ( mc ) {
+               meta_back_release_conn( op, mc );
+       }
 
        return rs->sr_err;
 }
index 2cf8369c7ca5fc908fc17fd03958950849ec1563..78bc791c3c354b0d5a566bb7684554e76c53c1bd 100644 (file)
@@ -174,17 +174,15 @@ typedef struct metasingleconn_t {
 #define META_ANONYMOUS         2
 #endif
 
-       time_t                  msc_create_time;
-       time_t                  msc_time;
-
        struct metainfo_t       *msc_info;
 } metasingleconn_t;
 
 typedef struct metaconn_t {
        struct slap_conn        *mc_conn;
-       ldap_pvt_thread_mutex_t mc_mutex;
        unsigned                mc_refcnt;
-       int                     mc_tainted;
+
+       time_t                  mc_create_time;
+       time_t                  mc_time;
        
        struct berval           mc_local_ndn;
        /* NOTE: msc_mscflags is used to recycle the #define
@@ -230,8 +228,6 @@ typedef struct metatarget_t {
        unsigned                mt_flags;
        int                     mt_version;
        time_t                  mt_network_timeout;
-       time_t                  mt_conn_ttl;
-       time_t                  mt_idle_timeout;
        struct timeval          mt_bind_timeout;
 #define META_BIND_TIMEOUT      LDAP_BACK_RESULT_UTIMEOUT
        time_t                  mt_timeout[ LDAP_BACK_OP_LAST ];
@@ -300,20 +296,19 @@ meta_back_getconn(
        ldap_back_send_t        sendok );
 
 extern void
-meta_back_release_conn(
+meta_back_release_conn_lock(
                Operation               *op,
-       metaconn_t              *mc );
+       metaconn_t              *mc,
+       int                     dolock );
+#define meta_back_release_conn(op, mc) meta_back_release_conn_lock( (op), (mc), 1 )
 
 extern int
-meta_back_retry_lock(
+meta_back_retry(
        Operation               *op,
        SlapReply               *rs,
-       metaconn_t              *mc,
+       metaconn_t              **mcp,
        int                     candidate,
-       ldap_back_send_t        sendok,
-       int                     dolock );
-#define meta_back_retry(op, rs, mc, candidate, sendok) \
-       meta_back_retry_lock((op), (rs), (mc), (candidate), (sendok), 1)
+       ldap_back_send_t        sendok );
 
 extern void
 meta_back_conn_free(
@@ -372,12 +367,12 @@ meta_back_conn_cmp(
        const void              *c2 );
 
 extern int
-meta_back_dnconn_cmp(
+meta_back_conndn_cmp(
        const void              *c1,
        const void              *c2 );
 
 extern int
-meta_back_dnconn_dup(
+meta_back_conndn_dup(
        void                    *c1,
        void                    *c2 );
 
index 9f5c0962dae51e0b22c5d3090b58d26a9cbfd318..1ec7217ab5c3eec7376056c36132e844c2f3221f 100644 (file)
@@ -192,6 +192,7 @@ meta_back_bind( Operation *op, SlapReply *rs )
                }
 
                if ( !dn_match( &op->o_req_ndn, &mc->mc_local_ndn ) ) {
+                       metaconn_t      *tmpmc;
                        int             lerr;
 
                        /* wait for all other ops to release the connection */
@@ -204,13 +205,13 @@ retry_lock:;
                        }
 
                        assert( mc->mc_refcnt == 1 );
-                       mc = avl_delete( &mi->mi_conninfo.lai_tree, (caddr_t)mc,
-                               meta_back_dnconn_cmp );
-                       assert( mc != NULL );
+                       tmpmc = avl_delete( &mi->mi_conninfo.lai_tree, (caddr_t)mc,
+                               meta_back_conndn_cmp );
+                       assert( tmpmc == mc );
 
                        ber_bvreplace( &mc->mc_local_ndn, &op->o_req_ndn );
                        lerr = avl_insert( &mi->mi_conninfo.lai_tree, (caddr_t)mc,
-                               meta_back_dnconn_cmp, meta_back_dnconn_dup );
+                               meta_back_conndn_cmp, meta_back_conndn_dup );
                        ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
                        if ( lerr == -1 ) {
                                for ( i = 0; i < mi->mi_ntargets; ++i ) {
@@ -383,7 +384,7 @@ retry:;
 
                        rc = slap_map_api2result( rs );
                        if ( rs->sr_err == LDAP_UNAVAILABLE && nretries != META_RETRY_NEVER ) {
-                               rc = meta_back_retry( op, rs, mc, candidate, LDAP_BACK_DONTSEND );
+                               rc = meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_DONTSEND );
                                if ( rc ) {
                                        if ( nretries > 0 ) {
                                                nretries--;
@@ -391,6 +392,7 @@ retry:;
                                        ldap_pvt_thread_yield();
                                        goto rebind;
                                }
+                               goto return_results;
                        }
                        break;
 
@@ -539,9 +541,6 @@ retry:;
 
                        rc = slap_map_api2result( rs );
                        if ( rc == LDAP_UNAVAILABLE && nretries != META_RETRY_NEVER ) {
-                               /* NOTE: we do not use meta_back_retry() here
-                                * to avoid circular loops; mc_mutex is set
-                                * by the caller */
                                if ( dolock ) {
                                        ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
                                }
@@ -628,8 +627,6 @@ meta_back_dobind(
                LDAP_BACK_PCONN_ID( mc->mc_conn ),
                isroot ? " (isroot)" : "" );
 
-       ldap_pvt_thread_mutex_lock( &mc->mc_mutex );
-
        /*
         * all the targets are bound as pseudoroot
         */
@@ -686,9 +683,10 @@ retry:;
 
                        if ( rc == LDAP_UNAVAILABLE && do_retry ) {
                                do_retry = 0;
-                               if ( meta_back_retry_lock( op, rs, mc, i, LDAP_BACK_DONTSEND, 0 ) ) {
+                               if ( meta_back_retry( op, rs, &mc, i, sendok ) ) {
                                        goto retry;
                                }
+                               return 0;
                        }
 
                        snprintf( buf, sizeof( buf ),
@@ -729,8 +727,6 @@ retry:;
        }
 
 done:;
-        ldap_pvt_thread_mutex_unlock( &mc->mc_mutex );
-
        Debug( LDAP_DEBUG_TRACE,
                "%s meta_back_dobind: conn=%ld bound=%d\n",
                op->o_log_prefix, LDAP_BACK_PCONN_ID( mc->mc_conn ), bound );
index cf26945dfe3a2c5da9b0f908508495541f0fbde2..4e5997a64c6d5474f6d7fa3ca47e2f22c1f91408 100644 (file)
@@ -158,8 +158,6 @@ meta_back_db_config(
                mi->mi_targets[ i ].mt_flags = mi->mi_flags;
                mi->mi_targets[ i ].mt_version = mi->mi_version;
                mi->mi_targets[ i ].mt_network_timeout = mi->mi_network_timeout;
-               mi->mi_targets[ i ].mt_conn_ttl = mi->mi_conn_ttl;
-               mi->mi_targets[ i ].mt_idle_timeout = mi->mi_idle_timeout;
                mi->mi_targets[ i ].mt_bind_timeout = mi->mi_bind_timeout;
                for ( c = 0; c < LDAP_BACK_OP_LAST; c++ ) {
                        mi->mi_targets[ i ].mt_timeout[ c ] = mi->mi_timeout[ c ];
@@ -448,9 +446,6 @@ meta_back_db_config(
        /* idle timeout when connecting to ldap servers */
        } else if ( strcasecmp( argv[ 0 ], "idle-timeout" ) == 0 ) {
                unsigned long   t;
-               time_t          *tp = mi->mi_ntargets ?
-                               &mi->mi_targets[ mi->mi_ntargets - 1 ].mt_idle_timeout
-                               : &mi->mi_idle_timeout;
 
                switch ( argc ) {
                case 1:
@@ -475,14 +470,11 @@ meta_back_db_config(
 
                }
 
-               *tp = (time_t)t;
+               mi->mi_idle_timeout = (time_t)t;
 
        /* conn ttl */
        } else if ( strcasecmp( argv[ 0 ], "conn-ttl" ) == 0 ) {
                unsigned long   t;
-               time_t          *tp = mi->mi_ntargets ?
-                               &mi->mi_targets[ mi->mi_ntargets - 1 ].mt_conn_ttl
-                               : &mi->mi_conn_ttl;
 
                switch ( argc ) {
                case 1:
@@ -507,7 +499,7 @@ meta_back_db_config(
 
                }
 
-               *tp = (time_t)t;
+               mi->mi_conn_ttl = (time_t)t;
 
        /* bind timeout when connecting to ldap servers */
        } else if ( strcasecmp( argv[ 0 ], "bind-timeout" ) == 0 ) {
index 1bb5fedc488c6a67b3e039a0cd8570e214d49313..9f6313eef3d456ae1d44ee03399396ef37c4c151 100644 (file)
 #define PRINT_CONNTREE 0
 
 /*
- * meta_back_dnconn_cmp
+ * meta_back_conndn_cmp
  *
  * compares two struct metaconn based on the value of the conn pointer
  * and of the local DN; used by avl stuff
  */
 int
-meta_back_dnconn_cmp(
+meta_back_conndn_cmp(
        const void *c1,
        const void *c2 )
 {
@@ -66,6 +66,36 @@ meta_back_dnconn_cmp(
        return rc;
 }
 
+/*
+ * meta_back_conndnmc_cmp
+ *
+ * compares two struct metaconn based on the value of the conn pointer,
+ * the local DN and the struct pointer; used by avl stuff
+ */
+static int
+meta_back_conndnmc_cmp(
+       const void *c1,
+       const void *c2 )
+{
+       metaconn_t      *mc1 = ( metaconn_t * )c1;
+        metaconn_t     *mc2 = ( metaconn_t * )c2;
+       int             rc;
+       
+       /* If local DNs don't match, it is definitely not a match */
+       /* For shared sessions, conn is NULL. Only explicitly
+        * bound sessions will have non-NULL conn.
+        */
+       rc = SLAP_PTRCMP( mc1->mc_conn, mc2->mc_conn );
+       if ( rc == 0 ) {
+               rc = ber_bvcmp( &mc1->mc_local_ndn, &mc2->mc_local_ndn );
+               if ( rc == 0 ) {
+                       rc = SLAP_PTRCMP( mc1, mc2 );
+               }
+       }
+
+       return rc;
+}
+
 /*
  * meta_back_conn_cmp
  *
@@ -87,13 +117,13 @@ meta_back_conn_cmp(
 }
 
 /*
- * meta_back_dnconn_dup
+ * meta_back_conndn_dup
  *
  * returns -1 in case a duplicate struct metaconn has been inserted;
  * used by avl stuff
  */
 int
-meta_back_dnconn_dup(
+meta_back_conndn_dup(
        void *c1,
        void *c2 )
 {
@@ -190,9 +220,7 @@ metaconn_alloc(
        BER_BVZERO( &mc->mc_local_ndn );
        mc->msc_mscflags = 0;
        mc->mc_authz_target = META_BOUND_NONE;
-       ldap_pvt_thread_mutex_init( &mc->mc_mutex );
        mc->mc_refcnt = 1;
-       mc->mc_tainted = 0;
 
        return mc;
 }
@@ -240,28 +268,7 @@ meta_back_init_one_conn(
         * Already init'ed
         */
        if ( msc->msc_ld != NULL ) {
-               int     doreturn = 1;
-
-               if ( ( mt->mt_idle_timeout != 0 && op->o_time > msc->msc_time + mt->mt_idle_timeout )
-                       || ( mt->mt_conn_ttl != 0 && op->o_time > msc->msc_create_time + mt->mt_conn_ttl ) )
-               {
-                       Debug( LDAP_DEBUG_TRACE,
-                               "%s meta_back_init_one_conn[%d]: idle timeout/ttl.\n",
-                               op->o_log_prefix, candidate, 0 );
-                       if ( meta_back_retry( op, rs, mc, candidate, sendok ) ) {
-                               return rs->sr_err;
-                       }
-
-                       doreturn = 0;
-               }
-
-               if ( mt->mt_idle_timeout != 0 ) {
-                       msc->msc_time = op->o_time;
-               }
-
-               if ( doreturn ) {
-                       return rs->sr_err = LDAP_SUCCESS;
-               }
+               return rs->sr_err = LDAP_SUCCESS;
        }
        
        /*
@@ -455,14 +462,6 @@ error_return:;
                 */
                ( void )rewrite_session_init( mt->mt_rwmap.rwm_rw, op->o_conn );
 
-               if ( mt->mt_idle_timeout ) {
-                       msc->msc_time = op->o_time;
-               }
-
-               if ( mt->mt_conn_ttl ) {
-                       msc->msc_create_time = op->o_time;
-               }
-
        } else {
                rs->sr_err = slap_map_api2result( rs );
                if ( sendok & LDAP_BACK_SENDERR ) {
@@ -475,38 +474,30 @@ error_return:;
 }
 
 /*
- * meta_back_retry_lock
+ * meta_back_retry
  * 
  * Retries one connection
  */
 int
-meta_back_retry_lock(
+meta_back_retry(
        Operation               *op,
        SlapReply               *rs,
-       metaconn_t              *mc,
+       metaconn_t              **mcp,
        int                     candidate,
-       ldap_back_send_t        sendok,
-       int                     dolock )
+       ldap_back_send_t        sendok )
 {
        metainfo_t              *mi = ( metainfo_t * )op->o_bd->be_private;
        metatarget_t            *mt = &mi->mi_targets[ candidate ];
        int                     rc = LDAP_UNAVAILABLE;
+       metaconn_t              *mc = *mcp;
        metasingleconn_t        *msc = &mc->mc_conns[ candidate ];
 
-retry_lock:;
        ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
 
        assert( mc->mc_refcnt > 0 );
-
        if ( mc->mc_refcnt == 1 ) {
                char    buf[ SLAP_TEXT_BUFLEN ];
 
-               while ( dolock && ldap_pvt_thread_mutex_trylock( &mc->mc_mutex ) ) {
-                       ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
-                       ldap_pvt_thread_yield();
-                       goto retry_lock;
-               }
-
                snprintf( buf, sizeof( buf ),
                        "retrying URI=\"%s\" DN=\"%s\"",
                        mt->mt_uri,
@@ -544,13 +535,15 @@ retry_lock:;
                        }
                }
 
-               if ( dolock ) {
-                       ldap_pvt_thread_mutex_unlock( &mc->mc_mutex );
-               }
-       }
+       } else {
+               meta_back_release_conn_lock( op, mc, 0 );
+               *mcp = NULL;
 
-       if ( rc != LDAP_SUCCESS ) {
-               mc->mc_tainted = 1;
+               if ( sendok ) {
+                       rs->sr_err = LDAP_UNAVAILABLE;
+                       rs->sr_text = "unable to retry";
+                       send_ldap_result( op, rs );
+               }
        }
 
        ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
@@ -778,8 +771,11 @@ meta_back_getconn(
 
 
        meta_op_type    op_type = META_OP_REQUIRE_SINGLE;
-       int             parent = 0,
-                       newparent = 0;
+       enum            {
+               META_DNTYPE_ENTRY,
+               META_DNTYPE_PARENT,
+               META_DNTYPE_NEWPARENT
+                       } dn_type = META_DNTYPE_ENTRY;
        struct berval   ndn = op->o_req_ndn,
                        pndn;
 
@@ -810,21 +806,26 @@ meta_back_getconn(
 retry_lock:
                ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
                mc = (metaconn_t *)avl_find( mi->mi_conninfo.lai_tree, 
-                       (caddr_t)&mc_curr, meta_back_dnconn_cmp );
+                       (caddr_t)&mc_curr, meta_back_conndn_cmp );
                if ( mc ) {
-                       if ( mc->mc_tainted ) {
-                               rs->sr_err = LDAP_UNAVAILABLE;
-                               rs->sr_text = "remote server unavailable";
-                               ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
-                               return NULL;
+                       if ( ( mi->mi_conn_ttl != 0 && op->o_time > mc->mc_create_time + mi->mi_conn_ttl )
+                               || ( mi->mi_idle_timeout != 0 && op->o_time > mc->mc_time + mi->mi_idle_timeout ) )
+                       {
+                               /* don't let anyone else use this expired connection */
+                               (void)avl_delete( &mi->mi_conninfo.lai_tree,
+                                       (caddr_t)mc, meta_back_conndnmc_cmp );
+
+                               Debug( LDAP_DEBUG_TRACE, "%s meta_back_getconn: mc=%p conn=%ld expired.\n",
+                                       op->o_log_prefix, (void *)mc, LDAP_BACK_PCONN_ID( mc->mc_conn ) );
                        }
-                       
+
                        /* Don't reuse connections while they're still binding */
                        if ( LDAP_BACK_CONN_BINDING( mc ) ) {
                                ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
                                ldap_pvt_thread_yield();
                                goto retry_lock;
                        }
+
                        mc->mc_refcnt++;
                }
                ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
@@ -834,7 +835,7 @@ retry_lock:
        case LDAP_REQ_ADD:
                /* if we go to selection, the entry must not exist,
                 * and we must be able to resolve the parent */
-               parent = 1;
+               dn_type = META_DNTYPE_PARENT;
                dnParent( &ndn, &pndn );
                break;
 
@@ -842,7 +843,7 @@ retry_lock:
                /* if nnewSuperior is not NULL, it must resolve
                 * to the same candidate as the req_ndn */
                if ( op->orr_nnewSup ) {
-                       newparent = 1;
+                       dn_type = META_DNTYPE_NEWPARENT;
                }
                break;
 
@@ -963,7 +964,7 @@ retry_lock:
                if ( i == META_TARGET_NONE ) {
                        i = meta_back_get_candidate( op, rs, &ndn );
 
-                       if ( rs->sr_err == LDAP_NO_SUCH_OBJECT && parent ) {
+                       if ( rs->sr_err == LDAP_NO_SUCH_OBJECT && dn_type == META_DNTYPE_PARENT ) {
                                i = meta_back_get_candidate( op, rs, &pndn );
                        }
        
@@ -985,7 +986,7 @@ retry_lock:
                        }
                }
 
-               if ( newparent && meta_back_get_candidate( op, rs, op->orr_nnewSup ) != i )
+               if ( dn_type == META_DNTYPE_NEWPARENT && meta_back_get_candidate( op, rs, op->orr_nnewSup ) != i )
                {
                        if ( mc != NULL ) {
                                meta_back_release_conn( op, mc );
@@ -1010,10 +1011,18 @@ retry_lock:
                         * the reason is that the connection might have been
                         * created by meta_back_get_candidate() */
                        if ( !( sendok & LDAP_BACK_BINDING ) ) {
+retry_lock2:;
                                ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
                                mc = (metaconn_t *)avl_find( mi->mi_conninfo.lai_tree, 
-                                       (caddr_t)&mc_curr, meta_back_dnconn_cmp );
+                                       (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 ) ) {
+                                               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 );
@@ -1172,14 +1181,23 @@ done:;
        rs->sr_err = LDAP_SUCCESS;
        rs->sr_text = NULL;
 
+       /* touch the timestamp */
+       if ( mi->mi_idle_timeout != 0 ) {
+               mc->mc_time = op->o_time;
+       }
+
        if ( new_conn ) {
                
+               if ( mi->mi_conn_ttl ) {
+                       mc->mc_create_time = op->o_time;
+               }
+
                /*
                 * Inserts the newly created metaconn in the avl tree
                 */
                ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
                err = avl_insert( &mi->mi_conninfo.lai_tree, ( caddr_t )mc,
-                               meta_back_dnconn_cmp, meta_back_dnconn_dup );
+                               meta_back_conndn_cmp, meta_back_conndn_dup );
 
 #if PRINT_CONNTREE > 0
                myprint( mi->mi_conninfo.lai_tree );
@@ -1225,22 +1243,33 @@ done:;
 }
 
 void
-meta_back_release_conn(
+meta_back_release_conn_lock(
                Operation               *op,
-       metaconn_t              *mc )
+       metaconn_t              *mc,
+       int                     dolock )
 {
        metainfo_t      *mi = ( metainfo_t * )op->o_bd->be_private;
 
        assert( mc != NULL );
 
-       ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
+       if ( dolock ) {
+               ldap_pvt_thread_mutex_lock( &mi->mi_conninfo.lai_mutex );
+       }
        assert( mc->mc_refcnt > 0 );
        mc->mc_refcnt--;
        LDAP_BACK_CONN_BINDING_CLEAR( mc );
-       if ( mc->mc_refcnt == 0 && mc->mc_tainted ) {
-               (void)avl_delete( &mi->mi_conninfo.lai_tree, ( caddr_t )mc,
-                               meta_back_dnconn_cmp );
-               meta_back_conn_free( mc );
+       if ( ( mi->mi_conn_ttl != 0 && op->o_time > mc->mc_create_time + mi->mi_conn_ttl )
+               || ( mi->mi_idle_timeout != 0 && op->o_time > mc->mc_time + mi->mi_idle_timeout ) )
+       {
+               Debug( LDAP_DEBUG_TRACE, "%s meta_back_release_conn: mc=%p conn=%ld expired.\n",
+                       op->o_log_prefix, (void *)mc, LDAP_BACK_PCONN_ID( mc->mc_conn ) );
+               (void)avl_delete( &mi->mi_conninfo.lai_tree,
+                       ( caddr_t )mc, meta_back_conndnmc_cmp );
+               if ( mc->mc_refcnt == 0 ) {
+                       meta_back_conn_free( mc );
+               }
+       }
+       if ( dolock ) {
+               ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
        }
-       ldap_pvt_thread_mutex_unlock( &mi->mi_conninfo.lai_mutex );
 }
index aaeaa3837c2d8522bd38ee85da43e28f8b1be7d7..d9461ac4e4d16aea618571e337c77235e5e42b2b 100644 (file)
@@ -68,9 +68,10 @@ retry:;
                        mdn.bv_val, op->o_ctrls, NULL, &msgid );
        if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
                do_retry = 0;
-               if ( meta_back_retry( op, rs, mc, candidate, LDAP_BACK_SENDERR ) ) {
+               if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
                        goto retry;
                }
+               goto cleanup;
 
        } else if ( rs->sr_err == LDAP_SUCCESS ) {
                struct timeval  tv, *tvp = NULL;
@@ -128,7 +129,9 @@ cleanup:;
        }
        
 done:;
-       meta_back_release_conn( op, mc );
+       if ( mc ) {
+               meta_back_release_conn( op, mc );
+       }
 
        return rs->sr_err;
 }
index 3697f41fd014c27bc8219195527b6261e760a778..a4962515d32293af52dce399cfa4bcb03b84bde4 100644 (file)
@@ -164,7 +164,6 @@ meta_back_conn_free(
                (void)meta_clear_one_candidate( &mc->mc_conns[ i ] );
        }
 
-       ldap_pvt_thread_mutex_destroy( &mc->mc_mutex );
        free( mc );
 }
 
index 20f04e28c2eaff4f108fe3542e931639bb3fc449..c17af5e928c675583d8805229255a9a499371025 100644 (file)
@@ -179,9 +179,10 @@ retry:;
                        modv, op->o_ctrls, NULL, &msgid );
        if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
                do_retry = 0;
-               if ( meta_back_retry( op, rs, mc, candidate, LDAP_BACK_SENDERR ) ) {
+               if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
                        goto retry;
                }
+               goto done;
 
        } else if ( rs->sr_err == LDAP_SUCCESS ) {
                struct timeval  tv, *tvp = NULL;
@@ -226,6 +227,14 @@ retry:;
        }
 
 cleanup:;
+       if ( maperr ) {
+               rc = meta_back_op_result( mc, op, rs, candidate );
+
+       } else {
+               send_ldap_result( op, rs );
+       }
+
+done:;
        if ( mdn.bv_val != op->o_req_dn.bv_val ) {
                free( mdn.bv_val );
                BER_BVZERO( &mdn );
@@ -238,15 +247,10 @@ cleanup:;
        free( mods );
        free( modv );
 
-       if ( maperr ) {
-               rc = meta_back_op_result( mc, op, rs, candidate );
-
-       } else {
-               send_ldap_result( op, rs );
+       if ( mc ) {
+               meta_back_release_conn( op, mc );
        }
 
-       meta_back_release_conn( op, mc );
-
        return rs->sr_err;
 }
 
index 6536cab579636ae0b04d69e6784be65e94f22e30..a490553b64762317e15abd0d0a816eb3b936d4d2 100644 (file)
@@ -111,9 +111,10 @@ retry:;
                        op->o_ctrls, NULL, &msgid );
        if ( rs->sr_err == LDAP_UNAVAILABLE && do_retry ) {
                do_retry = 0;
-               if ( meta_back_retry( op, rs, mc, candidate, LDAP_BACK_SENDERR ) ) {
+               if ( meta_back_retry( op, rs, &mc, candidate, LDAP_BACK_SENDERR ) ) {
                        goto retry;
                }
+               goto done;
 
        } else if ( rs->sr_err == LDAP_SUCCESS ) {
                struct timeval  tv, *tvp = NULL;
@@ -157,6 +158,14 @@ retry:;
        }
 
 cleanup:;
+       if ( maperr ) {
+               meta_back_op_result( mc, op, rs, candidate );
+
+       } else {
+               send_ldap_result( op, rs );
+       }
+
+done:;
        if ( mdn.bv_val != op->o_req_dn.bv_val ) {
                free( mdn.bv_val );
                BER_BVZERO( &mdn );
@@ -169,15 +178,10 @@ cleanup:;
                BER_BVZERO( &mnewSuperior );
        }
 
-       if ( maperr ) {
-               meta_back_op_result( mc, op, rs, candidate );
-
-       } else {
-               send_ldap_result( op, rs );
+       if ( mc ) {
+               meta_back_release_conn( op, mc );
        }
 
-       meta_back_release_conn( op, mc );
-
        return rs->sr_err;
 }
 
index 729db9cd73e227c44fb36e881711cdf2955486a9..00cd89f1f47c2404f55e628f868862cbc9c7b974 100644 (file)
@@ -416,7 +416,7 @@ really_bad:;
                                if ( candidates[ i ].sr_type == REP_INTERMEDIATE ) {
                                        candidates[ i ].sr_type = REP_RESULT;
 
-                                       if ( meta_back_retry( op, rs, mc, i, LDAP_BACK_DONTSEND ) ) {
+                                       if ( meta_back_retry( op, rs, &mc, i, LDAP_BACK_DONTSEND ) ) {
                                                switch ( meta_back_search_start( op, rs, &dc, msc, i, candidates ) )
                                                {
                                                case META_SEARCH_CANDIDATE:
@@ -427,6 +427,12 @@ really_bad:;
                                                        goto finish;
                                                }
                                        }
+
+                                       savepriv = op->o_private;
+                                       op->o_private = (void *)i;
+                                       send_ldap_result( op, rs );
+                                       op->o_private = savepriv;
+                                       goto finish;
                                }
 
                                /*
@@ -888,7 +894,9 @@ finish:;
                }
        }
 
-       meta_back_release_conn( op, mc );
+       if ( mc ) {
+               meta_back_release_conn( op, mc );
+       }
 
        return rs->sr_err;
 }