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 ExtendedReceiverAdapter {
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);
}
}
}