]> git.sur5r.net Git - openldap/commitdiff
Partially revert prev commit, fix lru_purge loop
authorHoward Chu <hyc@openldap.org>
Thu, 4 Jan 2007 11:01:59 +0000 (11:01 +0000)
committerHoward Chu <hyc@openldap.org>
Thu, 4 Jan 2007 11:01:59 +0000 (11:01 +0000)
servers/slapd/back-bdb/back-bdb.h
servers/slapd/back-bdb/cache.c
servers/slapd/back-bdb/init.c

index 534062b53d7d72c8989f614e6e5a3ceaef725581..dd343ca49479d852da34ab45d38616dd63fa0c38 100644 (file)
@@ -95,6 +95,7 @@ typedef struct bdb_entry_info {
 #define        CACHE_ENTRY_WALKING     0x20
 #define        CACHE_ENTRY_ONELEVEL    0x40
 #define        CACHE_ENTRY_REFERENCED  0x80
+       int bei_finders;
 
        /*
         * remaining fields require backend cache lock to access
@@ -132,9 +133,9 @@ typedef struct bdb_cache {
        int             c_minfree;
        int             c_eiused;       /* EntryInfo's in use */
        int             c_leaves;       /* EntryInfo leaf nodes */
+       u_int32_t       c_locker;       /* used by lru cleaner */
        ldap_pvt_thread_rdwr_t c_rwlock;
-       ldap_pvt_thread_mutex_t lru_head_mutex;
-       ldap_pvt_thread_mutex_t lru_tail_mutex;
+       ldap_pvt_thread_mutex_t c_lru_mutex;
        ldap_pvt_thread_mutex_t c_count_mutex;
        ldap_pvt_thread_mutex_t c_eifree_mutex;
 #ifdef SLAP_ZONE_ALLOC
index 7064c576b393afafb991b123a34165a237fd9f34..6dfe69306cc3bf07a5a78637738c21fe6ad6813b 100644 (file)
@@ -31,7 +31,7 @@
 #ifdef BDB_HIER
 #define bdb_cache_lru_purge    hdb_cache_lru_purge
 #endif
-static void bdb_cache_lru_purge( struct bdb_info *bdb, uint32_t locker );
+static void bdb_cache_lru_purge( struct bdb_info *bdb );
 
 static int     bdb_cache_delete_internal(Cache *cache, EntryInfo *e, int decr);
 #ifdef LDAP_DEBUG
@@ -71,6 +71,7 @@ bdb_cache_entryinfo_new( Cache *cache )
        }
 
        ei->bei_state = CACHE_ENTRY_REFERENCED;
+       ei->bei_finders = 0;
 
        return ei;
 }
@@ -87,7 +88,7 @@ static void
 bdb_cache_lru_link( Cache *cache, EntryInfo *ei )
 {
        /* Insert into circular LRU list */
-       ldap_pvt_thread_mutex_lock( &cache->lru_tail_mutex );
+       ldap_pvt_thread_mutex_lock( &cache->c_lru_mutex );
        ei->bei_lruprev = cache->c_lrutail;
        if ( cache->c_lrutail ) {
                ei->bei_lrunext = cache->c_lrutail->bei_lrunext;
@@ -99,7 +100,7 @@ bdb_cache_lru_link( Cache *cache, EntryInfo *ei )
                cache->c_lruhead = ei;
        }
        cache->c_lrutail = ei;
-       ldap_pvt_thread_mutex_unlock( &cache->lru_tail_mutex );
+       ldap_pvt_thread_mutex_unlock( &cache->c_lru_mutex );
 }
 
 #ifdef NO_THREADS
@@ -555,24 +556,35 @@ int hdb_cache_load(
 #endif
 
 static void
-bdb_cache_lru_purge( struct bdb_info *bdb, uint32_t locker )
+bdb_cache_lru_purge( struct bdb_info *bdb )
 {
-       DB_LOCK         lock;
+       DB_LOCK         lock, *lockp;
        EntryInfo *elru, *elnext;
-       int count, islocked;
+       int i, count, islocked, tests;
 
        /* Don't bother if we can't get the lock */
-       if ( ldap_pvt_thread_mutex_trylock( &bdb->bi_cache.lru_head_mutex ) )
+       if ( ldap_pvt_thread_mutex_trylock( &bdb->bi_cache.c_lru_mutex ) )
                return;
 
        if ( bdb->bi_cache.c_cursize <= bdb->bi_cache.c_maxsize ) {
-               ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.lru_head_mutex );
+               ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_lru_mutex );
                return;
        }
 
+       if ( bdb->bi_cache.c_locker ) {
+               lockp = &lock;
+       } else {
+               lockp = NULL;
+       }
+
        count = 0;
+
+       /* Give up after two loops around the circle */
+       tests = bdb->bi_cache.c_cursize * 2;
+
        /* Look for an unused entry to remove */
-       for (elru = bdb->bi_cache.c_lruhead; elru; elru = elnext ) {
+       for ( i = 0, elru = bdb->bi_cache.c_lruhead; i < tests;
+               i++, elru = elnext ) {
                elnext = elru->bei_lrunext;
 
                if ( ldap_pvt_thread_mutex_trylock( &elru->bei_kids_mutex ))
@@ -593,7 +605,7 @@ bdb_cache_lru_purge( struct bdb_info *bdb, uint32_t locker )
                 */
                if (( elru->bei_state & ( CACHE_ENTRY_NOT_LINKED |
                        CACHE_ENTRY_DELETED | CACHE_ENTRY_LOADING )) ||
-                       !elru->bei_e ) {
+                       elru->bei_finders > 0 || !elru->bei_e ) {
                        bdb_cache_entryinfo_unlock( elru );
                        continue;
                }
@@ -604,7 +616,8 @@ bdb_cache_lru_purge( struct bdb_info *bdb, uint32_t locker )
                /* If we can successfully writelock it, then
                 * the object is idle.
                 */
-               if ( bdb_cache_entry_db_lock( bdb, locker, elru, 1, 1, &lock ) == 0 ) {
+               if ( bdb_cache_entry_db_lock( bdb,
+                       bdb->bi_cache.c_locker, elru, 1, 1, lockp ) == 0 ) {
 
                        /* Free entry for this node if it's present */
                        if ( elru->bei_e ) {
@@ -617,7 +630,7 @@ bdb_cache_lru_purge( struct bdb_info *bdb, uint32_t locker )
                                elru->bei_e = NULL;
                                count++;
                        }
-                       bdb_cache_entry_db_unlock( bdb, &lock );
+                       bdb_cache_entry_db_unlock( bdb, lockp );
 
                        /* ITS#4010 if we're in slapcat, and this node is a leaf
                         * node, free it.
@@ -648,7 +661,7 @@ bdb_cache_lru_purge( struct bdb_info *bdb, uint32_t locker )
        }
 
        bdb->bi_cache.c_lruhead = elnext;
-       ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.lru_head_mutex );
+       ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_lru_mutex );
 }
 
 EntryInfo *
@@ -757,6 +770,7 @@ again:      ldap_pvt_thread_rdwr_rlock( &bdb->bi_cache.c_rwlock );
                if ( (*eip)->bei_state & CACHE_ENTRY_DELETED ) {
                        rc = DB_NOTFOUND;
                } else {
+                       (*eip)->bei_finders++;
                        /* Make sure only one thread tries to load the entry */
 load1:
 #ifdef SLAP_ZONE_ALLOC
@@ -770,6 +784,7 @@ load1:
                                load = 1;
                                (*eip)->bei_state |= CACHE_ENTRY_LOADING;
                        }
+
                        if ( islocked ) {
                                bdb_cache_entryinfo_unlock( *eip );
                                islocked = 0;
@@ -802,9 +817,6 @@ load1:
                                                /* Otherwise, release the lock. */
                                                bdb_cache_entry_db_unlock( bdb, lock );
                                        }
-                                       bdb_cache_entryinfo_lock( *eip );
-                                       (*eip)->bei_state ^= CACHE_ENTRY_LOADING;
-                                       bdb_cache_entryinfo_unlock( *eip );
                                } else if ( !(*eip)->bei_e ) {
                                        /* Some other thread is trying to load the entry,
                                         * wait for it to finish.
@@ -829,7 +841,11 @@ load1:
                                        }
 #endif
                                }
-
+                               bdb_cache_entryinfo_lock( *eip );
+                               (*eip)->bei_finders--;
+                               if ( load )
+                                       (*eip)->bei_state ^= CACHE_ENTRY_LOADING;
+                               bdb_cache_entryinfo_unlock( *eip );
                        }
                }
        }
@@ -855,7 +871,7 @@ load1:
                        ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex );
                }
                if ( purge )
-                       bdb_cache_lru_purge( bdb, locker );
+                       bdb_cache_lru_purge( bdb );
        }
 
 #ifdef SLAP_ZONE_ALLOC
@@ -955,7 +971,7 @@ bdb_cache_add(
        ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex );
 
        if ( purge )
-               bdb_cache_lru_purge( bdb, locker );
+               bdb_cache_lru_purge( bdb );
 
        return rc;
 }
@@ -1117,12 +1133,12 @@ bdb_cache_delete(
                e->e_id, 0, 0 );
 
        /* set lru mutex */
-       ldap_pvt_thread_mutex_lock( &bdb->bi_cache.lru_head_mutex );
+       ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_lru_mutex );
 
        rc = bdb_cache_delete_internal( &bdb->bi_cache, e->e_private, 1 );
 
        /* free lru mutex */
-       ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.lru_head_mutex );
+       ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_lru_mutex );
 
        /* Leave entry info locked */
 
@@ -1205,11 +1221,7 @@ bdb_cache_delete_internal(
        if ( rc == 0 ){
                /* lru */
                if ( e == cache->c_lruhead ) cache->c_lruhead = e->bei_lrunext;
-               if ( e == cache->c_lrutail ) {
-                       ldap_pvt_thread_mutex_lock( &cache->lru_tail_mutex );
-                       if ( e == cache->c_lrutail ) cache->c_lrutail = e->bei_lruprev;
-                       ldap_pvt_thread_mutex_unlock( &cache->lru_tail_mutex );
-               }
+               if ( e == cache->c_lrutail ) cache->c_lrutail = e->bei_lruprev;
 
                if ( e->bei_lrunext ) e->bei_lrunext->bei_lruprev = e->bei_lruprev;
                if ( e->bei_lruprev ) e->bei_lruprev->bei_lrunext = e->bei_lrunext;
@@ -1248,7 +1260,7 @@ bdb_cache_release_all( Cache *cache )
        /* set cache write lock */
        ldap_pvt_thread_rdwr_wlock( &cache->c_rwlock );
        /* set lru mutex */
-       ldap_pvt_thread_mutex_lock( &cache->lru_tail_mutex );
+       ldap_pvt_thread_mutex_lock( &cache->c_lru_mutex );
 
        Debug( LDAP_DEBUG_TRACE, "====> bdb_cache_release_all\n", 0, 0, 0 );
 
@@ -1267,7 +1279,7 @@ bdb_cache_release_all( Cache *cache )
        cache->c_dntree.bei_kids = NULL;
 
        /* free lru mutex */
-       ldap_pvt_thread_mutex_unlock( &cache->lru_tail_mutex );
+       ldap_pvt_thread_mutex_unlock( &cache->c_lru_mutex );
        /* free cache write lock */
        ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
 }
index 135f101702bc0a0e9d214116b12d8fdb52b56340..f89f2db850b92b22e5e2b5d0269773aca30104c0 100644 (file)
@@ -71,8 +71,7 @@ bdb_db_init( BackendDB *be )
 #ifdef BDB_HIER
        ldap_pvt_thread_mutex_init( &bdb->bi_modrdns_mutex );
 #endif
-       ldap_pvt_thread_mutex_init( &bdb->bi_cache.lru_head_mutex );
-       ldap_pvt_thread_mutex_init( &bdb->bi_cache.lru_tail_mutex );
+       ldap_pvt_thread_mutex_init( &bdb->bi_cache.c_lru_mutex );
        ldap_pvt_thread_mutex_init( &bdb->bi_cache.c_count_mutex );
        ldap_pvt_thread_mutex_init( &bdb->bi_cache.c_eifree_mutex );
        ldap_pvt_thread_mutex_init( &bdb->bi_cache.c_dntree.bei_kids_mutex );
@@ -423,6 +422,10 @@ bdb_db_open( BackendDB *be )
                goto fail;
        }
 
+       if ( !quick ) {
+               XLOCK_ID(bdb->bi_dbenv, &bdb->bi_cache.c_locker);
+       }
+
        /* monitor setup */
        rc = bdb_monitor_db_open( be );
        if ( rc != 0 ) {
@@ -486,6 +489,12 @@ bdb_db_close( BackendDB *be )
 
        /* close db environment */
        if( bdb->bi_dbenv ) {
+               /* Free cache locker if we enabled locking */
+               if ( !( slapMode & SLAP_TOOL_QUICK )) {
+                       XLOCK_ID_FREE(bdb->bi_dbenv, bdb->bi_cache.c_locker);
+                       bdb->bi_cache.c_locker = 0;
+               }
+
                /* force a checkpoint, but not if we were ReadOnly,
                 * and not in Quick mode since there are no transactions there.
                 */
@@ -532,8 +541,7 @@ bdb_db_destroy( BackendDB *be )
        bdb_attr_index_destroy( bdb );
 
        ldap_pvt_thread_rdwr_destroy ( &bdb->bi_cache.c_rwlock );
-       ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.lru_head_mutex );
-       ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.lru_tail_mutex );
+       ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.c_lru_mutex );
        ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.c_count_mutex );
        ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.c_eifree_mutex );
        ldap_pvt_thread_mutex_destroy( &bdb->bi_cache.c_dntree.bei_kids_mutex );