package org.jgroups.tests;
import org.jgroups.Global;
import org.jgroups.JChannel;
import org.jgroups.View;
import org.jgroups.protocols.*;
import org.jgroups.protocols.pbcast.GMS;
import org.jgroups.protocols.pbcast.NAKACK2;
import org.jgroups.protocols.pbcast.STABLE;
import org.jgroups.util.Util;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.util.concurrent.CyclicBarrier;
/**
* Creates 1 channel, then creates NUM channels, all try to join the same channel concurrently.
* @author Bela Ban Nov 20 2003
*/
@Test(groups=Global.FUNCTIONAL,singleThreaded=true)
public class ConnectStressTest {
protected static final int NUM=20;
protected final CyclicBarrier barrier=new CyclicBarrier(NUM+1);
protected final JChannel[] channels=new JChannel[NUM];
protected final MyThread[] threads=new MyThread[NUM];
static void log(String msg) {
System.out.println("-- [" + Thread.currentThread().getName() + "] " + msg);
}
@BeforeMethod protected void setup() throws Exception {
for(int i=0; i < NUM; i++) {
channels[i]=createChannel(String.valueOf((char)(i + 1)));
if(i == 0)
channels[i].connect("ConnectStressTest");
}
}
@AfterMethod protected void destroy() {Util.close(channels);}
public void testConcurrentJoining() throws Exception {
for(int i=0; i < NUM; i++) {
threads[i]=new MyThread(channels[i], i+1, barrier);
threads[i].start();
}
barrier.await(); // causes all threads to call Channel.connect()
System.out.println("*** Starting the connect phase ***");
long target_time=System.currentTimeMillis() + 60000L;
while(System.currentTimeMillis() < target_time) {
View view=channels[0].getView();
if(view != null) {
int size=view.size();
System.out.println("channel[0].view has " + size + " members (expected: " + NUM + ")");
if(size >= NUM)
break;
}
Util.sleep(1000L);
}
for(JChannel ch: channels) {
View view=ch.getView();
if(view != null)
System.out.println(ch.getName() + ": size=" + view.size() + ", view-id: " + view.getViewId());
}
for(JChannel ch: channels) {
View view=ch.getView();
int size=view != null? view.size() : 0;
assert view != null && size == NUM : "view doesn't have size of " + NUM + " (has " + size + "): " + view;
}
}
public static class MyThread extends Thread {
private final CyclicBarrier barrier;
private final JChannel ch;
public MyThread(JChannel channel, int i, CyclicBarrier barrier) {
super("thread #" + i);
this.ch=channel;
this.barrier=barrier;
}
public void run() {
try {
barrier.await(); // wait for all threads to be running
ch.connect("ConnectStressTest");
}
catch(Exception e) {
}
}
}
protected JChannel createChannel(String name) throws Exception {
return new JChannel(new SHARED_LOOPBACK(),
new SHARED_LOOPBACK_PING(),
new MERGE3().setValue("min_interval", 2000).setValue("max_interval", 5000),
new NAKACK2().setValue("log_discard_msgs", false),
new UNICAST3(),
new STABLE(),
new GMS().joinTimeout(1000).setValue("view_bundling", true).setValue("max_bundling_time", 300)
.setValue("print_local_addr", false),
new FRAG2().fragSize(8000));
}
}