package org.jgroups.tests; import org.jgroups.*; import org.jgroups.protocols.TP; import org.jgroups.protocols.pbcast.GMS; import org.jgroups.stack.Protocol; 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.Test; import java.util.*; /** * Measure the latency between messages with message bundling enabled at the transport level * @author Bela Ban */ @Test(groups=Global.STACK_DEPENDENT,sequential=true) public class MessageBundlingTest extends ChannelTestBase { private JChannel ch1, ch2; private MyReceiver r2; private final static long LATENCY=1500L; private final static long SLEEP=5000L; private static final boolean BUNDLING=true; private static final int MAX_BYTES=64000; @AfterMethod void tearDown() throws Exception { closeChannel(ch2); closeChannel(ch1); } protected boolean useBlocking() { return false; } public void testLatencyWithoutMessageBundling() throws Exception { createChannels("testLatencyWithoutMessageBundling"); Message tmp=new Message(); setBundling(ch1, false, MAX_BYTES, 30); r2.setNumExpectedMesssages(1); Promise<Integer> promise=new Promise<Integer>(); r2.setPromise(promise); long time=System.currentTimeMillis(); ch1.send(tmp); System.out.println(">>> sent message at " + new Date()); promise.getResult(SLEEP); List<Long> list=r2.getTimes(); Assert.assertEquals(1, list.size()); Long time2=list.get(0); long diff=time2 - time; System.out.println("latency: " + diff + " ms"); assertTrue("latency (" + diff + "ms) should be less than " + LATENCY + " ms", diff <= LATENCY); } public void testLatencyWithMessageBundling() throws Exception { createChannels("testLatencyWithMessageBundling"); Message tmp=new Message(); r2.setNumExpectedMesssages(1); Promise<Integer> promise=new Promise<Integer>(); r2.setPromise(promise); long time=System.currentTimeMillis(); ch1.send(tmp); System.out.println(">>> sent message at " + new Date()); promise.getResult(SLEEP); List<Long> list=r2.getTimes(); Assert.assertEquals(1, list.size()); Long time2=list.get(0); long diff=time2 - time; System.out.println("latency: " + diff + " ms"); assertTrue("latency (" + diff + "ms) should be less than 2 times the LATENCY (" + LATENCY *2 + ")", diff <= LATENCY * 2); } public void testLatencyWithMessageBundlingAndLoopback() throws Exception { createChannels("testLatencyWithMessageBundlingAndLoopback"); Message tmp=new Message(); setLoopback(ch1, true); setLoopback(ch2, true); r2.setNumExpectedMesssages(1); Promise<Integer> promise=new Promise<Integer>(); r2.setPromise(promise); long time=System.currentTimeMillis(); System.out.println(">>> sending message at " + new Date()); ch1.send(tmp); promise.getResult(SLEEP); List<Long> list=r2.getTimes(); Assert.assertEquals(1, list.size()); Long time2=list.get(0); long diff=time2 - time; System.out.println("latency: " + diff + " ms"); assertTrue("latency (" + diff + "ms) should be less than 2 times the LATENCY (" + LATENCY *2 + ")", diff <= LATENCY * 2); } public void testLatencyWithMessageBundlingAndMaxBytes() throws Exception { createChannels("testLatencyWithMessageBundlingAndMaxBytes"); setLoopback(ch1, true); setLoopback(ch2, true); r2.setNumExpectedMesssages(10); Promise<Integer> promise=new Promise<Integer>(); r2.setPromise(promise); Util.sleep(LATENCY *2); System.out.println(">>> sending 10 messages at " + new Date()); for(int i=0; i < 10; i++) ch1.send(new Message(null, null, new byte[2000])); promise.getResult(SLEEP); // we should get the messages immediately because max_bundle_size has been exceeded by the 20 messages List<Long> list=r2.getTimes(); Assert.assertEquals(10, list.size()); for(Iterator<Long> it=list.iterator(); it.hasNext();) { Long val=it.next(); System.out.println(val); } } public void testSimple() throws Exception { createChannels("testSimple"); Message tmp=new Message(); ch2.setReceiver(new SimpleReceiver()); ch1.send(tmp); System.out.println(">>> sent message at " + new Date()); Util.sleep(5000); } private void createChannels(String cluster) throws Exception { ch1=createChannel(true, 2); ch1.setName("A"); setBundling(ch1, BUNDLING, MAX_BYTES, LATENCY); setLoopback(ch1, false); ch1.setReceiver(new NullReceiver()); ch1.connect("MessageBundlingTest-" + cluster); ch2=createChannel(ch1); ch2.setName("B"); // setBundling(ch2, BUNDLING, MAX_BYTES, LATENCY); // setLoopback(ch2, false); r2=new MyReceiver(); ch2.setReceiver(r2); ch2.connect("MessageBundlingTest-" + cluster); View view=ch2.getView(); assert view.size() == 2 : " view=" + view; } private static void setLoopback(JChannel ch, boolean b) { ProtocolStack stack=ch.getProtocolStack(); List<Protocol> prots=stack.getProtocols(); TP transport=(TP)prots.get(prots.size() -1); transport.setLoopback(b); } private static void setBundling(JChannel ch, boolean enabled, int max_bytes, long timeout) { ProtocolStack stack=ch.getProtocolStack(); List<Protocol> prots=stack.getProtocols(); TP transport=(TP)prots.get(prots.size() -1); transport.setEnableBundling(enabled); if(enabled) { transport.setMaxBundleSize(max_bytes); transport.setMaxBundleTimeout(timeout); } transport.setEnableUnicastBundling(false); if(enabled) { GMS gms=(GMS)stack.findProtocol("GMS"); gms.setViewAckCollectionTimeout(LATENCY * 2); gms.setJoinTimeout(LATENCY * 2); } } private static void closeChannel(Channel c) { if(c != null && (c.isOpen() || c.isConnected())) { c.close(); } } private static class NullReceiver extends ReceiverAdapter { } private static class SimpleReceiver extends ReceiverAdapter { long start=System.currentTimeMillis(); public void receive(Message msg) { System.out.println("<<< received message from " + msg.getSrc() + " at " + new Date() + ", latency=" + (System.currentTimeMillis() - start) + " ms"); } } private static class MyReceiver extends ReceiverAdapter { private final List<Long> times=new LinkedList<Long>(); private int num_expected_msgs; private Promise<Integer> promise; public List<Long> getTimes() { return times; } public void setNumExpectedMesssages(int num_expected_msgs) { this.num_expected_msgs=num_expected_msgs; } public void setPromise(Promise<Integer> promise) { this.promise=promise; } public int size() { return times.size(); } public void receive(Message msg) { times.add(new Long(System.currentTimeMillis())); System.out.println("<<< received message from " + msg.getSrc() + " at " + new Date()); if(times.size() >= num_expected_msgs && promise != null) { promise.setResult(times.size()); } } } }