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)
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;
}
}
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 );
}
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;
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 );