X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fback-bdb%2Fcache.c;h=6ca332131c9850f05e49984cdb3cd940d95717ec;hb=8f02c3f57578f6e35e89fcf73574c34108b41195;hp=a6ba2b9b369dddd2ce459d10f4c7af88115edab9;hpb=e2fdc9a02ad824ba9f977ca8b8586b0dc22b4aee;p=openldap diff --git a/servers/slapd/back-bdb/cache.c b/servers/slapd/back-bdb/cache.c index a6ba2b9b36..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-2009 The OpenLDAP Foundation. + * Copyright 2000-2011 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -101,15 +101,20 @@ 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 } #define LRU_DEL( c, e ) do { \ - if ( e == (c)->c_lruhead ) (c)->c_lruhead = e->bei_lruprev; \ - if ( e == (c)->c_lrutail ) (c)->c_lrutail = e->bei_lruprev; \ - e->bei_lrunext->bei_lruprev = e->bei_lruprev; \ - e->bei_lruprev->bei_lrunext = e->bei_lrunext; \ + if ( e == e->bei_lruprev ) { \ + (c)->c_lruhead = (c)->c_lrutail = NULL; \ + } else { \ + if ( e == (c)->c_lruhead ) (c)->c_lruhead = e->bei_lruprev; \ + if ( e == (c)->c_lrutail ) (c)->c_lrutail = e->bei_lruprev; \ + e->bei_lrunext->bei_lruprev = e->bei_lruprev; \ + e->bei_lruprev->bei_lrunext = e->bei_lrunext; \ + } \ e->bei_lruprev = NULL; \ } while ( 0 ) @@ -180,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; @@ -221,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; @@ -258,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 @@ -436,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 )) { @@ -452,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; } @@ -471,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; @@ -959,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 ) { @@ -967,9 +976,9 @@ load1: * another thread is currently loading it. */ if ( (*eip)->bei_state & CACHE_ENTRY_NOT_CACHED ) { - (*eip)->bei_state &= ~CACHE_ENTRY_NOT_CACHED; + (*eip)->bei_state ^= CACHE_ENTRY_NOT_CACHED; + flag |= ID_CHKPURGE; } - flag &= ~ID_NOCACHE; } if ( flag & ID_LOCKED ) { @@ -995,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. */ @@ -1065,20 +1077,17 @@ load1: if ( rc == 0 ) { int purge = 0; - if ( bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize || - ( bdb->bi_cache.c_eimax && bdb->bi_cache.c_leaves > 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 ( !bdb->bi_cache.c_purging ) { - if ( load && !( flag & ID_NOCACHE )) { - bdb->bi_cache.c_cursize++; - if ( bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize ) { - purge = 1; - bdb->bi_cache.c_purging = 1; - } - } else if ( bdb->bi_cache.c_eimax && bdb->bi_cache.c_leaves > bdb->bi_cache.c_eimax ) { + 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; bdb->bi_cache.c_purging = 1; } + } else if ( !bdb->bi_cache.c_purging && bdb->bi_cache.c_eimax && bdb->bi_cache.c_leaves > bdb->bi_cache.c_eimax ) { + purge = 1; + bdb->bi_cache.c_purging = 1; } ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex ); } @@ -1137,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. */ @@ -1145,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 ) { @@ -1188,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 ) @@ -1196,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, @@ -1524,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 )