[jboss-cvs] JBossAS SVN: r58933 - branches/Branch_4_2/testsuite/src/main/org/jboss/test/cluster/test

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Fri Dec 8 13:25:49 EST 2006


Author: jerrygauth
Date: 2006-12-08 13:25:48 -0500 (Fri, 08 Dec 2006)
New Revision: 58933

Modified:
   branches/Branch_4_2/testsuite/src/main/org/jboss/test/cluster/test/DRMTestCase.java
Log:
JBAS-2560, JBAS-2470 - use GossipRouter to simulate merges

Modified: branches/Branch_4_2/testsuite/src/main/org/jboss/test/cluster/test/DRMTestCase.java
===================================================================
--- branches/Branch_4_2/testsuite/src/main/org/jboss/test/cluster/test/DRMTestCase.java	2006-12-08 16:29:56 UTC (rev 58932)
+++ branches/Branch_4_2/testsuite/src/main/org/jboss/test/cluster/test/DRMTestCase.java	2006-12-08 18:25:48 UTC (rev 58933)
@@ -26,19 +26,20 @@
 import java.security.SecureRandom;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Vector;
-import java.util.List;
-import java.util.HashSet;
 
 import javax.management.MBeanServer;
 import javax.management.MBeanServerFactory;
 import javax.management.MBeanServerInvocationHandler;
+import javax.management.Notification;
 import javax.management.ObjectName;
-import javax.management.Notification;
 
 import junit.framework.Test;
 
+import org.apache.log4j.Logger;
 import org.jboss.test.JBossClusteredTestCase;
 import org.jboss.test.cluster.drm.IReplicants;
 import org.jboss.test.cluster.drm.MockHAPartition;
@@ -46,11 +47,14 @@
 import org.jboss.ha.framework.interfaces.DistributedReplicantManager;
 import org.jboss.ha.framework.interfaces.DistributedReplicantManager.ReplicantListener;
 import org.jboss.ha.framework.server.DistributedReplicantManagerImpl;
+import org.jboss.ha.framework.server.HAPartitionImpl;
 import org.jboss.jmx.adaptor.rmi.RMIAdaptor;
 import org.jboss.jmx.adaptor.rmi.RMIAdaptorExt;
 import org.jboss.jmx.adaptor.rmi.RMINotificationListener;
+import org.jgroups.Channel;
+import org.jgroups.JChannel;
+import org.jgroups.stack.GossipRouter;
 import org.jgroups.stack.IpAddress;
-import org.apache.log4j.Logger;
 
 import EDU.oswego.cs.dl.util.concurrent.Semaphore;
 
@@ -62,6 +66,21 @@
  */
 public class DRMTestCase extends JBossClusteredTestCase
 {
+   private static final String SERVICEA = "serviceA";
+   private static final String SERVICEB = "serviceB";
+	
+   protected static final String CHANNEL_PROPS =
+	      "TUNNEL(router_port=4747;router_host=localhost;loopback=true):" +
+	      "PING(timeout=1000;num_initial_members=2;gossip_host=localhost;gossip_port=4747):" +
+	      "MERGE2(min_interval=3000;max_interval=5000):" +
+	      "FD(timeout=1000;max_tries=2;shun=false):" +
+	      "pbcast.NAKACK(gc_lag=50;retransmit_timeout=600,1200,2400,4800):" +
+	      "UNICAST(timeout=600,1200,2400):" +
+	      "pbcast.STABLE(desired_avg_gossip=20000):" +
+	      "pbcast.GMS(join_timeout=5000;join_retry_timeout=2000;" +
+	      "print_local_addr=false;shun=false):" +
+	      "pbcast.STATE_TRANSFER";
+   
    static class TestListener extends UnicastRemoteObject
       implements RMINotificationListener
    {
@@ -583,7 +602,9 @@
    
    /**
     * Tests the functionality of isMasterReplica(), also testing merge
-    * handling.
+    * handling.  This test creates and manipulates two HAPartition instances in memory 
+    * so it doesn't require a server deployment.  The partition instances communicate via
+    * a GossipRouter.  The router is stopped and restarted to simulate a merge condition.
     * 
     * TODO move this test out of the testsuite and into the cluster module
     *      itself, since it doesn't rely on the container.
@@ -592,116 +613,148 @@
     */
    public void testIsMasterReplica() throws Exception
    {
+	  MBeanServer mbeanServer1 = null;
+	  MBeanServer mbeanServer2 = null;
+	  JChannel channel1 = null;
+	  JChannel channel2 = null;
+	  GossipRouter router = null;
       log.debug("+++ testIsMasterReplica()");
-      
-      MBeanServer mbeanServer = 
-         MBeanServerFactory.createMBeanServer("mockPartition");
-      try {
-         ClusterNode localAddress = new ClusterNode(new IpAddress("127.0.0.1", 12345));
-         MockHAPartition partition = new MockHAPartition(localAddress);
-      
-         DistributedReplicantManagerImpl drm = 
-               new DistributedReplicantManagerImpl(partition, mbeanServer);
 
-         drm.init();
+      try
+      {  
+         String partitionName = "DRMTestCasePartition";
+         log.info("DRMTestCase.testIsMasterReplica() - starting GossipRouter");
+         router = new GossipRouter(4747, "localhost");
+    	 router.start();
          
-         // Create a fake view for the MockHAPartition
+	     mbeanServer1 = MBeanServerFactory.createMBeanServer("DRMTestCaseServer1");	      
+	     channel1 = createTestChannel(CHANNEL_PROPS);
+	     HAPartitionImpl partition1 = createTestPartition(partitionName, channel1, mbeanServer1, "DRMTestCaseNode1");
+	     
+	     mbeanServer2 = MBeanServerFactory.createMBeanServer("DRMTestCaseServer2");	      
+	     channel2 = createTestChannel(CHANNEL_PROPS);
+	     HAPartitionImpl partition2 = createTestPartition(partitionName, channel2, mbeanServer2, "DRMTestCaseNode2");
+	   
+         DistributedReplicantManager drm1 = partition1.getDistributedReplicantManager();
+         DistributedReplicantManager drm2 = partition2.getDistributedReplicantManager();
          
-         Vector remoteAddresses = new Vector();
-         for (int i = 1; i < 5; i++)
-            remoteAddresses.add(new ClusterNode(new IpAddress("127.0.0.1", 12340 + i)));
+         // confirm that each partition contains two nodes   
+         assertEquals("Partition1 should contain two nodes; ", 2, partition1.getCurrentView().size());
+         assertEquals("Partition2 should contain two nodes; ", 2, partition2.getCurrentView().size());
          
-         Vector allNodes = new Vector(remoteAddresses);
-         allNodes.add(localAddress);
-         partition.setCurrentViewClusterNodes(allNodes);
+	     drm1.add(SERVICEA, "valueA1");
+	     drm2.add(SERVICEA, "valueA2");
+	     drm2.add(SERVICEB, "valueB2");
+	     
+	     // test that only one node is the master replica for serviceA
+         assertTrue("ServiceA must have a master replica", 
+        		 drm1.isMasterReplica(SERVICEA) || drm2.isMasterReplica(SERVICEA));
+         assertTrue("ServiceA must have a single master replica", 
+        		 drm1.isMasterReplica(SERVICEA) != drm2.isMasterReplica(SERVICEA));
+ 
+         // ServiceB should only be a master replica on partition2
+         assertFalse("ServiceB should not be a master replica on partition1", 
+        		 drm1.isMasterReplica(SERVICEB));
+         assertTrue("ServiceB must have a master replica on partition2", 
+        		 drm2.isMasterReplica(SERVICEB));
          
-         // Pass fake state to DRMImpl
-      
-         HashMap replicants = new HashMap();
-         ArrayList remoteResponses = new ArrayList();
-         for (int i = 0; i < remoteAddresses.size(); i++)
-         {
-            ClusterNode node = (ClusterNode) remoteAddresses.elementAt(i);
-            Integer replicant = new Integer(i + 1);
-            replicants.put(node.getName(), replicant);
-            HashMap localReplicant = new HashMap();
-            localReplicant.put("Mock", replicant);
-            remoteResponses.add(new Object[] {node.getName(), localReplicant});
-         }
-         HashMap services = new HashMap();
-         services.put("Mock", replicants);
+         // confirm that each partition contains correct DRM replicants for services A and B  
+         assertEquals("Partition1 should contain two DRM replicants for serviceA; ", 
+        		 2, drm1.lookupReplicants(SERVICEA).size());
+         assertEquals("Partition2 should contain two DRM replicants for serviceA; ", 
+        		 2, drm2.lookupReplicants(SERVICEA).size());
+         assertEquals("Partition1 should contain one DRM replicant for serviceB; ", 
+        		 1, drm1.lookupReplicants(SERVICEB).size());
+         assertEquals("Partition2 should contain one DRM replicant for serviceB; ", 
+        		 1, drm2.lookupReplicants(SERVICEB).size());
+
+         // simulate a split of the partition
+         router.stop();
+         sleepThread(10000);
          
-         int hash = 0;
-         for (int i = 1; i < 5; i++)
-            hash += (new Integer(i)).hashCode();
+         // confirm that each partition contains one node   
+         assertEquals("Partition1 should contain one node after split; ", 
+        		 1, partition1.getCurrentView().size());
+         assertEquals("Partition2 should contain one node after split; ", 
+        		 1, partition2.getCurrentView().size());
+        
+         // confirm that each node is a master replica for serviceA after the split
+         assertTrue("ServiceA should be a master replica on partition1 after split", 
+        		 drm1.isMasterReplica(SERVICEA));
+         assertTrue("ServiceA should be a master replica on partition2 after split", 
+        		 drm2.isMasterReplica(SERVICEA));
          
-         HashMap intraviewIds = new HashMap();
-         intraviewIds.put("Mock", new Integer(hash));
-      
-         partition.setRemoteReplicants(remoteResponses);
+         // ServiceB should still only be a master replica on partition2 after split
+         assertFalse("ServiceB should not be a master replica on partition1 after split", 
+        		 drm1.isMasterReplica(SERVICEB));
+         assertTrue("ServiceB must have a master replica on partition2 after split", 
+        		 drm2.isMasterReplica(SERVICEB));
          
-         drm.setCurrentState(new Object[] {services, intraviewIds });
+         // Remove ServiceA replicant from partition1         
+         drm1.remove(SERVICEA);
          
-         drm.start();
+         // test that this node is not the master replica         
+         assertFalse("partition1 is not master replica after dropping ServiceA replicant", 
+        		 drm1.isMasterReplica(SERVICEA));
          
-         // add a local replicant
+         //Restore the local replicant         
+         drm1.add(SERVICEA, "valueA1a");
          
-         drm.add("Mock", new Integer(5));
-         
-         // test that this node is not the master replica
-         
-         assertFalse("Local node is not master after startup", 
-                     drm.isMasterReplica("Mock")); 
-      
-         // simulate a split where this node is the coord
-         
-         Vector localOnly = new Vector();
-         localOnly.add(localAddress);
-         
-         partition.setCurrentViewClusterNodes(localOnly);
-         partition.setRemoteReplicants(new ArrayList());
-         
-         drm.membershipChanged(remoteAddresses, new Vector(), localOnly);
-         
-         // test that this node is the master replica
-         
-         assertTrue("Local node is master after split", drm.isMasterReplica("Mock"));
-         
-         // Remove our local replicant
-         
-         drm.remove("Mock");
-         
-         // test that this node is not the master replica
-         
-         assertFalse("Local node is not master after dropping replicant", 
-                     drm.isMasterReplica("Mock"));
-         
-         // Restore the local replicant 
-         
-         drm.add("Mock", new Integer(5));
-         
          // simulate a merge
+         router.start();
+         // it seems to take more than 10 seconds for the merge to take effect
+         sleepThread(15000);
          
-         Vector mergeGroups = new Vector();
-         mergeGroups.add(remoteAddresses);
-         mergeGroups.add(localOnly);
+         // confirm that each partition contains two nodes again   
+         assertEquals("Partition1 should contain two nodes after merge; ", 
+        		 2, partition1.getCurrentView().size());
+         assertEquals("Partition2 should contain two nodes after merge; ", 
+        		 2, partition2.getCurrentView().size());
          
-         partition.setCurrentViewClusterNodes(allNodes);
-         partition.setRemoteReplicants(remoteResponses);
+	     // test that only one node is the master replica for serviceA after merge
+         assertTrue("ServiceA must have a master replica after merge", 
+        		 drm1.isMasterReplica(SERVICEA) || drm2.isMasterReplica(SERVICEA));
+         assertTrue("ServiceA must have a single master replica after merge", 
+        		 drm1.isMasterReplica(SERVICEA) != drm2.isMasterReplica(SERVICEA));
+ 
+         // ServiceB should only be a master replica on partition2 after merge
+         assertFalse("ServiceB should not be a master replica on partition1 after merge", 
+        		 drm1.isMasterReplica(SERVICEB));
+         assertTrue("ServiceB must have a master replica on partition2 after merge", 
+        		 drm2.isMasterReplica(SERVICEB));
          
-         drm.membershipChangedDuringMerge(new Vector(), remoteAddresses, 
-                                          allNodes, mergeGroups);         
+         // confirm that each partition contains correct DRM replicants for services A and B after merge 
+         assertEquals("Partition1 should contain two DRM replicants for serviceA after merge; ", 
+        		 2, drm1.lookupReplicants(SERVICEA).size());
+         assertEquals("Partition2 should contain two DRM replicants for serviceA after merge; ", 
+        		 2, drm2.lookupReplicants(SERVICEA).size());
+         assertEquals("Partition1 should contain one DRM replicant for serviceB after merge; ", 
+        		 1, drm1.lookupReplicants(SERVICEB).size());
+         assertEquals("Partition2 should contain one DRM replicant for serviceB after merge; ", 
+        		 1, drm2.lookupReplicants(SERVICEB).size());
          
-         // Merge processing is done asynchronously, so pause a bit
-         sleepThread(100);
-         
-         // test that this node is not the master replica
-         
-         assertFalse("Local node is not master after merge", 
-                     drm.isMasterReplica("Mock")); 
+         partition1.closePartition();
+         partition2.closePartition();
       }
-      finally {
-         MBeanServerFactory.releaseMBeanServer(mbeanServer);
+      finally
+      {
+         log.info("DRMTestCase.testIsMasterReplica() - cleaning up resources");
+         if (mbeanServer1 != null)
+    	    MBeanServerFactory.releaseMBeanServer(mbeanServer1);
+    	 if (mbeanServer2 != null)
+    	    MBeanServerFactory.releaseMBeanServer(mbeanServer2);
+    	 if (channel1 != null)
+    	 {
+    		 channel1.disconnect();
+    		 channel1.close();
+    	 }
+    	 if (channel2 != null)
+    	 {
+    		 channel2.disconnect();
+    		 channel2.close();
+    	 }
+         if (router != null)
+            router.stop();
       }
    }
    
@@ -1214,6 +1267,31 @@
       else
          return new ArrayList(toMask);
    }
+   
+   private JChannel createTestChannel(String props) throws Exception
+   {
+      JChannel channel = new JChannel(props);
+	  channel.setOpt(Channel.AUTO_RECONNECT, Boolean.TRUE);
+	  channel.setOpt(Channel.AUTO_GETSTATE, Boolean.TRUE);
+	  return channel;
+   }
+   
+   private HAPartitionImpl createTestPartition(String partitionName, JChannel channel, 
+		   									   MBeanServer server, String nodeName) throws Exception
+   {
+      // initialize HAPartition replicating logic from org.jboss.ha.framework.server.ClusterPartition
+      HAPartitionImpl partition = new HAPartitionImpl(partitionName, channel, false, server);
+	  // suppress JNDI binding else second instance will fail with NameAlreadyBound exception
+	  partition.setBindIntoJndi(false);
+	  partition.init();
+	  HashMap staticNodeName = new java.util.HashMap();
+	  staticNodeName.put("additional_data", nodeName.getBytes());
+	  channel.down(new org.jgroups.Event(org.jgroups.Event.CONFIG, staticNodeName));
+	  channel.getProtocolStack().flushEvents();
+	  channel.connect(partitionName);
+	  partition.startPartition();
+      return partition;
+   }
 
    private static void sleepThread(long millis)
    {




More information about the jboss-cvs-commits mailing list