X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fback-bdb%2Fcache.c;h=961c047e2bf5bac87f9a6ca3987c265196f22dc0;hb=08059f1633bfd9d0a709761b026bdb8e4441c6e6;hp=f26541a57c92b009d97dc56d21aec5a6b54e4413;hpb=4a8ab5dbf2ba037b0824d64bb3217ca06671884a;p=openldap diff --git a/servers/slapd/back-bdb/cache.c b/servers/slapd/back-bdb/cache.c index f26541a57c..961c047e2b 100644 --- a/servers/slapd/back-bdb/cache.c +++ b/servers/slapd/back-bdb/cache.c @@ -49,9 +49,9 @@ static int bdb_cache_entry_rdwr_lock(Entry *e, int rw) { #ifdef NEW_LOGGING - LDAP_LOG(( "cache", LDAP_LEVEL_ENTRY, - "bdb_cache_entry_rdwr_lock: %s lock on ID %ld\n", - rw ? "w" : "r", e->e_id )); + LDAP_LOG( CACHE, ENTRY, + "bdb_cache_entry_rdwr_lock: %s lock on ID %ld\n", + rw ? "w" : "r", e->e_id, 0 ); #else Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%slock: ID: %ld\n", rw ? "w" : "r", e->e_id, 0); @@ -67,9 +67,9 @@ static int bdb_cache_entry_rdwr_trylock(Entry *e, int rw) { #ifdef NEW_LOGGING - LDAP_LOG(( "cache", LDAP_LEVEL_ENTRY, - "bdb_cache_entry_rdwr_trylock: try %s lock on ID: %ld.\n", - rw ? "w" : "r", e->e_id )); + LDAP_LOG( CACHE, ENTRY, + "bdb_cache_entry_rdwr_trylock: try %s lock on ID: %ld.\n", + rw ? "w" : "r", e->e_id, 0 ); #else Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%strylock: ID: %ld\n", rw ? "w" : "r", e->e_id, 0); @@ -85,9 +85,9 @@ static int bdb_cache_entry_rdwr_unlock(Entry *e, int rw) { #ifdef NEW_LOGGING - LDAP_LOG(( "cache", LDAP_LEVEL_ENTRY, - "bdb_cache_entry_rdwr_unlock: remove %s lock on ID %ld.\n", - rw ? "w" : "r", e->e_id )); + LDAP_LOG( CACHE, ENTRY, + "bdb_cache_entry_rdwr_unlock: remove %s lock on ID %ld.\n", + rw ? "w" : "r", e->e_id, 0 ); #else Debug( LDAP_DEBUG_ARGS, "entry_rdwr_%sunlock: ID: %ld\n", rw ? "w" : "r", e->e_id, 0); @@ -132,6 +132,47 @@ 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); + if (rc) { +#ifdef NEW_LOGGING + LDAP_LOG( CACHE, DETAIL1, + "bdb_cache_entry_db_lock: entry %s, rw %d, rc %d\n", + e->e_nname.bv_val, rw, rc ); +#else + Debug( LDAP_DEBUG_TRACE, + "bdb_cache_entry_db_lock: entry %s, rw %d, rc %d\n", + e->e_nname.bv_val, rw, rc ); +#endif + } + 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,17 +203,20 @@ 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; - /* set cache mutex */ - ldap_pvt_thread_mutex_lock( &cache->c_mutex ); + /* set cache write lock */ + ldap_pvt_thread_rdwr_wlock( &cache->c_rwlock ); assert( e->e_private ); +#if 0 bdb_cache_entry_rdwr_unlock(e, rw); +#endif id = e->e_id; refcnt = --BEI(e)->bei_refcnt; @@ -183,7 +227,11 @@ bdb_cache_return_entry_rw( Cache *cache, Entry *e, int rw ) * 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 */ } @@ -191,13 +239,116 @@ bdb_cache_return_entry_rw( Cache *cache, Entry *e, int rw ) if ( BEI(e)->bei_state == CACHE_ENTRY_COMMITTED ) { BEI(e)->bei_state = CACHE_ENTRY_READY; - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); + /* free cache write lock */ + ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock ); #ifdef NEW_LOGGING - LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1, + LDAP_LOG( CACHE, DETAIL1, + "bdb_unlocked_cache_return_entry_rw: return (%ld):%s, refcnt=%d\n", + id, rw ? "w" : "r", refcnt ); +#else + Debug( LDAP_DEBUG_TRACE, + "====> bdb_unlocked_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, DETAIL1, + "bdb_unlocked_cache_return_entry_rw: %ld, delete pending (%d).\n", + id, refcnt, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, + "====> bdb_unlocked_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, DETAIL1, + "bdb_unlocked_cache_return_entry_rw: (%ld): deleted (%d)\n", + id, refcnt, 0 ); +#else + Debug( LDAP_DEBUG_TRACE, + "====> bdb_unlocked_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, DETAIL1, + "bdb_unlocked_cache_return_entry_rw: ID %ld:%s returned (%d)\n", + id, rw ? "w": "r", refcnt ); +#else + Debug( LDAP_DEBUG_TRACE, + "====> bdb_unlocked_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; + + /* + * 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, DETAIL1, "bdb_cache_return_entry_rw: return (%ld):%s, refcnt=%d\n", - id, rw ? "w" : "r", refcnt )); + id, rw ? "w" : "r", refcnt ); #else Debug( LDAP_DEBUG_TRACE, "====> bdb_cache_return_entry_%s( %ld ): created (%d)\n", @@ -207,13 +358,13 @@ bdb_cache_return_entry_rw( Cache *cache, Entry *e, int rw ) } else if ( BEI(e)->bei_state == CACHE_ENTRY_DELETED ) { if( refcnt > 0 ) { - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); + /* free cache write lock */ + ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock ); #ifdef NEW_LOGGING - LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1, + LDAP_LOG( CACHE, DETAIL1, "bdb_cache_return_entry_rw: %ld, delete pending (%d).\n", - id, refcnt )); + id, refcnt, 0 ); #else Debug( LDAP_DEBUG_TRACE, "====> bdb_cache_return_entry_%s( %ld ): delete pending (%d)\n", @@ -226,13 +377,13 @@ bdb_cache_return_entry_rw( Cache *cache, Entry *e, int rw ) bdb_entry_return( e ); } - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); + /* free cache write lock */ + ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock ); #ifdef NEW_LOGGING - LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1, + LDAP_LOG( CACHE, DETAIL1, "bdb_cache_return_entry_rw: (%ld): deleted (%d)\n", - id, refcnt )); + id, refcnt, 0 ); #else Debug( LDAP_DEBUG_TRACE, "====> bdb_cache_return_entry_%s( %ld ): deleted (%d)\n", @@ -241,13 +392,13 @@ bdb_cache_return_entry_rw( Cache *cache, Entry *e, int rw ) } } else { - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); + /* free cache write lock */ + ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock ); #ifdef NEW_LOGGING - LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1, + LDAP_LOG( CACHE, DETAIL1, "bdb_cache_return_entry_rw: ID %ld:%s returned (%d)\n", - id, rw ? "w": "r", refcnt )); + id, rw ? "w": "r", refcnt ); #else Debug( LDAP_DEBUG_TRACE, "====> bdb_cache_return_entry_%s( %ld ): returned (%d)\n", @@ -286,35 +437,39 @@ 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; Entry *ee; #ifdef NEW_LOGGING - LDAP_LOG(( "cache", LDAP_LEVEL_ENTRY, - "bdb_cache_add_entry_rw: add (%s):%s to cache\n", - e->e_dn, rw ? "w" : "r" )); + LDAP_LOG( CACHE, ENTRY, + "bdb_cache_add_entry_rw: add (%s):%s to cache\n", + e->e_dn, rw ? "w" : "r", 0 ); #endif - /* set cache mutex */ - ldap_pvt_thread_mutex_lock( &cache->c_mutex ); + /* set cache write lock */ + ldap_pvt_thread_rdwr_wlock( &cache->c_rwlock ); assert( e->e_private == NULL ); if( bdb_cache_entry_private_init(e) != 0 ) { - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); + /* free cache write lock */ + ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock ); #ifdef NEW_LOGGING - LDAP_LOG(( "cache", LDAP_LEVEL_ERR, - "bdb_cache_add_entry_rw: add (%s):%ld private init failed!\n", - e->e_dn, e->e_id )); + LDAP_LOG( CACHE, ERR, + "bdb_cache_add_entry_rw: add (%s):%ld private init failed!\n", + e->e_dn, e->e_id, 0 ); #else Debug( LDAP_DEBUG_ANY, "====> bdb_cache_add_entry( %ld ): \"%s\": private init failed!\n", @@ -328,13 +483,13 @@ bdb_cache_add_entry_rw( if ( avl_insert( &cache->c_dntree, (caddr_t) e, (AVL_CMP) entry_dn_cmp, avl_dup_error ) != 0 ) { - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); + /* free cache write lock */ + ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock ); #ifdef NEW_LOGGING - LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1, - "bdb_cache_add_entry: (%s):%ld already in cache.\n", - e->e_dn, e->e_id )); + LDAP_LOG( CACHE, DETAIL1, + "bdb_cache_add_entry: (%s):%ld already in cache.\n", + e->e_dn, e->e_id, 0 ); #else Debug( LDAP_DEBUG_TRACE, "====> bdb_cache_add_entry( %ld ): \"%s\": already in dn cache\n", @@ -351,9 +506,9 @@ bdb_cache_add_entry_rw( (AVL_CMP) entry_id_cmp, avl_dup_error ) != 0 ) { #ifdef NEW_LOGGING - LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1, - "bdb_cache_add_entry: (%s):%ls already in cache.\n", - e->e_dn, e->e_id )); + LDAP_LOG( CACHE, DETAIL1, + "bdb_cache_add_entry: (%s):%ls already in cache.\n", + e->e_dn, e->e_id, 0 ); #else Debug( LDAP_DEBUG_ANY, "====> bdb_cache_add_entry( %ld ): \"%s\": already in id cache\n", @@ -365,9 +520,9 @@ bdb_cache_add_entry_rw( (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 )); + LDAP_LOG( CACHE, INFO, + "bdb_cache_add_entry: can't delete (%s) from cache.\n", + e->e_dn, 0, 0 ); #else Debug( LDAP_DEBUG_ANY, "====> can't delete from dn cache\n", 0, 0, 0 ); @@ -376,18 +531,52 @@ bdb_cache_add_entry_rw( bdb_cache_entry_private_destroy(e); - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); + /* free cache write lock */ + ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock ); 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, INFO, + "bdb_cache_add_entry: can't delete (%s) from cache.\n", + e->e_dn, 0, 0 ); +#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, INFO, + "bdb_cache_add_entry: can't delete (%s) from cache.\n", + e->e_dn, 0, 0 ); +#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 */ BEI(e)->bei_state = CACHE_ENTRY_CREATING; BEI(e)->bei_refcnt = 1; + /* set lru mutex */ + ldap_pvt_thread_mutex_lock( &cache->lru_mutex ); /* lru */ LRU_ADD( cache, e ); if ( ++cache->c_cursize > cache->c_maxsize ) { @@ -426,8 +615,10 @@ bdb_cache_add_entry_rw( } } - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); + /* free lru mutex */ + ldap_pvt_thread_mutex_unlock( &cache->lru_mutex ); + /* free cache write lock */ + ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock ); return( 0 ); } @@ -446,8 +637,8 @@ bdb_cache_update_entry( int i, rc; Entry *ee; - /* set cache mutex */ - ldap_pvt_thread_mutex_lock( &cache->c_mutex ); + /* set cache write lock */ + ldap_pvt_thread_rdwr_wlock( &cache->c_rwlock ); assert( e->e_private ); @@ -455,17 +646,17 @@ bdb_cache_update_entry( (AVL_CMP) entry_dn_cmp, avl_dup_error ) != 0 ) { #ifdef NEW_LOGGING - LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1, - "bdb_cache_update_entry: (%s):%ld already in dn cache\n", - e->e_dn, e->e_id )); + LDAP_LOG( CACHE, DETAIL1, + "bdb_cache_update_entry: (%s):%ld already in dn cache\n", + e->e_dn, e->e_id, 0 ); #else Debug( LDAP_DEBUG_TRACE, "====> bdb_cache_update_entry( %ld ): \"%s\": already in dn cache\n", e->e_id, e->e_dn, 0 ); #endif - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); + /* free cache write lock */ + ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock ); return( 1 ); } @@ -474,9 +665,9 @@ bdb_cache_update_entry( (AVL_CMP) entry_id_cmp, avl_dup_error ) != 0 ) { #ifdef NEW_LOGGING - LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1, - "bdb_cache_update_entry: (%s)%ld already in id cache\n", - e->e_dn, e->e_id )); + LDAP_LOG( CACHE, DETAIL1, + "bdb_cache_update_entry: (%s)%ld already in id cache\n", + e->e_dn, e->e_id, 0 ); #else Debug( LDAP_DEBUG_ANY, "====> bdb_cache_update_entry( %ld ): \"%s\": already in id cache\n", @@ -488,17 +679,17 @@ bdb_cache_update_entry( (AVL_CMP) entry_dn_cmp ) == NULL ) { #ifdef NEW_LOGGING - LDAP_LOG(( "cache", LDAP_LEVEL_INFO, - "bdb_cache_update_entry: can't delete (%s)%ld from dn cache.\n", - e->e_dn, e->e_id )); + LDAP_LOG( CACHE, INFO, + "bdb_cache_update_entry: can't delete (%s)%ld from dn cache.\n", + e->e_dn, e->e_id, 0 ); #else Debug( LDAP_DEBUG_ANY, "====> can't delete from dn cache\n", 0, 0, 0 ); #endif } - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); + /* free cache write lock */ + ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock ); return( -1 ); } @@ -507,6 +698,8 @@ bdb_cache_update_entry( /* will be marked after when entry is returned */ BEI(e)->bei_state = CACHE_ENTRY_CREATING; + /* set lru mutex */ + ldap_pvt_thread_mutex_lock( &cache->lru_mutex ); /* lru */ LRU_ADD( cache, e ); if ( ++cache->c_cursize > cache->c_maxsize ) { @@ -545,8 +738,10 @@ bdb_cache_update_entry( } } - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); + /* free lru mutex */ + ldap_pvt_thread_mutex_unlock( &cache->lru_mutex ); + /* free cache write lock */ + ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock ); return( 0 ); } @@ -565,8 +760,8 @@ bdb_cache_find_entry_ndn2id( e.e_nname = *ndn; try_again: - /* set cache mutex */ - ldap_pvt_thread_mutex_lock( &cache->c_mutex ); + /* set cache read lock */ + ldap_pvt_thread_rdwr_rlock( &cache->c_rwlock ); if ( (ep = (Entry *) avl_find( cache->c_dntree, (caddr_t) &e, (AVL_CMP) entry_dn_cmp )) != NULL ) @@ -592,13 +787,13 @@ try_again: if ( state != CACHE_ENTRY_READY ) { assert(state != CACHE_ENTRY_UNDEFINED); - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); + /* free cache read lock */ + ldap_pvt_thread_rdwr_runlock( &cache->c_rwlock ); #ifdef NEW_LOGGING - LDAP_LOG(( "cache", LDAP_LEVEL_INFO, - "bdb_cache_find_entry_dn2id: (%s) %ld not ready: %d\n", - ndn->bv_val, id, state )); + LDAP_LOG( CACHE, INFO, + "bdb_cache_find_entry_dn2id: (%s) %ld not ready: %d\n", + ndn->bv_val, id, state ); #else Debug(LDAP_DEBUG_TRACE, "====> bdb_cache_find_entry_dn2id(\"%s\"): %ld (not ready) %d\n", @@ -610,17 +805,23 @@ try_again: goto try_again; } + /* free cache read lock */ + ldap_pvt_thread_rdwr_runlock( &cache->c_rwlock ); + + /* set lru mutex */ + ldap_pvt_thread_mutex_lock( &cache->lru_mutex ); + /* lru */ LRU_DELETE( cache, ep ); LRU_ADD( cache, ep ); - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); + /* free lru mutex */ + ldap_pvt_thread_mutex_unlock( &cache->lru_mutex ); #ifdef NEW_LOGGING - LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1, - "bdb_cache_find_entry_dn2id: (%s): %ld %d tries\n", - ndn->bv_val, id, count )); + LDAP_LOG( CACHE, DETAIL1, + "bdb_cache_find_entry_dn2id: (%s): %ld %d tries\n", + ndn->bv_val, id, count ); #else Debug(LDAP_DEBUG_TRACE, "====> bdb_cache_find_entry_dn2id(\"%s\"): %ld (%d tries)\n", @@ -628,8 +829,8 @@ try_again: #endif } else { - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); + /* free cache read lock */ + ldap_pvt_thread_rdwr_runlock( &cache->c_rwlock ); id = NOID; } @@ -643,20 +844,24 @@ 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; try_again: - /* set cache mutex */ - ldap_pvt_thread_mutex_lock( &cache->c_mutex ); + /* set cache read lock */ + ldap_pvt_thread_rdwr_rlock( &cache->c_rwlock ); if ( (ep = (Entry *) avl_find( cache->c_idtree, (caddr_t) &e, (AVL_CMP) entry_id_cmp )) != NULL ) @@ -678,13 +883,13 @@ try_again: assert(state != CACHE_ENTRY_UNDEFINED); - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); + /* free cache read lock */ + ldap_pvt_thread_rdwr_runlock( &cache->c_rwlock ); #ifdef NEW_LOGGING - LDAP_LOG(( "cache", LDAP_LEVEL_INFO, - "bdb_cache_find_entry_id: (%ld)->%ld not ready (%d).\n", - id, ep_id, state )); + LDAP_LOG( CACHE, INFO, + "bdb_cache_find_entry_id: (%ld)->%ld not ready (%d).\n", + id, ep_id, state ); #else Debug(LDAP_DEBUG_TRACE, @@ -697,42 +902,55 @@ 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. */ - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); + /* free cache read lock */ + ldap_pvt_thread_rdwr_runlock( &cache->c_rwlock ); #ifdef NEW_LOGGING - LDAP_LOG(( "cache", LDAP_LEVEL_INFO, - "bdb_cache_find_entry_id: %ld -> %ld (busy) %d.\n", - id, ep_id, state )); + LDAP_LOG( CACHE, INFO, + "bdb_cache_find_entry_id: %ld -> %ld (busy) %d.\n", + id, ep_id, state ); #else 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(); goto try_again; } + /* free cache read lock */ + ldap_pvt_thread_rdwr_runlock( &cache->c_rwlock ); + /* set lru mutex */ + ldap_pvt_thread_mutex_lock( &cache->lru_mutex ); /* lru */ LRU_DELETE( cache, ep ); LRU_ADD( cache, ep ); BEI(ep)->bei_refcnt++; - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); + /* free lru mutex */ + ldap_pvt_thread_mutex_unlock( &cache->lru_mutex ); #ifdef NEW_LOGGING - LDAP_LOG(( "cache", LDAP_LEVEL_DETAIL1, - "bdb_cache_find_entry_id: %ld -> %s found %d tries.\n", - ep_id, ep->e_dn, count )); + LDAP_LOG( CACHE, DETAIL1, + "bdb_cache_find_entry_id: %ld -> %s found %d tries.\n", + ep_id, ep->e_dn, count ); #else Debug(LDAP_DEBUG_TRACE, "====> bdb_cache_find_entry_id( %ld ) \"%s\" (found) (%d tries)\n", @@ -743,8 +961,8 @@ try_again: return( ep ); } - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); + /* free cache read lock */ + ldap_pvt_thread_rdwr_runlock( &cache->c_rwlock ); return( NULL ); } @@ -768,23 +986,27 @@ bdb_cache_delete_entry( { int rc; - /* set cache mutex */ - ldap_pvt_thread_mutex_lock( &cache->c_mutex ); + /* set cache write lock */ + ldap_pvt_thread_rdwr_wlock( &cache->c_rwlock ); assert( e->e_private ); #ifdef NEW_LOGGING - LDAP_LOG(( "cache", LDAP_LEVEL_ENTRY, - "bdb_cache_delete_entry: delete %ld.\n", e->e_id )); + LDAP_LOG( CACHE, ENTRY, + "bdb_cache_delete_entry: delete %ld.\n", e->e_id, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "====> bdb_cache_delete_entry( %ld )\n", e->e_id, 0, 0 ); #endif + /* set lru mutex */ + ldap_pvt_thread_mutex_lock( &cache->lru_mutex ); rc = bdb_cache_delete_entry_internal( cache, e ); + /* free lru mutex */ + ldap_pvt_thread_mutex_unlock( &cache->lru_mutex ); - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); + /* free cache write lock */ + ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock ); return( rc ); } @@ -832,12 +1054,13 @@ bdb_cache_release_all( Cache *cache ) Entry *e; int rc; - /* set cache mutex */ - ldap_pvt_thread_mutex_lock( &cache->c_mutex ); + /* set cache write lock */ + ldap_pvt_thread_rdwr_wlock( &cache->c_rwlock ); + /* set lru mutex */ + ldap_pvt_thread_mutex_lock( &cache->lru_mutex ); #ifdef NEW_LOGGING - LDAP_LOG(( "cache", LDAP_LEVEL_ENTRY, - "bdb_cache_release_all: enter\n" )); + LDAP_LOG( CACHE, ENTRY, "bdb_cache_release_all: enter\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "====> bdb_cache_release_all\n", 0, 0, 0 ); #endif @@ -856,16 +1079,18 @@ bdb_cache_release_all( Cache *cache ) if ( cache->c_cursize ) { #ifdef NEW_LOGGING - LDAP_LOG(( "cache", LDAP_LEVEL_INFO, - "bdb_cache_release_all: Entry cache could not be emptied.\n" )); + LDAP_LOG( CACHE, INFO, + "bdb_cache_release_all: Entry cache could not be emptied.\n", 0, 0, 0 ); #else Debug( LDAP_DEBUG_TRACE, "Entry-cache could not be emptied\n", 0, 0, 0 ); #endif } - /* free cache mutex */ - ldap_pvt_thread_mutex_unlock( &cache->c_mutex ); + /* free lru mutex */ + ldap_pvt_thread_mutex_unlock( &cache->lru_mutex ); + /* free cache write lock */ + ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock ); } #ifdef LDAP_DEBUG @@ -886,3 +1111,57 @@ bdb_lru_print( Cache *cache ) } } #endif + +#ifdef BDB_REUSE_LOCKERS +void +bdb_locker_id_free( void *key, void *data ) +{ + DB_ENV *env = key; + int lockid = (int) data; + + XLOCK_ID_FREE( env, lockid ); +} + +int +bdb_locker_id( Operation *op, DB_ENV *env, int *locker ) +{ + int i, rc, lockid; + void *data; + + if ( !env || !op || !locker ) return -1; + + /* Shouldn't happen unless we're single-threaded */ + if ( !op->o_threadctx ) { + *locker = 0; + return 0; + } + + if ( ldap_pvt_thread_pool_getkey( op->o_threadctx, env, &data, NULL ) ) { + for ( i=0, rc=1; rc != 0 && i<4; i++ ) { + rc = XLOCK_ID( env, &lockid ); + if (rc) ldap_pvt_thread_yield(); + } + if ( rc != 0) { + return rc; + } + data = (void *)lockid; + if ( ( rc = ldap_pvt_thread_pool_setkey( op->o_threadctx, env, + data, bdb_locker_id_free ) ) ) { + XLOCK_ID_FREE( env, lockid ); +#ifdef NEW_LOGGING + LDAP_LOG( BACK_BDB, ERR, "bdb_locker_id: err %s(%d)\n", + db_strerror(rc), rc, 0 ); +#else + Debug( LDAP_DEBUG_ANY, "bdb_locker_id: err %s(%d)\n", + db_strerror(rc), rc, 0 ); +#endif + + return rc; + } + } else { + lockid = (int)data; + } + *locker = lockid; + return 0; +} +#endif