ldap/servers/slapd/back-ldbm/index.c | 2
ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c | 60 ++++++++++++++++++++++++---
2 files changed, 55 insertions(+), 7 deletions(-)
New commits:
commit e72f4b277e8d06651d489467a7f77fd8f4a829cd
Author: Noriko Hosoi <nhosoi(a)jiji.usersys.redhat.com>
Date: Tue Jan 31 14:58:44 2012 -0800
Trac Ticket #274 - Reindexing entryrdn fails if
ancestors are also tombstoned
https://fedorahosted.org/389/ticket/274
Bug description: Inserting/traversing entryrdn fails if a parent
entry is tombstoned and the rdn in the entryrdn index includes
nsuniqueid.
In DIT cn=A,ou=B,o=C, cn=A and ou=B are removed and turned to
tombstone entries. Both of the 2 representations need to be
supported in the entryrdn.
nsuniqueid=...,cn=A,ou=B,o=C and
nsuniqueid=...,cn=A,nsuniqueid=...,ou=B,o=C
Fix description: Support for the second case is added by this patch.
Also, in index_add_mods, code for checking NULL mods is added.
diff --git a/ldap/servers/slapd/back-ldbm/index.c b/ldap/servers/slapd/back-ldbm/index.c
index 65ad867..0ed6918 100644
--- a/ldap/servers/slapd/back-ldbm/index.c
+++ b/ldap/servers/slapd/back-ldbm/index.c
@@ -526,7 +526,7 @@ index_add_mods(
* should be deleted.
*/
- for ( i = 0; mods[i] != NULL; i++ ) {
+ for ( i = 0; mods && mods[i] != NULL; i++ ) {
/* Get base attribute type */
basetype = buf;
tmp = slapi_attr_basetype(mods[i]->mod_type, buf, sizeof(buf));
diff --git a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
index 40b2f1e..d793705 100644
--- a/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
+++ b/ldap/servers/slapd/back-ldbm/ldbm_entryrdn.c
@@ -1652,11 +1652,12 @@ retry_get0:
childelem = (rdn_elem *)dataret.data;
childnrdn = (char *)childelem->rdn_elem_nrdn_rdn;
comma = strchr(childnrdn, ',');
- if (NULL == comma) { /* This node is not a tombstone */
+ if (NULL == comma) { /* No comma; This node is not a tombstone */
continue;
}
if (strncasecmp(childnrdn, SLAPI_ATTR_UNIQUEID,
sizeof(SLAPI_ATTR_UNIQUEID) - 1)) {
+ /* Does not start w/ UNIQUEID; not a tombstone */
continue;
}
if (0 == strcmp(comma + 1, slapi_rdn_get_nrdn(srdn))) {
@@ -1664,6 +1665,12 @@ retry_get0:
_entryrdn_dup_rdn_elem((const void *)dataret.data, elem);
goto bail;
}
+ if (0 == strncmp(childnrdn, slapi_rdn_get_nrdn(srdn),
+ comma - childnrdn)) {
+ /* found and done */
+ _entryrdn_dup_rdn_elem((const void *)dataret.data, elem);
+ goto bail;
+ }
} while (NULL != dataret.data && NULL != ptr);
retry_get1:
rc = cursor->c_get(cursor, key, &data, DB_NEXT_DUP|DB_MULTIPLE);
@@ -2268,8 +2275,7 @@ _entryrdn_insert_key(backend *be,
if (DB_NOTFOUND == rc) {
/* if 0 == rdnidx, Child is a Leaf RDN to be added */
if (0 == rdnidx) {
- /* keybuf (C#:<parent_rdn>) is consumed in
- _entryrdn_insert_key_elems */
+ /* keybuf (C#) is consumed in _entryrdn_insert_key_elems */
/* set id to the elem to be added */
id_internal_to_stored(id, elem->rdn_elem_id);
rc = _entryrdn_insert_key_elems(be, cursor, srdn, &key,
@@ -2279,6 +2285,17 @@ _entryrdn_insert_key(backend *be,
/* done */
} else {
ID currid = 0;
+ /*
+ * In DIT cn=A,ou=B,o=C, cn=A and ou=B are removed and
+ * turned to tombstone entries. We need to support both:
+ * nsuniqueid=...,cn=A,ou=B,o=C and
+ * nsuniqueid=...,cn=A,nsuniqueid=...,ou=B,o=C
+ * The former appears when cn=A is deleted;
+ * the latter appears when the entryrdn is reindexed.
+ * The former is taken care in _entryrdn_get_tombstone_elem;
+ * the else clause to skip "nsuniqueid" is needed for the
+ * latter case.
+ */
rc = _entryrdn_get_tombstone_elem(cursor, tmpsrdn, &key,
childnrdn, &tmpelem);
if (rc || (NULL == tmpelem)) {
@@ -2295,6 +2312,13 @@ _entryrdn_insert_key(backend *be,
}
slapi_ch_free_string(&dn);
goto bail;
+ } else {
+ int tmpidx = slapi_rdn_get_prev_ext(srdn, rdnidx,
+ &childnrdn, FLAG_ALL_NRDNS);
+ if (0 == strncasecmp(childnrdn, SLAPI_ATTR_UNIQUEID,
+ sizeof(SLAPI_ATTR_UNIQUEID) - 1)) {
+ rdnidx = tmpidx;
+ }
}
/* Node is a tombstone. */
slapi_ch_free((void **)&elem);
@@ -2779,10 +2803,34 @@ _entryrdn_index_read(backend *be,
slapi_ch_free((void **)&tmpelem);
if (flags & TOMBSTONE_INCLUDED) {
/* Node might be a tombstone */
+ /*
+ * In DIT cn=A,ou=B,o=C, cn=A and ou=B are removed and
+ * turned to tombstone entries. We need to support both:
+ * nsuniqueid=...,cn=A,ou=B,o=C and
+ * nsuniqueid=...,cn=A,nsuniqueid=...,ou=B,o=C
+ */
rc = _entryrdn_get_tombstone_elem(cursor, tmpsrdn, &key,
childnrdn, &tmpelem);
- }
- if (rc || (NULL == tmpelem)) {
+ if (rc || (NULL == tmpelem)) {
+ slapi_ch_free((void **)&tmpelem);
+ slapi_log_error(SLAPI_LOG_BACKLDBM, ENTRYRDN_TAG,
+ "_entryrdn_index_read: Child link \"%s\"
of "
+ "key \"%s\" not found: %s(%d)\n",
+ childnrdn, keybuf, dblayer_strerror(rc), rc);
+ rc = DB_NOTFOUND;
+ if (tmpsrdn != srdn) {
+ slapi_rdn_free(&tmpsrdn);
+ }
+ goto bail;
+ } else {
+ int tmpidx = slapi_rdn_get_prev_ext(srdn, rdnidx,
+ &childnrdn, FLAG_ALL_NRDNS);
+ if (0 == strncasecmp(childnrdn, SLAPI_ATTR_UNIQUEID,
+ sizeof(SLAPI_ATTR_UNIQUEID) - 1)) {
+ rdnidx = tmpidx;
+ }
+ }
+ } else {
slapi_ch_free((void **)&tmpelem);
slapi_log_error(SLAPI_LOG_BACKLDBM, ENTRYRDN_TAG,
"_entryrdn_index_read: Child link \"%s\"
of "
@@ -2790,7 +2838,7 @@ _entryrdn_index_read(backend *be,
childnrdn, keybuf, dblayer_strerror(rc), rc);
rc = DB_NOTFOUND;
if (tmpsrdn != srdn) {
- slapi_rdn_free(&tmpsrdn);
+ slapi_rdn_free(&tmpsrdn);
}
goto bail;
}