package org.jgroups.tests; import org.jgroups.Address; import org.jgroups.Global; import org.jgroups.JChannel; import org.jgroups.Message; import org.jgroups.blocks.MethodCall; import org.jgroups.blocks.RequestOptions; import org.jgroups.blocks.ResponseMode; import org.jgroups.blocks.RpcDispatcher; import org.jgroups.util.RspList; import org.jgroups.util.Util; import org.testng.Assert; import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; import java.util.List; import java.util.Vector; /** * Test the distributed RPC deadlock detection mechanism, using one or two channels. * * @author John Giorgiadis * @author Ovidiu Feodorov <ovidiuf@users.sourceforge.net> * * * @version $Revision: 1.23 $ */ @Test(groups=Global.STACK_DEPENDENT,sequential=true) public class Deadlock2Test extends ChannelTestBase { private String name = "Deadlock2Test"; private JChannel c1, c2; @AfterMethod void cleanup() { Util.close(c1, c2); } /** * Tests the deadlock resolution using self-calls on a single channel. The deadlock detection * is turned on so the method call should go straight through. If there is a problem, JUnit will * timeout. * * @throws Exception */ public void testOneChannel() throws Exception { c1 = createChannel(true); ServerObject serverObject = new ServerObject("obj1"); RpcDispatcher disp=new RpcDispatcher(c1, serverObject); serverObject.setRpcDispatcher(disp); c1.connect(name); Address localAddress = c1.getAddress(); // call the nested group method on itself MethodCall call = new MethodCall("outerMethod", new Object[0], new Class[0]); log("calling outerMethod() on all members"); RspList rspList = disp.callRemoteMethods(null, call, new RequestOptions(ResponseMode.GET_ALL, 0)); log("results of outerMethod(): " + rspList); Assert.assertEquals(1, rspList.size()); assertEquals("outerMethod[innerMethod]", rspList.getValue(localAddress)); assertTrue(rspList.isReceived(localAddress)); assertFalse(rspList.isSuspected(localAddress)); } /** * Tests the deadlock resolution using two different channels. The deadlock detection * is turned on. It implements the following scenario: * * Channel1 Channel2 * | | * + -------------------------------> outerMethod() * | RPC * | | * | | * | | * | <-- innerMethod() <-----------------+ ---------+ * | | | * | | <-- innerMethod() * * If there is a deadlock, JUnit will timeout and fail the test. * */ public void testTwoChannels() throws Throwable { ServerObject obj1, obj2 = null; c1 = createChannel(true); obj1 = new ServerObject("obj1"); RpcDispatcher disp1=new RpcDispatcher(c1, obj1); obj1.setRpcDispatcher(disp1); c1.connect(name); c2 = createChannel(c1); obj2 = new ServerObject("obj2"); RpcDispatcher disp2=new RpcDispatcher(c2, obj2); obj2.setRpcDispatcher(disp2); c2.connect(name); Address localAddress2 = c2.getAddress(); // call a point-to-point method on Member 2 that triggers a nested distributed RPC MethodCall call = new MethodCall("outerMethod", new Object[0], new Class[0]); log("calling outerMethod() on " + localAddress2); Object retval = disp1.callRemoteMethod(localAddress2, call, new RequestOptions(ResponseMode.GET_ALL, 0)); log("results of outerMethod(): " + retval); } public void testTwoChannelsWithInitialMulticast() throws Exception { ServerObject obj1, obj2 = null; c1 = createChannel(true); obj1 = new ServerObject("obj1"); RpcDispatcher disp1=new RpcDispatcher(c1, obj1); obj1.setRpcDispatcher(disp1); c1.connect(name); c2 = createChannel(c1); obj2 = new ServerObject("obj2"); RpcDispatcher disp2=new RpcDispatcher(c2, obj2); obj2.setRpcDispatcher(disp2); c2.connect(name); Vector<Address> dests=new Vector<Address>(); dests.add(c1.getAddress()); dests.add(c2.getAddress()); // call a point-to-point method on Member 2 that triggers a nested distributed RPC MethodCall call = new MethodCall("outerMethod", new Object[0], new Class[0]); log("calling outerMethod() on all members"); RspList rsps = disp1.callRemoteMethods(dests, call, new RequestOptions(ResponseMode.GET_ALL, 0)); log("results of outerMethod():\n" + rsps); Assert.assertEquals(2, rsps.size()); } static void log(String msg) { System.out.println("[" + Thread.currentThread() + "] " + msg); } public static class ServerObject { String myName; public ServerObject(String name) { this.myName=name; } private RpcDispatcher disp; /** * The ServerObject keeps a reference to its dispatcher to be able to send nested group * RPCs. */ public void setRpcDispatcher(RpcDispatcher rpcDispatcher) { this.disp = rpcDispatcher; } public String outerMethod() throws Exception { log("**** outerMethod() received, calling innerMethod() on all members"); MethodCall call = new MethodCall("innerMethod", new Object[0], new Class[0]); // RspList rspList = disp.callRemoteMethods(null, call, GroupResponseMode.GET_ALL, 5000); RequestOptions opts=new RequestOptions(ResponseMode.GET_ALL, 0, false, null, (Message.Flag[])null); opts.setFlags(Message.OOB); RspList<String> rspList = disp.callRemoteMethods(null, call, opts); List<String> results = rspList.getResults(); log("results of calling innerMethod():\n" + rspList); StringBuilder sb=new StringBuilder("outerMethod["); boolean first=true; for(String s: results) { if(first) first=false; else sb.append(";"); sb.append(s); } sb.append("]"); return sb.toString(); } public static String innerMethod() { log("**** innerMethod() received, returning result"); return "innerMethod"; } } }