From 2607f5c4a6e156f50caad96beb8328f2540b8eae Mon Sep 17 00:00:00 2001
From: gbellato <gbellato@localhost>
Date: Thu, 15 Jan 2009 07:38:52 +0000
Subject: [PATCH] Fix for issue 3683
---
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/Historical.java | 22 +++++++
opendj-sdk/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java | 39 +++++++++++-
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/UpdateOperationTest.java | 36 +++++++++++
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/service/ReplicationDomainTest.java | 28 +++++++++
4 files changed, 117 insertions(+), 8 deletions(-)
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/Historical.java b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/Historical.java
index cd45bce..89443da 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/Historical.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/Historical.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Copyright 2006-2008 Sun Microsystems, Inc.
+ * Copyright 2006-2009 Sun Microsystems, Inc.
*/
package org.opends.server.replication.plugin;
@@ -433,6 +433,26 @@
return builder.toAttribute();
}
+ /**
+ * Indicates if the Entry was renamed or added after the ChangeNumber
+ * that is given as a parameter.
+ *
+ * @param cn The ChangeNumber with which the ADD or Rename date must be
+ * compared.
+ *
+ * @return A boolean indicating if the Entry was renamed or added after
+ * the ChangeNumber that is given as a parameter.
+ */
+ public boolean AddedOrRenamedAfter(ChangeNumber cn)
+ {
+ if (cn.older(ADDDate) || cn.older(MODDNDate))
+ {
+ return true;
+ }
+ else
+ return false;
+ }
+
/**
* read the historical information from the entry attribute and
diff --git a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
index a0e0d85..fa6cf27 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/replication/plugin/LDAPReplicationDomain.java
@@ -64,6 +64,7 @@
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.CheckedOutputStream;
import java.util.zip.DataFormatException;
+
import org.opends.messages.Message;
import org.opends.messages.MessageBuilder;
import org.opends.server.admin.server.ConfigurationChangeListener;
@@ -75,6 +76,7 @@
import org.opends.server.api.SynchronizationProvider;
import org.opends.server.backends.jeb.BackendImpl;
import org.opends.server.config.ConfigException;
+import org.opends.server.controls.SubtreeDeleteControl;
import org.opends.server.core.AddOperation;
import org.opends.server.core.DeleteOperation;
import org.opends.server.core.DirectoryServer;
@@ -1069,6 +1071,8 @@
* different operation.
*/
op = msg.createOperation(conn);
+ if (op instanceof DeleteOperation)
+ op.addRequestControl(new SubtreeDeleteControl());
}
}
else
@@ -1407,9 +1411,11 @@
* The action taken here must be consistent with the actions
* done in the solveNamingConflict(AddOperation) method
* when we are adding an entry whose parent entry has already been deleted.
+ *
*/
- findAndRenameChild(entryUid, op.getEntryDN(), op);
- numUnresolvedNamingConflicts.incrementAndGet();
+ if (findAndRenameChild(entryUid, op.getEntryDN(), op))
+ numUnresolvedNamingConflicts.incrementAndGet();
+
return false;
}
else
@@ -1652,17 +1658,25 @@
* @param entryDN The DN of the entry whose child must be renamed.
* @param conflictOp The Operation that generated the conflict.
*/
- private void findAndRenameChild(
+ private boolean findAndRenameChild(
String entryUid, DN entryDN, Operation conflictOp)
{
+ boolean conflict = false;
+
// Find an rename child entries.
InternalClientConnection conn =
InternalClientConnection.getRootConnection();
+ DeleteContext ctx =
+ (DeleteContext) conflictOp.getAttachment(SYNCHROCONTEXT);
+ ChangeNumber cn = null;
+ if (ctx != null)
+ cn = ctx.getChangeNumber();
try
{
LinkedHashSet<String> attrs = new LinkedHashSet<String>(1);
attrs.add(ENTRYUIDNAME);
+ attrs.add(Historical.HISTORICALATTRIBUTENAME);
SearchFilter ALLMATCH;
ALLMATCH = SearchFilter.createFilterFromString("(objectClass=*)");
@@ -1678,9 +1692,22 @@
{
for (SearchResultEntry entry : entries)
{
- markConflictEntry(conflictOp, entry.getDN(), entryDN);
- renameConflictEntry(conflictOp, entry.getDN(),
+ /*
+ * Check the ADD and ModRDN date of the child entry. If it is after
+ * the delete date then keep the entry as a conflicting entry,
+ * otherwise delete the entry with the operation.
+ */
+ if (cn != null)
+ {
+ Historical hist = Historical.load(entry);
+ if (hist.AddedOrRenamedAfter(cn))
+ {
+ conflict = true;
+ markConflictEntry(conflictOp, entry.getDN(), entryDN);
+ renameConflictEntry(conflictOp, entry.getDN(),
Historical.getEntryUuid(entry));
+ }
+ }
}
}
}
@@ -1708,6 +1735,8 @@
mb.append(e.getLocalizedMessage());
logError(mb.toMessage());
}
+
+ return conflict;
}
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/UpdateOperationTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/UpdateOperationTest.java
index 175339a..a7db448 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/UpdateOperationTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/UpdateOperationTest.java
@@ -22,7 +22,7 @@
* CDDL HEADER END
*
*
- * Copyright 2006-2008 Sun Microsystems, Inc.
+ * Copyright 2006-2009 Sun Microsystems, Inc.
*/
package org.opends.server.replication;
@@ -1120,6 +1120,8 @@
// add domain1 entry with 2 children : domain2 and domain3
addEntry(domain1);
+ ChangeNumber olderCn = gen.newChangeNumber();
+ Thread.sleep(1000);
domain1uid = getEntryUUID(DN.decode(domain1dn));
addEntry(domain2);
domain2uid = getEntryUUID(DN.decode(domain2dn));
@@ -1134,7 +1136,7 @@
AlertCount = DummyAlertHandler.getAlertCount();
// delete domain1
- delMsg = new DeleteMsg(domain1dn, gen.newChangeNumber(), domain1uid);
+ delMsg = new DeleteMsg(domain1dn, olderCn, domain1uid);
broker.publish(delMsg);
// check that the domain1 has correctly been deleted
@@ -1167,6 +1169,36 @@
delEntry(conflictDomain3dn);
//
+ // Check that when a delete is replayed over an entry which has child
+ // those child are also deleted
+ //
+ // add domain1 entry with 2 children : domain2 and domain3
+ addEntry(domain1);
+ domain1uid = getEntryUUID(DN.decode(domain1dn));
+ addEntry(domain2);
+ domain2uid = getEntryUUID(DN.decode(domain2dn));
+ addEntry(domain3);
+ domain3uid = getEntryUUID(DN.decode(domain3dn));
+
+ updateMonitorCount(baseDn, unresolvedMonitorAttr);
+ AlertCount = DummyAlertHandler.getAlertCount();
+
+ // delete domain1
+ delMsg = new DeleteMsg(domain1dn, gen.newChangeNumber(), domain1uid);
+ broker.publish(delMsg);
+
+ // check that the domain1 has correctly been deleted
+ assertNull(getEntry(DN.decode(domain1dn), 10000, false),
+ "The DELETE replication message was not replayed");
+
+ // check that domain2 and domain3 have not been renamed as conflicting
+ assertNull(getEntry(conflictDomain2dn, 1000, true),
+ "The conflicting entries were not created");
+ assertNull(getEntry(conflictDomain3dn, 1000, true),
+ "The conflicting entries were not created");
+
+
+ //
// Check that when an entry is added on one master below an entry
// that is currently deleted on another master, the replay of the
// add on the second master cause the added entry to be renamed
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/service/ReplicationDomainTest.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/service/ReplicationDomainTest.java
index a3cdf79..d3cff52 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/service/ReplicationDomainTest.java
+++ b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/service/ReplicationDomainTest.java
@@ -41,6 +41,7 @@
import org.opends.server.replication.ReplicationTestCase;
import org.opends.server.replication.common.DSInfo;
import org.opends.server.replication.common.RSInfo;
+import org.opends.server.replication.common.ServerStatus;
import org.opends.server.replication.protocol.UpdateMsg;
import org.opends.server.replication.server.ReplServerFakeConfiguration;
import org.opends.server.replication.server.ReplicationServer;
@@ -128,6 +129,11 @@
assertTrue(replServerInfo.getGenerationId() == 1);
}
+ for (DSInfo serverInfo : domain1.getDsList())
+ {
+ assertTrue(serverInfo.getStatus() == ServerStatus.NORMAL_STATUS);
+ }
+
domain1.setGenerationID(2);
domain1.resetReplicationLog();
@@ -138,6 +144,28 @@
// The generation Id of the remote should now be 2
assertTrue(replServerInfo.getGenerationId() == 2);
}
+
+ for (DSInfo serverInfo : domain1.getDsList())
+ {
+ if (serverInfo.getDsId() == 2)
+ assertTrue(serverInfo.getStatus() == ServerStatus.BAD_GEN_ID_STATUS);
+ else
+ {
+ assertTrue(serverInfo.getDsId() == 1);
+ assertTrue(serverInfo.getStatus() == ServerStatus.NORMAL_STATUS);
+ }
+ }
+
+ for (DSInfo serverInfo : domain2.getDsList())
+ {
+ if (serverInfo.getDsId() == 2)
+ assertTrue(serverInfo.getStatus() == ServerStatus.BAD_GEN_ID_STATUS);
+ else
+ {
+ assertTrue(serverInfo.getDsId() == 1);
+ assertTrue(serverInfo.getStatus() == ServerStatus.NORMAL_STATUS);
+ }
+ }
}
finally
{
--
Gitblit v1.10.0