]> git.sur5r.net Git - openldap/commitdiff
actually, if a connection is already in the AVL tree, use it if not binding; otherwis...
authorPierangelo Masarati <ando@openldap.org>
Fri, 7 Apr 2006 01:28:56 +0000 (01:28 +0000)
committerPierangelo Masarati <ando@openldap.org>
Fri, 7 Apr 2006 01:28:56 +0000 (01:28 +0000)
servers/slapd/back-ldap/back-ldap.h
servers/slapd/back-ldap/bind.c
servers/slapd/back-meta/back-meta.h
servers/slapd/back-meta/bind.c
servers/slapd/back-meta/conn.c

index f6c25b2496b8af314de41ca64f2e0984c5261eb0..8a19a72c05412c7cab3cae046128426b4b89d26d 100644 (file)
@@ -60,6 +60,7 @@ typedef struct ldapconn_t {
 #define        LDAP_BACK_FCONN_ISPRIV  (0x04)
 #define        LDAP_BACK_FCONN_ISTLS   (0x08)
 #define        LDAP_BACK_FCONN_BINDING (0x10)
+#define        LDAP_BACK_FCONN_TAINTED (0x20)
 
 #define        LDAP_BACK_CONN_ISBOUND(lc)              LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_ISBOUND)
 #define        LDAP_BACK_CONN_ISBOUND_SET(lc)          LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_ISBOUND)
@@ -80,6 +81,9 @@ typedef struct ldapconn_t {
 #define        LDAP_BACK_CONN_BINDING(lc)              LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_BINDING)
 #define        LDAP_BACK_CONN_BINDING_SET(lc)          LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_BINDING)
 #define        LDAP_BACK_CONN_BINDING_CLEAR(lc)        LDAP_BACK_CONN_CLEAR((lc), LDAP_BACK_FCONN_BINDING)
+#define        LDAP_BACK_CONN_TAINTED(lc)              LDAP_BACK_CONN_ISSET((lc), LDAP_BACK_FCONN_TAINTED)
+#define        LDAP_BACK_CONN_TAINTED_SET(lc)          LDAP_BACK_CONN_SET((lc), LDAP_BACK_FCONN_TAINTED)
+#define        LDAP_BACK_CONN_TAINTED_CLEAR(lc)        LDAP_BACK_CONN_CLEAR((lc), LDAP_BACK_FCONN_TAINTED)
 
        unsigned                lc_refcnt;
        unsigned                lc_binding;
index dab6c56b75ebbe67782dc1ee33e4e8e4d16cc1c9..cc497ff04c8b0ed0c06f543981eb85f81a41ce5b 100644 (file)
@@ -654,12 +654,26 @@ retry_lock:
                        (void *)lc, refcnt, binding );
        
                /* Err could be -1 in case a duplicate ldapconn is inserted */
-               if ( rs->sr_err != 0 ) {
+               switch ( rs->sr_err ) {
+               case 0:
+                       break;
+
+               case -1:
+                       if ( !( sendok & LDAP_BACK_BINDING ) ) {
+                               /* duplicate: free and try to get the newly created one */
+                               goto retry_lock;
+                       }
+                       /* taint connection, so that it'll be freed when released */
+                       LDAP_BACK_CONN_TAINTED_SET( lc );
+                       break;
+
+               default:
                        ldap_back_conn_free( lc );
                        rs->sr_err = LDAP_OTHER;
+                       rs->sr_text = "proxy bind collision";
                        if ( op->o_conn && ( sendok & LDAP_BACK_SENDERR ) ) {
-                               send_ldap_error( op, rs, LDAP_OTHER,
-                                       "internal server error" );
+                               send_ldap_result( op, rs );
+                               rs->sr_text = NULL;
                        }
                        return NULL;
                }
@@ -679,6 +693,7 @@ retry_lock:
                        (void *)avl_delete( &li->li_conninfo.lai_tree, (caddr_t)lc,
                                        ldap_back_conndnlc_cmp );
                        ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
+                       LDAP_BACK_CONN_TAINTED_SET( lc );
                }
 
                if ( LogTest( LDAP_DEBUG_TRACE ) ) {
@@ -688,7 +703,6 @@ retry_lock:
                        Debug( LDAP_DEBUG_TRACE,
                                "=>ldap_back_getconn: %s.\n", buf, 0, 0 );
                }
-       
        }
 
        if ( li->li_idle_timeout && lc ) {
@@ -712,8 +726,10 @@ ldap_back_release_conn_lock(
                ldap_pvt_thread_mutex_lock( &li->li_conninfo.lai_mutex );
        }
        assert( lc->lc_refcnt > 0 );
-       lc->lc_refcnt--;
        LDAP_BACK_CONN_BINDING_CLEAR( lc );
+       if ( --lc->lc_refcnt == 0 && LDAP_BACK_CONN_TAINTED( lc ) ) {
+               ldap_back_freeconn( op, rs, 0 );
+       }
        if ( dolock ) {
                ldap_pvt_thread_mutex_unlock( &li->li_conninfo.lai_mutex );
        }
index 9d6eba8ab8f216b0dac353d7146f1b950646d8d6..cfb7790d81236d2b2b9700e368ad37acb7900cd8 100644 (file)
@@ -293,9 +293,8 @@ extern void
 meta_back_release_conn_lock(
                Operation               *op,
        metaconn_t              *mc,
-       int                     dofree,
        int                     dolock );
-#define meta_back_release_conn(op, mc) meta_back_release_conn_lock( (op), (mc), 0, 1 )
+#define meta_back_release_conn(op, mc) meta_back_release_conn_lock( (op), (mc), 1 )
 
 extern int
 meta_back_retry(
index 43f82973782011221749b4faa1922405b8a2c3a9..6a915f9efa03040a8f95896930bcfbafbca94d3e 100644 (file)
@@ -616,7 +616,8 @@ done:;
        rs->sr_err = rc;
        if ( rc != LDAP_SUCCESS && META_BACK_ONERR_STOP( mi ) ) {
                LDAP_BACK_CONN_BINDING_CLEAR( msc );
-               meta_back_release_conn_lock( op, mc, 1, dolock );
+               LDAP_BACK_CONN_TAINTED_SET( mc );
+               meta_back_release_conn_lock( op, mc, dolock );
                *mcp = NULL;
 
                if ( sendok & LDAP_BACK_SENDERR ) {
index 657881ca50df5126f4ea764f57585ada0420f4cd..36d85be07f056e587ac96ff2805ff04328ecd8f2 100644 (file)
@@ -531,7 +531,8 @@ meta_back_retry(
                        if ( binding ) {
                                LDAP_BACK_CONN_BINDING_CLEAR( msc );
                        }
-                       meta_back_release_conn_lock( op, mc, 1, 0 );
+                       LDAP_BACK_CONN_TAINTED_SET( mc );
+                       meta_back_release_conn_lock( op, mc, 0 );
                        *mcp = NULL;
                }
 
@@ -810,6 +811,7 @@ retry_lock:
                                /* don't let anyone else use this expired connection */
                                (void)avl_delete( &mi->mi_conninfo.lai_tree,
                                        (caddr_t)mc, meta_back_conndnmc_cmp );
+                               LDAP_BACK_CONN_TAINTED_SET( mc );
 
                                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 ) );
@@ -1183,7 +1185,6 @@ done:;
        }
 
        if ( new_conn ) {
-               
                if ( mi->mi_conn_ttl ) {
                        mc->mc_create_time = op->o_time;
                }
@@ -1203,19 +1204,29 @@ done:;
 
                /*
                 * Err could be -1 in case a duplicate metaconn is inserted
-                *
-                * FIXME: what if the same client issues more than one
-                * asynchronous operations?
                 */
-               if ( err != 0 ) {
+               switch ( err ) {
+               case 0:
+                       break;
+
+               case -1:
+                       if ( !( sendok & LDAP_BACK_BINDING ) ) {
+                               /* duplicate: free and try to get the newly created one */
+                               goto retry_lock;
+                       }
+                       LDAP_BACK_CONN_TAINTED_SET( mc );
+                       break;
+
+               default:
                        Debug( LDAP_DEBUG_ANY,
                                "%s meta_back_getconn: candidates=%d conn=%ld insert failed\n",
                                op->o_log_prefix, ncandidates,
                                LDAP_BACK_PCONN_ID( mc->mc_conn ) );
                
-                       rs->sr_err = LDAP_OTHER;
-                       rs->sr_text = "Internal server error";
                        meta_back_freeconn( op, mc );
+
+                       rs->sr_err = LDAP_OTHER;
+                       rs->sr_text = "proxy bind collision";
                        if ( sendok & LDAP_BACK_SENDERR ) {
                                send_ldap_result( op, rs );
                                rs->sr_text = NULL;
@@ -1242,7 +1253,6 @@ void
 meta_back_release_conn_lock(
                Operation               *op,
        metaconn_t              *mc,
-       int                     dofree,
        int                     dolock )
 {
        metainfo_t      *mi = ( metainfo_t * )op->o_bd->be_private;
@@ -1255,10 +1265,7 @@ meta_back_release_conn_lock(
        assert( mc->mc_refcnt > 0 );
        mc->mc_refcnt--;
        LDAP_BACK_CONN_BINDING_CLEAR( mc );
-       if ( dofree
-               || ( 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 ) )
-       {
+       if ( LDAP_BACK_CONN_TAINTED( mc ) ) {
                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,