use of io.netty.channel.local.LocalAddress in project netty by netty.
the class FixedChannelPoolTest method testAcquireNewConnectionWhen.
/**
* Tests that the acquiredChannelCount is not added up several times for the same channel acquire request.
* @throws Exception
*/
@Test
public void testAcquireNewConnectionWhen() throws Exception {
LocalAddress addr = new LocalAddress(getLocalAddrId());
Bootstrap cb = new Bootstrap();
cb.remoteAddress(addr);
cb.group(group).channel(LocalChannel.class);
ServerBootstrap sb = new ServerBootstrap();
sb.group(group).channel(LocalServerChannel.class).childHandler(new ChannelInitializer<LocalChannel>() {
@Override
public void initChannel(LocalChannel ch) throws Exception {
ch.pipeline().addLast(new ChannelInboundHandlerAdapter());
}
});
// Start server
Channel sc = sb.bind(addr).syncUninterruptibly().channel();
ChannelPoolHandler handler = new TestChannelPoolHandler();
ChannelPool pool = new FixedChannelPool(cb, handler, 1);
Channel channel1 = pool.acquire().syncUninterruptibly().getNow();
channel1.close().syncUninterruptibly();
pool.release(channel1);
Channel channel2 = pool.acquire().syncUninterruptibly().getNow();
assertNotSame(channel1, channel2);
sc.close().syncUninterruptibly();
channel2.close().syncUninterruptibly();
pool.close();
}
use of io.netty.channel.local.LocalAddress in project netty by netty.
the class FixedChannelPoolTest method testAcquire.
@Test
public void testAcquire() throws Exception {
LocalAddress addr = new LocalAddress(getLocalAddrId());
Bootstrap cb = new Bootstrap();
cb.remoteAddress(addr);
cb.group(group).channel(LocalChannel.class);
ServerBootstrap sb = new ServerBootstrap();
sb.group(group).channel(LocalServerChannel.class).childHandler(new ChannelInitializer<LocalChannel>() {
@Override
public void initChannel(LocalChannel ch) throws Exception {
ch.pipeline().addLast(new ChannelInboundHandlerAdapter());
}
});
// Start server
Channel sc = sb.bind(addr).syncUninterruptibly().channel();
CountingChannelPoolHandler handler = new CountingChannelPoolHandler();
ChannelPool pool = new FixedChannelPool(cb, handler, 1, Integer.MAX_VALUE);
Channel channel = pool.acquire().syncUninterruptibly().getNow();
Future<Channel> future = pool.acquire();
assertFalse(future.isDone());
pool.release(channel).syncUninterruptibly();
assertTrue(future.await(1, TimeUnit.SECONDS));
Channel channel2 = future.getNow();
assertSame(channel, channel2);
assertEquals(1, handler.channelCount());
assertEquals(2, handler.acquiredCount());
assertEquals(1, handler.releasedCount());
sc.close().syncUninterruptibly();
channel2.close().syncUninterruptibly();
pool.close();
}
use of io.netty.channel.local.LocalAddress in project netty by netty.
the class FixedChannelPoolTest method testAcquireTimeout.
private static void testAcquireTimeout(long timeoutMillis) throws Exception {
LocalAddress addr = new LocalAddress(getLocalAddrId());
Bootstrap cb = new Bootstrap();
cb.remoteAddress(addr);
cb.group(group).channel(LocalChannel.class);
ServerBootstrap sb = new ServerBootstrap();
sb.group(group).channel(LocalServerChannel.class).childHandler(new ChannelInitializer<LocalChannel>() {
@Override
public void initChannel(LocalChannel ch) throws Exception {
ch.pipeline().addLast(new ChannelInboundHandlerAdapter());
}
});
// Start server
Channel sc = sb.bind(addr).syncUninterruptibly().channel();
ChannelPoolHandler handler = new TestChannelPoolHandler();
ChannelPool pool = new FixedChannelPool(cb, handler, ChannelHealthChecker.ACTIVE, AcquireTimeoutAction.FAIL, timeoutMillis, 1, Integer.MAX_VALUE);
Channel channel = pool.acquire().syncUninterruptibly().getNow();
final Future<Channel> future = pool.acquire();
assertThrows(TimeoutException.class, new Executable() {
@Override
public void execute() throws Throwable {
future.syncUninterruptibly();
}
});
sc.close().syncUninterruptibly();
channel.close().syncUninterruptibly();
pool.close();
}
use of io.netty.channel.local.LocalAddress in project netty by netty.
the class ReentrantChannelTest method testWritabilityChanged.
@Test
public void testWritabilityChanged() throws Exception {
LocalAddress addr = new LocalAddress("testWritabilityChanged");
ServerBootstrap sb = getLocalServerBootstrap();
sb.bind(addr).sync().channel();
Bootstrap cb = getLocalClientBootstrap();
setInterest(Event.WRITE, Event.FLUSH, Event.WRITABILITY);
Channel clientChannel = cb.connect(addr).sync().channel();
clientChannel.config().setWriteBufferLowWaterMark(512);
clientChannel.config().setWriteBufferHighWaterMark(1024);
// What is supposed to happen from this point:
//
// 1. Because this write attempt has been made from a non-I/O thread,
// ChannelOutboundBuffer.pendingWriteBytes will be increased before
// write() event is really evaluated.
// -> channelWritabilityChanged() will be triggered,
// because the Channel became unwritable.
//
// 2. The write() event is handled by the pipeline in an I/O thread.
// -> write() will be triggered.
//
// 3. Once the write() event is handled, ChannelOutboundBuffer.pendingWriteBytes
// will be decreased.
// -> channelWritabilityChanged() will be triggered,
// because the Channel became writable again.
//
// 4. The message is added to the ChannelOutboundBuffer and thus
// pendingWriteBytes will be increased again.
// -> channelWritabilityChanged() will be triggered.
//
// 5. The flush() event causes the write request in theChannelOutboundBuffer
// to be removed.
// -> flush() and channelWritabilityChanged() will be triggered.
//
// Note that the channelWritabilityChanged() in the step 4 can occur between
// the flush() and the channelWritabilityChanged() in the step 5, because
// the flush() is invoked from a non-I/O thread while the other are from
// an I/O thread.
ChannelFuture future = clientChannel.write(createTestBuf(2000));
clientChannel.flush();
future.sync();
clientChannel.close().sync();
assertLog(// Case 1:
"WRITABILITY: writable=false\n" + "WRITE\n" + "WRITABILITY: writable=false\n" + "WRITABILITY: writable=false\n" + "FLUSH\n" + "WRITABILITY: writable=true\n", // Case 2:
"WRITABILITY: writable=false\n" + "WRITE\n" + "WRITABILITY: writable=false\n" + "FLUSH\n" + "WRITABILITY: writable=true\n" + "WRITABILITY: writable=true\n");
}
use of io.netty.channel.local.LocalAddress in project netty by netty.
the class FixedChannelPoolMapDeadlockTest method testDeadlockOnAcquire.
@Test
public void testDeadlockOnAcquire() throws Exception {
final EventLoop threadA1 = new DefaultEventLoop();
final Bootstrap bootstrapA1 = new Bootstrap().channel(LocalChannel.class).group(threadA1).localAddress(new LocalAddress("A1"));
final EventLoop threadA2 = new DefaultEventLoop();
final Bootstrap bootstrapA2 = new Bootstrap().channel(LocalChannel.class).group(threadA2).localAddress(new LocalAddress("A2"));
final EventLoop threadB1 = new DefaultEventLoop();
final Bootstrap bootstrapB1 = new Bootstrap().channel(LocalChannel.class).group(threadB1).localAddress(new LocalAddress("B1"));
final EventLoop threadB2 = new DefaultEventLoop();
final Bootstrap bootstrapB2 = new Bootstrap().channel(LocalChannel.class).group(threadB2).localAddress(new LocalAddress("B2"));
final FixedChannelPool poolA1 = new FixedChannelPool(bootstrapA1, NOOP_HANDLER, 1);
final FixedChannelPool poolA2 = new FixedChannelPool(bootstrapB2, NOOP_HANDLER, 1);
final FixedChannelPool poolB1 = new FixedChannelPool(bootstrapB1, NOOP_HANDLER, 1);
final FixedChannelPool poolB2 = new FixedChannelPool(bootstrapA2, NOOP_HANDLER, 1);
// Synchronize threads on these barriers to ensure order of execution, first wait until each thread is inside
// the newPool callback, then hold the two threads that should lose the match until the first two returns, then
// release them to test if they deadlock when trying to release their pools on each other's threads.
final CyclicBarrier arrivalBarrier = new CyclicBarrier(4);
final CyclicBarrier releaseBarrier = new CyclicBarrier(3);
final AbstractChannelPoolMap<String, FixedChannelPool> channelPoolMap = new AbstractChannelPoolMap<String, FixedChannelPool>() {
@Override
protected FixedChannelPool newPool(String key) {
if ("A".equals(key)) {
if (threadA1.inEventLoop()) {
// Thread A1 gets pool A with thread A1
await(arrivalBarrier);
return poolA1;
} else if (threadA2.inEventLoop()) {
// Thread A2 gets pool A with thread B2, but only after A1 won
await(arrivalBarrier);
await(releaseBarrier);
return poolA2;
}
} else if ("B".equals(key)) {
if (threadB1.inEventLoop()) {
// Thread B1 gets pool with thread B1
await(arrivalBarrier);
return poolB1;
} else if (threadB2.inEventLoop()) {
// Thread B2 gets pool with thread A2
await(arrivalBarrier);
await(releaseBarrier);
return poolB2;
}
}
throw new AssertionError("Unexpected key=" + key + " or thread=" + Thread.currentThread().getName());
}
};
// Thread A1 calls ChannelPoolMap.get(A)
// Thread A2 calls ChannelPoolMap.get(A)
// Thread B1 calls ChannelPoolMap.get(B)
// Thread B2 calls ChannelPoolMap.get(B)
Future<FixedChannelPool> futureA1 = threadA1.submit(new Callable<FixedChannelPool>() {
@Override
public FixedChannelPool call() throws Exception {
return channelPoolMap.get("A");
}
});
Future<FixedChannelPool> futureA2 = threadA2.submit(new Callable<FixedChannelPool>() {
@Override
public FixedChannelPool call() throws Exception {
return channelPoolMap.get("A");
}
});
Future<FixedChannelPool> futureB1 = threadB1.submit(new Callable<FixedChannelPool>() {
@Override
public FixedChannelPool call() throws Exception {
return channelPoolMap.get("B");
}
});
Future<FixedChannelPool> futureB2 = threadB2.submit(new Callable<FixedChannelPool>() {
@Override
public FixedChannelPool call() throws Exception {
return channelPoolMap.get("B");
}
});
// These should always succeed and return with new pools
try {
assertSame(poolA1, futureA1.get(1, TimeUnit.SECONDS));
assertSame(poolB1, futureB1.get(1, TimeUnit.SECONDS));
} catch (Exception e) {
shutdown(threadA1, threadA2, threadB1, threadB2);
throw e;
}
// Now release the other two threads which at this point lost the race and will try to clean up the acquired
// pools. The expected scenario is that both pools close, in case of a deadlock they will hang.
await(releaseBarrier);
// If the close is not blocking, then the previously created pools will be returned
try {
assertSame(poolA1, futureA2.get(1, TimeUnit.SECONDS));
assertSame(poolB1, futureB2.get(1, TimeUnit.SECONDS));
} catch (TimeoutException e) {
// Fail the test on timeout to distinguish from other errors
throw new AssertionError(e);
} finally {
poolA1.close();
poolA2.close();
poolB1.close();
poolB2.close();
channelPoolMap.close();
shutdown(threadA1, threadA2, threadB1, threadB2);
}
}
Aggregations