/*
* Copyright 2013 Thomas Bocek
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package net.tomp2p.connection2;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.util.concurrent.GenericFutureListener;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import net.tomp2p.futures.BaseFutureAdapter;
import net.tomp2p.futures.FutureChannelCreator;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* Test the connection reservation.
*
* @author Thomas Bocek
*
*/
public class TestReservation {
private static final int PORT = 4000;
private static final SocketAddress SOCKET_ADDRESS = new InetSocketAddress("127.0.0.1", PORT);
private ChannelServer cs;
/**
* Starts to processes to listen to port 4000.
*
* @throws IOException
* If the process could not be started
* @throws InterruptedException
*/
@Before
public void createSink() throws IOException {
Bindings bindings = new Bindings(InetAddress.getByName("127.0.0.1"));
ChannelServerConficuration c = new ChannelServerConficuration();
c.setBindings(bindings);
c.setTcpPort(PORT);
c.setUdpPort(PORT);
c.pipelineFilter(new MyPipeLine());
cs = new ChannelServer(c, null, null);
cs.startup();
}
/**
* Terminates the "server" part.
*/
@After
public void shutdwon() {
cs.shutdown();
}
/**
* Test the TCP connection reservation.
*
* @throws InterruptedException .
*/
@Test
public void testReservationTCP() throws InterruptedException {
EventLoopGroup ev = new NioEventLoopGroup();
long start = System.currentTimeMillis();
final int round = 10;
final int inner = 200;
final int conn = 50;
final int tcpMax = 1000;
for (int i = 0; i < round; i++) {
ChannelClientConfiguration c = new ChannelClientConfiguration();
c.maxPermitsTCP(tcpMax);
c.pipelineFilter(new MyPipeLine());
Reservation r = new Reservation(ev, c);
List<FutureChannelCreator> fcc = new ArrayList<FutureChannelCreator>();
for (int j = 0; j < inner; j++) {
FutureChannelCreator fc = r.create(0, conn);
fc.addListener(new BaseFutureAdapter<FutureChannelCreator>() {
@Override
public void operationComplete(final FutureChannelCreator future) throws Exception {
final ChannelCreator cc = future.getChannelCreator();
final int timeout = 2000;
final CountDownLatch countDownLatch = new CountDownLatch(conn);
for (int k = 0; k < conn; k++) {
ChannelFuture channelFuture = cc.createTCP(SOCKET_ADDRESS, timeout,
new HashMap<String, ChannelHandler>());
channelFuture.addListener(new GenericFutureListener<ChannelFuture>() {
@Override
public void operationComplete(final ChannelFuture future) throws Exception {
future.channel().close();
countDownLatch.countDown();
}
});
}
countDownLatch.await();
cc.shutdown().awaitUninterruptibly();
}
});
fcc.add(fc);
}
for (FutureChannelCreator fcc1 : fcc) {
fcc1.awaitListeners();
}
r.shutdown().awaitUninterruptibly();
}
ev.shutdownGracefully().awaitUninterruptibly();
long time = System.currentTimeMillis() - start;
long mil = TimeUnit.SECONDS.toMillis(1);
System.err.println("BENCHMARK: opened and closed " + round + " x " + inner + " x " + conn
+ " TCP connections to localhost in " + time + " ms. STAT: TCP res open/close per sec:"
+ ((round * inner * conn * mil) / time));
}
/**
* Test the TCP connection reservation.
*
* @throws InterruptedException .
*/
@Test
public void testReservationUDP() throws InterruptedException {
EventLoopGroup ev = new NioEventLoopGroup();
long start = System.currentTimeMillis();
final int round = 10;
final int inner = 200;
final int conn = 50;
final int udpMax = 1000;
for (int i = 0; i < round; i++) {
ChannelClientConfiguration c = new ChannelClientConfiguration();
c.pipelineFilter(new MyPipeLine());
c.maxPermitsUDP(udpMax);
Reservation r = new Reservation(ev, c);
List<FutureChannelCreator> fcc = new ArrayList<FutureChannelCreator>();
for (int j = 0; j < inner; j++) {
FutureChannelCreator fc = r.create(conn, 0);
fc.addListener(new BaseFutureAdapter<FutureChannelCreator>() {
@Override
public void operationComplete(final FutureChannelCreator future) throws Exception {
final ChannelCreator cc = future.getChannelCreator();
final CountDownLatch countDownLatch = new CountDownLatch(conn);
for (int k = 0; k < conn; k++) {
ChannelFuture channelFuture = cc.createUDP(SOCKET_ADDRESS, false,
new HashMap<String, ChannelHandler>() {
});
channelFuture.addListener(new GenericFutureListener<ChannelFuture>() {
@Override
public void operationComplete(final ChannelFuture future) throws Exception {
future.channel().writeAndFlush(Unpooled.wrappedBuffer(new byte[1]));
future.channel().close();
countDownLatch.countDown();
}
});
}
countDownLatch.await();
cc.shutdown().awaitUninterruptibly();
}
});
fcc.add(fc);
}
for (FutureChannelCreator fcc1 : fcc) {
fcc1.awaitListeners();
}
r.shutdown().awaitUninterruptibly();
}
ev.shutdownGracefully().awaitUninterruptibly();
long time = System.currentTimeMillis() - start;
long mil = TimeUnit.SECONDS.toMillis(1);
System.err.println("BENCHMARK: opened and closed " + round + " x " + inner + " x " + conn
+ " UDP connections to localhost in " + time + " ms. STAT: UDP res open/close per sec:"
+ ((round * inner * conn * mil) / time));
}
/**
* Test an unclean shutdown, that means the reservation is shutdown, but the connectioncreation is not.
*
* @throws InterruptedException .
*/
@Test
public void testReservationTCPNonCleanShutdown() throws InterruptedException {
EventLoopGroup ev = new NioEventLoopGroup();
long start = System.currentTimeMillis();
final int round = 50;
final int inner = 100;
final int conn = 10;
final int tcpMax = 1000;
for (int i = 0; i < round; i++) {
ChannelClientConfiguration c = new ChannelClientConfiguration();
c.pipelineFilter(new MyPipeLine());
c.maxPermitsTCP(tcpMax);
Reservation r = new Reservation(ev, c);
List<FutureChannelCreator> fcc = new ArrayList<FutureChannelCreator>();
for (int j = 0; j < inner; j++) {
FutureChannelCreator fc = r.create(0, conn);
fc.addListener(new BaseFutureAdapter<FutureChannelCreator>() {
@Override
public void operationComplete(final FutureChannelCreator future) throws Exception {
if (future.isFailed()) {
return;
}
final ChannelCreator cc = future.getChannelCreator();
final int timeout = 2000;
for (int k = 0; k < conn; k++) {
ChannelFuture channelFuture = cc.createTCP(SOCKET_ADDRESS, timeout,
new HashMap<String, ChannelHandler>() {
});
if (channelFuture == null) {
return;
}
channelFuture.addListener(new GenericFutureListener<ChannelFuture>() {
@Override
public void operationComplete(final ChannelFuture future) throws Exception {
future.channel().close();
}
});
}
}
});
fcc.add(fc);
}
for (FutureChannelCreator fcc1 : fcc) {
fcc1.awaitListeners();
}
r.shutdown().awaitUninterruptibly();
}
ev.shutdownGracefully().awaitUninterruptibly();
long time = System.currentTimeMillis() - start;
long mil = TimeUnit.SECONDS.toMillis(1);
System.err.println("BENCHMARK: opened and closed " + round + " x " + inner + " x " + conn
+ " TCP connections to localhost in " + time + " ms. STAT: TCP unclean open/close per sec:"
+ ((round * inner * conn * mil) / time));
}
/**
* Unclean shutdown of pending connections.
*
* @throws InterruptedException .
*/
@Test
public void testReservationTCPNonCleanShutdown2() throws InterruptedException {
EventLoopGroup ev = new NioEventLoopGroup();
final int round = 50;
final int inner = 100;
final int conn = 10;
final int tcpMax = 1000;
for (int i = 0; i < round; i++) {
ChannelClientConfiguration c = new ChannelClientConfiguration();
c.pipelineFilter(new MyPipeLine());
c.maxPermitsTCP(tcpMax);
Reservation r = new Reservation(ev, c);
List<FutureChannelCreator> fcc = new ArrayList<FutureChannelCreator>();
for (int j = 0; j < inner; j++) {
FutureChannelCreator fc = r.create(0, conn);
fc.addListener(new BaseFutureAdapter<FutureChannelCreator>() {
@Override
public void operationComplete(final FutureChannelCreator future) throws Exception {
if (future.isFailed()) {
return;
}
final ChannelCreator cc = future.getChannelCreator();
final int timeout = 2000;
for (int k = 0; k < conn; k++) {
ChannelFuture channelFuture = cc.createTCP(SOCKET_ADDRESS, timeout,
new HashMap<String, ChannelHandler>() {
});
if (channelFuture == null) {
return;
}
channelFuture.addListener(new GenericFutureListener<ChannelFuture>() {
@Override
public void operationComplete(final ChannelFuture future) throws Exception {
future.channel().close();
}
});
}
}
});
fcc.add(fc);
}
r.shutdown().awaitUninterruptibly();
}
ev.shutdownGracefully().awaitUninterruptibly();
}
private static class MyPipeLine implements PipelineFilter {
@Override
public void filter(Map<String, ChannelHandler> channelHandlers, boolean tcp, boolean client) {
for (Iterator<Map.Entry<String, ChannelHandler>> iterator = channelHandlers.entrySet().iterator(); iterator
.hasNext();) {
if (iterator.next().getValue() == null) {
iterator.remove();
}
}
}
}
}