use of io.netty.util.concurrent.EventExecutorGroup in project netty by netty.
the class LocalTransportThreadModelTest method testStagedExecution.
@Test(timeout = 5000)
public void testStagedExecution() throws Throwable {
EventLoopGroup l = new DefaultEventLoopGroup(4, new DefaultThreadFactory("l"));
EventExecutorGroup e1 = new DefaultEventExecutorGroup(4, new DefaultThreadFactory("e1"));
EventExecutorGroup e2 = new DefaultEventExecutorGroup(4, new DefaultThreadFactory("e2"));
ThreadNameAuditor h1 = new ThreadNameAuditor();
ThreadNameAuditor h2 = new ThreadNameAuditor();
ThreadNameAuditor h3 = new ThreadNameAuditor(true);
Channel ch = new LocalChannel();
// With no EventExecutor specified, h1 will be always invoked by EventLoop 'l'.
ch.pipeline().addLast(h1);
// h2 will be always invoked by EventExecutor 'e1'.
ch.pipeline().addLast(e1, h2);
// h3 will be always invoked by EventExecutor 'e2'.
ch.pipeline().addLast(e2, h3);
l.register(ch).sync().channel().connect(localAddr).sync();
// Fire inbound events from all possible starting points.
ch.pipeline().fireChannelRead("1");
ch.pipeline().context(h1).fireChannelRead("2");
ch.pipeline().context(h2).fireChannelRead("3");
ch.pipeline().context(h3).fireChannelRead("4");
// Fire outbound events from all possible starting points.
ch.pipeline().write("5");
ch.pipeline().context(h3).write("6");
ch.pipeline().context(h2).write("7");
ch.pipeline().context(h1).writeAndFlush("8").sync();
ch.close().sync();
// Wait until all events are handled completely.
while (h1.outboundThreadNames.size() < 3 || h3.inboundThreadNames.size() < 3 || h1.removalThreadNames.size() < 1) {
if (h1.exception.get() != null) {
throw h1.exception.get();
}
if (h2.exception.get() != null) {
throw h2.exception.get();
}
if (h3.exception.get() != null) {
throw h3.exception.get();
}
Thread.sleep(10);
}
String currentName = Thread.currentThread().getName();
try {
// Events should never be handled from the current thread.
Assert.assertFalse(h1.inboundThreadNames.contains(currentName));
Assert.assertFalse(h2.inboundThreadNames.contains(currentName));
Assert.assertFalse(h3.inboundThreadNames.contains(currentName));
Assert.assertFalse(h1.outboundThreadNames.contains(currentName));
Assert.assertFalse(h2.outboundThreadNames.contains(currentName));
Assert.assertFalse(h3.outboundThreadNames.contains(currentName));
Assert.assertFalse(h1.removalThreadNames.contains(currentName));
Assert.assertFalse(h2.removalThreadNames.contains(currentName));
Assert.assertFalse(h3.removalThreadNames.contains(currentName));
// Assert that events were handled by the correct executor.
for (String name : h1.inboundThreadNames) {
Assert.assertTrue(name.startsWith("l-"));
}
for (String name : h2.inboundThreadNames) {
Assert.assertTrue(name.startsWith("e1-"));
}
for (String name : h3.inboundThreadNames) {
Assert.assertTrue(name.startsWith("e2-"));
}
for (String name : h1.outboundThreadNames) {
Assert.assertTrue(name.startsWith("l-"));
}
for (String name : h2.outboundThreadNames) {
Assert.assertTrue(name.startsWith("e1-"));
}
for (String name : h3.outboundThreadNames) {
Assert.assertTrue(name.startsWith("e2-"));
}
for (String name : h1.removalThreadNames) {
Assert.assertTrue(name.startsWith("l-"));
}
for (String name : h2.removalThreadNames) {
Assert.assertTrue(name.startsWith("e1-"));
}
for (String name : h3.removalThreadNames) {
Assert.assertTrue(name.startsWith("e2-"));
}
// Assert that the events for the same handler were handled by the same thread.
Set<String> names = new HashSet<String>();
names.addAll(h1.inboundThreadNames);
names.addAll(h1.outboundThreadNames);
names.addAll(h1.removalThreadNames);
Assert.assertEquals(1, names.size());
names.clear();
names.addAll(h2.inboundThreadNames);
names.addAll(h2.outboundThreadNames);
names.addAll(h2.removalThreadNames);
Assert.assertEquals(1, names.size());
names.clear();
names.addAll(h3.inboundThreadNames);
names.addAll(h3.outboundThreadNames);
names.addAll(h3.removalThreadNames);
Assert.assertEquals(1, names.size());
// Count the number of events
Assert.assertEquals(1, h1.inboundThreadNames.size());
Assert.assertEquals(2, h2.inboundThreadNames.size());
Assert.assertEquals(3, h3.inboundThreadNames.size());
Assert.assertEquals(3, h1.outboundThreadNames.size());
Assert.assertEquals(2, h2.outboundThreadNames.size());
Assert.assertEquals(1, h3.outboundThreadNames.size());
Assert.assertEquals(1, h1.removalThreadNames.size());
Assert.assertEquals(1, h2.removalThreadNames.size());
Assert.assertEquals(1, h3.removalThreadNames.size());
} catch (AssertionError e) {
System.out.println("H1I: " + h1.inboundThreadNames);
System.out.println("H2I: " + h2.inboundThreadNames);
System.out.println("H3I: " + h3.inboundThreadNames);
System.out.println("H1O: " + h1.outboundThreadNames);
System.out.println("H2O: " + h2.outboundThreadNames);
System.out.println("H3O: " + h3.outboundThreadNames);
System.out.println("H1R: " + h1.removalThreadNames);
System.out.println("H2R: " + h2.removalThreadNames);
System.out.println("H3R: " + h3.removalThreadNames);
throw e;
} finally {
l.shutdownGracefully();
e1.shutdownGracefully();
e2.shutdownGracefully();
l.terminationFuture().sync();
e1.terminationFuture().sync();
e2.terminationFuture().sync();
}
}
use of io.netty.util.concurrent.EventExecutorGroup in project netty by netty.
the class LocalTransportThreadModelTest3 method testConcurrentAddRemove.
private static void testConcurrentAddRemove(boolean inbound) throws Exception {
EventLoopGroup l = new DefaultEventLoopGroup(4, new DefaultThreadFactory("l"));
EventExecutorGroup e1 = new DefaultEventExecutorGroup(4, new DefaultThreadFactory("e1"));
EventExecutorGroup e2 = new DefaultEventExecutorGroup(4, new DefaultThreadFactory("e2"));
EventExecutorGroup e3 = new DefaultEventExecutorGroup(4, new DefaultThreadFactory("e3"));
EventExecutorGroup e4 = new DefaultEventExecutorGroup(4, new DefaultThreadFactory("e4"));
EventExecutorGroup e5 = new DefaultEventExecutorGroup(4, new DefaultThreadFactory("e5"));
final EventExecutorGroup[] groups = { e1, e2, e3, e4, e5 };
try {
Deque<EventType> events = new ConcurrentLinkedDeque<EventType>();
final EventForwarder h1 = new EventForwarder();
final EventForwarder h2 = new EventForwarder();
final EventForwarder h3 = new EventForwarder();
final EventForwarder h4 = new EventForwarder();
final EventForwarder h5 = new EventForwarder();
final EventRecorder h6 = new EventRecorder(events, inbound);
final Channel ch = new LocalChannel();
if (!inbound) {
ch.config().setAutoRead(false);
}
ch.pipeline().addLast(e1, h1).addLast(e1, h2).addLast(e1, h3).addLast(e1, h4).addLast(e1, h5).addLast(e1, "recorder", h6);
l.register(ch).sync().channel().connect(localAddr).sync();
final LinkedList<EventType> expectedEvents = events(inbound, 8192);
Throwable cause = new Throwable();
Thread pipelineModifier = new Thread(new Runnable() {
@Override
public void run() {
Random random = new Random();
while (true) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
return;
}
if (!ch.isRegistered()) {
continue;
}
//EventForwardHandler forwardHandler = forwarders[random.nextInt(forwarders.length)];
ChannelHandler handler = ch.pipeline().removeFirst();
ch.pipeline().addBefore(groups[random.nextInt(groups.length)], "recorder", UUID.randomUUID().toString(), handler);
}
}
});
pipelineModifier.setDaemon(true);
pipelineModifier.start();
for (EventType event : expectedEvents) {
switch(event) {
case EXCEPTION_CAUGHT:
ch.pipeline().fireExceptionCaught(cause);
break;
case MESSAGE_RECEIVED:
ch.pipeline().fireChannelRead("");
break;
case MESSAGE_RECEIVED_LAST:
ch.pipeline().fireChannelReadComplete();
break;
case USER_EVENT:
ch.pipeline().fireUserEventTriggered("");
break;
case WRITE:
ch.pipeline().write("");
break;
case READ:
ch.pipeline().read();
break;
}
}
ch.close().sync();
while (events.peekLast() != EventType.UNREGISTERED) {
Thread.sleep(10);
}
expectedEvents.addFirst(EventType.ACTIVE);
expectedEvents.addFirst(EventType.REGISTERED);
expectedEvents.addLast(EventType.INACTIVE);
expectedEvents.addLast(EventType.UNREGISTERED);
for (; ; ) {
EventType event = events.poll();
if (event == null) {
Assert.assertTrue("Missing events:" + expectedEvents, expectedEvents.isEmpty());
break;
}
Assert.assertEquals(event, expectedEvents.poll());
}
} finally {
l.shutdownGracefully();
e1.shutdownGracefully();
e2.shutdownGracefully();
e3.shutdownGracefully();
e4.shutdownGracefully();
e5.shutdownGracefully();
l.terminationFuture().sync();
e1.terminationFuture().sync();
e2.terminationFuture().sync();
e3.terminationFuture().sync();
e4.terminationFuture().sync();
e5.terminationFuture().sync();
}
}
use of io.netty.util.concurrent.EventExecutorGroup in project netty by netty.
the class DefaultChannelPipelineTest method testPinExecutor.
@Test
public void testPinExecutor() {
EventExecutorGroup group = new DefaultEventExecutorGroup(2);
ChannelPipeline pipeline = new LocalChannel().pipeline();
ChannelPipeline pipeline2 = new LocalChannel().pipeline();
pipeline.addLast(group, "h1", new ChannelInboundHandlerAdapter());
pipeline.addLast(group, "h2", new ChannelInboundHandlerAdapter());
pipeline2.addLast(group, "h3", new ChannelInboundHandlerAdapter());
EventExecutor executor1 = pipeline.context("h1").executor();
EventExecutor executor2 = pipeline.context("h2").executor();
assertNotNull(executor1);
assertNotNull(executor2);
assertSame(executor1, executor2);
EventExecutor executor3 = pipeline2.context("h3").executor();
assertNotNull(executor3);
assertNotSame(executor3, executor2);
group.shutdownGracefully(0, 0, TimeUnit.SECONDS);
}
use of io.netty.util.concurrent.EventExecutorGroup in project netty by netty.
the class DefaultChannelPipelineTest method testHandlerAddedExceptionFromChildHandlerIsPropegated.
@Test(timeout = 3000)
public void testHandlerAddedExceptionFromChildHandlerIsPropegated() {
final EventExecutorGroup group1 = new DefaultEventExecutorGroup(1);
try {
final Promise<Void> promise = group1.next().newPromise();
final AtomicBoolean handlerAdded = new AtomicBoolean();
final Exception exception = new RuntimeException();
ChannelPipeline pipeline = new LocalChannel().pipeline();
pipeline.addLast(group1, new CheckExceptionHandler(exception, promise));
pipeline.addFirst(new ChannelHandlerAdapter() {
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
handlerAdded.set(true);
throw exception;
}
});
assertFalse(handlerAdded.get());
group.register(pipeline.channel());
promise.syncUninterruptibly();
} finally {
group1.shutdownGracefully();
}
}
use of io.netty.util.concurrent.EventExecutorGroup in project netty by netty.
the class DefaultChannelPipelineTest method testHandlerRemovedExceptionFromChildHandlerIsPropegated.
@Test(timeout = 3000)
public void testHandlerRemovedExceptionFromChildHandlerIsPropegated() {
final EventExecutorGroup group1 = new DefaultEventExecutorGroup(1);
try {
final Promise<Void> promise = group1.next().newPromise();
String handlerName = "foo";
final Exception exception = new RuntimeException();
ChannelPipeline pipeline = new LocalChannel().pipeline();
pipeline.addLast(handlerName, new ChannelHandlerAdapter() {
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
throw exception;
}
});
pipeline.addLast(group1, new CheckExceptionHandler(exception, promise));
group.register(pipeline.channel()).syncUninterruptibly();
pipeline.remove(handlerName);
promise.syncUninterruptibly();
} finally {
group1.shutdownGracefully();
}
}
Aggregations