cache entry is locked by Berkeley DB lock primitives.
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
struct berval pdn;
Entry *p = NULL;
- int rc;
+ int rc, ret;
const char *text;
char textbuf[SLAP_TEXT_BUFLEN];
size_t textlen = sizeof textbuf;
#ifdef BDB_SUBENTRIES
int subentry;
#endif
+ u_int32_t locker;
+ DB_LOCK lock;
#if 0
u_int32_t lockid;
DB_LOCK lock;
text = "internal error";
goto return_results;
}
+
+ locker = TXN_ID ( ltid );
#if 0
lockid = TXN_ID( ltid );
#endif
#endif
/* get parent */
- rc = bdb_dn2entry_r( be, ltid, &pdn, &p, &matched, 0 );
+ rc = bdb_dn2entry_r( be, ltid, &pdn, &p, &matched, 0, locker, &lock );
switch( rc ) {
case 0:
refs = is_entry_referral( matched )
? get_entry_referrals( be, conn, op, matched )
: NULL;
- bdb_cache_return_entry_r(&bdb->bi_cache, matched);
+ bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
matched = NULL;
} else {
case DB_LOCK_DEADLOCK:
case DB_LOCK_NOTGRANTED:
/* free parent and reader lock */
- bdb_cache_return_entry_r( &bdb->bi_cache, p );
+ bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, p, &lock );
p = NULL;
goto retry;
}
matched_dn, NULL, refs, NULL );
ber_bvarray_free( refs );
- bdb_cache_return_entry_r( &bdb->bi_cache, p );
+ bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, p, &lock );
p = NULL;
goto done;
}
#endif
/* free parent and reader lock */
- bdb_cache_return_entry_r( &bdb->bi_cache, p );
+ bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, p, &lock );
p = NULL;
} else {
text = "txn_prepare failed";
} else {
+ ret = bdb_cache_add_entry_rw(bdb->bi_dbenv, &bdb->bi_cache, e, CACHE_WRITE_LOCK, locker, &lock);
+#if 0
if ( bdb_cache_add_entry_rw(&bdb->bi_cache,
e, CACHE_WRITE_LOCK) != 0 )
- {
+#endif
+ switch ( ret ) {
+ case 0:
+ break;
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto retry;
+ default:
+ ret = LDAP_OTHER;
+ }
+
+ if ( ret ) {
if(( rc=TXN_ABORT( ltid )) != 0 ) {
text = "cache add & txn_abort failed";
} else {
const char *entry_at_name = entry_at->ad_cname.bv_val;
AccessControlState acl_state = ACL_STATE_INIT;
+ u_int32_t locker;
+ DB_LOCK lock;
+
#ifdef NEW_LOGGING
LDAP_LOG(( "backend", LDAP_LEVEL_ARGS,
"bdb_attribute: gr dn: \"%s\"\n", entry_ndn->bv_val ));
txn = boi->boi_txn;
}
+ if ( txn != NULL )
+ locker = TXN_ID ( txn );
+ else
+ LOCK_ID ( bdb->bi_dbenv, &locker );
+
if (target != NULL && dn_match(&target->e_nname, entry_ndn)) {
/* we already have a LOCKED copy of the entry */
e = target;
} else {
+dn2entry_retry:
/* can we find entry */
- rc = bdb_dn2entry_r( be, NULL, entry_ndn, &e, NULL, 0 );
+ rc = bdb_dn2entry_r( be, NULL, entry_ndn, &e, NULL, 0, locker, &lock );
switch( rc ) {
case DB_NOTFOUND:
case 0:
break;
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto dn2entry_retry;
default:
if( txn != NULL ) {
boi->boi_err = rc;
}
+ else {
+ LOCK_ID_FREE( bdb->bi_dbenv, locker );
+ }
return (rc != LDAP_BUSY) ? LDAP_OTHER : LDAP_BUSY;
}
if (e == NULL) {
"=> bdb_attribute: cannot find entry: \"%s\"\n",
entry_ndn->bv_val, 0, 0 );
#endif
+ if ( txn == NULL ) {
+ LOCK_ID_FREE( bdb->bi_dbenv, locker );
+ }
return LDAP_NO_SUCH_OBJECT;
}
return_results:
if( target != e ) {
/* free entry */
- bdb_cache_return_entry_r(&bdb->bi_cache, e);
+ bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
+ }
+
+ if ( txn == NULL ) {
+ LOCK_ID_FREE( bdb->bi_dbenv, locker );
}
#ifdef NEW_LOGGING
#if DB_VERSION_MAJOR < 4
#define LOCK_DETECT(env,f,t,a) lock_detect(env, f, t, a)
#define LOCK_GET(env,i,f,o,m,l) lock_get(env, i, f, o, m, l)
+#define LOCK_PUT(env,l) lock_put(env, l)
#define TXN_CHECKPOINT(env,k,m,f) txn_checkpoint(env, k, m, f)
#define TXN_BEGIN(env,p,t,f) txn_begin((env), p, t, f)
#define TXN_PREPARE(txn,gid) txn_prepare((txn), (gid))
#define TXN_COMMIT(txn,f) txn_commit((txn), (f))
#define TXN_ABORT(txn) txn_abort((txn))
#define TXN_ID(txn) txn_id(txn)
+#define LOCK_ID(env, locker) lock_id(env, locker)
+#define LOCK_ID_FREE(env, locker) lock_id_free(env, locker)
#else
#define LOCK_DETECT(env,f,t,a) (env)->lock_detect(env, f, t, a)
#define LOCK_GET(env,i,f,o,m,l) (env)->lock_get(env, i, f, o, m, l)
+#define LOCK_PUT(env,l) (env)->lock_put(env, l)
#define TXN_CHECKPOINT(env,k,m,f) (env)->txn_checkpoint(env, k, m, f)
#define TXN_BEGIN(env,p,t,f) (env)->txn_begin((env), p, t, f)
#define TXN_PREPARE(txn,g) (txn)->prepare((txn), (g))
#define TXN_COMMIT(txn,f) (txn)->commit((txn), (f))
#define TXN_ABORT(txn) (txn)->abort((txn))
#define TXN_ID(txn) (txn)->id(txn)
+#define LOCK_ID(env, locker) (env)->lock_id(env, locker)
+#define LOCK_ID_FREE(env, locker) (env)->lock_id_free(env, locker)
#endif
LDAP_END_DECL
AttributeDescription *password = slap_schema.si_ad_userPassword;
+ u_int32_t locker;
+ DB_LOCK lock;
+
#ifdef NEW_LOGGING
LDAP_LOG (( "bind", LDAP_LEVEL_ARGS, "==> bdb_bind: dn: %s\n", dn->bv_val ));
#else
Debug( LDAP_DEBUG_ARGS, "==> bdb_bind: dn: %s\n", dn->bv_val, 0, 0);
#endif
+ LOCK_ID(bdb->bi_dbenv, &locker);
+
+dn2entry_retry:
/* get entry */
- rc = bdb_dn2entry_r( be, NULL, ndn, &e, &matched, 0 );
+ rc = bdb_dn2entry_r( be, NULL, ndn, &e, &matched, 0, locker, &lock );
switch(rc) {
case DB_NOTFOUND:
case LDAP_BUSY:
send_ldap_result( conn, op, LDAP_BUSY,
NULL, "ldap server busy", NULL, NULL );
+ LOCK_ID_FREE(bdb->bi_dbenv, locker);
return LDAP_BUSY;
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto dn2entry_retry;
default:
send_ldap_result( conn, op, rc=LDAP_OTHER,
NULL, "internal error", NULL, NULL );
+ LOCK_ID_FREE(bdb->bi_dbenv, locker);
return rc;
}
? get_entry_referrals( be, conn, op, matched )
: NULL;
- bdb_cache_return_entry_r( &bdb->bi_cache, matched );
+ bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, matched, &lock );
matched = NULL;
} else {
NULL, NULL, NULL, NULL );
}
+ LOCK_ID_FREE(bdb->bi_dbenv, locker);
+
ber_bvarray_free( refs );
free( matched_dn );
done:
/* free entry and reader lock */
if( e != NULL ) {
- bdb_cache_return_entry_r( &bdb->bi_cache, e );
+ bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
}
+ LOCK_ID_FREE(bdb->bi_dbenv, locker);
+
/* front end with send result on success (rc==0) */
return rc;
}
return 0;
}
+int
+bdb_cache_entry_db_lock
+( DB_ENV *env, u_int32_t locker, Entry *e, int rw, u_int32_t flags, 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 = e->e_nname.bv_val;
+ lockobj.size = e->e_nname.bv_len;
+ rc = LOCK_GET(env, locker, flags | DB_LOCK_NOWAIT,
+ &lockobj, db_rw, lock);
+ return rc;
+}
+
+int
+bdb_cache_entry_db_unlock
+( DB_ENV *env, DB_LOCK *lock )
+{
+ int rc;
+
+ rc = LOCK_PUT ( env, lock );
+ return rc;
+}
+
/*
* marks an entry in CREATING state as committed, so it is really returned
* to the cache. Otherwise an entry in CREATING state is removed.
}
void
-bdb_cache_return_entry_rw( Cache *cache, Entry *e, int rw )
+bdb_unlocked_cache_return_entry_rw( Cache *cache, Entry *e, int rw )
{
+
ID id;
int refcnt, freeit = 1;
assert( e->e_private );
+#if 0
bdb_cache_entry_rdwr_unlock(e, rw);
+#endif
+
+ id = e->e_id;
+ refcnt = --BEI(e)->bei_refcnt;
+
+ /*
+ * if the entry is returned when in CREATING state, it is deleted
+ * but not freed because it may belong to someone else (do_add,
+ * for instance)
+ */
+ if ( BEI(e)->bei_state == CACHE_ENTRY_CREATING ) {
+ /* set lru mutex */
+ ldap_pvt_thread_mutex_lock( &cache->lru_mutex );
+ bdb_cache_delete_entry_internal( cache, e );
+ /* free lru mutex */
+ ldap_pvt_thread_mutex_unlock( &cache->lru_mutex );
+ freeit = 0;
+ /* now the entry is in DELETED state */
+ }
+
+ if ( BEI(e)->bei_state == CACHE_ENTRY_COMMITTED ) {
+ BEI(e)->bei_state = CACHE_ENTRY_READY;
+
+ /* free cache write lock */
+ ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
+
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
+ "bdb_cache_return_entry_rw: return (%ld):%s, refcnt=%d\n",
+ id, rw ? "w" : "r", refcnt ));
+#else
+ Debug( LDAP_DEBUG_TRACE,
+ "====> bdb_cache_return_entry_%s( %ld ): created (%d)\n",
+ rw ? "w" : "r", id, refcnt );
+#endif
+
+
+ } else if ( BEI(e)->bei_state == CACHE_ENTRY_DELETED ) {
+ if( refcnt > 0 ) {
+ /* free cache write lock */
+ ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
+
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
+ "bdb_cache_return_entry_rw: %ld, delete pending (%d).\n",
+ id, refcnt ));
+#else
+ Debug( LDAP_DEBUG_TRACE,
+ "====> bdb_cache_return_entry_%s( %ld ): delete pending (%d)\n",
+ rw ? "w" : "r", id, refcnt );
+#endif
+
+ } else {
+ bdb_cache_entry_private_destroy( e );
+ if ( freeit ) {
+ bdb_entry_return( e );
+ }
+
+ /* free cache write lock */
+ ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
+
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
+ "bdb_cache_return_entry_rw: (%ld): deleted (%d)\n",
+ id, refcnt ));
+#else
+ Debug( LDAP_DEBUG_TRACE,
+ "====> bdb_cache_return_entry_%s( %ld ): deleted (%d)\n",
+ rw ? "w" : "r", id, refcnt );
+#endif
+ }
+
+ } else {
+ /* free cache write lock */
+ ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
+
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1,
+ "bdb_cache_return_entry_rw: ID %ld:%s returned (%d)\n",
+ id, rw ? "w": "r", refcnt ));
+#else
+ Debug( LDAP_DEBUG_TRACE,
+ "====> bdb_cache_return_entry_%s( %ld ): returned (%d)\n",
+ rw ? "w" : "r", id, refcnt);
+#endif
+ }
+}
+
+void
+bdb_cache_return_entry_rw
+( DB_ENV *env, Cache *cache, Entry *e, int rw, DB_LOCK *lock )
+{
+ ID id;
+ int refcnt, freeit = 1;
+
+ /* set cache write lock */
+ ldap_pvt_thread_rdwr_wlock( &cache->c_rwlock );
+
+ assert( e->e_private );
+
+ bdb_cache_entry_db_unlock( env, lock );
+#if 0
+ bdb_cache_entry_rdwr_unlock(e, rw);
+#endif
id = e->e_id;
refcnt = --BEI(e)->bei_refcnt;
* returns: 0 entry has been created and locked
* 1 entry already existed
* -1 something bad happened
+ * other Berkeley DB locking error code
*/
int
bdb_cache_add_entry_rw(
+ DB_ENV *env,
Cache *cache,
Entry *e,
- int rw
+ int rw,
+ u_int32_t locker,
+ DB_LOCK *lock
)
{
int i, rc;
return( -1 );
}
- bdb_cache_entry_rdwr_lock( e, rw );
+ rc = bdb_cache_entry_db_lock( env, locker, e, rw, 0, lock );
+ switch ( rc ) {
+ case 0 :
+ break;
+ case DB_LOCK_DEADLOCK :
+ case DB_LOCK_NOTGRANTED :
+ /* undo avl changes immediately */
+ if ( avl_delete( &cache->c_idtree, (caddr_t) e,
+ (AVL_CMP) entry_id_cmp ) == NULL ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "cache", LDAP_LEVEL_INFO,
+ "bdb_cache_add_entry: can't delete (%s) from cache.\n", e->e_dn ));
+#else
+ Debug( LDAP_DEBUG_ANY, "====> can't delete from id cache\n", 0, 0, 0 );
+#endif
+ }
+ if ( avl_delete( &cache->c_dntree, (caddr_t) e,
+ (AVL_CMP) entry_dn_cmp ) == NULL ) {
+#ifdef NEW_LOGGING
+ LDAP_LOG(( "cache", LDAP_LEVEL_INFO,
+ "bdb_cache_add_entry: can't delete (%s) from cache.\n", e->e_dn ));
+#else
+ Debug( LDAP_DEBUG_ANY, "====> can't delete from dn cache\n", 0, 0, 0 );
+#endif
+ }
+ /* fall through */
+ default :
+ bdb_cache_entry_private_destroy(e);
+ ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
+ return rc;
+ }
/* put the entry into 'CREATING' state */
/* will be marked after when entry is returned */
Entry *
bdb_cache_find_entry_id(
+ DB_ENV *env,
Cache *cache,
ID id,
- int rw
+ int rw,
+ u_int32_t locker,
+ DB_LOCK *lock
)
{
Entry e;
Entry *ep;
int count = 0;
+ int rc;
e.e_id = id;
}
/* acquire reader lock */
+ rc = bdb_cache_entry_db_lock ( env, locker, ep, rw, 0, lock );
+
+#if 0
if ( bdb_cache_entry_rdwr_trylock(ep, rw) == LDAP_PVT_THREAD_EBUSY ) {
+#endif
+
+ if ( rc ) { /* will be changed to retry beyond threshold */
/* could not acquire entry lock...
* owner cannot free as we have the cache locked.
* so, unlock the cache, yield, and try again.
Debug(LDAP_DEBUG_TRACE,
"====> bdb_cache_find_entry_id( %ld ): %ld (busy) %d\n",
id, ep_id, state);
+ Debug(LDAP_DEBUG_TRACE,
+ "locker = %d\n",
+ locker, 0, 0);
#endif
ldap_pvt_thread_yield();
const char *text = NULL;
int manageDSAit = get_manageDSAit( op );
+ u_int32_t locker;
+ DB_LOCK lock;
+
+ LOCK_ID ( bdb->bi_dbenv, &locker );
+
+dn2entry_retry:
/* get entry */
- rc = bdb_dn2entry_r( be, NULL, ndn, &e, &matched, 0 );
+ rc = bdb_dn2entry_r( be, NULL, ndn, &e, &matched, 0, locker, &lock );
switch( rc ) {
case DB_NOTFOUND:
case LDAP_BUSY:
text = "ldap server busy";
goto return_results;
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto dn2entry_retry;
default:
rc = LDAP_OTHER;
text = "internal error";
refs = is_entry_referral( matched )
? get_entry_referrals( be, conn, op, matched )
: NULL;
- bdb_cache_return_entry_r( &bdb->bi_cache, matched );
+ bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, matched, &lock );
matched = NULL;
} else {
done:
/* free entry */
if( e != NULL ) {
- bdb_cache_return_entry_r( &bdb->bi_cache, e );
+ bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
}
+ LOCK_ID_FREE ( bdb->bi_dbenv, locker );
+
return rc;
}
AttributeDescription *children = slap_schema.si_ad_children;
DB_TXN *ltid = NULL;
struct bdb_op_info opinfo;
+
+ u_int32_t locker;
+ DB_LOCK lock;
#if 0
u_int32_t lockid;
DB_LOCK lock;
if( 0 ) {
retry: /* transaction retry */
if( e != NULL ) {
- bdb_cache_return_entry_w(&bdb->bi_cache, e);
+ bdb_cache_return_entry_w(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
}
#ifdef NEW_LOGGING
LDAP_LOG (( "delete", LDAP_LEVEL_DETAIL1,
text = "internal error";
goto return_results;
}
+
+ locker = TXN_ID ( ltid );
#if 0
lockid = TXN_ID( ltid );
#endif
}
#endif
/* get parent */
- rc = bdb_dn2entry_r( be, ltid, &pdn, &p, NULL, 0 );
+ rc = bdb_dn2entry_r( be, ltid, &pdn, &p, NULL, 0, locker, &lock );
switch( rc ) {
case 0:
rc = access_allowed( be, conn, op, p,
children, NULL, ACL_WRITE, NULL );
- bdb_cache_return_entry_r(&bdb->bi_cache, p);
+ bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, p, &lock);
p = NULL;
switch( opinfo.boi_err ) {
}
/* get entry for read/modify/write */
- rc = bdb_dn2entry_w( be, ltid, ndn, &e, &matched, DB_RMW );
+ rc = bdb_dn2entry_w( be, ltid, ndn, &e, &matched, DB_RMW, locker, &lock );
switch( rc ) {
case 0:
refs = is_entry_referral( matched )
? get_entry_referrals( be, conn, op, matched )
: NULL;
- bdb_cache_return_entry_r(&bdb->bi_cache, matched );
+ bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, matched, &lock );
matched = NULL;
} else {
done:
/* free entry */
if( e != NULL ) {
- bdb_cache_return_entry_w(&bdb->bi_cache, e);
+ bdb_cache_return_entry_w(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
}
if( ltid != NULL ) {
Entry **e,
Entry **matched,
int flags,
- int rw )
+ int rw,
+ u_int32_t locker,
+ DB_LOCK *lock )
{
int rc;
ID id, id2 = 0;
}
if( id2 == 0 ) {
- rc = bdb_id2entry_rw( be, tid, id, e, rw );
+ rc = bdb_id2entry_rw( be, tid, id, e, rw, locker, lock );
} else {
- rc = bdb_id2entry_r( be, tid, id2, matched);
+ rc = bdb_id2entry_r( be, tid, id2, matched, locker, lock );
}
return rc;
const char *group_oc_name = NULL;
const char *group_at_name = group_at->ad_cname.bv_val;
+ u_int32_t locker;
+ DB_LOCK lock;
+
if( group_oc->soc_names && group_oc->soc_names[0] ) {
group_oc_name = group_oc->soc_names[0];
} else {
txn = boi->boi_txn;
}
+ if ( txn )
+ locker = TXN_ID( txn );
+ else
+ LOCK_ID ( bdb->bi_dbenv, &locker );
+
if (dn_match(&target->e_name, gr_ndn)) {
/* we already have a LOCKED copy of the entry */
e = target;
gr_ndn->bv_val, 0, 0 );
#endif
} else {
+dn2entry_retry:
/* can we find group entry */
- rc = bdb_dn2entry_r( be, NULL, gr_ndn, &e, NULL, 0 );
+ rc = bdb_dn2entry_r( be, NULL, gr_ndn, &e, NULL, 0, locker, &lock );
if( rc ) {
+ if ( rc == DB_LOCK_DEADLOCK || rc == DB_LOCK_NOTGRANTED )
+ goto dn2entry_retry;
if( txn ) {
boi->boi_err = rc;
}
+ else {
+ LOCK_ID_FREE ( bdb->bi_dbenv, locker );
+ }
return( 1 );
}
if (e == NULL) {
"=> bdb_group: cannot find group: \"%s\"\n",
gr_ndn->bv_val, 0, 0 );
#endif
+ if ( txn == NULL ) {
+ LOCK_ID_FREE ( bdb->bi_dbenv, locker );
+ }
return( 1 );
}
#ifdef NEW_LOGGING
return_results:
if( target != e ) {
/* free entry */
- bdb_cache_return_entry_r( &bdb->bi_cache, e );
+ bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
+ }
+
+ if ( txn == NULL ) {
+ LOCK_ID_FREE ( bdb->bi_dbenv, locker );
}
#ifdef NEW_LOGGING
DB_TXN *tid,
ID id,
Entry **e,
- int rw )
+ int rw,
+ u_int32_t locker,
+ DB_LOCK *lock )
{
struct bdb_info *bdb = (struct bdb_info *) be->be_private;
DB *db = bdb->bi_id2entry->bdi_db;
DBT key, data;
struct berval bv;
- int rc = 0;
+ int rc = 0, ret = 0;
*e = NULL;
DBTzero( &data );
data.flags = DB_DBT_MALLOC;
- if ((*e = bdb_cache_find_entry_id(&bdb->bi_cache, id, rw)) != NULL) {
+ if ((*e = bdb_cache_find_entry_id(bdb->bi_dbenv, &bdb->bi_cache, id, rw, locker, lock)) != NULL) {
return 0;
}
ch_free( data.data );
}
- while (rc == 0 && bdb_cache_add_entry_rw(&bdb->bi_cache, *e, rw) != 0) {
- Entry *ee;
- int add_loop_cnt = 0;
- if ( (*e)->e_private != NULL ) {
- free ((*e)->e_private);
- }
- (*e)->e_private = NULL;
- if ( (ee = bdb_cache_find_entry_id
- (&bdb->bi_cache, id, rw) ) != NULL) {
- bdb_entry_return ( *e );
- *e = ee;
- return 0;
+ if ( rc == 0 ) {
+ ret = bdb_cache_add_entry_rw( bdb->bi_dbenv,
+ &bdb->bi_cache, *e, rw, locker, lock);
+ while ( ret == 1 || ret == -1 ) {
+ Entry *ee;
+ int add_loop_cnt = 0;
+ if ( (*e)->e_private != NULL ) {
+ free ((*e)->e_private);
+ }
+ (*e)->e_private = NULL;
+ if ( (ee = bdb_cache_find_entry_id
+ (bdb->bi_dbenv, &bdb->bi_cache, id, rw, locker, lock) ) != NULL) {
+ bdb_entry_return ( *e );
+ *e = ee;
+ return 0;
+ }
+ if ( ++add_loop_cnt == BDB_MAX_ADD_LOOP ) {
+ bdb_entry_return ( *e );
+ *e = NULL;
+ return LDAP_BUSY;
+ }
}
- if ( ++add_loop_cnt == BDB_MAX_ADD_LOOP ) {
- bdb_entry_return ( *e );
+ if ( ret != 0 ) {
+ if ( (*e)->e_private != NULL )
+ free ( (*e)->e_private );
+ bdb_entry_return( *e );
*e = NULL;
- return LDAP_BUSY;
+ ch_free( data.data );
}
+ rc = ret;
}
#ifdef BDB_HIER
if ( slapMode == SLAP_SERVER_MODE ) {
/* free entry and reader or writer lock */
- bdb_cache_return_entry_rw( &bdb->bi_cache, e, rw );
+ bdb_unlocked_cache_return_entry_rw( &bdb->bi_cache, e, rw );
} else {
if (e->e_private != NULL)
free (e->e_private);
DB_TXN *ltid = NULL;
struct bdb_op_info opinfo;
+ u_int32_t locker;
+ DB_LOCK lock;
+
#ifdef NEW_LOGGING
LDAP_LOG (( "modify", LDAP_LEVEL_ENTRY, "bdb_modify: %s\n", dn->bv_val ));
#else
retry: /* transaction retry */
if( e != NULL ) {
bdb_cache_delete_entry(&bdb->bi_cache, e);
- bdb_cache_return_entry_w(&bdb->bi_cache, e);
+ bdb_cache_return_entry_w(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
}
#ifdef NEW_LOGGING
LDAP_LOG (( "modify", LDAP_LEVEL_DETAIL1, "bdb_modify: retrying...\n" ));
goto return_results;
}
+ locker = TXN_ID ( ltid );
+
opinfo.boi_bdb = be;
opinfo.boi_txn = ltid;
opinfo.boi_err = 0;
op->o_private = &opinfo;
/* get entry */
- rc = bdb_dn2entry_w( be, ltid, ndn, &e, &matched, 0 );
+ rc = bdb_dn2entry_w( be, ltid, ndn, &e, &matched, 0, locker, &lock );
if ( rc != 0 ) {
#ifdef NEW_LOGGING
refs = is_entry_referral( matched )
? get_entry_referrals( be, conn, op, matched )
: NULL;
- bdb_cache_return_entry_r (&bdb->bi_cache, matched);
+ bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
matched = NULL;
} else {
}
if( e != NULL ) {
- bdb_cache_return_entry_w (&bdb->bi_cache, e);
+ bdb_cache_return_entry_w (bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
}
return rc;
}
int manageDSAit = get_manageDSAit( op );
+ u_int32_t locker;
+ DB_LOCK lock;
+
#ifdef NEW_LOGGING
LDAP_LOG (( "modrdn", LDAP_LEVEL_ENTRY, "==>bdb_modrdn(%s,%s,%s)\n",
dn->bv_val,newrdn->bv_val,
retry: /* transaction retry */
if (e != NULL) {
bdb_cache_delete_entry(&bdb->bi_cache, e);
- bdb_cache_return_entry_w(&bdb->bi_cache, e);
+ bdb_cache_return_entry_w(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
}
if (p != NULL) {
- bdb_cache_return_entry_r(&bdb->bi_cache, p);
+ bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, p, &lock);
}
if (np != NULL) {
- bdb_cache_return_entry_r(&bdb->bi_cache, np);
+ bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, np, &lock);
}
#ifdef NEW_LOGGING
LDAP_LOG (( "modrdn", LDAP_LEVEL_DETAIL1, "==>bdb_modrdn: retrying...\n"));
goto return_results;
}
+ locker = TXN_ID ( ltid );
+
opinfo.boi_bdb = be;
opinfo.boi_txn = ltid;
opinfo.boi_err = 0;
op->o_private = &opinfo;
/* get entry */
- rc = bdb_dn2entry_w( be, ltid, ndn, &e, &matched, 0 );
+ rc = bdb_dn2entry_w( be, ltid, ndn, &e, &matched, 0, locker, &lock );
switch( rc ) {
case 0:
refs = is_entry_referral( matched )
? get_entry_referrals( be, conn, op, matched )
: NULL;
- bdb_cache_return_entry_r( &bdb->bi_cache, matched );
+ bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, matched, &lock );
matched = NULL;
} else {
/* Make sure parent entry exist and we can write its
* children.
*/
- rc = bdb_dn2entry_r( be, ltid, &p_ndn, &p, NULL, 0 );
+ rc = bdb_dn2entry_r( be, ltid, &p_ndn, &p, NULL, 0, locker, &lock );
switch( rc ) {
case 0:
/* newSuperior == entry being moved?, if so ==> ERROR */
/* Get Entry with dn=newSuperior. Does newSuperior exist? */
- rc = bdb_dn2entry_r( be, ltid, nnewSuperior, &np, NULL, 0 );
+ rc = bdb_dn2entry_r( be, ltid, nnewSuperior, &np, NULL, 0, locker, &lock );
switch( rc ) {
case 0:
/* LDAP v3 Support */
if( np != NULL ) {
/* free new parent and reader lock */
- bdb_cache_return_entry_r(&bdb->bi_cache, np);
+ bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, np, &lock);
}
if( p != NULL ) {
/* free parent and reader lock */
- bdb_cache_return_entry_r(&bdb->bi_cache, p);
+ bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, p, &lock);
}
/* free entry */
if( e != NULL ) {
- bdb_cache_return_entry_w( &bdb->bi_cache, e );
+ bdb_cache_return_entry_w( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
}
if( ltid != NULL ) {
if( 0 ) {
retry: /* transaction retry */
+#if 0
if( e != NULL ) {
- bdb_cache_return_entry_w(&bdb->bi_cache, e);
+ bdb_cache_return_entry_w(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
}
+#endif
#ifdef NEW_LOGGING
LDAP_LOG (( "operational", LDAP_LEVEL_DETAIL1,
"=> bdb_operational: retrying...\n" ));
struct berval dn;
struct berval ndn;
+ u_int32_t locker;
+ DB_LOCK lock;
+
assert( reqoid != NULL );
assert( strcmp( LDAP_EXOP_MODIFY_PASSWD, reqoid ) == 0 );
retry: /* transaction retry */
if ( e != NULL ) {
bdb_cache_delete_entry(&bdb->bi_cache, e);
- bdb_cache_return_entry_w(&bdb->bi_cache, e);
+ bdb_cache_return_entry_w(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
}
#ifdef NEW_LOGGING
LDAP_LOG (( "passwd", LDAP_LEVEL_DETAIL1, "bdb_exop_passwd: retrying...\n" ));
goto done;
}
+ locker = TXN_ID ( ltid );
+
opinfo.boi_bdb = be;
opinfo.boi_txn = ltid;
opinfo.boi_err = 0;
op->o_private = &opinfo;
/* get entry */
- rc = bdb_dn2entry_w( be, ltid, &ndn, &e, NULL, 0 );
+ rc = bdb_dn2entry_w( be, ltid, &ndn, &e, NULL, 0 , locker, &lock);
switch(rc) {
case DB_LOCK_DEADLOCK:
done:
if( e != NULL ) {
- bdb_cache_return_entry_w( &bdb->bi_cache, e );
+ bdb_cache_return_entry_w( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
}
if( hash.bv_val != NULL ) {
* dn2entry.c
*/
int bdb_dn2entry_rw LDAP_P(( BackendDB *be, DB_TXN *tid,
- struct berval *dn, Entry **e, Entry **matched, int flags, int rw ));
-#define bdb_dn2entry_r(be, tid, dn, e, m, f) bdb_dn2entry_rw((be), (tid), (dn), (e), (m), (f), 0)
-#define bdb_dn2entry_w(be, tid, dn, e, m, f) bdb_dn2entry_rw((be), (tid), (dn), (e), (m), (f), 1)
+ struct berval *dn, Entry **e, Entry **matched, int flags, int rw , u_int32_t locker, DB_LOCK *lock));
+#define bdb_dn2entry_r(be, tid, dn, e, m, f, locker, lock) bdb_dn2entry_rw((be), (tid), (dn), (e), (m), (f), 0, locker, lock)
+#define bdb_dn2entry_w(be, tid, dn, e, m, f, locker, lock) bdb_dn2entry_rw((be), (tid), (dn), (e), (m), (f), 1, locker, lock)
/*
* dn2id.c
DB_TXN *tid,
ID id,
Entry **e,
- int rw );
-#define bdb_id2entry_r(be, tid, id, e) bdb_id2entry_rw((be), (tid), (id), (e), 0)
-#define bdb_id2entry_w(be, tid, id, e) bdb_id2entry_rw((be), (tid), (id), (e), 1)
+ int rw,
+ u_int32_t locker,
+ DB_LOCK *lock );
+#define bdb_id2entry_r(be, tid, id, e, locker, lock) bdb_id2entry_rw((be), (tid), (id), (e), 0, locker, lock)
+#define bdb_id2entry_w(be, tid, id, e, locker, lock) bdb_id2entry_rw((be), (tid), (id), (e), 1, locker, lock)
void bdb_entry_free ( Entry *e );
*/
void bdb_cache_entry_commit( Entry *e );
-void bdb_cache_return_entry_rw( Cache *cache, Entry *e, int rw );
-#define bdb_cache_return_entry_r(c, e) bdb_cache_return_entry_rw((c), (e), 0)
-#define bdb_cache_return_entry_w(c, e) bdb_cache_return_entry_rw((c), (e), 1)
+void bdb_cache_return_entry_rw( DB_ENV *env, Cache *cache, Entry *e, int rw, DB_LOCK *lock );
+#define bdb_cache_return_entry_r(env, c, e, l) bdb_cache_return_entry_rw((env), (c), (e), 0, (l))
+#define bdb_cache_return_entry_w(env, c, e, l) bdb_cache_return_entry_rw((env), (c), (e), 1, (l))
+void bdb_unlocked_cache_return_entry_rw( Cache *cache, Entry *e, int rw );
+#define bdb_unlocked_cache_return_entry_r( c, e ) bdb_cache_return_entry_rw((c), (e), 0)
+#define bdb_unlocked_cache_return_entry_w( c, e ) bdb_cache_return_entry_rw((c), (e), 1)
int bdb_cache_add_entry_rw(
- Cache *cache,
- Entry *e,
- int rw
+ DB_ENV *env,
+ Cache *cache,
+ Entry *e,
+ int rw,
+ u_int32_t locker,
+ DB_LOCK *lock
);
int bdb_cache_update_entry(
Cache *cache,
struct berval *ndn
);
Entry* bdb_cache_find_entry_id(
- Cache *cache,
- ID id,
- int rw
+ DB_ENV *env,
+ Cache *cache,
+ ID id,
+ int rw,
+ u_int32_t locker,
+ DB_LOCK *lock
);
int bdb_cache_delete_entry(
Cache *cache,
Entry *e = NULL;
Entry *matched = NULL;
+ u_int32_t locker;
+ DB_LOCK lock;
+
if( op->o_tag == LDAP_REQ_SEARCH ) {
/* let search take care of itself */
return rc;
return rc;
}
+ LOCK_ID ( bdb->bi_dbenv, &locker );
+
+dn2entry_retry:
/* get entry */
- rc = bdb_dn2entry_r( be, NULL, ndn, &e, &matched, 0 );
+ rc = bdb_dn2entry_r( be, NULL, ndn, &e, &matched, 0, locker, &lock );
switch(rc) {
case DB_NOTFOUND:
break;
case LDAP_BUSY:
if (e != NULL) {
- bdb_cache_return_entry_r(&bdb->bi_cache, e);
+ bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
}
if (matched != NULL) {
- bdb_cache_return_entry_r(&bdb->bi_cache, matched);
+ bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
}
send_ldap_result( conn, op, LDAP_BUSY,
NULL, "ldap server busy", NULL, NULL );
+ LOCK_ID_FREE ( bdb->bi_dbenv, locker );
return LDAP_BUSY;
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto dn2entry_retry;
default:
#ifdef NEW_LOGGING
LDAP_LOG (( "referral", LDAP_LEVEL_ERR,
db_strerror(rc), rc, 0 );
#endif
if (e != NULL) {
- bdb_cache_return_entry_r(&bdb->bi_cache, e);
+ bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
}
if (matched != NULL) {
- bdb_cache_return_entry_r(&bdb->bi_cache, matched);
+ bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
}
send_ldap_result( conn, op, rc=LDAP_OTHER,
NULL, "internal error", NULL, NULL );
+ LOCK_ID_FREE ( bdb->bi_dbenv, locker );
return rc;
}
refs = get_entry_referrals( be, conn, op, matched );
}
- bdb_cache_return_entry_r (&bdb->bi_cache, matched);
+ bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
matched = NULL;
} else if ( default_referral != NULL ) {
rc = LDAP_OTHER;
NULL, NULL );
}
+ LOCK_ID_FREE ( bdb->bi_dbenv, locker );
free( matched_dn );
return rc;
}
ber_bvarray_free( refs );
}
- bdb_cache_return_entry_r(&bdb->bi_cache, e);
+ bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
+ LOCK_ID_FREE ( bdb->bi_dbenv, locker );
return rc;
}
struct slap_limits_set *limit = NULL;
int isroot = 0;
+ u_int32_t locker;
+ DB_LOCK lock;
+
#ifdef NEW_LOGGING
LDAP_LOG (( "search", LDAP_LEVEL_ENTRY,"bdb_back_search\n"));
#else
manageDSAit = get_manageDSAit( op );
+ LOCK_ID (bdb->bi_dbenv, &locker );
+
if ( nbase->bv_len == 0 ) {
/* DIT root special case */
e = (Entry *) &slap_entry_root;
} else
#endif
{
- rc = bdb_dn2entry_r( be, NULL, nbase, &e, &matched, 0 );
+dn2entry_retry:
+ rc = bdb_dn2entry_r( be, NULL, nbase, &e, &matched, 0, locker, &lock );
}
switch(rc) {
break;
case LDAP_BUSY:
if (e != NULL) {
- bdb_cache_return_entry_r(&bdb->bi_cache, e);
+ bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
}
if (matched != NULL) {
- bdb_cache_return_entry_r(&bdb->bi_cache, matched);
+ bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
}
send_ldap_result( conn, op, LDAP_BUSY,
NULL, "ldap server busy", NULL, NULL );
+ LOCK_ID_FREE (bdb->bi_dbenv, locker );
return LDAP_BUSY;
+ case DB_LOCK_DEADLOCK:
+ case DB_LOCK_NOTGRANTED:
+ goto dn2entry_retry;
default:
if (e != NULL) {
- bdb_cache_return_entry_r(&bdb->bi_cache, e);
+ bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
}
if (matched != NULL) {
- bdb_cache_return_entry_r(&bdb->bi_cache, matched);
+ bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
}
send_ldap_result( conn, op, rc=LDAP_OTHER,
NULL, "internal error", NULL, NULL );
+ LOCK_ID_FREE (bdb->bi_dbenv, locker );
return rc;
}
? get_entry_referrals( be, conn, op, matched )
: NULL;
- bdb_cache_return_entry_r (&bdb->bi_cache, matched);
+ bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, matched, &lock);
matched = NULL;
if( erefs ) {
send_ldap_result( conn, op, rc=LDAP_REFERRAL ,
matched_dn.bv_val, text, refs, NULL );
+ LOCK_ID_FREE (bdb->bi_dbenv, locker );
if ( refs ) ber_bvarray_free( refs );
if ( matched_dn.bv_val ) ber_memfree( matched_dn.bv_val );
return rc;
erefs = get_entry_referrals( be, conn, op, e );
refs = NULL;
- bdb_cache_return_entry_r( &bdb->bi_cache, e );
+ bdb_cache_return_entry_r( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
e = NULL;
if( erefs ) {
refs ? NULL : "bad referral object",
refs, NULL );
+ LOCK_ID_FREE (bdb->bi_dbenv, locker );
ber_bvarray_free( refs );
ber_memfree( matched_dn.bv_val );
return 1;
cursor = e->e_id == NOID ? 1 : e->e_id;
if ( e != &slap_entry_root ) {
- bdb_cache_return_entry_r(&bdb->bi_cache, e);
+ bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
}
e = NULL;
goto done;
}
+id2entry_retry:
/* get the entry with reader lock */
- rc = bdb_id2entry_r( be, NULL, id, &e );
+ rc = bdb_id2entry_r( be, NULL, id, &e, locker, &lock );
if (rc == LDAP_BUSY) {
send_ldap_result( conn, op, rc=LDAP_BUSY,
NULL, "ldap server busy", NULL, NULL );
goto done;
}
+ else if ( rc == DB_LOCK_DEADLOCK || rc == DB_LOCK_NOTGRANTED ) {
+ goto id2entry_retry;
+ }
if ( e == NULL ) {
if( !BDB_IDL_IS_RANGE(candidates) ) {
if ( scopeok ) {
/* check size limit */
if ( --slimit == -1 ) {
- bdb_cache_return_entry_r (&bdb->bi_cache, e);
+ bdb_cache_return_entry_r (bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
e = NULL;
send_search_result( conn, op,
rc = LDAP_SIZELIMIT_EXCEEDED, NULL, NULL,
case 1: /* entry not sent */
break;
case -1: /* connection closed */
- bdb_cache_return_entry_r(&bdb->bi_cache, e);
+ bdb_cache_return_entry_r(bdb->bi_dbenv, &bdb->bi_cache, e, &lock);
e = NULL;
rc = LDAP_OTHER;
goto done;
loop_continue:
if( e != NULL ) {
/* free reader lock */
- bdb_cache_return_entry_r ( &bdb->bi_cache, e );
+ bdb_cache_return_entry_r ( bdb->bi_dbenv, &bdb->bi_cache, e , &lock);
e = NULL;
}
done:
if( e != NULL ) {
/* free reader lock */
- bdb_cache_return_entry_r ( &bdb->bi_cache, e );
+ bdb_cache_return_entry_r ( bdb->bi_dbenv, &bdb->bi_cache, e, &lock );
}
+ LOCK_ID_FREE (bdb->bi_dbenv, locker );
+
if( v2refs ) ber_bvarray_free( v2refs );
if( realbase.bv_val ) ch_free( realbase.bv_val );