|
|
dc8c34 |
From 7299b3561fa579b6b90bbf3becc821b91429c9ac Mon Sep 17 00:00:00 2001
|
|
|
dc8c34 |
From: Noriko Hosoi <nhosoi@redhat.com>
|
|
|
dc8c34 |
Date: Fri, 9 May 2014 09:53:36 -0700
|
|
|
dc8c34 |
Subject: [PATCH 209/225] Ticket #47750 - Creating a glue fails if one above
|
|
|
dc8c34 |
level is a conflict or missing
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Including the fix for Ticket #47696 - Large Searches Hang - Possibly entryrdn related
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Bug Descriptions:
|
|
|
dc8c34 |
There were multiple issues to break the parent-child relationship when a
|
|
|
dc8c34 |
resurrect occurred.
|
|
|
dc8c34 |
When resurrecting a tombstone, there is a possibility that an entry having
|
|
|
dc8c34 |
the same name was already added. In the case, the code consdered the entry
|
|
|
dc8c34 |
is already there, which confused the numsubordinates and tombstone-num-
|
|
|
dc8c34 |
subordinates count. If it is detected, it creates a conflict glue entry
|
|
|
dc8c34 |
instead of a pure glue entry. The 2 numsubordinates counts were also not
|
|
|
dc8c34 |
correctly updated in the resurrection case. When the entryrdn was introduced,
|
|
|
dc8c34 |
Slapi_RDN was held in the entry, which was not correctly updated in the
|
|
|
dc8c34 |
resurrect case.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Fix Descriptions:
|
|
|
dc8c34 |
[replication/urp.c]
|
|
|
dc8c34 |
urp_fixup_rename_entry sets the parent uniqueid if it is a RESURRECT mode
|
|
|
dc8c34 |
(called from tombstone_to_glue) as being done in urp_fixup_add_entry, which
|
|
|
dc8c34 |
is necessary to retrieve the correct parent in ldbm_back_modrdn.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
[replication/urp_glue.c]
|
|
|
dc8c34 |
In create_glue_entry,
|
|
|
dc8c34 |
. there was a possibility to pass a tombstone DN (nsuniqueid=...,<DN>) is
|
|
|
dc8c34 |
used to create a glue entry. If found, the part is removed before passing
|
|
|
dc8c34 |
it to create a glue entry.
|
|
|
dc8c34 |
. there is a possibility to create a glue entry fails due to the parent entry
|
|
|
dc8c34 |
not found. This occurs when the parent entry has turned to be a conflict
|
|
|
dc8c34 |
entry. In the case, instead of retrying the glue creation, it logs an
|
|
|
dc8c34 |
error and returns.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
[replication/urp_tombstone.c]
|
|
|
dc8c34 |
In tombstone_to_glue,
|
|
|
dc8c34 |
. turning a tombstone to an ordinary glue entry could fail with the entry
|
|
|
dc8c34 |
already exists. (Note: ldbm_back_add guarantees that the found entry has
|
|
|
dc8c34 |
a different nsuniqueid from this tombstone has.) This situation occurs an
|
|
|
dc8c34 |
entry having the same dn could have been added/replicated by this moment.
|
|
|
dc8c34 |
And the entry cannot be used for this tombstone to resurrect since the
|
|
|
dc8c34 |
subordinates/tombstonesubordinates relationships get corrupted. To maintain
|
|
|
dc8c34 |
the relationship properly, the tombstone is resurrected as a conflict, glue
|
|
|
dc8c34 |
entry using urp_fixup_rename_entry. If it still returns LDAP_ALREADY_EXISTS,
|
|
|
dc8c34 |
it is assured the expected glue entry exists since the same nsuniqueid is
|
|
|
dc8c34 |
shared.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
[slapd/back-ldbm/ldbm_add.c]
|
|
|
dc8c34 |
In ldbm_back_add,
|
|
|
dc8c34 |
. in is_resurect_operation case, a SLAPI_ADD_EXISTING_DN_ENTRY entry and a
|
|
|
dc8c34 |
SLAPI_ADD_EXISTING_UNIQUEID_ENTRY entry are identical, it returns SUCCESS
|
|
|
dc8c34 |
instead of LDAP_ALREADY_EXISTS.
|
|
|
dc8c34 |
. in is_resurect_operation case, the DN is modified from the tombstone DN
|
|
|
dc8c34 |
to the ordinary DN. The DN is stored in e_sdn as well as in e_srdn in the
|
|
|
dc8c34 |
Slapi_Entry. The e_srdn part was not updated. This patch fixes it and
|
|
|
dc8c34 |
e_sdn and e_srdn are in sync.
|
|
|
dc8c34 |
. parent_update_on_childchange adjusts the count of numsubordinates and
|
|
|
dc8c34 |
tombstonenumsubordinates. It only took PARENTUPDATE_ADD|_DELETE operations.
|
|
|
dc8c34 |
This patch adds PARENTUPDATE_RESURECT operation to increment numsubordinates
|
|
|
dc8c34 |
and decrement tombstonenumsubordinates at the same time.
|
|
|
dc8c34 |
. in is_resurect_operation case, a tombstone to be replaced with a glue entry
|
|
|
dc8c34 |
needs to be deleted from the entryrdn index, which was missing.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
[slapd/back-ldbm/ldbm_delete.c]
|
|
|
dc8c34 |
. Check the target DN if it starts with "nsuniqueid=...,", if it is, log an
|
|
|
dc8c34 |
error and returns.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
[slapd/back-ldbm/ldbm_modrdn.c]
|
|
|
dc8c34 |
. If it is is_resurect_operation case, it allows to rename a tombstone entry.
|
|
|
dc8c34 |
This is used to support to change a tombstone entry to a conflict glue entry
|
|
|
dc8c34 |
in tombstone_to_glue.
|
|
|
dc8c34 |
. ldbm_back_modify checks if the renamed entry has children or not and if
|
|
|
dc8c34 |
there are, they are updated to point to the renamed entry. The check
|
|
|
dc8c34 |
function slapi_entry_has_children was just checking the numsubordinates
|
|
|
dc8c34 |
attribute type. If a positive value is returned, it took care all the
|
|
|
dc8c34 |
children including the tombstones, but if the renamed entry had tombstoned
|
|
|
dc8c34 |
children only, it considered there were no children and the tombstoned
|
|
|
dc8c34 |
children were not updated to point the renamed entry. This patch fixes it.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
[slapd/back-ldbm/ldbm_entryrdn.c]
|
|
|
dc8c34 |
. Added a flag to entryrdn_rename_subtree and entryrdn_get_subordinates to
|
|
|
dc8c34 |
treat the given DN a tombstoned DN if it is.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
In addition, helper APIs such as slapi_rdn_is_multivalued and slapi_rdn_is_
|
|
|
dc8c34 |
conflict, and slapi_is_special_rdn are added.
|
|
|
dc8c34 |
|
|
|
dc8c34 |
https://fedorahosted.org/389/ticket/47750
|
|
|
dc8c34 |
|
|
|
dc8c34 |
Reviewed by mreynolds@redhat.com (Thank you, Mark!!)
|
|
|
dc8c34 |
(cherry picked from commit 9e5b3332cc33167837fce0477c8a4d0edc42f0db)
|
|
|
dc8c34 |
---
|
|
|
dc8c34 |
ldap/servers/plugins/replication/repl5.h | 1 +
|
|
|
dc8c34 |
ldap/servers/plugins/replication/urp.c | 79 +++--
|
|
|
dc8c34 |
ldap/servers/plugins/replication/urp.h | 5 +-
|
|
|
dc8c34 |
ldap/servers/plugins/replication/urp_glue.c | 32 +-
|
|
|
dc8c34 |
ldap/servers/plugins/replication/urp_tombstone.c | 55 +++-
|
|
|
dc8c34 |
ldap/servers/slapd/add.c | 15 +-
|
|
|
dc8c34 |
ldap/servers/slapd/back-ldbm/back-ldbm.h | 3 +-
|
|
|
dc8c34 |
ldap/servers/slapd/back-ldbm/backentry.c | 1 +
|
|
|
dc8c34 |
ldap/servers/slapd/back-ldbm/cache.c | 103 ++++---
|
|
|
dc8c34 |
ldap/servers/slapd/back-ldbm/ldbm_add.c | 362 ++++++++++++++---------
|
|
|
dc8c34 |
ldap/servers/slapd/back-ldbm/ldbm_delete.c | 337 ++++++++++++++-------
|
|
|
dc8c34 |
ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c | 12 +-
|
|
|
dc8c34 |
ldap/servers/slapd/back-ldbm/ldbm_modify.c | 41 ++-
|
|
|
dc8c34 |
ldap/servers/slapd/back-ldbm/ldbm_modrdn.c | 281 ++++++++++++++----
|
|
|
dc8c34 |
ldap/servers/slapd/back-ldbm/ldbm_search.c | 2 +-
|
|
|
dc8c34 |
ldap/servers/slapd/back-ldbm/ldif2ldbm.c | 2 +-
|
|
|
dc8c34 |
ldap/servers/slapd/back-ldbm/parents.c | 31 +-
|
|
|
dc8c34 |
ldap/servers/slapd/back-ldbm/proto-back-ldbm.h | 5 +-
|
|
|
dc8c34 |
ldap/servers/slapd/entry.c | 38 ++-
|
|
|
dc8c34 |
ldap/servers/slapd/rdn.c | 108 ++++++-
|
|
|
dc8c34 |
ldap/servers/slapd/slapi-plugin.h | 45 +++
|
|
|
dc8c34 |
ldap/servers/slapd/slapi-private.h | 7 +
|
|
|
dc8c34 |
ldap/servers/slapd/util.c | 67 +++++
|
|
|
dc8c34 |
23 files changed, 1184 insertions(+), 448 deletions(-)
|
|
|
dc8c34 |
|
|
|
dc8c34 |
diff --git a/ldap/servers/plugins/replication/repl5.h b/ldap/servers/plugins/replication/repl5.h
|
|
|
dc8c34 |
index b10b358..a5761be 100644
|
|
|
dc8c34 |
--- a/ldap/servers/plugins/replication/repl5.h
|
|
|
dc8c34 |
+++ b/ldap/servers/plugins/replication/repl5.h
|
|
|
dc8c34 |
@@ -60,6 +60,7 @@
|
|
|
dc8c34 |
#include "llist.h"
|
|
|
dc8c34 |
#include "repl5_ruv.h"
|
|
|
dc8c34 |
#include "cl4.h"
|
|
|
dc8c34 |
+#include "plstr.h"
|
|
|
dc8c34 |
|
|
|
dc8c34 |
#define REPLICA_TYPE_WINDOWS 1
|
|
|
dc8c34 |
#define REPLICA_TYPE_MULTIMASTER 0
|
|
|
dc8c34 |
diff --git a/ldap/servers/plugins/replication/urp.c b/ldap/servers/plugins/replication/urp.c
|
|
|
dc8c34 |
index 9787ff7..0182af3 100644
|
|
|
dc8c34 |
--- a/ldap/servers/plugins/replication/urp.c
|
|
|
dc8c34 |
+++ b/ldap/servers/plugins/replication/urp.c
|
|
|
dc8c34 |
@@ -58,7 +58,6 @@ static int urp_naming_conflict_removal (Slapi_PBlock *pb, char *sessionid, CSN *
|
|
|
dc8c34 |
static int mod_namingconflict_attr (const char *uniqueid, const Slapi_DN *entrysdn, const Slapi_DN *conflictsdn, CSN *opcsn);
|
|
|
dc8c34 |
static int del_replconflict_attr (Slapi_Entry *entry, CSN *opcsn, int opflags);
|
|
|
dc8c34 |
static char *get_dn_plus_uniqueid(char *sessionid,const Slapi_DN *oldsdn,const char *uniqueid);
|
|
|
dc8c34 |
-static char *get_rdn_plus_uniqueid(char *sessionid,const char *olddn,const char *uniqueid);
|
|
|
dc8c34 |
static int is_suffix_entry (Slapi_PBlock *pb, Slapi_Entry *entry, Slapi_DN **parenddn);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
@@ -372,6 +371,9 @@ urp_modrdn_operation( Slapi_PBlock *pb )
|
|
|
dc8c34 |
slapi_entry_get_sdn (target_entry), "renameTombstone", opcsn);
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
op_result = LDAP_NO_SUCH_OBJECT;
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_REPL, sessionid,
|
|
|
dc8c34 |
+ "urp_modrdn: target_entry %s is a tombstone; returning NO_SUCH_OBJECT.\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(target_entry));
|
|
|
dc8c34 |
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
|
|
|
dc8c34 |
if (op_result == 0)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
@@ -448,16 +450,16 @@ urp_modrdn_operation( Slapi_PBlock *pb )
|
|
|
dc8c34 |
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
|
|
|
dc8c34 |
rc= -1; /* Ignore this Operation */
|
|
|
dc8c34 |
PROFILE_POINT; /* ModRDN Conflict; Entry with Target DN Exists;
|
|
|
dc8c34 |
- Unique ID already in RDN - Change to Lost and Found entry */
|
|
|
dc8c34 |
+ Unique ID already in RDN - Change to Lost and Found entry */
|
|
|
dc8c34 |
goto bailout;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
mod_namingconflict_attr (op_uniqueid, target_sdn, existing_sdn, opcsn);
|
|
|
dc8c34 |
slapi_pblock_set(pb, SLAPI_MODRDN_NEWRDN, newrdn_with_uniqueid);
|
|
|
dc8c34 |
slapi_log_error(slapi_log_urp, sessionid,
|
|
|
dc8c34 |
- "Naming conflict MODRDN. Rename target entry to %s\n",
|
|
|
dc8c34 |
- newrdn_with_uniqueid );
|
|
|
dc8c34 |
+ "urp_modrdn_operation: Naming conflict MODRDN. Rename target entry from %s to %s\n",
|
|
|
dc8c34 |
+ newrdn, newrdn_with_uniqueid );
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- rc= slapi_setbit_int(rc,SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
|
|
|
dc8c34 |
+ rc= slapi_setbit_int(rc, SLAPI_RTN_BIT_FETCH_EXISTING_DN_ENTRY);
|
|
|
dc8c34 |
PROFILE_POINT; /* ModRDN Conflict; Entry with Target DN Exists; Rename Operation Entry */
|
|
|
dc8c34 |
goto bailout;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -608,14 +610,20 @@ urp_delete_operation( Slapi_PBlock *pb )
|
|
|
dc8c34 |
op_result= LDAP_NO_SUCH_OBJECT;
|
|
|
dc8c34 |
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
|
|
|
dc8c34 |
rc= -1; /* Don't apply the Delete */
|
|
|
dc8c34 |
+ slapi_log_error(slapi_log_urp, "no sessionid",
|
|
|
dc8c34 |
+ "Entry %s does not exist; returning NO_SUCH_OBJECT.\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(deleteentry));
|
|
|
dc8c34 |
PROFILE_POINT; /* Delete Operation; Entry not exist. */
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
else if(is_tombstone_entry(deleteentry))
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
/* The entry is already a Tombstone, ignore this delete. */
|
|
|
dc8c34 |
- op_result= LDAP_SUCCESS;
|
|
|
dc8c34 |
+ op_result= LDAP_ALREADY_EXISTS;
|
|
|
dc8c34 |
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
|
|
|
dc8c34 |
rc = -1; /* Don't apply the Delete */
|
|
|
dc8c34 |
+ slapi_log_error(slapi_log_urp, "no sessionid",
|
|
|
dc8c34 |
+ "Entry %s is already a tombstone; returning ALREADY_EXISTS.\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(deleteentry));
|
|
|
dc8c34 |
PROFILE_POINT; /* Delete Operation; Already a Tombstone. */
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
else /* The entry to be deleted exists and is not a tombstone */
|
|
|
dc8c34 |
@@ -639,7 +647,10 @@ urp_delete_operation( Slapi_PBlock *pb )
|
|
|
dc8c34 |
op_result= LDAP_SUCCESS;
|
|
|
dc8c34 |
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &op_result);
|
|
|
dc8c34 |
rc = -1; /* Don't apply the Delete */
|
|
|
dc8c34 |
- PROFILE_POINT; /* Delete Operation; Entry has children. */
|
|
|
dc8c34 |
+ slapi_log_error(slapi_log_urp, sessionid,
|
|
|
dc8c34 |
+ "Entry %s was turned to a glue; returning SUCCESS.\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(deleteentry) );
|
|
|
dc8c34 |
+ PROFILE_POINT; /* Delete Operation; Entry has children. */
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
return rc;
|
|
|
dc8c34 |
@@ -785,7 +796,7 @@ urp_fixup_add_entry (Slapi_Entry *e, const char *target_uniqueid, const char *pa
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
int
|
|
|
dc8c34 |
-urp_fixup_rename_entry (Slapi_Entry *entry, const char *newrdn, int opflags)
|
|
|
dc8c34 |
+urp_fixup_rename_entry (Slapi_Entry *entry, const char *newrdn, const char *parentuniqueid, int opflags)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
Slapi_PBlock *newpb;
|
|
|
dc8c34 |
Slapi_Operation *op;
|
|
|
dc8c34 |
@@ -813,7 +824,12 @@ urp_fixup_rename_entry (Slapi_Entry *entry, const char *newrdn, int opflags)
|
|
|
dc8c34 |
opcsn = (CSN *)entry_get_dncsn (entry);
|
|
|
dc8c34 |
slapi_pblock_get (newpb, SLAPI_OPERATION, &op);
|
|
|
dc8c34 |
operation_set_csn (op, opcsn);
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
+ if (parentuniqueid)
|
|
|
dc8c34 |
+ {
|
|
|
dc8c34 |
+ struct slapi_operation_parameters *op_params;
|
|
|
dc8c34 |
+ slapi_pblock_get( newpb, SLAPI_OPERATION_PARAMETERS, &op_params );
|
|
|
dc8c34 |
+ op_params->p.p_modrdn.modrdn_newsuperior_address.uniqueid = (char*)parentuniqueid; /* Consumes parentuniqueid */
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
slapi_modrdn_internal_pb(newpb);
|
|
|
dc8c34 |
slapi_pblock_get(newpb, SLAPI_PLUGIN_INTOP_RESULT, &op_result);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -1012,7 +1028,7 @@ urp_annotate_dn (char *sessionid, Slapi_Entry *entry, CSN *opcsn, const char *op
|
|
|
dc8c34 |
if(newrdn!=NULL)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
mod_namingconflict_attr (uniqueid, basesdn, basesdn, opcsn);
|
|
|
dc8c34 |
- op_result = urp_fixup_rename_entry ( entry, newrdn, 0 );
|
|
|
dc8c34 |
+ op_result = urp_fixup_rename_entry ( entry, newrdn, NULL, 0 );
|
|
|
dc8c34 |
switch(op_result)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
case LDAP_SUCCESS:
|
|
|
dc8c34 |
@@ -1191,7 +1207,7 @@ urp_naming_conflict_removal ( Slapi_PBlock *pb, char *sessionid, CSN *opcsn, con
|
|
|
dc8c34 |
* is done after DB lock was released. The backend modrdn
|
|
|
dc8c34 |
* will acquire the DB lock if it sees this flag.
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
- op_result = urp_fixup_rename_entry (min_naming_conflict_entry, newrdnstr, OP_FLAG_ACTION_INVOKE_FOR_REPLOP);
|
|
|
dc8c34 |
+ op_result = urp_fixup_rename_entry (min_naming_conflict_entry, newrdnstr, NULL, OP_FLAG_ACTION_INVOKE_FOR_REPLOP);
|
|
|
dc8c34 |
if ( op_result != LDAP_SUCCESS )
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
slapi_log_error (slapi_log_urp, sessionid,
|
|
|
dc8c34 |
@@ -1224,15 +1240,19 @@ bailout:
|
|
|
dc8c34 |
static char *
|
|
|
dc8c34 |
get_dn_plus_uniqueid(char *sessionid, const Slapi_DN *oldsdn, const char *uniqueid)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- Slapi_RDN *rdn= slapi_rdn_new();
|
|
|
dc8c34 |
- char *newdn;
|
|
|
dc8c34 |
+ Slapi_RDN *rdn = slapi_rdn_new();
|
|
|
dc8c34 |
+ char *newdn = NULL;
|
|
|
dc8c34 |
+ int rc = slapi_rdn_init_all_sdn_ext(rdn, oldsdn, 1);
|
|
|
dc8c34 |
+ if (rc) {
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, sessionid,
|
|
|
dc8c34 |
+ "Failed to convert %s to RDN\n", slapi_sdn_get_dn(oldsdn));
|
|
|
dc8c34 |
+ goto bail;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
|
|
|
dc8c34 |
PR_ASSERT(uniqueid!=NULL);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* Check if the RDN already contains the Unique ID */
|
|
|
dc8c34 |
- slapi_rdn_set_dn(rdn, slapi_sdn_get_dn(oldsdn));
|
|
|
dc8c34 |
- if(slapi_rdn_contains(rdn,SLAPI_ATTR_UNIQUEID,uniqueid,strlen(uniqueid)))
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
+ if (slapi_rdn_is_conflict(rdn)) {
|
|
|
dc8c34 |
/* The Unique ID is already in the RDN.
|
|
|
dc8c34 |
* This is a highly improbable collision.
|
|
|
dc8c34 |
* It suggests that a duplicate UUID was generated.
|
|
|
dc8c34 |
@@ -1241,7 +1261,6 @@ get_dn_plus_uniqueid(char *sessionid, const Slapi_DN *oldsdn, const char *unique
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
slapi_log_error(SLAPI_LOG_FATAL, sessionid,
|
|
|
dc8c34 |
"Annotated DN %s has naming conflict\n", slapi_sdn_get_dn(oldsdn) );
|
|
|
dc8c34 |
- newdn= NULL;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
else
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
@@ -1250,21 +1269,27 @@ get_dn_plus_uniqueid(char *sessionid, const Slapi_DN *oldsdn, const char *unique
|
|
|
dc8c34 |
newdn = slapi_ch_smprintf("%s,%s", slapi_rdn_get_rdn(rdn), parentdn);
|
|
|
dc8c34 |
slapi_ch_free_string(&parentdn);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+bail:
|
|
|
dc8c34 |
slapi_rdn_free(&rdn;;
|
|
|
dc8c34 |
return newdn;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
-static char *
|
|
|
dc8c34 |
+char *
|
|
|
dc8c34 |
get_rdn_plus_uniqueid(char *sessionid, const char *olddn, const char *uniqueid)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- char *newrdn;
|
|
|
dc8c34 |
+ char *newrdn = NULL;
|
|
|
dc8c34 |
/* Check if the RDN already contains the Unique ID */
|
|
|
dc8c34 |
- Slapi_DN *sdn= slapi_sdn_new_dn_byval(olddn);
|
|
|
dc8c34 |
- Slapi_RDN *rdn= slapi_rdn_new();
|
|
|
dc8c34 |
- slapi_sdn_get_rdn(sdn,rdn);
|
|
|
dc8c34 |
+ Slapi_DN *sdn = slapi_sdn_new_dn_byval(olddn);
|
|
|
dc8c34 |
+ Slapi_RDN *rdn = slapi_rdn_new();
|
|
|
dc8c34 |
+ int rc = slapi_rdn_init_all_sdn_ext(rdn, sdn, 1);
|
|
|
dc8c34 |
+ if (rc) {
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, sessionid,
|
|
|
dc8c34 |
+ "Failed to convert %s to RDN\n", olddn);
|
|
|
dc8c34 |
+ goto bail;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
PR_ASSERT(uniqueid!=NULL);
|
|
|
dc8c34 |
- if(slapi_rdn_contains(rdn,SLAPI_ATTR_UNIQUEID,uniqueid,strlen(uniqueid)))
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
+ if (slapi_rdn_is_conflict(rdn)) {
|
|
|
dc8c34 |
/* The Unique ID is already in the RDN.
|
|
|
dc8c34 |
* This is a highly improbable collision.
|
|
|
dc8c34 |
* It suggests that a duplicate UUID was generated.
|
|
|
dc8c34 |
@@ -1272,14 +1297,14 @@ get_rdn_plus_uniqueid(char *sessionid, const char *olddn, const char *uniqueid)
|
|
|
dc8c34 |
* require admin intercession
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
slapi_log_error(SLAPI_LOG_FATAL, sessionid,
|
|
|
dc8c34 |
- "Annotated DN %s has naming conflict\n", olddn );
|
|
|
dc8c34 |
- newrdn= NULL;
|
|
|
dc8c34 |
+ "Annotated RDN %s has naming conflict\n", olddn);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
else
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
slapi_rdn_add(rdn,SLAPI_ATTR_UNIQUEID,uniqueid);
|
|
|
dc8c34 |
- newrdn= slapi_ch_strdup(slapi_rdn_get_rdn(rdn));
|
|
|
dc8c34 |
+ newrdn = slapi_ch_strdup(slapi_rdn_get_rdn(rdn));
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+bail:
|
|
|
dc8c34 |
slapi_sdn_free(&sdn;;
|
|
|
dc8c34 |
slapi_rdn_free(&rdn;;
|
|
|
dc8c34 |
return newrdn;
|
|
|
dc8c34 |
diff --git a/ldap/servers/plugins/replication/urp.h b/ldap/servers/plugins/replication/urp.h
|
|
|
dc8c34 |
index ec7c94d..c7d8ca5 100644
|
|
|
dc8c34 |
--- a/ldap/servers/plugins/replication/urp.h
|
|
|
dc8c34 |
+++ b/ldap/servers/plugins/replication/urp.h
|
|
|
dc8c34 |
@@ -55,11 +55,12 @@ int urp_delete_operation( Slapi_PBlock *pb );
|
|
|
dc8c34 |
int urp_post_delete_operation( Slapi_PBlock *pb );
|
|
|
dc8c34 |
int urp_modrdn_operation( Slapi_PBlock *pb );
|
|
|
dc8c34 |
int urp_post_modrdn_operation( Slapi_PBlock *pb );
|
|
|
dc8c34 |
+char *get_rdn_plus_uniqueid(char *sessionid, const char *olddn, const char *uniqueid);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* urp internal ops */
|
|
|
dc8c34 |
int urp_fixup_add_entry (Slapi_Entry *e, const char *target_uniqueid, const char *parentuniqueid, CSN *opcsn, int opflags);
|
|
|
dc8c34 |
int urp_fixup_delete_entry (const char *uniqueid, const char *dn, CSN *opcsn, int opflags);
|
|
|
dc8c34 |
-int urp_fixup_rename_entry (Slapi_Entry *entry, const char *newrdn, int opflags);
|
|
|
dc8c34 |
+int urp_fixup_rename_entry (Slapi_Entry *entry, const char *newrdn, const char *parentuniqueid, int opflags);
|
|
|
dc8c34 |
int urp_fixup_modify_entry (const char *uniqueid, const Slapi_DN *sdn, CSN *opcsn, Slapi_Mods *smods, int opflags);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
int is_suffix_dn (Slapi_PBlock *pb, const Slapi_DN *dn, Slapi_DN **parenddn);
|
|
|
dc8c34 |
@@ -78,6 +79,6 @@ PRBool get_glue_csn(const Slapi_Entry *entry, const CSN **gluecsn);
|
|
|
dc8c34 |
* urp_tombstone.c
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
int is_tombstone_entry(const Slapi_Entry* entry);
|
|
|
dc8c34 |
-int tombstone_to_glue(Slapi_PBlock *pb, const char *sessionid, Slapi_Entry *entry, const Slapi_DN *parentdn, const char *reason, CSN *opcsn);
|
|
|
dc8c34 |
+int tombstone_to_glue(Slapi_PBlock *pb, char *sessionid, Slapi_Entry *entry, const Slapi_DN *parentdn, const char *reason, CSN *opcsn);
|
|
|
dc8c34 |
int entry_to_tombstone ( Slapi_PBlock *pb, Slapi_Entry *entry );
|
|
|
dc8c34 |
PRBool get_tombstone_csn(const Slapi_Entry *entry, const CSN **delcsn);
|
|
|
dc8c34 |
diff --git a/ldap/servers/plugins/replication/urp_glue.c b/ldap/servers/plugins/replication/urp_glue.c
|
|
|
dc8c34 |
index 6eeb826..199d4de 100644
|
|
|
dc8c34 |
--- a/ldap/servers/plugins/replication/urp_glue.c
|
|
|
dc8c34 |
+++ b/ldap/servers/plugins/replication/urp_glue.c
|
|
|
dc8c34 |
@@ -153,7 +153,7 @@ static const char *glue_entry =
|
|
|
dc8c34 |
"objectclass: top\n"
|
|
|
dc8c34 |
"objectclass: extensibleObject\n" /* JCMREPL - To avoid schema checking. */
|
|
|
dc8c34 |
"objectclass: glue\n"
|
|
|
dc8c34 |
- "nsuniqueid: %s\n"
|
|
|
dc8c34 |
+ "nsuniqueid: %s\n" /* this uniqueid is set to Slapi_Entry in slapi_str2entry. */
|
|
|
dc8c34 |
"%s: %s\n"; /* Add why it's been created */
|
|
|
dc8c34 |
|
|
|
dc8c34 |
static int
|
|
|
dc8c34 |
@@ -166,15 +166,15 @@ do_create_glue_entry(const Slapi_RDN *rdn, const Slapi_DN *superiordn, const cha
|
|
|
dc8c34 |
Slapi_DN *sdn = NULL;
|
|
|
dc8c34 |
Slapi_RDN *newrdn = slapi_rdn_new_rdn(rdn);
|
|
|
dc8c34 |
char *estr, *rdnstr, *rdntype, *rdnval, *rdnpair;
|
|
|
dc8c34 |
- sdn = slapi_sdn_new_dn_byval(slapi_sdn_get_ndn(superiordn));
|
|
|
dc8c34 |
+ sdn = slapi_sdn_new_ndn_byval(slapi_sdn_get_ndn(superiordn));
|
|
|
dc8c34 |
slapi_sdn_add_rdn(sdn,rdn);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* must take care of multi-valued rdn: split rdn into different lines introducing
|
|
|
dc8c34 |
* '\n' between each type/value pair.
|
|
|
dc8c34 |
- */
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
alloc_len = RDNBUFSIZE;
|
|
|
dc8c34 |
rdnstr = slapi_ch_malloc(alloc_len);
|
|
|
dc8c34 |
- rdnpair = rdnstr;
|
|
|
dc8c34 |
+ rdnpair = rdnstr;
|
|
|
dc8c34 |
*rdnpair = '\0'; /* so that strlen(rdnstr) may return 0 the first time it's called */
|
|
|
dc8c34 |
while ((rdnval_index = slapi_rdn_get_next(newrdn, rdnval_index, &rdntype, &rdnval)) != -1) {
|
|
|
dc8c34 |
rdntype_len = strlen(rdntype);
|
|
|
dc8c34 |
@@ -188,7 +188,7 @@ do_create_glue_entry(const Slapi_RDN *rdn, const Slapi_DN *superiordn, const cha
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
slapi_ldif_put_type_and_value_with_options(&rdnpair, rdntype, rdnval, rdnval_len, LDIF_OPT_NOWRAP);
|
|
|
dc8c34 |
*rdnpair = '\0';
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
estr= slapi_ch_smprintf(glue_entry, slapi_sdn_get_ndn(sdn), rdnstr, uniqueid,
|
|
|
dc8c34 |
ATTR_NSDS5_REPLCONFLICT, reason);
|
|
|
dc8c34 |
slapi_ch_free((void**)&rdnstr);
|
|
|
dc8c34 |
@@ -196,9 +196,7 @@ do_create_glue_entry(const Slapi_RDN *rdn, const Slapi_DN *superiordn, const cha
|
|
|
dc8c34 |
slapi_ch_free((void**)&newrdn);
|
|
|
dc8c34 |
e = slapi_str2entry( estr, 0 );
|
|
|
dc8c34 |
PR_ASSERT(e!=NULL);
|
|
|
dc8c34 |
- if ( e!=NULL )
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
- slapi_entry_set_uniqueid (e, slapi_ch_strdup(uniqueid));
|
|
|
dc8c34 |
+ if (e) {
|
|
|
dc8c34 |
op_result = urp_fixup_add_entry (e, NULL, NULL, opcsn, 0);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
slapi_ch_free_string(&estr);
|
|
|
dc8c34 |
@@ -232,7 +230,7 @@ create_glue_entry ( Slapi_PBlock *pb, char *sessionid, Slapi_DN *dn, const char
|
|
|
dc8c34 |
|
|
|
dc8c34 |
slapi_pblock_get( pb, SLAPI_BACKEND, &backend );
|
|
|
dc8c34 |
slapi_sdn_get_backend_parent ( dn, superiordn, backend );
|
|
|
dc8c34 |
- slapi_sdn_get_rdn ( dn, rdn );
|
|
|
dc8c34 |
+ slapi_rdn_set_dn_ext(rdn, slapi_sdn_get_dn(dn), 1/* skip nsuniqeid=..., in dn */);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
while(!done)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
@@ -246,16 +244,30 @@ create_glue_entry ( Slapi_PBlock *pb, char *sessionid, Slapi_DN *dn, const char
|
|
|
dc8c34 |
done= 1;
|
|
|
dc8c34 |
break;
|
|
|
dc8c34 |
case LDAP_ALREADY_EXISTS:
|
|
|
dc8c34 |
+ {
|
|
|
dc8c34 |
+ struct slapi_operation_parameters *op_params;
|
|
|
dc8c34 |
+ /* This is okay. While creating a glue, a real entry was added. */
|
|
|
dc8c34 |
slapi_log_error ( SLAPI_LOG_FATAL, repl_plugin_name,
|
|
|
dc8c34 |
"%s: Skipped creating glue entry %s uniqueid=%s reason Entry Already Exists\n",
|
|
|
dc8c34 |
sessionid, dnstr, uniqueid);
|
|
|
dc8c34 |
+ op_result = LDAP_SUCCESS;
|
|
|
dc8c34 |
+ /* If we could not create a glue having the nsuniqueid,
|
|
|
dc8c34 |
+ * we have to abandon it. */
|
|
|
dc8c34 |
+ slapi_pblock_get(pb, SLAPI_OPERATION_PARAMETERS, &op_params);
|
|
|
dc8c34 |
+ slapi_ch_free_string(&op_params->p.p_add.parentuniqueid);
|
|
|
dc8c34 |
done= 1;
|
|
|
dc8c34 |
break;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
case LDAP_NO_SUCH_OBJECT:
|
|
|
dc8c34 |
/* The parent is missing */
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
/* JCMREPL - Create the parent ... recursion?... but what's the uniqueid? */
|
|
|
dc8c34 |
- PR_ASSERT(0); /* JCMREPL */
|
|
|
dc8c34 |
+ slapi_log_error (SLAPI_LOG_FATAL, repl_plugin_name,
|
|
|
dc8c34 |
+ "%s: Can't created glue entry %s uniqueid=%s, error %d; "
|
|
|
dc8c34 |
+ "Possibly, parent entry is a conflict entry.\n",
|
|
|
dc8c34 |
+ sessionid, dnstr, uniqueid, op_result);
|
|
|
dc8c34 |
+ done= 1;
|
|
|
dc8c34 |
+ break;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
default:
|
|
|
dc8c34 |
slapi_log_error ( SLAPI_LOG_FATAL, repl_plugin_name,
|
|
|
dc8c34 |
diff --git a/ldap/servers/plugins/replication/urp_tombstone.c b/ldap/servers/plugins/replication/urp_tombstone.c
|
|
|
dc8c34 |
index a61f1e5..68cb269 100644
|
|
|
dc8c34 |
--- a/ldap/servers/plugins/replication/urp_tombstone.c
|
|
|
dc8c34 |
+++ b/ldap/servers/plugins/replication/urp_tombstone.c
|
|
|
dc8c34 |
@@ -84,7 +84,7 @@ get_tombstone_csn(const Slapi_Entry *entry, const CSN **delcsn)
|
|
|
dc8c34 |
static int
|
|
|
dc8c34 |
tombstone_to_glue_resolve_parent (
|
|
|
dc8c34 |
Slapi_PBlock *pb,
|
|
|
dc8c34 |
- const char *sessionid,
|
|
|
dc8c34 |
+ char *sessionid,
|
|
|
dc8c34 |
const Slapi_DN *parentdn,
|
|
|
dc8c34 |
const char *parentuniqueid,
|
|
|
dc8c34 |
CSN *opcsn)
|
|
|
dc8c34 |
@@ -144,7 +144,7 @@ tombstone_to_glue_resolve_parent (
|
|
|
dc8c34 |
int
|
|
|
dc8c34 |
tombstone_to_glue (
|
|
|
dc8c34 |
Slapi_PBlock *pb,
|
|
|
dc8c34 |
- const char *sessionid,
|
|
|
dc8c34 |
+ char *sessionid,
|
|
|
dc8c34 |
Slapi_Entry *tombstoneentry,
|
|
|
dc8c34 |
const Slapi_DN *tombstonedn,
|
|
|
dc8c34 |
const char *reason,
|
|
|
dc8c34 |
@@ -156,6 +156,7 @@ tombstone_to_glue (
|
|
|
dc8c34 |
Slapi_Entry *addingentry;
|
|
|
dc8c34 |
const char *addingdn;
|
|
|
dc8c34 |
int op_result;
|
|
|
dc8c34 |
+ int rdn_is_conflict = 0;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* JCMREPL
|
|
|
dc8c34 |
* Nothing logged to the 5.0 Change Log
|
|
|
dc8c34 |
@@ -170,18 +171,19 @@ tombstone_to_glue (
|
|
|
dc8c34 |
* which won't help us identify the correct backend to search.
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
is_suffix_dn_ext (pb, tombstonedn, &parentdn, 1 /* is_tombstone */);
|
|
|
dc8c34 |
- parentuniqueid= slapi_entry_attr_get_charptr (tombstoneentry,
|
|
|
dc8c34 |
- SLAPI_ATTR_VALUE_PARENT_UNIQUEID); /* Allocated */
|
|
|
dc8c34 |
+ parentuniqueid= slapi_entry_attr_get_charptr (tombstoneentry, SLAPI_ATTR_VALUE_PARENT_UNIQUEID); /* Allocated */
|
|
|
dc8c34 |
tombstone_to_glue_resolve_parent (pb, sessionid, parentdn, parentuniqueid, opcsn);
|
|
|
dc8c34 |
- slapi_sdn_free(&parentdn);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- /* Submit an Add operation to turn the tombstone entry into glue. */
|
|
|
dc8c34 |
+ /* Submit an Add operation to turn the tombstone entry into glue. */
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* The tombstone is stored with an invalid DN, we must fix this.
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
addingentry = slapi_entry_dup(tombstoneentry);
|
|
|
dc8c34 |
addingdn = slapi_sdn_get_dn(tombstonedn);
|
|
|
dc8c34 |
slapi_entry_set_sdn(addingentry, tombstonedn);
|
|
|
dc8c34 |
+ /* not just e_sdn, e_rsdn needs to be updated. */
|
|
|
dc8c34 |
+ slapi_rdn_set_all_dn(slapi_entry_get_srdn(addingentry), slapi_entry_get_dn_const(addingentry));
|
|
|
dc8c34 |
+ rdn_is_conflict = slapi_rdn_is_conflict(slapi_entry_get_srdn(addingentry));
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if (!slapi_entry_attr_hasvalue(addingentry, ATTR_NSDS5_REPLCONFLICT, reason))
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
@@ -189,18 +191,57 @@ tombstone_to_glue (
|
|
|
dc8c34 |
slapi_entry_add_string(addingentry, ATTR_NSDS5_REPLCONFLICT, reason);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
tombstoneuniqueid= slapi_entry_get_uniqueid(tombstoneentry);
|
|
|
dc8c34 |
- op_result = urp_fixup_add_entry (addingentry, tombstoneuniqueid, parentuniqueid, opcsn, OP_FLAG_RESURECT_ENTRY);
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * addingentry and parentuniqueid are consumed in urp_fixup_add_entry,
|
|
|
dc8c34 |
+ * regardless of the result.
|
|
|
dc8c34 |
+ * Note: addingentry is not really consumed in ldbm_back_add.
|
|
|
dc8c34 |
+ * tombstoneentry from DB/entry cache is duplicated and turned to be a glue.
|
|
|
dc8c34 |
+ * This addingentry is freed in op_shared_add.
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ op_result = urp_fixup_add_entry (addingentry, tombstoneuniqueid, slapi_ch_strdup(parentuniqueid), opcsn, OP_FLAG_RESURECT_ENTRY);
|
|
|
dc8c34 |
+ if ((LDAP_ALREADY_EXISTS == op_result) && !rdn_is_conflict) {
|
|
|
dc8c34 |
+ /* conflict -- there's already the same named entry added.
|
|
|
dc8c34 |
+ * But this to-be-glued entry needs to be added since this is a parent of child entries...
|
|
|
dc8c34 |
+ * So, rename this tombstone parententry a conflict, glue entry.
|
|
|
dc8c34 |
+ * Instead of "fixup_add", we have to "fixup_rename"...
|
|
|
dc8c34 |
+ * */
|
|
|
dc8c34 |
+ char *conflictrdn = get_rdn_plus_uniqueid(sessionid, addingdn, tombstoneuniqueid);
|
|
|
dc8c34 |
+ if (conflictrdn) {
|
|
|
dc8c34 |
+ addingentry = slapi_entry_dup(tombstoneentry);
|
|
|
dc8c34 |
+ if (!slapi_entry_attr_hasvalue(addingentry, ATTR_NSDS5_REPLCONFLICT, reason)) {
|
|
|
dc8c34 |
+ /* Add the reason of turning it to glue - The backend code will use it*/
|
|
|
dc8c34 |
+ slapi_entry_add_string(addingentry, ATTR_NSDS5_REPLCONFLICT, reason);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ slapi_log_error (SLAPI_LOG_FATAL, repl_plugin_name,
|
|
|
dc8c34 |
+ "%s: Can't resurrect tombstone to glue reason '%s'. "
|
|
|
dc8c34 |
+ "Try with conflict dn %s, error=%d\n",
|
|
|
dc8c34 |
+ sessionid, reason, addingdn, op_result);
|
|
|
dc8c34 |
+ op_result = urp_fixup_rename_entry(addingentry, (const char *)conflictrdn, parentuniqueid,
|
|
|
dc8c34 |
+ OP_FLAG_RESURECT_ENTRY|OP_FLAG_TOMBSTONE_ENTRY);
|
|
|
dc8c34 |
+ slapi_entry_free(addingentry);
|
|
|
dc8c34 |
+ addingentry = NULL;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ slapi_ch_free_string(&parentuniqueid);
|
|
|
dc8c34 |
if (op_result == LDAP_SUCCESS)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
slapi_log_error (slapi_log_urp, repl_plugin_name,
|
|
|
dc8c34 |
"%s: Resurrected tombstone %s to glue reason '%s'\n", sessionid, addingdn, reason);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+ else if (LDAP_ALREADY_EXISTS == op_result)
|
|
|
dc8c34 |
+ {
|
|
|
dc8c34 |
+ slapi_log_error(slapi_log_urp, repl_plugin_name,
|
|
|
dc8c34 |
+ "%s: No need to turn tombstone %s to glue; it was already resurrected.\n",
|
|
|
dc8c34 |
+ sessionid, addingdn);
|
|
|
dc8c34 |
+ op_result = LDAP_SUCCESS;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
else
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
slapi_log_error (SLAPI_LOG_FATAL, repl_plugin_name,
|
|
|
dc8c34 |
"%s: Can't resurrect tombstone %s to glue reason '%s', error=%d\n",
|
|
|
dc8c34 |
sessionid, addingdn, reason, op_result);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+ slapi_sdn_free(&parentdn);
|
|
|
dc8c34 |
return op_result;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/add.c b/ldap/servers/slapd/add.c
|
|
|
dc8c34 |
index 44a9aa2..1ce975a 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/add.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/add.c
|
|
|
dc8c34 |
@@ -699,10 +699,17 @@ static void op_shared_add (Slapi_PBlock *pb)
|
|
|
dc8c34 |
|
|
|
dc8c34 |
slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &pse;;
|
|
|
dc8c34 |
do_ps_service(pse, NULL, LDAP_CHANGETYPE_ADD, 0);
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- /* If be_add succeeded, then e is consumed. We
|
|
|
dc8c34 |
- * set e to NULL to prevent freeing it ourselves. */
|
|
|
dc8c34 |
- e = NULL;
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * If be_add succeeded, then e is consumed except the resurect case.
|
|
|
dc8c34 |
+ * If it is resurect, the corresponding tombstone entry is resurected
|
|
|
dc8c34 |
+ * and put into the cache.
|
|
|
dc8c34 |
+ * Otherwise, we set e to NULL to prevent freeing it ourselves.
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ if (operation_is_flag_set(operation,OP_FLAG_RESURECT_ENTRY) && save_e) {
|
|
|
dc8c34 |
+ e = save_e;
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ e = NULL;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
else
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/back-ldbm/back-ldbm.h b/ldap/servers/slapd/back-ldbm/back-ldbm.h
|
|
|
dc8c34 |
index 8ad3c20..d27a664 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/back-ldbm/back-ldbm.h
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/back-ldbm/back-ldbm.h
|
|
|
dc8c34 |
@@ -893,7 +893,8 @@ typedef struct _back_search_result_set
|
|
|
dc8c34 |
/* operation for parent_update_on_childchange */
|
|
|
dc8c34 |
#define PARENTUPDATE_ADD 0x1
|
|
|
dc8c34 |
#define PARENTUPDATE_DEL 0x2
|
|
|
dc8c34 |
-#define PARENTUPDATE_MASK (PARENTUPDATE_ADD|PARENTUPDATE_DEL)
|
|
|
dc8c34 |
+#define PARENTUPDATE_RESURECT 0x4
|
|
|
dc8c34 |
+#define PARENTUPDATE_MASK (PARENTUPDATE_ADD|PARENTUPDATE_DEL|PARENTUPDATE_RESURECT)
|
|
|
dc8c34 |
|
|
|
dc8c34 |
#define PARENTUPDATE_CREATE_TOMBSTONE 0x10
|
|
|
dc8c34 |
#define PARENTUPDATE_DELETE_TOMBSTONE 0x20
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/back-ldbm/backentry.c b/ldap/servers/slapd/back-ldbm/backentry.c
|
|
|
dc8c34 |
index 52468ad..114c2df 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/back-ldbm/backentry.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/back-ldbm/backentry.c
|
|
|
dc8c34 |
@@ -52,6 +52,7 @@ backentry_free( struct backentry **bep )
|
|
|
dc8c34 |
return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
ep = *bep;
|
|
|
dc8c34 |
+ PR_ASSERT(ep->ep_state & (ENTRY_STATE_DELETED|ENTRY_STATE_NOTINCACHE));
|
|
|
dc8c34 |
if ( ep->ep_entry != NULL ) {
|
|
|
dc8c34 |
slapi_entry_free( ep->ep_entry );
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/back-ldbm/cache.c b/ldap/servers/slapd/back-ldbm/cache.c
|
|
|
dc8c34 |
index 865f1ef..5510a9a 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/back-ldbm/cache.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/back-ldbm/cache.c
|
|
|
dc8c34 |
@@ -890,7 +890,7 @@ entrycache_remove_int(struct cache *cache, struct backentry *e)
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
else
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- LOG("remove %d from id hash failed\n", e->ep_id, 0, 0);
|
|
|
dc8c34 |
+ LOG("remove %s (%d) from id hash failed\n", ndn, e->ep_id, 0);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
#ifdef UUIDCACHE_ON
|
|
|
dc8c34 |
@@ -984,13 +984,19 @@ int cache_replace(struct cache *cache, void *oldptr, void *newptr)
|
|
|
dc8c34 |
static int entrycache_replace(struct cache *cache, struct backentry *olde,
|
|
|
dc8c34 |
struct backentry *newe)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- int found;
|
|
|
dc8c34 |
+ int found = 0;
|
|
|
dc8c34 |
+ int found_in_dn = 0;
|
|
|
dc8c34 |
+ int found_in_id = 0;
|
|
|
dc8c34 |
+#ifdef UUIDCACHE_ON
|
|
|
dc8c34 |
+ int found_in_uuid = 0;
|
|
|
dc8c34 |
+#endif
|
|
|
dc8c34 |
const char *oldndn;
|
|
|
dc8c34 |
const char *newndn;
|
|
|
dc8c34 |
#ifdef UUIDCACHE_ON
|
|
|
dc8c34 |
const char *olduuid;
|
|
|
dc8c34 |
const char *newuuid;
|
|
|
dc8c34 |
#endif
|
|
|
dc8c34 |
+ struct backentry *alte = NULL;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
LOG("=> entrycache_replace (%s) -> (%s)\n", backentry_get_ndn(olde),
|
|
|
dc8c34 |
backentry_get_ndn(newe), 0);
|
|
|
dc8c34 |
@@ -1013,31 +1019,21 @@ static int entrycache_replace(struct cache *cache, struct backentry *olde,
|
|
|
dc8c34 |
* cache tables, operation error
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
if ( (olde->ep_state & ENTRY_STATE_NOTINCACHE) == 0 ) {
|
|
|
dc8c34 |
- int found_in_dn = remove_hash(cache->c_dntable, (void *)oldndn, strlen(oldndn));
|
|
|
dc8c34 |
- int found_in_id = remove_hash(cache->c_idtable, &(olde->ep_id), sizeof(ID));
|
|
|
dc8c34 |
+ found_in_dn = remove_hash(cache->c_dntable, (void *)oldndn, strlen(oldndn));
|
|
|
dc8c34 |
+ found_in_id = remove_hash(cache->c_idtable, &(olde->ep_id), sizeof(ID));
|
|
|
dc8c34 |
#ifdef UUIDCACHE_ON
|
|
|
dc8c34 |
- int found_in_uuid = remove_hash(cache->c_uuidtable, (void *)olduuid, strlen(olduuid));
|
|
|
dc8c34 |
+ found_in_uuid = remove_hash(cache->c_uuidtable, (void *)olduuid, strlen(olduuid));
|
|
|
dc8c34 |
#endif
|
|
|
dc8c34 |
found = found_in_dn && found_in_id;
|
|
|
dc8c34 |
#ifdef UUIDCACHE_ON
|
|
|
dc8c34 |
found = found && found_in_uuid;
|
|
|
dc8c34 |
#endif
|
|
|
dc8c34 |
- if (!found) {
|
|
|
dc8c34 |
-#ifdef UUIDCACHE_ON
|
|
|
dc8c34 |
- LOG("entry cache replace: cache index tables out of sync - found dn [%d] id [%d] uuid [%d]\n",
|
|
|
dc8c34 |
- found_in_dn, found_in_id, found_in_uuid);
|
|
|
dc8c34 |
-#else
|
|
|
dc8c34 |
- LOG("entry cache replace: cache index tables out of sync - found dn [%d] id [%d]\n",
|
|
|
dc8c34 |
- found_in_dn, found_in_id, 0);
|
|
|
dc8c34 |
-#endif
|
|
|
dc8c34 |
- PR_Unlock(cache->c_mutex);
|
|
|
dc8c34 |
- return 1;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if (! entry_same_dn(newe, (void *)oldndn) &&
|
|
|
dc8c34 |
- (newe->ep_state & ENTRY_STATE_NOTINCACHE) == 0) {
|
|
|
dc8c34 |
- /* if we're doing a modrdn, the new entry can be in the dn table
|
|
|
dc8c34 |
- * already, so we need to remove that too.
|
|
|
dc8c34 |
+ /* If fails, we have to make sure the both entires are removed from the cache,
|
|
|
dc8c34 |
+ * otherwise, we have no idea what's left in the cache or not... */
|
|
|
dc8c34 |
+ if (!entry_same_dn(newe, (void *)oldndn) && (newe->ep_state & ENTRY_STATE_NOTINCACHE) == 0) {
|
|
|
dc8c34 |
+ /* if we're doing a modrdn or turning an entry to a tombstone,
|
|
|
dc8c34 |
+ * the new entry can be in the dn table already, so we need to remove that too.
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
if (remove_hash(cache->c_dntable, (void *)newndn, strlen(newndn)))
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
@@ -1046,20 +1042,44 @@ static int entrycache_replace(struct cache *cache, struct backentry *olde,
|
|
|
dc8c34 |
LOG("entry cache replace remove entry size %lu\n", newe->ep_size, 0, 0);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * The old entry could have been "removed" between the add and this replace,
|
|
|
dc8c34 |
+ * The entry is NOT freed, but NOT in the dn hash.
|
|
|
dc8c34 |
+ * which could happen since the entry is not necessarily locked.
|
|
|
dc8c34 |
+ * This is ok.
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ olde->ep_state = ENTRY_STATE_DELETED; /* olde is removed from the cache, so set DELETED here. */
|
|
|
dc8c34 |
+ if (!found) {
|
|
|
dc8c34 |
+ if (olde->ep_state & ENTRY_STATE_DELETED) {
|
|
|
dc8c34 |
+ LOG("entry cache replace (%s): cache index tables out of sync - found dn [%d] id [%d]; but the entry is alreay deleted.\n",
|
|
|
dc8c34 |
+ oldndn, found_in_dn, found_in_id);
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+#ifdef UUIDCACHE_ON
|
|
|
dc8c34 |
+ LOG("entry cache replace: cache index tables out of sync - found dn [%d] id [%d] uuid [%d]\n",
|
|
|
dc8c34 |
+ found_in_dn, found_in_id, found_in_uuid);
|
|
|
dc8c34 |
+#else
|
|
|
dc8c34 |
+ LOG("entry cache replace (%s): cache index tables out of sync - found dn [%d] id [%d]\n",
|
|
|
dc8c34 |
+ oldndn, found_in_dn, found_in_id);
|
|
|
dc8c34 |
+#endif
|
|
|
dc8c34 |
+ PR_Unlock(cache->c_mutex);
|
|
|
dc8c34 |
+ return 1;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
/* now, add the new entry to the hashtables */
|
|
|
dc8c34 |
/* (probably don't need such extensive error handling, once this has been
|
|
|
dc8c34 |
* tested enough that we believe it works.)
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
- if (!add_hash(cache->c_dntable, (void *)newndn, strlen(newndn), newe, NULL)) {
|
|
|
dc8c34 |
- LOG("entry cache replace: can't add dn\n", 0, 0, 0);
|
|
|
dc8c34 |
+ if (!add_hash(cache->c_dntable, (void *)newndn, strlen(newndn), newe, (void **)&alte)) {
|
|
|
dc8c34 |
+ LOG("entry cache replace (%s): can't add to dn table (returned %s)\n",
|
|
|
dc8c34 |
+ newndn, alte?slapi_entry_get_dn(alte->ep_entry):"none", 0);
|
|
|
dc8c34 |
PR_Unlock(cache->c_mutex);
|
|
|
dc8c34 |
return 1;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if (!add_hash(cache->c_idtable, &(newe->ep_id), sizeof(ID), newe, NULL)) {
|
|
|
dc8c34 |
- LOG("entry cache replace: can't add id\n", 0, 0, 0);
|
|
|
dc8c34 |
+ if (!add_hash(cache->c_idtable, &(newe->ep_id), sizeof(ID), newe, (void **)&alte)) {
|
|
|
dc8c34 |
+ LOG("entry cache replace (%s): can't add to id table (returned %s)\n",
|
|
|
dc8c34 |
+ newndn, alte?slapi_entry_get_dn(alte->ep_entry):"none", 0);
|
|
|
dc8c34 |
if(remove_hash(cache->c_dntable, (void *)newndn, strlen(newndn)) == 0){
|
|
|
dc8c34 |
- LOG("entry cache replace: failed to remove dn table\n", 0, 0, 0);
|
|
|
dc8c34 |
+ LOG("entry cache replace: failed to remove dn table\n", 0, 0, 0);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
PR_Unlock(cache->c_mutex);
|
|
|
dc8c34 |
return 1;
|
|
|
dc8c34 |
@@ -1069,10 +1089,10 @@ static int entrycache_replace(struct cache *cache, struct backentry *olde,
|
|
|
dc8c34 |
newe, NULL)) {
|
|
|
dc8c34 |
LOG("entry cache replace: can't add uuid\n", 0, 0, 0);
|
|
|
dc8c34 |
if(remove_hash(cache->c_dntable, (void *)newndn, strlen(newndn)) == 0){
|
|
|
dc8c34 |
- LOG("entry cache replace: failed to remove dn table(uuid cache)\n", 0, 0, 0);
|
|
|
dc8c34 |
+ LOG("entry cache replace: failed to remove dn table(uuid cache)\n", 0, 0, 0);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if(remove_hash(cache->c_idtable, &(newe->ep_id), sizeof(ID)) == 0){
|
|
|
dc8c34 |
- LOG("entry cache replace: failed to remove id table(uuid cache)\n", 0, 0, 0);
|
|
|
dc8c34 |
+ LOG("entry cache replace: failed to remove id table(uuid cache)\n", 0, 0, 0);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
PR_Unlock(cache->c_mutex);
|
|
|
dc8c34 |
return 1;
|
|
|
dc8c34 |
@@ -1086,7 +1106,6 @@ static int entrycache_replace(struct cache *cache, struct backentry *olde,
|
|
|
dc8c34 |
} else if (newe->ep_size < olde->ep_size) {
|
|
|
dc8c34 |
slapi_counter_subtract(cache->c_cursize, olde->ep_size - newe->ep_size);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- olde->ep_state = ENTRY_STATE_DELETED;
|
|
|
dc8c34 |
newe->ep_state = 0;
|
|
|
dc8c34 |
PR_Unlock(cache->c_mutex);
|
|
|
dc8c34 |
LOG("<= entrycache_replace OK, cache size now %lu cache count now %ld\n",
|
|
|
dc8c34 |
@@ -1269,7 +1288,7 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int state,
|
|
|
dc8c34 |
PR_Lock(cache->c_mutex);
|
|
|
dc8c34 |
if (! add_hash(cache->c_dntable, (void *)ndn, strlen(ndn), e,
|
|
|
dc8c34 |
(void **)&my_alt)) {
|
|
|
dc8c34 |
- LOG("entry \"%s\" already in dn cache\n", backentry_get_ndn(e), 0, 0);
|
|
|
dc8c34 |
+ LOG("entry \"%s\" already in dn cache\n", ndn, 0, 0);
|
|
|
dc8c34 |
/* add_hash filled in 'my_alt' if necessary */
|
|
|
dc8c34 |
if (my_alt == e)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
@@ -1309,14 +1328,15 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int state,
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
if (my_alt->ep_state & ENTRY_STATE_CREATING)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- LOG("the entry is reserved\n", 0, 0, 0);
|
|
|
dc8c34 |
+ LOG("the entry %s is reserved (ep_state: 0x%x, state: 0x%x\n", ndn, e->ep_state, state);
|
|
|
dc8c34 |
e->ep_state |= ENTRY_STATE_NOTINCACHE;
|
|
|
dc8c34 |
PR_Unlock(cache->c_mutex);
|
|
|
dc8c34 |
return -1;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
else if (state != 0)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- LOG("the entry already exists. cannot reserve it.\n", 0, 0, 0);
|
|
|
dc8c34 |
+ LOG("the entry %s already exists. cannot reserve it. (ep_state: 0x%x, state: 0x%x\n",
|
|
|
dc8c34 |
+ ndn, e->ep_state, state);
|
|
|
dc8c34 |
e->ep_state |= ENTRY_STATE_NOTINCACHE;
|
|
|
dc8c34 |
PR_Unlock(cache->c_mutex);
|
|
|
dc8c34 |
return -1;
|
|
|
dc8c34 |
@@ -1328,6 +1348,11 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int state,
|
|
|
dc8c34 |
if ((*alt)->ep_refcnt == 0)
|
|
|
dc8c34 |
lru_delete(cache, (void *)*alt);
|
|
|
dc8c34 |
(*alt)->ep_refcnt++;
|
|
|
dc8c34 |
+ LOG("the entry %s already exists. returning existing entry %s (state: 0x%x)\n",
|
|
|
dc8c34 |
+ ndn, backentry_get_ndn(my_alt), state);
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ LOG("the entry %s already exists. Not returning existing entry %s (state: 0x%x)\n",
|
|
|
dc8c34 |
+ ndn, backentry_get_ndn(my_alt), state);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
PR_Unlock(cache->c_mutex);
|
|
|
dc8c34 |
return 1;
|
|
|
dc8c34 |
@@ -1342,7 +1367,7 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int state,
|
|
|
dc8c34 |
if (state == 0) {
|
|
|
dc8c34 |
/* neither of these should fail, or something is very wrong. */
|
|
|
dc8c34 |
if (! add_hash(cache->c_idtable, &(e->ep_id), sizeof(ID), e, NULL)) {
|
|
|
dc8c34 |
- LOG("entry %s already in id cache!\n", backentry_get_ndn(e), 0, 0);
|
|
|
dc8c34 |
+ LOG("entry %s already in id cache!\n", ndn, 0, 0);
|
|
|
dc8c34 |
if (already_in) {
|
|
|
dc8c34 |
/* there's a bug in the implementatin of 'modify' and 'modrdn'
|
|
|
dc8c34 |
* that i'm working around here. basically they do a
|
|
|
dc8c34 |
@@ -1364,10 +1389,12 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int state,
|
|
|
dc8c34 |
return 0;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if(remove_hash(cache->c_dntable, (void *)ndn, strlen(ndn)) == 0){
|
|
|
dc8c34 |
- LOG("entrycache_add_int: failed to remove dn table\n", 0, 0, 0);
|
|
|
dc8c34 |
+ LOG("entrycache_add_int: failed to remove %s from dn table\n", 0, 0, 0);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
e->ep_state |= ENTRY_STATE_NOTINCACHE;
|
|
|
dc8c34 |
PR_Unlock(cache->c_mutex);
|
|
|
dc8c34 |
+ LOG("entrycache_add_int: failed to add %s to cache (ep_state: %x, already_in: %d)\n",
|
|
|
dc8c34 |
+ ndn, e->ep_state, already_in);
|
|
|
dc8c34 |
return -1;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
#ifdef UUIDCACHE_ON
|
|
|
dc8c34 |
@@ -1378,10 +1405,10 @@ entrycache_add_int(struct cache *cache, struct backentry *e, int state,
|
|
|
dc8c34 |
LOG("entry %s already in uuid cache!\n", backentry_get_ndn(e),
|
|
|
dc8c34 |
0, 0);
|
|
|
dc8c34 |
if(remove_hash(cache->c_dntable, (void *)ndn, strlen(ndn)) == 0){
|
|
|
dc8c34 |
- LOG("entrycache_add_int: failed to remove dn table(uuid cache)\n", 0, 0, 0);
|
|
|
dc8c34 |
+ LOG("entrycache_add_int: failed to remove dn table(uuid cache)\n", 0, 0, 0);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if(remove_hash(cache->c_idtable, &(e->ep_id), sizeof(ID)) == 0){
|
|
|
dc8c34 |
- LOG("entrycache_add_int: failed to remove id table(uuid cache)\n", 0, 0, 0);
|
|
|
dc8c34 |
+ LOG("entrycache_add_int: failed to remove id table(uuid cache)\n", 0, 0, 0);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
e->ep_state |= ENTRY_STATE_NOTINCACHE;
|
|
|
dc8c34 |
PR_Unlock(cache->c_mutex);
|
|
|
dc8c34 |
@@ -1487,8 +1514,8 @@ int cache_lock_entry(struct cache *cache, struct backentry *e)
|
|
|
dc8c34 |
if (!e->ep_mutexp) {
|
|
|
dc8c34 |
LOG("<= cache_lock_entry (DELETED)\n", 0, 0, 0);
|
|
|
dc8c34 |
LDAPDebug1Arg(LDAP_DEBUG_ANY,
|
|
|
dc8c34 |
- "cache_lock_entry: failed to create a lock for %s\n",
|
|
|
dc8c34 |
- backentry_get_ndn(e));
|
|
|
dc8c34 |
+ "cache_lock_entry: failed to create a lock for %s\n",
|
|
|
dc8c34 |
+ backentry_get_ndn(e));
|
|
|
dc8c34 |
LOG("<= cache_lock_entry (FAILED)\n", 0, 0, 0);
|
|
|
dc8c34 |
return 1;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c
|
|
|
dc8c34 |
index 0ade23c..b129307 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/back-ldbm/ldbm_add.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c
|
|
|
dc8c34 |
@@ -79,7 +79,6 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
backend *be;
|
|
|
dc8c34 |
struct ldbminfo *li;
|
|
|
dc8c34 |
ldbm_instance *inst;
|
|
|
dc8c34 |
- const char *dn = NULL;
|
|
|
dc8c34 |
Slapi_Entry *e = NULL;
|
|
|
dc8c34 |
struct backentry *tombstoneentry = NULL;
|
|
|
dc8c34 |
struct backentry *addingentry = NULL;
|
|
|
dc8c34 |
@@ -118,6 +117,7 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
CSN *opcsn = NULL;
|
|
|
dc8c34 |
entry_address addr = {0};
|
|
|
dc8c34 |
int parent_switched = 0;
|
|
|
dc8c34 |
+ int noabort = 1;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
slapi_pblock_get( pb, SLAPI_PLUGIN_PRIVATE, &li );
|
|
|
dc8c34 |
slapi_pblock_get( pb, SLAPI_ADD_ENTRY, &e );
|
|
|
dc8c34 |
@@ -210,15 +210,14 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
slapi_pblock_get( pb, SLAPI_ADD_TARGET_SDN, &sdn );
|
|
|
dc8c34 |
if (NULL == sdn)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- LDAPDebug0Args(LDAP_DEBUG_ANY,
|
|
|
dc8c34 |
- "ldbm_back_add: Null target dn\n");
|
|
|
dc8c34 |
+ LDAPDebug0Args(LDAP_DEBUG_ANY, "ldbm_back_add: FETCH_EXISTING_DN_ENTRY is set, but target dn is NULL.\n");
|
|
|
dc8c34 |
+ ldap_result_code = LDAP_OPERATIONS_ERROR;
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* not need to check the dn syntax as this is a replicated op */
|
|
|
dc8c34 |
if(!is_replicated_operation){
|
|
|
dc8c34 |
- dn = slapi_sdn_get_dn(sdn);
|
|
|
dc8c34 |
- ldap_result_code = slapi_dn_syntax_check(pb, dn, 1);
|
|
|
dc8c34 |
+ ldap_result_code = slapi_dn_syntax_check(pb, slapi_sdn_get_dn(sdn), 1);
|
|
|
dc8c34 |
if (ldap_result_code)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
ldap_result_code = LDAP_INVALID_DN_SYNTAX;
|
|
|
dc8c34 |
@@ -226,7 +225,10 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * If the parent is conflict, slapi_sdn_get_backend_parent does not support it.
|
|
|
dc8c34 |
+ * That is, adding children to a conflict entry is not allowed.
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
slapi_sdn_get_backend_parent(sdn, &parentsdn, pb->pb_backend);
|
|
|
dc8c34 |
/* Check if an entry with the intended DN already exists. */
|
|
|
dc8c34 |
done_with_pblock_entry(pb,SLAPI_ADD_EXISTING_DN_ENTRY); /* Could be through this multiple times */
|
|
|
dc8c34 |
@@ -234,30 +236,27 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
addr.udn = NULL;
|
|
|
dc8c34 |
addr.uniqueid = NULL;
|
|
|
dc8c34 |
ldap_result_code= get_copy_of_entry(pb, &addr, &txn, SLAPI_ADD_EXISTING_DN_ENTRY, !is_replicated_operation);
|
|
|
dc8c34 |
- if(ldap_result_code==LDAP_OPERATIONS_ERROR ||
|
|
|
dc8c34 |
- ldap_result_code==LDAP_INVALID_DN_SYNTAX)
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
- goto error_return;
|
|
|
dc8c34 |
+ if ((ldap_result_code == LDAP_OPERATIONS_ERROR) || (ldap_result_code==LDAP_INVALID_DN_SYNTAX)) {
|
|
|
dc8c34 |
+ goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
/* if we can find the parent by dn or uniqueid, and the operation has requested the parent
|
|
|
dc8c34 |
then get it */
|
|
|
dc8c34 |
- if(have_parent_address(&parentsdn, operation->o_params.p.p_add.parentuniqueid) &&
|
|
|
dc8c34 |
- slapi_isbitset_int(rc,SLAPI_RTN_BIT_FETCH_PARENT_ENTRY))
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
+ if (have_parent_address(&parentsdn, operation->o_params.p.p_add.parentuniqueid) &&
|
|
|
dc8c34 |
+ slapi_isbitset_int(rc,SLAPI_RTN_BIT_FETCH_PARENT_ENTRY)) {
|
|
|
dc8c34 |
done_with_pblock_entry(pb,SLAPI_ADD_PARENT_ENTRY); /* Could be through this multiple times */
|
|
|
dc8c34 |
addr.sdn = &parentsdn;
|
|
|
dc8c34 |
addr.udn = NULL;
|
|
|
dc8c34 |
addr.uniqueid = operation->o_params.p.p_add.parentuniqueid;
|
|
|
dc8c34 |
- ldap_result_code= get_copy_of_entry(pb, &addr, &txn, SLAPI_ADD_PARENT_ENTRY, !is_replicated_operation);
|
|
|
dc8c34 |
- /* need to set parentsdn or parentuniqueid if either is not set? */
|
|
|
dc8c34 |
+ ldap_result_code = get_copy_of_entry(pb, &addr, &txn, SLAPI_ADD_PARENT_ENTRY,
|
|
|
dc8c34 |
+ !is_replicated_operation);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* Call the Backend Pre Add plugins */
|
|
|
dc8c34 |
+ ldap_result_code = LDAP_SUCCESS;
|
|
|
dc8c34 |
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
|
|
|
dc8c34 |
- rc= plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_ADD_FN);
|
|
|
dc8c34 |
- if(rc==-1)
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
+ rc = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_PRE_ADD_FN);
|
|
|
dc8c34 |
+ if (rc == -1) {
|
|
|
dc8c34 |
int opreturn = 0;
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Plugin indicated some kind of failure,
|
|
|
dc8c34 |
@@ -284,7 +283,7 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
* the loop once again to get the new present state.
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
/* JCMREPL - Warning: A Plugin could cause an infinite loop by always returning a result code that requires some action. */
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Originally (in the U-M LDAP 3.3 code), there was a comment near this
|
|
|
dc8c34 |
@@ -309,10 +308,14 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
/* Set the parentuniqueid now */
|
|
|
dc8c34 |
operation->o_params.p.p_add.parentuniqueid = slapi_ch_strdup(slapi_entry_get_uniqueid(parententry->ep_entry));
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if (slapi_sdn_isempty(&parentsdn)) {
|
|
|
dc8c34 |
+ if (slapi_sdn_isempty(&parentsdn) ||
|
|
|
dc8c34 |
+ slapi_sdn_compare(&parentsdn, slapi_entry_get_sdn(parententry->ep_entry))) {
|
|
|
dc8c34 |
/* Set the parentsdn now */
|
|
|
dc8c34 |
slapi_sdn_set_dn_byval(&parentsdn, slapi_entry_get_dn_const(parententry->ep_entry));
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ LDAPDebug2Args(LDAP_DEBUG_BACKLDBM, "find_entry2modify_only returned NULL parententry pdn: %s, uniqueid: %s\n",
|
|
|
dc8c34 |
+ slapi_sdn_get_dn(&parentsdn), addr.uniqueid?addr.uniqueid:"none");
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
modify_init(&parent_modify_c,parententry);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -320,11 +323,39 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
/* Check if the entry we have been asked to add already exists */
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
Slapi_Entry *entry;
|
|
|
dc8c34 |
- slapi_pblock_get( pb, SLAPI_ADD_EXISTING_DN_ENTRY, &entry);
|
|
|
dc8c34 |
- if ( entry != NULL )
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
- /* The entry already exists */
|
|
|
dc8c34 |
- ldap_result_code= LDAP_ALREADY_EXISTS;
|
|
|
dc8c34 |
+ slapi_pblock_get(pb, SLAPI_ADD_EXISTING_DN_ENTRY, &entry);
|
|
|
dc8c34 |
+ if (entry) {
|
|
|
dc8c34 |
+ if (is_resurect_operation) {
|
|
|
dc8c34 |
+ Slapi_Entry *uniqentry;
|
|
|
dc8c34 |
+ slapi_pblock_get(pb, SLAPI_ADD_EXISTING_UNIQUEID_ENTRY, &uniqentry);
|
|
|
dc8c34 |
+ if (uniqentry == entry) {
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * adding entry having the uniqueid exists.
|
|
|
dc8c34 |
+ * No need to resurrect.
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ ldap_result_code = LDAP_SUCCESS;
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * The entry having the DN already exists.
|
|
|
dc8c34 |
+ * But the
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ if (uniqentry) {
|
|
|
dc8c34 |
+ if (PL_strcmp(slapi_entry_get_uniqueid(entry),
|
|
|
dc8c34 |
+ slapi_entry_get_uniqueid(uniqentry))) {
|
|
|
dc8c34 |
+ /* Not match; conflict. */
|
|
|
dc8c34 |
+ ldap_result_code = LDAP_ALREADY_EXISTS;
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ /* Same entry; no need to resurrect. */
|
|
|
dc8c34 |
+ ldap_result_code = LDAP_SUCCESS;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ ldap_result_code = LDAP_ALREADY_EXISTS;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ /* The entry already exists */
|
|
|
dc8c34 |
+ ldap_result_code = LDAP_ALREADY_EXISTS;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
else
|
|
|
dc8c34 |
@@ -335,7 +366,7 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
* entry we did match has a referral we should return
|
|
|
dc8c34 |
* instead. we do this only if managedsait is not on.
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
- if ( !managedsait && !is_tombstone_operation )
|
|
|
dc8c34 |
+ if (!managedsait && !is_tombstone_operation && !is_resurect_operation)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
int err= 0;
|
|
|
dc8c34 |
Slapi_DN ancestorsdn;
|
|
|
dc8c34 |
@@ -392,14 +423,14 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
if ( tombstoneentry==NULL )
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
ldap_result_code= -1;
|
|
|
dc8c34 |
- goto error_return; /* error result sent by find_entry2modify() */
|
|
|
dc8c34 |
+ goto error_return; /* error result sent by find_entry2modify() */
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
tombstone_in_cache = 1;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
addingentry = backentry_dup( tombstoneentry );
|
|
|
dc8c34 |
if ( addingentry==NULL )
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- ldap_result_code= LDAP_OPERATIONS_ERROR;
|
|
|
dc8c34 |
+ ldap_result_code = LDAP_OPERATIONS_ERROR;
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
@@ -411,17 +442,21 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
if (NULL == sdn) {
|
|
|
dc8c34 |
LDAPDebug0Args(LDAP_DEBUG_ANY, "ldbm_back_add: Null target dn\n");
|
|
|
dc8c34 |
+ ldap_result_code = LDAP_OPERATIONS_ERROR;
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- dn = slapi_sdn_get_dn(sdn);
|
|
|
dc8c34 |
slapi_entry_set_sdn(addingentry->ep_entry, sdn); /* The DN is passed into the entry. */
|
|
|
dc8c34 |
+ /* not just e_sdn, e_rsdn needs to be updated. */
|
|
|
dc8c34 |
+ slapi_rdn_set_all_dn(slapi_entry_get_srdn(addingentry->ep_entry),
|
|
|
dc8c34 |
+ slapi_entry_get_dn_const(addingentry->ep_entry));
|
|
|
dc8c34 |
/* LPREPL: the DN is normalized...Somehow who should get a not normalized one */
|
|
|
dc8c34 |
addingentry->ep_id = slapi_entry_attr_get_ulong(addingentry->ep_entry,"entryid");
|
|
|
dc8c34 |
slapi_entry_attr_delete(addingentry->ep_entry, SLAPI_ATTR_VALUE_PARENT_UNIQUEID);
|
|
|
dc8c34 |
slapi_entry_delete_string(addingentry->ep_entry, SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE);
|
|
|
dc8c34 |
/* Now also remove the nscpEntryDN */
|
|
|
dc8c34 |
if (slapi_entry_attr_delete(addingentry->ep_entry, SLAPI_ATTR_NSCP_ENTRYDN) != 0){
|
|
|
dc8c34 |
- LDAPDebug(LDAP_DEBUG_REPL, "Resurrection of %s - Couldn't remove %s\n", dn, SLAPI_ATTR_NSCP_ENTRYDN, 0);
|
|
|
dc8c34 |
+ LDAPDebug(LDAP_DEBUG_REPL, "Resurrection of %s - Couldn't remove %s\n",
|
|
|
dc8c34 |
+ slapi_sdn_get_dn(sdn), SLAPI_ATTR_NSCP_ENTRYDN, 0);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* And copy the reason from e */
|
|
|
dc8c34 |
@@ -429,7 +464,8 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
if (reason) {
|
|
|
dc8c34 |
if (!slapi_entry_attr_hasvalue(addingentry->ep_entry, "nsds5ReplConflict", reason)) {
|
|
|
dc8c34 |
slapi_entry_add_string(addingentry->ep_entry, "nsds5ReplConflict", reason);
|
|
|
dc8c34 |
- LDAPDebug(LDAP_DEBUG_REPL, "Resurrection of %s - Added Conflict reason %s\n", dn, reason, 0);
|
|
|
dc8c34 |
+ LDAPDebug(LDAP_DEBUG_REPL, "Resurrection of %s - Added Conflict reason %s\n",
|
|
|
dc8c34 |
+ slapi_sdn_get_dn(sdn), reason, 0);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
slapi_ch_free((void **)&reason);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -578,9 +614,8 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
Slapi_DN ancestorsdn;
|
|
|
dc8c34 |
struct backentry *ancestorentry;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE,
|
|
|
dc8c34 |
- "parent does not exist, pdn = %s\n",
|
|
|
dc8c34 |
- slapi_sdn_get_dn(&parentsdn), 0, 0 );
|
|
|
dc8c34 |
+ LDAPDebug1Arg(LDAP_DEBUG_BACKLDBM, "ldbm_add: Parent \"%s\" does not exist. "
|
|
|
dc8c34 |
+ "It might be a conflict entry.\n", slapi_sdn_get_dn(&parentsdn));
|
|
|
dc8c34 |
|
|
|
dc8c34 |
slapi_sdn_init(&ancestorsdn);
|
|
|
dc8c34 |
ancestorentry = dn2ancestor(be, &parentsdn, &ancestorsdn, &txn, &err );
|
|
|
dc8c34 |
@@ -591,22 +626,38 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
slapi_sdn_done(&ancestorsdn);
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- ldap_result_code = plugin_call_acl_plugin (pb, e, NULL, NULL, SLAPI_ACL_ADD,
|
|
|
dc8c34 |
- ACLPLUGIN_ACCESS_DEFAULT, &errbuf );
|
|
|
dc8c34 |
+ ldap_result_code = plugin_call_acl_plugin(pb, e, NULL, NULL, SLAPI_ACL_ADD,
|
|
|
dc8c34 |
+ ACLPLUGIN_ACCESS_DEFAULT, &errbuf );
|
|
|
dc8c34 |
if ( ldap_result_code != LDAP_SUCCESS )
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE, "no access to parent\n", 0, 0, 0 );
|
|
|
dc8c34 |
+ LDAPDebug1Arg(LDAP_DEBUG_TRACE, "no access to parent, pdn = %s\n",
|
|
|
dc8c34 |
+ slapi_sdn_get_dn(&parentsdn));
|
|
|
dc8c34 |
ldap_result_message= errbuf;
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
pid = parententry->ep_id;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ /* We may need to adjust the DN since parent could be a resrected conflict entry... */
|
|
|
dc8c34 |
+ if (!slapi_sdn_isparent(slapi_entry_get_sdn_const(parententry->ep_entry),
|
|
|
dc8c34 |
+ slapi_entry_get_sdn_const(addingentry->ep_entry))) {
|
|
|
dc8c34 |
+ Slapi_DN adjustedsdn = {0};
|
|
|
dc8c34 |
+ char *adjusteddn = slapi_ch_smprintf("%s,%s",
|
|
|
dc8c34 |
+ slapi_entry_get_rdn_const(addingentry->ep_entry),
|
|
|
dc8c34 |
+ slapi_entry_get_dn_const(parententry->ep_entry));
|
|
|
dc8c34 |
+ LDAPDebug2Args(LDAP_DEBUG_BACKLDBM, "ldbm_add: adjusting dn: %s --> %s\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(addingentry->ep_entry), adjusteddn);
|
|
|
dc8c34 |
+ slapi_sdn_set_normdn_passin(&adjustedsdn, adjusteddn);
|
|
|
dc8c34 |
+ slapi_entry_set_sdn(addingentry->ep_entry, &adjustedsdn);
|
|
|
dc8c34 |
+ /* not just e_sdn, e_rsdn needs to be updated. */
|
|
|
dc8c34 |
+ slapi_rdn_set_all_dn(slapi_entry_get_srdn(addingentry->ep_entry), adjusteddn);
|
|
|
dc8c34 |
+ slapi_sdn_done(&adjustedsdn);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
else
|
|
|
dc8c34 |
{ /* no parent */
|
|
|
dc8c34 |
- if ( !isroot && !is_replicated_operation)
|
|
|
dc8c34 |
+ if (!isroot && !is_replicated_operation)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE, "no parent & not root\n",
|
|
|
dc8c34 |
- 0, 0, 0 );
|
|
|
dc8c34 |
+ LDAPDebug0Args(LDAP_DEBUG_TRACE, "no parent & not root\n");
|
|
|
dc8c34 |
ldap_result_code= LDAP_INSUFFICIENT_ACCESS;
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -635,11 +686,12 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
* operational attributes to ensure that the cache is sized correctly. */
|
|
|
dc8c34 |
if ( cache_add_tentative( &inst->inst_cache, addingentry, NULL )!= 0 )
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_CACHE, "cache_add_tentative concurrency detected\n", 0, 0, 0 );
|
|
|
dc8c34 |
+ LDAPDebug1Arg(LDAP_DEBUG_CACHE, "cache_add_tentative concurrency detected: %s\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn_const(addingentry->ep_entry));
|
|
|
dc8c34 |
ldap_result_code= LDAP_ALREADY_EXISTS;
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- addingentry_in_cache= 1;
|
|
|
dc8c34 |
+ addingentry_in_cache = 1;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Before we add the entry, find out if the syntax of the aci
|
|
|
dc8c34 |
@@ -647,7 +699,8 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
* the entry if the syntax is incorrect.
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
if ( plugin_call_acl_verify_syntax (pb, addingentry->ep_entry, &errbuf) != 0 ) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE, "ACL syntax error\n", 0,0,0);
|
|
|
dc8c34 |
+ LDAPDebug1Arg(LDAP_DEBUG_TRACE, "ACL syntax error: %s\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn_const(addingentry->ep_entry));
|
|
|
dc8c34 |
ldap_result_code= LDAP_INVALID_SYNTAX;
|
|
|
dc8c34 |
ldap_result_message= errbuf;
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
@@ -656,12 +709,15 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
/* Having decided that we're really going to do the operation, let's modify
|
|
|
dc8c34 |
the in-memory state of the parent to reflect the new child (update
|
|
|
dc8c34 |
subordinate count specifically */
|
|
|
dc8c34 |
- if (NULL != parententry)
|
|
|
dc8c34 |
+ if (parententry)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
retval = parent_update_on_childchange(&parent_modify_c,
|
|
|
dc8c34 |
- PARENTUPDATE_ADD, NULL);
|
|
|
dc8c34 |
+ is_resurect_operation?PARENTUPDATE_RESURECT:PARENTUPDATE_ADD,
|
|
|
dc8c34 |
+ NULL);
|
|
|
dc8c34 |
/* The modify context now contains info needed later */
|
|
|
dc8c34 |
- if (0 != retval) {
|
|
|
dc8c34 |
+ if (retval) {
|
|
|
dc8c34 |
+ LDAPDebug2Args(LDAP_DEBUG_BACKLDBM, "parent_update_on_childchange: %s, rc=%d\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn_const(addingentry->ep_entry), retval);
|
|
|
dc8c34 |
ldap_result_code= LDAP_OPERATIONS_ERROR;
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -681,11 +737,16 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
for (retry_count = 0; retry_count < RETRY_TIMES; retry_count++) {
|
|
|
dc8c34 |
if (txn.back_txn_txn && (txn.back_txn_txn != parent_txn)) {
|
|
|
dc8c34 |
dblayer_txn_abort(li,&txn);
|
|
|
dc8c34 |
+ noabort = 1;
|
|
|
dc8c34 |
slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if (addingentry_in_cache) {
|
|
|
dc8c34 |
/* addingentry is in cache. Remove it once. */
|
|
|
dc8c34 |
- CACHE_REMOVE(&inst->inst_cache, addingentry);
|
|
|
dc8c34 |
+ retval = CACHE_REMOVE(&inst->inst_cache, addingentry);
|
|
|
dc8c34 |
+ if (retval) {
|
|
|
dc8c34 |
+ LDAPDebug1Arg(LDAP_DEBUG_CACHE, "ldbm_add: cache_remove %s failed.\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn_const(addingentry->ep_entry));
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
CACHE_RETURN(&inst->inst_cache, &addingentry);
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
backentry_free(&addingentry);
|
|
|
dc8c34 |
@@ -698,11 +759,11 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (addingentry_in_cache) {
|
|
|
dc8c34 |
/* Adding the resetted addingentry to the cache. */
|
|
|
dc8c34 |
- if (cache_add_tentative(&inst->inst_cache,
|
|
|
dc8c34 |
- addingentry, NULL) != 0) {
|
|
|
dc8c34 |
- LDAPDebug0Args(LDAP_DEBUG_CACHE,
|
|
|
dc8c34 |
- "cache_add_tentative concurrency detected\n");
|
|
|
dc8c34 |
+ if (cache_add_tentative(&inst->inst_cache, addingentry, NULL) != 0) {
|
|
|
dc8c34 |
+ LDAPDebug1Arg(LDAP_DEBUG_CACHE, "cache_add_tentative concurrency detected: %s\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn_const(addingentry->ep_entry));
|
|
|
dc8c34 |
ldap_result_code = LDAP_ALREADY_EXISTS;
|
|
|
dc8c34 |
+ addingentry_in_cache = 0;
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -732,6 +793,7 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
ldap_result_code= LDAP_OPERATIONS_ERROR;
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+ noabort = 0;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* stash the transaction for plugins */
|
|
|
dc8c34 |
slapi_pblock_set(pb, SLAPI_TXN, txn.back_txn_txn);
|
|
|
dc8c34 |
@@ -739,14 +801,12 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
/* call the transaction pre add plugins just after creating the transaction */
|
|
|
dc8c34 |
if ((retval = plugin_call_plugins(pb, SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN))) {
|
|
|
dc8c34 |
int opreturn = 0;
|
|
|
dc8c34 |
- LDAPDebug1Arg( LDAP_DEBUG_TRACE, "SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN plugin "
|
|
|
dc8c34 |
- "returned error code %d\n", retval );
|
|
|
dc8c34 |
+ LDAPDebug1Arg(LDAP_DEBUG_TRACE, "SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN plugin "
|
|
|
dc8c34 |
+ "returned error code %d\n", retval );
|
|
|
dc8c34 |
if (!ldap_result_code) {
|
|
|
dc8c34 |
slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (!ldap_result_code) {
|
|
|
dc8c34 |
- LDAPDebug0Args( LDAP_DEBUG_ANY, "SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN plugin "
|
|
|
dc8c34 |
- "returned error but did not setSLAPI_RESULT_CODE \n" );
|
|
|
dc8c34 |
ldap_result_code = LDAP_OPERATIONS_ERROR;
|
|
|
dc8c34 |
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -754,6 +814,8 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
if (!opreturn) {
|
|
|
dc8c34 |
slapi_pblock_set(pb, SLAPI_PLUGIN_OPRETURN, ldap_result_code ? &ldap_result_code : &retval);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+ LDAPDebug1Arg(LDAP_DEBUG_ANY, "SLAPI_PLUGIN_BE_TXN_PRE_ADD_FN plugin failed: %d",
|
|
|
dc8c34 |
+ ldap_result_code ? ldap_result_code : retval);
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -764,9 +826,10 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
/* Retry txn */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if (retval != 0) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE, "id2entry_add failed, err=%d %s\n",
|
|
|
dc8c34 |
- retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
|
|
|
dc8c34 |
+ if (retval) {
|
|
|
dc8c34 |
+ LDAPDebug(LDAP_DEBUG_TRACE, "id2entry_add(%s) failed, err=%d %s\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn_const(addingentry->ep_entry),
|
|
|
dc8c34 |
+ retval, (msg = dblayer_strerror( retval )) ? msg : "");
|
|
|
dc8c34 |
ADD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
|
|
|
dc8c34 |
disk_full = 1;
|
|
|
dc8c34 |
@@ -782,11 +845,11 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
/* Retry txn */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if (0 != retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE, "add 1 BAD, err=%d %s\n",
|
|
|
dc8c34 |
- retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
|
|
|
dc8c34 |
- ADD_SET_ERROR(ldap_result_code,
|
|
|
dc8c34 |
- LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
+ if (retval) {
|
|
|
dc8c34 |
+ LDAPDebug(LDAP_DEBUG_TRACE, "index_addordel_string TOMBSTONE (%s), err=%d %s\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn_const(addingentry->ep_entry),
|
|
|
dc8c34 |
+ retval, (msg = dblayer_strerror( retval )) ? msg : "");
|
|
|
dc8c34 |
+ ADD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
|
|
|
dc8c34 |
disk_full = 1;
|
|
|
dc8c34 |
goto diskfull_return;
|
|
|
dc8c34 |
@@ -800,10 +863,10 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (0 != retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE, "add 2 BAD, err=%d %s\n",
|
|
|
dc8c34 |
- retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
|
|
|
dc8c34 |
- ADD_SET_ERROR(ldap_result_code,
|
|
|
dc8c34 |
- LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
+ LDAPDebug(LDAP_DEBUG_TRACE, "index_addordel_string UNIQUEID (%s), err=%d %s\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn_const(addingentry->ep_entry),
|
|
|
dc8c34 |
+ retval, (msg = dblayer_strerror( retval )) ? msg : "");
|
|
|
dc8c34 |
+ ADD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
|
|
|
dc8c34 |
disk_full = 1;
|
|
|
dc8c34 |
goto diskfull_return;
|
|
|
dc8c34 |
@@ -821,17 +884,29 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (0 != retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE, "add 3 BAD, err=%d %s\n",
|
|
|
dc8c34 |
- retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
|
|
|
dc8c34 |
- ADD_SET_ERROR(ldap_result_code,
|
|
|
dc8c34 |
- LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
+ LDAPDebug(LDAP_DEBUG_TRACE, "index_addordel_string ENTRYDN (%s), err=%d %s\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn_const(addingentry->ep_entry),
|
|
|
dc8c34 |
+ retval, (msg = dblayer_strerror( retval )) ? msg : "");
|
|
|
dc8c34 |
+ ADD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
|
|
|
dc8c34 |
disk_full = 1;
|
|
|
dc8c34 |
goto diskfull_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
+ /* Need to delete the entryrdn index of the resurrected tombstone... */
|
|
|
dc8c34 |
+ if (entryrdn_get_switch()) { /* subtree-rename: on */
|
|
|
dc8c34 |
+ if (tombstoneentry) {
|
|
|
dc8c34 |
+ retval = entryrdn_index_entry(be, tombstoneentry, BE_INDEX_DEL, &txn);
|
|
|
dc8c34 |
+ if (retval) {
|
|
|
dc8c34 |
+ LDAPDebug(LDAP_DEBUG_ANY, "Resurrecting %s: failed to remove entryrdn index, err=%d %s\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn_const(tombstoneentry->ep_entry),
|
|
|
dc8c34 |
+ retval, (msg = dblayer_strerror( retval )) ? msg : "");
|
|
|
dc8c34 |
+ goto error_return;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
if (is_tombstone_operation)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
retval = index_addordel_entry( be, addingentry, BE_INDEX_ADD | BE_INDEX_TOMBSTONE, &txn );
|
|
|
dc8c34 |
@@ -846,9 +921,9 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
/* retry txn */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if (retval != 0) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_ANY, "add: attempt to index %lu failed\n",
|
|
|
dc8c34 |
- (u_long)addingentry->ep_id, 0, 0 );
|
|
|
dc8c34 |
+ if (retval) {
|
|
|
dc8c34 |
+ LDAPDebug2Args(LDAP_DEBUG_ANY, "add: attempt to index %lu failed; rc=%d\n",
|
|
|
dc8c34 |
+ (u_long)addingentry->ep_id, retval);
|
|
|
dc8c34 |
ADD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
|
|
|
dc8c34 |
disk_full = 1;
|
|
|
dc8c34 |
@@ -865,11 +940,10 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
/* Retry txn */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if (0 != retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE, "add 1 BAD, err=%d %s\n",
|
|
|
dc8c34 |
- retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
|
|
|
dc8c34 |
- ADD_SET_ERROR(ldap_result_code,
|
|
|
dc8c34 |
- LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
+ if (retval) {
|
|
|
dc8c34 |
+ LDAPDebug(LDAP_DEBUG_BACKLDBM, "modify_update_all: %s (%lu) failed; rc=%d\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(addingentry->ep_entry), (u_long)addingentry->ep_id, retval);
|
|
|
dc8c34 |
+ ADD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
|
|
|
dc8c34 |
disk_full = 1;
|
|
|
dc8c34 |
goto diskfull_return;
|
|
|
dc8c34 |
@@ -884,17 +958,16 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
retval= vlv_update_all_indexes(&txn, be, pb, NULL, addingentry);
|
|
|
dc8c34 |
if (DB_LOCK_DEADLOCK == retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_ARGS,
|
|
|
dc8c34 |
- "add DEADLOCK vlv_update_index\n", 0, 0, 0 );
|
|
|
dc8c34 |
+ LDAPDebug(LDAP_DEBUG_ARGS,
|
|
|
dc8c34 |
+ "add DEADLOCK vlv_update_index\n", 0, 0, 0 );
|
|
|
dc8c34 |
/* Retry txn */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if (0 != retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE,
|
|
|
dc8c34 |
- "vlv_update_index failed, err=%d %s\n",
|
|
|
dc8c34 |
- retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
|
|
|
dc8c34 |
- ADD_SET_ERROR(ldap_result_code,
|
|
|
dc8c34 |
- LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
+ if (retval) {
|
|
|
dc8c34 |
+ LDAPDebug2Args(LDAP_DEBUG_TRACE,
|
|
|
dc8c34 |
+ "vlv_update_index failed, err=%d %s\n",
|
|
|
dc8c34 |
+ retval, (msg = dblayer_strerror( retval )) ? msg : "");
|
|
|
dc8c34 |
+ ADD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
if (LDBM_OS_ERR_IS_DISKFULL(retval)) {
|
|
|
dc8c34 |
disk_full = 1;
|
|
|
dc8c34 |
goto diskfull_return;
|
|
|
dc8c34 |
@@ -940,7 +1013,7 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
if (retry_count == RETRY_TIMES) {
|
|
|
dc8c34 |
/* Failed */
|
|
|
dc8c34 |
LDAPDebug( LDAP_DEBUG_ANY, "Retry count exceeded in add\n", 0, 0, 0 );
|
|
|
dc8c34 |
- ldap_result_code= LDAP_BUSY;
|
|
|
dc8c34 |
+ ldap_result_code= LDAP_BUSY;
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -956,33 +1029,49 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* We can now switch the tombstone entry with the real entry.
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
- if (cache_replace( &inst->inst_cache, tombstoneentry, addingentry ) != 0 )
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
+ retval = cache_replace(&inst->inst_cache, tombstoneentry, addingentry);
|
|
|
dc8c34 |
+ if (retval) {
|
|
|
dc8c34 |
/* This happens if the dn of addingentry already exists */
|
|
|
dc8c34 |
- cache_unlock_entry( &inst->inst_cache, tombstoneentry );
|
|
|
dc8c34 |
ADD_SET_ERROR(ldap_result_code, LDAP_ALREADY_EXISTS, retry_count);
|
|
|
dc8c34 |
+ LDAPDebug2Args(LDAP_DEBUG_CACHE, "ldap_add: cache_replace concurrency detected: %s (rc: %d)\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn_const(addingentry->ep_entry), retval);
|
|
|
dc8c34 |
+ retval = -1;
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+ if (addingentry_in_cache) { /* decrease the refcnt added by tentative */
|
|
|
dc8c34 |
+ CACHE_RETURN( &inst->inst_cache, &addingentry );
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ addingentry_in_cache = 1; /* reset it to make it sure... */
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* The tombstone was locked down in the cache... we can
|
|
|
dc8c34 |
* get rid of the entry in the cache now.
|
|
|
dc8c34 |
+ * We cannot expect tombstoneentry exists from now on.
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
+ if (entryrdn_get_switch()) { /* subtree-rename: on */
|
|
|
dc8c34 |
+ /* since the op was successful, delete the tombstone dn from the dn cache */
|
|
|
dc8c34 |
+ struct backdn *bdn = dncache_find_id(&inst->inst_dncache,
|
|
|
dc8c34 |
+ tombstoneentry->ep_id);
|
|
|
dc8c34 |
+ if (bdn) { /* in the dncache, remove it. */
|
|
|
dc8c34 |
+ CACHE_REMOVE(&inst->inst_dncache, bdn);
|
|
|
dc8c34 |
+ CACHE_RETURN(&inst->inst_dncache, &bdn;;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
cache_unlock_entry( &inst->inst_cache, tombstoneentry );
|
|
|
dc8c34 |
CACHE_RETURN( &inst->inst_cache, &tombstoneentry );
|
|
|
dc8c34 |
- tombstone_in_cache = 0; /* deleted */
|
|
|
dc8c34 |
+ tombstone_in_cache = 0;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (parent_found)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
/* switch the parent entry copy into play */
|
|
|
dc8c34 |
- modify_switch_entries( &parent_modify_c,be);
|
|
|
dc8c34 |
+ modify_switch_entries(&parent_modify_c,be);
|
|
|
dc8c34 |
parent_switched = 1;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if (ruv_c_init) {
|
|
|
dc8c34 |
if (modify_switch_entries(&ruv_c, be) != 0 ) {
|
|
|
dc8c34 |
ldap_result_code= LDAP_OPERATIONS_ERROR;
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_ANY,
|
|
|
dc8c34 |
- "ldbm_back_add: modify_switch_entries failed\n", 0, 0, 0);
|
|
|
dc8c34 |
+ LDAPDebug0Args(LDAP_DEBUG_ANY,
|
|
|
dc8c34 |
+ "ldbm_back_add: modify_switch_entries failed\n");
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -996,8 +1085,6 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (!ldap_result_code) {
|
|
|
dc8c34 |
- LDAPDebug0Args( LDAP_DEBUG_ANY, "SLAPI_PLUGIN_BE_TXN_POST_ADD_FN plugin "
|
|
|
dc8c34 |
- "returned error but did not set SLAPI_RESULT_CODE\n" );
|
|
|
dc8c34 |
ldap_result_code = LDAP_OPERATIONS_ERROR;
|
|
|
dc8c34 |
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -1020,6 +1107,7 @@ ldbm_back_add( Slapi_PBlock *pb )
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+ noabort = 1;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
rc= 0;
|
|
|
dc8c34 |
goto common_return;
|
|
|
dc8c34 |
@@ -1029,21 +1117,20 @@ error_return:
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
next_id_return( be, addingentry->ep_id );
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if ( NULL != addingentry )
|
|
|
dc8c34 |
+ if ( addingentry )
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
if ( addingentry_in_cache )
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
CACHE_REMOVE(&inst->inst_cache, addingentry);
|
|
|
dc8c34 |
- addingentry_in_cache = 0;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- backentry_clear_entry(addingentry); /* e is released in the frontend */
|
|
|
dc8c34 |
- backentry_free( &addingentry ); /* release the backend wrapper, here */
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- if(tombstone_in_cache)
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
- CACHE_RETURN(&inst->inst_cache, &tombstoneentry);
|
|
|
dc8c34 |
+ else
|
|
|
dc8c34 |
+ {
|
|
|
dc8c34 |
+ if (!is_resurect_operation) { /* if resurect, tombstoneentry is dupped. */
|
|
|
dc8c34 |
+ backentry_clear_entry(addingentry); /* e is released in the frontend */
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ backentry_free( &addingentry ); /* release the backend wrapper, here */
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
if (rc == DB_RUNRECOVERY) {
|
|
|
dc8c34 |
dblayer_remember_disk_filled(li);
|
|
|
dc8c34 |
ldbm_nasty("Add",80,rc);
|
|
|
dc8c34 |
@@ -1063,7 +1150,7 @@ error_return:
|
|
|
dc8c34 |
|
|
|
dc8c34 |
diskfull_return:
|
|
|
dc8c34 |
if (disk_full) {
|
|
|
dc8c34 |
- rc= return_on_disk_full(li);
|
|
|
dc8c34 |
+ rc = return_on_disk_full(li);
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
/* It is safer not to abort when the transaction is not started. */
|
|
|
dc8c34 |
if (txn.back_txn_txn && (txn.back_txn_txn != parent_txn)) {
|
|
|
dc8c34 |
@@ -1096,39 +1183,44 @@ diskfull_return:
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- dblayer_txn_abort(li,&txn); /* abort crashes in case disk full */
|
|
|
dc8c34 |
+ if (!noabort) {
|
|
|
dc8c34 |
+ dblayer_txn_abort(li,&txn); /* abort crashes in case disk full */
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
/* txn is no longer valid - reset the txn pointer to the parent */
|
|
|
dc8c34 |
slapi_pblock_set(pb, SLAPI_TXN, parent_txn);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- rc= SLAPI_FAIL_GENERAL;
|
|
|
dc8c34 |
+ rc = SLAPI_FAIL_GENERAL;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
common_return:
|
|
|
dc8c34 |
- if (addingentry_in_cache && addingentry)
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
- if (entryrdn_get_switch()) { /* subtree-rename: on */
|
|
|
dc8c34 |
- /* since adding the entry to the entry cache was successful,
|
|
|
dc8c34 |
- * let's add the dn to dncache, if not yet done. */
|
|
|
dc8c34 |
- struct backdn *bdn = dncache_find_id(&inst->inst_dncache,
|
|
|
dc8c34 |
- addingentry->ep_id);
|
|
|
dc8c34 |
- if (bdn) { /* already in the dncache */
|
|
|
dc8c34 |
- CACHE_RETURN(&inst->inst_dncache, &bdn;;
|
|
|
dc8c34 |
- } else { /* not in the dncache yet */
|
|
|
dc8c34 |
- Slapi_DN *addingsdn =
|
|
|
dc8c34 |
- slapi_sdn_dup(slapi_entry_get_sdn(addingentry->ep_entry));
|
|
|
dc8c34 |
- if (addingsdn) {
|
|
|
dc8c34 |
- bdn = backdn_init(addingsdn, addingentry->ep_id, 0);
|
|
|
dc8c34 |
- if (bdn) {
|
|
|
dc8c34 |
- CACHE_ADD( &inst->inst_dncache, bdn, NULL );
|
|
|
dc8c34 |
- CACHE_RETURN(&inst->inst_dncache, &bdn;;
|
|
|
dc8c34 |
- slapi_log_error(SLAPI_LOG_CACHE, "ldbm_back_add",
|
|
|
dc8c34 |
- "set %s to dn cache\n", dn);
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- CACHE_RETURN( &inst->inst_cache, &addingentry );
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
+ if (inst) {
|
|
|
dc8c34 |
+ if(tombstone_in_cache && tombstoneentry) {
|
|
|
dc8c34 |
+ cache_unlock_entry(&inst->inst_cache, tombstoneentry);
|
|
|
dc8c34 |
+ CACHE_RETURN(&inst->inst_cache, &tombstoneentry);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ if (addingentry_in_cache && addingentry) {
|
|
|
dc8c34 |
+ if ((0 == retval) && entryrdn_get_switch()) { /* subtree-rename: on */
|
|
|
dc8c34 |
+ /* since the op was successful, add the addingentry's dn to the dn cache */
|
|
|
dc8c34 |
+ struct backdn *bdn = dncache_find_id(&inst->inst_dncache,
|
|
|
dc8c34 |
+ addingentry->ep_id);
|
|
|
dc8c34 |
+ if (bdn) { /* already in the dncache */
|
|
|
dc8c34 |
+ CACHE_RETURN(&inst->inst_dncache, &bdn;;
|
|
|
dc8c34 |
+ } else { /* not in the dncache yet */
|
|
|
dc8c34 |
+ Slapi_DN *addingsdn = slapi_sdn_dup(slapi_entry_get_sdn(addingentry->ep_entry));
|
|
|
dc8c34 |
+ if (addingsdn) {
|
|
|
dc8c34 |
+ bdn = backdn_init(addingsdn, addingentry->ep_id, 0);
|
|
|
dc8c34 |
+ if (bdn) {
|
|
|
dc8c34 |
+ CACHE_ADD( &inst->inst_dncache, bdn, NULL );
|
|
|
dc8c34 |
+ CACHE_RETURN(&inst->inst_dncache, &bdn;;
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_CACHE, "ldbm_back_add",
|
|
|
dc8c34 |
+ "set %s to dn cache\n", slapi_sdn_get_dn(sdn));
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ CACHE_RETURN( &inst->inst_cache, &addingentry );
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
/* bepost op needs to know this result */
|
|
|
dc8c34 |
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &ldap_result_code);
|
|
|
dc8c34 |
/* JCMREPL - The bepostop is called even if the operation fails. */
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_delete.c b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
|
|
|
dc8c34 |
index c9ce70f..32feeb1 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/back-ldbm/ldbm_delete.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/back-ldbm/ldbm_delete.c
|
|
|
dc8c34 |
@@ -91,6 +91,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
/* replication, we must create a new tombstone entry */
|
|
|
dc8c34 |
int tombstone_in_cache = 0;
|
|
|
dc8c34 |
int e_in_cache = 0;
|
|
|
dc8c34 |
+ int remove_e_from_cache = 0;
|
|
|
dc8c34 |
entry_address *addr;
|
|
|
dc8c34 |
int addordel_flags = 0; /* passed to index_addordel */
|
|
|
dc8c34 |
char *entryusn_str = NULL;
|
|
|
dc8c34 |
@@ -178,18 +179,29 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* find and lock the entry we are about to modify */
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * A corner case:
|
|
|
dc8c34 |
+ * If a conflict occurred in a MMR topology, a replicated delete
|
|
|
dc8c34 |
+ * op from another master could target a conflict entry; while the
|
|
|
dc8c34 |
+ * corresponding entry on this server could have been already
|
|
|
dc8c34 |
+ * deleted. That is, the entry 'e' found with "addr" is a tomb-
|
|
|
dc8c34 |
+ * stone. If it is the case, we need to back off.
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
if ( (e = find_entry2modify( pb, be, addr, &txn )) == NULL )
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
ldap_result_code= LDAP_NO_SUCH_OBJECT;
|
|
|
dc8c34 |
/* retval is -1 */
|
|
|
dc8c34 |
+ LDAPDebug0Args(LDAP_DEBUG_BACKLDBM, "ldbm_back_delete: Deleting entry is already deleted.\n");
|
|
|
dc8c34 |
goto error_return; /* error result sent by find_entry2modify() */
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
e_in_cache = 1; /* e is cached */
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- if ( slapi_entry_has_children( e->ep_entry ) )
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
+ retval = slapi_entry_has_children(e->ep_entry);
|
|
|
dc8c34 |
+ if (retval) {
|
|
|
dc8c34 |
ldap_result_code= LDAP_NOT_ALLOWED_ON_NONLEAF;
|
|
|
dc8c34 |
- /* retval is -1 */
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_delete", "Deleting entry %s has %d children.\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(e->ep_entry), retval);
|
|
|
dc8c34 |
+ retval = -1;
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -221,7 +233,17 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
* Plugin indicated some kind of failure,
|
|
|
dc8c34 |
* or that this Operation became a No-Op.
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
+ slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
|
|
|
dc8c34 |
if (!ldap_result_code) {
|
|
|
dc8c34 |
+ if (LDAP_ALREADY_EXISTS == ldap_result_code) {
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * The target entry is already a tombstone.
|
|
|
dc8c34 |
+ * We need to treat this as a success,
|
|
|
dc8c34 |
+ * but we need to remove the entry e from the entry cache.
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ remove_e_from_cache = 1;
|
|
|
dc8c34 |
+ ldap_result_code = LDAP_SUCCESS;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
slapi_pblock_get(pb, SLAPI_RESULT_CODE, &ldap_result_code);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
/* restore original entry so the front-end delete code can free it */
|
|
|
dc8c34 |
@@ -233,8 +255,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
/* the flag could be set in a preop plugin (e.g., USN) */
|
|
|
dc8c34 |
- delete_tombstone_entry = operation_is_flag_set(operation,
|
|
|
dc8c34 |
- OP_FLAG_TOMBSTONE_ENTRY);
|
|
|
dc8c34 |
+ delete_tombstone_entry = operation_is_flag_set(operation, OP_FLAG_TOMBSTONE_ENTRY);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
@@ -370,13 +391,15 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (NULL == parent) {
|
|
|
dc8c34 |
entry_address parent_addr;
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
+ if (is_tombstone_entry) {
|
|
|
dc8c34 |
+ parent_addr.uniqueid = slapi_entry_attr_get_charptr(e->ep_entry, SLAPI_ATTR_VALUE_PARENT_UNIQUEID);
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ parent_addr.uniqueid = NULL;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
parent_addr.sdn = &parentsdn;
|
|
|
dc8c34 |
- parent_addr.uniqueid = NULL;
|
|
|
dc8c34 |
- parent = find_entry2modify_only_ext(pb, be, &parent_addr,
|
|
|
dc8c34 |
- TOMBSTONE_INCLUDED, &txn);
|
|
|
dc8c34 |
+ parent = find_entry2modify_only_ext(pb, be, &parent_addr, TOMBSTONE_INCLUDED, &txn);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if (NULL != parent) {
|
|
|
dc8c34 |
+ if (parent) {
|
|
|
dc8c34 |
int isglue;
|
|
|
dc8c34 |
size_t haschildren = 0;
|
|
|
dc8c34 |
int op = PARENTUPDATE_DEL;
|
|
|
dc8c34 |
@@ -393,11 +416,11 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
} else if (delete_tombstone_entry) {
|
|
|
dc8c34 |
op |= PARENTUPDATE_DELETE_TOMBSTONE;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- retval = parent_update_on_childchange(&parent_modify_c,
|
|
|
dc8c34 |
- op, &haschildren);
|
|
|
dc8c34 |
+ retval = parent_update_on_childchange(&parent_modify_c, op, &haschildren);
|
|
|
dc8c34 |
/* The modify context now contains info needed later */
|
|
|
dc8c34 |
if (0 != retval) {
|
|
|
dc8c34 |
ldap_result_code= LDAP_OPERATIONS_ERROR;
|
|
|
dc8c34 |
+ slapi_sdn_done(&parentsdn);
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -426,10 +449,18 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
const char *childuniqueid= slapi_entry_get_uniqueid(e->ep_entry);
|
|
|
dc8c34 |
const char *parentuniqueid= NULL;
|
|
|
dc8c34 |
- char *tombstone_dn = compute_entry_tombstone_dn(slapi_entry_get_dn(e->ep_entry),
|
|
|
dc8c34 |
- childuniqueid);
|
|
|
dc8c34 |
+ char *edn = slapi_entry_get_dn(e->ep_entry);
|
|
|
dc8c34 |
+ char *tombstone_dn;
|
|
|
dc8c34 |
Slapi_Value *tomb_value;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+ if (slapi_is_special_rdn(edn, RDN_IS_TOMBSTONE)) {
|
|
|
dc8c34 |
+ LDAPDebug1Arg(LDAP_DEBUG_ANY, "Turning a tombstone into a tombstone! \"%s\"\n", edn);
|
|
|
dc8c34 |
+ ldap_result_code= LDAP_OPERATIONS_ERROR;
|
|
|
dc8c34 |
+ retval = -1;
|
|
|
dc8c34 |
+ goto error_return;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ tombstone_dn = compute_entry_tombstone_dn(edn, childuniqueid);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
slapi_sdn_set_ndn_byval(&nscpEntrySDN, slapi_sdn_get_ndn(slapi_entry_get_sdn(e->ep_entry)));
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* Copy the entry unique_id for URP conflict checking */
|
|
|
dc8c34 |
@@ -471,6 +502,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if ( (original_tombstone = backentry_dup( tombstone )) == NULL ) {
|
|
|
dc8c34 |
ldap_result_code= LDAP_OPERATIONS_ERROR;
|
|
|
dc8c34 |
+ retval = -1;
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -505,6 +537,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
if (tombstone_in_cache) {
|
|
|
dc8c34 |
CACHE_REMOVE(&inst->inst_cache, tombstone);
|
|
|
dc8c34 |
CACHE_RETURN(&inst->inst_cache, &tombstone);
|
|
|
dc8c34 |
+ tombstone = NULL;
|
|
|
dc8c34 |
tombstone_in_cache = 0;
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
backentry_free(&tombstone);
|
|
|
dc8c34 |
@@ -515,13 +548,6 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- /* reset original entry in cache */
|
|
|
dc8c34 |
- if (!e_in_cache) {
|
|
|
dc8c34 |
- CACHE_ADD(&inst->inst_cache, e, NULL);
|
|
|
dc8c34 |
- e_in_cache = 1;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
if (ruv_c_init) {
|
|
|
dc8c34 |
/* reset the ruv txn stuff */
|
|
|
dc8c34 |
modify_term(&ruv_c, be);
|
|
|
dc8c34 |
@@ -615,41 +641,85 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
* tentatively for now, then cache_add again when the original
|
|
|
dc8c34 |
* entry is removed from the cache.
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
- if (cache_add_tentative( &inst->inst_cache, tombstone, NULL) == 0) {
|
|
|
dc8c34 |
+ retval = cache_add_tentative(&inst->inst_cache, tombstone, NULL);
|
|
|
dc8c34 |
+ if (0 == retval) {
|
|
|
dc8c34 |
tombstone_in_cache = 1;
|
|
|
dc8c34 |
- } else if (!(tombstone->ep_state & ENTRY_STATE_NOTINCACHE)) {
|
|
|
dc8c34 |
- LDAPDebug1Arg(LDAP_DEBUG_CACHE,
|
|
|
dc8c34 |
- "id2entry_add tombstone (%s) is in cache\n",
|
|
|
dc8c34 |
- slapi_entry_get_dn(tombstone->ep_entry));
|
|
|
dc8c34 |
- tombstone_in_cache = 1;
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ LDAPDebug2Args(LDAP_DEBUG_ANY,
|
|
|
dc8c34 |
+ "tombstone entry %s failed to add to the cache: %d\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(tombstone->ep_entry), retval);
|
|
|
dc8c34 |
+ tombstone_in_cache = 0;
|
|
|
dc8c34 |
+ if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
|
|
|
dc8c34 |
+ DEL_SET_ERROR(ldap_result_code,
|
|
|
dc8c34 |
+ LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
+ goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
retval = id2entry_add( be, tombstone, &txn );
|
|
|
dc8c34 |
if (DB_LOCK_DEADLOCK == retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_ARGS, "delete 1 DB_LOCK_DEADLOCK\n", 0, 0, 0 );
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_BACKLDBM, "delete 1 DB_LOCK_DEADLOCK\n", 0, 0, 0 );
|
|
|
dc8c34 |
/* Abort and re-try */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if (0 != retval) {
|
|
|
dc8c34 |
+ if (retval) {
|
|
|
dc8c34 |
LDAPDebug( LDAP_DEBUG_ANY, "id2entry_add failed, err=%d %s\n",
|
|
|
dc8c34 |
- retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
|
|
|
dc8c34 |
+ retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
|
|
|
dc8c34 |
if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
|
|
|
dc8c34 |
- DEL_SET_ERROR(ldap_result_code,
|
|
|
dc8c34 |
- LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
+ DEL_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if (cache_replace( &inst->inst_cache, e, tombstone ) != 0 ) {
|
|
|
dc8c34 |
- LDAPDebug0Args( LDAP_DEBUG_BACKLDBM, "ldbm_back_delete cache_replace failed\n");
|
|
|
dc8c34 |
- DEL_SET_ERROR(ldap_result_code,
|
|
|
dc8c34 |
- LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
- retval= -1;
|
|
|
dc8c34 |
- goto error_return;
|
|
|
dc8c34 |
+ if (tombstone_in_cache) {
|
|
|
dc8c34 |
+ retval = cache_replace(&inst->inst_cache, e, tombstone);
|
|
|
dc8c34 |
+ if (retval) {
|
|
|
dc8c34 |
+ LDAPDebug(LDAP_DEBUG_CACHE, "ldbm_back_delete: cache_replace failed (%d): %s --> %s\n",
|
|
|
dc8c34 |
+ retval, slapi_entry_get_dn(e->ep_entry), slapi_entry_get_dn(tombstone->ep_entry));
|
|
|
dc8c34 |
+ retval= -1;
|
|
|
dc8c34 |
+ DEL_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
+ goto error_return;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
- e_in_cache = 0; /* e un-cached */
|
|
|
dc8c34 |
+ struct backentry *imposter = NULL;
|
|
|
dc8c34 |
+ retval = CACHE_ADD(&inst->inst_cache, tombstone, &imposter);
|
|
|
dc8c34 |
+ if (retval > 0) {
|
|
|
dc8c34 |
+ if (imposter) {
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * The same tombstone entry (different Slapi_Entry) is already
|
|
|
dc8c34 |
+ * generated and set to cache. Back off.
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ CACHE_RETURN(&inst->inst_cache, &imposter);
|
|
|
dc8c34 |
+ LDAPDebug1Arg(LDAP_DEBUG_CACHE,
|
|
|
dc8c34 |
+ "ldbm_delete: cache add: same DN tombstone in cache: %s\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(tombstone->ep_entry));
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ /*
|
|
|
dc8c34 |
+ * The same tombstone entry (same Slapi_Entry) is being created.
|
|
|
dc8c34 |
+ * Something is wrong. We should clean it up from the cache,
|
|
|
dc8c34 |
+ * and back off.
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ tombstone_in_cache = 1;
|
|
|
dc8c34 |
+ LDAPDebug1Arg(LDAP_DEBUG_CACHE,
|
|
|
dc8c34 |
+ "ldbm_delete: cache add: same tombstone in cache: %s\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(tombstone->ep_entry));
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ retval= -1;
|
|
|
dc8c34 |
+ DEL_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
+ goto error_return;
|
|
|
dc8c34 |
+ } else if (retval < 0) {
|
|
|
dc8c34 |
+ LDAPDebug1Arg(LDAP_DEBUG_CACHE,
|
|
|
dc8c34 |
+ "ldbm_delete: cache add: Add %s failed.\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(tombstone->ep_entry));
|
|
|
dc8c34 |
+ /* Complete add error */
|
|
|
dc8c34 |
+ retval= -1;
|
|
|
dc8c34 |
+ DEL_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
+ goto error_return;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- /* tombstone was already added to the cache via cache_add_tentative (to reserve its spot in the cache)
|
|
|
dc8c34 |
- and/or id2entry_add - so it already had one refcount - cache_replace adds another refcount -
|
|
|
dc8c34 |
- drop the extra ref added by cache_replace */
|
|
|
dc8c34 |
- CACHE_RETURN( &inst->inst_cache, &tombstone );
|
|
|
dc8c34 |
+ if (tombstone_in_cache) {
|
|
|
dc8c34 |
+ /* tombstone was already added to the cache via cache_add_tentative (to reserve its spot in the cache)
|
|
|
dc8c34 |
+ and/or id2entry_add - so it already had one refcount - cache_replace adds another refcount -
|
|
|
dc8c34 |
+ drop the extra ref added by cache_replace */
|
|
|
dc8c34 |
+ CACHE_RETURN( &inst->inst_cache, &tombstone );
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ tombstone_in_cache = 1;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
else
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
@@ -657,12 +727,12 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
retval = id2entry_delete( be, e, &txn );
|
|
|
dc8c34 |
if (DB_LOCK_DEADLOCK == retval)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_ARGS, "delete 2 DEADLOCK\n", 0, 0, 0 );
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_BACKLDBM, "delete 2 DEADLOCK\n", 0, 0, 0 );
|
|
|
dc8c34 |
/* Retry txn */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (retval != 0 ) {
|
|
|
dc8c34 |
- if (retval == DB_RUNRECOVERY ||
|
|
|
dc8c34 |
+ if (retval == DB_RUNRECOVERY ||
|
|
|
dc8c34 |
LDBM_OS_ERR_IS_DISKFULL(retval)) {
|
|
|
dc8c34 |
disk_full = 1;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -680,12 +750,13 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
retval = index_addordel_entry( be, e, addordel_flags, &txn );
|
|
|
dc8c34 |
if (DB_LOCK_DEADLOCK == retval)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_ARGS, "delete 1 DEADLOCK\n", 0, 0, 0 );
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_BACKLDBM, "delete 1 DEADLOCK\n", 0, 0, 0 );
|
|
|
dc8c34 |
/* Retry txn */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if (retval != 0) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE, "index_del_entry failed\n", 0, 0, 0 );
|
|
|
dc8c34 |
+ if (retval) {
|
|
|
dc8c34 |
+ LDAPDebug(LDAP_DEBUG_ANY, "index_del_entry(%s, 0x%x) failed (%d)\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(e->ep_entry), addordel_flags, retval);
|
|
|
dc8c34 |
DEL_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -700,14 +771,14 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
SLAPI_ATTR_VALUE_TOMBSTONE,
|
|
|
dc8c34 |
tombstone->ep_id,BE_INDEX_ADD, &txn);
|
|
|
dc8c34 |
if (DB_LOCK_DEADLOCK == retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_ARGS,
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_BACKLDBM,
|
|
|
dc8c34 |
"delete (adding %s) DB_LOCK_DEADLOCK\n",
|
|
|
dc8c34 |
SLAPI_ATTR_VALUE_TOMBSTONE, 0, 0 );
|
|
|
dc8c34 |
/* Retry txn */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (0 != retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE,
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_ANY,
|
|
|
dc8c34 |
"delete (adding %s) failed, err=%d %s\n",
|
|
|
dc8c34 |
SLAPI_ATTR_VALUE_TOMBSTONE, retval,
|
|
|
dc8c34 |
(msg = dblayer_strerror( retval )) ? msg : "" );
|
|
|
dc8c34 |
@@ -720,14 +791,14 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
slapi_entry_get_uniqueid(tombstone->ep_entry),
|
|
|
dc8c34 |
tombstone->ep_id,BE_INDEX_ADD,&txn);
|
|
|
dc8c34 |
if (DB_LOCK_DEADLOCK == retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_ARGS,
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_BACKLDBM,
|
|
|
dc8c34 |
"delete (adding %s) DB_LOCK_DEADLOCK\n",
|
|
|
dc8c34 |
SLAPI_ATTR_UNIQUEID, 0, 0 );
|
|
|
dc8c34 |
/* Retry txn */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (0 != retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE,
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_ANY,
|
|
|
dc8c34 |
"delete (adding %s) failed, err=%d %s\n",
|
|
|
dc8c34 |
SLAPI_ATTR_UNIQUEID, retval,
|
|
|
dc8c34 |
(msg = dblayer_strerror( retval )) ? msg : "" );
|
|
|
dc8c34 |
@@ -740,14 +811,14 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
slapi_sdn_get_ndn(&nscpEntrySDN),
|
|
|
dc8c34 |
tombstone->ep_id, BE_INDEX_ADD, &txn);
|
|
|
dc8c34 |
if (DB_LOCK_DEADLOCK == retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_ARGS,
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_BACKLDBM,
|
|
|
dc8c34 |
"delete (adding %s) DB_LOCK_DEADLOCK\n",
|
|
|
dc8c34 |
SLAPI_ATTR_NSCP_ENTRYDN, 0, 0 );
|
|
|
dc8c34 |
/* Retry txn */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (0 != retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE,
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_ANY,
|
|
|
dc8c34 |
"delete (adding %s) failed, err=%d %s\n",
|
|
|
dc8c34 |
SLAPI_ATTR_NSCP_ENTRYDN, retval,
|
|
|
dc8c34 |
(msg = dblayer_strerror( retval )) ? msg : "" );
|
|
|
dc8c34 |
@@ -764,14 +835,14 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
entryusn_str, tombstone->ep_id, BE_INDEX_ADD, &txn);
|
|
|
dc8c34 |
slapi_ch_free_string(&entryusn_str);
|
|
|
dc8c34 |
if (DB_LOCK_DEADLOCK == retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_ARGS,
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_BACKLDBM,
|
|
|
dc8c34 |
"delete (adding %s) DB_LOCK_DEADLOCK\n",
|
|
|
dc8c34 |
SLAPI_ATTR_ENTRYUSN, 0, 0 );
|
|
|
dc8c34 |
/* Retry txn */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (0 != retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE,
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_ANY,
|
|
|
dc8c34 |
"delete (adding %s) failed, err=%d %s\n",
|
|
|
dc8c34 |
SLAPI_ATTR_ENTRYUSN, retval,
|
|
|
dc8c34 |
(msg = dblayer_strerror( retval )) ? msg : "" );
|
|
|
dc8c34 |
@@ -795,13 +866,13 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
svals, NULL, e->ep_id,
|
|
|
dc8c34 |
BE_INDEX_ADD, &txn);
|
|
|
dc8c34 |
if (DB_LOCK_DEADLOCK == retval) {
|
|
|
dc8c34 |
- LDAPDebug0Args( LDAP_DEBUG_ARGS,
|
|
|
dc8c34 |
+ LDAPDebug0Args( LDAP_DEBUG_BACKLDBM,
|
|
|
dc8c34 |
"delete (updating " LDBM_PARENTID_STR ") DB_LOCK_DEADLOCK\n");
|
|
|
dc8c34 |
/* Retry txn */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if ( retval ) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE,
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_ANY,
|
|
|
dc8c34 |
"delete (deleting %s) failed, err=%d %s\n",
|
|
|
dc8c34 |
LDBM_PARENTID_STR, retval,
|
|
|
dc8c34 |
(msg = dblayer_strerror( retval )) ? msg : "" );
|
|
|
dc8c34 |
@@ -811,15 +882,16 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+#if 0 /* The entryrdn element is already deleted in the index_addordel_entry */
|
|
|
dc8c34 |
retval = entryrdn_index_entry(be, e, BE_INDEX_DEL, &txn);
|
|
|
dc8c34 |
if (DB_LOCK_DEADLOCK == retval) {
|
|
|
dc8c34 |
- LDAPDebug0Args( LDAP_DEBUG_ARGS,
|
|
|
dc8c34 |
+ LDAPDebug0Args( LDAP_DEBUG_BACKLDBM,
|
|
|
dc8c34 |
"delete (deleting entryrdn) DB_LOCK_DEADLOCK\n");
|
|
|
dc8c34 |
/* Retry txn */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if (0 != retval) {
|
|
|
dc8c34 |
- LDAPDebug2Args( LDAP_DEBUG_TRACE,
|
|
|
dc8c34 |
+ if (retval) {
|
|
|
dc8c34 |
+ LDAPDebug2Args( LDAP_DEBUG_ANY,
|
|
|
dc8c34 |
"delete (deleting entryrdn) failed, err=%d %s\n",
|
|
|
dc8c34 |
retval,
|
|
|
dc8c34 |
(msg = dblayer_strerror( retval )) ? msg : "" );
|
|
|
dc8c34 |
@@ -828,21 +900,22 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+#endif
|
|
|
dc8c34 |
retval = entryrdn_index_entry(be, tombstone, BE_INDEX_ADD, &txn);
|
|
|
dc8c34 |
if (DB_LOCK_DEADLOCK == retval) {
|
|
|
dc8c34 |
- LDAPDebug0Args( LDAP_DEBUG_ARGS,
|
|
|
dc8c34 |
+ LDAPDebug0Args( LDAP_DEBUG_BACKLDBM,
|
|
|
dc8c34 |
"adding (adding tombstone entryrdn) DB_LOCK_DEADLOCK\n");
|
|
|
dc8c34 |
/* Retry txn */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if (0 != retval) {
|
|
|
dc8c34 |
- LDAPDebug2Args( LDAP_DEBUG_TRACE,
|
|
|
dc8c34 |
- "adding (adding tombstone entryrdn) failed, err=%d %s\n",
|
|
|
dc8c34 |
- retval,
|
|
|
dc8c34 |
- (msg = dblayer_strerror( retval )) ? msg : "" );
|
|
|
dc8c34 |
+ if (retval) {
|
|
|
dc8c34 |
+ LDAPDebug(LDAP_DEBUG_ANY,
|
|
|
dc8c34 |
+ "adding (adding tombstone entryrdn %s) failed, err=%d %s\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(tombstone->ep_entry),
|
|
|
dc8c34 |
+ retval, (msg = dblayer_strerror( retval )) ? msg : "" );
|
|
|
dc8c34 |
+ if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
|
|
|
dc8c34 |
if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
|
|
|
dc8c34 |
- DEL_SET_ERROR(ldap_result_code,
|
|
|
dc8c34 |
- LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
+ DEL_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -859,14 +932,14 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
SLAPI_ATTR_VALUE_TOMBSTONE, e->ep_id,
|
|
|
dc8c34 |
BE_INDEX_DEL, &txn);
|
|
|
dc8c34 |
if (DB_LOCK_DEADLOCK == retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_ARGS,
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_BACKLDBM,
|
|
|
dc8c34 |
"delete (deleting %s) DB_LOCK_DEADLOCK\n",
|
|
|
dc8c34 |
SLAPI_ATTR_VALUE_TOMBSTONE, 0, 0 );
|
|
|
dc8c34 |
/* Retry txn */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (0 != retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE,
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_ANY,
|
|
|
dc8c34 |
"delete (deleting %s) failed, err=%d %s\n",
|
|
|
dc8c34 |
SLAPI_ATTR_VALUE_TOMBSTONE, retval,
|
|
|
dc8c34 |
(msg = dblayer_strerror( retval )) ? msg : "" );
|
|
|
dc8c34 |
@@ -879,14 +952,14 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
slapi_entry_get_uniqueid(e->ep_entry),
|
|
|
dc8c34 |
e->ep_id, BE_INDEX_DEL, &txn);
|
|
|
dc8c34 |
if (DB_LOCK_DEADLOCK == retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_ARGS,
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_BACKLDBM,
|
|
|
dc8c34 |
"delete (deleting %s) DB_LOCK_DEADLOCK\n",
|
|
|
dc8c34 |
SLAPI_ATTR_UNIQUEID, 0, 0 );
|
|
|
dc8c34 |
/* Retry txn */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (0 != retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE,
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_ANY,
|
|
|
dc8c34 |
"delete (deleting %s) failed, err=%d %s\n",
|
|
|
dc8c34 |
SLAPI_ATTR_UNIQUEID, retval,
|
|
|
dc8c34 |
(msg = dblayer_strerror( retval )) ? msg : "" );
|
|
|
dc8c34 |
@@ -903,14 +976,14 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
nscpedn, e->ep_id, BE_INDEX_DEL, &txn);
|
|
|
dc8c34 |
slapi_ch_free((void **)&nscpedn);
|
|
|
dc8c34 |
if (DB_LOCK_DEADLOCK == retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_ARGS,
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_BACKLDBM,
|
|
|
dc8c34 |
"delete (deleting %s) DB_LOCK_DEADLOCK\n",
|
|
|
dc8c34 |
SLAPI_ATTR_NSCP_ENTRYDN, 0, 0 );
|
|
|
dc8c34 |
/* Retry txn */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (0 != retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE,
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_ANY,
|
|
|
dc8c34 |
"delete (deleting %s) failed, err=%d %s\n",
|
|
|
dc8c34 |
SLAPI_ATTR_NSCP_ENTRYDN, retval,
|
|
|
dc8c34 |
(msg = dblayer_strerror( retval )) ? msg : "" );
|
|
|
dc8c34 |
@@ -929,14 +1002,14 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
BE_INDEX_DEL|BE_INDEX_EQUALITY, &txn);
|
|
|
dc8c34 |
slapi_ch_free_string(&entryusn_str);
|
|
|
dc8c34 |
if (DB_LOCK_DEADLOCK == retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_ARGS,
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_BACKLDBM,
|
|
|
dc8c34 |
"delete (deleting %s) DB_LOCK_DEADLOCK\n",
|
|
|
dc8c34 |
SLAPI_ATTR_ENTRYUSN, 0, 0 );
|
|
|
dc8c34 |
/* Retry txn */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (0 != retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE,
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_ANY,
|
|
|
dc8c34 |
"delete (deleting %s) failed, err=%d %s\n",
|
|
|
dc8c34 |
SLAPI_ATTR_ENTRYUSN, retval,
|
|
|
dc8c34 |
(msg = dblayer_strerror( retval )) ? msg : "" );
|
|
|
dc8c34 |
@@ -950,13 +1023,13 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
retval = entryrdn_index_entry(be, e, BE_INDEX_DEL, &txn);
|
|
|
dc8c34 |
if (DB_LOCK_DEADLOCK == retval) {
|
|
|
dc8c34 |
- LDAPDebug0Args( LDAP_DEBUG_ARGS,
|
|
|
dc8c34 |
+ LDAPDebug0Args( LDAP_DEBUG_BACKLDBM,
|
|
|
dc8c34 |
"delete (deleting entryrdn) DB_LOCK_DEADLOCK\n");
|
|
|
dc8c34 |
/* Retry txn */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (0 != retval) {
|
|
|
dc8c34 |
- LDAPDebug2Args( LDAP_DEBUG_TRACE,
|
|
|
dc8c34 |
+ LDAPDebug2Args( LDAP_DEBUG_ANY,
|
|
|
dc8c34 |
"delete (deleting entryrdn) failed, err=%d %s\n",
|
|
|
dc8c34 |
retval,
|
|
|
dc8c34 |
(msg = dblayer_strerror( retval )) ? msg : "" );
|
|
|
dc8c34 |
@@ -973,12 +1046,12 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
retval = modify_update_all(be,pb,&parent_modify_c,&txn);
|
|
|
dc8c34 |
if (DB_LOCK_DEADLOCK == retval)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_ARGS, "del 4 DEADLOCK\n", 0, 0, 0 );
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_BACKLDBM, "del 4 DEADLOCK\n", 0, 0, 0 );
|
|
|
dc8c34 |
/* Retry txn */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (0 != retval) {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE, "delete 3 BAD, err=%d %s\n",
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_ANY, "delete 3 BAD, err=%d %s\n",
|
|
|
dc8c34 |
retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
|
|
|
dc8c34 |
if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
|
|
|
dc8c34 |
DEL_SET_ERROR(ldap_result_code,
|
|
|
dc8c34 |
@@ -996,7 +1069,7 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if (DB_LOCK_DEADLOCK == retval)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_ARGS, "delete DEADLOCK vlv_update_index\n", 0, 0, 0 );
|
|
|
dc8c34 |
+ LDAPDebug( LDAP_DEBUG_BACKLDBM, "delete DEADLOCK vlv_update_index\n", 0, 0, 0 );
|
|
|
dc8c34 |
/* Retry txn */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -1087,14 +1160,24 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* delete from cache and clean up */
|
|
|
dc8c34 |
if (e) {
|
|
|
dc8c34 |
+ if (entryrdn_get_switch()) { /* subtree-rename: on */
|
|
|
dc8c34 |
+ /* since the op was successful, delete the tombstone dn from the dn cache */
|
|
|
dc8c34 |
+ struct backdn *bdn = dncache_find_id(&inst->inst_dncache, e->ep_id);
|
|
|
dc8c34 |
+ if (bdn) { /* in the dncache, remove it. */
|
|
|
dc8c34 |
+ CACHE_REMOVE(&inst->inst_dncache, bdn);
|
|
|
dc8c34 |
+ CACHE_RETURN(&inst->inst_dncache, &bdn;;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
if (e_in_cache) {
|
|
|
dc8c34 |
CACHE_REMOVE(&inst->inst_cache, e);
|
|
|
dc8c34 |
+ cache_unlock_entry(&inst->inst_cache, e);
|
|
|
dc8c34 |
+ CACHE_RETURN(&inst->inst_cache, &e);
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ cache_unlock_entry(&inst->inst_cache, e);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- cache_unlock_entry(&inst->inst_cache, e);
|
|
|
dc8c34 |
- CACHE_RETURN(&inst->inst_cache, &e);
|
|
|
dc8c34 |
e = NULL;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
if (ruv_c_init) {
|
|
|
dc8c34 |
if (modify_switch_entries(&ruv_c, be) != 0 ) {
|
|
|
dc8c34 |
ldap_result_code= LDAP_OPERATIONS_ERROR;
|
|
|
dc8c34 |
@@ -1115,16 +1198,37 @@ ldbm_back_delete( Slapi_PBlock *pb )
|
|
|
dc8c34 |
goto common_return;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
error_return:
|
|
|
dc8c34 |
- if (tombstone_in_cache)
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
- CACHE_REMOVE( &inst->inst_cache, tombstone );
|
|
|
dc8c34 |
- CACHE_RETURN( &inst->inst_cache, &tombstone );
|
|
|
dc8c34 |
- tombstone = NULL;
|
|
|
dc8c34 |
- tombstone_in_cache = 0;
|
|
|
dc8c34 |
+ if (tombstone) {
|
|
|
dc8c34 |
+ if (entryrdn_get_switch()) { /* subtree-rename: on */
|
|
|
dc8c34 |
+ /* since the op was successful, add the addingentry's dn to the dn cache */
|
|
|
dc8c34 |
+ struct backdn *bdn = dncache_find_id(&inst->inst_dncache, tombstone->ep_id);
|
|
|
dc8c34 |
+ if (bdn) { /* already in the dncache. Delete it. */
|
|
|
dc8c34 |
+ CACHE_REMOVE(&inst->inst_dncache, bdn);
|
|
|
dc8c34 |
+ CACHE_RETURN(&inst->inst_dncache, &bdn;;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ if (tombstone_in_cache) { /* successfully replaced */
|
|
|
dc8c34 |
+ CACHE_REMOVE( &inst->inst_cache, tombstone );
|
|
|
dc8c34 |
+ CACHE_RETURN( &inst->inst_cache, &tombstone );
|
|
|
dc8c34 |
+ tombstone = NULL;
|
|
|
dc8c34 |
+ tombstone_in_cache = 0;
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ backentry_free( &tombstone );
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- else
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
- backentry_free( &tombstone );
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ /* Need to return to cache after post op plugins are called */
|
|
|
dc8c34 |
+ if (e) {
|
|
|
dc8c34 |
+ if (e_in_cache) {
|
|
|
dc8c34 |
+ if (remove_e_from_cache) {
|
|
|
dc8c34 |
+ /* The entry is already transformed to a tombstone. */
|
|
|
dc8c34 |
+ CACHE_REMOVE( &inst->inst_cache, e );
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ cache_unlock_entry( &inst->inst_cache, e );
|
|
|
dc8c34 |
+ CACHE_RETURN( &inst->inst_cache, &e );
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ cache_unlock_entry( &inst->inst_cache, e );
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if (retval == DB_RUNRECOVERY) {
|
|
|
dc8c34 |
@@ -1184,15 +1288,32 @@ common_return:
|
|
|
dc8c34 |
for the post op plugins */
|
|
|
dc8c34 |
slapi_pblock_set( pb, SLAPI_DELETE_BEPREOP_ENTRY, orig_entry );
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if (tombstone_in_cache)
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
- CACHE_RETURN( &inst->inst_cache, &tombstone );
|
|
|
dc8c34 |
- tombstone = NULL;
|
|
|
dc8c34 |
- tombstone_in_cache = 0;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- else
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
- backentry_free( &tombstone );
|
|
|
dc8c34 |
+ if (tombstone) {
|
|
|
dc8c34 |
+ if ((0 == retval) && entryrdn_get_switch()) { /* subtree-rename: on */
|
|
|
dc8c34 |
+ /* since the op was successful, add the addingentry's dn to the dn cache */
|
|
|
dc8c34 |
+ struct backdn *bdn = dncache_find_id(&inst->inst_dncache, tombstone->ep_id);
|
|
|
dc8c34 |
+ if (bdn) { /* already in the dncache */
|
|
|
dc8c34 |
+ CACHE_RETURN(&inst->inst_dncache, &bdn;;
|
|
|
dc8c34 |
+ } else { /* not in the dncache yet */
|
|
|
dc8c34 |
+ Slapi_DN *tombstonesdn = slapi_sdn_dup(slapi_entry_get_sdn(tombstone->ep_entry));
|
|
|
dc8c34 |
+ if (tombstonesdn) {
|
|
|
dc8c34 |
+ bdn = backdn_init(tombstonesdn, tombstone->ep_id, 0);
|
|
|
dc8c34 |
+ if (bdn) {
|
|
|
dc8c34 |
+ CACHE_ADD( &inst->inst_dncache, bdn, NULL );
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_CACHE, "ldbm_back_delete",
|
|
|
dc8c34 |
+ "set %s to dn cache\n", slapi_sdn_get_dn(tombstonesdn));
|
|
|
dc8c34 |
+ CACHE_RETURN(&inst->inst_dncache, &bdn;;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ if (tombstone_in_cache) { /* successfully replaced */
|
|
|
dc8c34 |
+ CACHE_RETURN( &inst->inst_cache, &tombstone );
|
|
|
dc8c34 |
+ tombstone = NULL;
|
|
|
dc8c34 |
+ tombstone_in_cache = 0;
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ backentry_free( &tombstone );
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* result code could be used in the bepost plugin functions. */
|
|
|
dc8c34 |
@@ -1205,14 +1326,6 @@ common_return:
|
|
|
dc8c34 |
plugin_call_plugins (pb, SLAPI_PLUGIN_BE_POST_DELETE_FN);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- /* Need to return to cache after post op plugins are called */
|
|
|
dc8c34 |
- if (retval) { /* error case */
|
|
|
dc8c34 |
- if (e) {
|
|
|
dc8c34 |
- cache_unlock_entry( &inst->inst_cache, e );
|
|
|
dc8c34 |
- CACHE_RETURN( &inst->inst_cache, &e );
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
if (ruv_c_init) {
|
|
|
dc8c34 |
modify_term(&ruv_c, be);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -1222,7 +1335,7 @@ diskfull_return:
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
slapi_send_ldap_result( pb, ldap_result_code, NULL, ldap_result_message, 0, NULL );
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- modify_term(&parent_modify_c,be);
|
|
|
dc8c34 |
+ modify_term(&parent_modify_c, be);
|
|
|
dc8c34 |
if(dblock_acquired)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
dblayer_unlock_backend(be);
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
|
|
|
dc8c34 |
index 887f74b..6426fb7 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
|
|
|
dc8c34 |
@@ -387,7 +387,7 @@ entryrdn_index_read_ext(backend *be,
|
|
|
dc8c34 |
|
|
|
dc8c34 |
rc = slapi_rdn_init_all_sdn(&srdn, sdn);
|
|
|
dc8c34 |
if (rc < 0) {
|
|
|
dc8c34 |
- slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_BACKLDBM, ENTRYRDN_TAG,
|
|
|
dc8c34 |
"entryrdn_index_read: Param error: Failed to convert "
|
|
|
dc8c34 |
"%s to Slapi_RDN\n", slapi_sdn_get_dn(sdn));
|
|
|
dc8c34 |
rc = LDAP_INVALID_DN_SYNTAX;
|
|
|
dc8c34 |
@@ -501,7 +501,8 @@ entryrdn_rename_subtree(backend *be,
|
|
|
dc8c34 |
Slapi_RDN *newsrdn, /* new rdn */
|
|
|
dc8c34 |
const Slapi_DN *newsupsdn, /* new superior dn */
|
|
|
dc8c34 |
ID id,
|
|
|
dc8c34 |
- back_txn *txn)
|
|
|
dc8c34 |
+ back_txn *txn,
|
|
|
dc8c34 |
+ int flags)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
int rc = -1;
|
|
|
dc8c34 |
struct attrinfo *ai = NULL;
|
|
|
dc8c34 |
@@ -543,7 +544,7 @@ entryrdn_rename_subtree(backend *be,
|
|
|
dc8c34 |
goto bail;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- rc = slapi_rdn_init_all_sdn(&oldsrdn, oldsdn);
|
|
|
dc8c34 |
+ rc = slapi_rdn_init_all_sdn_ext(&oldsrdn, oldsdn, flags);
|
|
|
dc8c34 |
if (rc < 0) {
|
|
|
dc8c34 |
slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
|
|
|
dc8c34 |
"entryrdn_rename_subtree: Failed to convert olddn "
|
|
|
dc8c34 |
@@ -968,7 +969,8 @@ entryrdn_get_subordinates(backend *be,
|
|
|
dc8c34 |
const Slapi_DN *sdn,
|
|
|
dc8c34 |
ID id,
|
|
|
dc8c34 |
IDList **subordinates,
|
|
|
dc8c34 |
- back_txn *txn)
|
|
|
dc8c34 |
+ back_txn *txn,
|
|
|
dc8c34 |
+ int flags)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
int rc = -1;
|
|
|
dc8c34 |
struct attrinfo *ai = NULL;
|
|
|
dc8c34 |
@@ -1000,7 +1002,7 @@ entryrdn_get_subordinates(backend *be,
|
|
|
dc8c34 |
goto bail;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- rc = slapi_rdn_init_all_sdn(&srdn, sdn);
|
|
|
dc8c34 |
+ rc = slapi_rdn_init_all_sdn_ext(&srdn, sdn, flags);
|
|
|
dc8c34 |
if (rc) {
|
|
|
dc8c34 |
if (rc < 0) {
|
|
|
dc8c34 |
slapi_log_error(SLAPI_LOG_FATAL, ENTRYRDN_TAG,
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modify.c b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
|
|
|
dc8c34 |
index be47fcc..f7ebac1 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/back-ldbm/ldbm_modify.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modify.c
|
|
|
dc8c34 |
@@ -116,8 +116,14 @@ int modify_switch_entries(modify_context *mc,backend *be)
|
|
|
dc8c34 |
ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
|
|
|
dc8c34 |
int ret = 0;
|
|
|
dc8c34 |
if (mc->old_entry!=NULL && mc->new_entry!=NULL) {
|
|
|
dc8c34 |
- ret = cache_replace(&(inst->inst_cache), mc->old_entry, mc->new_entry);
|
|
|
dc8c34 |
- if (ret == 0) mc->new_entry_in_cache = 1;
|
|
|
dc8c34 |
+ ret = cache_replace(&(inst->inst_cache), mc->old_entry, mc->new_entry);
|
|
|
dc8c34 |
+ if (ret == 0) {
|
|
|
dc8c34 |
+ mc->new_entry_in_cache = 1;
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ LDAPDebug(LDAP_DEBUG_CACHE, "modify_switch_entries: replacing %s with %s failed (%d)\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(mc->old_entry->ep_entry),
|
|
|
dc8c34 |
+ slapi_entry_get_dn(mc->new_entry->ep_entry), ret);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
return ret;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -154,6 +160,10 @@ modify_unswitch_entries(modify_context *mc,backend *be)
|
|
|
dc8c34 |
CACHE_RETURN( &(inst->inst_cache), &(mc->old_entry) );
|
|
|
dc8c34 |
mc->new_entry_in_cache = 1;
|
|
|
dc8c34 |
mc->old_entry = NULL;
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ LDAPDebug(LDAP_DEBUG_CACHE, "modify_unswitch_entries: replacing %s with %s failed (%d)\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(mc->old_entry->ep_entry),
|
|
|
dc8c34 |
+ slapi_entry_get_dn(mc->new_entry->ep_entry), ret);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -722,6 +732,12 @@ ldbm_back_modify( Slapi_PBlock *pb )
|
|
|
dc8c34 |
MOD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+ /* e uncached */
|
|
|
dc8c34 |
+ /* we must return both e (which has been deleted) and new entry ec */
|
|
|
dc8c34 |
+ /* cache_replace removes e from the caches */
|
|
|
dc8c34 |
+ cache_unlock_entry( &inst->inst_cache, e );
|
|
|
dc8c34 |
+ CACHE_RETURN( &inst->inst_cache, &e );
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
/* lock new entry in cache to prevent usage until we are complete */
|
|
|
dc8c34 |
cache_lock_entry( &inst->inst_cache, ec );
|
|
|
dc8c34 |
ec_in_cache = 1;
|
|
|
dc8c34 |
@@ -732,10 +748,6 @@ ldbm_back_modify( Slapi_PBlock *pb )
|
|
|
dc8c34 |
/* invalidate virtual cache */
|
|
|
dc8c34 |
ec->ep_entry->e_virtual_watermark = 0;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- /* we must return both e (which has been deleted) and new entry ec */
|
|
|
dc8c34 |
- /* cache_replace removes e from the caches */
|
|
|
dc8c34 |
- cache_unlock_entry( &inst->inst_cache, e );
|
|
|
dc8c34 |
- CACHE_RETURN( &inst->inst_cache, &e );
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* LP Fix of crash when the commit will fail:
|
|
|
dc8c34 |
* If the commit fail, the common error path will
|
|
|
dc8c34 |
@@ -833,8 +845,10 @@ error_return:
|
|
|
dc8c34 |
CACHE_REMOVE( &inst->inst_cache, ec );
|
|
|
dc8c34 |
/* if ec was in cache, e was not - add back e */
|
|
|
dc8c34 |
if (e) {
|
|
|
dc8c34 |
- CACHE_ADD( &inst->inst_cache, e, NULL );
|
|
|
dc8c34 |
- cache_lock_entry( &inst->inst_cache, e );
|
|
|
dc8c34 |
+ if (CACHE_ADD( &inst->inst_cache, e, NULL )) {
|
|
|
dc8c34 |
+ LDAPDebug1Arg( LDAP_DEBUG_CACHE, "ldbm_modify: CACHE_ADD %s failed\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(e->ep_entry));
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -849,11 +863,12 @@ common_return:
|
|
|
dc8c34 |
else
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
backentry_free(&ec);
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- if (e!=NULL) {
|
|
|
dc8c34 |
- cache_unlock_entry( &inst->inst_cache, e);
|
|
|
dc8c34 |
- CACHE_RETURN( &inst->inst_cache, &e);
|
|
|
dc8c34 |
+ /* if ec was not in cache, cache_replace was not done.
|
|
|
dc8c34 |
+ * i.e., e was not unlocked. */
|
|
|
dc8c34 |
+ if (e) {
|
|
|
dc8c34 |
+ cache_unlock_entry( &inst->inst_cache, e);
|
|
|
dc8c34 |
+ CACHE_RETURN( &inst->inst_cache, &e);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* result code could be used in the bepost plugin functions. */
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
|
|
|
dc8c34 |
index c539463..4e5ce45 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/back-ldbm/ldbm_modrdn.c
|
|
|
dc8c34 |
@@ -45,10 +45,10 @@
|
|
|
dc8c34 |
|
|
|
dc8c34 |
#include "back-ldbm.h"
|
|
|
dc8c34 |
|
|
|
dc8c34 |
-static const char *moddn_get_newdn(Slapi_PBlock *pb, Slapi_DN *dn_olddn, Slapi_DN *dn_newrdn, Slapi_DN *dn_newsuperiordn);
|
|
|
dc8c34 |
+static const char *moddn_get_newdn(Slapi_PBlock *pb, Slapi_DN *dn_olddn, Slapi_DN *dn_newrdn, Slapi_DN *dn_newsuperiordn, int is_tombstone);
|
|
|
dc8c34 |
static void moddn_unlock_and_return_entry(backend *be,struct backentry **targetentry);
|
|
|
dc8c34 |
static int moddn_newrdn_mods(Slapi_PBlock *pb, const char *olddn, struct backentry *ec, Slapi_Mods *smods_wsi, int is_repl_op);
|
|
|
dc8c34 |
-static IDList *moddn_get_children(back_txn *ptxn, Slapi_PBlock *pb, backend *be, struct backentry *parententry, Slapi_DN *parentdn, struct backentry ***child_entries, struct backdn ***child_dns);
|
|
|
dc8c34 |
+static IDList *moddn_get_children(back_txn *ptxn, Slapi_PBlock *pb, backend *be, struct backentry *parententry, Slapi_DN *parentdn, struct backentry ***child_entries, struct backdn ***child_dns, int is_resurect_operation);
|
|
|
dc8c34 |
static int moddn_rename_children(back_txn *ptxn, Slapi_PBlock *pb, backend *be, IDList *children, Slapi_DN *dn_parentdn, Slapi_DN *dn_newsuperiordn, struct backentry *child_entries[]);
|
|
|
dc8c34 |
static int modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbminfo *li, struct backentry *e, struct backentry **ec, Slapi_Mods *smods1, Slapi_Mods *smods2, Slapi_Mods *smods3, int *e_in_cache, int *ec_in_cache);
|
|
|
dc8c34 |
static void mods_remove_nsuniqueid(Slapi_Mods *smods);
|
|
|
dc8c34 |
@@ -111,6 +111,8 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
|
|
|
dc8c34 |
int dblock_acquired= 0;
|
|
|
dc8c34 |
int is_replicated_operation= 0;
|
|
|
dc8c34 |
int is_fixup_operation = 0;
|
|
|
dc8c34 |
+ int is_resurect_operation = 0;
|
|
|
dc8c34 |
+ int is_tombstone = 0;
|
|
|
dc8c34 |
entry_address new_addr;
|
|
|
dc8c34 |
entry_address *old_addr;
|
|
|
dc8c34 |
entry_address oldparent_addr;
|
|
|
dc8c34 |
@@ -136,6 +138,8 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
|
|
|
dc8c34 |
slapi_pblock_get( pb, SLAPI_IS_REPLICATED_OPERATION, &is_replicated_operation );
|
|
|
dc8c34 |
is_ruv = operation_is_flag_set(operation, OP_FLAG_REPL_RUV);
|
|
|
dc8c34 |
is_fixup_operation = operation_is_flag_set(operation, OP_FLAG_REPL_FIXUP);
|
|
|
dc8c34 |
+ is_resurect_operation = operation_is_flag_set(operation,OP_FLAG_RESURECT_ENTRY);
|
|
|
dc8c34 |
+ is_tombstone = operation_is_flag_set(operation,OP_FLAG_TOMBSTONE_ENTRY); /* tombstone_to_glue on parent entry*/
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if (NULL == sdn) {
|
|
|
dc8c34 |
slapi_send_ldap_result( pb, LDAP_INVALID_DN_SYNTAX, NULL,
|
|
|
dc8c34 |
@@ -168,7 +172,13 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
|
|
|
dc8c34 |
slapi_pblock_get( pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &dn_newsuperiordn );
|
|
|
dc8c34 |
slapi_sdn_init_normdn_byref(&dn_newrdn, newrdn);
|
|
|
dc8c34 |
/* slapi_sdn_init_normdn_byref(&dn_newsuperiordn, newsuperiordn); */
|
|
|
dc8c34 |
- slapi_sdn_get_parent(sdn, &dn_parentdn);
|
|
|
dc8c34 |
+ if (is_resurect_operation) {
|
|
|
dc8c34 |
+ /* no need to free this pdn. */
|
|
|
dc8c34 |
+ const char *pdn = slapi_dn_find_parent_ext(slapi_sdn_get_dn(sdn), is_resurect_operation);
|
|
|
dc8c34 |
+ slapi_sdn_set_dn_byval(&dn_parentdn, pdn);
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ slapi_sdn_get_parent(sdn, &dn_parentdn);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* if old and new superior are equals, newsuperior should not be set
|
|
|
dc8c34 |
@@ -235,7 +245,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
|
|
|
dc8c34 |
* it's passed to slapi_sdn_init_normdn_byref */
|
|
|
dc8c34 |
slapi_pblock_get(pb, SLAPI_MODRDN_NEWRDN, &newrdn);
|
|
|
dc8c34 |
slapi_sdn_init_normdn_byref(&dn_newrdn, newrdn);
|
|
|
dc8c34 |
- newdn= moddn_get_newdn(pb,sdn, &dn_newrdn, dn_newsuperiordn);
|
|
|
dc8c34 |
+ newdn = moddn_get_newdn(pb, sdn, &dn_newrdn, dn_newsuperiordn, is_tombstone);
|
|
|
dc8c34 |
slapi_sdn_set_dn_passin(&dn_newdn,newdn);
|
|
|
dc8c34 |
new_addr.sdn = &dn_newdn;
|
|
|
dc8c34 |
new_addr.udn = NULL;
|
|
|
dc8c34 |
@@ -353,11 +363,14 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
e_in_cache = 1; /* e is in the cache and locked */
|
|
|
dc8c34 |
if (slapi_entry_flag_is_set(e->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE) ) {
|
|
|
dc8c34 |
- ldap_result_code = LDAP_UNWILLING_TO_PERFORM;
|
|
|
dc8c34 |
- ldap_result_message = "Operation not allowed on tombstone entry.";
|
|
|
dc8c34 |
- slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_modrdn",
|
|
|
dc8c34 |
- "Attempt to rename a tombstone entry %s\n", slapi_sdn_get_dn(slapi_entry_get_sdn_const( e->ep_entry )));
|
|
|
dc8c34 |
- goto error_return;
|
|
|
dc8c34 |
+ if (!is_resurect_operation) {
|
|
|
dc8c34 |
+ ldap_result_code = LDAP_UNWILLING_TO_PERFORM;
|
|
|
dc8c34 |
+ ldap_result_message = "Operation not allowed on tombstone entry.";
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_modrdn",
|
|
|
dc8c34 |
+ "Attempt to rename a tombstone entry %s\n",
|
|
|
dc8c34 |
+ slapi_sdn_get_dn(slapi_entry_get_sdn_const( e->ep_entry )));
|
|
|
dc8c34 |
+ goto error_return;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
/* Check that an entry with the same DN doesn't already exist. */
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
@@ -375,7 +388,11 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* Fetch and lock the parent of the entry that is moving */
|
|
|
dc8c34 |
oldparent_addr.sdn = &dn_parentdn;
|
|
|
dc8c34 |
- oldparent_addr.uniqueid = NULL;
|
|
|
dc8c34 |
+ if (is_resurect_operation) {
|
|
|
dc8c34 |
+ oldparent_addr.uniqueid = operation->o_params.p.p_modrdn.modrdn_newsuperior_address.uniqueid;
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ oldparent_addr.uniqueid = NULL;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
parententry = find_entry2modify_only( pb, be, &oldparent_addr, &txn );
|
|
|
dc8c34 |
modify_init(&parent_modify_context,parententry);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -383,7 +400,11 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
|
|
|
dc8c34 |
if(slapi_sdn_get_ndn(dn_newsuperiordn) != NULL)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
slapi_pblock_get (pb, SLAPI_MODRDN_NEWSUPERIOR_ADDRESS, &newsuperior_addr);
|
|
|
dc8c34 |
+ if (is_resurect_operation) {
|
|
|
dc8c34 |
+ newsuperior_addr->uniqueid = slapi_entry_attr_get_charptr(e->ep_entry, SLAPI_ATTR_VALUE_PARENT_UNIQUEID);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
newparententry = find_entry2modify_only( pb, be, newsuperior_addr, &txn );
|
|
|
dc8c34 |
+ slapi_ch_free_string(&newsuperior_addr->uniqueid);
|
|
|
dc8c34 |
modify_init(&newparent_modify_context,newparententry);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -426,8 +447,7 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
slapi_pblock_set( pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, dn_newsuperiordn );
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- slapi_sdn_set_dn_passin(&dn_newdn,
|
|
|
dc8c34 |
- moddn_get_newdn(pb, sdn, &dn_newrdn, dn_newsuperiordn));
|
|
|
dc8c34 |
+ slapi_sdn_set_dn_passin(&dn_newdn, moddn_get_newdn(pb, sdn, &dn_newrdn, dn_newsuperiordn, is_tombstone));
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* Check that we're allowed to add an entry below the new superior */
|
|
|
dc8c34 |
if ( newparententry == NULL )
|
|
|
dc8c34 |
@@ -528,6 +548,57 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
|
|
|
dc8c34 |
slapi_rdn_done(&srdn);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+ if(is_resurect_operation) {
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_REPL, "ldbm_back_modrdn",
|
|
|
dc8c34 |
+ "Resurrecting an entry %s\n", slapi_entry_get_dn(ec->ep_entry));
|
|
|
dc8c34 |
+ slapi_entry_attr_delete(ec->ep_entry, SLAPI_ATTR_VALUE_PARENT_UNIQUEID);
|
|
|
dc8c34 |
+ slapi_entry_delete_string(ec->ep_entry, SLAPI_ATTR_OBJECTCLASS, SLAPI_ATTR_VALUE_TOMBSTONE);
|
|
|
dc8c34 |
+ /* Now also remove the nscpEntryDN */
|
|
|
dc8c34 |
+ if (slapi_entry_attr_delete(ec->ep_entry, SLAPI_ATTR_NSCP_ENTRYDN) != 0){
|
|
|
dc8c34 |
+ LDAPDebug(LDAP_DEBUG_REPL, "Resurrection of %s - Couldn't remove %s\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(ec->ep_entry), SLAPI_ATTR_NSCP_ENTRYDN, 0);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ /* Set the reason (this is only a reason why modrdn is needed for resurrection) */
|
|
|
dc8c34 |
+ slapi_entry_add_string(ec->ep_entry, "nsds5ReplConflict", "deletedEntryHasChildren");
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ /* Clear the Tombstone Flag in the entry */
|
|
|
dc8c34 |
+ slapi_entry_clear_flag(ec->ep_entry, SLAPI_ENTRY_FLAG_TOMBSTONE);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ /* make sure the objectclass
|
|
|
dc8c34 |
+ - does not contain any duplicate values
|
|
|
dc8c34 |
+ - has CSNs for the new values we added
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+ {
|
|
|
dc8c34 |
+ Slapi_Attr *sa = NULL;
|
|
|
dc8c34 |
+ Slapi_Value sv;
|
|
|
dc8c34 |
+ const struct berval *svbv = NULL;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ /* add the extensibleobject objectclass with csn if not present */
|
|
|
dc8c34 |
+ slapi_entry_attr_find(ec->ep_entry, SLAPI_ATTR_OBJECTCLASS, &sa);
|
|
|
dc8c34 |
+ slapi_value_init_string(&sv, "extensibleobject");
|
|
|
dc8c34 |
+ svbv = slapi_value_get_berval(&sv;;
|
|
|
dc8c34 |
+ if (slapi_attr_value_find(sa, svbv)) { /* not found, so add it */
|
|
|
dc8c34 |
+ if (opcsn) {
|
|
|
dc8c34 |
+ value_update_csn(&sv, CSN_TYPE_VALUE_UPDATED, opcsn);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ slapi_attr_add_value(sa, &sv;;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ value_done(&sv;;
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ /* add the glue objectclass with csn if not present */
|
|
|
dc8c34 |
+ slapi_value_init_string(&sv, "glue");
|
|
|
dc8c34 |
+ svbv = slapi_value_get_berval(&sv;;
|
|
|
dc8c34 |
+ if (slapi_attr_value_find(sa, svbv)) { /* not found, so add it */
|
|
|
dc8c34 |
+ if (opcsn) {
|
|
|
dc8c34 |
+ value_update_csn(&sv, CSN_TYPE_VALUE_UPDATED, opcsn);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ slapi_attr_add_value(sa, &sv;;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ value_done(&sv;;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
/* create it in the cache - prevents others from creating it */
|
|
|
dc8c34 |
if (( cache_add_tentative( &inst->inst_cache, ec, NULL ) != 0 ) ) {
|
|
|
dc8c34 |
ec_in_cache = 0; /* not in cache */
|
|
|
dc8c34 |
@@ -537,6 +608,10 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
|
|
|
dc8c34 |
/* somebody must've created it between dn2entry() and here */
|
|
|
dc8c34 |
/* JCMREPL - Hmm... we can't permit this to happen...? */
|
|
|
dc8c34 |
ldap_result_code= LDAP_ALREADY_EXISTS;
|
|
|
dc8c34 |
+ if (is_resurect_operation) {
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_CACHE, "ldbm_back_modrdn",
|
|
|
dc8c34 |
+ "cache_add_tentative failed: %s\n", slapi_entry_get_dn(ec->ep_entry));
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
/* so if the old dn is the same as the new dn, the entry will not be cached
|
|
|
dc8c34 |
@@ -584,8 +659,8 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
|
|
|
dc8c34 |
- slapi_mods_init_byref(&smods_operation_wsi,mods);
|
|
|
dc8c34 |
+ slapi_pblock_get( pb, SLAPI_MODIFY_MODS, &mods );
|
|
|
dc8c34 |
+ slapi_mods_init_byref(&smods_operation_wsi,mods);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* We are about to pass the last abandon test, so from now on we are
|
|
|
dc8c34 |
@@ -675,10 +750,8 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Update the subordinate count of the parents to reflect the moved child.
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
- if ( parententry!=NULL )
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
- retval = parent_update_on_childchange(&parent_modify_context,
|
|
|
dc8c34 |
- PARENTUPDATE_DEL, NULL);
|
|
|
dc8c34 |
+ if (parententry) {
|
|
|
dc8c34 |
+ retval = parent_update_on_childchange(&parent_modify_context, PARENTUPDATE_DEL, NULL);
|
|
|
dc8c34 |
/* The parent modify context now contains info needed later */
|
|
|
dc8c34 |
if (0 != retval)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
@@ -696,27 +769,64 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+ /* is_resurect_operation case, there's no new superior. Just rename. */
|
|
|
dc8c34 |
+ if (is_resurect_operation && parententry) {
|
|
|
dc8c34 |
+ retval = parent_update_on_childchange(&parent_modify_context, PARENTUPDATE_RESURECT, NULL);
|
|
|
dc8c34 |
+ if (retval) {
|
|
|
dc8c34 |
+ LDAPDebug(LDAP_DEBUG_BACKLDBM, "parent_update_on_childchange parent %s of %s failed, rc=%d\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn_const(parent_modify_context.old_entry->ep_entry),
|
|
|
dc8c34 |
+ slapi_entry_get_dn_const(ec->ep_entry), retval);
|
|
|
dc8c34 |
+ goto error_return;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
- * If the entry has children then we're going to have to rename them all.
|
|
|
dc8c34 |
+ * If the entry has children including tombstones,
|
|
|
dc8c34 |
+ * then we're going to have to rename them all.
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
- if (slapi_entry_has_children( e->ep_entry ))
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
+ if (slapi_entry_has_children_ext(e->ep_entry, 1)) {
|
|
|
dc8c34 |
/* JCM - This is where the subtree lock will appear */
|
|
|
dc8c34 |
if (entryrdn_get_switch()) /* subtree-rename: on */
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
+ if (is_resurect_operation) {
|
|
|
dc8c34 |
+#if defined(DEBUG)
|
|
|
dc8c34 |
+ /* Get the present value of the subcount attr, or 0 if not present */
|
|
|
dc8c34 |
+ Slapi_Attr *read_attr = NULL;
|
|
|
dc8c34 |
+ int sub_count = -1;
|
|
|
dc8c34 |
+ if (0 == slapi_entry_attr_find(parent_modify_context.old_entry->ep_entry,
|
|
|
dc8c34 |
+ "numsubordinates", &read_attr)) {
|
|
|
dc8c34 |
+ /* decode the value */
|
|
|
dc8c34 |
+ Slapi_Value *sval;
|
|
|
dc8c34 |
+ slapi_attr_first_value(read_attr, &sval);
|
|
|
dc8c34 |
+ if (sval) {
|
|
|
dc8c34 |
+ const struct berval *bval = slapi_value_get_berval(sval);
|
|
|
dc8c34 |
+ if(bval) {
|
|
|
dc8c34 |
+ sub_count = atol(bval->bv_val);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ LDAPDebug(LDAP_DEBUG_ANY, "parent_update_on_childchange parent %s of %s numsub=%d\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn_const(parent_modify_context.old_entry->ep_entry),
|
|
|
dc8c34 |
+ slapi_entry_get_dn_const(e->ep_entry), sub_count);
|
|
|
dc8c34 |
+#endif
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_BACKLDBM, "ldbm_back_modrdn",
|
|
|
dc8c34 |
+ "%s has children\n", slapi_entry_get_dn(e->ep_entry));
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
children = moddn_get_children(&txn, pb, be, e, sdn,
|
|
|
dc8c34 |
- &child_entries, &child_dns);
|
|
|
dc8c34 |
+ &child_entries, &child_dns, is_resurect_operation);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
else
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
children = moddn_get_children(&txn, pb, be, e, sdn,
|
|
|
dc8c34 |
- &child_entries, NULL);
|
|
|
dc8c34 |
+ &child_entries, NULL, 0);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* JCM - Shouldn't we perform an access control check on all the children. */
|
|
|
dc8c34 |
/* JCMREPL - But, the replication client has total rights over its subtree, so no access check needed. */
|
|
|
dc8c34 |
/* JCM - A subtree move could break ACIs, static groups, and dynamic groups. */
|
|
|
dc8c34 |
+ } else if (is_resurect_operation) {
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_modrdn",
|
|
|
dc8c34 |
+ "%s has NO children\n", slapi_entry_get_dn(e->ep_entry));
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
@@ -777,7 +887,11 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
/* make sure the original entry is back in the cache if it was removed */
|
|
|
dc8c34 |
if (!e_in_cache) {
|
|
|
dc8c34 |
- CACHE_ADD(&inst->inst_cache, e, NULL);
|
|
|
dc8c34 |
+ if (CACHE_ADD(&inst->inst_cache, e, NULL)) {
|
|
|
dc8c34 |
+ LDAPDebug1Arg(LDAP_DEBUG_CACHE,
|
|
|
dc8c34 |
+ "ldbm_back_modrdn: CACHE_ADD %s to cache failed\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn_const(e->ep_entry));
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
e_in_cache = 1;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
slapi_pblock_get( pb, SLAPI_MODRDN_EXISTING_ENTRY, &ent );
|
|
|
dc8c34 |
@@ -820,11 +934,11 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- if (ruv_c_init) {
|
|
|
dc8c34 |
- /* reset the ruv txn stuff */
|
|
|
dc8c34 |
- modify_term(&ruv_c, be);
|
|
|
dc8c34 |
- ruv_c_init = 0;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
+ if (ruv_c_init) {
|
|
|
dc8c34 |
+ /* reset the ruv txn stuff */
|
|
|
dc8c34 |
+ modify_term(&ruv_c, be);
|
|
|
dc8c34 |
+ ruv_c_init = 0;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
/* We're re-trying */
|
|
|
dc8c34 |
LDAPDebug0Args(LDAP_DEBUG_BACKLDBM,
|
|
|
dc8c34 |
"Modrdn Retrying Transaction\n");
|
|
|
dc8c34 |
@@ -871,10 +985,10 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
|
|
|
dc8c34 |
/* Retry txn */
|
|
|
dc8c34 |
continue;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if (retval != 0 )
|
|
|
dc8c34 |
+ if (retval)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE, "modrdn_rename_entry_update_indexes failed, err=%d %s\n",
|
|
|
dc8c34 |
- retval, (msg = dblayer_strerror( retval )) ? msg : "", 0 );
|
|
|
dc8c34 |
+ LDAPDebug(LDAP_DEBUG_ANY, "modrdn_rename_entry_update_indexes %s --> %s failed, err=%d\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(e->ep_entry), slapi_entry_get_dn(ec->ep_entry), retval);
|
|
|
dc8c34 |
if (LDBM_OS_ERR_IS_DISKFULL(retval)) disk_full = 1;
|
|
|
dc8c34 |
MOD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
@@ -994,14 +1108,17 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
|
|
|
dc8c34 |
slapi_rdn_init_sdn(&newsrdn, (const Slapi_DN *)&dn_newdn);
|
|
|
dc8c34 |
retval = entryrdn_rename_subtree(be, (const Slapi_DN *)sdn, &newsrdn,
|
|
|
dc8c34 |
(const Slapi_DN *)dn_newsuperiordn,
|
|
|
dc8c34 |
- e->ep_id, &txn);
|
|
|
dc8c34 |
+ e->ep_id, &txn, is_tombstone);
|
|
|
dc8c34 |
slapi_rdn_done(&newsrdn);
|
|
|
dc8c34 |
if (retval != 0) {
|
|
|
dc8c34 |
if (retval == DB_LOCK_DEADLOCK) continue;
|
|
|
dc8c34 |
if (retval == DB_RUNRECOVERY || LDBM_OS_ERR_IS_DISKFULL(retval))
|
|
|
dc8c34 |
disk_full = 1;
|
|
|
dc8c34 |
- MOD_SET_ERROR(ldap_result_code,
|
|
|
dc8c34 |
- LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
+ MOD_SET_ERROR(ldap_result_code, LDAP_OPERATIONS_ERROR, retry_count);
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_FATAL, "ldbm_back_modrdn",
|
|
|
dc8c34 |
+ "entryrdn_rename_subtree failed (%d); dn: %s, newsrdn: %s, dn_newsuperiordn: %s\n",
|
|
|
dc8c34 |
+ retval, slapi_sdn_get_dn(sdn), slapi_rdn_get_rdn(&newsrdn),
|
|
|
dc8c34 |
+ slapi_sdn_get_dn(dn_newsuperiordn));
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -1125,6 +1242,12 @@ ldbm_back_modrdn( Slapi_PBlock *pb )
|
|
|
dc8c34 |
* "renamed" dn is generated based upon the moved subtree.
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
for (i = 0; child_entries[i] != NULL; i++) {
|
|
|
dc8c34 |
+ if (is_resurect_operation) {
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_CACHE, "ldbm_back_modrdn",
|
|
|
dc8c34 |
+ "Calling cache remove & return %s (refcnt: %d)\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(child_entries[i]->ep_entry),
|
|
|
dc8c34 |
+ child_entries[i]->ep_refcnt);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
CACHE_REMOVE( &inst->inst_cache, child_entries[i] );
|
|
|
dc8c34 |
cache_unlock_entry( &inst->inst_cache, child_entries[i] );
|
|
|
dc8c34 |
CACHE_RETURN( &inst->inst_cache, &child_entries[i] );
|
|
|
dc8c34 |
@@ -1168,12 +1291,6 @@ error_return:
|
|
|
dc8c34 |
/* make sure caller doesn't attempt to free this */
|
|
|
dc8c34 |
slapi_pblock_set( pb, SLAPI_ENTRY_POST_OP, postentry );
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- if (e && entryrdn_get_switch())
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
- struct backdn *bdn = dncache_find_id(&inst->inst_dncache, e->ep_id);
|
|
|
dc8c34 |
- CACHE_REMOVE(&inst->inst_dncache, bdn);
|
|
|
dc8c34 |
- CACHE_RETURN(&inst->inst_dncache, &bdn;;
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
if(children)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
int i = 0;
|
|
|
dc8c34 |
@@ -1270,9 +1387,32 @@ common_return:
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* Free up the resource we don't need any more */
|
|
|
dc8c34 |
if (ec) {
|
|
|
dc8c34 |
+ if (is_resurect_operation) {
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_REPL, "ldbm_back_modrdn",
|
|
|
dc8c34 |
+ "Resurrecting an entry %s: result: %d, %d\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(ec->ep_entry), ldap_result_code, retval);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ if ((0 == retval) && entryrdn_get_switch()) { /* subtree-rename: on */
|
|
|
dc8c34 |
+ /* since the op was successful, add the addingentry's dn to the dn cache */
|
|
|
dc8c34 |
+ struct backdn *bdn = dncache_find_id(&inst->inst_dncache, ec->ep_id);
|
|
|
dc8c34 |
+ if (bdn) { /* already in the dncache */
|
|
|
dc8c34 |
+ CACHE_RETURN(&inst->inst_dncache, &bdn;;
|
|
|
dc8c34 |
+ } else { /* not in the dncache yet */
|
|
|
dc8c34 |
+ Slapi_DN *ecsdn = slapi_sdn_dup(slapi_entry_get_sdn(ec->ep_entry));
|
|
|
dc8c34 |
+ if (ecsdn) {
|
|
|
dc8c34 |
+ bdn = backdn_init(ecsdn, ec->ep_id, 0);
|
|
|
dc8c34 |
+ if (bdn) {
|
|
|
dc8c34 |
+ CACHE_ADD( &inst->inst_dncache, bdn, NULL );
|
|
|
dc8c34 |
+ CACHE_RETURN(&inst->inst_dncache, &bdn;;
|
|
|
dc8c34 |
+ slapi_log_error(SLAPI_LOG_CACHE, "ldbm_back_modrdn",
|
|
|
dc8c34 |
+ "set %s to dn cache\n", slapi_sdn_get_dn(sdn));
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
/* remove the new entry from the cache if the op failed -
|
|
|
dc8c34 |
otherwise, leave it in */
|
|
|
dc8c34 |
- if (ec_in_cache && retval) {
|
|
|
dc8c34 |
+ if (ec_in_cache && ec && retval) {
|
|
|
dc8c34 |
CACHE_REMOVE( &inst->inst_cache, ec );
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (ec_in_cache) {
|
|
|
dc8c34 |
@@ -1286,9 +1426,10 @@ common_return:
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* put e back in the cache if the modrdn failed */
|
|
|
dc8c34 |
if (e) {
|
|
|
dc8c34 |
- if (!e_in_cache && retval) {
|
|
|
dc8c34 |
- CACHE_ADD(&inst->inst_cache, e, NULL);
|
|
|
dc8c34 |
- e_in_cache = 1;
|
|
|
dc8c34 |
+ if (entryrdn_get_switch() && (0 == retval)) {
|
|
|
dc8c34 |
+ struct backdn *bdn = dncache_find_id(&inst->inst_dncache, e->ep_id);
|
|
|
dc8c34 |
+ CACHE_REMOVE(&inst->inst_dncache, bdn);
|
|
|
dc8c34 |
+ CACHE_RETURN(&inst->inst_dncache, &bdn;;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -1352,7 +1493,7 @@ common_return:
|
|
|
dc8c34 |
* Work out what the new DN of the entry will be.
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
static const char *
|
|
|
dc8c34 |
-moddn_get_newdn(Slapi_PBlock *pb, Slapi_DN *dn_olddn, Slapi_DN *dn_newrdn, Slapi_DN *dn_newsuperiordn)
|
|
|
dc8c34 |
+moddn_get_newdn(Slapi_PBlock *pb, Slapi_DN *dn_olddn, Slapi_DN *dn_newrdn, Slapi_DN *dn_newsuperiordn, int is_tombstone)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
char *newdn;
|
|
|
dc8c34 |
const char *newrdn= slapi_sdn_get_dn(dn_newrdn);
|
|
|
dc8c34 |
@@ -1373,18 +1514,18 @@ moddn_get_newdn(Slapi_PBlock *pb, Slapi_DN *dn_olddn, Slapi_DN *dn_newrdn, Slapi
|
|
|
dc8c34 |
else
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
/* construct the new dn */
|
|
|
dc8c34 |
- char *pdn;
|
|
|
dc8c34 |
- const char *dn= slapi_sdn_get_dn(dn_olddn);
|
|
|
dc8c34 |
- pdn = slapi_dn_beparent( pb, dn );
|
|
|
dc8c34 |
- if ( pdn != NULL )
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
- newdn= slapi_dn_plus_rdn(pdn, newrdn); /* JCM - Use Slapi_RDN */
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
- else
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
- newdn= slapi_ch_strdup(newrdn);
|
|
|
dc8c34 |
+ const char *dn = slapi_sdn_get_dn((const Slapi_DN *)dn_olddn);
|
|
|
dc8c34 |
+ if (slapi_dn_isbesuffix(pb, dn)) {
|
|
|
dc8c34 |
+ newdn = slapi_ch_strdup(newrdn);
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ /* no need to free this pdn. */
|
|
|
dc8c34 |
+ const char *pdn = slapi_dn_find_parent_ext(dn, is_tombstone);
|
|
|
dc8c34 |
+ if (pdn) {
|
|
|
dc8c34 |
+ newdn = slapi_dn_plus_rdn(pdn, newrdn);
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ newdn = slapi_ch_strdup(newrdn);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- slapi_ch_free( (void**)&pdn );
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
return newdn;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -1611,6 +1752,7 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbm
|
|
|
dc8c34 |
Slapi_Operation *operation;
|
|
|
dc8c34 |
int is_ruv = 0; /* True if the current entry is RUV */
|
|
|
dc8c34 |
int orig_ec_in_cache = 0;
|
|
|
dc8c34 |
+ int cache_rc = 0;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
slapi_pblock_get( pb, SLAPI_BACKEND, &be );
|
|
|
dc8c34 |
slapi_pblock_get( pb, SLAPI_OPERATION, &operation );
|
|
|
dc8c34 |
@@ -1622,7 +1764,12 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbm
|
|
|
dc8c34 |
* Update the ID to Entry index.
|
|
|
dc8c34 |
* Note that id2entry_add replaces the entry, so the Entry ID stays the same.
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
- retval = id2entry_add( be, *ec, ptxn );
|
|
|
dc8c34 |
+ retval = id2entry_add_ext(be, *ec, ptxn, 1, &cache_rc);
|
|
|
dc8c34 |
+ if (cache_rc) {
|
|
|
dc8c34 |
+ LDAPDebug(LDAP_DEBUG_CACHE,
|
|
|
dc8c34 |
+ "modrdn_rename_entry_update_indexes: adding %s failed to add to the cache (rc: %d, cache_rc: %d)\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(e->ep_entry), retval, cache_rc);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
if (DB_LOCK_DEADLOCK == retval)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
/* Retry txn */
|
|
|
dc8c34 |
@@ -1716,11 +1863,11 @@ modrdn_rename_entry_update_indexes(back_txn *ptxn, Slapi_PBlock *pb, struct ldbm
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (cache_replace( &inst->inst_cache, e, *ec ) != 0 ) {
|
|
|
dc8c34 |
- LDAPDebug0Args( LDAP_DEBUG_BACKLDBM, "modrdn_rename_entry_update_indexes cache_replace failed\n");
|
|
|
dc8c34 |
+ LDAPDebug2Args(LDAP_DEBUG_CACHE,
|
|
|
dc8c34 |
+ "modrdn_rename_entry_update_indexes cache_replace %s -> %s failed\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(e->ep_entry), slapi_entry_get_dn((*ec)->ep_entry));
|
|
|
dc8c34 |
retval= -1;
|
|
|
dc8c34 |
goto error_return;
|
|
|
dc8c34 |
- } else {
|
|
|
dc8c34 |
- *e_in_cache = 0; /* e un-cached */
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
if (orig_ec_in_cache) {
|
|
|
dc8c34 |
/* ec was already added to the cache via cache_add_tentative (to reserve its spot in the cache)
|
|
|
dc8c34 |
@@ -1936,7 +2083,8 @@ moddn_get_children(back_txn *ptxn,
|
|
|
dc8c34 |
struct backentry *parententry,
|
|
|
dc8c34 |
Slapi_DN *dn_parentdn,
|
|
|
dc8c34 |
struct backentry ***child_entries,
|
|
|
dc8c34 |
- struct backdn ***child_dns)
|
|
|
dc8c34 |
+ struct backdn ***child_dns,
|
|
|
dc8c34 |
+ int is_resurect_operation)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
ldbm_instance *inst = (ldbm_instance *) be->be_instance_info;
|
|
|
dc8c34 |
int err= 0;
|
|
|
dc8c34 |
@@ -1964,7 +2112,7 @@ moddn_get_children(back_txn *ptxn,
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
err = entryrdn_get_subordinates(be,
|
|
|
dc8c34 |
slapi_entry_get_sdn_const(parententry->ep_entry),
|
|
|
dc8c34 |
- parententry->ep_id, &candidates, ptxn);
|
|
|
dc8c34 |
+ parententry->ep_id, &candidates, ptxn, is_resurect_operation);
|
|
|
dc8c34 |
if (err) {
|
|
|
dc8c34 |
LDAPDebug1Arg( LDAP_DEBUG_ANY, "moddn_get_children: "
|
|
|
dc8c34 |
"entryrdn_get_subordinates returned %d\n", err);
|
|
|
dc8c34 |
@@ -1985,6 +2133,12 @@ moddn_get_children(back_txn *ptxn,
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if (candidates!=NULL)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
+ Slapi_DN parentsdn = {0};
|
|
|
dc8c34 |
+ if (is_resurect_operation) {
|
|
|
dc8c34 |
+ slapi_sdn_get_parent(dn_parentdn, &parentsdn);
|
|
|
dc8c34 |
+ dn_parentdn = &parentsdn;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
sr_current = idl_iterator_init(candidates);
|
|
|
dc8c34 |
result_idl= idl_alloc(candidates->b_nids);
|
|
|
dc8c34 |
do
|
|
|
dc8c34 |
@@ -2017,6 +2171,7 @@ moddn_get_children(back_txn *ptxn,
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
} while (id!=NOID);
|
|
|
dc8c34 |
idl_free(candidates);
|
|
|
dc8c34 |
+ slapi_sdn_done(&parentsdn);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
nids = result_idl ? result_idl->b_nids : 0;
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_search.c b/ldap/servers/slapd/back-ldbm/ldbm_search.c
|
|
|
dc8c34 |
index a097307..746528e 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/back-ldbm/ldbm_search.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/back-ldbm/ldbm_search.c
|
|
|
dc8c34 |
@@ -1164,7 +1164,7 @@ subtree_candidates(
|
|
|
dc8c34 |
/* subtree-rename: on && no ancestorid */
|
|
|
dc8c34 |
*err = entryrdn_get_subordinates(be,
|
|
|
dc8c34 |
slapi_entry_get_sdn_const(e->ep_entry),
|
|
|
dc8c34 |
- e->ep_id, &descendants, &txn);
|
|
|
dc8c34 |
+ e->ep_id, &descendants, &txn, 0);
|
|
|
dc8c34 |
idl_insert(&descendants, e->ep_id);
|
|
|
dc8c34 |
candidates = idl_intersection(be, candidates, descendants);
|
|
|
dc8c34 |
idl_free(tmp);
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
|
|
|
dc8c34 |
index 47e0269..51ff62b 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
|
|
|
dc8c34 |
@@ -898,7 +898,7 @@ static IDList *ldbm_fetch_subtrees(backend *be, char **include, int *err)
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
if (entryrdn_get_noancestorid()) {
|
|
|
dc8c34 |
/* subtree-rename: on && no ancestorid */
|
|
|
dc8c34 |
- *err = entryrdn_get_subordinates(be, &sdn, id, &idl, txn);
|
|
|
dc8c34 |
+ *err = entryrdn_get_subordinates(be, &sdn, id, &idl, txn, 0);
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
*err = ldbm_ancestorid_read(be, txn, id, &idl);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/back-ldbm/parents.c b/ldap/servers/slapd/back-ldbm/parents.c
|
|
|
dc8c34 |
index 7ca9f24..669eaef 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/back-ldbm/parents.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/back-ldbm/parents.c
|
|
|
dc8c34 |
@@ -58,11 +58,17 @@ char *tombstone_numsubordinates = LDBM_TOMBSTONE_NUMSUBORDINATES_STR;
|
|
|
dc8c34 |
* The routine is allowed to modify the parent entry, and to return a set of
|
|
|
dc8c34 |
* LDAPMods reflecting the changes it made. The LDAPMods array must be freed
|
|
|
dc8c34 |
* by the called by calling ldap_free_mods(p,1)
|
|
|
dc8c34 |
+ *
|
|
|
dc8c34 |
+ * PARENTUPDATE_RESURECT == turning a tombstone into an entry
|
|
|
dc8c34 |
+ * tombstone_numsubordinates--
|
|
|
dc8c34 |
+ * numsubordinates++
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
- * PARENTUPDATE_CREATE_TOMBSTONE: increment tombstone_numsubordinates
|
|
|
dc8c34 |
+ * PARENTUPDATE_CREATE_TOMBSTONE: turning an entry into a tombstone
|
|
|
dc8c34 |
+ * numsubordinates--
|
|
|
dc8c34 |
+ * tombstone_numsubordinates++
|
|
|
dc8c34 |
* PARENTUPDATE_DELETE_TOMBSTONE: don't touch numsubordinates, and
|
|
|
dc8c34 |
- * decrement tombstone_numsubordinates
|
|
|
dc8c34 |
+ * tombstone_numsubordinates--
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
|
|
|
dc8c34 |
int
|
|
|
dc8c34 |
@@ -84,7 +90,7 @@ parent_update_on_childchange(modify_context *mc,int op, size_t *new_sub_count )
|
|
|
dc8c34 |
op &= PARENTUPDATE_MASK;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* Check nobody is trying to use op == 3, it's not implemented yet */
|
|
|
dc8c34 |
- PR_ASSERT( (op == PARENTUPDATE_ADD) || (op == PARENTUPDATE_DEL));
|
|
|
dc8c34 |
+ PR_ASSERT((op == PARENTUPDATE_ADD) || (op == PARENTUPDATE_DEL) || (op == PARENTUPDATE_RESURECT));
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* We want to invent a mods set to be passed to modify_apply_mods() */
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -114,16 +120,17 @@ parent_update_on_childchange(modify_context *mc,int op, size_t *new_sub_count )
|
|
|
dc8c34 |
|
|
|
dc8c34 |
if (PARENTUPDATE_DELETE_TOMBSTONE != repl_op) {
|
|
|
dc8c34 |
/* are we adding ? */
|
|
|
dc8c34 |
- if ( (PARENTUPDATE_ADD == op) && !already_present) {
|
|
|
dc8c34 |
+ if (((PARENTUPDATE_ADD == op) || (PARENTUPDATE_RESURECT == op)) && !already_present) {
|
|
|
dc8c34 |
/* If so, and the parent entry does not already have a subcount
|
|
|
dc8c34 |
* attribute, we need to add it */
|
|
|
dc8c34 |
mod_op = LDAP_MOD_ADD;
|
|
|
dc8c34 |
} else if (PARENTUPDATE_DEL == op) {
|
|
|
dc8c34 |
if (!already_present) {
|
|
|
dc8c34 |
/* This means that something is wrong---deleting a child but no subcount present on parent */
|
|
|
dc8c34 |
- LDAPDebug0Args( LDAP_DEBUG_ANY,
|
|
|
dc8c34 |
- "numsubordinates assertion failure\n" );
|
|
|
dc8c34 |
+ LDAPDebug(LDAP_DEBUG_ANY, "Parent %s has no children. (op 0x%x, repl_op 0x%x)\n",
|
|
|
dc8c34 |
+ slapi_entry_get_dn(mc->old_entry->ep_entry), op, repl_op);
|
|
|
dc8c34 |
slapi_mods_free(&smods);
|
|
|
dc8c34 |
+ PR_ASSERT(0);
|
|
|
dc8c34 |
return -1;
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
if (current_sub_count == 1) {
|
|
|
dc8c34 |
@@ -138,7 +145,7 @@ parent_update_on_childchange(modify_context *mc,int op, size_t *new_sub_count )
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* Now compute the new value */
|
|
|
dc8c34 |
- if (PARENTUPDATE_ADD == op) {
|
|
|
dc8c34 |
+ if ((PARENTUPDATE_ADD == op) || (PARENTUPDATE_RESURECT == op)) {
|
|
|
dc8c34 |
current_sub_count++;
|
|
|
dc8c34 |
} else {
|
|
|
dc8c34 |
current_sub_count--;
|
|
|
dc8c34 |
@@ -159,8 +166,8 @@ parent_update_on_childchange(modify_context *mc,int op, size_t *new_sub_count )
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* tombstoneNumSubordinates is needed only when this is repl op
|
|
|
dc8c34 |
* and a child is being deleted */
|
|
|
dc8c34 |
- if (repl_op && (PARENTUPDATE_DEL == op)) {
|
|
|
dc8c34 |
- current_sub_count = LDAP_MAXINT;
|
|
|
dc8c34 |
+ current_sub_count = LDAP_MAXINT;
|
|
|
dc8c34 |
+ if ((repl_op && (PARENTUPDATE_DEL == op)) || (PARENTUPDATE_RESURECT == op)) {
|
|
|
dc8c34 |
ret = slapi_entry_attr_find(mc->old_entry->ep_entry,
|
|
|
dc8c34 |
tombstone_numsubordinates, &read_attr);
|
|
|
dc8c34 |
if (0 == ret) {
|
|
|
dc8c34 |
@@ -175,7 +182,7 @@ parent_update_on_childchange(modify_context *mc,int op, size_t *new_sub_count )
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
- if (PARENTUPDATE_DELETE_TOMBSTONE == repl_op) {
|
|
|
dc8c34 |
+ if ((PARENTUPDATE_DELETE_TOMBSTONE == repl_op) || (PARENTUPDATE_RESURECT == op)) {
|
|
|
dc8c34 |
/* deleting a tombstone entry:
|
|
|
dc8c34 |
* reaping or manually deleting it */
|
|
|
dc8c34 |
if ((current_sub_count != LDAP_MAXINT) &&
|
|
|
dc8c34 |
@@ -187,9 +194,7 @@ parent_update_on_childchange(modify_context *mc,int op, size_t *new_sub_count )
|
|
|
dc8c34 |
tombstone_numsubordinates,
|
|
|
dc8c34 |
strlen(value_buffer), value_buffer);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
- }
|
|
|
dc8c34 |
-
|
|
|
dc8c34 |
- if (PARENTUPDATE_CREATE_TOMBSTONE == repl_op) {
|
|
|
dc8c34 |
+ } else if (PARENTUPDATE_CREATE_TOMBSTONE == repl_op) {
|
|
|
dc8c34 |
/* creating a tombstone entry */
|
|
|
dc8c34 |
if (current_sub_count != LDAP_MAXINT) {
|
|
|
dc8c34 |
current_sub_count++;
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
|
|
|
dc8c34 |
index 02b261b..f3c84a1 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/back-ldbm/proto-back-ldbm.h
|
|
|
dc8c34 |
@@ -190,6 +190,7 @@ struct backentry *dn2entry_ext(Slapi_Backend *be, const Slapi_DN *sdn, back_txn
|
|
|
dc8c34 |
struct backentry *dn2entry_or_ancestor(Slapi_Backend *be, const Slapi_DN *sdn, Slapi_DN *ancestor, back_txn *txn, int *err);
|
|
|
dc8c34 |
struct backentry *dn2ancestor(Slapi_Backend *be,const Slapi_DN *sdn,Slapi_DN *ancestordn,back_txn *txn,int *err);
|
|
|
dc8c34 |
int get_copy_of_entry(Slapi_PBlock *pb, const entry_address *addr, back_txn *txn, int plock_parameter, int must_exist);
|
|
|
dc8c34 |
+int get_copy_of_entry_ext(Slapi_PBlock *pb, ID id, const entry_address *addr, back_txn *txn, int plock_parameter, int must_exist);
|
|
|
dc8c34 |
void done_with_pblock_entry(Slapi_PBlock *pb, int plock_parameter);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
@@ -699,8 +700,8 @@ int entryrdn_index_entry(backend *be, struct backentry *e, int flags, back_txn *
|
|
|
dc8c34 |
int entryrdn_index_read(backend *be, const Slapi_DN *sdn, ID *id, back_txn *txn);
|
|
|
dc8c34 |
int
|
|
|
dc8c34 |
entryrdn_index_read_ext(backend *be, const Slapi_DN *sdn, ID *id, int flags, back_txn *txn);
|
|
|
dc8c34 |
-int entryrdn_rename_subtree(backend *be, const Slapi_DN *oldsdn, Slapi_RDN *newsrdn, const Slapi_DN *newsupsdn, ID id, back_txn *txn);
|
|
|
dc8c34 |
-int entryrdn_get_subordinates(backend *be, const Slapi_DN *sdn, ID id, IDList **subordinates, back_txn *txn);
|
|
|
dc8c34 |
+int entryrdn_rename_subtree(backend *be, const Slapi_DN *oldsdn, Slapi_RDN *newsrdn, const Slapi_DN *newsupsdn, ID id, back_txn *txn, int flags);
|
|
|
dc8c34 |
+int entryrdn_get_subordinates(backend *be, const Slapi_DN *sdn, ID id, IDList **subordinates, back_txn *txn, int flags);
|
|
|
dc8c34 |
int entryrdn_lookup_dn(backend *be, const char *rdn, ID id, char **dn, back_txn *txn);
|
|
|
dc8c34 |
int entryrdn_get_parent(backend *be, const char *rdn, ID id, char **prdn, ID *pid, back_txn *txn);
|
|
|
dc8c34 |
#endif
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/entry.c b/ldap/servers/slapd/entry.c
|
|
|
dc8c34 |
index a5a21e0..785256f 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/entry.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/entry.c
|
|
|
dc8c34 |
@@ -3090,9 +3090,10 @@ slapi_entry_add_rdn_values( Slapi_Entry *e )
|
|
|
dc8c34 |
* Author/Modifier: RJP
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
int
|
|
|
dc8c34 |
-slapi_entry_has_children(const Slapi_Entry *entry)
|
|
|
dc8c34 |
+slapi_entry_has_children_ext(const Slapi_Entry *entry, int include_tombstone)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
Slapi_Attr *attr;
|
|
|
dc8c34 |
+ int count = 0;
|
|
|
dc8c34 |
|
|
|
dc8c34 |
LDAPDebug( LDAP_DEBUG_TRACE, "=> slapi_has_children( %s )\n", slapi_entry_get_dn_const(entry), 0, 0);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -3102,15 +3103,34 @@ slapi_entry_has_children(const Slapi_Entry *entry)
|
|
|
dc8c34 |
Slapi_Value *sval;
|
|
|
dc8c34 |
slapi_attr_first_value( attr, &sval );
|
|
|
dc8c34 |
if(sval!=NULL)
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
+ {
|
|
|
dc8c34 |
const struct berval *bval = slapi_value_get_berval( sval );
|
|
|
dc8c34 |
if(bval!=NULL)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
/* The entry has the attribute, and it's non-zero */
|
|
|
dc8c34 |
- if (strcmp(bval->bv_val, "0") != 0)
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
- LDAPDebug( LDAP_DEBUG_TRACE, "<= slapi_has_children 1\n", 0, 0, 0 );
|
|
|
dc8c34 |
- return(1);
|
|
|
dc8c34 |
+ count = strtol(bval->bv_val, (char **)NULL, 10);
|
|
|
dc8c34 |
+ if (count > 0) {
|
|
|
dc8c34 |
+ LDAPDebug1Arg( LDAP_DEBUG_TRACE, "<= slapi_has_children %d\n", count);
|
|
|
dc8c34 |
+ return count;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ /*If the subordinatecount exists, and it's nonzero, then return 1.*/
|
|
|
dc8c34 |
+ if (include_tombstone && (slapi_entry_attr_find( entry, "tombstonenumsubordinates", &attr) == 0))
|
|
|
dc8c34 |
+ {
|
|
|
dc8c34 |
+ Slapi_Value *sval;
|
|
|
dc8c34 |
+ slapi_attr_first_value( attr, &sval );
|
|
|
dc8c34 |
+ if(sval!=NULL)
|
|
|
dc8c34 |
+ {
|
|
|
dc8c34 |
+ const struct berval *bval = slapi_value_get_berval( sval );
|
|
|
dc8c34 |
+ if(bval!=NULL)
|
|
|
dc8c34 |
+ {
|
|
|
dc8c34 |
+ /* The entry has the attribute, and it's non-zero */
|
|
|
dc8c34 |
+ count = strtol(bval->bv_val, (char **)NULL, 10);
|
|
|
dc8c34 |
+ if (count > 0) {
|
|
|
dc8c34 |
+ LDAPDebug1Arg( LDAP_DEBUG_TRACE, "<= slapi_has_tombstone_children %d\n", count);
|
|
|
dc8c34 |
+ return count;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -3119,6 +3139,12 @@ slapi_entry_has_children(const Slapi_Entry *entry)
|
|
|
dc8c34 |
return(0);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+int
|
|
|
dc8c34 |
+slapi_entry_has_children(const Slapi_Entry *entry)
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ return slapi_entry_has_children_ext(entry, 0);
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* Renames an entry to simulate a MODRDN operation
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/rdn.c b/ldap/servers/slapd/rdn.c
|
|
|
dc8c34 |
index fe2fae0..6e40ed8 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/rdn.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/rdn.c
|
|
|
dc8c34 |
@@ -124,7 +124,7 @@ slapi_rdn_init_dn(Slapi_RDN *rdn,const char *dn)
|
|
|
dc8c34 |
* 1 -- "dn" does not belong to the database; could be "rdn"
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
static int
|
|
|
dc8c34 |
-_slapi_rdn_init_all_dn_ext(Slapi_RDN *rdn, const Slapi_DN *sdn)
|
|
|
dc8c34 |
+_slapi_rdn_init_all_dn_ext(Slapi_RDN *rdn, const Slapi_DN *sdn, int is_tombstone)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
const char *dn = NULL;
|
|
|
dc8c34 |
const char *ndn= NULL;
|
|
|
dc8c34 |
@@ -202,9 +202,16 @@ _slapi_rdn_init_all_dn_ext(Slapi_RDN *rdn, const Slapi_DN *sdn)
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/* Get the last matched position */
|
|
|
dc8c34 |
- if(dns)
|
|
|
dc8c34 |
- {
|
|
|
dc8c34 |
- rdn->rdn = slapi_ch_strdup(dns[0]);
|
|
|
dc8c34 |
+ if (dns) {
|
|
|
dc8c34 |
+ if (is_tombstone && slapi_is_special_rdn(dns[0], RDN_IS_TOMBSTONE)) {
|
|
|
dc8c34 |
+ /* merge nsuniqueid=...,<rdn> into one rdn */
|
|
|
dc8c34 |
+ rdn->rdn = slapi_ch_smprintf("%s,%s", dns[0], dns[1]);
|
|
|
dc8c34 |
+ slapi_ch_free_string(&dns[0]);
|
|
|
dc8c34 |
+ dns[0] = slapi_ch_strdup(rdn->rdn);
|
|
|
dc8c34 |
+ charray_remove(dns, dns[1], 1);
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ rdn->rdn = slapi_ch_strdup(dns[0]);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
rdn->all_rdns = dns;
|
|
|
dc8c34 |
slapi_setbit_uchar(rdn->flag,FLAG_ALL_RDNS);
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -238,7 +245,7 @@ slapi_rdn_init_all_dn(Slapi_RDN *rdn, const char *dn)
|
|
|
dc8c34 |
slapi_rdn_init(rdn);
|
|
|
dc8c34 |
slapi_sdn_init(&sdn;;
|
|
|
dc8c34 |
slapi_sdn_set_dn_byval(&sdn, dn);
|
|
|
dc8c34 |
- rc = _slapi_rdn_init_all_dn_ext(rdn, (const Slapi_DN *)&sdn;;
|
|
|
dc8c34 |
+ rc = _slapi_rdn_init_all_dn_ext(rdn, (const Slapi_DN *)&sdn, 0);
|
|
|
dc8c34 |
slapi_sdn_done(&sdn;;
|
|
|
dc8c34 |
return rc;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
@@ -257,6 +264,33 @@ slapi_rdn_init_all_dn(Slapi_RDN *rdn, const char *dn)
|
|
|
dc8c34 |
* 1 -- dn does not belong to the database
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
int
|
|
|
dc8c34 |
+slapi_rdn_init_all_sdn_ext(Slapi_RDN *rdn, const Slapi_DN *sdn, int is_tombstone)
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ int rc = 0; /* success */
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ if (NULL == rdn || NULL == sdn)
|
|
|
dc8c34 |
+ {
|
|
|
dc8c34 |
+ return -1;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ slapi_rdn_init(rdn);
|
|
|
dc8c34 |
+ rc = _slapi_rdn_init_all_dn_ext(rdn, sdn, is_tombstone);
|
|
|
dc8c34 |
+ return rc;
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+/*
|
|
|
dc8c34 |
+ * This function sets DN from sdn to Slapi_RDN.
|
|
|
dc8c34 |
+ * Note: The underlying function _slapi_rdn_init_all_dn_ext checks if the DN
|
|
|
dc8c34 |
+ * is in the root or sub suffix the server owns. If it is, the root or sub
|
|
|
dc8c34 |
+ * suffix is treated as one "rdn" (e.g., "dc=sub,dc=example,dc=com") and 0 is
|
|
|
dc8c34 |
+ * returned. If it is not, the DN is separated by ',' and each string is set
|
|
|
dc8c34 |
+ * to RDN array. (e.g., input: "uid=A,ou=does_not_exist" ==> "uid=A", "ou=
|
|
|
dc8c34 |
+ * does_not_exist") and 1 is returned.
|
|
|
dc8c34 |
+ *
|
|
|
dc8c34 |
+ * Return Value: 0 -- Success
|
|
|
dc8c34 |
+ * -1 -- Error
|
|
|
dc8c34 |
+ * 1 -- dn does not belong to the database
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+int
|
|
|
dc8c34 |
slapi_rdn_init_all_sdn(Slapi_RDN *rdn, const Slapi_DN *sdn)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
int rc = 0; /* success */
|
|
|
dc8c34 |
@@ -266,7 +300,7 @@ slapi_rdn_init_all_sdn(Slapi_RDN *rdn, const Slapi_DN *sdn)
|
|
|
dc8c34 |
return -1;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
slapi_rdn_init(rdn);
|
|
|
dc8c34 |
- rc = _slapi_rdn_init_all_dn_ext(rdn, sdn);
|
|
|
dc8c34 |
+ rc = _slapi_rdn_init_all_dn_ext(rdn, sdn, 0);
|
|
|
dc8c34 |
return rc;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
@@ -291,6 +325,17 @@ slapi_rdn_init_rdn(Slapi_RDN *rdn,const Slapi_RDN *fromrdn)
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
void
|
|
|
dc8c34 |
+slapi_rdn_set_dn_ext(Slapi_RDN *rdn,const char *dn, int skip_tombstone)
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ const char *mydn = dn;
|
|
|
dc8c34 |
+ slapi_rdn_done(rdn);
|
|
|
dc8c34 |
+ if (skip_tombstone && slapi_is_special_rdn(dn, RDN_IS_TOMBSTONE)) {
|
|
|
dc8c34 |
+ mydn = dn + slapi_uniqueIDRdnSize() + 1/*,*/;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ slapi_rdn_init_dn(rdn, mydn);
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+void
|
|
|
dc8c34 |
slapi_rdn_set_dn(Slapi_RDN *rdn,const char *dn)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
slapi_rdn_done(rdn);
|
|
|
dc8c34 |
@@ -473,6 +518,33 @@ slapi_rdn_contains(Slapi_RDN *rdn, const char *type, const char *value, size_t l
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
int
|
|
|
dc8c34 |
+slapi_rdn_is_multivalued(Slapi_RDN *rdn)
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ char *p = NULL;
|
|
|
dc8c34 |
+ if (rdn && rdn->rdn) {
|
|
|
dc8c34 |
+ p = PL_strchr(rdn->rdn, '+');
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ if (p) {
|
|
|
dc8c34 |
+ return 1;
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ return 0;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+/*
|
|
|
dc8c34 |
+ * Return value 1: if rdn is a conflict rdn
|
|
|
dc8c34 |
+ * 0: otherwise
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+int
|
|
|
dc8c34 |
+slapi_rdn_is_conflict(Slapi_RDN *rdn)
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ if (!rdn) {
|
|
|
dc8c34 |
+ return 0;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ return slapi_is_special_rdn(slapi_rdn_get_nrdn(rdn), RDN_IS_CONFLICT);
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+int
|
|
|
dc8c34 |
slapi_rdn_add(Slapi_RDN *rdn, const char *type, const char *value)
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
PR_ASSERT(NULL != type);
|
|
|
dc8c34 |
@@ -484,12 +556,32 @@ slapi_rdn_add(Slapi_RDN *rdn, const char *type, const char *value)
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
else
|
|
|
dc8c34 |
{
|
|
|
dc8c34 |
- /* type=value+rdn '\0' */
|
|
|
dc8c34 |
- char *newrdn = slapi_create_dn_string("%s=%s+%s", type, value, rdn->rdn);
|
|
|
dc8c34 |
+ char *newrdn = NULL;
|
|
|
dc8c34 |
+ char *rp = rdn->rdn;
|
|
|
dc8c34 |
+ PRUint32 uniqueidlen = slapi_uniqueIDRdnSize();
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ if (slapi_is_special_rdn(rp, RDN_IS_TOMBSTONE)) {
|
|
|
dc8c34 |
+ char *corerp = rp + uniqueidlen + 1;
|
|
|
dc8c34 |
+ *(rp + uniqueidlen) = '\0';
|
|
|
dc8c34 |
+ newrdn = slapi_create_dn_string("%s,%s=%s+%s", rp, type, value, corerp);
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ /* type=value+rdn '\0' */
|
|
|
dc8c34 |
+ newrdn = slapi_create_dn_string("%s=%s+%s", type, value, rp);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
slapi_ch_free_string(&rdn->rdn);
|
|
|
dc8c34 |
rdn->rdn = newrdn;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
slapi_unsetbit_uchar(rdn->flag,FLAG_RDNS);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ if (rdn->all_rdns && rdn->all_rdns[0]) {
|
|
|
dc8c34 |
+ slapi_ch_free_string(&rdn->all_rdns[0]);
|
|
|
dc8c34 |
+ rdn->all_rdns[0] = slapi_ch_strdup(rdn->rdn);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ if (rdn->all_nrdns && rdn->all_nrdns[0]) {
|
|
|
dc8c34 |
+ slapi_ch_free_string(&rdn->all_nrdns[0]);
|
|
|
dc8c34 |
+ rdn->all_nrdns[0] = slapi_ch_strdup(rdn->rdn);
|
|
|
dc8c34 |
+ slapi_dn_ignore_case(rdn->all_nrdns[0]);
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
return 1;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
|
|
|
dc8c34 |
index 80500a5..9e85dc0 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/slapi-plugin.h
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/slapi-plugin.h
|
|
|
dc8c34 |
@@ -1832,6 +1832,17 @@ int slapi_entry_attr_has_syntax_value(const Slapi_Entry *e, const char *type, co
|
|
|
dc8c34 |
int slapi_entry_has_children(const Slapi_Entry *e);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/**
|
|
|
dc8c34 |
+ * This function determines if the specified entry has child entries
|
|
|
dc8c34 |
+ * including the tombstoned descendents.
|
|
|
dc8c34 |
+ *
|
|
|
dc8c34 |
+ * \param e Entry that you want to test for child entries.
|
|
|
dc8c34 |
+ * \param include_tombstone If non-zero, check tombstone_subordinates, too.
|
|
|
dc8c34 |
+ * \return \c 1 if the entry you supply has child entries.
|
|
|
dc8c34 |
+ * \return \c 0 if the entry you supply has child entries.
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+int slapi_entry_has_children_ext(const Slapi_Entry *e, int include_tombstone);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+/**
|
|
|
dc8c34 |
* This function determines if an entry is the root DSE.
|
|
|
dc8c34 |
*
|
|
|
dc8c34 |
* The root DSE is a special entry that contains information about the Directory
|
|
|
dc8c34 |
@@ -2930,9 +2941,11 @@ void slapi_rdn_init_rdn(Slapi_RDN *rdn,const Slapi_RDN *fromrdn);
|
|
|
dc8c34 |
* \see slapi_rdn_set_rdn()
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
void slapi_rdn_set_dn(Slapi_RDN *rdn,const char *dn);
|
|
|
dc8c34 |
+void slapi_rdn_set_dn_ext(Slapi_RDN *rdn,const char *dn, int skip_tombstone);
|
|
|
dc8c34 |
Slapi_RDN *slapi_rdn_new_all_dn(const char *dn);
|
|
|
dc8c34 |
int slapi_rdn_init_all_dn(Slapi_RDN *rdn, const char *dn);
|
|
|
dc8c34 |
int slapi_rdn_init_all_sdn(Slapi_RDN *rdn, const Slapi_DN *sdn);
|
|
|
dc8c34 |
+int slapi_rdn_init_all_sdn_ext(Slapi_RDN *rdn, const Slapi_DN *sdn, int is_tombstone);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
/**
|
|
|
dc8c34 |
* Sets the RDN value in a \c Slapi_RDN structure from a \c Slapi_DN.
|
|
|
dc8c34 |
@@ -3348,6 +3361,24 @@ size_t slapi_rdn_get_size(Slapi_RDN *srdn);
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
char * slapi_rdn_get_value(const char *rdn);
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+/**
|
|
|
dc8c34 |
+ * Check if the rdn is multivalued or not
|
|
|
dc8c34 |
+ *
|
|
|
dc8c34 |
+ * \param rdn A pointer to rdn to exam.
|
|
|
dc8c34 |
+ * \return 1, if the rdn is multi valued.
|
|
|
dc8c34 |
+ * 0, if the rdn is simgle valued.
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+int slapi_rdn_is_multivalued(Slapi_RDN *rdn);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+/**
|
|
|
dc8c34 |
+ * Check if the rdn is a conflict rdn or not
|
|
|
dc8c34 |
+ *
|
|
|
dc8c34 |
+ * \param rdn A pointer to rdn to exam.
|
|
|
dc8c34 |
+ * \return 1, if the rdn is a conflict rdn
|
|
|
dc8c34 |
+ * 0, if the rdn is not a conflict rdn
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+int slapi_rdn_is_conflict(Slapi_RDN *rdn);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
/*
|
|
|
dc8c34 |
* utility routines for dealing with DNs
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
@@ -7301,6 +7332,20 @@ char *slapi_pr_strerror( const PRErrorCode prerrno );
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
const char *slapi_system_strerror( const int syserrno );
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+/** Check if rdn is a slecial rdn/dn or not.
|
|
|
dc8c34 |
+ *
|
|
|
dc8c34 |
+ * \param rdn rdn/dn to check
|
|
|
dc8c34 |
+ * \param flags specify the type: RDN_IS_TOMBSTONE or RDN_IS_CONFLICT or 0
|
|
|
dc8c34 |
+ *
|
|
|
dc8c34 |
+ * \return 1 if rdn matches the flag.
|
|
|
dc8c34 |
+ * If flag is IS_TOMBSTONE, returns 1 if rdn is a tombstone rdn/dn.
|
|
|
dc8c34 |
+ * If flag is IS_CONFLICT, returns 1 if rdn is a conflict rdn/dn.
|
|
|
dc8c34 |
+ * \return 0 otherwise
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+#define RDN_IS_TOMBSTONE 0x1
|
|
|
dc8c34 |
+#define RDN_IS_CONFLICT 0x2
|
|
|
dc8c34 |
+int slapi_is_special_rdn(const char *rdn, int flag);
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
#ifdef __cplusplus
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
#endif
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/slapi-private.h b/ldap/servers/slapd/slapi-private.h
|
|
|
dc8c34 |
index b9131a5..ecabbe2 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/slapi-private.h
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/slapi-private.h
|
|
|
dc8c34 |
@@ -997,6 +997,13 @@ int slapi_uniqueIDIsUUID(const Slapi_UniqueID *uId);
|
|
|
dc8c34 |
*/
|
|
|
dc8c34 |
int slapi_uniqueIDSize( void );
|
|
|
dc8c34 |
|
|
|
dc8c34 |
+/* Name: slapi_uniqueIDRdnSize
|
|
|
dc8c34 |
+ Description: returns size of SLAPI_ATTR_UNIQUEID=slapi_uniqueIDSize()
|
|
|
dc8c34 |
+ Parameters: none
|
|
|
dc8c34 |
+ Return: size of the string version of "SLAPI_ATTR_UNIQUEID=uniqueID" in bytes
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+int slapi_uniqueIDRdnSize( void );
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
/* Name: slapi_uniqueIDDup
|
|
|
dc8c34 |
Description: duplicates an UniqueID object
|
|
|
dc8c34 |
Parameters: uId - id to duplicate
|
|
|
dc8c34 |
diff --git a/ldap/servers/slapd/util.c b/ldap/servers/slapd/util.c
|
|
|
dc8c34 |
index 0a9d23d..c566512 100644
|
|
|
dc8c34 |
--- a/ldap/servers/slapd/util.c
|
|
|
dc8c34 |
+++ b/ldap/servers/slapd/util.c
|
|
|
dc8c34 |
@@ -1089,3 +1089,70 @@ slapi_str_to_u64(const char *s)
|
|
|
dc8c34 |
(v6 << 36) | (v7 << 32) | (v8 << 28) | (v9 << 24) | (v10 << 20) | (v11 << 16) |
|
|
|
dc8c34 |
(v12 << 12) | (v13 << 8) | (v14 << 4) | v15;
|
|
|
dc8c34 |
}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+/*
|
|
|
dc8c34 |
+ * Check if rdn is a slecial rdn/dn or not.
|
|
|
dc8c34 |
+ * If flag is IS_TOMBSTONE, returns 1 if rdn is a tombstone rdn/dn.
|
|
|
dc8c34 |
+ * If flag is IS_CONFLICT, returns 1 if rdn is a conflict rdn/dn.
|
|
|
dc8c34 |
+ * Otherwise returns 0.
|
|
|
dc8c34 |
+ */
|
|
|
dc8c34 |
+static int util_uniqueidlen = 0;
|
|
|
dc8c34 |
+int
|
|
|
dc8c34 |
+slapi_is_special_rdn(const char *rdn, int flag)
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ char *rp;
|
|
|
dc8c34 |
+ int plus = 0;
|
|
|
dc8c34 |
+ if (!util_uniqueidlen) {
|
|
|
dc8c34 |
+ util_uniqueidlen = SLAPI_ATTR_UNIQUEID_LENGTH + slapi_uniqueIDSize() + 1/*=*/;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ if ((RDN_IS_TOMBSTONE != flag) && (RDN_IS_CONFLICT != flag)) {
|
|
|
dc8c34 |
+ LDAPDebug1Arg(LDAP_DEBUG_ANY, "slapi_is_special_rdn: invalid flag %d\n", flag);
|
|
|
dc8c34 |
+ return 0; /* not a special rdn/dn */
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ if (!rdn) {
|
|
|
dc8c34 |
+ LDAPDebug0Args(LDAP_DEBUG_ANY, "slapi_is_special_rdn: NULL rdn\n");
|
|
|
dc8c34 |
+ return 0; /* not a special rdn/dn */
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+ if (strlen(rdn) < util_uniqueidlen) {
|
|
|
dc8c34 |
+ return 0; /* not a special rdn/dn */
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ rp = (char *)rdn;
|
|
|
dc8c34 |
+ while (rp) {
|
|
|
dc8c34 |
+ char *comma = NULL;
|
|
|
dc8c34 |
+ if (!PL_strncasecmp(rp, SLAPI_ATTR_UNIQUEID, SLAPI_ATTR_UNIQUEID_LENGTH) &&
|
|
|
dc8c34 |
+ (*(rp + SLAPI_ATTR_UNIQUEID_LENGTH) == '=')) {
|
|
|
dc8c34 |
+ if (RDN_IS_TOMBSTONE == flag) {
|
|
|
dc8c34 |
+ if ((*(rp + util_uniqueidlen) == ',') ||
|
|
|
dc8c34 |
+ (*(rp + util_uniqueidlen) == '\0')) {
|
|
|
dc8c34 |
+ return 1;
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ return 0;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ } else {
|
|
|
dc8c34 |
+ if ((*(rp + util_uniqueidlen) == '+') ||
|
|
|
dc8c34 |
+ (plus && ((*(rp + util_uniqueidlen) == ',') ||
|
|
|
dc8c34 |
+ (*(rp + util_uniqueidlen) == '\0')))) {
|
|
|
dc8c34 |
+ return 1;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ comma = PL_strchr(rp, ',');
|
|
|
dc8c34 |
+ rp = PL_strchr(rp, '+');
|
|
|
dc8c34 |
+ if (rp && (rp < comma)) {
|
|
|
dc8c34 |
+ plus = 1;
|
|
|
dc8c34 |
+ rp++;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ return 0;
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
+
|
|
|
dc8c34 |
+int
|
|
|
dc8c34 |
+slapi_uniqueIDRdnSize()
|
|
|
dc8c34 |
+{
|
|
|
dc8c34 |
+ if (!util_uniqueidlen) {
|
|
|
dc8c34 |
+ util_uniqueidlen = SLAPI_ATTR_UNIQUEID_LENGTH + slapi_uniqueIDSize() + 1/*=*/;
|
|
|
dc8c34 |
+ }
|
|
|
dc8c34 |
+ return util_uniqueidlen;
|
|
|
dc8c34 |
+}
|
|
|
dc8c34 |
--
|
|
|
dc8c34 |
1.8.1.4
|
|
|
dc8c34 |
|