]> git.sur5r.net Git - openldap/blobdiff - servers/slapd/back-bdb/cache.c
Plug mutex/rwlock leaks (destroy them)
[openldap] / servers / slapd / back-bdb / cache.c
index bab34701b6d098069621dc9d009ec17c65a69a66..a42db5c5a20cace55b8d41d309ae599368dbc3aa 100644 (file)
@@ -2,7 +2,7 @@
 /* $OpenLDAP$ */
 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  *
- * 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
@@ -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
 }
@@ -108,7 +109,7 @@ bdb_cache_entryinfo_free( Cache *cache, EntryInfo *ei )
 #define LRU_DEL( c, e ) do { \
        if ( e == e->bei_lruprev ) { \
                (c)->c_lruhead = (c)->c_lrutail = NULL; \
-       } else { \      
+       } 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; \
@@ -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;
 
@@ -440,7 +443,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 +459,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 +478,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;
@@ -972,6 +977,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;
                        }
@@ -1069,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 (( 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_eimax && 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 );
                }