package org.jgroups.tests;
import org.jgroups.Address;
import org.jgroups.Global;
import org.jgroups.blocks.cs.NioClient;
import org.jgroups.blocks.cs.NioServer;
import org.jgroups.blocks.cs.ReceiverAdapter;
import org.jgroups.stack.IpAddress;
import org.jgroups.util.Util;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Tests transfer of messages from client to server
* @author Bela Ban
* @since 3.6.7
*/
@Test(groups=Global.FUNCTIONAL,singleThreaded=true)
public class NioServerTest {
protected static final int NUM_MSGS=10000;
protected static final int NUM_SENDERS=25;
protected static final int MSG_SIZE=1000;
protected static final int recv_buf_size=50000, send_buf_size=10000;
protected NioServer srv;
protected NioClient client;
protected final AtomicInteger counter=new AtomicInteger(0);
protected final Sender[] senders=new Sender[NUM_SENDERS];
protected final CountDownLatch latch=new CountDownLatch(1);
@BeforeMethod protected void init() throws Exception {
srv=new NioServer(Util.getLocalhost(), 0);
srv.sendBufferSize(send_buf_size).receiveBufferSize(recv_buf_size);
srv.start();
client=new NioClient(null, 0, Util.getLocalhost(), ((IpAddress)srv.localAddress()).getPort());
client.sendBufferSize(send_buf_size).receiveBufferSize(recv_buf_size);
client.maxSendBuffers(1000);
client.start();
for(int i=0; i < senders.length; i++) {
senders[i]=new Sender(counter, latch, client);
senders[i].start();
}
}
@AfterMethod protected void destroy() {Util.close(client, srv);}
public void testTransfer() throws Exception {
MyReceiver receiver=new MyReceiver();
srv.receiver(receiver);
latch.countDown(); // releases senders
for(int i=0; i < 10; i++) {
if(receiver.good() + receiver.bad() >= NUM_MSGS)
break;
Util.sleep(500);
}
System.out.printf("%d good buffers, %d bad buffers\n", receiver.good(), receiver.bad());
if(receiver.bad() > 0) {
List<byte[]> bad_msgs=receiver.badMsgs();
for(byte[] arr: bad_msgs)
System.out.printf("bad buffer: length=%d\n", arr.length);
assert receiver.bad() == 0 : String.format("%d bad msgs, %d good msgs\n", receiver.bad(), receiver.good());
}
}
protected static class Sender extends Thread {
protected final AtomicInteger cnt;
protected final CountDownLatch latch;
protected final NioClient client;
public Sender(AtomicInteger cnt, CountDownLatch latch, NioClient client) {
this.cnt=cnt;
this.latch=latch;
this.client=client;
}
public void run() {
int num_sends=0;
try {
latch.await();
}
catch(InterruptedException e) {
e.printStackTrace();
}
while(cnt.incrementAndGet() <= NUM_MSGS) {
num_sends++;
try {
client.send(new byte[MSG_SIZE], 0, MSG_SIZE);
}
catch(Exception e) {
e.printStackTrace();
}
}
System.out.printf("Thread %s sent %d msgs\n", Thread.currentThread().getId(), num_sends);
}
}
protected static class MyReceiver extends ReceiverAdapter {
protected int good, bad;
protected List<byte[]> bad_msgs=new ArrayList<>(1000);
public int good() {return good;}
public int bad() {return bad;}
public List<byte[]> badMsgs() {return bad_msgs;}
public void receive(Address sender, byte[] buf, int offset, int length) {
if(length != MSG_SIZE) {
bad++;
byte[] copy=new byte[length];
System.arraycopy(buf, offset, copy, 0, length);
bad_msgs.add(copy);
}
else
good++;
}
}
}