package org.jgroups.tests;
import org.jgroups.protocols.MERGE2;
import org.jgroups.protocols.MERGE3;
import org.testng.annotations.*;
import org.jgroups.*;
import org.jgroups.protocols.DISCARD;
import org.jgroups.stack.ProtocolStack;
import org.jgroups.util.Promise;
import org.jgroups.util.Util;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import java.util.Properties;
/**
* Tests the NAKACK (retransmission) and STABLE (garbage collection) protocols
* by discarding 10% of all network-bound messages
*
* @author Bela Ban
*/
@Test(groups=Global.STACK_DEPENDENT,sequential=true)
public class DiscardTest extends ChannelTestBase {
JChannel ch1, ch2;
static final long NUM_MSGS=10000;
static final int MSG_SIZE=1000;
private static final String GROUP="DiscardTest";
final Promise<Long> ch1_all_received=new Promise<Long>();
final Promise<Long> ch2_all_received=new Promise<Long>();
@BeforeMethod
protected void setUp() throws Exception {
ch1_all_received.reset();
ch2_all_received.reset();
}
@AfterMethod
protected void tearDown() throws Exception{
Util.close(ch2,ch1);
}
public void testDiscardProperties() throws Exception {
_testLosslessReception(true);
}
public void testFastProperties() throws Exception {
_testLosslessReception(false);
}
private void _testLosslessReception(boolean discard) throws Exception {
Address ch1_addr, ch2_addr;
long start, stop;
ch1=createChannel(true);
ch1.setReceiver(new MyReceiver(ch1_all_received, NUM_MSGS, "ch1"));
ch2=createChannel(ch1);
ch2.setReceiver(new MyReceiver(ch2_all_received, NUM_MSGS, "ch2"));
if(discard) {
DISCARD discard_prot=new DISCARD();
Properties properties=new Properties();
properties.setProperty("down", "0.1");
ch1.getProtocolStack().insertProtocol(discard_prot, ProtocolStack.BELOW, MERGE2.class, MERGE3.class);
discard_prot=new DISCARD();
properties=new Properties();
properties.setProperty("down", "0.1");
ch2.getProtocolStack().insertProtocol(discard_prot, ProtocolStack.BELOW, MERGE2.class, MERGE3.class);
}
ch1.connect(GROUP);
ch1_addr=ch1.getAddress();
ch2.connect(GROUP);
ch2_addr=ch2.getAddress();
Util.sleep(2000);
View v=ch2.getView();
System.out.println("**** ch2's view: " + v);
Assert.assertEquals(2, v.size());
assertTrue(v.getMembers().contains(ch1_addr));
assertTrue(v.getMembers().contains(ch2_addr));
System.out.println("sending " + NUM_MSGS + " 1K messages to all members (including myself)");
start=System.currentTimeMillis();
for(int i=0;i < NUM_MSGS;i++) {
Message msg=createMessage(MSG_SIZE);
ch1.send(msg);
if(i % 1000 == 0)
System.out.println("-- sent " + i + " messages");
}
System.out.println("-- waiting for ch1 and ch2 to receive " + NUM_MSGS + " messages");
Long num_msgs;
num_msgs=ch1_all_received.getResult();
System.out.println("-- received " + num_msgs + " messages on ch1");
num_msgs=ch2_all_received.getResult();
stop=System.currentTimeMillis();
System.out.println("-- received " + num_msgs + " messages on ch2");
long diff=stop - start;
double msgs_sec=NUM_MSGS / (diff / 1000.0);
System.out.println("== Sent and received " + NUM_MSGS
+ " in "
+ diff
+ "ms, "
+ msgs_sec
+ " msgs/sec");
}
static class MyReceiver extends ReceiverAdapter {
final Promise<Long> p;
final long num_msgs_expected;
long num_msgs=0;
String channel_name;
boolean operational=true;
public MyReceiver(final Promise<Long> p,final long num_msgs_expected,String channel_name) {
this.p=p;
this.num_msgs_expected=num_msgs_expected;
this.channel_name=channel_name;
}
public void receive(Message msg) {
if(!operational)
return;
num_msgs++;
if(num_msgs > 0 && num_msgs % 1000 == 0)
System.out.println("-- received " + num_msgs + " on " + channel_name);
if(num_msgs >= num_msgs_expected) {
System.out.println("SUCCESS: received all " + num_msgs_expected
+ " messages on "
+ channel_name);
operational=false;
p.setResult(new Long(num_msgs));
}
}
public void viewAccepted(View new_view) {
System.out.println("-- view (" + channel_name + "): " + new_view);
}
}
private static Message createMessage(int size) {
byte[] buf=new byte[size];
for(int i=0;i < buf.length;i++)
buf[i]=(byte)'x';
return new Message(null, null, buf);
}
}