]> git.sur5r.net Git - openldap/commitdiff
ITS#4010 fixes complaint, larger problem remains
authorHoward Chu <hyc@openldap.org>
Thu, 8 Sep 2005 15:28:36 +0000 (15:28 +0000)
committerHoward Chu <hyc@openldap.org>
Thu, 8 Sep 2005 15:28:36 +0000 (15:28 +0000)
servers/slapd/back-bdb/back-bdb.h
servers/slapd/back-bdb/cache.c

index e28d7c189ba99e4c2b20a1c776d2ed79de9f5e75..3f3401df5c0519e38c0d4ca091c42fe055a538a7 100644 (file)
@@ -124,6 +124,7 @@ typedef struct bdb_cache {
        int             c_maxsize;
        int             c_cursize;
        int             c_eiused;       /* EntryInfo's in use */
+       int             c_leaves;       /* EntryInfo leaf nodes */
        EntryInfo       c_dntree;
        EntryInfo       *c_eifree;      /* free list */
        Avlnode         *c_idtree;
index d98ed21ecc7ca5db7a00a0a60ca8552078baf934..efd963a82fd209292ad9bae3ffbc310d910d4adb 100644 (file)
@@ -257,6 +257,13 @@ bdb_entryinfo_add_internal(
        } else {
                bdb->bi_cache.c_eiused++;
                ber_dupbv( &ei2->bei_nrdn, &ei->bei_nrdn );
+
+               /* This is a new leaf node. But if parent had no kids, then it was
+                * a leaf and we would be decrementing that. So, only increment if
+                * the parent already has kids.
+                */
+               if ( ei->bei_parent->bei_kids || !ei->bei_parent->bei_id )
+                       bdb->bi_cache.c_leaves++;
                avl_insert( &ei->bei_parent->bei_kids, ei2, bdb_rdn_cmp,
                        avl_dup_error );
 #ifdef BDB_HIER
@@ -387,7 +394,7 @@ hdb_cache_find_parent(
        struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private;
        EntryInfo ei, eip, *ei2 = NULL, *ein = NULL, *eir = NULL;
        int rc;
-       int addlru = 1;
+       int addlru = 0;
 
        ei.bei_id = id;
        ei.bei_kids = NULL;
@@ -435,11 +442,15 @@ hdb_cache_find_parent(
                                ein->bei_ckids++;
                                bdb_cache_entryinfo_unlock( ein );
                        }
+                       addlru = 0;
 
-                       if ( !eir ) {
-                               addlru = 0;
-                       }
                }
+               if ( addlru ) {
+                       ldap_pvt_thread_mutex_lock( &bdb->bi_cache.lru_mutex );
+                       LRU_ADD( &bdb->bi_cache, ein );
+                       ldap_pvt_thread_mutex_unlock( &bdb->bi_cache.lru_mutex );
+               }
+               addlru = 1;
 
                /* If this is the first time, save this node
                 * to be returned later.
@@ -457,6 +468,8 @@ hdb_cache_find_parent(
                        ei2 = &bdb->bi_cache.c_dntree;
                }
                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 );
 
                /* Got the parent, link in and we're done. */
@@ -555,31 +568,53 @@ bdb_cache_lru_add(
                         */
                        if ( bdb_cache_entry_db_lock( bdb->bi_dbenv,
                                        bdb->bi_cache.c_locker, elru, 1, 1, lockp ) == 0 ) {
-                               int stop = 0;
 
-                               /* If there's no entry, or this node is in
-                                * the process of linking into the cache,
+                               int stop = 0, decr = 0;
+
+                               /* If this node is in the process of linking into the cache,
                                 * or this node is being deleted, skip it.
                                 */
-                               if ( !elru->bei_e || (elru->bei_state &
-                                       ( CACHE_ENTRY_NOT_LINKED | CACHE_ENTRY_DELETED ))) {
+                               if ( elru->bei_state &
+                                       ( CACHE_ENTRY_NOT_LINKED | CACHE_ENTRY_DELETED )) {
                                        bdb_cache_entry_db_unlock( bdb->bi_dbenv, lockp );
                                        continue;
                                }
-                               LRU_DELETE( &bdb->bi_cache, elru );
-                               elru->bei_e->e_private = NULL;
+                               /* Free entry for this node if it's present */
+                               if ( elru->bei_e ) {
+                                       elru->bei_e->e_private = NULL;
 #ifdef SLAP_ZONE_ALLOC
-                               bdb_entry_return( bdb, elru->bei_e, elru->bei_zseq );
+                                       bdb_entry_return( bdb, elru->bei_e, elru->bei_zseq );
 #else
-                               bdb_entry_return( elru->bei_e );
+                                       bdb_entry_return( elru->bei_e );
 #endif
-                               elru->bei_e = NULL;
+                                       elru->bei_e = NULL;
+                                       decr = 1;
+                               }
+                               /* ITS#4010 if we're in slapcat, and this node is a leaf
+                                * node, free it.
+                                *
+                                * FIXME: we need to do this for slapd as well, (which is
+                                * why we compute bi_cache.c_leaves now) but at the moment
+                                * we can't because it causes unresolvable deadlocks. 
+                                */
+                               if ( slapMode & SLAP_TOOL_READONLY ) {
+                                       if ( !elru->bei_kids ) {
+                                               /* This does LRU_DELETE for us */
+                                               bdb_cache_delete_internal( &bdb->bi_cache, elru, 0 );
+                                               bdb_cache_delete_cleanup( &bdb->bi_cache, elru );
+                                       }
+                                       /* Leave node on LRU list for a future pass */
+                               } else {
+                                       LRU_DELETE( &bdb->bi_cache, elru );
+                               }
+                               bdb_cache_entry_db_unlock( bdb->bi_dbenv, lockp );
+
                                ldap_pvt_thread_rdwr_wlock( &bdb->bi_cache.c_rwlock );
-                               --bdb->bi_cache.c_cursize;
+                               if ( decr )
+                                       --bdb->bi_cache.c_cursize;
                                if (bdb->bi_cache.c_cursize <= bdb->bi_cache.c_maxsize)
                                        stop = 1;
                                ldap_pvt_thread_rdwr_wunlock( &bdb->bi_cache.c_rwlock );
-                               bdb_cache_entry_db_unlock( bdb->bi_dbenv, lockp );
                                if (stop) break;
                        }
                }
@@ -1085,7 +1120,15 @@ bdb_cache_delete(
 
        /* set lru mutex */
        ldap_pvt_thread_mutex_lock( &cache->lru_mutex );
+
+       /* set cache write lock */
+       ldap_pvt_thread_rdwr_wlock( &cache->c_rwlock );
+
        rc = bdb_cache_delete_internal( cache, e->e_private, 1 );
+
+       /* free cache write lock */
+       ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
+
        /* free lru mutex */
        ldap_pvt_thread_mutex_unlock( &cache->lru_mutex );
 
@@ -1137,9 +1180,6 @@ bdb_cache_delete_internal(
 {
        int rc = 0;     /* return code */
 
-       /* set cache write lock */
-       ldap_pvt_thread_rdwr_wlock( &cache->c_rwlock );
-
        /* Lock the parent's kids tree */
        bdb_cache_entryinfo_lock( e->bei_parent );
 
@@ -1153,27 +1193,25 @@ bdb_cache_delete_internal(
        {
                rc = -1;
        }
+       if ( e->bei_parent->bei_kids )
+               cache->c_leaves--;
 
        /* id tree */
        if ( avl_delete( &cache->c_idtree, (caddr_t) e, bdb_id_cmp ) == NULL ) {
                rc = -1;
        }
 
-       if (rc != 0) {
-               return rc;
-       }
-
-       cache->c_eiused--;
+       if ( rc == 0 ){
+               cache->c_eiused--;
 
-       /* lru */
-       LRU_DELETE( cache, e );
-       if ( e->bei_e ) cache->c_cursize--;
+               /* lru */
+               LRU_DELETE( cache, e );
+               if ( e->bei_e ) cache->c_cursize--;
+       }
 
-       /* free cache write lock */
-       ldap_pvt_thread_rdwr_wunlock( &cache->c_rwlock );
        bdb_cache_entryinfo_unlock( e->bei_parent );
 
-       return( 0 );
+       return( rc );
 }
 
 static void
@@ -1212,6 +1250,7 @@ bdb_cache_release_all( Cache *cache )
        }
        cache->c_cursize = 0;
        cache->c_eiused = 0;
+       cache->c_leaves = 0;
        cache->c_idtree = NULL;
        cache->c_lruhead = NULL;
        cache->c_lrutail = NULL;