X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=servers%2Fslapd%2Fback-bdb%2Fcache.c;h=f4de1cb9eab933420f065f6139e6dc20f1e52340;hb=1adee08e8912c1f47c7b170fe62bebdd9797921f;hp=216816c6ca7ed1a44fa8bdfa536ead2edfbef2de;hpb=bc05508d28d6520002fcdc173bfa8e85b95e8a9f;p=openldap diff --git a/servers/slapd/back-bdb/cache.c b/servers/slapd/back-bdb/cache.c index 216816c6ca..f4de1cb9ea 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-2010 The OpenLDAP Foundation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -38,6 +38,7 @@ static int bdb_cache_delete_internal(Cache *cache, EntryInfo *e, int decr); #define SLAPD_UNUSED #ifdef SLAPD_UNUSED static void bdb_lru_print(Cache *cache); +static void bdb_idtree_print(Cache *cache); #endif #endif @@ -105,10 +106,14 @@ bdb_cache_entryinfo_free( Cache *cache, EntryInfo *ei ) } #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 ) @@ -564,7 +569,7 @@ again: bdb_id_cmp, bdb_id_dup_err ) ) { EntryInfo *eix = ein->bei_lrunext; - if ( eix->bei_state & (CACHE_ENTRY_PURGED|CACHE_ENTRY_DELETED) ) { + if ( bdb_cache_entryinfo_trylock( eix )) { ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock ); ldap_pvt_thread_yield(); goto again; @@ -580,7 +585,6 @@ again: if ( eir == ein ) { *res = eix; rc = 0; - bdb_cache_entryinfo_lock( eix ); break; } @@ -596,26 +600,28 @@ again: if ( ei2 ) ei2->bei_parent = ein; /* Look for this node's parent */ +par2: if ( eip.bei_id ) { ei2 = (EntryInfo *) avl_find( bdb->bi_cache.c_idtree, (caddr_t) &eip, bdb_id_cmp ); - if ( ei2 && ( ei2->bei_state & ( CACHE_ENTRY_PURGED|CACHE_ENTRY_DELETED ))) { - ei2 = NULL; - } } else { ei2 = &bdb->bi_cache.c_dntree; } - if ( add ) { - bdb->bi_cache.c_eiused++; - if ( ei2 && ( ei2->bei_kids || !ei2->bei_id )) - bdb->bi_cache.c_leaves++; + if ( ei2 && bdb_cache_entryinfo_trylock( ei2 )) { + ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock ); + ldap_pvt_thread_yield(); + ldap_pvt_thread_rdwr_wlock( &bdb->bi_cache.c_rwlock ); + goto par2; } + if ( add ) + bdb->bi_cache.c_eiused++; + if ( ei2 && ( ei2->bei_kids || !ei2->bei_id )) + bdb->bi_cache.c_leaves++; ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock ); gotparent: /* Got the parent, link in and we're done. */ if ( ei2 ) { - bdb_cache_entryinfo_lock( ei2 ); bdb_cache_entryinfo_lock( eir ); ein->bei_parent = ei2; @@ -628,6 +634,7 @@ gotparent: ein->bei_state &= ~CACHE_ENTRY_NOT_LINKED; bdb_cache_entryinfo_unlock( ei2 ); + eir->bei_finders--; *res = eir; break; @@ -686,8 +693,9 @@ bdb_cache_lru_purge( struct bdb_info *bdb ) { DB_LOCK lock, *lockp; EntryInfo *elru, *elnext = NULL; - int count, islocked, eimax; - int efree = 0, eifree = 0, eicount, ecount; + int islocked; + ID eicount, ecount; + ID count, efree, eifree = 0; #ifdef LDAP_DEBUG int iter; #endif @@ -695,24 +703,24 @@ bdb_cache_lru_purge( struct bdb_info *bdb ) /* Wait for the mutex; we're the only one trying to purge. */ ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_lru_mutex ); + if ( bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize ) { + efree = bdb->bi_cache.c_cursize - bdb->bi_cache.c_maxsize; + efree += bdb->bi_cache.c_minfree; + } else { + efree = 0; + } + /* maximum number of EntryInfo leaves to cache. In slapcat * we always free all leaf nodes. */ - if ( slapMode & SLAP_TOOL_READONLY ) - eimax = 0; - else - eimax = bdb->bi_cache.c_eimax; - efree = bdb->bi_cache.c_cursize - bdb->bi_cache.c_maxsize; - if ( efree < 1 ) - efree = 0; - else - efree += bdb->bi_cache.c_minfree; - - if ( bdb->bi_cache.c_leaves > eimax ) { + if ( slapMode & SLAP_TOOL_READONLY ) { + eifree = bdb->bi_cache.c_leaves; + } else if ( bdb->bi_cache.c_eimax && + bdb->bi_cache.c_leaves > bdb->bi_cache.c_eimax ) { eifree = bdb->bi_cache.c_minfree * 10; - if ( eifree >= eimax ) - eifree = eimax / 2; + if ( eifree >= bdb->bi_cache.c_leaves ) + eifree /= 2; } if ( !efree && !eifree ) { @@ -964,6 +972,9 @@ load1: */ 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 ); } flag &= ~ID_NOCACHE; } @@ -976,6 +987,9 @@ load1: if ( (*eip)->bei_state & CACHE_ENTRY_DELETED ) { rc = DB_NOTFOUND; bdb_cache_entry_db_unlock( bdb, lock ); + bdb_cache_entryinfo_lock( *eip ); + (*eip)->bei_finders--; + bdb_cache_entryinfo_unlock( *eip ); } else if ( rc == 0 ) { if ( load ) { if ( !ep) { @@ -1036,12 +1050,12 @@ load1: } #endif } + bdb_cache_entryinfo_lock( *eip ); + (*eip)->bei_finders--; + if ( load ) + (*eip)->bei_state ^= CACHE_ENTRY_LOADING; + bdb_cache_entryinfo_unlock( *eip ); } - bdb_cache_entryinfo_lock( *eip ); - (*eip)->bei_finders--; - if ( load ) - (*eip)->bei_state ^= CACHE_ENTRY_LOADING; - bdb_cache_entryinfo_unlock( *eip ); } } if ( flag & ID_LOCKED ) { @@ -1058,20 +1072,17 @@ load1: if ( rc == 0 ) { int purge = 0; - if ( bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize || - bdb->bi_cache.c_leaves > bdb->bi_cache.c_eimax ) { + if (( load && !( flag & ID_NOCACHE )) || 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_leaves > bdb->bi_cache.c_eimax ) { + if ( load && !( flag & ID_NOCACHE )) { + 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 ); } @@ -1333,7 +1344,7 @@ bdb_cache_delete( DB_LOCK *lock ) { EntryInfo *ei = BEI(e); - int rc; + int rc, busy = 0; assert( e->e_private != NULL ); @@ -1343,8 +1354,24 @@ bdb_cache_delete( /* Set this early, warn off any queriers */ ei->bei_state |= CACHE_ENTRY_DELETED; + if (( ei->bei_state & ( CACHE_ENTRY_NOT_LINKED | + CACHE_ENTRY_LOADING | CACHE_ENTRY_ONELEVEL )) || + ei->bei_finders > 0 ) + busy = 1; + bdb_cache_entryinfo_unlock( ei ); + while ( busy ) { + ldap_pvt_thread_yield(); + busy = 0; + bdb_cache_entryinfo_lock( ei ); + if (( ei->bei_state & ( CACHE_ENTRY_NOT_LINKED | + CACHE_ENTRY_LOADING | CACHE_ENTRY_ONELEVEL )) || + ei->bei_finders > 0 ) + busy = 1; + bdb_cache_entryinfo_unlock( ei ); + } + /* Get write lock on the data */ rc = bdb_cache_entry_db_relock( bdb, txn, ei, 1, 0, lock ); if ( rc ) { @@ -1411,8 +1438,6 @@ bdb_cache_delete_internal( return -1; } - e->bei_state |= CACHE_ENTRY_PURGED; - #ifdef BDB_HIER e->bei_parent->bei_ckids--; if ( decr && e->bei_parent->bei_dkids ) e->bei_parent->bei_dkids--; @@ -1527,6 +1552,21 @@ bdb_lru_print( Cache *cache ) break; } } + +static int +bdb_entryinfo_print(void *data, void *arg) +{ + EntryInfo *e = data; + fprintf( stderr, "\t%p, %p id %ld rdn \"%s\"\n", + (void *) e, (void *) e->bei_e, e->bei_id, e->bei_nrdn.bv_val ); + return 0; +} + +static void +bdb_idtree_print(Cache *cache) +{ + avl_apply( cache->c_idtree, bdb_entryinfo_print, NULL, -1, AVL_INORDER ); +} #endif #endif