]> git.sur5r.net Git - openldap/commitdiff
seems to definitely fix issues related to ITS#3808
authorPierangelo Masarati <ando@openldap.org>
Wed, 29 Jun 2005 16:38:09 +0000 (16:38 +0000)
committerPierangelo Masarati <ando@openldap.org>
Wed, 29 Jun 2005 16:38:09 +0000 (16:38 +0000)
13 files changed:
servers/slapd/back-ldap/add.c
servers/slapd/back-ldap/back-ldap.h
servers/slapd/back-ldap/bind.c
servers/slapd/back-ldap/compare.c
servers/slapd/back-ldap/config.c
servers/slapd/back-ldap/delete.c
servers/slapd/back-ldap/extended.c
servers/slapd/back-ldap/init.c
servers/slapd/back-ldap/modify.c
servers/slapd/back-ldap/modrdn.c
servers/slapd/back-ldap/proto-ldap.h
servers/slapd/back-ldap/search.c
servers/slapd/back-ldap/unbind.c

index eb272c76628fa067c9f8f489fc96d056725be588..e27e6a0255b8e9b5b57055f5a7d908f4c87e016d 100644 (file)
@@ -54,6 +54,7 @@ ldap_back_add(
 
        lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
        if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
+               lc = NULL;
                goto cleanup;
        }
 
@@ -116,6 +117,10 @@ cleanup:
                ch_free( attrs );
        }
 
+       if ( lc ) {
+               ldap_back_release_conn( op, rs, lc );
+       }
+
        Debug( LDAP_DEBUG_ARGS, "<== ldap_back_add(\"%s\"): %d\n",
                        op->o_req_dn.bv_val, rs->sr_err, 0 );
 
index 79b5d8e8e58383429dc844b463a984b6bbb4c82e..ba965d5d853dc7d94e54fc11f23f2fffe98d3fd8 100644 (file)
@@ -39,6 +39,7 @@ struct ldapconn {
        int                     lc_bound;
        int                     lc_ispriv;
        ldap_pvt_thread_mutex_t lc_mutex;
+       unsigned                lc_refcnt;
 };
 
 /*
index 65de40ae644289ef35d0e456bd0cdb9d8e37d20f..93aa6abe32e74d86a474d4a1b424f75b6e21c49e 100644 (file)
@@ -101,31 +101,38 @@ done:;
 
        /* must re-insert if local DN changed as result of bind */
        if ( lc->lc_bound && !dn_match( &op->o_req_ndn, &lc->lc_local_ndn ) ) {
-               struct ldapconn *tmplc;
                int             lerr;
 
                ldap_pvt_thread_mutex_lock( &li->conn_mutex );
-               tmplc = avl_delete( &li->conntree, (caddr_t)lc,
+               /* wait for all other ops to release the connection */
+               while ( lc->lc_refcnt > 1 ) {
+                       ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
+                       ldap_pvt_thread_yield();
+                       ldap_pvt_thread_mutex_lock( &li->conn_mutex );
+               }
+               assert( lc->lc_refcnt == 1 );
+               lc = avl_delete( &li->conntree, (caddr_t)lc,
                                ldap_back_conn_cmp );
-               if ( tmplc != NULL ) {
-                       if ( !BER_BVISNULL( &lc->lc_local_ndn ) ) {
-                               ch_free( lc->lc_local_ndn.bv_val );
-                       }
-                       ber_dupbv( &lc->lc_local_ndn, &op->o_req_ndn );
-                       lerr = avl_insert( &li->conntree, (caddr_t)lc,
-                               ldap_back_conn_cmp, ldap_back_conn_dup );
+               assert( lc != NULL );
 
-               } else {
-                       /* something BAD happened */
-                       lerr = -1;
-                       rc = LDAP_OTHER;
+               if ( !BER_BVISNULL( &lc->lc_local_ndn ) ) {
+                       ch_free( lc->lc_local_ndn.bv_val );
                }
+               ber_dupbv( &lc->lc_local_ndn, &op->o_req_ndn );
+               lerr = avl_insert( &li->conntree, (caddr_t)lc,
+                       ldap_back_conn_cmp, ldap_back_conn_dup );
                ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
                if ( lerr == -1 ) {
+                       /* handle this! (e.g. wait until refcnt goes to 1...) */
                        ldap_back_conn_free( lc );
+                       lc = NULL;
                }
        }
 
+       if ( lc != NULL ) {
+               ldap_back_release_conn( op, rs, lc );
+       }
+
        return( rc );
 }
 
@@ -223,13 +230,12 @@ ldap_back_freeconn( Operation *op, struct ldapconn *lc )
        int             rc = 0;
 
        ldap_pvt_thread_mutex_lock( &li->conn_mutex );
-       lc = avl_delete( &li->conntree, (caddr_t)lc,
-                       ldap_back_conn_cmp );
-       if ( lc == NULL ) {
-               /* something BAD happened */
-               rc = -1;
+       assert( lc->lc_refcnt > 0 );
+       if ( --lc->lc_refcnt == 0 ) {
+               lc = avl_delete( &li->conntree, (caddr_t)lc,
+                               ldap_back_conn_cmp );
+               assert( lc != NULL );
 
-       } else {
                ldap_back_conn_free( (void *)lc );
        }
        ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
@@ -358,6 +364,7 @@ retry:;
                memset( *lcp, 0, sizeof( struct ldapconn ) );
        }
        (*lcp)->lc_ld = ld;
+       (*lcp)->lc_refcnt = 1;
 
 error_return:;
        if ( rs->sr_err != LDAP_SUCCESS ) {
@@ -407,10 +414,13 @@ ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok )
        ldap_pvt_thread_mutex_lock( &li->conn_mutex );
        lc = (struct ldapconn *)avl_find( li->conntree, 
                        (caddr_t)&lc_curr, ldap_back_conn_cmp );
+       if ( lc != NULL ) {
+               lc->lc_refcnt++;
+       }
        ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
 
        /* Looks like we didn't get a bind. Open a new session... */
-       if ( !lc ) {
+       if ( lc == NULL ) {
                /* lc here must be NULL */
                if ( ldap_back_prepare_conn( &lc, op, rs, sendok ) != LDAP_SUCCESS ) {
                        return NULL;
@@ -440,6 +450,7 @@ ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok )
 
                /* Inserts the newly created ldapconn in the avl tree */
                ldap_pvt_thread_mutex_lock( &li->conn_mutex );
+               assert( lc->lc_refcnt == 1 );
                rs->sr_err = avl_insert( &li->conntree, (caddr_t)lc,
                        ldap_back_conn_cmp, ldap_back_conn_dup );
 
@@ -450,7 +461,8 @@ ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok )
                ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
 
                Debug( LDAP_DEBUG_TRACE,
-                       "=>ldap_back_getconn: conn %p inserted\n", (void *) lc, 0, 0 );
+                       "=>ldap_back_getconn: conn %p inserted (refcnt=%u)\n",
+                       (void *)lc, lc->lc_refcnt, 0 );
        
                /* Err could be -1 in case a duplicate ldapconn is inserted */
                if ( rs->sr_err != 0 ) {
@@ -464,12 +476,27 @@ ldap_back_getconn( Operation *op, SlapReply *rs, ldap_back_send_t sendok )
                }
        } else {
                Debug( LDAP_DEBUG_TRACE,
-                       "=>ldap_back_getconn: conn %p fetched\n", (void *) lc, 0, 0 );
+                       "=>ldap_back_getconn: conn %p fetched (refcnt=%u)\n",
+                       (void *)lc, lc->lc_refcnt, 0 );
        }
        
        return lc;
 }
 
+void
+ldap_back_release_conn(
+       Operation               *op,
+       SlapReply               *rs,
+       struct ldapconn         *lc )
+{
+       struct ldapinfo *li = (struct ldapinfo *)op->o_bd->be_private;
+       
+       ldap_pvt_thread_mutex_lock( &li->conn_mutex );
+       assert( lc->lc_refcnt > 0 );
+       lc->lc_refcnt--;
+       ldap_pvt_thread_mutex_unlock( &li->conn_mutex );
+}
+
 /*
  * ldap_back_dobind
  *
index a538e3d4b27cb9ea94822dcd77c7463f1ea161a6..44628d98b4c4486df1eefc9124bad6e8e1daa400 100644 (file)
@@ -44,6 +44,7 @@ ldap_back_compare(
 
        lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
        if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
+               lc = NULL;
                goto cleanup;
        }
 
@@ -70,5 +71,9 @@ retry:
 cleanup:
        (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
        
+       if ( lc != NULL ) {
+               ldap_back_release_conn( op, rs, lc );
+       }
+
        return rs->sr_err;
 }
index d01b8a825e85fd21d6dfaa1905903be4aedea7ec..27876cbfecf8001349479edeeec074ae36519c1c 100644 (file)
@@ -1573,6 +1573,11 @@ retry:
                if (rs->sr_err != LDAP_SUCCESS) {
                        rs->sr_err = slap_map_api2result( rs );
                }
+
+               if ( lc != NULL ) {
+                       ldap_back_release_conn( &op2, rs, lc );
+               }
+
        } else {
        /* else just do the same as before */
                bv = (struct berval *) ch_malloc( sizeof(struct berval) );
index 3d6575be57c9153453c57d0a167635f690c72627..08c970388e975f21a5588bf117d3770f2f0a0754 100644 (file)
@@ -45,8 +45,7 @@ ldap_back_delete(
        lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
        
        if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
-               rc = -1;
-               goto cleanup;
+               return -1;
        }
 
        ctrls = op->o_ctrls;
@@ -71,5 +70,9 @@ retry:
 cleanup:
        (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
 
+       if ( lc != NULL ) {
+               ldap_back_release_conn( op, rs, lc );
+       }
+
        return rc;
 }
index 8fb7e44a53955b55048d6d586d52692b0acb0e87..070466ae0355ec1f3059dcfd83af98c6e37f1188 100644 (file)
@@ -68,7 +68,8 @@ ldap_back_extended(
                                op->o_ctrls = oldctrls;
                                send_ldap_result( op, rs );
                                rs->sr_text = NULL;
-                               return rs->sr_err;
+                               rc = rs->sr_err;
+                               goto done;
                        }
 
                        rc = ( *exop_table[i].extended )( op, rs );
@@ -79,6 +80,11 @@ ldap_back_extended(
                        }
                        op->o_ctrls = oldctrls;
 
+done:;
+                       if ( lc != NULL ) {
+                               ldap_back_release_conn( op, rs, lc );
+                       }
+                       
                        return rc;
                }
        }
@@ -170,5 +176,9 @@ retry:
                rc = -1;
        }
 
+       if ( lc != NULL ) {
+               ldap_back_release_conn( op, rs, lc );
+       }
+
        return rc;
 }
index 1b8fb45139bdf32d11f8f53cbcdc4e3fc39ee48c..b572c36936b73c214ec4970cb00382d7d0b85617 100644 (file)
@@ -202,8 +202,10 @@ void
 ldap_back_conn_free( void *v_lc )
 {
        struct ldapconn *lc = v_lc;
-       
-       ldap_unbind_ext_s( lc->lc_ld, NULL, NULL );
+
+       if ( lc->lc_ld != NULL ) {      
+               ldap_unbind_ext_s( lc->lc_ld, NULL, NULL );
+       }
        if ( !BER_BVISNULL( &lc->lc_bound_ndn ) ) {
                ch_free( lc->lc_bound_ndn.bv_val );
        }
index 0936bb4e0f75463795e24873309a31964bddb411..5acd9a1aae6126862cb5e3bf9ae579b5903f8f79 100644 (file)
@@ -122,6 +122,10 @@ cleanup:;
        }
        ch_free( modv );
 
+       if ( lc != NULL ) {
+               ldap_back_release_conn( op, rs, lc );
+       }
+
        return rc;
 }
 
index 22554b24307742c3912b2d388bfc86832eb89d4e..437ba646e752f16fc0e6caa22d4338ac1174c69d 100644 (file)
@@ -45,7 +45,7 @@ ldap_back_modrdn(
 
        lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
        if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
-               return( -1 );
+               return -1;
        }
 
        if ( op->orr_newSup ) {
@@ -78,6 +78,10 @@ retry:
 cleanup:
        (void)ldap_back_proxy_authz_ctrl_free( op, &ctrls );
 
+       if ( lc != NULL ) {
+               ldap_back_release_conn( op, rs, lc );
+       }
+
        return rc;
 }
 
index 8c85f507f414e1a8d1f44ba4876820f8c6412377..5f29e710a3f5299e9902211e07e0597b5364002a 100644 (file)
@@ -50,6 +50,7 @@ extern BI_entry_get_rw                ldap_back_entry_get;
 
 int ldap_back_freeconn( Operation *op, struct ldapconn *lc );
 struct ldapconn *ldap_back_getconn(struct slap_op *op, struct slap_rep *rs, ldap_back_send_t sendok);
+void ldap_back_release_conn( struct slap_op *op, struct slap_rep *rs, struct ldapconn *lc );
 int ldap_back_dobind(struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok);
 int ldap_back_retry(struct ldapconn *lc, Operation *op, SlapReply *rs, ldap_back_send_t sendok);
 int ldap_back_map_result(SlapReply *rs);
index d7fb4a8afb583bb328fd21076ef34d040409be4c..307e2dbfd6af0354ad927a79e6fe93e00d686b9d 100644 (file)
@@ -157,7 +157,7 @@ ldap_back_search(
        LDAPControl     **ctrls = NULL;
 
        lc = ldap_back_getconn( op, rs, LDAP_BACK_SENDERR );
-       if ( !lc ) {
+       if ( !lc || !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
                return rs->sr_err;
        }
 
@@ -165,9 +165,6 @@ ldap_back_search(
         * FIXME: in case of values return filter, we might want
         * to map attrs and maybe rewrite value
         */
-       if ( !ldap_back_dobind( lc, op, rs, LDAP_BACK_SENDERR ) ) {
-               return rs->sr_err;
-       }
 
        /* should we check return values? */
        if ( op->ors_deref != -1 ) {
@@ -441,6 +438,10 @@ finish:;
                ch_free( attrs );
        }
 
+       if ( lc != NULL ) {
+               ldap_back_release_conn( op, rs, lc );
+       }
+
        return rc;
 }
 
@@ -722,6 +723,10 @@ cleanup:
                ch_free( filter );
        }
 
+       if ( lc != NULL ) {
+               ldap_back_release_conn( op, &rs, lc );
+       }
+
        return rc;
 }
 
index e93dba2c89035feab94fad81b9b1507f2ac005cb..c35d2834c295b0bdfbca6fe0fa328c3e99340d89 100644 (file)
@@ -53,8 +53,10 @@ ldap_back_conn_destroy(
 
        if ( lc ) {
                Debug( LDAP_DEBUG_TRACE,
-                       "=>ldap_back_conn_destroy: destroying conn %ld\n",
-                       lc->lc_conn->c_connid, 0, 0 );
+                       "=>ldap_back_conn_destroy: destroying conn %ld (refcnt=%u)\n",
+                       lc->lc_conn->c_connid, lc->lc_refcnt, 0 );
+
+               assert( lc->lc_refcnt == 0 );
 
                /*
                 * Needs a test because the handler may be corrupted,