[jboss-cvs] JBossAS SVN: r62445 - in branches/JBoss_4_0_1_SP1_CP: cluster/src/main/org/jboss/ha/framework/server and 5 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Fri Apr 20 14:19:10 EDT 2007
Author: fnasser at redhat.com
Date: 2007-04-20 14:19:09 -0400 (Fri, 20 Apr 2007)
New Revision: 62445
Added:
branches/JBoss_4_0_1_SP1_CP/testsuite/src/main/org/jboss/test/cluster/drm/MockHAPartition.java
Modified:
branches/JBoss_4_0_1_SP1_CP/cluster/src/main/org/jboss/ha/framework/interfaces/DistributedReplicantManager.java
branches/JBoss_4_0_1_SP1_CP/cluster/src/main/org/jboss/ha/framework/interfaces/HAPartition.java
branches/JBoss_4_0_1_SP1_CP/cluster/src/main/org/jboss/ha/framework/server/DistributedReplicantManagerImpl.java
branches/JBoss_4_0_1_SP1_CP/testsuite/src/main/org/jboss/test/cluster/test/DRMTestCase.java
branches/JBoss_4_0_1_SP1_CP/testsuite/src/main/org/jboss/test/testbeancluster/bean/StatelessSessionBean.java
branches/JBoss_4_0_1_SP1_CP/testsuite/src/main/org/jboss/test/testbeancluster/interfaces/StatelessSession.java
branches/JBoss_4_0_1_SP1_CP/testsuite/src/main/org/jboss/test/testbeancluster/test/BeanUnitTestCase.java
Log:
Merge of JBAS-2700 one-off branch (ASPATCH-197)
Modified: branches/JBoss_4_0_1_SP1_CP/cluster/src/main/org/jboss/ha/framework/interfaces/DistributedReplicantManager.java
===================================================================
--- branches/JBoss_4_0_1_SP1_CP/cluster/src/main/org/jboss/ha/framework/interfaces/DistributedReplicantManager.java 2007-04-20 14:51:57 UTC (rev 62444)
+++ branches/JBoss_4_0_1_SP1_CP/cluster/src/main/org/jboss/ha/framework/interfaces/DistributedReplicantManager.java 2007-04-20 18:19:09 UTC (rev 62445)
@@ -39,7 +39,10 @@
/**
* Callback called when the content/list of replicant for a given replicant key has changed
* @param key The name of the key of the replicant that has changed
- * @param newReplicants The list of new replicants for the give replicant key
+ * @param newReplicants The list of new replicants for the give replicant key.
+ * This list will be in a consistent order on all
+ * cluster nodes on which the current viewId is
+ * in effect
* @param newReplicantsViewId The new replicant view id corresponding to this change
*/
public void replicantsChanged(String key, List newReplicants, int newReplicantsViewId);
@@ -86,14 +89,18 @@
/**
* Return a list of all replicants.
* @param key The replicant name
- * @return An array of serialized replicants available around the cluster for the given key
+ * @return An list of serialized replicants available around the cluster
+ * for the given key. This list will be in the same order in all
+ * nodes in the cluster.
*/
public List lookupReplicants(String key);
/**
* Return a list of all replicants node names.
* @param key The replicant name
- * @return An array of replicants node names available around the cluster for the given key
+ * @return A list the node names of cluster nodes that have made available
+ * a replicant for the given key. This list will be in the same
+ * order in all nodes in the cluster.
*/
public List lookupReplicantsNodeNames(String key);
Modified: branches/JBoss_4_0_1_SP1_CP/cluster/src/main/org/jboss/ha/framework/interfaces/HAPartition.java
===================================================================
--- branches/JBoss_4_0_1_SP1_CP/cluster/src/main/org/jboss/ha/framework/interfaces/HAPartition.java 2007-04-20 14:51:57 UTC (rev 62444)
+++ branches/JBoss_4_0_1_SP1_CP/cluster/src/main/org/jboss/ha/framework/interfaces/HAPartition.java 2007-04-20 18:19:09 UTC (rev 62445)
@@ -35,9 +35,14 @@
// *******************************
//
/**
- * Return the name of the current name in the current partition. The name is
- * dynamically determined by the partition.
- * @return The partition name
+ * Return the name of this node in the current partition. The name is
+ * dynamically determined by the partition. The name is derived by
+ * calling {@link ClusterNode#getName()} on the <code>ClusterNode</code>
+ * instance that represents this node.
+ *
+ * @return The node name
+ *
+ * @see #getClusterNodes()
*/
public String getNodeName();
/**
@@ -266,7 +271,9 @@
/**
* Return the member nodes that built the current view i.e. the current partition.
- * @return An array of ClusterNode containing the node names
+ * @return An array of ClusterNode listing the current members of the partitionn.
+ * This array will be in the same order in all nodes in the cluster that
+ * have received the current view.
*/
public ClusterNode[] getClusterNodes ();
}
\ No newline at end of file
Modified: branches/JBoss_4_0_1_SP1_CP/cluster/src/main/org/jboss/ha/framework/server/DistributedReplicantManagerImpl.java
===================================================================
--- branches/JBoss_4_0_1_SP1_CP/cluster/src/main/org/jboss/ha/framework/server/DistributedReplicantManagerImpl.java 2007-04-20 14:51:57 UTC (rev 62444)
+++ branches/JBoss_4_0_1_SP1_CP/cluster/src/main/org/jboss/ha/framework/server/DistributedReplicantManagerImpl.java 2007-04-20 18:19:09 UTC (rev 62445)
@@ -8,6 +8,7 @@
package org.jboss.ha.framework.server;
+import java.util.Set;
import java.util.Vector;
import java.util.ArrayList;
import java.util.HashMap;
@@ -26,6 +27,7 @@
import org.jboss.logging.Logger;
+import org.jboss.ha.framework.interfaces.ClusterNode;
import org.jboss.ha.framework.interfaces.DistributedReplicantManager;
import org.jboss.ha.framework.interfaces.HAPartition;
@@ -368,8 +370,33 @@
HashMap replicant = (HashMap)replicants.get(key);
if (replicant == null && local == null) return null;
ArrayList rtn = new ArrayList();
- if (local != null) rtn.add(local);
- if (replicant != null) rtn.addAll(replicant.values());
+
+ if (replicant == null)
+ {
+ if (local != null)
+ rtn.add(local);
+ }
+ else
+ {
+ // JBAS-2677. Put the replicants in view order.
+ ClusterNode[] nodes = partition.getClusterNodes();
+ String replNode;
+ Object replVal;
+ for (int i = 0; i < nodes.length; i++)
+ {
+ replNode = nodes[i].getName();
+ if (local != null && nodeName.equals(replNode))
+ {
+ rtn.add(local);
+ continue;
+ }
+
+ replVal = replicant.get(replNode);
+ if (replVal != null)
+ rtn.add(replVal);
+ }
+ }
+
return rtn;
}
}
@@ -382,8 +409,32 @@
HashMap replicant = (HashMap)replicants.get(key);
if (replicant == null && !locallyReplicated) return null;
ArrayList rtn = new ArrayList();
- if (locallyReplicated) rtn.add(this.nodeName);
- if (replicant != null) rtn.addAll(replicant.keySet ());
+
+ if (replicant == null)
+ {
+ if (locallyReplicated)
+ rtn.add(this.nodeName);
+ }
+ else
+ {
+ // JBAS-2677. Put the replicants in view order.
+ Set keys = replicant.keySet();
+ ClusterNode[] nodes = partition.getClusterNodes();
+ String keyOwner;
+ for (int i = 0; i < nodes.length; i++)
+ {
+ keyOwner = nodes[i].getName();
+ if (locallyReplicated && nodeName.equals(keyOwner))
+ {
+ rtn.add(this.nodeName);
+ continue;
+ }
+
+ if (keys.contains(keyOwner))
+ rtn.add(keyOwner);
+ }
+ }
+
return rtn;
}
}
Added: branches/JBoss_4_0_1_SP1_CP/testsuite/src/main/org/jboss/test/cluster/drm/MockHAPartition.java
===================================================================
--- branches/JBoss_4_0_1_SP1_CP/testsuite/src/main/org/jboss/test/cluster/drm/MockHAPartition.java (rev 0)
+++ branches/JBoss_4_0_1_SP1_CP/testsuite/src/main/org/jboss/test/cluster/drm/MockHAPartition.java 2007-04-20 18:19:09 UTC (rev 62445)
@@ -0,0 +1,217 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+package org.jboss.test.cluster.drm;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Vector;
+
+import org.jboss.ha.framework.interfaces.ClusterNode;
+import org.jboss.ha.framework.interfaces.DistributedReplicantManager;
+import org.jboss.ha.framework.interfaces.DistributedState;
+import org.jboss.ha.framework.interfaces.HAPartition;
+import org.jgroups.stack.IpAddress;
+
+/**
+ * Mock implementation of HAPartition intended to support unit testing
+ * of DistributedReplicantManagerImpl without the need for an underlying
+ * JChannel.
+ *
+ * @author <a href="brian.stansberry at jboss.com">Brian Stansberry</a>
+ * @version $Id$
+ */
+public class MockHAPartition implements HAPartition
+{
+ public static final String PARTITION_NAME = "MockPartition";
+
+ private DistributedReplicantManager drm;
+ private Vector currentNodes;
+ private ClusterNode localAddress;
+ private ArrayList remoteReplicants;
+
+ public MockHAPartition(ClusterNode localAddress)
+ {
+ this.localAddress = localAddress;
+ }
+ // ------------------------------------------------------------ HAPartition
+
+ public String getNodeName()
+ {
+ return localAddress.getName();
+ }
+
+ public String getPartitionName()
+ {
+ return PARTITION_NAME;
+ }
+
+ public DistributedReplicantManager getDistributedReplicantManager()
+ {
+ return drm;
+ }
+
+ public DistributedState getDistributedStateService()
+ {
+
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ public void registerRPCHandler(String serviceName, Object handler)
+ {
+ if (handler instanceof DistributedReplicantManager)
+ drm = (DistributedReplicantManager) handler;
+ else
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ public void unregisterRPCHandler(String serviceName, Object subscriber)
+ {
+ if (subscriber == drm)
+ drm = null;
+ else
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ public ArrayList callMethodOnCluster(String serviceName, String methodName, Object[] args, Class[] types,
+ boolean excludeSelf) throws Exception
+ {
+ if (excludeSelf)
+ {
+ if ("_add".equals(methodName))
+ {
+ // no-op -- there is no cluster
+ return null;
+ }
+ else if ("lookupLocalReplicants".equals(methodName) && args.length == 0)
+ {
+ return remoteReplicants;
+ }
+ }
+ // TODO Implement lookupLocalReplicants for DRM SERVICE_NAME
+
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ public ArrayList callMethodOnCluster(String serviceName, String methodName, Object[] args, boolean excludeSelf)
+ throws Exception
+ {
+
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ public void callAsynchMethodOnCluster(String serviceName, String methodName, Object[] args, Class[] types,
+ boolean excludeSelf) throws Exception
+ {
+ if (excludeSelf && "_remove".equals(methodName))
+ {
+ // no-op -- there is no cluster
+ return;
+ }
+
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ public void callAsynchMethodOnCluster(String serviceName, String methodName, Object[] args, boolean excludeSelf)
+ throws Exception
+ {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ public ArrayList callMethodOnCoordinatorNode(String serviceName, String methodName, Object[] args, Class[] types,
+ boolean excludeSelf) throws Exception
+ {
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ public void subscribeToStateTransferEvents(String serviceName, HAPartitionStateTransfer subscriber)
+ {
+ // no-op. at this point the test fixture directly passes state
+ // to the target DRM
+ }
+
+ public void unsubscribeFromStateTransferEvents(String serviceName, HAPartitionStateTransfer subscriber)
+ {
+ // no-op. at this point the test fixture directly passes state
+ // to the target DRM
+ }
+
+ public void registerMembershipListener(HAMembershipListener listener)
+ {
+ // no-op. at this point the test fixture directly passes membership
+ // changes to the target DRM
+ }
+
+ public void unregisterMembershipListener(HAMembershipListener listener)
+ {
+ // no-op. at this point the test fixture directly passes membership
+ // changes to the target DRM
+ }
+
+ public boolean getAllowSynchronousMembershipNotifications()
+ {
+ return false;
+ }
+
+ public void setAllowSynchronousMembershipNotifications(boolean allowSync)
+ {
+ // no-op
+ }
+
+ public long getCurrentViewId()
+ {
+
+ throw new UnsupportedOperationException("not implemented");
+ }
+
+ public Vector getCurrentView()
+ {
+ Vector result = new Vector();
+ for (int i = 0; i < currentNodes.size(); i++)
+ result.add(((ClusterNode) currentNodes.elementAt(i)).getName());
+
+ return result;
+ }
+
+ public ClusterNode[] getClusterNodes()
+ {
+ ClusterNode[] result = new ClusterNode[currentNodes.size()];
+ return (ClusterNode[]) currentNodes.toArray(result);
+ }
+
+ public ClusterNode getClusterNode()
+ {
+ return localAddress;
+ }
+
+ // --------------------------------------------------------- Public Methods
+
+ public void setCurrentViewClusterNodes(Vector nodes)
+ {
+ this.currentNodes = nodes;
+ }
+
+ public void setRemoteReplicants(ArrayList remoteReplicants)
+ {
+ this.remoteReplicants = remoteReplicants;
+ }
+
+}
Modified: branches/JBoss_4_0_1_SP1_CP/testsuite/src/main/org/jboss/test/cluster/test/DRMTestCase.java
===================================================================
--- branches/JBoss_4_0_1_SP1_CP/testsuite/src/main/org/jboss/test/cluster/test/DRMTestCase.java 2007-04-20 14:51:57 UTC (rev 62444)
+++ branches/JBoss_4_0_1_SP1_CP/testsuite/src/main/org/jboss/test/cluster/test/DRMTestCase.java 2007-04-20 18:19:09 UTC (rev 62445)
@@ -8,9 +8,15 @@
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.Iterator;
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.ObjectName;
import javax.management.Notification;
@@ -19,9 +25,14 @@
import org.jboss.test.JBossClusteredTestCase;
import org.jboss.test.cluster.drm.IReplicants;
+import org.jboss.test.cluster.drm.MockHAPartition;
+import org.jboss.ha.framework.interfaces.ClusterNode;
+import org.jboss.ha.framework.interfaces.DistributedReplicantManager.ReplicantListener;
+import org.jboss.ha.framework.server.DistributedReplicantManagerImpl;
import org.jboss.jmx.adaptor.rmi.RMIAdaptor;
import org.jboss.jmx.adaptor.rmi.RMIAdaptorExt;
import org.jboss.jmx.adaptor.rmi.RMINotificationListener;
+import org.jgroups.stack.IpAddress;
import org.apache.log4j.Logger;
/** Tests of http session replication
@@ -45,6 +56,35 @@
log.info(notification);
}
}
+
+ /** ReplicantListener that caches the list of replicants */
+ static class CachingListener implements ReplicantListener
+ {
+ List replicants = null;
+ boolean clean = true;
+
+ public void replicantsChanged(String key, List newReplicants,
+ int newReplicantsViewId)
+ {
+ this.replicants = newReplicants;
+ if (clean && newReplicants != null)
+ {
+ int last = Integer.MIN_VALUE;
+ for (Iterator iter = newReplicants.iterator(); iter.hasNext(); )
+ {
+ int cur = ((Integer) iter.next()).intValue();
+ if (last >= cur)
+ {
+ clean = false;
+ break;
+ }
+
+ last = cur;
+ }
+ }
+ }
+
+ }
public static Test suite() throws Exception
{
@@ -104,5 +144,109 @@
assertTrue("replicants0 contains:"+entry, testSet.contains(entry));
}
}
+
+ public void testReplicantOrder() throws Exception
+ {
+ MBeanServer mbeanServer =
+ MBeanServerFactory.createMBeanServer("mockPartitionA");
+ try {
+
+ // Create a fake view for the MockHAPartition
+ ClusterNode[] nodes = new ClusterNode[5];
+ String[] names = new String[nodes.length];
+ Integer[] replicants = new Integer[nodes.length];
+ Vector allNodes = new Vector();
+ for (int i = 0; i < nodes.length; i++)
+ {
+ nodes[i] = new ClusterNode(new IpAddress("127.0.0.1", 12340 + i));
+ allNodes.add(nodes[i]);
+ names[i] = nodes[i].getName();
+ replicants[i] = new Integer(i);
+ }
+
+ MockHAPartition partition = new MockHAPartition(nodes[2]);
+ partition.setCurrentViewClusterNodes(allNodes);
+
+ DistributedReplicantManagerImpl drm =
+ new DistributedReplicantManagerImpl(partition, mbeanServer);
+ drm.init();
+ drm.start();
+
+ CachingListener listener = new CachingListener();
+ drm.registerListener("TEST", listener);
+
+ SecureRandom random = new SecureRandom();
+ boolean[] added = new boolean[nodes.length];
+ List lookup = null;
+ for (int i = 0; i < 10; i++)
+ {
+ int node = random.nextInt(nodes.length);
+ if (added[node])
+ {
+ if (node == 2)
+ drm.remove("TEST");
+ else
+ drm._remove("TEST", nodes[node].getName());
+ added[node] = false;
+ }
+ else
+ {
+ if (node == 2)
+ drm.add("TEST", replicants[node]);
+ else
+ drm._add("TEST", nodes[node].getName(), replicants[node]);
+ added[node] = true;
+ }
+
+ // Confirm the proper order of the replicant node names
+ lookup = maskListClass(drm.lookupReplicantsNodeNames("TEST"));
+ confirmReplicantList(lookup, names, added);
+
+ // Confirm the proper order of the replicants via lookupReplicants
+ lookup = maskListClass(drm.lookupReplicants("TEST"));
+ confirmReplicantList(lookup, replicants, added);
+
+ // Confirm the listener got the same list
+// assertEquals("Listener received a correct list", lookup,
+// maskListClass(listener.replicants));
+ }
+
+ // Let the asynchronous notification thread catch up
+ sleep(25);
+
+ // Confirm all lists presented to the listener were properly ordered
+ assertTrue("Listener saw no misordered lists", listener.clean);
+
+ }
+ finally {
+ MBeanServerFactory.releaseMBeanServer(mbeanServer);
+ }
+ }
+
+ private void confirmReplicantList(List current, Object[] all, boolean[] added)
+ {
+ Iterator iter = current.iterator();
+ for (int i = 0; i < added.length; i++)
+ {
+ if (added[i])
+ {
+ assertTrue("List has more replicants", iter.hasNext());
+ assertEquals("Replicant for node " + i + " is next",
+ all[i], iter.next());
+ }
+ }
+ assertFalse("List has no extra replicants", iter.hasNext());
+ }
+
+ /** Converts the given list to an ArrayList, if it isn't already */
+ private List maskListClass(List toMask)
+ {
+ if (toMask instanceof ArrayList)
+ return toMask;
+ else if (toMask == null)
+ return new ArrayList();
+ else
+ return new ArrayList(toMask);
+ }
}
Modified: branches/JBoss_4_0_1_SP1_CP/testsuite/src/main/org/jboss/test/testbeancluster/bean/StatelessSessionBean.java
===================================================================
--- branches/JBoss_4_0_1_SP1_CP/testsuite/src/main/org/jboss/test/testbeancluster/bean/StatelessSessionBean.java 2007-04-20 14:51:57 UTC (rev 62444)
+++ branches/JBoss_4_0_1_SP1_CP/testsuite/src/main/org/jboss/test/testbeancluster/bean/StatelessSessionBean.java 2007-04-20 18:19:09 UTC (rev 62445)
@@ -90,4 +90,9 @@
return numberOfCalls;
}
+ public String getBindAddress()
+ {
+ return System.getProperty("jboss.bind.address");
+ }
+
}
Modified: branches/JBoss_4_0_1_SP1_CP/testsuite/src/main/org/jboss/test/testbeancluster/interfaces/StatelessSession.java
===================================================================
--- branches/JBoss_4_0_1_SP1_CP/testsuite/src/main/org/jboss/test/testbeancluster/interfaces/StatelessSession.java 2007-04-20 14:51:57 UTC (rev 62444)
+++ branches/JBoss_4_0_1_SP1_CP/testsuite/src/main/org/jboss/test/testbeancluster/interfaces/StatelessSession.java 2007-04-20 18:19:09 UTC (rev 62445)
@@ -31,4 +31,7 @@
public long getCallCount()
throws RemoteException;
+
+ public String getBindAddress()
+ throws RemoteException;
}
Modified: branches/JBoss_4_0_1_SP1_CP/testsuite/src/main/org/jboss/test/testbeancluster/test/BeanUnitTestCase.java
===================================================================
--- branches/JBoss_4_0_1_SP1_CP/testsuite/src/main/org/jboss/test/testbeancluster/test/BeanUnitTestCase.java 2007-04-20 14:51:57 UTC (rev 62444)
+++ branches/JBoss_4_0_1_SP1_CP/testsuite/src/main/org/jboss/test/testbeancluster/test/BeanUnitTestCase.java 2007-04-20 18:19:09 UTC (rev 62445)
@@ -125,6 +125,51 @@
getLog().debug("ok");
}
+ public void testRoundRobin() throws Exception
+ {
+ getLog().debug("+++ Enter testRoundRobin");
+
+ // Connect to the server0 JNDI
+ String[] urls = getNamingURLs();
+ Properties env1 = new Properties();
+ env1.setProperty(Context.INITIAL_CONTEXT_FACTORY,
+ "org.jnp.interfaces.NamingContextFactory");
+ env1.setProperty(Context.PROVIDER_URL, urls[0]);
+ InitialContext ctx = new InitialContext(env1);
+
+ // Do 4 home lookups in case different lookups lead to different patterns
+ for (int i = 0; i < 4; i++)
+ {
+ StatelessSessionHome home =
+ (StatelessSessionHome) ctx.lookup("nextgen_StatelessSession");
+ assertTrue("home != null", home != null);
+ getLog().debug("ok");
+
+ String last = null;
+ for (int j = 0; j < 10; j++)
+ {
+ StatelessSession slsb = home.create();
+ assertTrue("slsb != null", slsb != null);
+ getLog().debug("ok");
+
+ for (int k = 0; k < 3; k++)
+ {
+ String cur = slsb.getBindAddress();
+ if (cur == null)
+ {
+ getLog().debug("jboss.bind.address property not set; aborting");
+ return;
+ }
+
+ assertFalse("Target switched", cur.equals(last));
+ last = cur;
+ }
+ }
+ }
+
+ getLog().debug("+++ Exit testRoundRobin");
+ }
+
public void testStatelessBeanColocation() throws Exception
{
getLog().debug(++test+"- "+"testStatelessBeanColocation");
More information about the jboss-cvs-commits
mailing list