From dd9090e630e82d58abdc1bfea933bbe02a3a2485 Mon Sep 17 00:00:00 2001
From: gbellato <gbellato@localhost>
Date: Thu, 03 Jan 2008 16:35:57 +0000
Subject: [PATCH]  fix for 2794 : Delete are sometimes not replayed when they immediately follow a moddn    When a delete is done on the new name of an entry immediately after renaming it, the dependencies between these 2 operations are not detected and the delete can therefore be replayed without waiting for the moddn to complete. This cause the delete to fail and not being replayed.

---
 opends/tests/unit-tests-testng/src/server/org/opends/server/replication/DependencyTest.java |  128 ++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 127 insertions(+), 1 deletions(-)

diff --git a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/DependencyTest.java b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/DependencyTest.java
index b093c50..be9671e 100644
--- a/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/DependencyTest.java
+++ b/opends/tests/unit-tests-testng/src/server/org/opends/server/replication/DependencyTest.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Portions Copyright 2007 Sun Microsystems, Inc.
+ *      Portions Copyright 2007-2008 Sun Microsystems, Inc.
  */
 package org.opends.server.replication;
 
@@ -250,6 +250,131 @@
   }
 
   /**
+   * Check the dependency between moddn and delete operation
+   * when an entry is renamed to a new dn and then deleted.
+   */
+  @SuppressWarnings("unchecked")
+  @Test(enabled=true)
+  public void moddnDelDependencyTest() throws Exception
+  {
+    ReplicationServer replServer = null;
+    ReplicationDomain domain = null;
+    DN baseDn = DN.decode(BASEDN_STRING);
+    SynchronizationProvider replicationPlugin = null;
+    short brokerId = 2;
+    short serverId = 1;
+    short replServerId = 1;
+
+    cleanDB();
+
+    try
+    {
+      //
+      // Create replication server, replication domain and broker.
+      //
+      
+      String entryldif = "dn:" + BASEDN_STRING + "\n"
+      + "objectClass: top\n"
+      + "objectClass: domain\n";
+      Entry entry = TestCaseUtils.entryFromLdifString(entryldif);
+      AttributeType uidType =
+        DirectoryServer.getSchema().getAttributeType("entryuuid");
+      ChangeNumberGenerator gen = new ChangeNumberGenerator(brokerId, 0L);
+      int renamedEntryUuid = 100;
+
+      // find  a free port for the replicationServer
+      ServerSocket socket = TestCaseUtils.bindFreePort();
+      int replServerPort = socket.getLocalPort();
+      socket.close();
+
+      replicationPlugin = new MultimasterReplication();
+      DirectoryServer.registerSynchronizationProvider(replicationPlugin);
+      ReplServerFakeConfiguration conf =
+        new ReplServerFakeConfiguration(replServerPort, "addModDeldependency",
+                                        0, replServerId, 0,
+                                        200, null);
+      replServer = new ReplicationServer(conf);
+
+      // configure and start replication of dc=example,dc=com on the server
+      SortedSet<String> replServers = new TreeSet<String>();
+      replServers.add("localhost:"+replServerPort);
+      DomainFakeCfg domainConf =
+        new DomainFakeCfg(baseDn, serverId, replServers);
+      domainConf.setHeartbeatInterval(100000);
+
+      Thread.sleep(2000);
+      domain = MultimasterReplication.createNewDomain(domainConf);
+      
+      ReplicationBroker broker =
+        openReplicationSession(baseDn, brokerId, 1000, replServerPort, 1000,
+                               false);
+      
+      // add an entry to play with.
+      entry.removeAttribute(uidType);
+      entry.addAttribute(new Attribute("entryuuid",
+                         stringUID(renamedEntryUuid)),
+                         new LinkedList<AttributeValue>());
+      String addDn = "dc=moddndel" + "," + BASEDN_STRING;
+      AddMsg addMsg =
+        new AddMsg(gen.newChangeNumber(), addDn, stringUID(renamedEntryUuid),
+                   stringUID(1),
+                   entry.getObjectClassAttribute(),
+                   entry.getAttributes(), null );
+
+      broker.publish(addMsg);
+      
+      // check that the entry was correctly added
+      boolean found =
+        checkEntryHasAttribute(DN.decode(addDn), "entryuuid",
+                               stringUID(renamedEntryUuid),
+                               30000, true);
+      
+      assertTrue(found, "The initial entry add failed");
+      
+    
+      // disable the domain to make sure that the messages are 
+      // all sent in a row.
+      domain.disable();
+      
+      // rename and delete the entry.
+      ModifyDNMsg moddnMsg =
+        new ModifyDNMsg(addDn, gen.newChangeNumber(),
+                        stringUID(renamedEntryUuid),
+                        stringUID(1), true, null, "dc=new_name");
+      broker.publish(moddnMsg);
+      DeleteMsg delMsg =
+        new DeleteMsg("dc=new_name" + "," + BASEDN_STRING,
+                      gen.newChangeNumber(), stringUID(renamedEntryUuid));
+      broker.publish(delMsg);
+      
+      // enable back the domain to trigger message replay.
+      domain.enable();
+      
+      // check that entry does not exist anymore.
+      Thread.sleep(10000);
+      found = checkEntryHasAttribute(DN.decode("dc=new_name" + "," + BASEDN_STRING),
+                                     "entryuuid",
+                                     stringUID(renamedEntryUuid),
+                                     30000, false);
+      
+      assertFalse(found, "The delete dependencies was not correctly enforced");
+    }
+    finally
+    {
+      if (replServer != null)
+        replServer.shutdown();
+
+      if (domain != null)
+        MultimasterReplication.deleteDomain(baseDn);
+
+      if (replicationPlugin != null)
+        DirectoryServer.deregisterSynchronizationProvider(replicationPlugin);
+    }
+  
+  }
+  
+  
+  /**
    * Clean the database and replace with a single entry.
    *
    * @throws FileNotFoundException
@@ -286,6 +411,7 @@
           + "ds-task-import-reject-file: " + path + "reject\n");
   }
 
+
   /**
    * Check that after a sequence of add/del/add done on the same DN
    * the second entry is in the database.

--
Gitblit v1.10.0