use of org.apache.bookkeeper.proto.PerChannelBookieClient.ConnectionState in project bookkeeper by apache.
the class TestPerChannelBookieClient method testDisconnectRace.
/**
* Test that all resources are freed if connections and disconnections
* are interleaved randomly.
*
* {@link https://issues.apache.org/jira/browse/BOOKKEEPER-620}
*/
@Test
public void testDisconnectRace() throws Exception {
final GenericCallback<PerChannelBookieClient> nullop = new GenericCallback<PerChannelBookieClient>() {
@Override
public void operationComplete(int rc, PerChannelBookieClient client) {
// do nothing, we don't care about doing anything with the connection,
// we just want to trigger it connecting.
}
};
final int iterations = 100000;
EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
OrderedExecutor executor = getOrderedSafeExecutor();
BookieSocketAddress addr = getBookie(0);
final PerChannelBookieClient client = new PerChannelBookieClient(executor, eventLoopGroup, addr, authProvider, extRegistry);
final AtomicBoolean shouldFail = new AtomicBoolean(false);
final AtomicBoolean running = new AtomicBoolean(true);
final CountDownLatch disconnectRunning = new CountDownLatch(1);
Thread connectThread = new Thread() {
public void run() {
try {
if (!disconnectRunning.await(10, TimeUnit.SECONDS)) {
LOG.error("Disconnect thread never started");
shouldFail.set(true);
}
} catch (InterruptedException ie) {
LOG.error("Connect thread interrupted", ie);
Thread.currentThread().interrupt();
running.set(false);
}
for (int i = 0; i < iterations && running.get(); i++) {
client.connectIfNeededAndDoOp(nullop);
}
running.set(false);
}
};
Thread disconnectThread = new Thread() {
public void run() {
disconnectRunning.countDown();
while (running.get()) {
client.disconnect();
}
}
};
Thread checkThread = new Thread() {
public void run() {
ConnectionState state;
Channel channel;
while (running.get()) {
synchronized (client) {
state = client.state;
channel = client.channel;
if ((state == ConnectionState.CONNECTED && (channel == null || !channel.isActive())) || (state != ConnectionState.CONNECTED && channel != null && channel.isActive())) {
LOG.error("State({}) and channel({}) inconsistent " + channel, state, channel == null ? null : channel.isActive());
shouldFail.set(true);
running.set(false);
}
}
}
}
};
connectThread.start();
disconnectThread.start();
checkThread.start();
connectThread.join();
disconnectThread.join();
checkThread.join();
assertFalse("Failure in threads, check logs", shouldFail.get());
client.close();
eventLoopGroup.shutdownGracefully();
executor.shutdown();
}
Aggregations