]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-bdb/cache.c
More for ITS#5860
[openldap] / servers / slapd / back-bdb / cache.c
index 1049375735e166164d6bd181b603f8f0a9fbb709..260623cfa82ff4bef803c33abf572885b67e5ff1 100644 (file)
@@ -658,7 +658,10 @@ 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;
+       int efree = 0, eifree = 0, eicount, ecount;
+#ifdef LDAP_DEBUG
+       int iter;
+#endif
 
        /* Wait for the mutex; we're the only one trying to purge. */
        ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_lru_mutex );
@@ -673,8 +676,11 @@ bdb_cache_lru_purge( struct bdb_info *bdb )
 
        if ( bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize )
                efree = bdb->bi_cache.c_minfree;
-       if ( bdb->bi_cache.c_leaves > eimax )
+       if ( bdb->bi_cache.c_leaves > eimax ) {
                eifree = bdb->bi_cache.c_minfree * 10;
+               if ( eifree >= eimax )
+                       eifree = eimax / 2;
+       }
 
        if ( !efree && !eifree ) {
                ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_lru_mutex );
@@ -690,6 +696,10 @@ bdb_cache_lru_purge( struct bdb_info *bdb )
 
        count = 0;
        eicount = 0;
+       ecount = 0;
+#ifdef LDAP_DEBUG
+       iter = 0;
+#endif
 
        /* Look for an unused entry to remove */
        for ( elru = bdb->bi_cache.c_lruhead; elru; elru = elnext ) {
@@ -726,6 +736,14 @@ bdb_cache_lru_purge( struct bdb_info *bdb )
 
                        /* Free entry for this node if it's present */
                        if ( elru->bei_e ) {
+                               ecount++;
+
+                               /* the cache may have gone over the limit while we
+                                * weren't looking, so double check.
+                                */
+                               if ( !efree && ecount > bdb->bi_cache.c_maxsize )
+                                       efree = bdb->bi_cache.c_minfree;
+
                                if ( count < efree ) {
                                        elru->bei_e->e_private = NULL;
 #ifdef SLAP_ZONE_ALLOC
@@ -763,8 +781,11 @@ next:
                        bdb_cache_entryinfo_unlock( elru );
 
                if ( count >= efree && eicount >= eifree ) {
-                       if ( count ) {
+                       if ( count || ecount > bdb->bi_cache.c_cursize ) {
                                ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_count_mutex );
+                               /* HACK: we seem to be losing track, fix up now */
+                               if ( ecount > bdb->bi_cache.c_cursize )
+                                       bdb->bi_cache.c_cursize = ecount;
                                bdb->bi_cache.c_cursize -= count;
                                ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex );
                        }
@@ -773,6 +794,9 @@ next:
 bottom:
                if ( elnext == bdb->bi_cache.c_lruhead )
                        break;
+#ifdef LDAP_DEBUG
+               iter++;
+#endif
        }
 
        bdb->bi_cache.c_lruhead = elnext;
@@ -814,7 +838,7 @@ bdb_cache_find_id(
 {
        struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
        Entry   *ep = NULL;
-       int     rc = 0, load = 0, added = 0;
+       int     rc = 0, load = 0;
        EntryInfo ei = { 0 };
 
        ei.bei_id = id;
@@ -912,7 +936,6 @@ load1:
                                 */
                                if ( (*eip)->bei_state & CACHE_ENTRY_NOT_CACHED ) {
                                        (*eip)->bei_state &= ~CACHE_ENTRY_NOT_CACHED;
-                                       added = 1;
                                }
                                flag &= ~ID_NOCACHE;
                        }
@@ -941,7 +964,6 @@ load1:
 #endif
                                                ep = NULL;
                                                bdb_cache_lru_link( bdb, *eip );
-                                               added = 1;
                                                if (( flag & ID_NOCACHE ) &&
                                                        ( bdb_cache_entryinfo_trylock( *eip ) == 0 )) {
                                                        /* Set the cached state only if no other thread
@@ -1006,18 +1028,20 @@ load1:
        if ( rc == 0 ) {
                int purge = 0;
 
-               if ( added ) {
+               if ( bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize ||
+                       bdb->bi_cache.c_leaves > bdb->bi_cache.c_eimax ) {
                        ldap_pvt_thread_mutex_lock( &bdb->bi_cache.c_count_mutex );
-                       if ( !( flag & ID_NOCACHE )) {
-                               bdb->bi_cache.c_cursize++;
-                               if ( bdb->bi_cache.c_cursize > bdb->bi_cache.c_maxsize &&
-                                       !bdb->bi_cache.c_purging ) {
+                       if ( !bdb->bi_cache.c_purging ) {
+                               if ( !( 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 ) {
                                        purge = 1;
                                        bdb->bi_cache.c_purging = 1;
                                }
-                       } else if ( bdb->bi_cache.c_leaves > bdb->bi_cache.c_eimax && !bdb->bi_cache.c_purging ) {
-                               purge = 1;
-                               bdb->bi_cache.c_purging = 1;
                        }
                        ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.c_count_mutex );
                }
@@ -1465,7 +1489,7 @@ bdb_reader_free( void *key, void *data )
        /* DB_ENV *env = key; */
        DB_TXN *txn = data;
 
-       TXN_ABORT( txn );
+       if ( txn ) TXN_ABORT( txn );
 }
 
 /* free up any keys used by the main thread */