]> git.sur5r.net Git - openldap/commitdiff
ITS#5728 release entries before send_ldap_ber()
authorHoward Chu <hyc@openldap.org>
Tue, 7 Oct 2008 00:40:52 +0000 (00:40 +0000)
committerHoward Chu <hyc@openldap.org>
Tue, 7 Oct 2008 00:40:52 +0000 (00:40 +0000)
servers/slapd/back-bdb/back-bdb.h
servers/slapd/back-bdb/id2entry.c
servers/slapd/back-bdb/search.c

index 4a22fa00ddfa2a7df4890c5f56a5960f956e4ee0..ba0c477f701af85103c993a217372abc6fcafb7c 100644 (file)
@@ -212,18 +212,22 @@ struct bdb_info {
 
 struct bdb_lock_info {
        struct bdb_lock_info *bli_next;
-       ID              bli_id;
        DB_LOCK bli_lock;
+       ID              bli_id;
+       int             bli_flag;
 };
+#define        BLI_DONTFREE    1
 
 struct bdb_op_info {
        BackendDB*      boi_bdb;
        DB_TXN*         boi_txn;
+       struct bdb_lock_info *boi_locks;        /* used when no txn */
        u_int32_t       boi_err;
        u_int32_t       boi_locker;
-       int             boi_acl_cache;
-       struct bdb_lock_info *boi_locks;        /* used when no txn */
+       char            boi_acl_cache;
+       char            boi_flag;
 };
+#define        BOI_DONTFREE    1
 
 #define        DB_OPEN(db, file, name, type, flags, mode) \
        ((db)->open)(db, file, name, type, flags, mode)
index 7a964bf6c2d7d164aa2d2e141b8d18d24db98fd1..88f2cfabbe0d3b7ae4485d8fd5590a2f47131585 100644 (file)
@@ -271,12 +271,17 @@ int bdb_entry_release(
                                        bdb_cache_return_entry_rw( bdb->bi_dbenv, &bdb->bi_cache,
                                                e, rw, &bli->bli_lock );
                                        prev->bli_next = bli->bli_next;
-                                       op->o_tmpfree( bli, op->o_tmpmemctx );
+                                       /* Cleanup, or let caller know we unlocked */
+                                       if (bli->bli_flag & BLI_DONTFREE)
+                                               bli->bli_flag = 0;
+                                       else
+                                               op->o_tmpfree( bli, op->o_tmpmemctx );
                                        break;
                                }
                        }
                        if ( !boi->boi_locks ) {
-                               op->o_tmpfree( boi, op->o_tmpmemctx );
+                               if ( !(boi->boi_flag & BOI_DONTFREE))
+                                       op->o_tmpfree( boi, op->o_tmpmemctx );
                                op->o_private = NULL;
                        }
                }
index c11439ef606683672e95b9f6e68470aeec02b295..19393c526135b3fc8a041edd9bf2cf939c451732 100644 (file)
@@ -837,6 +837,14 @@ fetch_entry_retry:
                                op->oq_search.rs_scope == LDAP_SCOPE_ONELEVEL
                                        ? LDAP_SCOPE_BASE : LDAP_SCOPE_SUBTREE );
 
+                       /* free reader lock */
+#ifdef SLAP_ZONE_ALLOC
+                       slap_zn_runlock(bdb->bi_cache.c_zctx, e);
+#endif
+                       bdb_cache_return_entry_r( bdb->bi_dbenv,
+                               &bdb->bi_cache, e , &lock );
+                       e = NULL;
+
                        send_search_reference( op, rs );
 
                        ber_bvarray_free( rs->sr_ref );
@@ -870,14 +878,55 @@ fetch_entry_retry:
                        }
 
                        if (e) {
+                               struct bdb_op_info bois, *boi2;
+                               struct bdb_lock_info blis;
+
+                               /* Must set lockinfo so that entry_release will work */
+                               if (!opinfo) {
+                                       boi2 = &bois;
+                                       op->o_private = boi2;
+                                       bois.boi_bdb = op->o_bd;
+                                       bois.boi_txn = NULL;
+                                       bois.boi_locker = locker;
+                                       bois.boi_err = 0;
+                                       bois.boi_locks = &blis;
+                                       blis.bli_next = NULL;
+                                       bois.boi_flag = BOI_DONTFREE;
+                               } else {
+                                       boi2 = opinfo;
+                                       blis.bli_next = boi2->boi_locks;
+                                       boi2->boi_locks = &blis;
+                               }
+                               blis.bli_id = e->e_id;
+                               blis.bli_lock = lock;
+                               blis.bli_flag = BLI_DONTFREE;
+
                                /* safe default */
                                rs->sr_attrs = op->oq_search.rs_attrs;
                                rs->sr_operational_attrs = NULL;
                                rs->sr_ctrls = NULL;
-                               rs->sr_flags = 0;
+                               rs->sr_flags = REP_ENTRY_MUSTRELEASE;
                                rs->sr_err = LDAP_SUCCESS;
                                rs->sr_err = send_search_entry( op, rs );
 
+                               /* send_search_entry will usually free it.
+                                * an overlay might leave its own copy here;
+                                * bli_flag will be 0 if lock was already released.
+                                */
+                               if ( blis.bli_flag ) {
+#ifdef SLAP_ZONE_ALLOC
+                                       slap_zn_runlock(bdb->bi_cache.c_zctx, e);
+#endif
+                                       bdb_cache_return_entry_r(bdb->bi_dbenv,
+                                               &bdb->bi_cache, e, &lock);
+                                       op->o_private = opinfo;
+                                       if ( opinfo ) {
+                                               opinfo->boi_locks = blis.bli_next;
+                                       }
+                               }
+                               rs->sr_entry = NULL;
+                               e = NULL;
+
                                switch ( rs->sr_err ) {
                                case LDAP_SUCCESS:      /* entry sent ok */
                                        break;
@@ -885,13 +934,6 @@ fetch_entry_retry:
                                        break;
                                case LDAP_UNAVAILABLE:
                                case LDAP_SIZELIMIT_EXCEEDED:
-#ifdef SLAP_ZONE_ALLOC
-                                       slap_zn_runlock(bdb->bi_cache.c_zctx, e);
-#endif
-                                       bdb_cache_return_entry_r(bdb->bi_dbenv,
-                                               &bdb->bi_cache, e, &lock);
-                                       e = NULL;
-                                       rs->sr_entry = NULL;
                                        if ( rs->sr_err == LDAP_SIZELIMIT_EXCEEDED ) {
                                                rs->sr_ref = rs->sr_v2ref;
                                                send_ldap_result( op, rs );