extern int __lock_getlocker(DB_LOCKTAB *lt, u_int32_t locker, int create, DB_LOCKER **ret);
#define CURSOR_SETLOCKER(cursor, id) cursor->locker = id
-#define CURSOR_GETLOCKER(cursor) cursor->locker
+#define CURSOR_GETLOCKER(cursor) cursor->locker
+#define BDB_LOCKID(locker) locker->id
#else
typedef u_int32_t BDB_LOCKER;
#define CURSOR_SETLOCKER(cursor, id) cursor->locker = id
#define CURSOR_GETLOCKER(cursor) cursor->locker
+#define BDB_LOCKID(locker) locker
#endif
* alternatives though.
*/
-#if DB_VERSION_FULL >= 0x04060012
-#define BDB_LOCKID(locker) locker->id
-#else
-#define BDB_LOCKID(locker) locker
-#endif
-
/* Atomically release and reacquire a lock */
int
bdb_cache_entry_db_relock(
ei.bei_parent = eip;
ei2 = (EntryInfo *)avl_find( eip->bei_kids, &ei, bdb_rdn_cmp );
if ( !ei2 ) {
+ DB_LOCK lock;
int len = ei.bei_nrdn.bv_len;
if ( BER_BVISEMPTY( ndn )) {
ei.bei_nrdn.bv_val );
#endif
- rc = bdb_dn2id( op, locker, &ei.bei_nrdn, &ei );
+ lock.mode = DB_LOCK_NG;
+ rc = bdb_dn2id( op, &ei.bei_nrdn, &ei, locker, &lock );
if (rc) {
bdb_cache_entryinfo_lock( eip );
+ bdb_cache_entry_db_unlock( bdb, &lock );
*res = eip;
return rc;
}
ei.bei_nrdn.bv_val, ei.bei_id, 0 );
/* add_internal left eip and c_rwlock locked */
ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
+ bdb_cache_entry_db_unlock( bdb, &lock );
if ( rc ) {
*res = eip;
return rc;
#include "idl.h"
#include "lutil.h"
+#define bdb_dn2id_lock BDB_SYMBOL(dn2id_lock)
+
+static int
+bdb_dn2id_lock( struct bdb_info *bdb, struct berval *dn,
+ int rw, BDB_LOCKER locker, DB_LOCK *lock )
+{
+ int rc;
+ DBT lockobj;
+ int db_rw;
+
+ if (rw)
+ db_rw = DB_LOCK_WRITE;
+ else
+ db_rw = DB_LOCK_READ;
+
+ lockobj.data = dn->bv_val;
+ lockobj.size = dn->bv_len;
+
+ rc = LOCK_GET(bdb->bi_dbenv, BDB_LOCKID(locker), DB_LOCK_NOWAIT,
+ &lockobj, db_rw, lock);
+ return rc;
+}
+
#ifndef BDB_HIER
int
bdb_dn2id_add(
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
DB *db = bdb->bi_dn2id->bdi_db;
- int rc;
- DBT key;
char *buf;
+ DBT key;
+ DB_LOCK lock;
struct berval pdn, ptr;
+ int rc;
Debug( LDAP_DEBUG_TRACE, "=> bdb_dn2id_delete( \"%s\", 0x%08lx )\n",
e->e_ndn, e->e_id, 0 );
AC_MEMCPY( ptr.bv_val, e->e_nname.bv_val, e->e_nname.bv_len );
ptr.bv_val[ptr.bv_len] = '\0';
+ /* We hold this lock until the TXN completes */
+ rc = bdb_dn2id_lock( bdb, &e->e_nname, 1, TXN_ID( txn ), &lock );
+ if ( rc ) return rc;
+
/* delete it */
rc = db->del( db, txn, &key, 0 );
if( rc != 0 ) {
int
bdb_dn2id(
Operation *op,
- BDB_LOCKER locker,
struct berval *dn,
- EntryInfo *ei )
+ EntryInfo *ei,
+ BDB_LOCKER locker,
+ DB_LOCK *lock )
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
DB *db = bdb->bi_dn2id->bdi_db;
data.ulen = sizeof(ID);
data.flags = DB_DBT_USERMEM;
+ rc = bdb_dn2id_lock( bdb, dn, 0, locker, lock );
+ if ( rc ) return rc;
+
rc = db->cursor( db, NULL, &cursor, bdb->bi_db_opflags );
if ( rc ) return rc;
if ( locker ) {
int rc;
ID nid;
unsigned char dlen[2];
+ DB_LOCK lock;
DBTzero(&key);
key.size = sizeof(ID);
data.dlen = data.size;
data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
+ /* We hold this lock until the TXN completes */
+ rc = bdb_dn2id_lock( bdb, &e->e_nname, 1, TXN_ID( txn ), &lock );
+ if ( rc ) return rc;
+
key.data = &nid;
rc = db->cursor( db, txn, &cursor, bdb->bi_db_opflags );
if ( rc ) return rc;
int
hdb_dn2id(
Operation *op,
- BDB_LOCKER locker,
struct berval *in,
- EntryInfo *ei )
+ EntryInfo *ei,
+ BDB_LOCKER locker,
+ DB_LOCK *lock )
{
struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
DB *db = bdb->bi_dn2id->bdi_db;
data.dlen = data.ulen;
data.flags = DB_DBT_USERMEM | DB_DBT_PARTIAL;
+ rc = bdb_dn2id_lock( bdb, in, 0, locker, lock );
+ if ( rc ) return rc;
+
rc = db->cursor( db, NULL, &cursor, bdb->bi_db_opflags );
if ( rc ) return rc;
if ( locker ) {