package org.jgroups.tests; import org.jgroups.*; import org.jgroups.protocols.DISCARD; import org.jgroups.protocols.MERGE3; import org.jgroups.protocols.TCP_NIO2; import org.jgroups.protocols.TP; import org.jgroups.stack.ProtocolStack; import org.jgroups.util.Promise; import org.jgroups.util.Util; import org.testng.annotations.AfterMethod; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; 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,singleThreaded=true) public class DiscardTest extends ChannelTestBase { JChannel a, b; 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<>(); final Promise<Long> ch2_all_received=new Promise<>(); @BeforeMethod protected void setUp() throws Exception { ch1_all_received.reset(); ch2_all_received.reset(); } @AfterMethod protected void tearDown() throws Exception { TP tp_a=a.getProtocolStack().getTransport(), tp_b=b.getProtocolStack().getTransport(); if(tp_a instanceof TCP_NIO2) { System.out.printf("partial writes in A: %d, partial writes in B: %d\n", ((TCP_NIO2)tp_a).numPartialWrites(), ((TCP_NIO2)tp_b).numPartialWrites()); } Util.close(b, a); } public void testDiscardProperties() throws Exception { _testLosslessReception(true); } public void testFastProperties() throws Exception { _testLosslessReception(false); } private void _testLosslessReception(boolean discard) throws Exception { long start, stop; a=createChannel(true).name("A"); a.setReceiver(new MyReceiver(ch1_all_received, NUM_MSGS, "A")); b=createChannel(a).name("B"); b.setReceiver(new MyReceiver(ch2_all_received, NUM_MSGS, "B")); a.connect(GROUP); b.connect(GROUP); Util.waitUntilAllChannelsHaveSameView(10000, 500, a, b); if(discard) { DISCARD discard_prot=new DISCARD(); Properties properties=new Properties(); properties.setProperty("down", "0.1"); a.getProtocolStack().insertProtocol(discard_prot, ProtocolStack.Position.BELOW, MERGE3.class); discard_prot=new DISCARD(); properties=new Properties(); properties.setProperty("down", "0.1"); b.getProtocolStack().insertProtocol(discard_prot, ProtocolStack.Position.BELOW, MERGE3.class); } System.out.printf("sending %d %d-byte messages to all members (including myself)\n", NUM_MSGS, MSG_SIZE); start=System.currentTimeMillis(); for(int i=0;i < NUM_MSGS;i++) { Message msg=createMessage(MSG_SIZE); a.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.getResultWithTimeout(10000); System.out.println("-- received " + num_msgs + " messages on ch1"); num_msgs=ch2_all_received.getResultWithTimeout(10000); 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.printf("== Sent and received %d in %d ms, %.2f msgs/sec\n", NUM_MSGS, diff, 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.printf("-- received %d on %s\n", num_msgs, channel_name); if(num_msgs >= num_msgs_expected) { System.out.printf("SUCCESS: received all %d messages on %s\n", num_msgs_expected, channel_name); operational=false; p.setResult(num_msgs); } } public void viewAccepted(View new_view) { System.out.printf("-- view (%s): %s\n", 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, buf); } }