ITS#5439 fix ID_NOCACHE handling

This commit is contained in:
Howard Chu 2008-04-03 08:02:11 +00:00
parent f2de258e3d
commit 77e7b92c87

View File

@ -252,16 +252,27 @@ bdb_cache_return_entry_rw( struct bdb_info *bdb, Entry *e,
int free = 0; int free = 0;
ei = e->e_private; ei = e->e_private;
bdb_cache_entry_db_unlock( bdb, lock ); if ( ei &&
if ( ei ) { ( ei->bei_state & CACHE_ENTRY_NOT_CACHED ) &&
bdb_cache_entryinfo_lock( ei ); ( bdb_cache_entryinfo_trylock( ei ) == 0 )) {
if ( ei->bei_state & CACHE_ENTRY_NOT_CACHED ) { if ( ei->bei_state & CACHE_ENTRY_NOT_CACHED ) {
/* Releasing the entry can only be done when
* we know that nobody else is using it, i.e we
* should have an entry_db writelock. But the
* flag is only set by the thread that loads the
* entry, and only if no other threads has found
* it while it was working. All other threads
* clear the flag, which mean that we should be
* the only thread using the entry if the flag
* is set here.
*/
ei->bei_e = NULL; ei->bei_e = NULL;
ei->bei_state ^= CACHE_ENTRY_NOT_CACHED; ei->bei_state ^= CACHE_ENTRY_NOT_CACHED;
free = 1; free = 1;
} }
bdb_cache_entryinfo_unlock( ei ); bdb_cache_entryinfo_unlock( ei );
} }
bdb_cache_entry_db_unlock( bdb, lock );
if ( free ) { if ( free ) {
e->e_private = NULL; e->e_private = NULL;
bdb_entry_return( e ); bdb_entry_return( e );
@ -854,6 +865,11 @@ again: ldap_pvt_thread_rdwr_rlock( &bdb->bi_cache.c_rwlock );
/* Ok, we found the info, do we have the entry? */ /* Ok, we found the info, do we have the entry? */
if ( rc == 0 ) { if ( rc == 0 ) {
if ( !( flag & ID_LOCKED )) {
bdb_cache_entryinfo_lock( *eip );
flag |= ID_LOCKED;
}
if ( (*eip)->bei_state & CACHE_ENTRY_DELETED ) { if ( (*eip)->bei_state & CACHE_ENTRY_DELETED ) {
rc = DB_NOTFOUND; rc = DB_NOTFOUND;
} else { } else {
@ -873,13 +889,13 @@ load1:
(*eip)->bei_state |= CACHE_ENTRY_LOADING; (*eip)->bei_state |= CACHE_ENTRY_LOADING;
} }
/* If the entry was loaded before but uncached, and we need if ( !load ) {
* it again, clear the uncached state /* Clear the uncached state if we are not
*/ * loading it, i.e it is already cached or
if ( (*eip)->bei_state & CACHE_ENTRY_NOT_CACHED ) { * another thread is currently loading it.
(*eip)->bei_state ^= CACHE_ENTRY_NOT_CACHED; */
if ( flag & ID_NOCACHE ) (*eip)->bei_state &= ~CACHE_ENTRY_NOT_CACHED;
flag ^= ID_NOCACHE; flag &= ~ID_NOCACHE;
} }
if ( flag & ID_LOCKED ) { if ( flag & ID_LOCKED ) {
@ -906,9 +922,13 @@ load1:
#endif #endif
ep = NULL; ep = NULL;
bdb_cache_lru_link( bdb, *eip ); bdb_cache_lru_link( bdb, *eip );
if ( flag & ID_NOCACHE ) { if (( flag & ID_NOCACHE ) &&
bdb_cache_entryinfo_lock( *eip ); ( bdb_cache_entryinfo_trylock( *eip ) == 0 )) {
(*eip)->bei_state |= CACHE_ENTRY_NOT_CACHED; /* Set the cached state only if no other thread
* found the info while we was loading the entry.
*/
if ( (*eip)->bei_finders == 1 )
(*eip)->bei_state |= CACHE_ENTRY_NOT_CACHED;
bdb_cache_entryinfo_unlock( *eip ); bdb_cache_entryinfo_unlock( *eip );
} }
} }