ldap/servers/plugins/replication/cl5_api.c | 31 +-
ldap/servers/plugins/replication/urp.c | 3
ldap/servers/plugins/replication/urp.h | 2
ldap/servers/plugins/replication/urp_glue.c | 2
ldap/servers/plugins/replication/urp_tombstone.c | 59 ++--
ldap/servers/slapd/add.c | 2
ldap/servers/slapd/back-ldbm/back-ldbm.h | 3
ldap/servers/slapd/back-ldbm/cache.c | 316 +++++++++++++++--------
ldap/servers/slapd/back-ldbm/ldbm_add.c | 110 ++++----
ldap/servers/slapd/back-ldbm/ldbm_delete.c | 202 ++++++++------
ldap/servers/slapd/back-ldbm/ldbm_modify.c | 90 +++---
ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 191 ++++++-------
ldap/servers/slapd/back-ldbm/parents.c | 4
ldap/servers/slapd/back-ldbm/proto-back-ldbm.h | 6
ldap/servers/slapd/bind.c | 13
ldap/servers/slapd/dn.c | 6
ldap/servers/slapd/rdn.c | 22 +
ldap/servers/slapd/slapi-plugin.h | 4
18 files changed, 636 insertions(+), 430 deletions(-)
New commits:
commit 154abc975af643ebecc70750eddf5921e2befc12
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Mon Sep 22 14:34:58 2014 -0700
Ticket #47750 - Creating a glue fails if one above level is a conflict or missing
Description: Poring changes made to 1.2.11 branch to newer versions.
1) Enabiling cache lock in cache_is_in_cache and cache_has_otherref.
2) Removing unused field new_entry_in_cache from "struct _modify_context".
(cherry picked from commit 5ae13072330e9a769a5949b2e8a91085b38ac4e1)
(cherry picked from commit ef766784ed7d09aa81e82316b621e8490a368dc6)
(cherry picked from commit 6ca4422d1a585c30b92045cff4d38f1c7edf72c7)
diff --git a/ldap/servers/slapd/back-ldbm/back-ldbm.h
b/ldap/servers/slapd/back-ldbm/back-ldbm.h
index 7213a9e..a74a9db 100644
--- a/ldap/servers/slapd/back-ldbm/back-ldbm.h
+++ b/ldap/servers/slapd/back-ldbm/back-ldbm.h
@@ -694,7 +694,6 @@ typedef struct _import_subcount_stuff import_subcount_stuff;
/* Handy structures for modify operations */
struct _modify_context {
- int new_entry_in_cache;
struct backentry *old_entry;
struct backentry *new_entry;
Slapi_Mods *smods;
diff --git a/ldap/servers/slapd/back-ldbm/cache.c b/ldap/servers/slapd/back-ldbm/cache.c
index a98cf0c..4746204 100644
--- a/ldap/servers/slapd/back-ldbm/cache.c
+++ b/ldap/servers/slapd/back-ldbm/cache.c
@@ -1506,10 +1506,12 @@ int cache_add_tentative(struct cache *cache, struct backentry *e,
{
return entrycache_add_int(cache, e, ENTRY_STATE_CREATING, alt);
}
+
void cache_lock(struct cache *cache)
{
PR_EnterMonitor(cache->c_mutex);
}
+
void cache_unlock(struct cache *cache)
{
PR_ExitMonitor(cache->c_mutex);
@@ -2095,9 +2097,9 @@ cache_has_otherref(struct cache *cache, void *ptr)
return hasref;
}
bep = (struct backcommon *)ptr;
- /* slows down too much? PR_Lock(cache->c_mutex); */
+ cache_lock(cache);
hasref = bep->ep_refcnt;
- /* PR_Unlock(cache->c_mutex); */
+ cache_unlock(cache);
return (hasref>1)?1:0;
}
@@ -2111,8 +2113,8 @@ cache_is_in_cache(struct cache *cache, void *ptr)
return in_cache;
}
bep = (struct backcommon *)ptr;
- /* slows down too much? PR_Lock(cache->c_mutex); */
+ cache_lock(cache);
in_cache = (bep->ep_state &
(ENTRY_STATE_DELETED|ENTRY_STATE_NOTINCACHE))?0:1;
- /* PR_Unlock(cache->c_mutex); */
+ cache_unlock(cache);
return in_cache;
}
commit 44b66b4ceabc78c21ba48a7fe153915663dbc749
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Tue Sep 9 12:45:58 2014 -0700
Ticket #47748 - Simultaneous adding a user and binding as the user could fail in the
password policy check
Description: commit 4fc53e1a63222d0ff67c30a59f2cff4b535f90a8 fix for
Ticket #47748 introduced a bug: "Simple bind hangs after enabling
password policy".
In do_bind, slapi_check_account_lock and need_new_pw overwrote the
return code from backend bind which is used later. This patch fixes
it not to override the return code.
https://fedorahosted.org/389/ticket/47748
Reviewed by mreynolds(a)redhat.com (Thank you, Mark!!)
(cherry picked from commit 4f11606b02419c8ccdb319b8040e683af9109d1b)
(cherry picked from commit 8c82941c0f2b0b5d7fa698a1ca3e4f26245cf85a)
(cherry picked from commit 5b6d60ec4d3d93d1d69f6a071ce135a06f4c8cfd)
diff --git a/ldap/servers/slapd/bind.c b/ldap/servers/slapd/bind.c
index 58a4e13..bc4aa24 100644
--- a/ldap/servers/slapd/bind.c
+++ b/ldap/servers/slapd/bind.c
@@ -769,6 +769,7 @@ do_bind( Slapi_PBlock *pb )
}
if ( rc == SLAPI_BIND_SUCCESS ) {
+ int myrc = 0;
if (!auto_bind) {
/*
* There could be a race that bind_target_entry was not added
@@ -779,9 +780,9 @@ do_bind( Slapi_PBlock *pb )
if (!bind_target_entry) {
bind_target_entry = get_entry(pb, slapi_sdn_get_ndn(sdn));
if (bind_target_entry) {
- rc = slapi_check_account_lock(pb, bind_target_entry,
+ myrc = slapi_check_account_lock(pb, bind_target_entry,
pw_response_requested, 1,
1);
- if (1 == rc) { /* account is locked */
+ if (1 == myrc) { /* account is locked */
goto account_locked;
}
} else {
@@ -795,8 +796,8 @@ do_bind( Slapi_PBlock *pb )
if (!slapi_be_is_flag_set(be, SLAPI_BE_FLAG_REMOTE_DATA)) {
/* check if need new password before sending
the bind success result */
- rc = need_new_pw(pb, &t, bind_target_entry,
pw_response_requested);
- switch (rc) {
+ myrc = need_new_pw(pb, &t, bind_target_entry,
pw_response_requested);
+ switch (myrc) {
case 1:
(void)slapi_add_pwd_control(pb, LDAP_CONTROL_PWEXPIRED,
0);
break;
@@ -811,8 +812,8 @@ do_bind( Slapi_PBlock *pb )
if (auth_response_requested) {
slapi_add_auth_response_control(pb, slapi_sdn_get_ndn(sdn));
}
- if (-1 == rc) {
- /* neeed_new_pw failed; need_new_pw already send_ldap_result in
it. */
+ if (-1 == myrc) {
+ /* need_new_pw failed; need_new_pw already send_ldap_result in
it. */
goto free_and_return;
}
} else { /* anonymous */
commit 891d03a3d36fc46d3851eeaf2582bd3575fd5823
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Tue Aug 19 14:42:52 2014 -0700
Ticket #47834 - Tombstone_to_glue: if parents are also converted to glue, the target
entry's DN must be adjusted.
Bug Description: Test case to verify the problem crashed the server.
Fix Description:
1. Clean up entry cache related code
1-1. Changing cache log reentrant to avoid self deadlock.
1-2. Introducing cache_is_in_cache to get rid of local variables in
ldap_back_{add,delete,modify,modrdn}.
2. ldap_back_{add,delete,modify,modrdn}
2-1. As described in 1-2, removed [a-z]*_in_cache local variables.
2-2. In the deadlock retry loop, entries were duplicated by backentry_
dup after CACHE_REMOVE'd and CACHE_RETURN'ed. At the moment, the
entry could be already freed. Changed to create a duplicated
entry before calling CACHE_REMOVE and CACHE_RETURN.
3. _cl5NewDBFile (replication/cl5_api.c): When a leftover semaphore is
found, _cl5NewDBFile removes it and creates it, but it rarely fails
to delete and it causes the server restart fail. Adding a message
to remove such a leftover semaphore by ipcrm.
https://fedorahosted.org/389/ticket/47834
Reviewed by mreynolds(a)redhat.com (Thank you, Mark!!)
(cherry picked from commit 6333936da2c4287e96b36fecc24a4c62da5a8ea2)
(cherry picked from commit d9c8b1fe47e8ce708fa3cbeddbefa1916f1bf669)
diff --git a/ldap/servers/plugins/replication/cl5_api.c
b/ldap/servers/plugins/replication/cl5_api.c
index abcc39a..4ab0eb0 100644
--- a/ldap/servers/plugins/replication/cl5_api.c
+++ b/ldap/servers/plugins/replication/cl5_api.c
@@ -5697,7 +5697,7 @@ static int _cl5DBOpenFileByReplicaName (const char *replName, const
char *replGe
if (checkDups)
{
PR_Lock (s_cl5Desc.fileLock);
- file_name = _cl5MakeFileName (replName, replGen);
+ file_name = _cl5MakeFileName (replName, replGen);
tmpObj = objset_find (s_cl5Desc.dbFiles, _cl5CompareDBFile, file_name);
slapi_ch_free((void **)&file_name);
if (tmpObj) /* this file already exist */
@@ -5772,10 +5772,10 @@ done:;
if (checkDups)
{
- PR_Unlock (s_cl5Desc.fileLock);
- }
+ PR_Unlock (s_cl5Desc.fileLock);
+ }
- return rc;
+ return rc;
}
/* adds file to the db file list */
@@ -5939,7 +5939,14 @@ out:
* and re-create it.
*/
if (PR_GetError() == PR_FILE_EXISTS_ERROR) {
+ PRErrorCode prerr;
PR_DeleteSemaphore((*dbFile)->semaName);
+ prerr = PR_GetError();
+ if (PR_SUCCESS != prerr) {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl,
+ "_cl5NewDBFile: PR_DeleteSemaphore: %s; NSPR error -
%d\n",
+ (*dbFile)->semaName ? (*dbFile)->semaName : "(nil)",
prerr);
+ }
(*dbFile)->sema = PR_OpenSemaphore((*dbFile)->semaName,
PR_SEM_CREATE | PR_SEM_EXCL, 0666,
s_cl5Desc.dbConfig.maxConcurrentWrites );
@@ -5949,9 +5956,19 @@ out:
* we should just error out. */
if ((*dbFile)->sema == NULL )
{
- slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl,
- "_cl5NewDBFile: failed to create semaphore %s; NSPR error - %d\n",
- (*dbFile)->semaName ? (*dbFile)->semaName : "(nil)", PR_GetError());
+ PRErrorCode prerr = PR_GetError();
+ if (PR_FILE_EXISTS_ERROR == prerr) {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl,
+ "_cl5NewDBFile: PR_OpenSemaphore: %s; sema: 0x%p, NSPR error -
%d\n",
+ (*dbFile)->semaName ? (*dbFile)->semaName : "(nil)",
(*dbFile)->sema, prerr);
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl,
+ " : Leftover semaphores may exist. "
+ "Run \"ipcs -s\", and remove them with \"ipcrm -s
<SEMID>\" if any\n");
+ } else {
+ slapi_log_error(SLAPI_LOG_FATAL, repl_plugin_name_cl,
+ "_cl5NewDBFile: failed to create semaphore %s; NSPR error -
%d\n",
+ (*dbFile)->semaName ? (*dbFile)->semaName : "(nil)",
prerr);
+ }
rc = CL5_SYSTEM_ERROR;
goto done;
}
diff --git a/ldap/servers/slapd/back-ldbm/back-ldbm.h
b/ldap/servers/slapd/back-ldbm/back-ldbm.h
index 8aa9825..7213a9e 100644
--- a/ldap/servers/slapd/back-ldbm/back-ldbm.h
+++ b/ldap/servers/slapd/back-ldbm/back-ldbm.h
@@ -403,7 +403,7 @@ struct cache {
Slapi_Counter *c_tries;
struct backcommon *c_lruhead; /* add entries here */
struct backcommon *c_lrutail; /* remove entries here */
- PRLock *c_mutex; /* lock for cache operations */
+ PRMonitor *c_mutex; /* lock for cache operations */
PRLock *c_emutexalloc_mutex;
};
diff --git a/ldap/servers/slapd/back-ldbm/cache.c b/ldap/servers/slapd/back-ldbm/cache.c
index 0732415..a98cf0c 100644
--- a/ldap/servers/slapd/back-ldbm/cache.c
+++ b/ldap/servers/slapd/back-ldbm/cache.c
@@ -544,10 +544,9 @@ int cache_init(struct cache *cache, size_t maxsize, long maxentries,
int type)
cache->c_lruhead = cache->c_lrutail = NULL;
cache_make_hashes(cache, type);
- if (((cache->c_mutex = PR_NewLock()) == NULL) ||
- ((cache->c_emutexalloc_mutex = PR_NewLock()) == NULL)) {
- LDAPDebug(LDAP_DEBUG_ANY, "ldbm: cache_init: PR_NewLock failed\n",
- 0, 0, 0);
+ if (((cache->c_mutex = PR_NewMonitor()) == NULL) ||
+ ((cache->c_emutexalloc_mutex = PR_NewLock()) == NULL)) {
+ LDAPDebug0Args(LDAP_DEBUG_ANY, "ldbm: cache_init: PR_NewMonitor
failed\n");
return 0;
}
LDAPDebug(LDAP_DEBUG_TRACE, "<= cache_init\n", 0, 0, 0);
@@ -634,13 +633,13 @@ static void entrycache_clear_int(struct cache *cache)
void cache_clear(struct cache *cache, int type)
{
- PR_Lock(cache->c_mutex);
+ cache_lock(cache);
if (CACHE_TYPE_ENTRY == type) {
entrycache_clear_int(cache);
} else if (CACHE_TYPE_DN == type) {
dncache_clear_int(cache);
}
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
}
static void erase_cache(struct cache *cache, int type)
@@ -664,7 +663,7 @@ void cache_destroy_please(struct cache *cache, int type)
slapi_counter_destroy(&cache->c_cursize);
slapi_counter_destroy(&cache->c_hits);
slapi_counter_destroy(&cache->c_tries);
- PR_DestroyLock(cache->c_mutex);
+ PR_DestroyMonitor(cache->c_mutex);
PR_DestroyLock(cache->c_emutexalloc_mutex);
}
@@ -688,7 +687,7 @@ static void entrycache_set_max_size(struct cache *cache, size_t
bytes)
"WARNING -- Minimum cache size is %lu -- rounding up\n",
MINCACHESIZE, 0, 0);
}
- PR_Lock(cache->c_mutex);
+ cache_lock(cache);
cache->c_maxsize = bytes;
LOG("entry cache size set to %lu\n", bytes, 0, 0);
/* check for full cache, and clear out if necessary */
@@ -707,7 +706,7 @@ static void entrycache_set_max_size(struct cache *cache, size_t
bytes)
erase_cache(cache, CACHE_TYPE_ENTRY);
cache_make_hashes(cache, CACHE_TYPE_ENTRY);
}
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
if (! dblayer_is_cachesize_sane(&bytes)) {
LDAPDebug(LDAP_DEBUG_ANY,
"WARNING -- Possible CONFIGURATION ERROR -- cachesize "
@@ -725,7 +724,7 @@ void cache_set_max_entries(struct cache *cache, long entries)
* was given in # entries instead of memory footprint. hopefully,
* we can eventually drop this.
*/
- PR_Lock(cache->c_mutex);
+ cache_lock(cache);
cache->c_maxentries = entries;
if (entries >= 0) {
LOG("entry cache entry-limit set to %lu\n", entries, 0, 0);
@@ -736,7 +735,7 @@ void cache_set_max_entries(struct cache *cache, long entries)
/* check for full cache, and clear out if necessary */
if (CACHE_FULL(cache))
eflush = entrycache_flush(cache);
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
while (eflush)
{
eflushtemp = BACK_LRU_NEXT(eflush, struct backentry *);
@@ -749,9 +748,9 @@ size_t cache_get_max_size(struct cache *cache)
{
size_t n = 0;
- PR_Lock(cache->c_mutex);
+ cache_lock(cache);
n = cache->c_maxsize;
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
return n;
}
@@ -759,9 +758,9 @@ long cache_get_max_entries(struct cache *cache)
{
long n;
- PR_Lock(cache->c_mutex);
+ cache_lock(cache);
n = cache->c_maxentries;
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
return n;
}
@@ -787,14 +786,14 @@ void cache_get_stats(struct cache *cache, PRUint64 *hits, PRUint64
*tries,
long *nentries, long *maxentries,
size_t *size, size_t *maxsize)
{
- PR_Lock(cache->c_mutex);
+ cache_lock(cache);
if (hits) *hits = slapi_counter_get_value(cache->c_hits);
if (tries) *tries = slapi_counter_get_value(cache->c_tries);
if (nentries) *nentries = cache->c_curentries;
if (maxentries) *maxentries = cache->c_maxentries;
if (size) *size = slapi_counter_get_value(cache->c_cursize);
if (maxsize) *maxsize = cache->c_maxsize;
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
}
void cache_debug_hash(struct cache *cache, char **out)
@@ -805,7 +804,7 @@ void cache_debug_hash(struct cache *cache, char **out)
Hashtable *ht = NULL;
char *name = "unknown";
- PR_Lock(cache->c_mutex);
+ cache_lock(cache);
*out = (char *)slapi_ch_malloc(1024);
**out = 0;
@@ -841,7 +840,7 @@ void cache_debug_hash(struct cache *cache, char **out)
sprintf(*out + strlen(*out), "%d[%d] ", j, slot_stats[j]);
slapi_ch_free((void **)&slot_stats);
}
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
}
@@ -947,14 +946,14 @@ int cache_remove(struct cache *cache, void *ptr)
}
e = (struct backcommon *)ptr;
- PR_Lock(cache->c_mutex);
+ cache_lock(cache);
if (CACHE_TYPE_ENTRY == e->ep_type) {
ASSERT(e->ep_refcnt > 0);
ret = entrycache_remove_int(cache, (struct backentry *)e);
} else if (CACHE_TYPE_DN == e->ep_type) {
ret = dncache_remove_int(cache, (struct backdn *)e);
}
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
return ret;
}
@@ -1014,7 +1013,7 @@ static int entrycache_replace(struct cache *cache, struct backentry
*olde,
#endif
newndn = slapi_sdn_get_ndn(backentry_get_sdn(newe));
entry_size = cache_entry_size(newe);
- PR_Lock(cache->c_mutex);
+ cache_lock(cache);
/*
* First, remove the old entry from all the hashtables.
@@ -1034,7 +1033,7 @@ static int entrycache_replace(struct cache *cache, struct backentry
*olde,
}
/* If fails, we have to make sure the both entires are removed from the cache,
* otherwise, we have no idea what's left in the cache or not... */
- if (!entry_same_dn(newe, (void *)oldndn) && (newe->ep_state &
ENTRY_STATE_NOTINCACHE) == 0) {
+ if (cache_is_in_cache(cache, newe)) {
/* if we're doing a modrdn or turning an entry to a tombstone,
* the new entry can be in the dn table already, so we need to remove that too.
*/
@@ -1042,6 +1041,7 @@ static int entrycache_replace(struct cache *cache, struct backentry
*olde,
{
slapi_counter_subtract(cache->c_cursize, newe->ep_size);
cache->c_curentries--;
+ newe->ep_refcnt--;
LOG("entry cache replace remove entry size %lu\n",
newe->ep_size, 0, 0);
}
}
@@ -1064,7 +1064,7 @@ static int entrycache_replace(struct cache *cache, struct backentry
*olde,
LOG("entry cache replace (%s): cache index tables out of sync - found dn
[%d] id [%d]\n",
oldndn, found_in_dn, found_in_id);
#endif
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
return 1;
}
}
@@ -1073,32 +1073,32 @@ static int entrycache_replace(struct cache *cache, struct
backentry *olde,
* tested enough that we believe it works.)
*/
if (!add_hash(cache->c_dntable, (void *)newndn, strlen(newndn), newe, (void
**)&alte)) {
- LOG("entry cache replace (%s): can't add to dn table (returned
%s)\n",
- newndn, alte?slapi_entry_get_dn(alte->ep_entry):"none", 0);
- PR_Unlock(cache->c_mutex);
- return 1;
+ LOG("entry cache replace (%s): can't add to dn table (returned
%s)\n",
+ newndn, alte?slapi_entry_get_dn(alte->ep_entry):"none", 0);
+ cache_lock(cache);
+ return 1;
}
if (!add_hash(cache->c_idtable, &(newe->ep_id), sizeof(ID), newe, (void
**)&alte)) {
- LOG("entry cache replace (%s): can't add to id table (returned
%s)\n",
- newndn, alte?slapi_entry_get_dn(alte->ep_entry):"none", 0);
- if(remove_hash(cache->c_dntable, (void *)newndn, strlen(newndn)) == 0){
- LOG("entry cache replace: failed to remove dn table\n", 0, 0, 0);
- }
- PR_Unlock(cache->c_mutex);
- return 1;
+ LOG("entry cache replace (%s): can't add to id table (returned
%s)\n",
+ newndn, alte?slapi_entry_get_dn(alte->ep_entry):"none", 0);
+ if(remove_hash(cache->c_dntable, (void *)newndn, strlen(newndn)) == 0){
+ LOG("entry cache replace: failed to remove dn table\n", 0, 0, 0);
+ }
+ cache_unlock(cache);
+ return 1;
}
#ifdef UUIDCACHE_ON
if (newuuid && !add_hash(cache->c_uuidtable, (void *)newuuid,
strlen(newuuid),
newe, NULL)) {
- LOG("entry cache replace: can't add uuid\n", 0, 0, 0);
- if(remove_hash(cache->c_dntable, (void *)newndn, strlen(newndn)) == 0){
- LOG("entry cache replace: failed to remove dn table(uuid cache)\n",
0, 0, 0);
- }
- if(remove_hash(cache->c_idtable, &(newe->ep_id), sizeof(ID)) == 0){
- LOG("entry cache replace: failed to remove id table(uuid cache)\n",
0, 0, 0);
- }
- PR_Unlock(cache->c_mutex);
- return 1;
+ LOG("entry cache replace: can't add uuid\n", 0, 0, 0);
+ if(remove_hash(cache->c_dntable, (void *)newndn, strlen(newndn)) == 0){
+ LOG("entry cache replace: failed to remove dn table(uuid cache)\n",
0, 0, 0);
+ }
+ if(remove_hash(cache->c_idtable, &(newe->ep_id), sizeof(ID)) == 0){
+ LOG("entry cache replace: failed to remove id table(uuid cache)\n",
0, 0, 0);
+ }
+ cache_unlock(cache);
+ return 1;
}
#endif
/* adjust cache meta info */
@@ -1110,7 +1110,7 @@ static int entrycache_replace(struct cache *cache, struct backentry
*olde,
slapi_counter_subtract(cache->c_cursize, olde->ep_size -
newe->ep_size);
}
newe->ep_state = 0;
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
LOG("<= entrycache_replace OK, cache size now %lu cache count now
%ld\n",
slapi_counter_get_value(cache->c_cursize), cache->c_curentries, 0);
return 0;
@@ -1144,10 +1144,14 @@ entrycache_return(struct cache *cache, struct backentry **bep)
struct backentry *e;
e = *bep;
+ if (!e) {
+ LDAPDebug0Args(LDAP_DEBUG_ANY, "entrycache_return e is NULL\n");
+ return;
+ }
LOG("=> entrycache_return (%s) entry count: %d, entry in cache:%ld\n",
backentry_get_ndn(e), e->ep_refcnt, cache->c_curentries);
- PR_Lock(cache->c_mutex);
+ cache_lock(cache);
if (e->ep_state & ENTRY_STATE_NOTINCACHE)
{
backentry_free(bep);
@@ -1166,7 +1170,7 @@ entrycache_return(struct cache *cache, struct backentry **bep)
}
}
}
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
while (eflush)
{
eflushtemp = BACK_LRU_NEXT(eflush, struct backentry *);
@@ -1185,22 +1189,22 @@ struct backentry *cache_find_dn(struct cache *cache, const char
*dn, unsigned lo
LOG("=> cache_find_dn (%s)\n", dn, 0, 0);
/*entry normalized by caller (dn2entry.c) */
- PR_Lock(cache->c_mutex);
+ cache_lock(cache);
if (find_hash(cache->c_dntable, (void *)dn, ndnlen, (void **)&e)) {
/* need to check entry state */
if (e->ep_state != 0) {
/* entry is deleted or not fully created yet */
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
LOG("<= cache_find_dn (NOT FOUND)\n", 0, 0, 0);
return NULL;
}
if (e->ep_refcnt == 0)
lru_delete(cache, (void *)e);
e->ep_refcnt++;
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
slapi_counter_increment(cache->c_hits);
} else {
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
}
slapi_counter_increment(cache->c_tries);
@@ -1216,22 +1220,22 @@ struct backentry *cache_find_id(struct cache *cache, ID id)
LOG("=> cache_find_id (%lu)\n", (u_long)id, 0, 0);
- PR_Lock(cache->c_mutex);
+ cache_lock(cache);
if (find_hash(cache->c_idtable, &id, sizeof(ID), (void **)&e)) {
/* need to check entry state */
if (e->ep_state != 0) {
/* entry is deleted or not fully created yet */
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
LOG("<= cache_find_id (NOT FOUND)\n", 0, 0, 0);
return NULL;
}
if (e->ep_refcnt == 0)
lru_delete(cache, (void *)e);
e->ep_refcnt++;
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
slapi_counter_increment(cache->c_hits);
} else {
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
}
slapi_counter_increment(cache->c_tries);
@@ -1247,22 +1251,22 @@ struct backentry *cache_find_uuid(struct cache *cache, const char
*uuid)
LOG("=> cache_find_uuid (%s)\n", uuid, 0, 0);
- PR_Lock(cache->c_mutex);
+ cache_lock(cache);
if (find_hash(cache->c_uuidtable, uuid, strlen(uuid), (void **)&e)) {
/* need to check entry state */
if (e->ep_state != 0) {
/* entry is deleted or not fully created yet */
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
LOG("<= cache_find_uuid (NOT FOUND)\n", 0, 0, 0);
return NULL;
}
if (e->ep_refcnt == 0)
lru_delete(cache, (void *)e);
e->ep_refcnt++;
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
slapi_counter_increment(cache->c_hits);
} else {
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
}
slapi_counter_increment(cache->c_tries);
@@ -1299,7 +1303,7 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int
state,
entry_size = e->ep_size;
}
- PR_Lock(cache->c_mutex);
+ cache_lock(cache);
if (! add_hash(cache->c_dntable, (void *)ndn, strlen(ndn), e,
(void **)&my_alt)) {
LOG("entry \"%s\" already in dn cache\n", ndn, 0, 0);
@@ -1334,7 +1338,7 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int
state,
* to prevent that the caller accidentally thinks the existing
* entry is not the same one the caller has and releases it.
*/
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
return 1;
}
}
@@ -1344,7 +1348,7 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int
state,
{
LOG("the entry %s is reserved (ep_state: 0x%x, state: 0x%x)\n",
ndn, e->ep_state, state);
e->ep_state |= ENTRY_STATE_NOTINCACHE;
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
return -1;
}
else if (state != 0)
@@ -1352,7 +1356,7 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int
state,
LOG("the entry %s already exists. cannot reserve it. (ep_state:
0x%x, state: 0x%x)\n",
ndn, e->ep_state, state);
e->ep_state |= ENTRY_STATE_NOTINCACHE;
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
return -1;
}
else
@@ -1364,12 +1368,14 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int
state,
(*alt)->ep_refcnt++;
LOG("the entry %s already exists. returning existing entry %s
(state: 0x%x)\n",
ndn, backentry_get_ndn(my_alt), state);
+ cache_unlock(cache);
+ return 1;
} else {
LOG("the entry %s already exists. Not returning existing entry
%s (state: 0x%x)\n",
ndn, backentry_get_ndn(my_alt), state);
+ cache_unlock(cache);
+ return -1;
}
- PR_Unlock(cache->c_mutex);
- return 1;
}
}
}
@@ -1399,14 +1405,14 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int
state,
* fine (i think).
*/
LOG("<= entrycache_add_int (ignoring)\n", 0, 0, 0);
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
return 0;
}
if(remove_hash(cache->c_dntable, (void *)ndn, strlen(ndn)) == 0){
LOG("entrycache_add_int: failed to remove %s from dn table\n",
0, 0, 0);
}
e->ep_state |= ENTRY_STATE_NOTINCACHE;
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
LOG("entrycache_add_int: failed to add %s to cache (ep_state: %x,
already_in: %d)\n",
ndn, e->ep_state, already_in);
return -1;
@@ -1425,7 +1431,7 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int
state,
LOG("entrycache_add_int: failed to remove id table(uuid
cache)\n", 0, 0, 0);
}
e->ep_state |= ENTRY_STATE_NOTINCACHE;
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
return -1;
}
}
@@ -1450,7 +1456,7 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int
state,
if (CACHE_FULL(cache))
eflush = entrycache_flush(cache);
}
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
while (eflush)
{
@@ -1502,11 +1508,11 @@ int cache_add_tentative(struct cache *cache, struct backentry *e,
}
void cache_lock(struct cache *cache)
{
- PR_Lock(cache->c_mutex);
+ PR_EnterMonitor(cache->c_mutex);
}
void cache_unlock(struct cache *cache)
{
- PR_Unlock(cache->c_mutex);
+ PR_ExitMonitor(cache->c_mutex);
}
/* locks an entry so that it can be modified (you should have gotten the
@@ -1540,14 +1546,14 @@ int cache_lock_entry(struct cache *cache, struct backentry *e)
PR_EnterMonitor(e->ep_mutexp);
/* make sure entry hasn't been deleted now */
- PR_Lock(cache->c_mutex);
+ cache_lock(cache);
if (e->ep_state & (ENTRY_STATE_DELETED|ENTRY_STATE_NOTINCACHE)) {
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
PR_ExitMonitor(e->ep_mutexp);
LOG("<= cache_lock_entry (DELETED)\n", 0, 0, 0);
return RETRY_CACHE_LOCK;
}
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
LOG("<= cache_lock_entry (FOUND)\n", 0, 0, 0);
return 0;
@@ -1613,7 +1619,7 @@ dncache_set_max_size(struct cache *cache, size_t bytes)
"WARNING -- Minimum cache size is %lu -- rounding up\n",
MINCACHESIZE, 0, 0);
}
- PR_Lock(cache->c_mutex);
+ cache_lock(cache);
cache->c_maxsize = bytes;
LOG("entry cache size set to %lu\n", bytes, 0, 0);
/* check for full cache, and clear out if necessary */
@@ -1633,7 +1639,7 @@ dncache_set_max_size(struct cache *cache, size_t bytes)
erase_cache(cache, CACHE_TYPE_DN);
cache_make_hashes(cache, CACHE_TYPE_DN);
}
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
if (! dblayer_is_cachesize_sane(&bytes)) {
LDAPDebug1Arg(LDAP_DEBUG_ANY,
"WARNING -- Possible CONFIGURATION ERROR -- cachesize "
@@ -1697,7 +1703,7 @@ dncache_return(struct cache *cache, struct backdn **bdn)
LOG("=> dncache_return (%s) reference count: %d, dn in cache:%ld\n",
slapi_sdn_get_dn((*bdn)->dn_sdn), (*bdn)->ep_refcnt,
cache->c_curentries);
- PR_Lock(cache->c_mutex);
+ cache_lock(cache);
if ((*bdn)->ep_state & ENTRY_STATE_NOTINCACHE)
{
backdn_free(bdn);
@@ -1717,7 +1723,7 @@ dncache_return(struct cache *cache, struct backdn **bdn)
}
}
}
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
while (dnflush)
{
dnflushtemp = BACK_LRU_NEXT(dnflush, struct backdn *);
@@ -1738,22 +1744,22 @@ dncache_find_id(struct cache *cache, ID id)
LOG("=> dncache_find_id (%lu)\n", (u_long)id, 0, 0);
- PR_Lock(cache->c_mutex);
+ cache_lock(cache);
if (find_hash(cache->c_idtable, &id, sizeof(ID), (void **)&bdn)) {
/* need to check entry state */
if (bdn->ep_state != 0) {
/* entry is deleted or not fully created yet */
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
LOG("<= dncache_find_id (NOT FOUND)\n", 0, 0, 0);
return NULL;
}
if (bdn->ep_refcnt == 0)
lru_delete(cache, (void *)bdn);
bdn->ep_refcnt++;
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
slapi_counter_increment(cache->c_hits);
} else {
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
}
slapi_counter_increment(cache->c_tries);
@@ -1778,7 +1784,7 @@ dncache_add_int(struct cache *cache, struct backdn *bdn, int state,
LOG("=> dncache_add_int( \"%s\", %ld )\n",
slapi_sdn_get_dn(bdn->dn_sdn),
bdn->ep_id, 0);
- PR_Lock(cache->c_mutex);
+ cache_lock(cache);
if (! add_hash(cache->c_idtable, &(bdn->ep_id), sizeof(ID), bdn,
(void **)&my_alt)) {
@@ -1813,7 +1819,7 @@ dncache_add_int(struct cache *cache, struct backdn *bdn, int state,
* to prevent that the caller accidentally thinks the existing
* entry is not the same one the caller has and releases it.
*/
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
return 1;
}
}
@@ -1823,14 +1829,14 @@ dncache_add_int(struct cache *cache, struct backdn *bdn, int
state,
{
LOG("the entry is reserved\n", 0, 0, 0);
bdn->ep_state |= ENTRY_STATE_NOTINCACHE;
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
return -1;
}
else if (state != 0)
{
LOG("the entry already exists. cannot reserve it.\n", 0, 0,
0);
bdn->ep_state |= ENTRY_STATE_NOTINCACHE;
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
return -1;
}
else
@@ -1841,7 +1847,7 @@ dncache_add_int(struct cache *cache, struct backdn *bdn, int state,
lru_delete(cache, (void *)*alt);
(*alt)->ep_refcnt++;
}
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
return 1;
}
}
@@ -1870,7 +1876,7 @@ dncache_add_int(struct cache *cache, struct backdn *bdn, int state,
dnflush = dncache_flush(cache);
}
}
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
while (dnflush)
{
@@ -1898,7 +1904,7 @@ dncache_replace(struct cache *cache, struct backdn *olddn, struct
backdn *newdn)
* where the entry isn't in all the table yet, so we don't care if any
* of these return errors.
*/
- PR_Lock(cache->c_mutex);
+ cache_lock(cache);
/*
* First, remove the old entry from the hashtable.
@@ -1910,7 +1916,7 @@ dncache_replace(struct cache *cache, struct backdn *olddn, struct
backdn *newdn)
found = remove_hash(cache->c_idtable, &(olddn->ep_id), sizeof(ID));
if (!found) {
LOG("dn cache replace: cache index tables out of sync\n", 0, 0,
0);
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
return 1;
}
}
@@ -1921,7 +1927,7 @@ dncache_replace(struct cache *cache, struct backdn *olddn, struct
backdn *newdn)
*/
if (!add_hash(cache->c_idtable, &(newdn->ep_id), sizeof(ID), newdn, NULL))
{
LOG("dn cache replace: can't add id\n", 0, 0, 0);
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
return 1;
}
/* adjust cache meta info */
@@ -1936,7 +1942,7 @@ dncache_replace(struct cache *cache, struct backdn *olddn, struct
backdn *newdn)
}
olddn->ep_state = ENTRY_STATE_DELETED;
newdn->ep_state = 0;
- PR_Unlock(cache->c_mutex);
+ cache_unlock(cache);
LOG("<= dncache_replace OK, cache size now %lu cache count now %ld\n",
slapi_counter_get_value(cache->c_cursize), cache->c_curentries, 0);
return 0;
@@ -2022,23 +2028,24 @@ dn_lru_verify(struct cache *cache, struct backdn *dn, int in)
#ifdef CACHE_DEBUG
void
-check_entry_cache(struct cache *cache, struct backentry *e, int in_cache)
+check_entry_cache(struct cache *cache, struct backentry *e)
{
Slapi_DN *sdn = slapi_entry_get_sdn(e->ep_entry);
struct backentry *debug_e = cache_find_dn(cache,
slapi_sdn_get_dn(sdn),
slapi_sdn_get_ndn_len(sdn));
+ in_cache = cache_is_in_cache(cache, (void *)e);
if (in_cache) {
if (debug_e) { /* e is in cache */
CACHE_RETURN(cache, &debug_e);
if ((e != debug_e) && !(e->ep_state & ENTRY_STATE_DELETED)) {
- slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete",
+ slapi_log_error(SLAPI_LOG_FATAL, "check_entry_cache",
"entry 0x%p is not in dn cache but 0x%p having the same dn %s is
"
"although in_cache flag is set!!!\n",
e, debug_e, slapi_sdn_get_dn(sdn));
}
} else if (!(e->ep_state & ENTRY_STATE_DELETED)) {
- slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete",
+ slapi_log_error(SLAPI_LOG_FATAL, "check_entry_cache",
"%s (id %d) is not in dn cache although in_cache flag is
set!!!\n",
slapi_sdn_get_dn(sdn), e->ep_id);
}
@@ -2046,13 +2053,13 @@ check_entry_cache(struct cache *cache, struct backentry *e, int
in_cache)
if (debug_e) { /* e is in cache */
CACHE_RETURN(cache, &debug_e);
if ((e != debug_e) && !(e->ep_state & ENTRY_STATE_DELETED)) {
- slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete",
+ slapi_log_error(SLAPI_LOG_FATAL, "check_entry_cache",
"entry 0x%p is not in id cache but 0x%p having the same id %d is
"
"although in_cache flag is set!!!\n",
e, debug_e, e->ep_id);
}
} else {
- slapi_log_error(SLAPI_LOG_CACHE, "ldbm_back_delete",
+ slapi_log_error(SLAPI_LOG_CACHE, "check_entry_cache",
"%s (id %d) is not in id cache although in_cache flag is
set!!!\n",
slapi_sdn_get_dn(sdn), e->ep_id);
}
@@ -2060,7 +2067,7 @@ check_entry_cache(struct cache *cache, struct backentry *e, int
in_cache)
if (debug_e) { /* e is in cache */
CACHE_RETURN(cache, &debug_e);
if (e == debug_e) {
- slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete",
+ slapi_log_error(SLAPI_LOG_FATAL, "check_entry_cache",
"%s (id %d) is in dn cache although in_cache flag is not
set!!!\n",
slapi_sdn_get_dn(sdn), e->ep_id);
}
@@ -2069,7 +2076,7 @@ check_entry_cache(struct cache *cache, struct backentry *e, int
in_cache)
if (debug_e) { /* e is in cache: bad */
CACHE_RETURN(cache, &debug_e);
if (e == debug_e) {
- slapi_log_error(SLAPI_LOG_CACHE, "ldbm_back_delete",
+ slapi_log_error(SLAPI_LOG_CACHE, "check_entry_cache",
"%s (id %d) is in id cache although in_cache flag is not
set!!!\n",
slapi_sdn_get_dn(sdn), e->ep_id);
}
@@ -2077,3 +2084,35 @@ check_entry_cache(struct cache *cache, struct backentry *e, int
in_cache)
}
}
#endif
+
+int
+cache_has_otherref(struct cache *cache, void *ptr)
+{
+ struct backcommon *bep;
+ int hasref = 0;
+
+ if (NULL == ptr) {
+ return hasref;
+ }
+ bep = (struct backcommon *)ptr;
+ /* slows down too much? PR_Lock(cache->c_mutex); */
+ hasref = bep->ep_refcnt;
+ /* PR_Unlock(cache->c_mutex); */
+ return (hasref>1)?1:0;
+}
+
+int
+cache_is_in_cache(struct cache *cache, void *ptr)
+{
+ struct backcommon *bep;
+ int in_cache = 0;
+
+ if (NULL == ptr) {
+ return in_cache;
+ }
+ bep = (struct backcommon *)ptr;
+ /* slows down too much? PR_Lock(cache->c_mutex); */
+ in_cache = (bep->ep_state &
(ENTRY_STATE_DELETED|ENTRY_STATE_NOTINCACHE))?0:1;
+ /* PR_Unlock(cache->c_mutex); */
+ return in_cache;
+}
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c
b/ldap/servers/slapd/back-ldbm/ldbm_add.c
index 2d26e40..d92343e 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c
@@ -85,6 +85,7 @@ ldbm_back_add( Slapi_PBlock *pb )
struct backentry *addingentry = NULL;
struct backentry *parententry = NULL;
struct backentry *originalentry = NULL;
+ struct backentry *tmpentry = NULL;
ID pid;
int isroot;
char *errbuf= NULL;
@@ -104,8 +105,6 @@ ldbm_back_add( Slapi_PBlock *pb )
int ruv_c_init = 0;
int rc = 0;
int addingentry_id_assigned = 0;
- int addingentry_in_cache = 0;
- int tombstone_in_cache = 0;
Slapi_DN *sdn = NULL;
Slapi_DN parentsdn;
Slapi_Operation *operation;
@@ -222,34 +221,32 @@ ldbm_back_add( Slapi_PBlock *pb )
dblayer_txn_abort_ext(li, &txn, PR_FALSE);
noabort = 1;
slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
-
- if (addingentry_in_cache) {
+ /* must duplicate addingentry before returning it to cache,
+ * which could free the entry. */
+ if ( (tmpentry = backentry_dup( addingentry )) == NULL ) {
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
+ if (cache_is_in_cache(&inst->inst_cache, addingentry)) {
/* addingentry is in cache. Remove it once. */
retval = CACHE_REMOVE(&inst->inst_cache, addingentry);
if (retval) {
LDAPDebug1Arg(LDAP_DEBUG_CACHE, "ldbm_add: cache_remove %s failed.\n",
slapi_entry_get_dn_const(addingentry->ep_entry));
}
- CACHE_RETURN(&inst->inst_cache, &addingentry);
- } else {
- backentry_free(&addingentry);
}
+ CACHE_RETURN(&inst->inst_cache, &addingentry);
slapi_pblock_set( pb, SLAPI_ADD_ENTRY, originalentry->ep_entry );
addingentry = originalentry;
- if ( (originalentry = backentry_dup( addingentry )) == NULL ) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
+ originalentry = tmpentry;
+ tmpentry = NULL;
+ /* Adding the resetted addingentry to the cache. */
+ if (cache_add_tentative(&inst->inst_cache, addingentry, NULL) < 0) {
+ LDAPDebug1Arg(LDAP_DEBUG_CACHE, "cache_add_tentative concurrency detected:
%s\n",
+ slapi_entry_get_dn_const(addingentry->ep_entry));
+ ldap_result_code = LDAP_ALREADY_EXISTS;
goto error_return;
}
- if (addingentry_in_cache) {
- /* Adding the resetted addingentry to the cache. */
- if (cache_add_tentative(&inst->inst_cache, addingentry, NULL) != 0) {
- LDAPDebug1Arg(LDAP_DEBUG_CACHE, "cache_add_tentative concurrency detected:
%s\n",
- slapi_entry_get_dn_const(addingentry->ep_entry));
- ldap_result_code = LDAP_ALREADY_EXISTS;
- addingentry_in_cache = 0;
- goto error_return;
- }
- }
if (ruv_c_init) {
/* reset the ruv txn stuff */
modify_term(&ruv_c, be);
@@ -531,7 +528,6 @@ ldbm_back_add( Slapi_PBlock *pb )
ldap_result_code= -1;
goto error_return; /* error result sent by find_entry2modify() */
}
- tombstone_in_cache = 1;
addingentry = backentry_dup( tombstoneentry );
if ( addingentry==NULL )
@@ -788,14 +784,13 @@ ldbm_back_add( Slapi_PBlock *pb )
/* Tentatively add the entry to the cache. We do this after adding any
* operational attributes to ensure that the cache is sized correctly. */
- if ( cache_add_tentative( &inst->inst_cache, addingentry, NULL )!= 0 )
+ if ( cache_add_tentative( &inst->inst_cache, addingentry, NULL ) < 0 )
{
LDAPDebug1Arg(LDAP_DEBUG_CACHE, "cache_add_tentative concurrency detected:
%s\n",
slapi_entry_get_dn_const(addingentry->ep_entry));
ldap_result_code= LDAP_ALREADY_EXISTS;
goto error_return;
}
- addingentry_in_cache = 1;
/*
* Before we add the entry, find out if the syntax of the aci
@@ -830,7 +825,6 @@ ldbm_back_add( Slapi_PBlock *pb )
parent_found = 1;
parententry = NULL;
}
-
if ( (originalentry = backentry_dup(addingentry )) == NULL ) {
ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
@@ -865,7 +859,7 @@ ldbm_back_add( Slapi_PBlock *pb )
goto error_return;
}
- retval = id2entry_add( be, addingentry, &txn );
+ retval = id2entry_add_ext(be, addingentry, &txn, 1, &myrc);
if (DB_LOCK_DEADLOCK == retval)
{
LDAPDebug( LDAP_DEBUG_ARGS, "add 1 DEADLOCK\n", 0, 0, 0 );
@@ -1085,10 +1079,6 @@ ldbm_back_add( Slapi_PBlock *pb )
retval = -1;
goto error_return;
}
- if (addingentry_in_cache) { /* decrease the refcnt added by tentative */
- CACHE_RETURN( &inst->inst_cache, &addingentry );
- }
- addingentry_in_cache = 1; /* reset it to make it sure... */
/*
* The tombstone was locked down in the cache... we can
* get rid of the entry in the cache now.
@@ -1103,9 +1093,6 @@ ldbm_back_add( Slapi_PBlock *pb )
CACHE_RETURN(&inst->inst_dncache, &bdn);
}
}
- cache_unlock_entry(&inst->inst_cache, tombstoneentry);
- CACHE_RETURN(&inst->inst_cache, &tombstoneentry);
- tombstone_in_cache = 0;
}
if (parent_found)
{
@@ -1173,21 +1160,18 @@ error_return:
}
if ( addingentry )
{
- if ( addingentry_in_cache )
- {
- if (inst) {
- CACHE_REMOVE(&inst->inst_cache, addingentry);
- /* tell frontend not to free this entry */
- slapi_pblock_set(pb, SLAPI_ADD_ENTRY, NULL);
- }
+ if (inst && cache_is_in_cache(&inst->inst_cache, addingentry)) {
+ CACHE_REMOVE(&inst->inst_cache, addingentry);
+ /* tell frontend not to free this entry */
+ slapi_pblock_set(pb, SLAPI_ADD_ENTRY, NULL);
}
- else
+ else if (!cache_has_otherref(&inst->inst_cache, addingentry))
{
if (!is_resurect_operation) { /* if resurect, tombstoneentry is dupped. */
backentry_clear_entry(addingentry); /* e is released in the frontend */
}
- backentry_free( &addingentry ); /* release the backend wrapper, here */
}
+ CACHE_RETURN( &inst->inst_cache, &addingentry );
}
if (rc == DB_RUNRECOVERY) {
dblayer_remember_disk_filled(li);
@@ -1240,12 +1224,6 @@ diskfull_return:
opreturn = -1;
slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, &opreturn);
}
- if (addingentry_in_cache && addingentry && inst) {
- CACHE_REMOVE(&inst->inst_cache, addingentry);
- /* tell frontend not to free this entry */
- slapi_pblock_set(pb, SLAPI_ADD_ENTRY, NULL);
- }
-
slapi_pblock_get(pb, SLAPI_PB_RESULT_TEXT, &ldap_result_message);
}
@@ -1263,11 +1241,11 @@ diskfull_return:
common_return:
if (inst) {
- if(tombstone_in_cache && tombstoneentry) {
+ if (tombstoneentry && cache_is_in_cache(&inst->inst_cache,
tombstoneentry)) {
cache_unlock_entry(&inst->inst_cache, tombstoneentry);
CACHE_RETURN(&inst->inst_cache, &tombstoneentry);
}
- if (addingentry_in_cache && addingentry) {
+ if (addingentry) {
if ((0 == retval) && entryrdn_get_switch()) { /* subtree-rename: on */
/* since adding the entry to the entry cache was successful,
* let's add the dn to dncache, if not yet done. */
@@ -1319,6 +1297,7 @@ common_return:
slapi_send_ldap_result( pb, ldap_result_code, ldap_result_matcheddn,
ldap_result_message, 0, NULL );
}
backentry_free(&originalentry);
+ backentry_free(&tmpentry);
slapi_sdn_done(&parentsdn);
slapi_ch_free( (void**)&ldap_result_matcheddn );
slapi_ch_free( (void**)&errbuf );
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index 13a78fa..90736b3 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -61,6 +61,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
struct backentry *e = NULL;
struct backentry *tombstone = NULL;
struct backentry *original_tombstone = NULL;
+ struct backentry *tmptombstone = NULL;
const char *dn = NULL;
back_txn txn;
back_txnid parent_txn;
@@ -88,8 +89,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
int delete_tombstone_entry = 0; /* We must remove the given tombstone entry from the
DB */
int create_tombstone_entry = 0; /* We perform a "regular" LDAP delete but
since we use */
/* replication, we must create a new tombstone entry */
- int tombstone_in_cache = 0;
- int e_in_cache = 0;
int remove_e_from_cache = 0;
entry_address *addr;
int addordel_flags = 0; /* passed to index_addordel */
@@ -103,6 +102,9 @@ ldbm_back_delete( Slapi_PBlock *pb )
int myrc = 0;
PRUint64 conn_id;
int op_id;
+ ID ep_id = 0;
+ ID tomb_ep_id = 0;
+
if (slapi_pblock_get(pb, SLAPI_CONN_ID, &conn_id) < 0) {
conn_id = 0; /* connection is NULL */
}
@@ -205,7 +207,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
*/
txn.back_txn_txn = NULL; /* ready to create the child transaction */
for (retry_count = 0; retry_count < RETRY_TIMES; retry_count++) {
- if (txn.back_txn_txn && (txn.back_txn_txn != parent_txn)) {
+ if (txn.back_txn_txn && (txn.back_txn_txn != parent_txn)) { /* retry_count >
0 */
Slapi_Entry *ent = NULL;
/* Don't release SERIAL LOCK */
@@ -226,25 +228,30 @@ ldbm_back_delete( Slapi_PBlock *pb )
/* reset tombstone entry */
if (original_tombstone) {
- if (tombstone_in_cache) {
- CACHE_REMOVE(&inst->inst_cache, tombstone);
- CACHE_RETURN(&inst->inst_cache, &tombstone);
- tombstone = NULL;
- tombstone_in_cache = 0;
- } else {
- backentry_free(&tombstone);
- }
- tombstone = original_tombstone;
- if ( (original_tombstone = backentry_dup( tombstone )) == NULL ) {
+ /* must duplicate tombstone before returning it to cache,
+ * which could free the entry. */
+ if ( (tmptombstone = backentry_dup( original_tombstone )) == NULL ) {
ldap_result_code= LDAP_OPERATIONS_ERROR;
goto error_return;
}
+ if (cache_is_in_cache(&inst->inst_cache, tombstone)) {
+ CACHE_REMOVE(&inst->inst_cache, tombstone);
+ }
+ CACHE_RETURN(&inst->inst_cache, &tombstone);
+ if (tombstone) {
+ slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete",
+ "conn=%lu op=%d [retry: %d] tombstone %s is not freed!!! refcnt
%d, state %d\n",
+ conn_id, op_id, retry_count,
slapi_entry_get_dn(tombstone->ep_entry),
+ tombstone->ep_refcnt, tombstone->ep_state);
+ }
+ tombstone = original_tombstone;
+ original_tombstone = tmptombstone;
+ tmptombstone = NULL;
+ } else {
+ slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete",
+ "conn=%lu op=%d [retry: %d] No original_tombstone for
%s!!\n",
+ conn_id, op_id, retry_count, slapi_entry_get_dn(e->ep_entry));
}
- /* reset original entry in cache */
- if (!e_in_cache) {
- CACHE_ADD(&inst->inst_cache, e, NULL);
- e_in_cache = 1;
- }
if (ruv_c_init) {
/* reset the ruv txn stuff */
modify_term(&ruv_c, be);
@@ -252,8 +259,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
}
/* We're re-trying */
- LDAPDebug0Args(LDAP_DEBUG_BACKLDBM,
- "Delete Retrying Transaction\n");
+ LDAPDebug0Args(LDAP_DEBUG_BACKLDBM, "Delete Retrying Transaction\n");
#ifndef LDBM_NO_BACKOFF_DELAY
{
PRIntervalTime interval;
@@ -295,12 +301,11 @@ ldbm_back_delete( Slapi_PBlock *pb )
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM, "ldbm_back_delete: Deleting entry is already
deleted.\n");
goto error_return; /* error result sent by find_entry2modify() */
}
- e_in_cache = 1; /* e is cached */
-
+ ep_id = e->ep_id;
retval = slapi_entry_has_children(e->ep_entry);
if (retval) {
ldap_result_code= LDAP_NOT_ALLOWED_ON_NONLEAF;
- slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete",
+ slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_delete",
"conn=%lu op=%d Deleting entry %s has %d children.\n",
conn_id, op_id, slapi_entry_get_dn(e->ep_entry), retval);
retval = -1;
@@ -548,12 +553,11 @@ ldbm_back_delete( Slapi_PBlock *pb )
op |= PARENTUPDATE_DELETE_TOMBSTONE;
}
retval = parent_update_on_childchange(&parent_modify_c, op, &haschildren);
- slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_delete",
- "conn=%lu op=%d parent_update_on_childchange: old_entry=0x%p,
new_entry=0x%p, rc=%d\n",
- conn_id, op_id, parent_modify_c.old_entry,
parent_modify_c.new_entry, retval);
-
/* The modify context now contains info needed later */
if (0 != retval) {
+ slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete",
+ "conn=%lu op=%d parent_update_on_childchange: old_entry=0x%p,
new_entry=0x%p, rc=%d\n",
+ conn_id, op_id, parent_modify_c.old_entry,
parent_modify_c.new_entry, retval);
ldap_result_code= LDAP_OPERATIONS_ERROR;
slapi_sdn_done(&parentsdn);
retval = -1;
@@ -610,6 +614,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
parentuniqueid= slapi_entry_get_uniqueid(parent_modify_c.old_entry->ep_entry);
}
tombstone = backentry_dup( e );
+ tomb_ep_id = tombstone->ep_id;
slapi_entry_set_dn(tombstone->ep_entry,tombstone_dn); /* Consumes DN */
if (entryrdn_get_switch()) /* subtree-rename: on */
{
@@ -720,13 +725,10 @@ ldbm_back_delete( Slapi_PBlock *pb )
* entry is removed from the cache.
*/
retval = cache_add_tentative(&inst->inst_cache, tombstone, NULL);
- if (0 == retval) {
- tombstone_in_cache = 1;
- } else {
+ if (0 > retval) {
slapi_log_error(SLAPI_LOG_CACHE, "ldbm_back_delete",
"conn=%lu op=%d tombstone entry %s failed to add to the cache:
%d\n",
conn_id, op_id, slapi_entry_get_dn(tombstone->ep_entry), retval);
- tombstone_in_cache = 0;
if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
DEL_SET_ERROR(ldap_result_code,
LDAP_OPERATIONS_ERROR, retry_count);
@@ -745,13 +747,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
DEL_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
goto error_return;
}
- if (tombstone_in_cache) {
- /* tombstone was already added to the cache via cache_add_tentative (to reserve its
spot in the cache)
- and/or id2entry_add - so it already had one refcount - cache_replace adds another
refcount -
- drop the extra ref added by cache_replace */
- CACHE_RETURN( &inst->inst_cache, &tombstone );
- }
- tombstone_in_cache = 1;
}
else
{
@@ -1155,6 +1150,15 @@ ldbm_back_delete( Slapi_PBlock *pb )
retval = -1;
goto error_return;
}
+ if (create_tombstone_entry) {
+ retval = cache_replace(&inst->inst_cache, e, tombstone);
+ if (retval) {
+ LDAPDebug(LDAP_DEBUG_CACHE, "ldbm_back_delete: cache_replace failed (%d): %s
--> %s\n",
+ retval, slapi_entry_get_dn(e->ep_entry),
slapi_entry_get_dn(tombstone->ep_entry));
+ retval= -1;
+ goto error_return;
+ }
+ }
if (create_tombstone_entry) {
retval = cache_replace(&inst->inst_cache, e, tombstone);
@@ -1205,22 +1209,26 @@ ldbm_back_delete( Slapi_PBlock *pb )
/* delete from cache and clean up */
if (e) {
- if (entryrdn_get_switch()) { /* subtree-rename: on */
+ if (cache_is_in_cache(&inst->inst_cache, e)) {
+ ep_id = e->ep_id; /* Otherwise, e might have been freed. */
+ CACHE_REMOVE(&inst->inst_cache, e);
+ }
+ cache_unlock_entry(&inst->inst_cache, e);
+ CACHE_RETURN(&inst->inst_cache, &e);
+ /*
+ * e is unlocked and no longer in cache.
+ * It could be freed at any moment.
+ */
+ e = NULL;
+
+ if (entryrdn_get_switch() && ep_id) { /* subtree-rename: on */
/* since the op was successful, delete the tombstone dn from the dn cache */
- struct backdn *bdn = dncache_find_id(&inst->inst_dncache, e->ep_id);
+ struct backdn *bdn = dncache_find_id(&inst->inst_dncache, ep_id);
if (bdn) { /* in the dncache, remove it. */
CACHE_REMOVE(&inst->inst_dncache, bdn);
CACHE_RETURN(&inst->inst_dncache, &bdn);
}
}
- if (e_in_cache) {
- CACHE_REMOVE(&inst->inst_cache, e);
- cache_unlock_entry(&inst->inst_cache, e);
- CACHE_RETURN(&inst->inst_cache, &e);
- } else {
- cache_unlock_entry(&inst->inst_cache, e);
- }
- e = NULL;
}
if (ruv_c_init) {
@@ -1250,43 +1258,23 @@ ldbm_back_delete( Slapi_PBlock *pb )
error_return:
if (tombstone) {
- if (entryrdn_get_switch()) { /* subtree-rename: on */
+ if (cache_is_in_cache(&inst->inst_cache, tombstone)) {
+ tomb_ep_id = tombstone->ep_id; /* Otherwise, tombstone might have been freed. */
+ }
+ if (entryrdn_get_switch() && tomb_ep_id) { /* subtree-rename: on */
struct backdn *bdn = dncache_find_id(&inst->inst_dncache,
tombstone->ep_id);
if (bdn) { /* already in the dncache. Delete it. */
CACHE_REMOVE(&inst->inst_dncache, bdn);
CACHE_RETURN(&inst->inst_dncache, &bdn);
}
}
-#ifdef CACHE_DEBUG
- check_entry_cache(&inst->inst_cache, tombstone, tombstone_in_cache);
-#endif
- if (tombstone_in_cache) { /* successfully replaced */
- CACHE_REMOVE( &inst->inst_cache, tombstone );
- CACHE_RETURN( &inst->inst_cache, &tombstone );
- tombstone = NULL;
- tombstone_in_cache = 0;
- } else {
- backentry_free( &tombstone );
- }
- }
- /* Need to return to cache after post op plugins are called */
- if (e) {
-#ifdef CACHE_DEBUG
- check_entry_cache(&inst->inst_cache, e, e_in_cache);
-#endif
- if (e_in_cache) {
- if (remove_e_from_cache) {
- /* The entry is already transformed to a tombstone. */
- CACHE_REMOVE( &inst->inst_cache, e );
- }
- cache_unlock_entry( &inst->inst_cache, e );
- CACHE_RETURN( &inst->inst_cache, &e );
- } else {
- cache_unlock_entry( &inst->inst_cache, e );
+ if (cache_is_in_cache(&inst->inst_cache, tombstone)) {
+ CACHE_REMOVE(&inst->inst_cache, tombstone);
}
+ CACHE_RETURN( &inst->inst_cache, &tombstone );
+ tombstone = NULL;
}
-
if (retval == DB_RUNRECOVERY) {
dblayer_remember_disk_filled(li);
ldbm_nasty("Delete",79,retval);
@@ -1376,16 +1364,8 @@ common_return:
}
}
}
-#ifdef CACHE_DEBUG
- check_entry_cache(&inst->inst_cache, tombstone, tombstone_in_cache);
-#endif
- if (tombstone_in_cache) { /* successfully replaced */
- CACHE_RETURN( &inst->inst_cache, &tombstone );
- tombstone = NULL;
- tombstone_in_cache = 0;
- } else {
- backentry_free( &tombstone );
- }
+ CACHE_RETURN( &inst->inst_cache, &tombstone );
+ tombstone = NULL;
}
/* result code could be used in the bepost plugin functions. */
@@ -1397,8 +1377,14 @@ common_return:
if (!delete_tombstone_entry) {
plugin_call_plugins (pb, SLAPI_PLUGIN_BE_POST_DELETE_FN);
}
+<<<<<<< HEAD
if (e) {
if (e_in_cache) {
+=======
+ /* Need to return to cache after post op plugins are called */
+ if (e) {
+ if (cache_is_in_cache(&inst->inst_cache, e)) {
+>>>>>>> d9c8b1f... Ticket #47834 - Tombstone_to_glue: if parents are
also converted to glue, the target entry's DN must be adjusted.
if (remove_e_from_cache) {
/* The entry is already transformed to a tombstone. */
CACHE_REMOVE( &inst->inst_cache, e );
@@ -1406,7 +1392,11 @@ common_return:
}
cache_unlock_entry( &inst->inst_cache, e );
CACHE_RETURN( &inst->inst_cache, &e );
+<<<<<<< HEAD
/*
+=======
+ /*
+>>>>>>> d9c8b1f... Ticket #47834 - Tombstone_to_glue: if parents are
also converted to glue, the target entry's DN must be adjusted.
* e is unlocked and no longer in cache.
* It could be freed at any moment.
*/
@@ -1430,7 +1420,8 @@ diskfull_return:
}
slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_delete",
"conn=%lu op=%d modify_term: old_entry=0x%p, new_entry=0x%p,
in_cache=%d\n",
- conn_id, op_id, parent_modify_c.old_entry, parent_modify_c.new_entry,
parent_modify_c.new_entry_in_cache);
+ conn_id, op_id, parent_modify_c.old_entry, parent_modify_c.new_entry,
+ cache_is_in_cache(&inst->inst_cache,
parent_modify_c.new_entry));
myrc = modify_term(&parent_modify_c, be);
if (rc == 0 && opcsn && !is_fixup_operation &&
!delete_tombstone_entry)
{
@@ -1448,6 +1439,7 @@ diskfull_return:
slapi_pblock_set(pb, SLAPI_DELETE_EXISTING_ENTRY, NULL);
}
backentry_free(&original_tombstone);
+ backentry_free(&tmptombstone);
slapi_ch_free((void**)&errbuf);
slapi_sdn_done(&nscpEntrySDN);
slapi_ch_free_string(&e_uniqueid);
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
index da6a127..e6ccf20 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
@@ -65,7 +65,6 @@ void modify_init(modify_context *mc,struct backentry *old_entry)
PR_ASSERT(NULL == mc->new_entry);
mc->old_entry = old_entry;
- mc->new_entry_in_cache = 0;
mc->attr_encrypt = 1;
}
@@ -86,6 +85,9 @@ int modify_apply_mods_ignore_error(modify_context *mc, Slapi_Mods
*smods, int er
ret = entry_apply_mods_ignore_error( mc->new_entry->ep_entry,
slapi_mods_get_ldapmods_byref(smods), error);
}
mc->smods= smods;
+ if (error == ret) {
+ ret = LDAP_SUCCESS;
+ }
return ret;
}
@@ -96,16 +98,13 @@ int modify_term(modify_context *mc,struct backend *be)
slapi_mods_free(&mc->smods);
/* Unlock and return entries */
- if (NULL != mc->old_entry) {
+ if (mc->old_entry) {
cache_unlock_entry(&inst->inst_cache, mc->old_entry);
CACHE_RETURN( &(inst->inst_cache), &(mc->old_entry) );
mc->old_entry= NULL;
}
- if (mc->new_entry_in_cache) {
- CACHE_RETURN( &(inst->inst_cache), &(mc->new_entry) );
- } else {
- backentry_free(&(mc->new_entry));
- }
+
+ CACHE_RETURN(&(inst->inst_cache), &(mc->new_entry));
mc->new_entry= NULL;
return 0;
}
@@ -115,11 +114,9 @@ int modify_switch_entries(modify_context *mc,backend *be)
{
ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
int ret = 0;
- if (mc->old_entry!=NULL && mc->new_entry!=NULL) {
+ if (mc->old_entry && mc->new_entry) {
ret = cache_replace(&(inst->inst_cache), mc->old_entry, mc->new_entry);
- if (ret == 0) {
- mc->new_entry_in_cache = 1;
- } else {
+ if (ret) {
LDAPDebug(LDAP_DEBUG_CACHE, "modify_switch_entries: replacing %s with %s failed
(%d)\n",
slapi_entry_get_dn(mc->old_entry->ep_entry),
slapi_entry_get_dn(mc->new_entry->ep_entry), ret);
@@ -140,13 +137,19 @@ modify_unswitch_entries(modify_context *mc,backend *be)
ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
int ret = 0;
- if (mc->old_entry && mc->new_entry && mc->new_entry_in_cache)
{
+ if (mc->old_entry && mc->new_entry &&
+ cache_is_in_cache(&inst->inst_cache, mc->new_entry)) {
/* switch the entries, and reset the new, new, entry */
tmp_be = mc->new_entry;
mc->new_entry = mc->old_entry;
mc->new_entry->ep_state = 0;
- mc->new_entry->ep_refcnt = 0;
- mc->new_entry_in_cache = 0;
+ if (cache_has_otherref(&(inst->inst_cache), mc->new_entry)) {
+ /* some other thread refers the entry */
+ CACHE_RETURN(&(inst->inst_cache), &(mc->new_entry));
+ } else {
+ /* don't call CACHE_RETURN, that frees the entry! */
+ mc->new_entry->ep_refcnt = 0;
+ }
mc->old_entry = tmp_be;
ret = cache_replace(&(inst->inst_cache), mc->old_entry, mc->new_entry);
@@ -157,9 +160,7 @@ modify_unswitch_entries(modify_context *mc,backend *be)
* "old" one. modify_term() will then return the "new" entry.
*/
cache_unlock_entry(&inst->inst_cache, mc->new_entry);
- CACHE_RETURN( &(inst->inst_cache), &(mc->old_entry) );
- mc->new_entry_in_cache = 1;
- mc->old_entry = NULL;
+ cache_lock_entry(&inst->inst_cache, mc->old_entry);
} else {
LDAPDebug(LDAP_DEBUG_CACHE, "modify_unswitch_entries: replacing %s with %s failed
(%d)\n",
slapi_entry_get_dn(mc->old_entry->ep_entry),
@@ -362,7 +363,8 @@ ldbm_back_modify( Slapi_PBlock *pb )
backend *be;
ldbm_instance *inst = NULL;
struct ldbminfo *li;
- struct backentry *e = NULL, *ec = NULL, *original_entry = NULL;
+ struct backentry *e = NULL, *ec = NULL;
+ struct backentry *original_entry = NULL, *tmpentry = NULL;
Slapi_Entry *postentry = NULL;
LDAPMod **mods = NULL;
LDAPMod **mods_original = NULL;
@@ -381,7 +383,6 @@ ldbm_back_modify( Slapi_PBlock *pb )
int rc = 0;
Slapi_Operation *operation;
entry_address *addr;
- int ec_in_cache = 0;
int is_fixup_operation= 0;
int is_ruv = 0; /* True if the current entry is RUV */
CSN *opcsn = NULL;
@@ -475,14 +476,22 @@ ldbm_back_modify( Slapi_PBlock *pb )
slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
ldap_mods_free(mods, 1);
slapi_pblock_set(pb, SLAPI_MODIFY_MODS, copy_mods(mods_original));
- /* ec is not really added to the cache until cache_replace, so we
- don't have to worry about the cache here */
- backentry_free(&ec);
- slapi_pblock_set( pb, SLAPI_MODIFY_EXISTING_ENTRY, original_entry->ep_entry );
- ec = original_entry;
- if ( (original_entry = backentry_dup( ec )) == NULL ) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
+
+ /* reset ec set cache in id2entry_add_ext */
+ if (ec) {
+ /* must duplicate ec before returning it to cache,
+ * which could free the entry. */
+ if ( (tmpentry = backentry_dup( ec )) == NULL ) {
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
+ if (cache_is_in_cache(&inst->inst_cache, ec)) {
+ CACHE_REMOVE(&inst->inst_cache, ec);
+ }
+ CACHE_RETURN(&inst->inst_cache, &ec);
+ ec = original_entry;
+ original_entry = tmpentry;
+ tmpentry = NULL;
}
if (ruv_c_init) {
@@ -765,15 +774,12 @@ ldbm_back_modify( Slapi_PBlock *pb )
goto error_return;
}
/* e uncached */
- /* we must return both e (which has been deleted) and new entry ec */
- /* cache_replace removes e from the caches */
+ /* we must return both e (which has been deleted) and new entry ec to cache */
+ /* cache_replace removes e from the cache hash tables */
cache_unlock_entry( &inst->inst_cache, e );
CACHE_RETURN( &inst->inst_cache, &e );
-
/* lock new entry in cache to prevent usage until we are complete */
cache_lock_entry( &inst->inst_cache, ec );
- ec_in_cache = 1;
-
postentry = slapi_entry_dup( ec->ep_entry );
slapi_pblock_set( pb, SLAPI_ENTRY_POST_OP, postentry );
@@ -879,11 +885,11 @@ error_return:
}
/* if ec is in cache, remove it, then add back e if we still have it */
- if (inst && ec_in_cache) {
+ if (inst && cache_is_in_cache(&inst->inst_cache, ec)) {
CACHE_REMOVE( &inst->inst_cache, ec );
/* if ec was in cache, e was not - add back e */
if (e) {
- if (CACHE_ADD( &inst->inst_cache, e, NULL )) {
+ if (CACHE_ADD( &inst->inst_cache, e, NULL ) < 0) {
LDAPDebug1Arg(LDAP_DEBUG_CACHE, "ldbm_modify: CACHE_ADD %s failed\n",
slapi_entry_get_dn(e->ep_entry));
}
@@ -894,18 +900,15 @@ common_return:
slapi_mods_done(&smods);
if (inst) {
- if (ec_in_cache) {
- cache_unlock_entry( &inst->inst_cache, ec);
- CACHE_RETURN( &inst->inst_cache, &ec );
- } else {
- backentry_free(&ec);
+ if (cache_is_in_cache(&inst->inst_cache, ec)) {
+ cache_unlock_entry(&inst->inst_cache, ec);
+ } else if (e) {
/* if ec was not in cache, cache_replace was not done.
* i.e., e was not unlocked. */
- if (e) {
- cache_unlock_entry( &inst->inst_cache, e);
- CACHE_RETURN( &inst->inst_cache, &e);
- }
+ cache_unlock_entry(&inst->inst_cache, e);
+ CACHE_RETURN(&inst->inst_cache, &e);
}
+ CACHE_RETURN(&inst->inst_cache, &ec);
if (inst->inst_ref_count) {
slapi_counter_decrement(inst->inst_ref_count);
}
@@ -935,6 +938,7 @@ common_return:
/* free our backups */
ldap_mods_free(mods_original, 1);
backentry_free(&original_entry);
+ backentry_free(&tmpentry);
slapi_ch_free_string(&errbuf);
return rc;
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
index 65880f9..1b297a4 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
@@ -50,7 +50,7 @@ static void moddn_unlock_and_return_entry(backend *be,struct backentry
**targete
static int moddn_newrdn_mods(Slapi_PBlock *pb, const char *olddn, struct backentry *ec,
Slapi_Mods *smods_wsi, int is_repl_op);
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);
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[]);
-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);
+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);
static void mods_remove_nsuniqueid(Slapi_Mods *smods);
#define MOD_SET_ERROR(rc, error, count) \
@@ -67,8 +67,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
struct ldbminfo *li;
struct backentry *e= NULL;
struct backentry *ec= NULL;
- int ec_in_cache= 0;
- int e_in_cache= 0;
back_txn txn;
back_txnid parent_txn;
int retval = -1;
@@ -83,8 +81,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
struct backentry *parententry= NULL;
struct backentry *newparententry= NULL;
struct backentry *original_entry = NULL;
- struct backentry *original_parent = NULL;
- struct backentry *original_newparent = NULL;
+ struct backentry *tmpentry = NULL;
modify_context parent_modify_context = {0};
modify_context newparent_modify_context = {0};
modify_context ruv_c = {0};
@@ -270,29 +267,22 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
slapi_sdn_free(&dn_newsuperiordn);
slapi_pblock_set(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, orig_dn_newsuperiordn);
orig_dn_newsuperiordn = slapi_sdn_dup(orig_dn_newsuperiordn);
-#ifdef CACHE_DEBUG
- check_entry_cache(&inst->inst_cache, ec, ec_in_cache);
-#endif
- if (ec_in_cache) {
- /* New entry 'ec' is in the entry cache.
- * Remove it from the cache . */
+ /* must duplicate ec before returning it to cache,
+ * which could free the entry. */
+ if ( (tmpentry = backentry_dup( ec )) == NULL ) {
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
+ goto error_return;
+ }
+ if (cache_is_in_cache(&inst->inst_cache, ec)) {
CACHE_REMOVE(&inst->inst_cache, ec);
- CACHE_RETURN(&inst->inst_cache, &ec);
-#ifdef DEBUG_CACHE
- PR_ASSERT(ec == NULL);
-#endif
- ec_in_cache = 0;
- } else {
- backentry_free(&ec);
}
- /* make sure the original entry is back in the cache if it was removed */
- if (!e_in_cache) {
- if (CACHE_ADD(&inst->inst_cache, e, NULL)) {
+ CACHE_RETURN(&inst->inst_cache, &ec);
+ if (!cache_is_in_cache(&inst->inst_cache, e)) {
+ if (CACHE_ADD(&inst->inst_cache, e, NULL) < 0) {
LDAPDebug1Arg(LDAP_DEBUG_CACHE,
"ldbm_back_modrdn: CACHE_ADD %s to cache
failed\n",
slapi_entry_get_dn_const(e->ep_entry));
}
- e_in_cache = 1;
}
slapi_pblock_get( pb, SLAPI_MODRDN_EXISTING_ENTRY, &ent );
if (ent && (ent != original_entry->ep_entry)) {
@@ -300,16 +290,13 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
slapi_pblock_set( pb, SLAPI_MODRDN_EXISTING_ENTRY, NULL );
}
ec = original_entry;
- if ( (original_entry = backentry_dup( ec )) == NULL ) {
- ldap_result_code= LDAP_OPERATIONS_ERROR;
- goto error_return;
- }
+ original_entry = tmpentry;
+ tmpentry = NULL;
slapi_pblock_set( pb, SLAPI_MODRDN_EXISTING_ENTRY,
original_entry->ep_entry );
free_modrdn_existing_entry = 0; /* owned by original_entry now */
- if (!ec_in_cache) {
+ if (!cache_is_in_cache(&inst->inst_cache, ec)) {
/* Put the resetted entry 'ec' into the cache again. */
- if (cache_add_tentative( &inst->inst_cache, ec, NULL ) != 0) {
- ec_in_cache = 0; /* not in cache */
+ if (cache_add_tentative( &inst->inst_cache, ec, NULL ) < 0) {
/* allow modrdn even if the src dn and dest dn are identical */
if ( 0 != slapi_sdn_compare((const Slapi_DN *)&dn_newdn,
(const Slapi_DN *)sdn) ) {
@@ -321,8 +308,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
}
/* so if the old dn is the same as the new dn, the entry will not be
cached
until it is replaced with cache_replace */
- } else {
- ec_in_cache = 1;
}
}
@@ -509,7 +494,6 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
ldap_result_code= -1;
goto error_return; /* error result sent by find_entry2modify() */
}
- e_in_cache = 1; /* e is in the cache and locked */
if (slapi_entry_flag_is_set(e->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE)
&&
!is_resurect_operation) {
ldap_result_code = LDAP_UNWILLING_TO_PERFORM;
@@ -747,8 +731,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
}
/* create it in the cache - prevents others from creating it */
- if (( cache_add_tentative( &inst->inst_cache, ec, NULL ) != 0 ) ) {
- ec_in_cache = 0; /* not in cache */
+ if (( cache_add_tentative( &inst->inst_cache, ec, NULL ) < 0 ) ) {
/* allow modrdn even if the src dn and dest dn are identical */
if ( 0 != slapi_sdn_compare((const Slapi_DN *)&dn_newdn,
(const Slapi_DN *)sdn) ) {
@@ -764,46 +747,41 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
}
/* so if the old dn is the same as the new dn, the entry will not be
cached
until it is replaced with cache_replace */
- } else {
- ec_in_cache = 1;
}
-
/* Build the list of modifications required to the existing entry */
+ slapi_mods_init(&smods_generated,4);
+ slapi_mods_init(&smods_generated_wsi,4);
+ ldap_result_code = moddn_newrdn_mods(pb, slapi_sdn_get_ndn(sdn),
+ ec, &smods_generated_wsi, is_replicated_operation);
+ if (ldap_result_code != LDAP_SUCCESS) {
+ if (ldap_result_code == LDAP_UNWILLING_TO_PERFORM)
+ ldap_result_message = "Modification of old rdn attribute type
not allowed.";
+ goto error_return;
+ }
+ if (!entryrdn_get_switch()) /* subtree-rename: off */
{
- slapi_mods_init(&smods_generated,4);
- slapi_mods_init(&smods_generated_wsi,4);
- ldap_result_code = moddn_newrdn_mods(pb, slapi_sdn_get_ndn(sdn),
- ec, &smods_generated_wsi,
is_replicated_operation);
- if (ldap_result_code != LDAP_SUCCESS) {
- if (ldap_result_code == LDAP_UNWILLING_TO_PERFORM)
- ldap_result_message = "Modification of old rdn attribute
type not allowed.";
- goto error_return;
- }
- if (!entryrdn_get_switch()) /* subtree-rename: off */
- {
- /*
- * Remove the old entrydn index entry, and add the new one.
- */
- slapi_mods_add( &smods_generated, LDAP_MOD_DELETE,
LDBM_ENTRYDN_STR,
- strlen(backentry_get_ndn(e)), backentry_get_ndn(e));
- slapi_mods_add( &smods_generated, LDAP_MOD_REPLACE,
LDBM_ENTRYDN_STR,
- strlen(backentry_get_ndn(ec)), backentry_get_ndn(ec));
- }
-
/*
- * Update parentid if we have a new superior.
- */
- if(slapi_sdn_get_dn(dn_newsuperiordn)!=NULL) {
- char buf[40]; /* Enough for an ID */
-
- if (parententry != NULL) {
- sprintf( buf, "%lu", (u_long)parententry->ep_id );
- slapi_mods_add_string(&smods_generated, LDAP_MOD_DELETE,
LDBM_PARENTID_STR, buf);
- }
- if (newparententry != NULL) {
- sprintf( buf, "%lu", (u_long)newparententry->ep_id
);
- slapi_mods_add_string(&smods_generated, LDAP_MOD_REPLACE,
LDBM_PARENTID_STR, buf);
- }
+ * Remove the old entrydn index entry, and add the new one.
+ */
+ slapi_mods_add( &smods_generated, LDAP_MOD_DELETE, LDBM_ENTRYDN_STR,
+ strlen(backentry_get_ndn(e)), backentry_get_ndn(e));
+ slapi_mods_add( &smods_generated, LDAP_MOD_REPLACE,
LDBM_ENTRYDN_STR,
+ strlen(backentry_get_ndn(ec)), backentry_get_ndn(ec));
+ }
+
+ /*
+ * Update parentid if we have a new superior.
+ */
+ if(slapi_sdn_get_dn(dn_newsuperiordn)!=NULL) {
+ char buf[40]; /* Enough for an ID */
+
+ if (parententry != NULL) {
+ sprintf( buf, "%lu", (u_long)parententry->ep_id );
+ slapi_mods_add_string(&smods_generated, LDAP_MOD_DELETE,
LDBM_PARENTID_STR, buf);
+ }
+ if (newparententry != NULL) {
+ sprintf( buf, "%lu", (u_long)newparententry->ep_id );
+ slapi_mods_add_string(&smods_generated, LDAP_MOD_REPLACE,
LDBM_PARENTID_STR, buf);
}
}
@@ -1029,7 +1007,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
/*
* Update the indexes for the entry.
*/
- 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);
+ retval = modrdn_rename_entry_update_indexes(&txn, pb, li, e, &ec,
&smods_generated, &smods_generated_wsi, &smods_operation_wsi);
if (DB_LOCK_DEADLOCK == retval)
{
/* Retry txn */
@@ -1472,19 +1450,13 @@ common_return:
}
/* remove the new entry from the cache if the op failed -
otherwise, leave it in */
-#ifdef CACHE_DEBUG
- check_entry_cache(&inst->inst_cache, ec, ec_in_cache);
-#endif
- if (ec_in_cache && ec && inst) {
- if (retval) {
+ if (ec && inst) {
+ if (retval && cache_is_in_cache(&inst->inst_cache, ec)) {
CACHE_REMOVE( &inst->inst_cache, ec );
}
CACHE_RETURN( &inst->inst_cache, &ec );
- } else {
- backentry_free( &ec );
}
ec = NULL;
- ec_in_cache = 0;
}
if (inst) {
@@ -1546,8 +1518,7 @@ common_return:
slapi_ch_free_string(&original_newrdn);
slapi_sdn_free(&orig_dn_newsuperiordn);
backentry_free(&original_entry);
- backentry_free(&original_parent);
- backentry_free(&original_newparent);
+ backentry_free(&tmpentry);
slapi_entry_free(original_targetentry);
slapi_ch_free((void**)&errbuf);
if (retval == 0 && opcsn != NULL && !is_fixup_operation)
@@ -1817,7 +1788,9 @@ mods_remove_nsuniqueid(Slapi_Mods *smods)
* mods contains the list of attribute change made.
*/
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)
+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)
{
backend *be;
ldbm_instance *inst;
@@ -1825,7 +1798,6 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb,
struct ldbm
char *msg;
Slapi_Operation *operation;
int is_ruv = 0; /* True if the current entry is RUV */
- int orig_ec_in_cache = 0;
int cache_rc = 0;
slapi_pblock_get( pb, SLAPI_BACKEND, &be );
@@ -1833,7 +1805,6 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb,
struct ldbm
is_ruv = operation_is_flag_set(operation, OP_FLAG_REPL_RUV);
inst = (ldbm_instance *) be->be_instance_info;
- orig_ec_in_cache = *ec_in_cache;
/*
* Update the ID to Entry index.
* Note that id2entry_add replaces the entry, so the Entry ID stays the same.
@@ -1855,7 +1826,6 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb,
struct ldbm
LDAPDebug( LDAP_DEBUG_ANY, "modrdn_rename_entry_update_indexes: id2entry_add
failed, err=%d %s\n", retval, (msg = dblayer_strerror( retval )) ? msg :
"", 0 );
goto error_return;
}
- *ec_in_cache = 1; /* id2entry_add adds to cache if not already in */
if(smods1!=NULL && slapi_mods_get_num_mods(smods1)>0)
{
/*
@@ -1943,13 +1913,6 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock
*pb, struct ldbm
retval= -1;
goto error_return;
}
- *e_in_cache = 0;
- if (orig_ec_in_cache) {
- /* ec was already added to the cache via cache_add_tentative (to reserve its spot
in the cache)
- and/or id2entry_add - so it already had one refcount - cache_replace adds
another refcount -
- drop the extra ref added by cache_replace */
- CACHE_RETURN( &inst->inst_cache, ec );
- }
error_return:
return retval;
}
@@ -1984,9 +1947,6 @@ moddn_rename_child_entry(
int olddncomps= 0;
int need= 1; /* For the '\0' */
int i;
- int e_in_cache = 1;
- int ec_in_cache = 0;
-
olddn = slapi_entry_get_dn((*ec)->ep_entry);
if (NULL == olddn) {
return retval;
@@ -2048,8 +2008,7 @@ moddn_rename_child_entry(
* Update all the indexes.
*/
retval = modrdn_rename_entry_update_indexes(ptxn, pb, li, e, ec,
- smodsp, NULL, NULL,
- &e_in_cache, &ec_in_cache);
+ smodsp, NULL, NULL);
/* JCMREPL - Should the children get updated modifiersname and lastmodifiedtime?
*/
slapi_mods_done(&smods);
}
diff --git a/ldap/servers/slapd/back-ldbm/parents.c
b/ldap/servers/slapd/back-ldbm/parents.c
index d375519..f55d527 100644
--- a/ldap/servers/slapd/back-ldbm/parents.c
+++ b/ldap/servers/slapd/back-ldbm/parents.c
@@ -126,11 +126,11 @@ parent_update_on_childchange(modify_context *mc,int op, size_t
*new_sub_count )
mod_op = LDAP_MOD_ADD;
} else if (PARENTUPDATE_DEL == op) {
if (!already_present) {
- /* This means that something is wrong---deleting a child but no subcount present on
parent */
+ /* This means that there was a conflict. Before coming to this point,
+ * the entry to be deleted was deleted... */
LDAPDebug(LDAP_DEBUG_ANY, "Parent %s has no children. (op 0x%x, repl_op
0x%x)\n",
slapi_entry_get_dn(mc->old_entry->ep_entry), op, repl_op);
slapi_mods_free(&smods);
- PR_ASSERT(0);
return -1;
} else {
if (current_sub_count == 1) {
diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
index 180ad4c..632502d 100644
--- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
+++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
@@ -87,8 +87,11 @@ int cache_add_tentative(struct cache *cache, struct backentry *e,
int cache_lock_entry(struct cache *cache, struct backentry *e);
void cache_unlock_entry(struct cache *cache, struct backentry *e);
int cache_replace(struct cache *cache, void *oldptr, void *newptr);
+int cache_has_otherref(struct cache *cache, void *bep);
+int cache_is_in_cache(struct cache *cache, void *ptr);
+
#ifdef CACHE_DEBUG
-void check_entry_cache(struct cache *cache, struct backentry *e, int in_cache);
+void check_entry_cache(struct cache *cache, struct backentry *e);
#endif
Hashtable *new_hash(u_long size, u_long offset, HashFn hfn,
commit 112203f49844bdc47649a6305b64d00485193671
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Tue Jun 24 16:39:24 2014 -0700
Ticket #47834 - Tombstone_to_glue: if parents are also converted to glue, the target
entry's DN must be adjusted.
Bug description: tombstone_to_glue resolves parents recursively if
they are also a tombstone entry, which may change the DN of the
target entry, but the DN change was not adjusted.
Fix description: Added a new argument newparentdn to tombstone_to_
glue_resolve_parent to return the new parent DN if it has been updated.
If a new parent DN is returned, set it to the target DN.
This patch also adds a cache debugging function: check_entry_cache,
which is disabled by default (in #ifdef CACHE_DEBUG)
Note: this bug is a left over of ticket #47750.
https://fedorahosted.org/389/ticket/47834
Reviewed by rmeggins(a)redhat.com (Thank you, Rich!!)
(cherry picked from commit 708a56b8d524131362e2d71b7fbc2eb257075e14)
(cherry picked from commit 513788ce60ef4f3742bfdb5442a92887735367c9)
diff --git a/ldap/servers/plugins/replication/urp.c
b/ldap/servers/plugins/replication/urp.c
index d867274..c7d60e2 100644
--- a/ldap/servers/plugins/replication/urp.c
+++ b/ldap/servers/plugins/replication/urp.c
@@ -966,7 +966,8 @@ urp_add_resolve_parententry (Slapi_PBlock *pb, char *sessionid,
Slapi_Entry *ent
if(is_tombstone_entry(parententry)) /* The parent is a tombstone */
{
/* The parent entry must be resurected from the dead. */
- ldap_rc = tombstone_to_glue (pb, sessionid, parententry, parentdn,
REASON_RESURRECT_ENTRY, opcsn);
+ /* parentdn retrieved from entry is not tombstone dn. */
+ ldap_rc = tombstone_to_glue (pb, sessionid, parententry, parentdn,
REASON_RESURRECT_ENTRY, opcsn, NULL);
if ( ldap_rc != LDAP_SUCCESS )
{
ldap_rc= LDAP_OPERATIONS_ERROR;
diff --git a/ldap/servers/plugins/replication/urp.h
b/ldap/servers/plugins/replication/urp.h
index 8afd7d1..678a2cc 100644
--- a/ldap/servers/plugins/replication/urp.h
+++ b/ldap/servers/plugins/replication/urp.h
@@ -79,6 +79,6 @@ PRBool get_glue_csn(const Slapi_Entry *entry, const CSN **gluecsn);
* urp_tombstone.c
*/
int is_tombstone_entry(const Slapi_Entry* entry);
-int tombstone_to_glue(Slapi_PBlock *pb, char *sessionid, Slapi_Entry *entry, const
Slapi_DN *parentdn, const char *reason, CSN *opcsn);
+int tombstone_to_glue(Slapi_PBlock *pb, char *sessionid, Slapi_Entry *entry, const
Slapi_DN *parentdn, const char *reason, CSN *opcsn, Slapi_DN **newparentdn);
int entry_to_tombstone ( Slapi_PBlock *pb, Slapi_Entry *entry );
PRBool get_tombstone_csn(const Slapi_Entry *entry, const CSN **delcsn);
diff --git a/ldap/servers/plugins/replication/urp_glue.c
b/ldap/servers/plugins/replication/urp_glue.c
index 199d4de..a13c0be 100644
--- a/ldap/servers/plugins/replication/urp_glue.c
+++ b/ldap/servers/plugins/replication/urp_glue.c
@@ -230,7 +230,7 @@ create_glue_entry ( Slapi_PBlock *pb, char *sessionid, Slapi_DN *dn,
const char
slapi_pblock_get( pb, SLAPI_BACKEND, &backend );
slapi_sdn_get_backend_parent ( dn, superiordn, backend );
- slapi_rdn_set_dn_ext(rdn, slapi_sdn_get_dn(dn), 1/* skip nsuniqeid=..., in dn */);
+ slapi_rdn_set_dn_ext(rdn, slapi_sdn_get_dn(dn), SLAPI_RDN_SET_DN_SKIP_UNIQUEID);
while(!done)
{
diff --git a/ldap/servers/plugins/replication/urp_tombstone.c
b/ldap/servers/plugins/replication/urp_tombstone.c
index 5a37ca8..db7fa00 100644
--- a/ldap/servers/plugins/replication/urp_tombstone.c
+++ b/ldap/servers/plugins/replication/urp_tombstone.c
@@ -87,17 +87,18 @@ tombstone_to_glue_resolve_parent (
char *sessionid,
const Slapi_DN *parentdn,
const char *parentuniqueid,
- CSN *opcsn)
+ CSN *opcsn,
+ Slapi_DN **newparentdn)
{
/* Let's have a look at the parent of this entry... */
if(!slapi_sdn_isempty(parentdn) && parentuniqueid!=NULL)
{
int op_result;
- Slapi_PBlock *newpb= slapi_pblock_new();
- slapi_search_internal_set_pb(
- newpb,
- slapi_sdn_get_dn(parentdn), /* JCM - This DN just identifies the backend to be
searched. */
- LDAP_SCOPE_BASE,
+ Slapi_PBlock *newpb= slapi_pblock_new();
+ slapi_search_internal_set_pb(
+ newpb,
+ slapi_sdn_get_dn(parentdn), /* JCM - This DN just identifies the backend to be
searched. */
+ LDAP_SCOPE_BASE,
"objectclass=*",
NULL, /*attrs*/
0, /*attrsonly*/
@@ -106,7 +107,7 @@ tombstone_to_glue_resolve_parent (
repl_get_plugin_identity(PLUGIN_MULTIMASTER_REPLICATION),
0);
slapi_search_internal_pb(newpb);
- slapi_pblock_get(newpb, SLAPI_PLUGIN_INTOP_RESULT, &op_result);
+ slapi_pblock_get(newpb, SLAPI_PLUGIN_INTOP_RESULT, &op_result);
switch(op_result)
{
case LDAP_SUCCESS:
@@ -118,7 +119,8 @@ tombstone_to_glue_resolve_parent (
{
if(is_tombstone_entry(entries[0]))
{
- tombstone_to_glue (pb, sessionid, entries[0], parentdn, REASON_RESURRECT_ENTRY,
opcsn);
+ tombstone_to_glue(pb, sessionid, entries[0], parentdn,
+ REASON_RESURRECT_ENTRY, opcsn, newparentdn);
}
}
else
@@ -146,14 +148,16 @@ tombstone_to_glue (
Slapi_PBlock *pb,
char *sessionid,
Slapi_Entry *tombstoneentry,
- const Slapi_DN *tombstonedn,
+ const Slapi_DN *gluedn, /* does not start with uniqueid= */
const char *reason,
- CSN *opcsn)
+ CSN *opcsn,
+ Slapi_DN **newparentdn)
{
Slapi_DN *parentdn;
char *parentuniqueid;
const char *tombstoneuniqueid;
- Slapi_Entry *addingentry;
+ Slapi_Entry *addingentry = NULL;
+ Slapi_Entry *addingentry_bakup = NULL;
const char *addingdn;
int op_result;
int rdn_is_conflict = 0;
@@ -164,23 +168,35 @@ tombstone_to_glue (
* must attach the entry to the Operation
*/
-
/* Resurrect the parent entry first */
/* JCM - This DN calculation is odd. It could resolve to NULL
* which won't help us identify the correct backend to search.
*/
- is_suffix_dn_ext (pb, tombstonedn, &parentdn, 1 /* is_tombstone */);
- parentuniqueid= slapi_entry_attr_get_charptr (tombstoneentry,
SLAPI_ATTR_VALUE_PARENT_UNIQUEID); /* Allocated */
- tombstone_to_glue_resolve_parent (pb, sessionid, parentdn, parentuniqueid, opcsn);
+ is_suffix_dn_ext (pb, gluedn, &parentdn, 1 /* is_tombstone */);
+ parentuniqueid = slapi_entry_attr_get_charptr (tombstoneentry,
SLAPI_ATTR_VALUE_PARENT_UNIQUEID); /* Allocated */
+ tombstone_to_glue_resolve_parent (pb, sessionid, parentdn, parentuniqueid, opcsn,
newparentdn);
/* Submit an Add operation to turn the tombstone entry into glue. */
/*
* The tombstone is stored with an invalid DN, we must fix this.
*/
addingentry = slapi_entry_dup(tombstoneentry);
- addingdn = slapi_sdn_get_dn(tombstonedn);
- slapi_entry_set_sdn(addingentry, tombstonedn);
+
+ if (newparentdn && *newparentdn && slapi_sdn_compare(parentdn,
*newparentdn)) {
+ /* If the parents are resolved, the tombstone's DN is going to be different... */
+ /* Update DN in addingentry */
+ Slapi_RDN *rdn = slapi_rdn_new();
+ slapi_rdn_set_dn_ext(rdn, slapi_sdn_get_dn(gluedn),
SLAPI_RDN_SET_DN_INCLUDE_UNIQUEID);
+ addingdn = slapi_moddn_get_newdn(slapi_entry_get_sdn(addingentry),
slapi_rdn_get_rdn(rdn),
+ slapi_sdn_get_dn(*newparentdn));
+ slapi_rdn_free(&rdn);
+ slapi_sdn_init_normdn_passin(*newparentdn, addingdn); /* to return the new parentdn to
the caller */
+ } else {
+ slapi_sdn_free(newparentdn); /* no change in parentdn; returning NULL */
+ addingdn = slapi_sdn_get_dn(gluedn);
+ }
+ slapi_sdn_set_normdn_byval(slapi_entry_get_sdn(addingentry), addingdn);
/* not just e_sdn, e_rsdn needs to be updated. */
slapi_rdn_set_all_dn(slapi_entry_get_srdn(addingentry),
slapi_entry_get_dn_const(addingentry));
rdn_is_conflict = slapi_rdn_is_conflict(slapi_entry_get_srdn(addingentry));
@@ -198,6 +214,7 @@ tombstone_to_glue (
* tombstoneentry from DB/entry cache is duplicated and turned to be a glue.
* This addingentry is freed in op_shared_add.
*/
+ addingentry_bakup = slapi_entry_dup(addingentry);
op_result = urp_fixup_add_entry (addingentry, tombstoneuniqueid,
slapi_ch_strdup(parentuniqueid), opcsn, OP_FLAG_RESURECT_ENTRY);
if ((LDAP_ALREADY_EXISTS == op_result) && !rdn_is_conflict) {
/* conflict -- there's already the same named entry added.
@@ -207,7 +224,8 @@ tombstone_to_glue (
* */
char *conflictrdn = get_rdn_plus_uniqueid(sessionid, addingdn, tombstoneuniqueid);
if (conflictrdn) {
- addingentry = slapi_entry_dup(tombstoneentry);
+ addingentry = addingentry_bakup;
+ addingentry_bakup = NULL;
if (!slapi_entry_attr_hasvalue(addingentry, ATTR_NSDS5_REPLCONFLICT, reason)) {
/* Add the reason of turning it to glue - The backend code will use it*/
slapi_entry_add_string(addingentry, ATTR_NSDS5_REPLCONFLICT, reason);
@@ -223,15 +241,16 @@ tombstone_to_glue (
addingentry = NULL;
}
}
+ slapi_entry_free(addingentry_bakup);
slapi_ch_free_string(&parentuniqueid);
if (op_result == LDAP_SUCCESS)
{
- slapi_log_error (slapi_log_urp, repl_plugin_name,
+ slapi_log_error (/*slapi_log_urp*/SLAPI_LOG_FATAL, repl_plugin_name,
"%s: Resurrected tombstone %s to glue reason '%s'\n", sessionid,
addingdn, reason);
}
else if (LDAP_ALREADY_EXISTS == op_result)
{
- slapi_log_error(slapi_log_urp, repl_plugin_name,
+ slapi_log_error(/*slapi_log_urp*/SLAPI_LOG_FATAL, repl_plugin_name,
"%s: No need to turn tombstone %s to glue; it was already
resurrected.\n",
sessionid, addingdn);
op_result = LDAP_SUCCESS;
diff --git a/ldap/servers/slapd/add.c b/ldap/servers/slapd/add.c
index 2a89358..4559951 100644
--- a/ldap/servers/slapd/add.c
+++ b/ldap/servers/slapd/add.c
@@ -737,9 +737,9 @@ static void op_shared_add (Slapi_PBlock *pb)
if (be->be_add != NULL)
{
- rc = (*be->be_add)(pb);
/* backend may change this if errors and not consumed */
slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &save_e);
+ rc = (*be->be_add)(pb);
slapi_pblock_set(pb, SLAPI_ADD_ENTRY, ec);
if (rc == 0)
{
diff --git a/ldap/servers/slapd/back-ldbm/cache.c b/ldap/servers/slapd/back-ldbm/cache.c
index 0309fcf..0732415 100644
--- a/ldap/servers/slapd/back-ldbm/cache.c
+++ b/ldap/servers/slapd/back-ldbm/cache.c
@@ -47,6 +47,7 @@
#ifdef DEBUG
#define LDAP_CACHE_DEBUG
/* #define LDAP_CACHE_DEBUG_LRU * causes slowdown */
+/* #define CACHE_DEBUG * causes slowdown */
#endif
/* cache can't get any smaller than this (in bytes) */
@@ -1341,14 +1342,14 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int
state,
{
if (my_alt->ep_state & ENTRY_STATE_CREATING)
{
- LOG("the entry %s is reserved (ep_state: 0x%x, state: 0x%x\n",
ndn, e->ep_state, state);
+ LOG("the entry %s is reserved (ep_state: 0x%x, state: 0x%x)\n",
ndn, e->ep_state, state);
e->ep_state |= ENTRY_STATE_NOTINCACHE;
PR_Unlock(cache->c_mutex);
return -1;
}
else if (state != 0)
{
- LOG("the entry %s already exists. cannot reserve it. (ep_state:
0x%x, state: 0x%x\n",
+ LOG("the entry %s already exists. cannot reserve it. (ep_state:
0x%x, state: 0x%x)\n",
ndn, e->ep_state, state);
e->ep_state |= ENTRY_STATE_NOTINCACHE;
PR_Unlock(cache->c_mutex);
@@ -1519,20 +1520,20 @@ int cache_lock_entry(struct cache *cache, struct backentry *e)
LOG("=> cache_lock_entry (%s)\n", backentry_get_ndn(e), 0, 0);
if (! e->ep_mutexp) {
- /* make sure only one thread does this */
- PR_Lock(cache->c_emutexalloc_mutex);
- if (! e->ep_mutexp) {
- e->ep_mutexp = PR_NewMonitor();
- if (!e->ep_mutexp) {
- LOG("<= cache_lock_entry (DELETED)\n", 0, 0, 0);
- LDAPDebug1Arg(LDAP_DEBUG_ANY,
- "cache_lock_entry: failed to create a lock for
%s\n",
- backentry_get_ndn(e));
- LOG("<= cache_lock_entry (FAILED)\n", 0, 0, 0);
- return 1;
- }
- }
- PR_Unlock(cache->c_emutexalloc_mutex);
+ /* make sure only one thread does this */
+ PR_Lock(cache->c_emutexalloc_mutex);
+ if (! e->ep_mutexp) {
+ e->ep_mutexp = PR_NewMonitor();
+ if (!e->ep_mutexp) {
+ LOG("<= cache_lock_entry (DELETED)\n", 0, 0, 0);
+ LDAPDebug1Arg(LDAP_DEBUG_ANY,
+ "cache_lock_entry: failed to create a lock for
%s\n",
+ backentry_get_ndn(e));
+ LOG("<= cache_lock_entry (FAILED)\n", 0, 0, 0);
+ return 1;
+ }
+ }
+ PR_Unlock(cache->c_emutexalloc_mutex);
}
/* wait on entry lock (done w/o holding the cache lock) */
@@ -2018,3 +2019,61 @@ dn_lru_verify(struct cache *cache, struct backdn *dn, int in)
ASSERT(is_in == in);
}
#endif
+
+#ifdef CACHE_DEBUG
+void
+check_entry_cache(struct cache *cache, struct backentry *e, int in_cache)
+{
+ Slapi_DN *sdn = slapi_entry_get_sdn(e->ep_entry);
+ struct backentry *debug_e = cache_find_dn(cache,
+ slapi_sdn_get_dn(sdn),
+ slapi_sdn_get_ndn_len(sdn));
+ if (in_cache) {
+ if (debug_e) { /* e is in cache */
+ CACHE_RETURN(cache, &debug_e);
+ if ((e != debug_e) && !(e->ep_state & ENTRY_STATE_DELETED)) {
+ slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete",
+ "entry 0x%p is not in dn cache but 0x%p having the same dn %s is
"
+ "although in_cache flag is set!!!\n",
+ e, debug_e, slapi_sdn_get_dn(sdn));
+ }
+ } else if (!(e->ep_state & ENTRY_STATE_DELETED)) {
+ slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete",
+ "%s (id %d) is not in dn cache although in_cache flag is
set!!!\n",
+ slapi_sdn_get_dn(sdn), e->ep_id);
+ }
+ debug_e = cache_find_id(cache, e->ep_id);
+ if (debug_e) { /* e is in cache */
+ CACHE_RETURN(cache, &debug_e);
+ if ((e != debug_e) && !(e->ep_state & ENTRY_STATE_DELETED)) {
+ slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete",
+ "entry 0x%p is not in id cache but 0x%p having the same id %d is
"
+ "although in_cache flag is set!!!\n",
+ e, debug_e, e->ep_id);
+ }
+ } else {
+ slapi_log_error(SLAPI_LOG_CACHE, "ldbm_back_delete",
+ "%s (id %d) is not in id cache although in_cache flag is
set!!!\n",
+ slapi_sdn_get_dn(sdn), e->ep_id);
+ }
+ } else {
+ if (debug_e) { /* e is in cache */
+ CACHE_RETURN(cache, &debug_e);
+ if (e == debug_e) {
+ slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete",
+ "%s (id %d) is in dn cache although in_cache flag is not
set!!!\n",
+ slapi_sdn_get_dn(sdn), e->ep_id);
+ }
+ }
+ debug_e = cache_find_id(cache, e->ep_id);
+ if (debug_e) { /* e is in cache: bad */
+ CACHE_RETURN(cache, &debug_e);
+ if (e == debug_e) {
+ slapi_log_error(SLAPI_LOG_CACHE, "ldbm_back_delete",
+ "%s (id %d) is in id cache although in_cache flag is not
set!!!\n",
+ slapi_sdn_get_dn(sdn), e->ep_id);
+ }
+ }
+ }
+}
+#endif
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c
b/ldap/servers/slapd/back-ldbm/ldbm_add.c
index e68c138..2d26e40 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c
@@ -119,7 +119,13 @@ ldbm_back_add( Slapi_PBlock *pb )
int not_an_error = 0;
int parent_switched = 0;
int noabort = 1;
-
+ int myrc = 0;
+ PRUint64 conn_id;
+ int op_id;
+ if (slapi_pblock_get(pb, SLAPI_CONN_ID, &conn_id) < 0) {
+ conn_id = 0; /* connection is NULL */
+ }
+ slapi_pblock_get(pb, SLAPI_OPERATION_ID, &op_id);
slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &e );
slapi_pblock_get( pb, SLAPI_REQUESTOR_ISROOT, &isroot );
@@ -811,6 +817,9 @@ ldbm_back_add( Slapi_PBlock *pb )
retval = parent_update_on_childchange(&parent_modify_c,
is_resurect_operation?PARENTUPDATE_RESURECT:PARENTUPDATE_ADD,
NULL);
+ slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_add",
+ "conn=%lu op=%d parent_update_on_childchange: old_entry=0x%p,
new_entry=0x%p, rc=%d\n",
+ conn_id, op_id, parent_modify_c.old_entry, parent_modify_c.new_entry,
retval);
/* The modify context now contains info needed later */
if (retval) {
LDAPDebug2Args(LDAP_DEBUG_BACKLDBM, "parent_update_on_childchange: %s,
rc=%d\n",
@@ -970,6 +979,9 @@ ldbm_back_add( Slapi_PBlock *pb )
if (parent_found) {
/* Push out the db modifications from the parent entry */
retval = modify_update_all(be,pb,&parent_modify_c,&txn);
+ slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_add",
+ "conn=%lu op=%d modify_update_all: old_entry=0x%p,
new_entry=0x%p, rc=%d\n",
+ conn_id, op_id, parent_modify_c.old_entry, parent_modify_c.new_entry,
retval);
if (DB_LOCK_DEADLOCK == retval)
{
LDAPDebug( LDAP_DEBUG_ARGS, "add 6 DEADLOCK\n", 0, 0, 0 );
@@ -1098,8 +1110,13 @@ ldbm_back_add( Slapi_PBlock *pb )
if (parent_found)
{
/* switch the parent entry copy into play */
- modify_switch_entries(&parent_modify_c,be);
- parent_switched = 1;
+ myrc = modify_switch_entries(&parent_modify_c,be);
+ slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_add",
+ "conn=%lu op=%d modify_switch_entries: old_entry=0x%p,
new_entry=0x%p, rc=%d\n",
+ conn_id, op_id, parent_modify_c.old_entry, parent_modify_c.new_entry,
myrc);
+ if (0 == myrc) {
+ parent_switched = 1;
+ }
}
if (ruv_c_init) {
@@ -1179,13 +1196,16 @@ error_return:
} else if (0 == rc) {
rc = SLAPI_FAIL_GENERAL;
}
- if (parent_switched){
+ if (parent_switched) {
/*
* Restore the old parent entry, switch the new with the original.
* Otherwise the numsubordinate count will be off, and could later
* be written to disk.
*/
- modify_unswitch_entries( &parent_modify_c,be);
+ myrc = modify_unswitch_entries(&parent_modify_c, be);
+ slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_add",
+ "conn=%lu op=%d modify_unswitch_entries: old_entry=0x%p,
new_entry=0x%p, rc=%d\n",
+ conn_id, op_id, parent_modify_c.old_entry, parent_modify_c.new_entry,
myrc);
}
diskfull_return:
if (disk_full) {
@@ -1282,7 +1302,10 @@ common_return:
if (ruv_c_init) {
modify_term(&ruv_c, be);
}
- modify_term(&parent_modify_c,be);
+ slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_add",
+ "conn=%lu op=%d modify_term: old_entry=0x%p,
new_entry=0x%p\n",
+ conn_id, op_id, parent_modify_c.old_entry, parent_modify_c.new_entry);
+ myrc = modify_term(&parent_modify_c,be);
done_with_pblock_entry(pb,SLAPI_ADD_EXISTING_DN_ENTRY);
done_with_pblock_entry(pb,SLAPI_ADD_EXISTING_UNIQUEID_ENTRY);
done_with_pblock_entry(pb,SLAPI_ADD_PARENT_ENTRY);
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
index 2a1730f..13a78fa 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
@@ -99,6 +99,14 @@ ldbm_back_delete( Slapi_PBlock *pb )
int opreturn = 0;
int free_delete_existing_entry = 0;
int not_an_error = 0;
+ int parent_switched = 0;
+ int myrc = 0;
+ PRUint64 conn_id;
+ int op_id;
+ if (slapi_pblock_get(pb, SLAPI_CONN_ID, &conn_id) < 0) {
+ conn_id = 0; /* connection is NULL */
+ }
+ slapi_pblock_get(pb, SLAPI_OPERATION_ID, &op_id);
slapi_pblock_get( pb, SLAPI_BACKEND, &be);
slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
@@ -292,8 +300,9 @@ ldbm_back_delete( Slapi_PBlock *pb )
retval = slapi_entry_has_children(e->ep_entry);
if (retval) {
ldap_result_code= LDAP_NOT_ALLOWED_ON_NONLEAF;
- slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete", "Deleting entry
%s has %d children.\n",
- slapi_entry_get_dn(e->ep_entry), retval);
+ slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete",
+ "conn=%lu op=%d Deleting entry %s has %d children.\n",
+ conn_id, op_id, slapi_entry_get_dn(e->ep_entry), retval);
retval = -1;
goto error_return;
}
@@ -539,6 +548,10 @@ ldbm_back_delete( Slapi_PBlock *pb )
op |= PARENTUPDATE_DELETE_TOMBSTONE;
}
retval = parent_update_on_childchange(&parent_modify_c, op, &haschildren);
+ slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_delete",
+ "conn=%lu op=%d parent_update_on_childchange: old_entry=0x%p,
new_entry=0x%p, rc=%d\n",
+ conn_id, op_id, parent_modify_c.old_entry,
parent_modify_c.new_entry, retval);
+
/* The modify context now contains info needed later */
if (0 != retval) {
ldap_result_code= LDAP_OPERATIONS_ERROR;
@@ -575,9 +588,11 @@ ldbm_back_delete( Slapi_PBlock *pb )
char *edn = slapi_entry_get_dn(e->ep_entry);
char *tombstone_dn;
Slapi_Value *tomb_value;
-
+
if (slapi_is_special_rdn(edn, RDN_IS_TOMBSTONE)) {
- LDAPDebug1Arg(LDAP_DEBUG_ANY, "Turning a tombstone into a tombstone!
\"%s\"\n", edn);
+ slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete",
+ "conn=%lu op=%d Turning a tombstone into a tombstone!
\"%s\"; e: 0x%p, cache_state: 0x%x, refcnt: %d\n",
+ conn_id, op_id, edn, e, e->ep_state, e->ep_refcnt);
ldap_result_code= LDAP_OPERATIONS_ERROR;
retval = -1;
goto error_return;
@@ -708,9 +723,9 @@ ldbm_back_delete( Slapi_PBlock *pb )
if (0 == retval) {
tombstone_in_cache = 1;
} else {
- LDAPDebug2Args(LDAP_DEBUG_ANY,
- "tombstone entry %s failed to add to the cache: %d\n",
- slapi_entry_get_dn(tombstone->ep_entry), retval);
+ slapi_log_error(SLAPI_LOG_CACHE, "ldbm_back_delete",
+ "conn=%lu op=%d tombstone entry %s failed to add to the cache:
%d\n",
+ conn_id, op_id, slapi_entry_get_dn(tombstone->ep_entry), retval);
tombstone_in_cache = 0;
if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
DEL_SET_ERROR(ldap_result_code,
@@ -1059,6 +1074,9 @@ ldbm_back_delete( Slapi_PBlock *pb )
if (parent_found) {
/* Push out the db modifications from the parent entry */
retval = modify_update_all(be,pb,&parent_modify_c,&txn);
+ slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_delete",
+ "conn=%lu op=%d modify_update_all: old_entry=0x%p,
new_entry=0x%p, rc=%d\n",
+ conn_id, op_id, parent_modify_c.old_entry, parent_modify_c.new_entry,
retval);
if (DB_LOCK_DEADLOCK == retval)
{
LDAPDebug( LDAP_DEBUG_BACKLDBM, "del 4 DEADLOCK\n", 0, 0, 0 );
@@ -1218,7 +1236,13 @@ ldbm_back_delete( Slapi_PBlock *pb )
if (parent_found)
{
/* Replace the old parent entry with the newly modified one */
- modify_switch_entries( &parent_modify_c,be);
+ myrc = modify_switch_entries( &parent_modify_c,be);
+ slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_delete",
+ "conn=%lu op=%d modify_switch_entries: old_entry=0x%p,
new_entry=0x%p, rc=%d\n",
+ conn_id, op_id, parent_modify_c.old_entry, parent_modify_c.new_entry,
myrc);
+ if (myrc == 0) {
+ parent_switched = 1;
+ }
}
rc= 0;
@@ -1233,6 +1257,9 @@ error_return:
CACHE_RETURN(&inst->inst_dncache, &bdn);
}
}
+#ifdef CACHE_DEBUG
+ check_entry_cache(&inst->inst_cache, tombstone, tombstone_in_cache);
+#endif
if (tombstone_in_cache) { /* successfully replaced */
CACHE_REMOVE( &inst->inst_cache, tombstone );
CACHE_RETURN( &inst->inst_cache, &tombstone );
@@ -1245,6 +1272,9 @@ error_return:
/* Need to return to cache after post op plugins are called */
if (e) {
+#ifdef CACHE_DEBUG
+ check_entry_cache(&inst->inst_cache, e, e_in_cache);
+#endif
if (e_in_cache) {
if (remove_e_from_cache) {
/* The entry is already transformed to a tombstone. */
@@ -1308,7 +1338,17 @@ error_return:
/* txn is no longer valid - reset the txn pointer to the parent */
slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
}
-
+ if (parent_switched) {
+ /*
+ * Restore the old parent entry, switch the new with the original.
+ * Otherwise the numsubordinate count will be off, and could later
+ * be written to disk.
+ */
+ myrc = modify_unswitch_entries(&parent_modify_c, be);
+ slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_delete",
+ "conn=%lu op=%d modify_unswitch_entries: old_entry=0x%p,
new_entry=0x%p, rc=%d\n",
+ conn_id, op_id, parent_modify_c.old_entry, parent_modify_c.new_entry,
myrc);
+ }
common_return:
if (orig_entry) {
/* NOTE: #define SLAPI_DELETE_BEPREOP_ENTRY SLAPI_ENTRY_PRE_OP */
@@ -1336,6 +1376,9 @@ common_return:
}
}
}
+#ifdef CACHE_DEBUG
+ check_entry_cache(&inst->inst_cache, tombstone, tombstone_in_cache);
+#endif
if (tombstone_in_cache) { /* successfully replaced */
CACHE_RETURN( &inst->inst_cache, &tombstone );
tombstone = NULL;
@@ -1385,7 +1428,10 @@ diskfull_return:
}
slapi_send_ldap_result( pb, ldap_result_code, NULL, ldap_result_message, 0, NULL );
}
- modify_term(&parent_modify_c, be);
+ slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_delete",
+ "conn=%lu op=%d modify_term: old_entry=0x%p, new_entry=0x%p,
in_cache=%d\n",
+ conn_id, op_id, parent_modify_c.old_entry, parent_modify_c.new_entry,
parent_modify_c.new_entry_in_cache);
+ myrc = modify_term(&parent_modify_c, be);
if (rc == 0 && opcsn && !is_fixup_operation &&
!delete_tombstone_entry)
{
/* URP Naming Collision
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
index 7d424fb..da6a127 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
@@ -140,7 +140,7 @@ modify_unswitch_entries(modify_context *mc,backend *be)
ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
int ret = 0;
- if (mc->old_entry!=NULL && mc->new_entry!=NULL) {
+ if (mc->old_entry && mc->new_entry && mc->new_entry_in_cache)
{
/* switch the entries, and reset the new, new, entry */
tmp_be = mc->new_entry;
mc->new_entry = mc->old_entry;
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
index 4bb4227..65880f9 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
@@ -123,6 +123,13 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
int opreturn = 0;
int free_modrdn_existing_entry = 0;
int not_an_error = 0;
+ int myrc = 0;
+ PRUint64 conn_id;
+ int op_id;
+ if (slapi_pblock_get(pb, SLAPI_CONN_ID, &conn_id) < 0) {
+ conn_id = 0; /* connection is NULL */
+ }
+ slapi_pblock_get(pb, SLAPI_OPERATION_ID, &op_id);
/* sdn & parentsdn need to be initialized before "goto *_return" */
slapi_sdn_init(&dn_newdn);
@@ -263,6 +270,9 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
slapi_sdn_free(&dn_newsuperiordn);
slapi_pblock_set(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, orig_dn_newsuperiordn);
orig_dn_newsuperiordn = slapi_sdn_dup(orig_dn_newsuperiordn);
+#ifdef CACHE_DEBUG
+ check_entry_cache(&inst->inst_cache, ec, ec_in_cache);
+#endif
if (ec_in_cache) {
/* New entry 'ec' is in the entry cache.
* Remove it from the cache . */
@@ -747,7 +757,8 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
ldap_result_code= LDAP_ALREADY_EXISTS;
if (is_resurect_operation) {
slapi_log_error(SLAPI_LOG_CACHE, "ldbm_back_modrdn",
- "cache_add_tentative failed: %s\n",
slapi_entry_get_dn(ec->ep_entry));
+ "conn=%lu op=%d cache_add_tentative failed:
%s\n",
+ conn_id, op_id,
slapi_entry_get_dn(ec->ep_entry));
}
goto error_return;
}
@@ -890,6 +901,10 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
if (parententry) {
retval = parent_update_on_childchange(&parent_modify_context,
PARENTUPDATE_DEL, NULL);
+ slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_modrdn",
+ "conn=%lu op=%d parent_update_on_childchange:
old_entry=0x%p, new_entry=0x%p, rc=%d\n",
+ conn_id, op_id, parent_modify_context.old_entry,
parent_modify_context.new_entry, retval);
+
/* The parent modify context now contains info needed later */
if (retval) {
goto error_return;
@@ -898,6 +913,9 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
if (newparententry) {
retval = parent_update_on_childchange(&newparent_modify_context,
PARENTUPDATE_ADD, NULL);
+ slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_modrdn",
+ "conn=%lu op=%d parent_update_on_childchange:
old_entry=0x%p, new_entry=0x%p, rc=%d\n",
+ conn_id, op_id, parent_modify_context.old_entry,
parent_modify_context.new_entry, retval);
/* The newparent modify context now contains info needed later */
if (retval) {
goto error_return;
@@ -908,9 +926,11 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
if (is_resurect_operation && parententry) {
retval = parent_update_on_childchange(&parent_modify_context,
PARENTUPDATE_RESURECT, NULL);
if (retval) {
- LDAPDebug(LDAP_DEBUG_BACKLDBM, "parent_update_on_childchange
parent %s of %s failed, rc=%d\n",
-
slapi_entry_get_dn_const(parent_modify_context.old_entry->ep_entry),
- slapi_entry_get_dn_const(ec->ep_entry), retval);
+ slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_modrdn",
+ "conn=%lu op=%d parent_update_on_childchange
parent %s of %s failed, rc=%d\n",
+ conn_id, op_id,
+
slapi_entry_get_dn_const(parent_modify_context.old_entry->ep_entry),
+ slapi_entry_get_dn_const(ec->ep_entry), retval);
goto error_return;
}
}
@@ -1096,6 +1116,9 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
else /* retval == 0 */
{
retval = modify_update_all(be, pb, &newparent_modify_context,
&txn);
+ slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_modrdn",
+ "conn=%lu op=%d modify_update_all: old_entry=0x%p,
new_entry=0x%p, rc=%d\n",
+ conn_id, op_id, parent_modify_context.old_entry,
parent_modify_context.new_entry, retval);
if (DB_LOCK_DEADLOCK == retval)
{
/* Retry txn */
@@ -1223,7 +1246,10 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
}
if(newparententry!=NULL)
{
- modify_switch_entries( &newparent_modify_context,be);
+ myrc = modify_switch_entries( &newparent_modify_context,be);
+ slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_modrdn",
+ "conn=%lu op=%d modify_switch_entries: old_entry=0x%p,
new_entry=0x%p, rc=%d\n",
+ conn_id, op_id, parent_modify_context.old_entry,
parent_modify_context.new_entry, myrc);
}
slapi_pblock_set( pb, SLAPI_ENTRY_POST_OP, postentry );
@@ -1446,6 +1472,9 @@ common_return:
}
/* remove the new entry from the cache if the op failed -
otherwise, leave it in */
+#ifdef CACHE_DEBUG
+ check_entry_cache(&inst->inst_cache, ec, ec_in_cache);
+#endif
if (ec_in_cache && ec && inst) {
if (retval) {
CACHE_REMOVE( &inst->inst_cache, ec );
@@ -1496,8 +1525,16 @@ common_return:
slapi_sdn_done(&dn_newdn);
slapi_sdn_done(&dn_newrdn);
slapi_sdn_done(&dn_parentdn);
- modify_term(&parent_modify_context,be);
- modify_term(&newparent_modify_context,be);
+ slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_modrdn",
+ "conn=%lu op=%d modify_term: old_entry=0x%p,
new_entry=0x%p\n",
+ conn_id, op_id, parent_modify_context.old_entry,
parent_modify_context.new_entry);
+ myrc = modify_term(&parent_modify_context,be);
+ slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_modrdn",
+ "conn=%lu op=%d modify_term: rc=%d\n", conn_id, op_id,
myrc);
+ slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_modrdn",
+ "conn=%lu op=%d modify_term: old_entry=0x%p,
new_entry=0x%p\n",
+ conn_id, op_id, newparent_modify_context.old_entry,
newparent_modify_context.new_entry);
+ myrc = modify_term(&newparent_modify_context,be);
if (free_modrdn_existing_entry) {
done_with_pblock_entry(pb,SLAPI_MODRDN_EXISTING_ENTRY);
} else { /* owned by original_entry */
@@ -1906,6 +1943,7 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb,
struct ldbm
retval= -1;
goto error_return;
}
+ *e_in_cache = 0;
if (orig_ec_in_cache) {
/* ec was already added to the cache via cache_add_tentative (to reserve its spot
in the cache)
and/or id2entry_add - so it already had one refcount - cache_replace adds
another refcount -
diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
index 732568d..180ad4c 100644
--- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
+++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
@@ -87,6 +87,9 @@ int cache_add_tentative(struct cache *cache, struct backentry *e,
int cache_lock_entry(struct cache *cache, struct backentry *e);
void cache_unlock_entry(struct cache *cache, struct backentry *e);
int cache_replace(struct cache *cache, void *oldptr, void *newptr);
+#ifdef CACHE_DEBUG
+void check_entry_cache(struct cache *cache, struct backentry *e, int in_cache);
+#endif
Hashtable *new_hash(u_long size, u_long offset, HashFn hfn,
HashTestFn tfn);
diff --git a/ldap/servers/slapd/dn.c b/ldap/servers/slapd/dn.c
index 2f1ae92..b197243 100644
--- a/ldap/servers/slapd/dn.c
+++ b/ldap/servers/slapd/dn.c
@@ -2431,6 +2431,12 @@ slapi_sdn_get_rdn(const Slapi_DN *sdn,Slapi_RDN *rdn)
slapi_rdn_set_dn(rdn, slapi_sdn_get_dn(sdn));
}
+void
+slapi_sdn_get_rdn_ext(const Slapi_DN *sdn, Slapi_RDN *rdn, int is_tombstone)
+{
+ slapi_rdn_set_dn_ext(rdn, slapi_sdn_get_dn(sdn), is_tombstone);
+}
+
Slapi_DN *
slapi_sdn_dup(const Slapi_DN *sdn)
{
diff --git a/ldap/servers/slapd/rdn.c b/ldap/servers/slapd/rdn.c
index 6e40ed8..d56c143 100644
--- a/ldap/servers/slapd/rdn.c
+++ b/ldap/servers/slapd/rdn.c
@@ -324,15 +324,29 @@ slapi_rdn_init_rdn(Slapi_RDN *rdn,const Slapi_RDN *fromrdn)
rdn->rdn= slapi_ch_strdup(fromrdn->rdn);
}
+/*
+ * flags:
+ * SLAPI_RDN_SET_DN_SKIP_UNIQUEID -- strip uniqueid, and set to rdn
+ * SLAPI_RDN_SET_DN_INCLUDE_UNIQUEID -- set <uniqueid,rdn> to rdn
+ */
void
-slapi_rdn_set_dn_ext(Slapi_RDN *rdn,const char *dn, int skip_tombstone)
+slapi_rdn_set_dn_ext(Slapi_RDN *rdn,const char *dn, int flags)
{
const char *mydn = dn;
slapi_rdn_done(rdn);
- if (skip_tombstone && slapi_is_special_rdn(dn, RDN_IS_TOMBSTONE)) {
- mydn = dn + slapi_uniqueIDRdnSize() + 1/*,*/;
+ if (flags && slapi_is_special_rdn(dn, RDN_IS_TOMBSTONE)) {
+ if (SLAPI_RDN_SET_DN_SKIP_UNIQUEID == flags) {
+ mydn = dn + slapi_uniqueIDRdnSize() + 1/*,*/;
+ slapi_rdn_init_dn(rdn, mydn);
+ } else if (SLAPI_RDN_SET_DN_INCLUDE_UNIQUEID == flags) {
+ Slapi_DN sdn = {0};
+ slapi_sdn_set_dn_byval(&sdn, dn);
+ _slapi_rdn_init_all_dn_ext(rdn, (const Slapi_DN *)&sdn, 1);
+ slapi_sdn_done(&sdn);
+ }
+ } else {
+ slapi_rdn_init_dn(rdn, mydn);
}
- slapi_rdn_init_dn(rdn, mydn);
}
void
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index bf10e45..a93feda 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -3044,7 +3044,9 @@ void slapi_rdn_init_rdn(Slapi_RDN *rdn,const Slapi_RDN *fromrdn);
* \see slapi_rdn_set_rdn()
*/
void slapi_rdn_set_dn(Slapi_RDN *rdn,const char *dn);
-void slapi_rdn_set_dn_ext(Slapi_RDN *rdn,const char *dn, int skip_tombstone);
+#define SLAPI_RDN_SET_DN_SKIP_UNIQUEID 1
+#define SLAPI_RDN_SET_DN_INCLUDE_UNIQUEID 2
+void slapi_rdn_set_dn_ext(Slapi_RDN *rdn,const char *dn, int flags);
Slapi_RDN *slapi_rdn_new_all_dn(const char *dn);
int slapi_rdn_init_all_dn(Slapi_RDN *rdn, const char *dn);
int slapi_rdn_init_all_sdn(Slapi_RDN *rdn, const Slapi_DN *sdn);