From 558f901ea9e8ab8f9aab441ad0e415368cc6b620 Mon Sep 17 00:00:00 2001 From: Ludwig Krispenz Date: Thu, 1 Mar 2018 15:36:12 +0100 Subject: [PATCH] Ticket 49591 - Inconsistencies in complex conflict cases and failure to do cleanup after tests Bug: in complex test cases for replication conflicts there were inconstencies on three masters. Also sometimes the cleanup after the test failed. Fix: handle the ADD and DEL cases properly where tombstones are turned into conflicts or conflicts into topmbstones and where a valid entry with dn of the original conflict existes. If replication completes properly the cleanup works Reviewed by: --- ldap/servers/plugins/replication/urp_tombstone.c | 48 +++++++++++++++++++----- ldap/servers/slapd/back-ldbm/ldbm_add.c | 1 + 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/ldap/servers/plugins/replication/urp_tombstone.c b/ldap/servers/plugins/replication/urp_tombstone.c index 9f1f060..8aab2cb 100644 --- a/ldap/servers/plugins/replication/urp_tombstone.c +++ b/ldap/servers/plugins/replication/urp_tombstone.c @@ -209,21 +209,21 @@ conflict_to_tombstone(char *sessionid, Slapi_Entry *entry, CSN *opcsn) Slapi_RDN *srdn = slapi_rdn_new(); const char *uniqueid = slapi_entry_get_uniqueid ( entry ); const char *newrdn = NULL; - char *conflictdn = NULL; + char *validdn = NULL; char *replconflict = slapi_entry_attr_get_charptr(entry,ATTR_NSDS5_REPLCONFLICT ); if (replconflict) { - conflictdn = strstr(replconflict, " (ADD) "); - if (conflictdn == NULL) { + validdn = strstr(replconflict, " (ADD) "); + if (validdn == NULL) { /* error, wrong type of conflict */ op_result = 1; } else { - conflictdn += 7; - slapi_rdn_init_all_dn(srdn, conflictdn); + validdn += 7; + slapi_rdn_init_all_dn(srdn, validdn); newrdn = slapi_rdn_get_nrdn(srdn); slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "conflict_to_tombstone - %s - valid entry dn: %s newrdn: %s\n", - sessionid, conflictdn, newrdn); + sessionid, validdn, newrdn); } } @@ -232,10 +232,40 @@ conflict_to_tombstone(char *sessionid, Slapi_Entry *entry, CSN *opcsn) slapi_log_err(SLAPI_LOG_REPL, repl_plugin_name, "conflict_to_tombstone - %s - Renaming entry %s to %s\n", sessionid, slapi_entry_get_dn_const (entry), newrdn); - op_result = urp_fixup_rename_entry(entry, newrdn, NULL, OP_FLAG_NOOP); - if (op_result) goto done; - op_result = urp_fixup_delete_entry (uniqueid, slapi_entry_get_dn_const (entry), opcsn, 0); + op_result = urp_fixup_rename_entry(entry, newrdn, NULL, OP_FLAG_NOOP); + if (op_result == LDAP_SUCCESS) { + op_result = urp_fixup_delete_entry (uniqueid, slapi_entry_get_dn_const (entry), opcsn, 0); + } else if (op_result == LDAP_ALREADY_EXISTS) { + /* a entry with the valid dn exists, we need to temporarily move it + * out of the way and retry + */ + char *tmprdn = slapi_ch_smprintf("cn=tmprdn_%s",uniqueid); + char *parentdn = slapi_dn_parent(validdn); + char *tmpdn = slapi_ch_smprintf("%s,%s", tmprdn, parentdn); + Slapi_DN *tmp_sdn = slapi_sdn_new_dn_byval(tmpdn); + Slapi_DN *valid_sdn = slapi_sdn_new_dn_byval(validdn) ; + op_result = urp_fixup_modrdn_entry(valid_sdn, + tmprdn, NULL, NULL, NULL, NULL, OP_FLAG_NOOP); + if (0 == op_result) { + int op_result2 = 0; + op_result = urp_fixup_rename_entry(entry, newrdn, NULL, OP_FLAG_NOOP); + if (0 == op_result) { + op_result = urp_fixup_delete_entry (uniqueid, slapi_entry_get_dn_const (entry), opcsn, 0); + } + op_result2 = urp_fixup_modrdn_entry(tmp_sdn, + newrdn, NULL, NULL, NULL, NULL, OP_FLAG_NOOP); + if (op_result2) { + op_result = op_result2; + } + + } + slapi_ch_free_string(&tmprdn); + slapi_ch_free_string(&parentdn); + slapi_ch_free_string(&tmpdn); + slapi_sdn_free(&tmp_sdn); + slapi_sdn_free(&valid_sdn); + } done: slapi_ch_free_string(&replconflict); diff --git a/ldap/servers/slapd/back-ldbm/ldbm_add.c b/ldap/servers/slapd/back-ldbm/ldbm_add.c index 412e1d3..ab9a8fd 100644 --- a/ldap/servers/slapd/back-ldbm/ldbm_add.c +++ b/ldap/servers/slapd/back-ldbm/ldbm_add.c @@ -344,6 +344,7 @@ ldbm_back_add(Slapi_PBlock *pb) is_tombstone_operation = 1; is_noop = 1; op_plugin_call = 0; + done_with_pblock_entry(pb, SLAPI_ADD_EXISTING_DN_ENTRY); rc = LDAP_SUCCESS; } else if (rc < 0) { int opreturn = 0; -- 2.9.5