package org.jgroups.tests; import org.jgroups.*; import org.jgroups.util.Util; import org.testng.annotations.AfterMethod; import org.testng.annotations.Test; import java.util.concurrent.CyclicBarrier; /** * @author Bela Ban */ @Test(groups=Global.STACK_DEPENDENT,sequential=true) public class ConcurrentCloseTest extends ChannelTestBase { JChannel c1, c2; @AfterMethod void tearDown() throws Exception { Util.close(c2, c1); } /** * 2 channels, both call Channel.close() at exactly the same time */ public void testConcurrentClose() throws Exception { System.setProperty("useBlocking", "true"); // enables reception of block() and unblock() callbacks c1=createChannel(true); c1.setReceiver(new MyReceiver("C1")); c2=createChannel(c1); c2.setReceiver(new MyReceiver("C2")); final String GROUP=getUniqueClusterName("ConcurrentCloseTest"); c1.connect(GROUP); c2.connect(GROUP); CyclicBarrier barrier=new CyclicBarrier(3); Closer one=new Closer(c1, barrier), two=new Closer(c2, barrier); one.start(); two.start(); Util.sleep(500); barrier.await(); // starts the closing of the 2 channels one.join(10000); two.join(10000); assertFalse(one.isAlive()); assertFalse(two.isAlive()); } private static class Closer extends Thread { private final Channel channel; final private CyclicBarrier barrier; public Closer(Channel channel, CyclicBarrier barrier) { this.channel=channel; this.barrier=barrier; } public void run() { try { barrier.await(); System.out.println("closing channel for " + channel.getAddress()); channel.close(); } catch(Exception e) { } } } private static class MyReceiver extends ReceiverAdapter { private final String name; public MyReceiver(String name) { this.name=name; } public void block() { System.out.println("[" + name + "] block()"); } public void unblock() { System.out.println("[" + name + "] unblock()"); } public void viewAccepted(View new_view) { System.out.println("[" + name + "] " + new_view); } public void receive(Message msg) { System.out.println("[" + name + "] " + msg); } } }