X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=sidebyside;f=servers%2Fslapd%2Fback-bdb%2Fcache.c;h=6ca332131c9850f05e49984cdb3cd940d95717ec;hb=8f02c3f57578f6e35e89fcf73574c34108b41195;hp=f4de1cb9eab933420f065f6139e6dc20f1e52340;hpb=1adee08e8912c1f47c7b170fe62bebdd9797921f;p=openldap diff --git a/servers/slapd/back-bdb/cache.c b/servers/slapd/back-bdb/cache.c index f4de1cb9ea..6ca332131c 100644 --- a/servers/slapd/back-bdb/cache.c +++ b/servers/slapd/back-bdb/cache.c @@ -2,7 +2,7 @@ /* $OpenLDAP$ */ /* This work is part of OpenLDAP Software . * - * Copyright 2000-2010 The OpenLDAP Foundation. + * Copyright 2000-2011 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -101,6 +101,7 @@ bdb_cache_entryinfo_free( Cache *cache, EntryInfo *ei ) cache->c_eifree = ei; ldap_pvt_thread_mutex_unlock( &cache->c_eifree_mutex ); #else + ldap_pvt_thread_mutex_destroy( &ei->bei_kids_mutex ); ch_free( ei ); #endif } @@ -184,6 +185,7 @@ bdb_cache_entry_db_relock( if ( !lock ) return 0; + DBTzero( &lockobj ); lockobj.data = &ei->bei_id; lockobj.size = sizeof(ei->bei_id) + 1; @@ -225,6 +227,7 @@ bdb_cache_entry_db_lock( struct bdb_info *bdb, DB_TXN *txn, EntryInfo *ei, else db_rw = DB_LOCK_READ; + DBTzero( &lockobj ); lockobj.data = &ei->bei_id; lockobj.size = sizeof(ei->bei_id) + 1; @@ -262,9 +265,8 @@ bdb_cache_return_entry_rw( struct bdb_info *bdb, Entry *e, int free = 0; ei = e->e_private; - if ( ei && - ( ei->bei_state & CACHE_ENTRY_NOT_CACHED ) && - ( bdb_cache_entryinfo_trylock( ei ) == 0 )) { + if ( ei && ( ei->bei_state & CACHE_ENTRY_NOT_CACHED )) { + bdb_cache_entryinfo_lock( ei ); 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 @@ -440,7 +442,7 @@ bdb_cache_find_ndn( ei.bei_parent = eip; ei2 = (EntryInfo *)avl_find( eip->bei_kids, &ei, bdb_rdn_cmp ); if ( !ei2 ) { - DB_LOCK lock; + DBC *cursor; int len = ei.bei_nrdn.bv_len; if ( BER_BVISEMPTY( ndn )) { @@ -456,12 +458,12 @@ bdb_cache_find_ndn( BDB_LOG_PRINTF( bdb->bi_dbenv, NULL, "slapd Reading %s", ei.bei_nrdn.bv_val ); - lock.mode = DB_LOCK_NG; - rc = bdb_dn2id( op, &ei.bei_nrdn, &ei, txn, &lock ); + cursor = NULL; + rc = bdb_dn2id( op, &ei.bei_nrdn, &ei, txn, &cursor ); if (rc) { bdb_cache_entryinfo_lock( eip ); eip->bei_finders--; - bdb_cache_entry_db_unlock( bdb, &lock ); + if ( cursor ) cursor->c_close( cursor ); *res = eip; return rc; } @@ -475,22 +477,24 @@ bdb_cache_find_ndn( /* add_internal left eip and c_rwlock locked */ eip->bei_finders--; ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock ); - bdb_cache_entry_db_unlock( bdb, &lock ); + if ( cursor ) cursor->c_close( cursor ); if ( rc ) { *res = eip; return rc; } - } else if ( ei2->bei_state & CACHE_ENTRY_DELETED ) { + } + bdb_cache_entryinfo_lock( ei2 ); + if ( ei2->bei_state & CACHE_ENTRY_DELETED ) { /* In the midst of deleting? Give it a chance to * complete. */ + bdb_cache_entryinfo_unlock( ei2 ); bdb_cache_entryinfo_unlock( eip ); ldap_pvt_thread_yield(); bdb_cache_entryinfo_lock( eip ); *res = eip; return DB_NOTFOUND; } - bdb_cache_entryinfo_lock( ei2 ); bdb_cache_entryinfo_unlock( eip ); eip = ei2; @@ -963,6 +967,7 @@ load1: if ( !(*eip)->bei_e && !((*eip)->bei_state & CACHE_ENTRY_LOADING)) { load = 1; (*eip)->bei_state |= CACHE_ENTRY_LOADING; + flag |= ID_CHKPURGE; } if ( !load ) { @@ -971,12 +976,9 @@ load1: * another thread is currently loading it. */ if ( (*eip)->bei_state & CACHE_ENTRY_NOT_CACHED ) { - (*eip)->bei_state &= ~CACHE_ENTRY_NOT_CACHED; - ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_count_mutex ); - ++bdb->bi_cache.c_cursize; - ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex ); + (*eip)->bei_state ^= CACHE_ENTRY_NOT_CACHED; + flag |= ID_CHKPURGE; } - flag &= ~ID_NOCACHE; } if ( flag & ID_LOCKED ) { @@ -1002,21 +1004,24 @@ load1: ldap_pvt_thread_yield(); bdb_fix_dn( ep, 0 ); #endif + bdb_cache_entryinfo_lock( *eip ); + (*eip)->bei_e = ep; #ifdef SLAP_ZONE_ALLOC (*eip)->bei_zseq = *((ber_len_t *)ep - 2); #endif ep = NULL; - bdb_cache_lru_link( bdb, *eip ); - if (( flag & ID_NOCACHE ) && - ( bdb_cache_entryinfo_trylock( *eip ) == 0 )) { + if ( flag & ID_NOCACHE ) { /* Set the cached state only if no other thread * found the info while we were loading the entry. */ - if ( (*eip)->bei_finders == 1 ) + if ( (*eip)->bei_finders == 1 ) { (*eip)->bei_state |= CACHE_ENTRY_NOT_CACHED; - bdb_cache_entryinfo_unlock( *eip ); + flag ^= ID_CHKPURGE; + } } + bdb_cache_entryinfo_unlock( *eip ); + bdb_cache_lru_link( bdb, *eip ); } if ( rc == 0 ) { /* If we succeeded, downgrade back to a readlock. */ @@ -1072,9 +1077,9 @@ load1: if ( rc == 0 ) { int purge = 0; - if (( load && !( flag & ID_NOCACHE )) || bdb->bi_cache.c_eimax ) { + if (( flag & ID_CHKPURGE ) || bdb->bi_cache.c_eimax ) { ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_count_mutex ); - if ( load && !( flag & ID_NOCACHE )) { + if ( flag & ID_CHKPURGE ) { bdb->bi_cache.c_cursize++; if ( !bdb->bi_cache.c_purging && bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize ) { purge = 1; @@ -1141,6 +1146,7 @@ bdb_cache_add( ei.bei_nrdn = *nrdn; ei.bei_lockpad = 0; +#if 0 /* Lock this entry so that bdb_add can run to completion. * It can only fail if BDB has run out of lock resources. */ @@ -1149,6 +1155,7 @@ bdb_cache_add( bdb_cache_entryinfo_unlock( eip ); return rc; } +#endif #ifdef BDB_HIER if ( nrdn->bv_len != e->e_nname.bv_len ) { @@ -1192,6 +1199,7 @@ bdb_cache_add( } ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex ); + new->bei_finders = 1; bdb_cache_lru_link( bdb, new ); if ( purge ) @@ -1200,6 +1208,15 @@ bdb_cache_add( return rc; } +void bdb_cache_deref( + EntryInfo *ei + ) +{ + bdb_cache_entryinfo_lock( ei ); + ei->bei_finders--; + bdb_cache_entryinfo_unlock( ei ); +} + int bdb_cache_modify( struct bdb_info *bdb, @@ -1528,6 +1545,36 @@ bdb_cache_release_all( Cache *cache ) } #ifdef LDAP_DEBUG +static void +bdb_lru_count( Cache *cache ) +{ + EntryInfo *e; + int ei = 0, ent = 0, nc = 0; + + for ( e = cache->c_lrutail; ; ) { + ei++; + if ( e->bei_e ) { + ent++; + if ( e->bei_state & CACHE_ENTRY_NOT_CACHED ) + nc++; + fprintf( stderr, "ei %d entry %p dn %s\n", ei, (void *) e->bei_e, e->bei_e->e_name.bv_val ); + } + e = e->bei_lrunext; + if ( e == cache->c_lrutail ) + break; + } + fprintf( stderr, "counted %d entryInfos and %d entries, %d notcached\n", + ei, ent, nc ); + ei = 0; + for ( e = cache->c_lrutail; ; ) { + ei++; + e = e->bei_lruprev; + if ( e == cache->c_lrutail ) + break; + } + fprintf( stderr, "counted %d entryInfos (on lruprev)\n", ei ); +} + #ifdef SLAPD_UNUSED static void bdb_lru_print( Cache *cache )