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 {
OpExtra boi_oe;
DB_TXN* boi_txn;
- u_int32_t boi_err;
- int boi_acl_cache;
struct bdb_lock_info *boi_locks; /* used when no txn */
+ u_int32_t boi_err;
+ 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)
if ( bli->bli_id == e->e_id ) {
bdb_cache_return_entry_rw( bdb, 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 ) {
LDAP_SLIST_REMOVE( &op->o_extra, &boi->boi_oe, OpExtra, oe_next );
- op->o_tmpfree( boi, op->o_tmpmemctx );
+ if ( !(boi->boi_flag & BOI_DONTFREE))
+ op->o_tmpfree( boi, op->o_tmpmemctx );
}
}
} else {
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, e, &lock );
+ e = NULL;
+
send_search_reference( op, rs );
ber_bvarray_free( rs->sr_ref );
}
if (e) {
+ struct bdb_op_info bois;
+ struct bdb_lock_info blis;
+
+ /* Must set lockinfo so that entry_release will work */
+ if (!opinfo) {
+ bois.boi_oe.oe_key = bdb;
+ bois.boi_txn = NULL;
+ bois.boi_err = 0;
+ bois.boi_acl_cache = op->o_do_not_cache;
+ bois.boi_flag = BOI_DONTFREE;
+ bois.boi_locks = &blis;
+ blis.bli_next = NULL;
+ LDAP_SLIST_INSERT_HEAD( &op->o_extra, &bois.boi_oe,
+ oe_next );
+ } else {
+ blis.bli_next = opinfo->boi_locks;
+ opinfo->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, e, &lock);
+ if ( opinfo ) {
+ opinfo->boi_locks = blis.bli_next;
+ } else {
+ LDAP_SLIST_REMOVE( &op->o_extra, &bois.boi_oe,
+ OpExtra, oe_next );
+ }
+ }
+ rs->sr_entry = NULL;
+ e = NULL;
+
switch ( rs->sr_err ) {
case LDAP_SUCCESS: /* entry sent ok */
break;
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, 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 );