From: Jong Hyuk Choi Date: Fri, 31 May 2002 20:49:19 +0000 (+0000) Subject: redesign of back-bdb locking : X-Git-Tag: OPENLDAP_REL_ENG_2_MP~34 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=7341dc5db656b33d6dfe86bce5a00c1328809caa;p=openldap redesign of back-bdb locking : cache entry is locked by Berkeley DB lock primitives. --- diff --git a/servers/slapd/back-bdb/add.c b/servers/slapd/back-bdb/add.c index b7cc3e70ef..303ed63a35 100644 --- a/servers/slapd/back-bdb/add.c +++ b/servers/slapd/back-bdb/add.c @@ -23,7 +23,7 @@ bdb_add( 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; @@ -33,6 +33,8 @@ bdb_add( #ifdef BDB_SUBENTRIES int subentry; #endif + u_int32_t locker; + DB_LOCK lock; #if 0 u_int32_t lockid; DB_LOCK lock; @@ -108,6 +110,8 @@ retry: /* transaction retry */ text = "internal error"; goto return_results; } + + locker = TXN_ID ( ltid ); #if 0 lockid = TXN_ID( ltid ); #endif @@ -142,7 +146,7 @@ retry: /* transaction retry */ #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: @@ -169,7 +173,7 @@ retry: /* transaction retry */ 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 { @@ -200,7 +204,7 @@ retry: /* transaction retry */ 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; } @@ -262,7 +266,7 @@ retry: /* transaction 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; } @@ -275,7 +279,7 @@ retry: /* transaction retry */ #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 { @@ -430,9 +434,22 @@ retry: /* transaction retry */ 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 { diff --git a/servers/slapd/back-bdb/attribute.c b/servers/slapd/back-bdb/attribute.c index 38203b994d..1277f02561 100644 --- a/servers/slapd/back-bdb/attribute.c +++ b/servers/slapd/back-bdb/attribute.c @@ -39,6 +39,9 @@ bdb_attribute( 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 )); @@ -65,6 +68,11 @@ bdb_attribute( 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; @@ -80,16 +88,23 @@ bdb_attribute( } 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) { @@ -102,6 +117,9 @@ bdb_attribute( "=> 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; } @@ -205,7 +223,11 @@ bdb_attribute( 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 diff --git a/servers/slapd/back-bdb/back-bdb.h b/servers/slapd/back-bdb/back-bdb.h index be89b98bf3..784bbc89aa 100644 --- a/servers/slapd/back-bdb/back-bdb.h +++ b/servers/slapd/back-bdb/back-bdb.h @@ -146,21 +146,27 @@ struct bdb_op_info { #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 diff --git a/servers/slapd/back-bdb/bind.c b/servers/slapd/back-bdb/bind.c index ad1bcfe3bb..be64c5b6a8 100644 --- a/servers/slapd/back-bdb/bind.c +++ b/servers/slapd/back-bdb/bind.c @@ -40,14 +40,20 @@ bdb_bind( 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: @@ -56,10 +62,15 @@ bdb_bind( 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; } @@ -75,7 +86,7 @@ bdb_bind( ? 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 { @@ -108,6 +119,8 @@ bdb_bind( NULL, NULL, NULL, NULL ); } + LOCK_ID_FREE(bdb->bi_dbenv, locker); + ber_bvarray_free( refs ); free( matched_dn ); @@ -274,9 +287,11 @@ bdb_bind( 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; } diff --git a/servers/slapd/back-bdb/cache.c b/servers/slapd/back-bdb/cache.c index 5038db4bc7..35d5a5720d 100644 --- a/servers/slapd/back-bdb/cache.c +++ b/servers/slapd/back-bdb/cache.c @@ -132,6 +132,36 @@ bdb_cache_entry_private_init( Entry *e ) 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. @@ -162,8 +192,9 @@ bdb_cache_entry_private_destroy( Entry *e ) } 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; @@ -172,7 +203,112 @@ bdb_cache_return_entry_rw( Cache *cache, Entry *e, int rw ) 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; @@ -290,12 +426,16 @@ bdb_cache_return_entry_rw( Cache *cache, Entry *e, int rw ) * 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; @@ -385,7 +525,37 @@ bdb_cache_add_entry_rw( 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 */ @@ -661,14 +831,18 @@ try_again: 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; @@ -715,7 +889,13 @@ try_again: } /* 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. @@ -732,6 +912,9 @@ 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(); diff --git a/servers/slapd/back-bdb/compare.c b/servers/slapd/back-bdb/compare.c index e9c40dcbbc..ac799bb627 100644 --- a/servers/slapd/back-bdb/compare.c +++ b/servers/slapd/back-bdb/compare.c @@ -31,8 +31,14 @@ bdb_compare( 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: @@ -41,6 +47,9 @@ bdb_compare( 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"; @@ -56,7 +65,7 @@ bdb_compare( 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 { @@ -125,8 +134,10 @@ return_results: 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; } diff --git a/servers/slapd/back-bdb/delete.c b/servers/slapd/back-bdb/delete.c index dcaf399faf..9ded16580e 100644 --- a/servers/slapd/back-bdb/delete.c +++ b/servers/slapd/back-bdb/delete.c @@ -33,6 +33,9 @@ bdb_delete( 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; @@ -49,7 +52,7 @@ bdb_delete( 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, @@ -87,6 +90,8 @@ retry: /* transaction retry */ text = "internal error"; goto return_results; } + + locker = TXN_ID ( ltid ); #if 0 lockid = TXN_ID( ltid ); #endif @@ -111,7 +116,7 @@ retry: /* transaction retry */ } #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: @@ -147,7 +152,7 @@ retry: /* transaction retry */ 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 ) { @@ -226,7 +231,7 @@ retry: /* transaction retry */ } /* 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: @@ -263,7 +268,7 @@ retry: /* transaction retry */ 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 { @@ -465,7 +470,7 @@ return_results: 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 ) { diff --git a/servers/slapd/back-bdb/dn2entry.c b/servers/slapd/back-bdb/dn2entry.c index 00cd9efed7..a6440536f7 100644 --- a/servers/slapd/back-bdb/dn2entry.c +++ b/servers/slapd/back-bdb/dn2entry.c @@ -25,7 +25,9 @@ bdb_dn2entry_rw( Entry **e, Entry **matched, int flags, - int rw ) + int rw, + u_int32_t locker, + DB_LOCK *lock ) { int rc; ID id, id2 = 0; @@ -52,9 +54,9 @@ bdb_dn2entry_rw( } 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; diff --git a/servers/slapd/back-bdb/group.c b/servers/slapd/back-bdb/group.c index 2000de5209..6c2cdf1133 100644 --- a/servers/slapd/back-bdb/group.c +++ b/servers/slapd/back-bdb/group.c @@ -44,6 +44,9 @@ bdb_group( 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 { @@ -76,6 +79,11 @@ bdb_group( 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; @@ -88,12 +96,18 @@ bdb_group( 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) { @@ -106,6 +120,9 @@ bdb_group( "=> 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 @@ -211,7 +228,11 @@ bdb_group( 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 diff --git a/servers/slapd/back-bdb/id2entry.c b/servers/slapd/back-bdb/id2entry.c index 10ec1637a5..0a841cab21 100644 --- a/servers/slapd/back-bdb/id2entry.c +++ b/servers/slapd/back-bdb/id2entry.c @@ -80,13 +80,15 @@ int bdb_id2entry_rw( 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; @@ -97,7 +99,7 @@ int bdb_id2entry_rw( 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; } @@ -121,24 +123,36 @@ int bdb_id2entry_rw( 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 @@ -232,7 +246,7 @@ int bdb_entry_release( 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); diff --git a/servers/slapd/back-bdb/modify.c b/servers/slapd/back-bdb/modify.c index 184976e5e8..2e47ab49a5 100644 --- a/servers/slapd/back-bdb/modify.c +++ b/servers/slapd/back-bdb/modify.c @@ -249,6 +249,9 @@ bdb_modify( 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 @@ -259,7 +262,7 @@ bdb_modify( 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" )); @@ -295,13 +298,15 @@ retry: /* transaction retry */ 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 @@ -337,7 +342,7 @@ retry: /* transaction retry */ 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 { @@ -463,7 +468,7 @@ 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); } return rc; } diff --git a/servers/slapd/back-bdb/modrdn.c b/servers/slapd/back-bdb/modrdn.c index cb1e1517eb..0a7e1de7ee 100644 --- a/servers/slapd/back-bdb/modrdn.c +++ b/servers/slapd/back-bdb/modrdn.c @@ -56,6 +56,9 @@ bdb_modrdn( 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, @@ -78,13 +81,13 @@ bdb_modrdn( 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")); @@ -119,13 +122,15 @@ retry: /* transaction retry */ 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: @@ -152,7 +157,7 @@ retry: /* transaction retry */ 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 { @@ -199,7 +204,7 @@ retry: /* transaction retry */ /* 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: @@ -348,7 +353,7 @@ retry: /* transaction retry */ /* 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: @@ -855,17 +860,17 @@ done: /* 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 ) { diff --git a/servers/slapd/back-bdb/operational.c b/servers/slapd/back-bdb/operational.c index 08172b8c2d..d0517abf9e 100644 --- a/servers/slapd/back-bdb/operational.c +++ b/servers/slapd/back-bdb/operational.c @@ -44,9 +44,11 @@ bdb_operational( 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" )); diff --git a/servers/slapd/back-bdb/passwd.c b/servers/slapd/back-bdb/passwd.c index 0e05443926..25f0c654ed 100644 --- a/servers/slapd/back-bdb/passwd.c +++ b/servers/slapd/back-bdb/passwd.c @@ -41,6 +41,9 @@ bdb_exop_passwd( struct berval dn; struct berval ndn; + u_int32_t locker; + DB_LOCK lock; + assert( reqoid != NULL ); assert( strcmp( LDAP_EXOP_MODIFY_PASSWD, reqoid ) == 0 ); @@ -109,7 +112,7 @@ bdb_exop_passwd( 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" )); @@ -144,13 +147,15 @@ retry: /* transaction retry */ 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: @@ -256,7 +261,7 @@ retry: /* transaction retry */ 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 ) { diff --git a/servers/slapd/back-bdb/proto-bdb.h b/servers/slapd/back-bdb/proto-bdb.h index cdea9803e1..7cfe90293f 100644 --- a/servers/slapd/back-bdb/proto-bdb.h +++ b/servers/slapd/back-bdb/proto-bdb.h @@ -58,9 +58,9 @@ bdb_db_cache( * 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 @@ -152,9 +152,11 @@ int bdb_id2entry_rw( 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 ); @@ -301,13 +303,19 @@ BI_op_extended bdb_exop_passwd; */ 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, @@ -319,9 +327,12 @@ ID bdb_cache_find_entry_ndn2id( 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, diff --git a/servers/slapd/back-bdb/referral.c b/servers/slapd/back-bdb/referral.c index 3517492c79..4d60f68d0e 100644 --- a/servers/slapd/back-bdb/referral.c +++ b/servers/slapd/back-bdb/referral.c @@ -26,6 +26,9 @@ bdb_referrals( 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; @@ -36,8 +39,11 @@ bdb_referrals( 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: @@ -46,14 +52,18 @@ bdb_referrals( 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, @@ -65,13 +75,14 @@ bdb_referrals( 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; } @@ -97,7 +108,7 @@ bdb_referrals( 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; @@ -116,6 +127,7 @@ bdb_referrals( NULL, NULL ); } + LOCK_ID_FREE ( bdb->bi_dbenv, locker ); free( matched_dn ); return rc; } @@ -148,6 +160,7 @@ bdb_referrals( 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; } diff --git a/servers/slapd/back-bdb/search.c b/servers/slapd/back-bdb/search.c index 9887feb342..5dabe6b49f 100644 --- a/servers/slapd/back-bdb/search.c +++ b/servers/slapd/back-bdb/search.c @@ -59,6 +59,9 @@ bdb_search( 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 @@ -68,6 +71,8 @@ bdb_search( manageDSAit = get_manageDSAit( op ); + LOCK_ID (bdb->bi_dbenv, &locker ); + if ( nbase->bv_len == 0 ) { /* DIT root special case */ e = (Entry *) &slap_entry_root; @@ -81,7 +86,8 @@ bdb_search( } 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) { @@ -90,23 +96,28 @@ bdb_search( 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; } @@ -123,7 +134,7 @@ bdb_search( ? 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 ) { @@ -140,6 +151,7 @@ bdb_search( 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; @@ -154,7 +166,7 @@ bdb_search( 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 ) { @@ -175,6 +187,7 @@ bdb_search( 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; @@ -270,7 +283,7 @@ bdb_search( 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; @@ -320,14 +333,18 @@ bdb_search( 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) ) { @@ -456,7 +473,7 @@ bdb_search( 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, @@ -481,7 +498,7 @@ bdb_search( 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; @@ -509,7 +526,7 @@ bdb_search( 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; } @@ -524,9 +541,11 @@ loop_continue: 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 );