andykimpe / rpms / 389-ds-base

Forked from rpms/389-ds-base 5 months ago
Clone
dc8c34
From 13e35a48c22cef7e68b39dbf88f99631ef5f590c Mon Sep 17 00:00:00 2001
dc8c34
From: Mark Reynolds <mreynolds@redhat.com>
dc8c34
Date: Thu, 18 Sep 2014 10:52:07 -0400
dc8c34
Subject: [PATCH 261/262] Ticket 47750 - Entry cache part 2
dc8c34
dc8c34
Description: replacing PRLock for cache->c_mutex with PRMonitor.
dc8c34
Introducing cache_is_in_cache and replacing in_cache local variables
dc8c34
(e.g., e_in_cache) with the function call.
dc8c34
dc8c34
(cherry picked from commit 2c16d7d536481687b39f0d72c235aa8b7e7ef2d6)
dc8c34
---
dc8c34
 ldap/servers/slapd/back-ldbm/back-ldbm.h       |   3 +-
dc8c34
 ldap/servers/slapd/back-ldbm/cache.c           | 183 +++++++++++++++----------
dc8c34
 ldap/servers/slapd/back-ldbm/ldbm_add.c        | 134 +++++++++---------
dc8c34
 ldap/servers/slapd/back-ldbm/ldbm_delete.c     | 112 ++++++---------
dc8c34
 ldap/servers/slapd/back-ldbm/ldbm_modify.c     |  84 ++++++------
dc8c34
 ldap/servers/slapd/back-ldbm/ldbm_modrdn.c     | 147 ++++++++------------
dc8c34
 ldap/servers/slapd/back-ldbm/proto-back-ldbm.h |   2 +
dc8c34
 7 files changed, 328 insertions(+), 337 deletions(-)
dc8c34
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/back-ldbm.h b/ldap/servers/slapd/back-ldbm/back-ldbm.h
dc8c34
index d27a664..ec0e2dc 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/back-ldbm.h
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/back-ldbm.h
dc8c34
@@ -402,7 +402,7 @@ struct cache {
dc8c34
     Slapi_Counter *c_tries;
dc8c34
     struct backcommon *c_lruhead;	/* add entries here */
dc8c34
     struct backcommon *c_lrutail;	/* remove entries here */
dc8c34
-    PRLock *c_mutex;			/* lock for cache operations */
dc8c34
+    PRMonitor *c_mutex;			/* lock for cache operations */
dc8c34
     PRLock *c_emutexalloc_mutex;
dc8c34
 };
dc8c34
 
dc8c34
@@ -694,7 +694,6 @@ typedef struct _import_subcount_stuff import_subcount_stuff;
dc8c34
 /* Handy structures for modify operations */
dc8c34
 
dc8c34
 struct _modify_context {
dc8c34
-	int new_entry_in_cache;
dc8c34
 	struct backentry *old_entry;
dc8c34
 	struct backentry *new_entry;
dc8c34
 	Slapi_Mods *smods;
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/cache.c b/ldap/servers/slapd/back-ldbm/cache.c
dc8c34
index 5510a9a..202386e 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/cache.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/cache.c
dc8c34
@@ -543,8 +543,8 @@ int cache_init(struct cache *cache, size_t maxsize, long maxentries, int type)
dc8c34
     cache->c_lruhead = cache->c_lrutail = NULL;
dc8c34
     cache_make_hashes(cache, type);
dc8c34
 
dc8c34
-    if (((cache->c_mutex = PR_NewLock()) == NULL) ||
dc8c34
-       ((cache->c_emutexalloc_mutex = PR_NewLock()) == NULL)) {
dc8c34
+    if (((cache->c_mutex = PR_NewMonitor()) == NULL) ||
dc8c34
+        ((cache->c_emutexalloc_mutex = PR_NewLock()) == NULL)) {
dc8c34
        LDAPDebug(LDAP_DEBUG_ANY, "ldbm: cache_init: PR_NewLock failed\n",
dc8c34
                 0, 0, 0);
dc8c34
        return 0;
dc8c34
@@ -633,13 +633,13 @@ static void entrycache_clear_int(struct cache *cache)
dc8c34
 
dc8c34
 void cache_clear(struct cache *cache, int type)
dc8c34
 {
dc8c34
-    PR_Lock(cache->c_mutex);
dc8c34
+    cache_lock(cache);
dc8c34
     if (CACHE_TYPE_ENTRY == type) {
dc8c34
         entrycache_clear_int(cache);
dc8c34
     } else if (CACHE_TYPE_DN == type) {
dc8c34
         dncache_clear_int(cache);
dc8c34
     }
dc8c34
-    PR_Unlock(cache->c_mutex);
dc8c34
+    cache_unlock(cache);
dc8c34
 }
dc8c34
 
dc8c34
 static void erase_cache(struct cache *cache, int type)
dc8c34
@@ -663,7 +663,7 @@ void cache_destroy_please(struct cache *cache, int type)
dc8c34
     slapi_counter_destroy(&cache->c_cursize);
dc8c34
     slapi_counter_destroy(&cache->c_hits);
dc8c34
     slapi_counter_destroy(&cache->c_tries);
dc8c34
-    PR_DestroyLock(cache->c_mutex);
dc8c34
+    PR_DestroyMonitor(cache->c_mutex);
dc8c34
     PR_DestroyLock(cache->c_emutexalloc_mutex);
dc8c34
 }
dc8c34
 
dc8c34
@@ -687,7 +687,7 @@ static void entrycache_set_max_size(struct cache *cache, size_t bytes)
dc8c34
                 "WARNING -- Minimum cache size is %lu -- rounding up\n",
dc8c34
                 MINCACHESIZE, 0, 0);
dc8c34
     }
dc8c34
-    PR_Lock(cache->c_mutex);
dc8c34
+    cache_lock(cache);
dc8c34
     cache->c_maxsize = bytes;
dc8c34
     LOG("entry cache size set to %lu\n", bytes, 0, 0);
dc8c34
     /* check for full cache, and clear out if necessary */
dc8c34
@@ -706,7 +706,7 @@ static void entrycache_set_max_size(struct cache *cache, size_t bytes)
dc8c34
        erase_cache(cache, CACHE_TYPE_ENTRY);
dc8c34
        cache_make_hashes(cache, CACHE_TYPE_ENTRY);
dc8c34
     }
dc8c34
-    PR_Unlock(cache->c_mutex);
dc8c34
+    cache_unlock(cache);
dc8c34
     if (! dblayer_is_cachesize_sane(&bytes)) {
dc8c34
        LDAPDebug(LDAP_DEBUG_ANY,
dc8c34
                 "WARNING -- Possible CONFIGURATION ERROR -- cachesize "
dc8c34
@@ -724,7 +724,7 @@ void cache_set_max_entries(struct cache *cache, long entries)
dc8c34
      * was given in # entries instead of memory footprint.  hopefully,
dc8c34
      * we can eventually drop this.
dc8c34
      */
dc8c34
-    PR_Lock(cache->c_mutex);
dc8c34
+    cache_lock(cache);
dc8c34
     cache->c_maxentries = entries;
dc8c34
     if (entries >= 0) {
dc8c34
         LOG("entry cache entry-limit set to %lu\n", entries, 0, 0);
dc8c34
@@ -735,7 +735,7 @@ void cache_set_max_entries(struct cache *cache, long entries)
dc8c34
     /* check for full cache, and clear out if necessary */
dc8c34
     if (CACHE_FULL(cache))
dc8c34
         eflush = entrycache_flush(cache);
dc8c34
-    PR_Unlock(cache->c_mutex);
dc8c34
+    cache_unlock(cache);
dc8c34
     while (eflush)
dc8c34
     {
dc8c34
         eflushtemp = BACK_LRU_NEXT(eflush, struct backentry *);
dc8c34
@@ -748,9 +748,9 @@ size_t cache_get_max_size(struct cache *cache)
dc8c34
 {
dc8c34
     size_t n = 0;
dc8c34
 
dc8c34
-    PR_Lock(cache->c_mutex);
dc8c34
+    cache_lock(cache);
dc8c34
     n = cache->c_maxsize;
dc8c34
-    PR_Unlock(cache->c_mutex);
dc8c34
+    cache_unlock(cache);
dc8c34
     return n;
dc8c34
 }
dc8c34
 
dc8c34
@@ -758,9 +758,9 @@ long cache_get_max_entries(struct cache *cache)
dc8c34
 {
dc8c34
     long n;
dc8c34
 
dc8c34
-    PR_Lock(cache->c_mutex);
dc8c34
+    cache_lock(cache);
dc8c34
     n = cache->c_maxentries;
dc8c34
-    PR_Unlock(cache->c_mutex);
dc8c34
+    cache_unlock(cache);
dc8c34
     return n;
dc8c34
 }
dc8c34
 
dc8c34
@@ -786,14 +786,14 @@ void cache_get_stats(struct cache *cache, PRUint64 *hits, PRUint64 *tries,
dc8c34
                      long *nentries, long *maxentries,
dc8c34
                      size_t *size, size_t *maxsize)
dc8c34
 {
dc8c34
-    PR_Lock(cache->c_mutex);
dc8c34
+    cache_lock(cache);
dc8c34
     if (hits) *hits = slapi_counter_get_value(cache->c_hits);
dc8c34
     if (tries) *tries = slapi_counter_get_value(cache->c_tries);
dc8c34
     if (nentries) *nentries = cache->c_curentries;
dc8c34
     if (maxentries) *maxentries = cache->c_maxentries;
dc8c34
     if (size) *size = slapi_counter_get_value(cache->c_cursize);
dc8c34
     if (maxsize) *maxsize = cache->c_maxsize;
dc8c34
-    PR_Unlock(cache->c_mutex);
dc8c34
+    cache_unlock(cache);
dc8c34
 }
dc8c34
 
dc8c34
 void cache_debug_hash(struct cache *cache, char **out)
dc8c34
@@ -804,7 +804,7 @@ void cache_debug_hash(struct cache *cache, char **out)
dc8c34
     Hashtable *ht = NULL;
dc8c34
     char *name = "unknown";
dc8c34
 
dc8c34
-    PR_Lock(cache->c_mutex);
dc8c34
+    cache_lock(cache);
dc8c34
     *out = (char *)slapi_ch_malloc(1024);
dc8c34
     **out = 0;
dc8c34
 
dc8c34
@@ -840,7 +840,7 @@ void cache_debug_hash(struct cache *cache, char **out)
dc8c34
             sprintf(*out + strlen(*out), "%d[%d] ", j, slot_stats[j]);
dc8c34
         slapi_ch_free((void **)&slot_stats);
dc8c34
     }
dc8c34
-    PR_Unlock(cache->c_mutex);
dc8c34
+    cache_unlock(cache);
dc8c34
 }
dc8c34
 
dc8c34
 
dc8c34
@@ -946,14 +946,14 @@ int cache_remove(struct cache *cache,  void *ptr)
dc8c34
     }
dc8c34
     e = (struct backcommon *)ptr;
dc8c34
 
dc8c34
-    PR_Lock(cache->c_mutex);
dc8c34
+    cache_lock(cache);
dc8c34
     if (CACHE_TYPE_ENTRY == e->ep_type) {
dc8c34
         ASSERT(e->ep_refcnt > 0);
dc8c34
         ret = entrycache_remove_int(cache, (struct backentry *)e);
dc8c34
     } else if (CACHE_TYPE_DN == e->ep_type) {
dc8c34
         ret = dncache_remove_int(cache, (struct backdn *)e);
dc8c34
     }
dc8c34
-    PR_Unlock(cache->c_mutex);
dc8c34
+    cache_unlock(cache);
dc8c34
     return ret;
dc8c34
 }
dc8c34
 
dc8c34
@@ -1011,7 +1011,7 @@ static int entrycache_replace(struct cache *cache, struct backentry *olde,
dc8c34
     newuuid = slapi_entry_get_uniqueid(newe->ep_entry);
dc8c34
 #endif
dc8c34
     newndn = slapi_sdn_get_ndn(backentry_get_sdn(newe));
dc8c34
-    PR_Lock(cache->c_mutex);
dc8c34
+    cache_lock(cache);
dc8c34
 
dc8c34
     /*
dc8c34
      * First, remove the old entry from all the hashtables.
dc8c34
@@ -1031,7 +1031,7 @@ static int entrycache_replace(struct cache *cache, struct backentry *olde,
dc8c34
     }
dc8c34
     /* If fails, we have to make sure the both entires are removed from the cache,
dc8c34
      * otherwise, we have no idea what's left in the cache or not... */
dc8c34
-    if (!entry_same_dn(newe, (void *)oldndn) && (newe->ep_state & ENTRY_STATE_NOTINCACHE) == 0) {
dc8c34
+    if (cache_is_in_cache(cache, newe)) {
dc8c34
         /* if we're doing a modrdn or turning an entry to a tombstone,
dc8c34
          * the new entry can be in the dn table already, so we need to remove that too.
dc8c34
          */
dc8c34
@@ -1039,6 +1039,7 @@ static int entrycache_replace(struct cache *cache, struct backentry *olde,
dc8c34
         {
dc8c34
             slapi_counter_subtract(cache->c_cursize, newe->ep_size);
dc8c34
             cache->c_curentries--;
dc8c34
+            newe->ep_refcnt--;
dc8c34
             LOG("entry cache replace remove entry size %lu\n", newe->ep_size, 0, 0);
dc8c34
         }
dc8c34
     }
dc8c34
@@ -1061,7 +1062,7 @@ static int entrycache_replace(struct cache *cache, struct backentry *olde,
dc8c34
             LOG("entry cache replace (%s): cache index tables out of sync - found dn [%d] id [%d]\n",
dc8c34
                 oldndn, found_in_dn, found_in_id);
dc8c34
 #endif
dc8c34
-            PR_Unlock(cache->c_mutex);
dc8c34
+            cache_unlock(cache);
dc8c34
             return 1;
dc8c34
         }
dc8c34
     }
dc8c34
@@ -1072,7 +1073,7 @@ static int entrycache_replace(struct cache *cache, struct backentry *olde,
dc8c34
     if (!add_hash(cache->c_dntable, (void *)newndn, strlen(newndn), newe, (void **)&alte)) {
dc8c34
        LOG("entry cache replace (%s): can't add to dn table (returned %s)\n", 
dc8c34
            newndn, alte?slapi_entry_get_dn(alte->ep_entry):"none", 0);
dc8c34
-       PR_Unlock(cache->c_mutex);
dc8c34
+       cache_unlock(cache);
dc8c34
        return 1;
dc8c34
     }
dc8c34
     if (!add_hash(cache->c_idtable, &(newe->ep_id), sizeof(ID), newe, (void **)&alte)) {
dc8c34
@@ -1081,7 +1082,7 @@ static int entrycache_replace(struct cache *cache, struct backentry *olde,
dc8c34
        if(remove_hash(cache->c_dntable, (void *)newndn, strlen(newndn)) == 0){
dc8c34
            LOG("entry cache replace: failed to remove dn table\n", 0, 0, 0);
dc8c34
        }
dc8c34
-       PR_Unlock(cache->c_mutex);
dc8c34
+       cache_unlock(cache);
dc8c34
        return 1;
dc8c34
     }
dc8c34
 #ifdef UUIDCACHE_ON 
dc8c34
@@ -1094,7 +1095,7 @@ static int entrycache_replace(struct cache *cache, struct backentry *olde,
dc8c34
        if(remove_hash(cache->c_idtable, &(newe->ep_id), sizeof(ID)) == 0){
dc8c34
            LOG("entry cache replace: failed to remove id table(uuid cache)\n", 0, 0, 0);
dc8c34
        }
dc8c34
-       PR_Unlock(cache->c_mutex);
dc8c34
+       cache_unlock(cache);
dc8c34
        return 1;
dc8c34
     }
dc8c34
 #endif
dc8c34
@@ -1107,7 +1108,7 @@ static int entrycache_replace(struct cache *cache, struct backentry *olde,
dc8c34
         slapi_counter_subtract(cache->c_cursize, olde->ep_size - newe->ep_size);
dc8c34
     }
dc8c34
     newe->ep_state = 0;
dc8c34
-    PR_Unlock(cache->c_mutex);
dc8c34
+    cache_unlock(cache);
dc8c34
     LOG("<= entrycache_replace OK,  cache size now %lu cache count now %ld\n",
dc8c34
              slapi_counter_get_value(cache->c_cursize), cache->c_curentries, 0);
dc8c34
     return 0;
dc8c34
@@ -1144,7 +1145,7 @@ entrycache_return(struct cache *cache, struct backentry **bep)
dc8c34
     LOG("=> entrycache_return (%s) entry count: %d, entry in cache:%ld\n",
dc8c34
                     backentry_get_ndn(e), e->ep_refcnt, cache->c_curentries);
dc8c34
 
dc8c34
-    PR_Lock(cache->c_mutex);
dc8c34
+    cache_lock(cache);
dc8c34
     if (e->ep_state & ENTRY_STATE_NOTINCACHE)
dc8c34
     {
dc8c34
         backentry_free(bep);
dc8c34
@@ -1163,7 +1164,7 @@ entrycache_return(struct cache *cache, struct backentry **bep)
dc8c34
             }
dc8c34
         }
dc8c34
     }
dc8c34
-    PR_Unlock(cache->c_mutex);
dc8c34
+    cache_unlock(cache);
dc8c34
     while (eflush)
dc8c34
     {
dc8c34
         eflushtemp = BACK_LRU_NEXT(eflush, struct backentry *);
dc8c34
@@ -1182,22 +1183,22 @@ struct backentry *cache_find_dn(struct cache *cache, const char *dn, unsigned lo
dc8c34
     LOG("=> cache_find_dn (%s)\n", dn, 0, 0);
dc8c34
 
dc8c34
     /*entry normalized by caller (dn2entry.c)  */
dc8c34
-    PR_Lock(cache->c_mutex);
dc8c34
+    cache_lock(cache);
dc8c34
     if (find_hash(cache->c_dntable, (void *)dn, ndnlen, (void **)&e)) {
dc8c34
        /* need to check entry state */
dc8c34
        if (e->ep_state != 0) {
dc8c34
            /* entry is deleted or not fully created yet */
dc8c34
-           PR_Unlock(cache->c_mutex);
dc8c34
+           cache_unlock(cache);
dc8c34
            LOG("<= cache_find_dn (NOT FOUND)\n", 0, 0, 0);
dc8c34
            return NULL;
dc8c34
        }
dc8c34
        if (e->ep_refcnt == 0)
dc8c34
            lru_delete(cache, (void *)e);
dc8c34
        e->ep_refcnt++;
dc8c34
-       PR_Unlock(cache->c_mutex);
dc8c34
+       cache_unlock(cache);
dc8c34
        slapi_counter_increment(cache->c_hits);
dc8c34
     } else {
dc8c34
-       PR_Unlock(cache->c_mutex);
dc8c34
+       cache_unlock(cache);
dc8c34
     }
dc8c34
     slapi_counter_increment(cache->c_tries);
dc8c34
 
dc8c34
@@ -1213,22 +1214,22 @@ struct backentry *cache_find_id(struct cache *cache, ID id)
dc8c34
 
dc8c34
     LOG("=> cache_find_id (%lu)\n", (u_long)id, 0, 0);
dc8c34
 
dc8c34
-    PR_Lock(cache->c_mutex);
dc8c34
+    cache_lock(cache);
dc8c34
     if (find_hash(cache->c_idtable, &id, sizeof(ID), (void **)&e)) {
dc8c34
        /* need to check entry state */
dc8c34
        if (e->ep_state != 0) {
dc8c34
            /* entry is deleted or not fully created yet */
dc8c34
-           PR_Unlock(cache->c_mutex);
dc8c34
+           cache_unlock(cache);
dc8c34
            LOG("<= cache_find_id (NOT FOUND)\n", 0, 0, 0);
dc8c34
            return NULL;
dc8c34
        }
dc8c34
        if (e->ep_refcnt == 0)
dc8c34
            lru_delete(cache, (void *)e);
dc8c34
        e->ep_refcnt++;
dc8c34
-       PR_Unlock(cache->c_mutex);
dc8c34
+       cache_unlock(cache);
dc8c34
        slapi_counter_increment(cache->c_hits);
dc8c34
     } else {
dc8c34
-       PR_Unlock(cache->c_mutex);
dc8c34
+       cache_unlock(cache);
dc8c34
     }
dc8c34
     slapi_counter_increment(cache->c_tries);
dc8c34
 
dc8c34
@@ -1244,22 +1245,22 @@ struct backentry *cache_find_uuid(struct cache *cache, const char *uuid)
dc8c34
 
dc8c34
     LOG("=> cache_find_uuid (%s)\n", uuid, 0, 0);
dc8c34
 
dc8c34
-    PR_Lock(cache->c_mutex);
dc8c34
+    cache_lock(cache);
dc8c34
     if (find_hash(cache->c_uuidtable, uuid, strlen(uuid), (void **)&e)) {
dc8c34
        /* need to check entry state */
dc8c34
        if (e->ep_state != 0) {
dc8c34
            /* entry is deleted or not fully created yet */
dc8c34
-           PR_Unlock(cache->c_mutex);
dc8c34
+           cache_unlock(cache);
dc8c34
            LOG("<= cache_find_uuid (NOT FOUND)\n", 0, 0, 0);
dc8c34
            return NULL;
dc8c34
        }
dc8c34
        if (e->ep_refcnt == 0)
dc8c34
            lru_delete(cache, (void *)e);
dc8c34
        e->ep_refcnt++;
dc8c34
-       PR_Unlock(cache->c_mutex);
dc8c34
+       cache_unlock(cache);
dc8c34
        slapi_counter_increment(cache->c_hits);
dc8c34
     } else {
dc8c34
-       PR_Unlock(cache->c_mutex);
dc8c34
+       cache_unlock(cache);
dc8c34
     }
dc8c34
     slapi_counter_increment(cache->c_tries);
dc8c34
 
dc8c34
@@ -1285,7 +1286,7 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int state,
dc8c34
     LOG("=> entrycache_add_int( \"%s\", %ld )\n", backentry_get_ndn(e),
dc8c34
         e->ep_id, 0);
dc8c34
 
dc8c34
-    PR_Lock(cache->c_mutex);
dc8c34
+    cache_lock(cache);
dc8c34
     if (! add_hash(cache->c_dntable, (void *)ndn, strlen(ndn), e,
dc8c34
            (void **)&my_alt)) {
dc8c34
         LOG("entry \"%s\" already in dn cache\n", ndn, 0, 0);
dc8c34
@@ -1320,7 +1321,7 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int state,
dc8c34
                  * to prevent that the caller accidentally thinks the existing
dc8c34
                  * entry is not the same one the caller has and releases it.
dc8c34
                  */
dc8c34
-                PR_Unlock(cache->c_mutex);
dc8c34
+                cache_unlock(cache);
dc8c34
                 return 1;
dc8c34
             }
dc8c34
         }
dc8c34
@@ -1330,7 +1331,7 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int state,
dc8c34
             {
dc8c34
                 LOG("the entry %s is reserved (ep_state: 0x%x, state: 0x%x\n", ndn, e->ep_state, state);
dc8c34
                 e->ep_state |= ENTRY_STATE_NOTINCACHE;
dc8c34
-                PR_Unlock(cache->c_mutex);
dc8c34
+                cache_unlock(cache);
dc8c34
                 return -1;
dc8c34
             }
dc8c34
             else if (state != 0)
dc8c34
@@ -1338,7 +1339,7 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int state,
dc8c34
                 LOG("the entry %s already exists. cannot reserve it. (ep_state: 0x%x, state: 0x%x\n",
dc8c34
                     ndn, e->ep_state, state);
dc8c34
                 e->ep_state |= ENTRY_STATE_NOTINCACHE;
dc8c34
-                PR_Unlock(cache->c_mutex);
dc8c34
+                cache_unlock(cache);
dc8c34
                 return -1;
dc8c34
             }
dc8c34
             else
dc8c34
@@ -1350,12 +1351,14 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int state,
dc8c34
                     (*alt)->ep_refcnt++;
dc8c34
                     LOG("the entry %s already exists.  returning existing entry %s (state: 0x%x)\n",
dc8c34
                         ndn, backentry_get_ndn(my_alt), state);
dc8c34
+                    cache_unlock(cache);
dc8c34
+                    return -1;
dc8c34
                 } else {
dc8c34
                     LOG("the entry %s already exists.  Not returning existing entry %s (state: 0x%x)\n",
dc8c34
                         ndn, backentry_get_ndn(my_alt), state);
dc8c34
+                    cache_unlock(cache);
dc8c34
+                    return -1;
dc8c34
                 }
dc8c34
-                PR_Unlock(cache->c_mutex);
dc8c34
-                return 1;
dc8c34
             }
dc8c34
         }
dc8c34
     }
dc8c34
@@ -1385,14 +1388,14 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int state,
dc8c34
                  * fine (i think).
dc8c34
                  */
dc8c34
                 LOG("<= entrycache_add_int (ignoring)\n", 0, 0, 0);
dc8c34
-                PR_Unlock(cache->c_mutex);
dc8c34
+                cache_unlock(cache);
dc8c34
                 return 0;
dc8c34
             }
dc8c34
             if(remove_hash(cache->c_dntable, (void *)ndn, strlen(ndn)) == 0){
dc8c34
                 LOG("entrycache_add_int: failed to remove %s from dn table\n", 0, 0, 0);
dc8c34
             }
dc8c34
             e->ep_state |= ENTRY_STATE_NOTINCACHE;
dc8c34
-            PR_Unlock(cache->c_mutex);
dc8c34
+            cache_unlock(cache);
dc8c34
             LOG("entrycache_add_int: failed to add %s to cache (ep_state: %x, already_in: %d)\n",
dc8c34
                 ndn, e->ep_state, already_in);
dc8c34
             return -1;
dc8c34
@@ -1411,7 +1414,7 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int state,
dc8c34
                     LOG("entrycache_add_int: failed to remove id table(uuid cache)\n", 0, 0, 0);
dc8c34
                 }
dc8c34
                 e->ep_state |= ENTRY_STATE_NOTINCACHE;
dc8c34
-                PR_Unlock(cache->c_mutex);
dc8c34
+                cache_unlock(cache);
dc8c34
                 return -1;
dc8c34
             }
dc8c34
         }
dc8c34
@@ -1437,7 +1440,7 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int state,
dc8c34
         if (CACHE_FULL(cache))
dc8c34
             eflush = entrycache_flush(cache);
dc8c34
     }
dc8c34
-    PR_Unlock(cache->c_mutex);
dc8c34
+    cache_unlock(cache);
dc8c34
 
dc8c34
     while (eflush)
dc8c34
     {
dc8c34
@@ -1489,11 +1492,11 @@ int cache_add_tentative(struct cache *cache, struct backentry *e,
dc8c34
 }
dc8c34
 void cache_lock(struct cache *cache)
dc8c34
 {
dc8c34
-    PR_Lock(cache->c_mutex);
dc8c34
+	PR_EnterMonitor(cache->c_mutex);
dc8c34
 }
dc8c34
 void cache_unlock(struct cache *cache)
dc8c34
 {
dc8c34
-    PR_Unlock(cache->c_mutex);
dc8c34
+	PR_ExitMonitor(cache->c_mutex);
dc8c34
 }
dc8c34
 
dc8c34
 /* locks an entry so that it can be modified (you should have gotten the
dc8c34
@@ -1527,14 +1530,14 @@ int cache_lock_entry(struct cache *cache, struct backentry *e)
dc8c34
     PR_EnterMonitor(e->ep_mutexp);
dc8c34
 
dc8c34
     /* make sure entry hasn't been deleted now */
dc8c34
-    PR_Lock(cache->c_mutex);
dc8c34
+    cache_lock(cache);
dc8c34
     if (e->ep_state & (ENTRY_STATE_DELETED|ENTRY_STATE_NOTINCACHE)) {
dc8c34
-       PR_Unlock(cache->c_mutex);
dc8c34
+       cache_unlock(cache);
dc8c34
        PR_ExitMonitor(e->ep_mutexp);
dc8c34
        LOG("<= cache_lock_entry (DELETED)\n", 0, 0, 0);
dc8c34
        return RETRY_CACHE_LOCK;
dc8c34
     }
dc8c34
-    PR_Unlock(cache->c_mutex);
dc8c34
+    cache_unlock(cache);
dc8c34
 
dc8c34
     LOG("<= cache_lock_entry (FOUND)\n", 0, 0, 0);
dc8c34
     return 0;
dc8c34
@@ -1600,7 +1603,7 @@ dncache_set_max_size(struct cache *cache, size_t bytes)
dc8c34
                 "WARNING -- Minimum cache size is %lu -- rounding up\n",
dc8c34
                 MINCACHESIZE, 0, 0);
dc8c34
     }
dc8c34
-    PR_Lock(cache->c_mutex);
dc8c34
+    cache_lock(cache);
dc8c34
     cache->c_maxsize = bytes;
dc8c34
     LOG("entry cache size set to %lu\n", bytes, 0, 0);
dc8c34
     /* check for full cache, and clear out if necessary */
dc8c34
@@ -1620,7 +1623,7 @@ dncache_set_max_size(struct cache *cache, size_t bytes)
dc8c34
        erase_cache(cache, CACHE_TYPE_DN);
dc8c34
        cache_make_hashes(cache, CACHE_TYPE_DN);
dc8c34
     }
dc8c34
-    PR_Unlock(cache->c_mutex);
dc8c34
+    cache_unlock(cache);
dc8c34
     if (! dblayer_is_cachesize_sane(&bytes)) {
dc8c34
        LDAPDebug1Arg(LDAP_DEBUG_ANY,
dc8c34
                 "WARNING -- Possible CONFIGURATION ERROR -- cachesize "
dc8c34
@@ -1684,7 +1687,7 @@ dncache_return(struct cache *cache, struct backdn **bdn)
dc8c34
     LOG("=> dncache_return (%s) reference count: %d, dn in cache:%ld\n",
dc8c34
       slapi_sdn_get_dn((*bdn)->dn_sdn), (*bdn)->ep_refcnt, cache->c_curentries);
dc8c34
 
dc8c34
-    PR_Lock(cache->c_mutex);
dc8c34
+    cache_lock(cache);
dc8c34
     if ((*bdn)->ep_state & ENTRY_STATE_NOTINCACHE)
dc8c34
     {
dc8c34
         backdn_free(bdn);
dc8c34
@@ -1704,7 +1707,7 @@ dncache_return(struct cache *cache, struct backdn **bdn)
dc8c34
             }
dc8c34
         }
dc8c34
     }
dc8c34
-    PR_Unlock(cache->c_mutex);
dc8c34
+    cache_unlock(cache);
dc8c34
     while (dnflush)
dc8c34
     {
dc8c34
         dnflushtemp = BACK_LRU_NEXT(dnflush, struct backdn *);
dc8c34
@@ -1725,22 +1728,22 @@ dncache_find_id(struct cache *cache, ID id)
dc8c34
 
dc8c34
     LOG("=> dncache_find_id (%lu)\n", (u_long)id, 0, 0);
dc8c34
 
dc8c34
-    PR_Lock(cache->c_mutex);
dc8c34
+    cache_lock(cache);
dc8c34
     if (find_hash(cache->c_idtable, &id, sizeof(ID), (void **)&bdn)) {
dc8c34
        /* need to check entry state */
dc8c34
        if (bdn->ep_state != 0) {
dc8c34
            /* entry is deleted or not fully created yet */
dc8c34
-           PR_Unlock(cache->c_mutex);
dc8c34
+           cache_unlock(cache);
dc8c34
            LOG("<= dncache_find_id (NOT FOUND)\n", 0, 0, 0);
dc8c34
            return NULL;
dc8c34
        }
dc8c34
        if (bdn->ep_refcnt == 0)
dc8c34
            lru_delete(cache, (void *)bdn);
dc8c34
        bdn->ep_refcnt++;
dc8c34
-       PR_Unlock(cache->c_mutex);
dc8c34
+       cache_unlock(cache);
dc8c34
        slapi_counter_increment(cache->c_hits);
dc8c34
     } else {
dc8c34
-       PR_Unlock(cache->c_mutex);
dc8c34
+       cache_unlock(cache);
dc8c34
     }
dc8c34
     slapi_counter_increment(cache->c_tries);
dc8c34
 
dc8c34
@@ -1765,7 +1768,7 @@ dncache_add_int(struct cache *cache, struct backdn *bdn, int state,
dc8c34
     LOG("=> dncache_add_int( \"%s\", %ld )\n", slapi_sdn_get_dn(bdn->dn_sdn), 
dc8c34
         bdn->ep_id, 0);
dc8c34
 
dc8c34
-    PR_Lock(cache->c_mutex);
dc8c34
+    cache_lock(cache);
dc8c34
 
dc8c34
     if (! add_hash(cache->c_idtable, &(bdn->ep_id), sizeof(ID), bdn,
dc8c34
                                                            (void **)&my_alt)) {
dc8c34
@@ -1800,7 +1803,7 @@ dncache_add_int(struct cache *cache, struct backdn *bdn, int state,
dc8c34
                  * to prevent that the caller accidentally thinks the existing
dc8c34
                  * entry is not the same one the caller has and releases it.
dc8c34
                  */
dc8c34
-                PR_Unlock(cache->c_mutex);
dc8c34
+                cache_unlock(cache);
dc8c34
                 return 1;
dc8c34
             }
dc8c34
         }
dc8c34
@@ -1810,14 +1813,14 @@ dncache_add_int(struct cache *cache, struct backdn *bdn, int state,
dc8c34
             {
dc8c34
                 LOG("the entry is reserved\n", 0, 0, 0);
dc8c34
                 bdn->ep_state |= ENTRY_STATE_NOTINCACHE;
dc8c34
-                PR_Unlock(cache->c_mutex);
dc8c34
+                cache_unlock(cache);
dc8c34
                 return -1;
dc8c34
             }
dc8c34
             else if (state != 0)
dc8c34
             {
dc8c34
                 LOG("the entry already exists. cannot reserve it.\n", 0, 0, 0);
dc8c34
                 bdn->ep_state |= ENTRY_STATE_NOTINCACHE;
dc8c34
-                PR_Unlock(cache->c_mutex);
dc8c34
+                cache_unlock(cache);
dc8c34
                 return -1;
dc8c34
             }
dc8c34
             else
dc8c34
@@ -1828,7 +1831,7 @@ dncache_add_int(struct cache *cache, struct backdn *bdn, int state,
dc8c34
                         lru_delete(cache, (void *)*alt);
dc8c34
                     (*alt)->ep_refcnt++;
dc8c34
                 }
dc8c34
-                PR_Unlock(cache->c_mutex);
dc8c34
+                cache_unlock(cache);
dc8c34
                 return 1;
dc8c34
             }
dc8c34
         }
dc8c34
@@ -1857,7 +1860,7 @@ dncache_add_int(struct cache *cache, struct backdn *bdn, int state,
dc8c34
             dnflush = dncache_flush(cache);
dc8c34
         }
dc8c34
     }
dc8c34
-    PR_Unlock(cache->c_mutex);
dc8c34
+    cache_unlock(cache);
dc8c34
 
dc8c34
     while (dnflush)
dc8c34
     {
dc8c34
@@ -1885,7 +1888,7 @@ dncache_replace(struct cache *cache, struct backdn *olddn, struct backdn *newdn)
dc8c34
      * where the entry isn't in all the table yet, so we don't care if any
dc8c34
      * of these return errors.
dc8c34
      */
dc8c34
-    PR_Lock(cache->c_mutex);
dc8c34
+    cache_lock(cache);
dc8c34
 
dc8c34
     /*
dc8c34
      * First, remove the old entry from the hashtable.
dc8c34
@@ -1897,7 +1900,7 @@ dncache_replace(struct cache *cache, struct backdn *olddn, struct backdn *newdn)
dc8c34
         found = remove_hash(cache->c_idtable, &(olddn->ep_id), sizeof(ID));
dc8c34
         if (!found) {
dc8c34
             LOG("dn cache replace: cache index tables out of sync\n", 0, 0, 0);
dc8c34
-            PR_Unlock(cache->c_mutex);
dc8c34
+            cache_unlock(cache);
dc8c34
             return 1;
dc8c34
         }
dc8c34
     }
dc8c34
@@ -1908,7 +1911,7 @@ dncache_replace(struct cache *cache, struct backdn *olddn, struct backdn *newdn)
dc8c34
      */
dc8c34
     if (!add_hash(cache->c_idtable, &(newdn->ep_id), sizeof(ID), newdn, NULL)) {
dc8c34
        LOG("dn cache replace: can't add id\n", 0, 0, 0);
dc8c34
-       PR_Unlock(cache->c_mutex);
dc8c34
+       cache_unlock(cache);
dc8c34
        return 1;
dc8c34
     }
dc8c34
     /* adjust cache meta info */
dc8c34
@@ -1923,7 +1926,7 @@ dncache_replace(struct cache *cache, struct backdn *olddn, struct backdn *newdn)
dc8c34
     }
dc8c34
     olddn->ep_state = ENTRY_STATE_DELETED;
dc8c34
     newdn->ep_state = 0;
dc8c34
-    PR_Unlock(cache->c_mutex);
dc8c34
+    cache_unlock(cache);
dc8c34
     LOG("<= dncache_replace OK,  cache size now %lu cache count now %ld\n",
dc8c34
              slapi_counter_get_value(cache->c_cursize), cache->c_curentries, 0);
dc8c34
     return 0;
dc8c34
@@ -2006,3 +2009,37 @@ dn_lru_verify(struct cache *cache, struct backdn *dn, int in)
dc8c34
     ASSERT(is_in == in);
dc8c34
 }
dc8c34
 #endif
dc8c34
+
dc8c34
+int
dc8c34
+cache_has_otherref(struct cache *cache, void *ptr)
dc8c34
+{
dc8c34
+    struct backcommon *bep;
dc8c34
+    int hasref = 0;
dc8c34
+
dc8c34
+    if (NULL == ptr) {
dc8c34
+        return hasref;
dc8c34
+    }
dc8c34
+    bep = (struct backcommon *)ptr;
dc8c34
+    cache_lock(cache);
dc8c34
+    hasref = bep->ep_refcnt;
dc8c34
+    cache_unlock(cache);
dc8c34
+
dc8c34
+    return (hasref>1)?1:0;
dc8c34
+}
dc8c34
+
dc8c34
+int
dc8c34
+cache_is_in_cache(struct cache *cache, void *ptr)
dc8c34
+{
dc8c34
+    struct backcommon *bep;
dc8c34
+    int in_cache = 0;
dc8c34
+
dc8c34
+    if (NULL == ptr) {
dc8c34
+        return in_cache;
dc8c34
+    }
dc8c34
+    bep = (struct backcommon *)ptr;
dc8c34
+    cache_lock(cache);
dc8c34
+    in_cache = (bep->ep_state & (ENTRY_STATE_DELETED|ENTRY_STATE_NOTINCACHE))?0:1;
dc8c34
+    cache_unlock(cache);
dc8c34
+
dc8c34
+    return in_cache;
dc8c34
+}
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c
dc8c34
index 6361bc7..5069f98 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c
dc8c34
@@ -84,6 +84,7 @@ ldbm_back_add( Slapi_PBlock *pb )
dc8c34
 	struct backentry *addingentry = NULL;
dc8c34
 	struct backentry *parententry = NULL;
dc8c34
 	struct backentry *originalentry = NULL;
dc8c34
+	struct backentry *tmpentry = NULL;
dc8c34
 	ID pid;
dc8c34
 	int	isroot;
dc8c34
 	char *errbuf= NULL;
dc8c34
@@ -103,12 +104,11 @@ ldbm_back_add( Slapi_PBlock *pb )
dc8c34
 	int ruv_c_init = 0;
dc8c34
 	int rc;
dc8c34
 	int addingentry_id_assigned= 0;
dc8c34
-	int addingentry_in_cache= 0;
dc8c34
-	int tombstone_in_cache= 0;
dc8c34
 	Slapi_DN *sdn = NULL;
dc8c34
 	Slapi_DN parentsdn;
dc8c34
 	Slapi_Operation *operation;
dc8c34
 	int dblock_acquired= 0;
dc8c34
+	int is_remove_from_cache= 0;
dc8c34
 	int is_replicated_operation= 0;
dc8c34
 	int is_resurect_operation= 0;
dc8c34
 	int is_tombstone_operation= 0;
dc8c34
@@ -118,6 +118,7 @@ ldbm_back_add( Slapi_PBlock *pb )
dc8c34
 	entry_address addr = {0};
dc8c34
 	int parent_switched = 0;
dc8c34
 	int noabort = 1;
dc8c34
+	const char *dn = NULL;
dc8c34
 
dc8c34
 	slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
dc8c34
 	slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &e );
dc8c34
@@ -425,7 +426,6 @@ ldbm_back_add( Slapi_PBlock *pb )
dc8c34
 			ldap_result_code= -1;
dc8c34
 			goto error_return;  /* error result sent by find_entry2modify() */
dc8c34
 		}
dc8c34
-		tombstone_in_cache = 1;
dc8c34
 
dc8c34
 		addingentry = backentry_dup( tombstoneentry );
dc8c34
 		if ( addingentry==NULL )
dc8c34
@@ -684,14 +684,13 @@ ldbm_back_add( Slapi_PBlock *pb )
dc8c34
 
dc8c34
 	/* Tentatively add the entry to the cache.  We do this after adding any
dc8c34
 	 * operational attributes to ensure that the cache is sized correctly. */
dc8c34
-	if ( cache_add_tentative( &inst->inst_cache, addingentry, NULL )!= 0 )
dc8c34
+	if ( cache_add_tentative( &inst->inst_cache, addingentry, NULL ) < 0 )
dc8c34
 	{
dc8c34
 		LDAPDebug1Arg(LDAP_DEBUG_CACHE, "cache_add_tentative concurrency detected: %s\n",
dc8c34
 		              slapi_entry_get_dn_const(addingentry->ep_entry));
dc8c34
 		ldap_result_code= LDAP_ALREADY_EXISTS;
dc8c34
 		goto error_return;
dc8c34
 	}
dc8c34
-	addingentry_in_cache = 1;
dc8c34
 
dc8c34
 	/*
dc8c34
 	 * Before we add the entry, find out if the syntax of the aci
dc8c34
@@ -740,33 +739,32 @@ ldbm_back_add( Slapi_PBlock *pb )
dc8c34
 			noabort = 1;
dc8c34
 			slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
dc8c34
 
dc8c34
-			if (addingentry_in_cache) {
dc8c34
+			/* must duplicate addingentry before returning it to cache,
dc8c34
+			 * which could free the entry. */
dc8c34
+			if ( (tmpentry = backentry_dup( addingentry )) == NULL ) {
dc8c34
+				ldap_result_code= LDAP_OPERATIONS_ERROR;
dc8c34
+				goto error_return;
dc8c34
+			}
dc8c34
+			if (cache_is_in_cache(&inst->inst_cache, addingentry)) {
dc8c34
 				/* addingentry is in cache.  Remove it once. */
dc8c34
 				retval = CACHE_REMOVE(&inst->inst_cache, addingentry);
dc8c34
 				if (retval) {
dc8c34
 					LDAPDebug1Arg(LDAP_DEBUG_CACHE, "ldbm_add: cache_remove %s failed.\n",
dc8c34
 					              slapi_entry_get_dn_const(addingentry->ep_entry));
dc8c34
 				}
dc8c34
-				CACHE_RETURN(&inst->inst_cache, &addingentry);
dc8c34
-			} else {
dc8c34
-				backentry_free(&addingentry);
dc8c34
 			}
dc8c34
+			CACHE_RETURN(&inst->inst_cache, &addingentry);
dc8c34
 			slapi_pblock_set( pb, SLAPI_ADD_ENTRY, originalentry->ep_entry );
dc8c34
 			addingentry = originalentry;
dc8c34
-			if ( (originalentry = backentry_dup( addingentry )) == NULL ) {
dc8c34
-				ldap_result_code= LDAP_OPERATIONS_ERROR;
dc8c34
+			originalentry = tmpentry;
dc8c34
+			tmpentry = NULL;
dc8c34
+			/* Adding the resetted addingentry to the cache. */
dc8c34
+			if (cache_add_tentative(&inst->inst_cache, addingentry, NULL) < 0) {
dc8c34
+				LDAPDebug1Arg(LDAP_DEBUG_CACHE, "cache_add_tentative concurrency detected: %s\n",
dc8c34
+					slapi_entry_get_dn_const(addingentry->ep_entry));
dc8c34
+				ldap_result_code = LDAP_ALREADY_EXISTS;
dc8c34
 				goto error_return;
dc8c34
 			}
dc8c34
-			if (addingentry_in_cache) {
dc8c34
-				/* Adding the resetted addingentry to the cache. */
dc8c34
-				if (cache_add_tentative(&inst->inst_cache, addingentry, NULL) != 0) {
dc8c34
-					LDAPDebug1Arg(LDAP_DEBUG_CACHE, "cache_add_tentative concurrency detected: %s\n",
dc8c34
-					              slapi_entry_get_dn_const(addingentry->ep_entry));
dc8c34
-					ldap_result_code = LDAP_ALREADY_EXISTS;
dc8c34
-					addingentry_in_cache = 0;
dc8c34
-					goto error_return;
dc8c34
-				}
dc8c34
-			}
dc8c34
 			if (ruv_c_init) {
dc8c34
 				/* reset the ruv txn stuff */
dc8c34
 				modify_term(&ruv_c, be);
dc8c34
@@ -1038,10 +1036,6 @@ ldbm_back_add( Slapi_PBlock *pb )
dc8c34
 			retval = -1;
dc8c34
 			goto error_return;
dc8c34
 		}
dc8c34
-		if (addingentry_in_cache) { /* decrease the refcnt added by tentative */
dc8c34
-			CACHE_RETURN( &inst->inst_cache, &addingentry );
dc8c34
-		}
dc8c34
-		addingentry_in_cache = 1; /* reset it to make it sure... */
dc8c34
 		/*
dc8c34
 		 * The tombstone was locked down in the cache... we can
dc8c34
 		 * get rid of the entry in the cache now.
dc8c34
@@ -1056,9 +1050,6 @@ ldbm_back_add( Slapi_PBlock *pb )
dc8c34
 				CACHE_RETURN(&inst->inst_dncache, &bdn;;
dc8c34
 			}
dc8c34
 		}
dc8c34
-		cache_unlock_entry( &inst->inst_cache, tombstoneentry );
dc8c34
-		CACHE_RETURN( &inst->inst_cache, &tombstoneentry );
dc8c34
-		tombstone_in_cache = 0;
dc8c34
 	}
dc8c34
 	if (parent_found)
dc8c34
 	{
dc8c34
@@ -1116,20 +1107,6 @@ error_return:
dc8c34
 	{
dc8c34
 		next_id_return( be, addingentry->ep_id );
dc8c34
 	}
dc8c34
-	if ( addingentry )
dc8c34
-	{
dc8c34
-		if ( addingentry_in_cache )
dc8c34
-		{
dc8c34
-			CACHE_REMOVE(&inst->inst_cache, addingentry);
dc8c34
-		}
dc8c34
-		else
dc8c34
-		{
dc8c34
-			if (!is_resurect_operation) { /* if resurect, tombstoneentry is dupped. */
dc8c34
-				backentry_clear_entry(addingentry); /* e is released in the frontend */
dc8c34
-			}
dc8c34
-			backentry_free( &addingentry ); /* release the backend wrapper, here */
dc8c34
-		}
dc8c34
-	}
dc8c34
 	if (rc == DB_RUNRECOVERY) {
dc8c34
 		dblayer_remember_disk_filled(li);
dc8c34
 		ldbm_nasty("Add",80,rc);
dc8c34
@@ -1149,6 +1126,21 @@ error_return:
dc8c34
 
dc8c34
 diskfull_return:
dc8c34
 	if (disk_full) {
dc8c34
+		if ( addingentry )
dc8c34
+		{
dc8c34
+			if (inst && cache_is_in_cache(&inst->inst_cache, addingentry)) {
dc8c34
+				CACHE_REMOVE(&inst->inst_cache, addingentry);
dc8c34
+				/* tell frontend not to free this entry */
dc8c34
+				slapi_pblock_set(pb, SLAPI_ADD_ENTRY, NULL);
dc8c34
+			}
dc8c34
+			else if (!cache_has_otherref(&inst->inst_cache, addingentry))
dc8c34
+			{
dc8c34
+				if (!is_resurect_operation) { /* if resurect, tombstoneentry is dupped. */
dc8c34
+					backentry_clear_entry(addingentry); /* e is released in the frontend */
dc8c34
+				}
dc8c34
+			}
dc8c34
+			CACHE_RETURN( &inst->inst_cache, &addingentry );
dc8c34
+		}
dc8c34
 		rc = return_on_disk_full(li);
dc8c34
 	} else {
dc8c34
 		/* It is safer not to abort when the transaction is not started. */
dc8c34
@@ -1187,38 +1179,57 @@ diskfull_return:
dc8c34
 			}
dc8c34
 			/* txn is no longer valid - reset the txn pointer to the parent */
dc8c34
 			slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
dc8c34
+		} else {
dc8c34
+			if ( addingentry ) {
dc8c34
+				if (inst && cache_is_in_cache(&inst->inst_cache, addingentry)) {
dc8c34
+					CACHE_REMOVE(&inst->inst_cache, addingentry);
dc8c34
+					/* tell frontend not to free this entry */
dc8c34
+					slapi_pblock_set(pb, SLAPI_ADD_ENTRY, NULL);
dc8c34
+				}
dc8c34
+				else if (!cache_has_otherref(&inst->inst_cache, addingentry))
dc8c34
+				{
dc8c34
+					if (!is_resurect_operation) { /* if resurect, tombstoneentry is dupped. */
dc8c34
+						backentry_clear_entry(addingentry); /* e is released in the frontend */
dc8c34
+					}
dc8c34
+				}
dc8c34
+				CACHE_RETURN( &inst->inst_cache, &addingentry );
dc8c34
+			}
dc8c34
 		}
dc8c34
 		rc = SLAPI_FAIL_GENERAL;
dc8c34
 	}
dc8c34
 	
dc8c34
 common_return:
dc8c34
 	if (inst) {
dc8c34
-		if(tombstone_in_cache && tombstoneentry) {
dc8c34
+		if (tombstoneentry && cache_is_in_cache(&inst->inst_cache, tombstoneentry)) {
dc8c34
 			cache_unlock_entry(&inst->inst_cache, tombstoneentry);
dc8c34
 			CACHE_RETURN(&inst->inst_cache, &tombstoneentry);
dc8c34
 		}
dc8c34
-	}
dc8c34
-	if (addingentry_in_cache && addingentry) {
dc8c34
-		if ((0 == retval) && entryrdn_get_switch()) { /* subtree-rename: on */
dc8c34
-			/* since the op was successful, add the addingentry's dn to the dn cache */
dc8c34
-			struct backdn *bdn = dncache_find_id(&inst->inst_dncache,
dc8c34
-			                                     addingentry->ep_id);
dc8c34
-			if (bdn) { /* already in the dncache */
dc8c34
-				CACHE_RETURN(&inst->inst_dncache, &bdn;;
dc8c34
-			} else { /* not in the dncache yet */
dc8c34
-				Slapi_DN *addingsdn = slapi_sdn_dup(slapi_entry_get_sdn(addingentry->ep_entry));
dc8c34
-				if (addingsdn) {
dc8c34
-					bdn = backdn_init(addingsdn, addingentry->ep_id, 0);
dc8c34
-					if (bdn) {
dc8c34
-						CACHE_ADD( &inst->inst_dncache, bdn, NULL );
dc8c34
-						CACHE_RETURN(&inst->inst_dncache, &bdn;;
dc8c34
-						slapi_log_error(SLAPI_LOG_CACHE, "ldbm_back_add",
dc8c34
-						                "set %s to dn cache\n", slapi_sdn_get_dn(sdn));
dc8c34
+		if (addingentry) {
dc8c34
+			if ((0 == retval) && entryrdn_get_switch()) { /* subtree-rename: on */
dc8c34
+				/* since adding the entry to the entry cache was successful,
dc8c34
+				 * let's add the dn to dncache, if not yet done. */
dc8c34
+				struct backdn *bdn = dncache_find_id(&inst->inst_dncache,
dc8c34
+				                                     addingentry->ep_id);
dc8c34
+				if (bdn) { /* already in the dncache */
dc8c34
+					CACHE_RETURN(&inst->inst_dncache, &bdn;;
dc8c34
+				} else { /* not in the dncache yet */
dc8c34
+					Slapi_DN *addingsdn = slapi_sdn_dup(slapi_entry_get_sdn(addingentry->ep_entry));
dc8c34
+					if (addingsdn) {
dc8c34
+						bdn = backdn_init(addingsdn, addingentry->ep_id, 0);
dc8c34
+						if (bdn) {
dc8c34
+							CACHE_ADD( &inst->inst_dncache, bdn, NULL );
dc8c34
+							CACHE_RETURN(&inst->inst_dncache, &bdn;;
dc8c34
+							slapi_log_error(SLAPI_LOG_CACHE, "ldbm_back_add",
dc8c34
+							                "set %s to dn cache\n", dn);
dc8c34
+						}
dc8c34
 					}
dc8c34
 				}
dc8c34
 			}
dc8c34
+			if (is_remove_from_cache) {
dc8c34
+				CACHE_REMOVE(&inst->inst_cache, addingentry);
dc8c34
+			}
dc8c34
+			CACHE_RETURN( &inst->inst_cache, &addingentry );
dc8c34
 		}
dc8c34
-		CACHE_RETURN( &inst->inst_cache, &addingentry );
dc8c34
 	}
dc8c34
 	/* bepost op needs to know this result */
dc8c34
 	slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
dc8c34
@@ -1240,6 +1251,7 @@ common_return:
dc8c34
 		slapi_send_ldap_result( pb, ldap_result_code, ldap_result_matcheddn, ldap_result_message, 0, NULL );
dc8c34
 	}
dc8c34
 	backentry_free(&originalentry);
dc8c34
+	backentry_free(&tmpentry);
dc8c34
 	slapi_sdn_done(&parentsdn);
dc8c34
 	slapi_ch_free( (void**)&ldap_result_matcheddn );
dc8c34
 	slapi_ch_free( (void**)&errbuf );
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
dc8c34
index 32c119c..e06f241 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
dc8c34
@@ -60,6 +60,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
dc8c34
 	struct ldbminfo	*li = NULL;
dc8c34
 	struct backentry *e = NULL;
dc8c34
 	struct backentry *tombstone = NULL;
dc8c34
+	struct backentry *tmptombstone = NULL;
dc8c34
 	struct backentry *original_tombstone = NULL;
dc8c34
 	const char *dn = NULL;
dc8c34
 	back_txn txn;
dc8c34
@@ -89,8 +90,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
dc8c34
 	int delete_tombstone_entry = 0;	/* We must remove the given tombstone entry from the DB	*/
dc8c34
 	int create_tombstone_entry = 0;	/* We perform a "regular" LDAP delete but since we use	*/
dc8c34
 									/* replication, we must create a new tombstone entry	*/
dc8c34
-	int tombstone_in_cache = 0;
dc8c34
-	int e_in_cache = 0;
dc8c34
 	int remove_e_from_cache = 0;
dc8c34
 	entry_address *addr;
dc8c34
 	int addordel_flags = 0; /* passed to index_addordel */
dc8c34
@@ -99,6 +98,8 @@ ldbm_back_delete( Slapi_PBlock *pb )
dc8c34
 	Slapi_DN parentsdn;
dc8c34
 	int opreturn = 0;
dc8c34
 	int free_delete_existing_entry = 0;
dc8c34
+	ID ep_id = 0;
dc8c34
+	ID tomb_ep_id = 0;
dc8c34
 
dc8c34
 	slapi_pblock_get( pb, SLAPI_BACKEND, &be);
dc8c34
 	slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
dc8c34
@@ -194,7 +195,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
dc8c34
 		LDAPDebug0Args(LDAP_DEBUG_BACKLDBM, "ldbm_back_delete: Deleting entry is already deleted.\n");
dc8c34
 		goto error_return; /* error result sent by find_entry2modify() */
dc8c34
 	}
dc8c34
-	e_in_cache = 1; /* e is cached */
dc8c34
+	ep_id = e->ep_id;
dc8c34
 
dc8c34
 	retval = slapi_entry_has_children(e->ep_entry);
dc8c34
 	if (retval) {
dc8c34
@@ -472,6 +473,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
dc8c34
 			parentuniqueid= slapi_entry_get_uniqueid(parent_modify_c.old_entry->ep_entry);
dc8c34
 		}
dc8c34
 		tombstone = backentry_dup( e );
dc8c34
+		tomb_ep_id = tombstone->ep_id;
dc8c34
 		slapi_entry_set_dn(tombstone->ep_entry,tombstone_dn); /* Consumes DN */
dc8c34
 		if (entryrdn_get_switch()) /* subtree-rename: on */
dc8c34
 		{
dc8c34
@@ -534,25 +536,20 @@ ldbm_back_delete( Slapi_PBlock *pb )
dc8c34
 
dc8c34
 			/* reset tombstone entry */
dc8c34
 			if (original_tombstone) {
dc8c34
-				if (tombstone_in_cache) {
dc8c34
-					CACHE_REMOVE(&inst->inst_cache, tombstone);
dc8c34
-					CACHE_RETURN(&inst->inst_cache, &tombstone);
dc8c34
-					tombstone = NULL;
dc8c34
-					tombstone_in_cache = 0; 
dc8c34
-				} else {
dc8c34
-					backentry_free(&tombstone);
dc8c34
-				}
dc8c34
-				tombstone = original_tombstone;
dc8c34
-				if ( (original_tombstone = backentry_dup( tombstone )) == NULL ) {
dc8c34
+				/* must duplicate tombstone before returning it to cache,
dc8c34
+				 * which could free the entry. */
dc8c34
+				if ( (tmptombstone = backentry_dup( original_tombstone )) == NULL ) {
dc8c34
 					ldap_result_code= LDAP_OPERATIONS_ERROR;
dc8c34
 					goto error_return;
dc8c34
 				}
dc8c34
+				if (cache_is_in_cache(&inst->inst_cache, tombstone)) {
dc8c34
+					CACHE_REMOVE(&inst->inst_cache, tombstone);
dc8c34
+				}
dc8c34
+				CACHE_RETURN(&inst->inst_cache, &tombstone);
dc8c34
+				tombstone = original_tombstone;
dc8c34
+				original_tombstone = tmptombstone;
dc8c34
+				tmptombstone = NULL;
dc8c34
 			}
dc8c34
-			/* reset original entry in cache */ 
dc8c34
-			if (!e_in_cache) { 
dc8c34
-				CACHE_ADD(&inst->inst_cache, e, NULL); 
dc8c34
-				e_in_cache = 1; 
dc8c34
-			} 
dc8c34
 			if (ruv_c_init) {
dc8c34
 				/* reset the ruv txn stuff */
dc8c34
 				modify_term(&ruv_c, be);
dc8c34
@@ -647,13 +644,10 @@ ldbm_back_delete( Slapi_PBlock *pb )
dc8c34
 			 * entry is removed from the cache.
dc8c34
 			 */
dc8c34
 			retval = cache_add_tentative(&inst->inst_cache, tombstone, NULL);
dc8c34
-			if (0 == retval) {
dc8c34
-				tombstone_in_cache = 1;
dc8c34
-			} else {
dc8c34
+			if (0 > retval) {
dc8c34
 				LDAPDebug2Args(LDAP_DEBUG_ANY,
dc8c34
 				               "tombstone entry %s failed to add to the cache: %d\n",
dc8c34
 				               slapi_entry_get_dn(tombstone->ep_entry), retval);
dc8c34
-				tombstone_in_cache = 0;
dc8c34
 				if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
dc8c34
 				DEL_SET_ERROR(ldap_result_code, 
dc8c34
 							  LDAP_OPERATIONS_ERROR, retry_count);
dc8c34
@@ -672,13 +666,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
dc8c34
 				DEL_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
dc8c34
 				goto error_return;
dc8c34
 			}
dc8c34
-			if (tombstone_in_cache) {
dc8c34
-				/* tombstone was already added to the cache via cache_add_tentative (to reserve its spot in the cache)
dc8c34
-				   and/or id2entry_add - so it already had one refcount - cache_replace adds another refcount -
dc8c34
-				   drop the extra ref added by cache_replace */
dc8c34
-				CACHE_RETURN( &inst->inst_cache, &tombstone );
dc8c34
-			}
dc8c34
-			tombstone_in_cache = 1;
dc8c34
 		}
dc8c34
 		else
dc8c34
 		{
dc8c34
@@ -1129,22 +1116,22 @@ ldbm_back_delete( Slapi_PBlock *pb )
dc8c34
 
dc8c34
 	/* delete from cache and clean up */
dc8c34
 	if (e) {
dc8c34
-		if (entryrdn_get_switch()) { /* subtree-rename: on */
dc8c34
+		if (cache_is_in_cache(&inst->inst_cache, e)) {
dc8c34
+			ep_id = e->ep_id;
dc8c34
+			CACHE_REMOVE(&inst->inst_cache, e);
dc8c34
+		}
dc8c34
+		cache_unlock_entry(&inst->inst_cache, e);
dc8c34
+		CACHE_RETURN(&inst->inst_cache, &e);
dc8c34
+		e = NULL;
dc8c34
+
dc8c34
+		if (entryrdn_get_switch() && ep_id) { /* subtree-rename: on */
dc8c34
 			/* since the op was successful, delete the tombstone dn from the dn cache */
dc8c34
-			struct backdn *bdn = dncache_find_id(&inst->inst_dncache, e->ep_id);
dc8c34
+			struct backdn *bdn = dncache_find_id(&inst->inst_dncache, ep_id);
dc8c34
 			if (bdn) { /* in the dncache, remove it. */
dc8c34
 				CACHE_REMOVE(&inst->inst_dncache, bdn);
dc8c34
 				CACHE_RETURN(&inst->inst_dncache, &bdn;;
dc8c34
 			}
dc8c34
 		}
dc8c34
-		if (e_in_cache) {
dc8c34
-			CACHE_REMOVE(&inst->inst_cache, e);
dc8c34
-			cache_unlock_entry(&inst->inst_cache, e);
dc8c34
-			CACHE_RETURN(&inst->inst_cache, &e);
dc8c34
-		} else {
dc8c34
-			cache_unlock_entry(&inst->inst_cache, e);
dc8c34
-		}
dc8c34
-		e = NULL;
dc8c34
 	}
dc8c34
 
dc8c34
 	if (ruv_c_init) {
dc8c34
@@ -1168,36 +1155,23 @@ ldbm_back_delete( Slapi_PBlock *pb )
dc8c34
 
dc8c34
 error_return:
dc8c34
 	if (tombstone) {
dc8c34
-		if (entryrdn_get_switch()) { /* subtree-rename: on */
dc8c34
+		if (cache_is_in_cache(&inst->inst_cache, tombstone)) {
dc8c34
+			tomb_ep_id = tombstone->ep_id;
dc8c34
+		}
dc8c34
+
dc8c34
+		if (entryrdn_get_switch() && tomb_ep_id) { /* subtree-rename: on */
dc8c34
 			/* since the op was successful, add the addingentry's dn to the dn cache */
dc8c34
-			struct backdn *bdn = dncache_find_id(&inst->inst_dncache, tombstone->ep_id);
dc8c34
+			struct backdn *bdn = dncache_find_id(&inst->inst_dncache, tomb_ep_id);
dc8c34
 			if (bdn) { /* already in the dncache. Delete it. */
dc8c34
 				CACHE_REMOVE(&inst->inst_dncache, bdn);
dc8c34
 				CACHE_RETURN(&inst->inst_dncache, &bdn;;
dc8c34
-			} 
dc8c34
+			}
dc8c34
 		}
dc8c34
-		if (tombstone_in_cache) { /* successfully replaced */
dc8c34
+		if (cache_is_in_cache(&inst->inst_cache, tombstone)) {
dc8c34
 			CACHE_REMOVE( &inst->inst_cache, tombstone );
dc8c34
-			CACHE_RETURN( &inst->inst_cache, &tombstone );
dc8c34
-			tombstone = NULL;
dc8c34
-			tombstone_in_cache = 0;
dc8c34
-		} else {
dc8c34
-			backentry_free( &tombstone );
dc8c34
-		}
dc8c34
-	}
dc8c34
-
dc8c34
-	/* Need to return to cache after post op plugins are called */
dc8c34
-	if (e) {
dc8c34
-		if (e_in_cache) {
dc8c34
-			if (remove_e_from_cache) {
dc8c34
-				/* The entry is already transformed to a tombstone. */
dc8c34
-				CACHE_REMOVE( &inst->inst_cache, e );
dc8c34
-			}
dc8c34
-			cache_unlock_entry( &inst->inst_cache, e );
dc8c34
-			CACHE_RETURN( &inst->inst_cache, &e );
dc8c34
-		} else {
dc8c34
-			cache_unlock_entry( &inst->inst_cache, e );
dc8c34
 		}
dc8c34
+		CACHE_RETURN( &inst->inst_cache, &tombstone );
dc8c34
+		tombstone = NULL;
dc8c34
 	}
dc8c34
 
dc8c34
 	if (retval == DB_RUNRECOVERY) {
dc8c34
@@ -1257,7 +1231,7 @@ common_return:
dc8c34
 		   for the post op plugins */
dc8c34
 		slapi_pblock_set( pb, SLAPI_DELETE_BEPREOP_ENTRY, orig_entry );
dc8c34
 	}
dc8c34
-	if (tombstone) {
dc8c34
+	if (inst && tombstone) {
dc8c34
 		if ((0 == retval) && entryrdn_get_switch()) { /* subtree-rename: on */
dc8c34
 			/* since the op was successful, add the addingentry's dn to the dn cache */
dc8c34
 			struct backdn *bdn = dncache_find_id(&inst->inst_dncache, tombstone->ep_id);
dc8c34
@@ -1276,13 +1250,8 @@ common_return:
dc8c34
 				}
dc8c34
 			}
dc8c34
 		}
dc8c34
-		if (tombstone_in_cache) { /* successfully replaced */
dc8c34
-			CACHE_RETURN( &inst->inst_cache, &tombstone );
dc8c34
-			tombstone = NULL;
dc8c34
-			tombstone_in_cache = 0;
dc8c34
-		} else {
dc8c34
-			backentry_free( &tombstone );
dc8c34
-		}
dc8c34
+		CACHE_RETURN( &inst->inst_cache, &tombstone );
dc8c34
+		tombstone = NULL;
dc8c34
 	}
dc8c34
 	
dc8c34
 	/* result code could be used in the bepost plugin functions. */
dc8c34
@@ -1296,7 +1265,7 @@ common_return:
dc8c34
 	}
dc8c34
 
dc8c34
 	if (e) {
dc8c34
-		if (e_in_cache) {
dc8c34
+		if (cache_is_in_cache(&inst->inst_cache, e)) {
dc8c34
 			if (remove_e_from_cache) {
dc8c34
 				/* The entry is already transformed to a tombstone. */
dc8c34
 				CACHE_REMOVE( &inst->inst_cache, e );
dc8c34
@@ -1341,6 +1310,7 @@ diskfull_return:
dc8c34
 		slapi_pblock_set(pb, SLAPI_DELETE_EXISTING_ENTRY, NULL);
dc8c34
 	}
dc8c34
 	backentry_free(&original_tombstone);
dc8c34
+	backentry_free(&tmptombstone);
dc8c34
 	slapi_ch_free((void**)&errbuf);
dc8c34
 	slapi_sdn_done(&nscpEntrySDN);
dc8c34
 	slapi_ch_free_string(&e_uniqueid);
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
dc8c34
index b6a889f..4c1f33f 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
dc8c34
@@ -65,7 +65,6 @@ void modify_init(modify_context *mc,struct backentry *old_entry)
dc8c34
 	PR_ASSERT(NULL == mc->new_entry);
dc8c34
 
dc8c34
 	mc->old_entry = old_entry;
dc8c34
-	mc->new_entry_in_cache = 0;
dc8c34
 	mc->attr_encrypt = 1;
dc8c34
 }
dc8c34
 
dc8c34
@@ -96,16 +95,13 @@ int modify_term(modify_context *mc,struct backend *be)
dc8c34
 
dc8c34
     slapi_mods_free(&mc->smods);
dc8c34
     /* Unlock and return entries */
dc8c34
-    if (NULL != mc->old_entry)  {
dc8c34
+    if (mc->old_entry)  {
dc8c34
         cache_unlock_entry(&inst->inst_cache, mc->old_entry);
dc8c34
         CACHE_RETURN( &(inst->inst_cache), &(mc->old_entry) );
dc8c34
         mc->old_entry= NULL;
dc8c34
     }
dc8c34
-    if (mc->new_entry_in_cache) {
dc8c34
-        CACHE_RETURN( &(inst->inst_cache), &(mc->new_entry) );
dc8c34
-    } else {
dc8c34
-        backentry_free(&(mc->new_entry));
dc8c34
-    }
dc8c34
+
dc8c34
+    CACHE_RETURN( &(inst->inst_cache), &(mc->new_entry) );
dc8c34
     mc->new_entry= NULL;
dc8c34
     return 0;
dc8c34
 }
dc8c34
@@ -115,11 +111,9 @@ int modify_switch_entries(modify_context *mc,backend *be)
dc8c34
 {
dc8c34
 	ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
dc8c34
 	int ret = 0;
dc8c34
-	if (mc->old_entry!=NULL && mc->new_entry!=NULL) {
dc8c34
+	if (mc->old_entry && mc->new_entry) {
dc8c34
 		ret = cache_replace(&(inst->inst_cache), mc->old_entry, mc->new_entry);
dc8c34
-		if (ret == 0) {
dc8c34
-			mc->new_entry_in_cache = 1;
dc8c34
-		} else {
dc8c34
+		if (ret){
dc8c34
 			LDAPDebug(LDAP_DEBUG_CACHE, "modify_switch_entries: replacing %s with %s failed (%d)\n",
dc8c34
 			          slapi_entry_get_dn(mc->old_entry->ep_entry), 
dc8c34
 			          slapi_entry_get_dn(mc->new_entry->ep_entry), ret);
dc8c34
@@ -140,13 +134,19 @@ modify_unswitch_entries(modify_context *mc,backend *be)
dc8c34
 	ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
dc8c34
 	int ret = 0;
dc8c34
 
dc8c34
-	if (mc->old_entry!=NULL && mc->new_entry!=NULL) {
dc8c34
+	if (mc->old_entry && mc->new_entry &&
dc8c34
+	    cache_is_in_cache(&inst->inst_cache, mc->new_entry)) {
dc8c34
 		/* switch the entries, and reset the new, new, entry */
dc8c34
 		tmp_be = mc->new_entry;
dc8c34
 		mc->new_entry = mc->old_entry;
dc8c34
 		mc->new_entry->ep_state = 0;
dc8c34
-		mc->new_entry->ep_refcnt = 0;
dc8c34
-		mc->new_entry_in_cache = 0;
dc8c34
+		if (cache_has_otherref(&(inst->inst_cache), mc->new_entry)) {
dc8c34
+			/* some other thread refers the entry */
dc8c34
+			CACHE_RETURN(&(inst->inst_cache), &(mc->new_entry));
dc8c34
+		} else {
dc8c34
+			/* don't call CACHE_RETURN, that frees the entry!  */
dc8c34
+			mc->new_entry->ep_refcnt = 0;
dc8c34
+		}
dc8c34
 		mc->old_entry = tmp_be;
dc8c34
 
dc8c34
 		ret = cache_replace(&(inst->inst_cache), mc->old_entry, mc->new_entry);
dc8c34
@@ -157,9 +157,7 @@ modify_unswitch_entries(modify_context *mc,backend *be)
dc8c34
 			 * "old" one.  modify_term() will then return the "new" entry.
dc8c34
 			 */
dc8c34
 			cache_unlock_entry(&inst->inst_cache, mc->new_entry);
dc8c34
-			CACHE_RETURN( &(inst->inst_cache), &(mc->old_entry) );
dc8c34
-			mc->new_entry_in_cache = 1;
dc8c34
-			mc->old_entry = NULL;
dc8c34
+			cache_lock_entry(&inst->inst_cache, mc->old_entry);
dc8c34
 		} else {
dc8c34
 			LDAPDebug(LDAP_DEBUG_CACHE, "modify_unswitch_entries: replacing %s with %s failed (%d)\n",
dc8c34
 			          slapi_entry_get_dn(mc->old_entry->ep_entry), 
dc8c34
@@ -362,7 +360,8 @@ ldbm_back_modify( Slapi_PBlock *pb )
dc8c34
 	backend *be;
dc8c34
 	ldbm_instance *inst = NULL;
dc8c34
 	struct ldbminfo		*li;
dc8c34
-	struct backentry	*e = NULL, *ec = NULL, *original_entry = NULL;
dc8c34
+	struct backentry	*e = NULL, *ec = NULL;
dc8c34
+	struct backentry    *original_entry = NULL, *tmpentry = NULL;;
dc8c34
 	Slapi_Entry		*postentry = NULL;
dc8c34
 	LDAPMod			**mods = NULL;
dc8c34
 	LDAPMod			**mods_original = NULL;
dc8c34
@@ -382,7 +381,6 @@ ldbm_back_modify( Slapi_PBlock *pb )
dc8c34
 	Slapi_Operation *operation;
dc8c34
 	int dblock_acquired= 0;
dc8c34
 	entry_address *addr;
dc8c34
-	int ec_in_cache = 0;
dc8c34
 	int is_fixup_operation= 0;
dc8c34
 	int is_ruv = 0;                 /* True if the current entry is RUV */
dc8c34
 	CSN *opcsn = NULL;
dc8c34
@@ -551,14 +549,21 @@ ldbm_back_modify( Slapi_PBlock *pb )
dc8c34
 			slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods;;
dc8c34
 			ldap_mods_free(mods, 1);
dc8c34
 			slapi_pblock_set(pb, SLAPI_MODIFY_MODS, copy_mods(mods_original));
dc8c34
-			/* ec is not really added to the cache until cache_replace, so we
dc8c34
-			   don't have to worry about the cache here */
dc8c34
-			backentry_free(&ec);
dc8c34
-			slapi_pblock_set( pb, SLAPI_MODIFY_EXISTING_ENTRY, original_entry->ep_entry );
dc8c34
-			ec = original_entry;
dc8c34
-			if ( (original_entry = backentry_dup( ec )) == NULL ) {
dc8c34
-				ldap_result_code= LDAP_OPERATIONS_ERROR;
dc8c34
-				goto error_return;
dc8c34
+			/* reset ec set cache in id2entry_add_ext */
dc8c34
+			if (ec) {
dc8c34
+				/* must duplicate ec before returning it to cache,
dc8c34
+				 * which could free the entry. */
dc8c34
+				if ( (tmpentry = backentry_dup( ec )) == NULL ) {
dc8c34
+					ldap_result_code= LDAP_OPERATIONS_ERROR;
dc8c34
+					goto error_return;
dc8c34
+				}
dc8c34
+				if (cache_is_in_cache(&inst->inst_cache, ec)) {
dc8c34
+					CACHE_REMOVE(&inst->inst_cache, ec);
dc8c34
+				}
dc8c34
+				CACHE_RETURN(&inst->inst_cache, &ec);
dc8c34
+				ec = original_entry;
dc8c34
+				original_entry = tmpentry;
dc8c34
+				tmpentry = NULL;
dc8c34
 			}
dc8c34
 
dc8c34
 			if (ruv_c_init) {
dc8c34
@@ -740,7 +745,6 @@ ldbm_back_modify( Slapi_PBlock *pb )
dc8c34
 
dc8c34
 	/* lock new entry in cache to prevent usage until we are complete */
dc8c34
 	cache_lock_entry( &inst->inst_cache, ec );
dc8c34
-	ec_in_cache = 1;
dc8c34
 
dc8c34
 	postentry = slapi_entry_dup( ec->ep_entry );
dc8c34
 	slapi_pblock_set( pb, SLAPI_ENTRY_POST_OP, postentry );
dc8c34
@@ -841,11 +845,11 @@ error_return:
dc8c34
 	}
dc8c34
 
dc8c34
 	/* if ec is in cache, remove it, then add back e if we still have it */
dc8c34
-	if (ec_in_cache) {
dc8c34
+	if (inst && cache_is_in_cache(&inst->inst_cache, ec)) {
dc8c34
 		CACHE_REMOVE( &inst->inst_cache, ec );
dc8c34
 		/* if ec was in cache, e was not - add back e */
dc8c34
 		if (e) {
dc8c34
-			if (CACHE_ADD( &inst->inst_cache, e, NULL )) {
dc8c34
+			if (CACHE_ADD( &inst->inst_cache, e, NULL ) < 0) {
dc8c34
 				LDAPDebug1Arg( LDAP_DEBUG_CACHE, "ldbm_modify: CACHE_ADD %s failed\n",
dc8c34
 							   slapi_entry_get_dn(e->ep_entry));
dc8c34
 			}
dc8c34
@@ -855,20 +859,17 @@ error_return:
dc8c34
 common_return:
dc8c34
 	slapi_mods_done(&smods);
dc8c34
 	
dc8c34
-	if (ec_in_cache)
dc8c34
-	{
dc8c34
-		cache_unlock_entry( &inst->inst_cache, ec);
dc8c34
-		CACHE_RETURN( &inst->inst_cache, &ec );
dc8c34
-	}
dc8c34
-	else
dc8c34
-	{
dc8c34
-		backentry_free(&ec);
dc8c34
-		/* if ec was not in cache, cache_replace was not done.
dc8c34
-		 * i.e., e was not unlocked. */
dc8c34
-		if (e) {
dc8c34
+	if(inst){
dc8c34
+		if (cache_is_in_cache( &inst->inst_cache, ec))
dc8c34
+		{
dc8c34
+			cache_unlock_entry( &inst->inst_cache, ec);
dc8c34
+		} else if (e) {
dc8c34
+			/* if ec was not in cache, cache_replace was not done.
dc8c34
+			 * i.e., e was not unlocked. */
dc8c34
 			cache_unlock_entry( &inst->inst_cache, e);
dc8c34
 			CACHE_RETURN( &inst->inst_cache, &e);
dc8c34
 		}
dc8c34
+		CACHE_RETURN(&inst->inst_cache, &ec);
dc8c34
 	}
dc8c34
 
dc8c34
 	/* result code could be used in the bepost plugin functions. */
dc8c34
@@ -894,6 +895,7 @@ common_return:
dc8c34
 	/* free our backups */
dc8c34
 	ldap_mods_free(mods_original, 1);
dc8c34
 	backentry_free(&original_entry);
dc8c34
+	backentry_free(&tmpentry);
dc8c34
 	slapi_ch_free_string(&errbuf);
dc8c34
 
dc8c34
 	return rc;
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
dc8c34
index 09d8f05..d8379ab 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
dc8c34
@@ -50,7 +50,7 @@ static void moddn_unlock_and_return_entry(backend *be,struct backentry **targete
dc8c34
 static int moddn_newrdn_mods(Slapi_PBlock *pb, const char *olddn, struct backentry *ec, Slapi_Mods *smods_wsi, int is_repl_op);
dc8c34
 static IDList *moddn_get_children(back_txn *ptxn, Slapi_PBlock *pb, backend *be, struct backentry *parententry, Slapi_DN *parentdn, struct backentry ***child_entries, struct backdn ***child_dns, int is_resurect_operation);
dc8c34
 static int moddn_rename_children(back_txn *ptxn, Slapi_PBlock *pb, backend *be, IDList *children, Slapi_DN *dn_parentdn, Slapi_DN *dn_newsuperiordn, struct backentry *child_entries[]);
dc8c34
-static int modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbminfo *li, struct backentry *e, struct backentry **ec, Slapi_Mods *smods1, Slapi_Mods *smods2, Slapi_Mods *smods3, int *e_in_cache, int *ec_in_cache);
dc8c34
+static int modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbminfo *li, struct backentry *e, struct backentry **ec, Slapi_Mods *smods1, Slapi_Mods *smods2, Slapi_Mods *smods3);
dc8c34
 static void mods_remove_nsuniqueid(Slapi_Mods *smods);
dc8c34
 
dc8c34
 #define MOD_SET_ERROR(rc, error, count)                                        \
dc8c34
@@ -67,8 +67,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
dc8c34
     struct ldbminfo  *li;
dc8c34
     struct backentry *e= NULL;
dc8c34
     struct backentry *ec= NULL;
dc8c34
-    int ec_in_cache= 0;
dc8c34
-    int e_in_cache= 0;
dc8c34
     back_txn txn;
dc8c34
     back_txnid parent_txn;
dc8c34
     int retval = -1;
dc8c34
@@ -83,8 +81,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
dc8c34
     struct backentry *parententry= NULL;
dc8c34
     struct backentry *newparententry= NULL;
dc8c34
     struct backentry *original_entry = NULL;
dc8c34
-    struct backentry *original_parent = NULL;
dc8c34
-    struct backentry *original_newparent = NULL;
dc8c34
+    struct backentry *tmpentry = NULL;
dc8c34
     modify_context parent_modify_context = {0};
dc8c34
     modify_context newparent_modify_context = {0};
dc8c34
     modify_context ruv_c = {0};
dc8c34
@@ -361,7 +358,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
dc8c34
         ldap_result_code= -1;
dc8c34
         goto error_return; /* error result sent by find_entry2modify() */
dc8c34
     }
dc8c34
-    e_in_cache = 1; /* e is in the cache and locked */
dc8c34
     if (slapi_entry_flag_is_set(e->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE) ) {
dc8c34
         if (!is_resurect_operation) {
dc8c34
             ldap_result_code = LDAP_UNWILLING_TO_PERFORM;
dc8c34
@@ -600,8 +596,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
dc8c34
     }
dc8c34
 
dc8c34
     /* create it in the cache - prevents others from creating it */
dc8c34
-    if (( cache_add_tentative( &inst->inst_cache, ec, NULL ) != 0 ) ) {
dc8c34
-        ec_in_cache = 0; /* not in cache */
dc8c34
+    if (( cache_add_tentative( &inst->inst_cache, ec, NULL ) < 0 ) ) {
dc8c34
         /* allow modrdn even if the src dn and dest dn are identical */
dc8c34
         if ( 0 != slapi_sdn_compare((const Slapi_DN *)&dn_newdn,
dc8c34
                                     (const Slapi_DN *)sdn) ) {
dc8c34
@@ -616,46 +611,42 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
dc8c34
         }
dc8c34
         /* so if the old dn is the same as the new dn, the entry will not be cached
dc8c34
            until it is replaced with cache_replace */
dc8c34
-    } else {
dc8c34
-        ec_in_cache = 1;
dc8c34
     }
dc8c34
 
dc8c34
     /* Build the list of modifications required to the existing entry */
dc8c34
+    slapi_mods_init(&smods_generated,4);
dc8c34
+    slapi_mods_init(&smods_generated_wsi,4);
dc8c34
+    ldap_result_code = moddn_newrdn_mods(pb, slapi_sdn_get_ndn(sdn),
dc8c34
+            ec, &smods_generated_wsi, is_replicated_operation);
dc8c34
+    if (ldap_result_code != LDAP_SUCCESS) {
dc8c34
+        if (ldap_result_code == LDAP_UNWILLING_TO_PERFORM)
dc8c34
+            ldap_result_message = "Modification of old rdn attribute type not allowed.";
dc8c34
+        goto error_return;
dc8c34
+    }
dc8c34
+	if (!entryrdn_get_switch()) /* subtree-rename: off */
dc8c34
     {
dc8c34
-        slapi_mods_init(&smods_generated,4);
dc8c34
-        slapi_mods_init(&smods_generated_wsi,4);
dc8c34
-        ldap_result_code = moddn_newrdn_mods(pb, slapi_sdn_get_ndn(sdn),
dc8c34
-                            ec, &smods_generated_wsi, is_replicated_operation);
dc8c34
-        if (ldap_result_code != LDAP_SUCCESS) {
dc8c34
-            if (ldap_result_code == LDAP_UNWILLING_TO_PERFORM)
dc8c34
-                ldap_result_message = "Modification of old rdn attribute type not allowed.";
dc8c34
-            goto error_return;
dc8c34
-        }
dc8c34
-        if (!entryrdn_get_switch()) /* subtree-rename: off */
dc8c34
-        {
dc8c34
-            /*
dc8c34
-            * Remove the old entrydn index entry, and add the new one.
dc8c34
-            */
dc8c34
-            slapi_mods_add( &smods_generated, LDAP_MOD_DELETE, LDBM_ENTRYDN_STR,
dc8c34
-                        strlen(backentry_get_ndn(e)), backentry_get_ndn(e));
dc8c34
-            slapi_mods_add( &smods_generated, LDAP_MOD_REPLACE, LDBM_ENTRYDN_STR,
dc8c34
-                        strlen(backentry_get_ndn(ec)), backentry_get_ndn(ec));
dc8c34
-        }
dc8c34
-
dc8c34
         /*
dc8c34
-         * Update parentid if we have a new superior.
dc8c34
+         * Remove the old entrydn index entry, and add the new one.
dc8c34
          */
dc8c34
-        if(slapi_sdn_get_dn(dn_newsuperiordn)!=NULL) {
dc8c34
-            char buf[40]; /* Enough for an ID */
dc8c34
-            
dc8c34
-            if (parententry != NULL) {
dc8c34
-                sprintf( buf, "%lu", (u_long)parententry->ep_id );
dc8c34
-                slapi_mods_add_string(&smods_generated, LDAP_MOD_DELETE, LDBM_PARENTID_STR, buf);
dc8c34
-            }
dc8c34
-            if (newparententry != NULL) {
dc8c34
-                sprintf( buf, "%lu", (u_long)newparententry->ep_id );
dc8c34
-                slapi_mods_add_string(&smods_generated, LDAP_MOD_REPLACE, LDBM_PARENTID_STR, buf);
dc8c34
-            }
dc8c34
+        slapi_mods_add( &smods_generated, LDAP_MOD_DELETE, LDBM_ENTRYDN_STR,
dc8c34
+                strlen(backentry_get_ndn(e)), backentry_get_ndn(e));
dc8c34
+        slapi_mods_add( &smods_generated, LDAP_MOD_REPLACE, LDBM_ENTRYDN_STR,
dc8c34
+                strlen(backentry_get_ndn(ec)), backentry_get_ndn(ec));
dc8c34
+    }
dc8c34
+
dc8c34
+    /*
dc8c34
+     * Update parentid if we have a new superior.
dc8c34
+     */
dc8c34
+    if(slapi_sdn_get_dn(dn_newsuperiordn)!=NULL) {
dc8c34
+        char buf[40]; /* Enough for an ID */
dc8c34
+
dc8c34
+        if (parententry != NULL) {
dc8c34
+            sprintf( buf, "%lu", (u_long)parententry->ep_id );
dc8c34
+            slapi_mods_add_string(&smods_generated, LDAP_MOD_DELETE, LDBM_PARENTID_STR, buf);
dc8c34
+        }
dc8c34
+        if (newparententry != NULL) {
dc8c34
+            sprintf( buf, "%lu", (u_long)newparententry->ep_id );
dc8c34
+            slapi_mods_add_string(&smods_generated, LDAP_MOD_REPLACE, LDBM_PARENTID_STR, buf);
dc8c34
         }
dc8c34
     }
dc8c34
 
dc8c34
@@ -873,26 +864,22 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
dc8c34
             slapi_sdn_free(&dn_newsuperiordn);
dc8c34
             slapi_pblock_set(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, orig_dn_newsuperiordn);
dc8c34
             orig_dn_newsuperiordn = slapi_sdn_dup(orig_dn_newsuperiordn);
dc8c34
-            if (ec_in_cache) {
dc8c34
-                /* New entry 'ec' is in the entry cache.
dc8c34
-                 * Remove it from the cache . */
dc8c34
+            /* must duplicate ec before returning it to cache,
dc8c34
+             * which could free the entry. */
dc8c34
+            if ( (tmpentry = backentry_dup( ec )) == NULL ) {
dc8c34
+                ldap_result_code= LDAP_OPERATIONS_ERROR;
dc8c34
+                goto error_return;
dc8c34
+            }
dc8c34
+            if (cache_is_in_cache(&inst->inst_cache, ec)) {
dc8c34
                 CACHE_REMOVE(&inst->inst_cache, ec);
dc8c34
-                CACHE_RETURN(&inst->inst_cache, &ec);
dc8c34
-#ifdef DEBUG_CACHE
dc8c34
-                PR_ASSERT(ec == NULL);
dc8c34
-#endif
dc8c34
-                ec_in_cache = 0;
dc8c34
-            } else {
dc8c34
-                backentry_free(&ec);
dc8c34
             }
dc8c34
-            /* make sure the original entry is back in the cache if it was removed */
dc8c34
-            if (!e_in_cache) {
dc8c34
-                if (CACHE_ADD(&inst->inst_cache, e, NULL)) {
dc8c34
+            CACHE_RETURN(&inst->inst_cache, &ec);
dc8c34
+            if (!cache_is_in_cache(&inst->inst_cache, e)) {
dc8c34
+                if (CACHE_ADD(&inst->inst_cache, e, NULL) < 0) {
dc8c34
                     LDAPDebug1Arg(LDAP_DEBUG_CACHE, 
dc8c34
                                   "ldbm_back_modrdn: CACHE_ADD %s to cache failed\n",
dc8c34
                                   slapi_entry_get_dn_const(e->ep_entry));
dc8c34
                 }
dc8c34
-                e_in_cache = 1;
dc8c34
             }
dc8c34
             slapi_pblock_get( pb, SLAPI_MODRDN_EXISTING_ENTRY, &ent );
dc8c34
             if (ent && (ent != original_entry->ep_entry)) {
dc8c34
@@ -900,16 +887,13 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
dc8c34
                 slapi_pblock_set( pb, SLAPI_MODRDN_EXISTING_ENTRY, NULL );
dc8c34
             }
dc8c34
             ec = original_entry;
dc8c34
-            if ( (original_entry = backentry_dup( ec )) == NULL ) {
dc8c34
-                ldap_result_code= LDAP_OPERATIONS_ERROR;
dc8c34
-                goto error_return;
dc8c34
-            }
dc8c34
+            original_entry = tmpentry;
dc8c34
+            tmpentry = NULL;
dc8c34
             slapi_pblock_set( pb, SLAPI_MODRDN_EXISTING_ENTRY, original_entry->ep_entry );
dc8c34
             free_modrdn_existing_entry = 0; /* owned by original_entry now */
dc8c34
-            if (!ec_in_cache) {
dc8c34
+            if (!cache_is_in_cache(&inst->inst_cache, ec)) {
dc8c34
                 /* Put the resetted entry 'ec' into the cache again. */
dc8c34
-                if (cache_add_tentative( &inst->inst_cache, ec, NULL ) != 0) {
dc8c34
-                    ec_in_cache = 0; /* not in cache */
dc8c34
+                if (cache_add_tentative( &inst->inst_cache, ec, NULL ) < 0) {
dc8c34
                     /* allow modrdn even if the src dn and dest dn are identical */
dc8c34
                     if ( 0 != slapi_sdn_compare((const Slapi_DN *)&dn_newdn,
dc8c34
                                                 (const Slapi_DN *)sdn) ) {
dc8c34
@@ -921,8 +905,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
dc8c34
                     }
dc8c34
                     /* so if the old dn is the same as the new dn, the entry will not be cached
dc8c34
                        until it is replaced with cache_replace */
dc8c34
-                } else {
dc8c34
-                    ec_in_cache = 1;
dc8c34
                 }
dc8c34
             }
dc8c34
 
dc8c34
@@ -979,7 +961,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
dc8c34
         /*
dc8c34
          * Update the indexes for the entry.
dc8c34
          */
dc8c34
-        retval = modrdn_rename_entry_update_indexes(&txn, pb, li, e, &ec, &smods_generated, &smods_generated_wsi, &smods_operation_wsi, &e_in_cache, &ec_in_cache);
dc8c34
+        retval = modrdn_rename_entry_update_indexes(&txn, pb, li, e, &ec, &smods_generated, &smods_generated_wsi, &smods_operation_wsi);
dc8c34
         if (DB_LOCK_DEADLOCK == retval)
dc8c34
         {
dc8c34
             /* Retry txn */
dc8c34
@@ -1412,16 +1394,13 @@ common_return:
dc8c34
         }
dc8c34
         /* remove the new entry from the cache if the op failed -
dc8c34
            otherwise, leave it in */
dc8c34
-        if (ec_in_cache && ec && retval) {
dc8c34
-            CACHE_REMOVE( &inst->inst_cache, ec );
dc8c34
-        }
dc8c34
-        if (ec_in_cache) {
dc8c34
+        if (inst && ec){
dc8c34
+            if (retval && cache_is_in_cache(&inst->inst_cache, ec)) {
dc8c34
+                CACHE_REMOVE( &inst->inst_cache, ec );
dc8c34
+            }
dc8c34
             CACHE_RETURN( &inst->inst_cache, &ec );
dc8c34
-        } else {
dc8c34
-            backentry_free( &ec );
dc8c34
         }
dc8c34
         ec = NULL;
dc8c34
-        ec_in_cache = 0;
dc8c34
     }
dc8c34
 
dc8c34
     /* put e back in the cache if the modrdn failed */
dc8c34
@@ -1468,8 +1447,7 @@ common_return:
dc8c34
     slapi_ch_free_string(&original_newrdn);
dc8c34
     slapi_sdn_free(&orig_dn_newsuperiordn);
dc8c34
     backentry_free(&original_entry);
dc8c34
-    backentry_free(&original_parent);
dc8c34
-    backentry_free(&original_newparent);
dc8c34
+    backentry_free(&tmpentry);
dc8c34
     slapi_entry_free(original_targetentry);
dc8c34
 
dc8c34
     if(dblock_acquired)
dc8c34
@@ -1743,7 +1721,9 @@ mods_remove_nsuniqueid(Slapi_Mods *smods)
dc8c34
  * mods contains the list of attribute change made.
dc8c34
  */
dc8c34
 static int
dc8c34
-modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbminfo *li, struct backentry *e, struct backentry **ec, Slapi_Mods *smods1, Slapi_Mods *smods2, Slapi_Mods *smods3, int *e_in_cache, int *ec_in_cache)
dc8c34
+modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbminfo *li,
dc8c34
+		                           struct backentry *e, struct backentry **ec,
dc8c34
+		                           Slapi_Mods *smods1, Slapi_Mods *smods2, Slapi_Mods *smods3)
dc8c34
 {
dc8c34
     backend *be;
dc8c34
     ldbm_instance *inst;
dc8c34
@@ -1751,7 +1731,6 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbm
dc8c34
     char *msg;
dc8c34
     Slapi_Operation *operation;
dc8c34
     int is_ruv = 0;                 /* True if the current entry is RUV */
dc8c34
-    int orig_ec_in_cache = 0;
dc8c34
     int cache_rc = 0;
dc8c34
 
dc8c34
     slapi_pblock_get( pb, SLAPI_BACKEND, &be );
dc8c34
@@ -1759,7 +1738,6 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbm
dc8c34
     is_ruv = operation_is_flag_set(operation, OP_FLAG_REPL_RUV);
dc8c34
     inst = (ldbm_instance *) be->be_instance_info;
dc8c34
 
dc8c34
-    orig_ec_in_cache = *ec_in_cache;
dc8c34
     /*
dc8c34
      * Update the ID to Entry index. 
dc8c34
      * Note that id2entry_add replaces the entry, so the Entry ID stays the same.
dc8c34
@@ -1781,7 +1759,6 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbm
dc8c34
         LDAPDebug( LDAP_DEBUG_ANY, "modrdn_rename_entry_update_indexes: id2entry_add failed, err=%d %s\n", retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
dc8c34
         goto error_return;
dc8c34
     }
dc8c34
-    *ec_in_cache = 1; /* id2entry_add adds to cache if not already in */
dc8c34
     if(smods1!=NULL && slapi_mods_get_num_mods(smods1)>0)
dc8c34
     {
dc8c34
         /*
dc8c34
@@ -1869,12 +1846,7 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbm
dc8c34
         retval= -1;
dc8c34
         goto error_return;
dc8c34
     }
dc8c34
-    if (orig_ec_in_cache) {
dc8c34
-        /* ec was already added to the cache via cache_add_tentative (to reserve its spot in the cache)
dc8c34
-           and/or id2entry_add - so it already had one refcount - cache_replace adds another refcount -
dc8c34
-           drop the extra ref added by cache_replace */
dc8c34
-        CACHE_RETURN( &inst->inst_cache, ec );
dc8c34
-    }
dc8c34
+
dc8c34
 error_return:
dc8c34
     return retval;
dc8c34
 }
dc8c34
@@ -1909,8 +1881,6 @@ moddn_rename_child_entry(
dc8c34
     int olddncomps= 0;
dc8c34
     int need= 1; /* For the '\0' */
dc8c34
     int i;
dc8c34
-    int e_in_cache = 1;
dc8c34
-    int ec_in_cache = 0;
dc8c34
 
dc8c34
     olddn = slapi_entry_get_dn((*ec)->ep_entry);
dc8c34
     if (NULL == olddn) {
dc8c34
@@ -1973,8 +1943,7 @@ moddn_rename_child_entry(
dc8c34
          * Update all the indexes.
dc8c34
          */
dc8c34
         retval = modrdn_rename_entry_update_indexes(ptxn, pb, li, e, ec,
dc8c34
-                                                    smodsp, NULL, NULL,
dc8c34
-                                                    &e_in_cache, &ec_in_cache);
dc8c34
+                                                    smodsp, NULL, NULL);
dc8c34
         /* JCMREPL - Should the children get updated modifiersname and lastmodifiedtime? */
dc8c34
         slapi_mods_done(&smods);
dc8c34
     }
dc8c34
diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
dc8c34
index 65cafea..688f293 100644
dc8c34
--- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
dc8c34
+++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
dc8c34
@@ -87,6 +87,8 @@ int cache_add_tentative(struct cache *cache, struct backentry *e,
dc8c34
 int cache_lock_entry(struct cache *cache, struct backentry *e);
dc8c34
 void cache_unlock_entry(struct cache *cache, struct backentry *e);
dc8c34
 int cache_replace(struct cache *cache, void *oldptr, void *newptr);
dc8c34
+int cache_has_otherref(struct cache *cache, void *ptr);
dc8c34
+int cache_is_in_cache(struct cache *cache, void *ptr);
dc8c34
 
dc8c34
 Hashtable *new_hash(u_long size, u_long offset, HashFn hfn,
dc8c34
                HashTestFn tfn);
dc8c34
-- 
dc8c34
1.9.3
dc8c34