ldap/servers/slapd/back-ldbm/import-threads.c | 52 ++++++++++++++++--
ldap/servers/slapd/back-ldbm/ldif2ldbm.c | 24 +++++++-
ldap/servers/slapd/entry.c | 75 ++++++++++++++++++++++++--
ldap/servers/slapd/rdn.c | 36 ++++++++++++
ldap/servers/slapd/slap.h | 3 +
ldap/servers/slapd/slapi-plugin.h | 7 ++
6 files changed, 189 insertions(+), 8 deletions(-)
New commits:
commit 2ba240b48dbae4a49d194f7a4ebc59fb0ad3d908
Author: Noriko Hosoi <nhosoi(a)redhat.com>
Date: Thu Mar 17 11:21:19 2011 -0700
Bug 684996 - Exported tombstone cannot be imported correctly
https://bugzilla.redhat.com/show_bug.cgi?id=684996
Description: When nsslapd-subtree-rename-switch is on,
a tombstone entry has a special RDN which looks like this:
nsuniqueid=042d8081-...-ca8fe9f7,<original_leaf_rdn>
This special format was not treated properly.
This patch adds the code to handle the special tombstone
RDN, where an internal entry has the above RDN and points
the correct parent entry.
diff --git a/ldap/servers/slapd/back-ldbm/import-threads.c
b/ldap/servers/slapd/back-ldbm/import-threads.c
index d743baa..df070a3 100644
--- a/ldap/servers/slapd/back-ldbm/import-threads.c
+++ b/ldap/servers/slapd/back-ldbm/import-threads.c
@@ -2136,11 +2136,11 @@ import_foreman(void *param)
goto error;
}
- if (! slapi_entry_flag_is_set(fi->entry->ep_entry,
- SLAPI_ENTRY_FLAG_TOMBSTONE)) {
+ if (entryrdn_get_switch() ||
+ !slapi_entry_flag_is_set(fi->entry->ep_entry,
+ SLAPI_ENTRY_FLAG_TOMBSTONE)) {
/*
- * Only check for a parent and add to the entry2dn index if
- * the entry is not a tombstone.
+ * Only check for a parent and add to the entry2dn index
*/
if (job->flags & FLAG_ABORT) {
goto error;
@@ -2865,6 +2865,50 @@ static int bulk_import_queue(ImportJob *job, Slapi_Entry *entry)
job->fifo.c_bsize = 0;
backentry_free(&old_ep);
}
+ /* Is subtree-rename on? And is this a tombstone?
+ * If so, need a special treatment */
+ if (entryrdn_get_switch() &&
+ (ep->ep_entry->e_flags & SLAPI_ENTRY_FLAG_TOMBSTONE)) {
+ char *tombstone_rdn =
+ slapi_ch_strdup(slapi_entry_get_dn_const(ep->ep_entry));
+ if ((0 == PL_strncasecmp(tombstone_rdn, SLAPI_ATTR_UNIQUEID,
+ sizeof(SLAPI_ATTR_UNIQUEID) - 1)) &&
+ /* dn starts with "nsuniqueid=" */
+ (NULL == PL_strstr(tombstone_rdn, RUV_STORAGE_ENTRY_UNIQUEID))) {
+ /* and this is not an RUV */
+ char *sepp = PL_strchr(tombstone_rdn, ',');
+ /* dn looks like this:
+ *
nsuniqueid=042d8081-...-ca8fe9f7,uid=tuser,o=abc.com
+ * create a new srdn for the original dn
+ *
uid=tuser,o=abc.com
+ */
+ if (sepp) {
+ Slapi_RDN mysrdn = {0};
+ if (slapi_rdn_init_all_dn(&mysrdn, sepp + 1)) {
+ slapi_log_error(SLAPI_LOG_FATAL, "bulk_import_queue",
+ "Failed to convert DN %s to RDN\n", sepp + 1);
+ slapi_ch_free_string(&tombstone_rdn);
+ /* entry is released in the frontend on failure*/
+ backentry_clear_entry(ep);
+ backentry_free( &ep ); /* release the backend wrapper */
+ PR_Unlock(job->wire_lock);
+ return -1;
+ }
+ sepp = PL_strchr(sepp + 1, ',');
+ if (sepp) {
+ Slapi_RDN *srdn = slapi_entry_get_srdn(ep->ep_entry);
+ /* nsuniqueid=042d8081-...-ca8fe9f7,uid=tuser, */
+ /* ^ */
+ *sepp = '\0';
+ slapi_rdn_replace_rdn(&mysrdn, tombstone_rdn);
+ slapi_rdn_done(srdn);
+ slapi_entry_set_srdn(ep->ep_entry, &mysrdn);
+ slapi_rdn_done(&mysrdn);
+ }
+ }
+ }
+ slapi_ch_free_string(&tombstone_rdn);
+ }
newesize = (slapi_entry_size(ep->ep_entry) + sizeof(struct backentry));
if (newesize > job->fifo.bsize) { /* entry too big */
diff --git a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
index ccad8e6..fd7934a 100644
--- a/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
+++ b/ldap/servers/slapd/back-ldbm/ldif2ldbm.c
@@ -254,6 +254,28 @@ int add_op_attrs(Slapi_PBlock *pb, struct ldbminfo *li, struct
backentry *ep,
slapi_sdn_set_dn_byval(&sdn, pdn);
err = entryrdn_index_read(be, &sdn, &pid, NULL);
slapi_sdn_done(&sdn);
+ if (DB_NOTFOUND == err) {
+ /*
+ * Could be a tombstone. E.g.,
+ * nsuniqueid=042d8081-..-ca8fe9f7,uid=tuser,o=abc,com
+ * If so, need to get the grandparent of the leaf.
+ */
+ if (slapi_entry_flag_is_set(ep->ep_entry,
+ SLAPI_ENTRY_FLAG_TOMBSTONE)) {
+ char *ppdn = slapi_dn_parent(pdn);
+ slapi_ch_free_string(&pdn);
+ if (NULL == ppdn) {
+ if (NULL != status) {
+ *status = IMPORT_ADD_OP_ATTRS_NO_PARENT;
+ goto next;
+ }
+ }
+ pdn = ppdn;
+ slapi_sdn_set_dn_byval(&sdn, pdn);
+ err = entryrdn_index_read(be, &sdn, &pid, NULL);
+ slapi_sdn_done(&sdn);
+ }
+ }
if (err) {
if (DB_NOTFOUND != err && 1 != err) {
LDAPDebug1Arg( LDAP_DEBUG_ANY, "database error %d\n", err
);
@@ -291,7 +313,7 @@ int add_op_attrs(Slapi_PBlock *pb, struct ldbminfo *li, struct
backentry *ep,
*status = IMPORT_ADD_OP_ATTRS_NO_PARENT;
}
}
-
+next:
/* Get rid of attributes you're not allowed to specify yourself */
slapi_entry_delete_values( ep->ep_entry, hassubordinates, NULL );
slapi_entry_delete_values( ep->ep_entry, numsubordinates, NULL );
diff --git a/ldap/servers/slapd/entry.c b/ldap/servers/slapd/entry.c
index 33ac468..9e0b57f 100644
--- a/ldap/servers/slapd/entry.c
+++ b/ldap/servers/slapd/entry.c
@@ -61,6 +61,9 @@
#define DELETED_VALUE_STRING ";deleted"
#define DELETED_VALUE_STRSIZE 8 /* sizeof(";deleted") */
+/* a helper function to set special rdn to a tombstone entry */
+static int _entry_set_tombstone_rdn(Slapi_Entry *e, char *normdn);
+
/*
* An attribute name is of the form 'basename[;option]'.
* The state informaion is encoded in options. For example:
@@ -519,6 +522,18 @@ str2entry_fast( const char *rawdn, char *s, int flags, int
read_stateinfo )
/* release read lock of name2asi, per-entry lock */
attr_syntax_unlock_read();
+ /* If this is a tombstone, it requires a special treatment for rdn. */
+ if (e->e_flags & SLAPI_ENTRY_FLAG_TOMBSTONE) {
+ /* tombstone */
+ if (_entry_set_tombstone_rdn(e, slapi_entry_get_dn_const(e))) {
+ LDAPDebug1Arg( LDAP_DEBUG_TRACE, "str2entry_fast: "
+ "tombstone entry has badly formatted dn: %s\n",
+ slapi_entry_get_dn_const(e) );
+ slapi_entry_free( e ); e = NULL;
+ goto done;
+ }
+ }
+
/* check to make sure there was a dn: line */
if ( slapi_entry_get_dn_const(e)==NULL ) {
if (!(SLAPI_STR2ENTRY_INCLUDE_VERSION_STR & flags))
@@ -807,7 +822,7 @@ str2entry_dupcheck( const char *rawdn, char *s, int flags, int
read_stateinfo )
normdn = slapi_create_dn_string("%s", rawdn);
if (NULL == normdn) {
LDAPDebug1Arg(LDAP_DEBUG_TRACE,
- "str2entry_fast: Invalid DN: %s\n", rawdn);
+ "str2entry_dupcheck: Invalid DN: %s\n", rawdn);
slapi_entry_free( e );
if (freeval) slapi_ch_free_string(&bvvalue.bv_val);
csn_free(&attributedeletioncsn);
@@ -1221,6 +1236,17 @@ str2entry_dupcheck( const char *rawdn, char *s, int flags, int
read_stateinfo )
/* release read lock of name2asi, per-entry lock */
attr_syntax_unlock_read();
+ /* If this is a tombstone, it requires a special treatment for rdn. */
+ if (e->e_flags & SLAPI_ENTRY_FLAG_TOMBSTONE) {
+ /* tombstone */
+ if (_entry_set_tombstone_rdn(e, slapi_entry_get_dn_const(e))) {
+ LDAPDebug1Arg( LDAP_DEBUG_TRACE, "str2entry_dupcheck: "
+ "tombstone entry has badly formatted dn: %s\n",
+ slapi_entry_get_dn_const(e) );
+ slapi_entry_free( e ); e = NULL;
+ goto free_and_return;
+ }
+ }
/* Add the RDN values, if asked, and if not already present */
if ( flags & SLAPI_STR2ENTRY_ADDRDNVALS ) {
@@ -1974,8 +2000,8 @@ slapi_entry_size(Slapi_Entry *e)
if (e->e_uniqueid) size += strlen(e->e_uniqueid) + 1;
if (e->e_dncsnset) size += csnset_size(e->e_dncsnset);
if (e->e_maxcsn) size += sizeof( CSN );
- size += slapi_dn_size(&e->e_sdn); /* covers rdn format,
- since (rdn length < dn length) */
+ size += slapi_dn_size(&e->e_sdn);
+ size += slapi_rdn_get_size(&e->e_srdn);
size += slapi_attrlist_size(e->e_attrs);
if (e->e_deleted_attrs) size += slapi_attrlist_size(e->e_deleted_attrs);
if (e->e_virtual_attrs) size += slapi_attrlist_size(e->e_virtual_attrs);
@@ -3830,3 +3856,46 @@ out:
return rval;
}
+
+/* a helper function to set special rdn to a tombstone entry */
+/* Since this a tombstone, it requires a special treatment for rdn*/
+static int
+_entry_set_tombstone_rdn(Slapi_Entry *e, char *normdn)
+{
+ int rc = 0;
+ char *tombstone_rdn = slapi_ch_strdup(normdn);
+ if ((0 == PL_strncasecmp(tombstone_rdn, SLAPI_ATTR_UNIQUEID,
+ sizeof(SLAPI_ATTR_UNIQUEID) - 1)) &&
+ (NULL == PL_strstr(tombstone_rdn, RUV_STORAGE_ENTRY_UNIQUEID))) {
+ /* dn starts with "nsuniqueid=" and this is not an RUV */
+ char *sepp = PL_strchr(tombstone_rdn, ',');
+ /* dn looks like this:
+ *
nsuniqueid=042d8081-...-ca8fe9f7,uid=tuser,o=abc.com
+ * create a new srdn for the original dn
+ *
uid=tuser,o=abc.com
+ */
+ if (sepp) {
+ Slapi_RDN mysrdn = {0};
+ rc = slapi_rdn_init_all_dn(&mysrdn, sepp + 1);
+ if (rc) {
+ slapi_log_error(SLAPI_LOG_FATAL, "str2entry",
+ "Failed to convert DN %s to RDN\n", sepp + 1);
+ goto bail;
+ }
+ sepp = PL_strchr(sepp + 1, ',');
+ if (sepp) {
+ Slapi_RDN *srdn = slapi_entry_get_srdn(e);
+ /* nsuniqueid=042d8081-...-ca8fe9f7,uid=tuser, */
+ /* ^ */
+ *sepp = '\0';
+ slapi_rdn_replace_rdn(&mysrdn, tombstone_rdn);
+ slapi_rdn_done(srdn);
+ slapi_entry_set_srdn(e, &mysrdn);
+ slapi_rdn_done(&mysrdn);
+ }
+ }
+ }
+bail:
+ slapi_ch_free_string(&tombstone_rdn);
+ return rc;
+}
diff --git a/ldap/servers/slapd/rdn.c b/ldap/servers/slapd/rdn.c
index 39b40bd..e8b7915 100644
--- a/ldap/servers/slapd/rdn.c
+++ b/ldap/servers/slapd/rdn.c
@@ -997,3 +997,39 @@ slapi_rdn_partial_dup(Slapi_RDN *from, Slapi_RDN **to, int rdnidx)
(*to)->all_nrdns = charray_dup(&(from->all_nrdns[rdnidx]));
return 0;
}
+
+size_t
+slapi_rdn_get_size(Slapi_RDN *srdn)
+{
+ size_t sz = 0;
+ char **ptr;
+
+ if (!srdn) {
+ goto bail;
+ }
+ sz = sizeof(Slapi_RDN);
+ if (srdn->rdn) {
+ sz += strlen(srdn->rdn) + 1;
+ }
+ if (srdn->nrdn) {
+ sz += strlen(srdn->nrdn) + 1;
+ }
+ if (srdn->rdns) {
+ for (ptr = srdn->rdns; ptr && *ptr; ptr++) {
+ sz += strlen(*ptr) + 1;
+ }
+ }
+ if (srdn->all_rdns) {
+ for (ptr = srdn->all_rdns; ptr && *ptr; ptr++) {
+ sz += strlen(*ptr) + 1;
+ }
+ }
+ if (srdn->all_nrdns) {
+ for (ptr = srdn->all_nrdns; ptr && *ptr; ptr++) {
+ sz += strlen(*ptr) + 1;
+ }
+ }
+bail:
+ return sz;
+}
+
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index a19e5c8..b3728d3 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -2259,4 +2259,7 @@ extern char *attr_dataversion;
#define LDAP_VIRTUAL_LIST_VIEW_ERROR 0x4C /* 76 */
#endif
+/* copied from replication/repl5.h */
+#define RUV_STORAGE_ENTRY_UNIQUEID "ffffffff-ffffffff-ffffffff-ffffffff"
+
#endif /* _slap_h_ */
diff --git a/ldap/servers/slapd/slapi-plugin.h b/ldap/servers/slapd/slapi-plugin.h
index 8613c60..f0be0a6 100644
--- a/ldap/servers/slapd/slapi-plugin.h
+++ b/ldap/servers/slapd/slapi-plugin.h
@@ -3071,6 +3071,13 @@ int slapi_rdn_replace_rdn(Slapi_RDN *srdn, char *new_rdn);
*/
int slapi_rdn_partial_dup(Slapi_RDN *from, Slapi_RDN **to, int idx);
+/**
+ * Return the size of the RDN
+ *
+ * \param srdn A pointer to Slapi_RDN to calculate the size
+ * \return The size of the given RDN.
+ */
+size_t slapi_rdn_get_size(Slapi_RDN *srdn);
/*
* utility routines for dealing with DNs