Attempts to use Epoll native transport if available.
Uses Epoll.isAvailable() to check availability.
Refer : http://netty.io/wiki/native-transports.html
Change-Id: I0019a084b0f2410f4cea7d5541fe0e5b49699bec
Depends-on: I073093f9a7b28de9890a6842f8bef72d4fdf6872
Signed-off-by: Dileep Ranganathan <dileep.ranganathan@intel.com>
<groupId>io.netty</groupId>
<artifactId>netty-transport</artifactId>
</dependency>
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-transport-native-epoll</artifactId>
+ <!-- Explicitly bring in the linux classifier, test may fail on 32-bit linux -->
+ <classifier>linux-x86_64</classifier>
+ </dependency>
</dependencies>
</project>
<groupId>org.opendaylight.controller</groupId>
<artifactId>config-api</artifactId>
</dependency>
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-transport-native-epoll</artifactId>
+ <!-- Explicitly bring in the linux classifier, test may fail on 32-bit linux -->
+ <classifier>linux-x86_64</classifier>
+ </dependency>
</dependencies>
</project>
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
-import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.epoll.Epoll;
import org.opendaylight.openflowjava.protocol.api.connection.ConnectionConfiguration;
import org.opendaylight.openflowjava.protocol.api.connection.SwitchConnectionHandler;
import org.opendaylight.openflowjava.protocol.api.extensibility.DeserializerRegistry;
factory.setDeserializationFactory(deserializationFactory);
factory.setUseBarrier(connConfig.useBarrier());
final TransportProtocol transportProtocol = (TransportProtocol) connConfig.getTransferProtocol();
+
+ // Check if Epoll native transport is available.
+ // TODO : Add option to disable Epoll.
+ boolean isEpollEnabled = Epoll.isAvailable();
+
if (transportProtocol.equals(TransportProtocol.TCP) || transportProtocol.equals(TransportProtocol.TLS)) {
server = new TcpHandler(connConfig.getAddress(), connConfig.getPort());
final TcpChannelInitializer channelInitializer = factory.createPublishingChannelInitializer();
((TcpHandler) server).setChannelInitializer(channelInitializer);
- ((TcpHandler) server).initiateEventLoopGroups(connConfig.getThreadConfiguration());
+ ((TcpHandler) server).initiateEventLoopGroups(connConfig.getThreadConfiguration(), isEpollEnabled);
- final NioEventLoopGroup workerGroupFromTcpHandler = ((TcpHandler) server).getWorkerGroup();
- connectionInitializer = new TcpConnectionInitializer(workerGroupFromTcpHandler);
+ final EventLoopGroup workerGroupFromTcpHandler = ((TcpHandler) server).getWorkerGroup();
+ connectionInitializer = new TcpConnectionInitializer(workerGroupFromTcpHandler, isEpollEnabled);
connectionInitializer.setChannelInitializer(channelInitializer);
connectionInitializer.run();
} else if (transportProtocol.equals(TransportProtocol.UDP)){
server = new UdpHandler(connConfig.getAddress(), connConfig.getPort());
+ ((UdpHandler) server).initiateEventLoopGroups(connConfig.getThreadConfiguration(), isEpollEnabled);
((UdpHandler) server).setChannelInitializer(factory.createUdpChannelInitializer());
} else {
throw new IllegalStateException("Unknown transport protocol received: " + transportProtocol);
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.EventLoopGroup;
-import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.epoll.EpollSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
-
import org.opendaylight.openflowjava.protocol.api.connection.ThreadConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private TcpChannelInitializer channelInitializer;
private Bootstrap b;
+ private boolean isEpollEnabled;
/**
* Constructor
* @param workerGroup - shared worker group
*/
- public TcpConnectionInitializer(NioEventLoopGroup workerGroup) {
+ public TcpConnectionInitializer(EventLoopGroup workerGroup, boolean isEpollEnabled) {
Preconditions.checkNotNull(workerGroup, "WorkerGroup can't be null");
this.workerGroup = workerGroup;
+ this.isEpollEnabled = isEpollEnabled;
}
@Override
public void run() {
b = new Bootstrap();
- b.group(workerGroup).channel(NioSocketChannel.class)
- .handler(channelInitializer);
+ if(isEpollEnabled) {
+ b.group(workerGroup).channel(EpollSocketChannel.class)
+ .handler(channelInitializer);
+ } else {
+ b.group(workerGroup).channel(NioSocketChannel.class)
+ .handler(channelInitializer);
+ }
}
@Override
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.concurrent.GenericFutureListener;
+import io.netty.channel.epoll.Epoll;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.epoll.EpollEventLoopGroup;
+import io.netty.channel.epoll.EpollServerSocketChannel;
+
import java.net.InetAddress;
import java.net.InetSocketAddress;
private int port;
private String address;
private final InetAddress startupAddress;
- private NioEventLoopGroup workerGroup;
- private NioEventLoopGroup bossGroup;
+ private EventLoopGroup workerGroup;
+ private EventLoopGroup bossGroup;
private final SettableFuture<Boolean> isOnlineFuture;
private ThreadConfiguration threadConfig;
private TcpChannelInitializer channelInitializer;
+ private Class<? extends ServerSocketChannel> socketChannelClass;
+
/**
* Constructor of TCPHandler that listens on selected port.
*
* Any other setting means netty will measure the time it spent selecting
* and spend roughly proportional time executing tasks.
*/
- workerGroup.setIoRatio(100);
+ //workerGroup.setIoRatio(100);
final ChannelFuture f;
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
- .channel(NioServerSocketChannel.class)
+ .channel(socketChannelClass)
.handler(new LoggingHandler(LogLevel.DEBUG))
.childHandler(channelInitializer)
.option(ChannelOption.SO_BACKLOG, 128)
* Initiate event loop groups
* @param threadConfiguration number of threads to be created, if not specified in threadConfig
*/
- public void initiateEventLoopGroups(ThreadConfiguration threadConfiguration) {
+ public void initiateEventLoopGroups(ThreadConfiguration threadConfiguration, boolean isEpollEnabled) {
+
+ if(isEpollEnabled) {
+ initiateEpollEventLoopGroups(threadConfiguration);
+ } else {
+ initiateNioEventLoopGroups(threadConfiguration);
+ }
+ }
+
+ /**
+ * Initiate Nio event loop groups
+ * @param threadConfiguration number of threads to be created, if not specified in threadConfig
+ */
+ public void initiateNioEventLoopGroups(ThreadConfiguration threadConfiguration) {
+ socketChannelClass = NioServerSocketChannel.class;
if (threadConfiguration != null) {
bossGroup = new NioEventLoopGroup(threadConfiguration.getBossThreadCount());
workerGroup = new NioEventLoopGroup(threadConfiguration.getWorkerThreadCount());
bossGroup = new NioEventLoopGroup();
workerGroup = new NioEventLoopGroup();
}
+ ((NioEventLoopGroup)workerGroup).setIoRatio(100);
+ }
+
+ /**
+ * Initiate Epoll event loop groups with Nio as fall back
+ * @param threadConfiguration
+ */
+ protected void initiateEpollEventLoopGroups(ThreadConfiguration threadConfiguration) {
+ try {
+ socketChannelClass = EpollServerSocketChannel.class;
+ if (threadConfiguration != null) {
+ bossGroup = new EpollEventLoopGroup(threadConfiguration.getBossThreadCount());
+ workerGroup = new EpollEventLoopGroup(threadConfiguration.getWorkerThreadCount());
+ } else {
+ bossGroup = new EpollEventLoopGroup();
+ workerGroup = new EpollEventLoopGroup();
+ }
+ ((EpollEventLoopGroup)workerGroup).setIoRatio(100);
+ return;
+ } catch (Throwable ex) {
+ LOGGER.debug("Epoll initiation failed");
+ }
+
+ //Fallback mechanism
+ initiateNioEventLoopGroups(threadConfiguration);
}
/**
* @return workerGroup
*/
- public NioEventLoopGroup getWorkerGroup() {
+ public EventLoopGroup getWorkerGroup() {
return workerGroup;
}
package org.opendaylight.openflowjava.protocol.impl.core;
-import io.netty.channel.socket.nio.NioDatagramChannel;
+import io.netty.channel.socket.DatagramChannel;
/**
* @author michal.polkorab
*
*/
-public class UdpChannelInitializer extends ProtocolChannelInitializer<NioDatagramChannel> {
+public class UdpChannelInitializer extends ProtocolChannelInitializer<DatagramChannel> {
@Override
- protected void initChannel(NioDatagramChannel ch) throws Exception {
+ protected void initChannel(DatagramChannel ch) throws Exception {
ch.pipeline().addLast(PipelineHandlers.OF_DATAGRAMPACKET_HANDLER.name(),
new OFDatagramPacketHandler(getSwitchConnectionHandler()));
OFDatagramPacketDecoder ofDatagramPacketDecoder = new OFDatagramPacketDecoder();
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
+import io.netty.channel.epoll.EpollDatagramChannel;
+import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.DatagramChannel;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.util.concurrent.GenericFutureListener;
private final SettableFuture<Boolean> isOnlineFuture;
private UdpChannelInitializer channelInitializer;
private ThreadConfiguration threadConfig;
+ private Class<? extends DatagramChannel> datagramChannelClass;
/**
* Constructor of UdpHandler that listens on selected port.
@Override
public void run() {
- if (threadConfig != null) {
- group = new NioEventLoopGroup(threadConfig.getWorkerThreadCount());
- } else {
- group = new NioEventLoopGroup();
- }
final ChannelFuture f;
try {
Bootstrap b = new Bootstrap();
b.group(group)
- .channel(NioDatagramChannel.class)
+ .channel(datagramChannelClass)
.option(ChannelOption.SO_BROADCAST, false)
.handler(channelInitializer);
public void setThreadConfig(ThreadConfiguration threadConfig) {
this.threadConfig = threadConfig;
}
+
+ /**
+ * Initiate event loop groups
+ * @param threadConfiguration number of threads to be created, if not specified in threadConfig
+ */
+ public void initiateEventLoopGroups(ThreadConfiguration threadConfiguration, boolean isEpollEnabled) {
+
+ if(isEpollEnabled) {
+ initiateEpollEventLoopGroups(threadConfiguration);
+ } else {
+ initiateNioEventLoopGroups(threadConfiguration);
+ }
+ }
+
+ /**
+ * Initiate Nio event loop groups
+ * @param threadConfiguration number of threads to be created, if not specified in threadConfig
+ */
+ public void initiateNioEventLoopGroups(ThreadConfiguration threadConfiguration) {
+ datagramChannelClass = NioDatagramChannel.class;
+ if (threadConfiguration != null) {
+ group = new NioEventLoopGroup(threadConfiguration.getWorkerThreadCount());
+ } else {
+ group = new NioEventLoopGroup();
+ }
+ }
+
+ /**
+ * Initiate Epoll event loop groups with Nio as fall back
+ * @param threadConfiguration
+ */
+ protected void initiateEpollEventLoopGroups(ThreadConfiguration threadConfiguration) {
+ try {
+ datagramChannelClass = EpollDatagramChannel.class;
+ if (threadConfiguration != null) {
+ group = new EpollEventLoopGroup(threadConfiguration.getWorkerThreadCount());
+ } else {
+ group = new EpollEventLoopGroup();
+ }
+ return;
+ } catch (Throwable ex) {
+ LOGGER.debug("Epoll initiation failed");
+ }
+
+ //Fallback mechanism
+ initiateNioEventLoopGroups(threadConfiguration);
+ }
}
\ No newline at end of file
import java.net.Socket;
import java.util.concurrent.ExecutionException;
+import io.netty.channel.unix.Errors;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mock;
tcpHandler = new TcpHandler(null, 0);
tcpHandler.setChannelInitializer(mockChannelInitializer);
- assertEquals("failed to start server", true, startupServer()) ;
+ assertEquals("failed to start server", true, startupServer(false)) ;
+ assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort())) ;
+ shutdownServer();
+ }
+
+ /**
+ * Test run with null address set on Epoll native transport
+ * @throws IOException
+ * @throws InterruptedException
+ * @throws ExecutionException
+ */
+ @Test
+ public void testRunWithNullAddressOnEpoll() throws IOException, InterruptedException, ExecutionException {
+
+ tcpHandler = new TcpHandler(null, 0);
+ tcpHandler.setChannelInitializer(mockChannelInitializer);
+
+ //Use Epoll native transport
+ assertEquals("failed to start server", true, startupServer(true)) ;
assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort())) ;
shutdownServer();
}
tcpHandler = new TcpHandler(serverAddress, 0);
tcpHandler.setChannelInitializer(mockChannelInitializer);
- assertEquals("failed to start server", true, startupServer()) ;
+ assertEquals("failed to start server", true, startupServer(false)) ;
assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort())) ;
shutdownServer();
}
+ /**
+ * Test run with address set on Epoll native transport
+ * @throws IOException
+ * @throws InterruptedException
+ * @throws ExecutionException
+ */
+ @Test
+ public void testRunWithAddressOnEpoll() throws IOException, InterruptedException, ExecutionException {
+
+ tcpHandler = new TcpHandler(serverAddress, 0);
+ tcpHandler.setChannelInitializer(mockChannelInitializer);
+
+ //Use Epoll native transport
+ assertEquals("failed to start server", true, startupServer(true));
+ assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort()));
+ shutdownServer();
+ }
+
/**
* Test run with encryption
* @throws InterruptedException
* @throws ExecutionException
*/
@Test
- public void testRunWithEncryption () throws InterruptedException, IOException, ExecutionException {
+ public void testRunWithEncryption() throws InterruptedException, IOException, ExecutionException {
int serverPort = 28001;
tcpHandler = new TcpHandler(serverAddress, serverPort);
tcpHandler.setChannelInitializer(mockChannelInitializer);
- assertEquals( "failed to start server", true, startupServer()) ;
- assertEquals( "wrong connection count", 0, tcpHandler.getNumberOfConnections() );
- assertEquals( "wrong port", serverPort, tcpHandler.getPort() );
- assertEquals( "wrong address", serverAddress.getHostAddress(), tcpHandler.getAddress()) ;
+ assertEquals( "failed to start server", true, startupServer(false));
+ assertEquals( "wrong connection count", 0, tcpHandler.getNumberOfConnections());
+ assertEquals( "wrong port", serverPort, tcpHandler.getPort());
+ assertEquals( "wrong address", serverAddress.getHostAddress(), tcpHandler.getAddress());
- assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort())) ;
+ assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort()));
+
+ shutdownServer();
+ }
+
+ /**
+ * Test run with encryption on Epoll native transport
+ * @throws InterruptedException
+ * @throws IOException
+ * @throws ExecutionException
+ */
+ @Test
+ public void testRunWithEncryptionOnEpoll() throws InterruptedException, IOException, ExecutionException {
+ int serverPort = 28001;
+ tcpHandler = new TcpHandler(serverAddress, serverPort);
+ tcpHandler.setChannelInitializer(mockChannelInitializer);
+
+ //Use Epoll native transport
+ assertEquals( "failed to start server", true, startupServer(true));
+ assertEquals( "wrong connection count", 0, tcpHandler.getNumberOfConnections());
+ assertEquals( "wrong port", serverPort, tcpHandler.getPort());
+ assertEquals( "wrong address", serverAddress.getHostAddress(), tcpHandler.getAddress());
+
+ assertEquals("failed to connect client", true, clientConnection(tcpHandler.getPort()));
shutdownServer();
}
try {
tcpHandler = new TcpHandler(serverAddress, serverPort);
tcpHandler.setChannelInitializer(mockChannelInitializer);
- tcpHandler.initiateEventLoopGroups(null);
+ tcpHandler.initiateEventLoopGroups(null, false);
tcpHandler.run();
} catch (Exception e) {
if (e instanceof BindException) {
Assert.assertTrue("Expected BindException has not been thrown", exceptionThrown == true);
}
+ /**
+ * Test run on already used port
+ * @throws IOException
+ */
+ @Test
+ public void testSocketAlreadyInUseOnEpoll() throws IOException {
+ int serverPort = 28001;
+ Socket firstBinder = new Socket();
+ boolean exceptionThrown = false;
+ try {
+ firstBinder.bind(new InetSocketAddress(serverAddress, serverPort));
+ } catch (Exception e) {
+ Assert.fail("Test precondition failed - not able to bind socket to port " + serverPort);
+ }
+ try {
+ tcpHandler = new TcpHandler(serverAddress, serverPort);
+ tcpHandler.setChannelInitializer(mockChannelInitializer);
+ //Use Epoll native transport
+ tcpHandler.initiateEventLoopGroups(null, true);
+ tcpHandler.run();
+ } catch (Exception e) {
+ if (e instanceof BindException || e instanceof Errors.NativeIoException) {
+ exceptionThrown = true;
+ }
+ }
+ firstBinder.close();
+ Assert.assertTrue("Expected BindException has not been thrown", exceptionThrown == true);
+ }
+
/**
* Trigger the server shutdown and wait 2 seconds for completion
*/
* @throws IOException
* @throws ExecutionException
*/
- private Boolean startupServer() throws InterruptedException, IOException, ExecutionException {
+ private Boolean startupServer(boolean isEpollEnabled) throws InterruptedException, IOException, ExecutionException {
ListenableFuture<Boolean> online = tcpHandler.getIsOnlineFuture();
- tcpHandler.initiateEventLoopGroups(null);
+ /**
+ * Test EPoll based native transport if isEpollEnabled is true.
+ * Else use Nio based transport.
+ */
+ tcpHandler.initiateEventLoopGroups(null, isEpollEnabled);
(new Thread(tcpHandler)).start();
int retry = 0;
while (online.isDone() != true && retry++ < 20) {
} catch (InterruptedException | ExecutionException | TimeoutException e) {
Assert.fail();
}
- }
+ }
/**
* Tests correct provider shutdown
public void testWithEmptyAddress() throws InterruptedException, ExecutionException, IOException {
udpHandler = new UdpHandler(null, 0);
udpHandler.setChannelInitializer(udpChannelInitializerMock);
- Assert.assertTrue("Wrong - start server", startupServer());
+ Assert.assertTrue("Wrong - start server", startupServer(false));
+ try {
+ Assert.assertTrue(udpHandler.getIsOnlineFuture().get(1500,TimeUnit.MILLISECONDS).booleanValue());
+ } catch (TimeoutException e) {
+ Assert.fail("Wrong - getIsOnlineFuture timed out");
+ }
+ Assert.assertFalse("Wrong - port has been set to zero", udpHandler.getPort() == 0);
+ shutdownServer();
+ }
+
+ /**
+ * Test to create UdpHandler with empty address and zero port on Epoll native transport
+ * @throws InterruptedException
+ * @throws ExecutionException
+ * @throws IOException
+ */
+ @Test
+ public void testWithEmptyAddressOnEpoll() throws InterruptedException, ExecutionException, IOException {
+ udpHandler = new UdpHandler(null, 0);
+ udpHandler.setChannelInitializer(udpChannelInitializerMock);
+ Assert.assertTrue("Wrong - start server", startupServer(true));
try {
Assert.assertTrue(udpHandler.getIsOnlineFuture().get(1500,TimeUnit.MILLISECONDS).booleanValue());
} catch (TimeoutException e) {
int port = 9874;
udpHandler = new UdpHandler(InetAddress.getLocalHost(), port);
udpHandler.setChannelInitializer(udpChannelInitializerMock);
- Assert.assertTrue("Wrong - start server", startupServer());
+ Assert.assertTrue("Wrong - start server", startupServer(false));
try {
Assert.assertTrue(udpHandler.getIsOnlineFuture().get(1500,TimeUnit.MILLISECONDS).booleanValue());
} catch (TimeoutException e) {
shutdownServer();
}
- private Boolean startupServer() throws InterruptedException, IOException, ExecutionException {
- ListenableFuture<Boolean> online = udpHandler.getIsOnlineFuture();
+ /**
+ * Test to create UdpHandler with fill address and given port on Epoll native transport
+ * @throws InterruptedException
+ * @throws ExecutionException
+ * @throws IOException
+ */
+ @Test
+ public void testWithAddressAndPortOnEpoll() throws InterruptedException, ExecutionException, IOException{
+ int port = 9874;
+ udpHandler = new UdpHandler(InetAddress.getLocalHost(), port);
+ udpHandler.setChannelInitializer(udpChannelInitializerMock);
+ Assert.assertTrue("Wrong - start server", startupServer(true));
+ try {
+ Assert.assertTrue(udpHandler.getIsOnlineFuture().get(1500,TimeUnit.MILLISECONDS).booleanValue());
+ } catch (TimeoutException e) {
+ Assert.fail("Wrong - getIsOnlineFuture timed out");
+ }
+ Assert.assertEquals("Wrong - bad port number has been set", port, udpHandler.getPort());
+ shutdownServer();
+ }
+ private Boolean startupServer(boolean isEpollEnabled) throws InterruptedException, IOException, ExecutionException {
+ ListenableFuture<Boolean> online = udpHandler.getIsOnlineFuture();
+ /**
+ * Test EPoll based native transport if isEpollEnabled is true.
+ * Else use Nio based transport.
+ */
+ udpHandler.initiateEventLoopGroups(null, isEpollEnabled);
(new Thread(udpHandler)).start();
int retry = 0;
while (online.isDone() != true && retry++ < 20) {
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
-import io.netty.channel.socket.nio.NioSocketChannel;
+import io.netty.channel.socket.SocketChannel;
import io.netty.handler.ssl.SslHandler;
import javax.net.ssl.SSLEngine;
*
* @author michal.polkorab
*/
-public class SimpleClientInitializer extends ChannelInitializer<NioSocketChannel> {
+public class SimpleClientInitializer extends ChannelInitializer<SocketChannel> {
private SettableFuture<Boolean> isOnlineFuture;
private boolean secured;
}
@Override
- public void initChannel(NioSocketChannel ch) throws Exception {
+ public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
if (secured) {
SSLEngine engine = ClientSslContextFactory.getClientContext()
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
-import io.netty.channel.socket.nio.NioDatagramChannel;
+import io.netty.channel.socket.DatagramChannel;
import com.google.common.util.concurrent.SettableFuture;
*
* @author michal.polkorab
*/
-public class UdpSimpleClientInitializer extends ChannelInitializer<NioDatagramChannel> {
+public class UdpSimpleClientInitializer extends ChannelInitializer<DatagramChannel> {
private SettableFuture<Boolean> isOnlineFuture;
private ScenarioHandler scenarioHandler;
}
@Override
- public void initChannel(NioDatagramChannel ch) throws Exception {
+ public void initChannel(DatagramChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
SimpleClientHandler simpleClientHandler = new SimpleClientHandler(isOnlineFuture, scenarioHandler);
simpleClientHandler.setScenario(scenarioHandler);