}
TCPSelectorHandler createTcpEndpoint(InetSocketAddress addr) {
int linger = -1;
final TCPSelectorHandler selectorHandler = new TCPSelectorHandler() {
/**
* Intercept the accept operations and cache the associated connection.
*/
@Override
public boolean onAcceptInterest(SelectionKey key, Context ctx)
throws IOException {
SelectableChannel channel = acceptWithoutRegistration(key);
if (channel != null) {
configureChannel(channel);
SelectionKey readKey = channel.register(selector,
SelectionKey.OP_READ);
// Cache the connection.
TargetTuple tt = connectionManager.add(readKey, this);
outboundConnectionsTuple.put(readKey, tt);
}
return false;
}
/*
* Need this until the fix is available as part of 1.8.6.x grizzly.
* See issue 491 in Grizzly,
*/
@Override
public void shutdown() {
// If shutdown was called for this SelectorHandler
if (isShutDown.getAndSet(true)) {
return;
}
stateHolder.setState(State.STOPPED);
if (selector != null) {
try {
boolean isContinue = true;
while (isContinue) {
try {
for (SelectionKey selectionKey : selector.keys()) {
selectionKeyHandler.close(selectionKey);
}
isContinue = false;
} catch (ConcurrentModificationException e) {
// ignore
}
}
} catch (ClosedSelectorException e) {
// If Selector is already closed - OK
}
}
try {
if (serverSocket != null) {
serverSocket.close();
}
} catch (Throwable ex) {
logger.log(Level.SEVERE,
"Close server socket", ex);
}
try {
if (serverSocketChannel != null) {
serverSocketChannel.close();
}
} catch (Throwable ex) {
logger.log(Level.SEVERE,
"Close server socket channel", ex);
}
try {
if (selector != null) {
selector.close();
}
} catch (Throwable ex) {
logger.log(Level.SEVERE,
"Close selector", ex);
}
if (asyncQueueReader != null) {
asyncQueueReader.close();
asyncQueueReader = null;
}
if (asyncQueueWriter != null) {
asyncQueueWriter.close();
asyncQueueWriter = null;
}
opToRegister.clear();
attributes = null;
}
@Override
protected void onConnectOp(Context ctx,
SelectionKeyOP.ConnectSelectionKeyOP selectionKeyOp)
throws IOException {
SocketAddress remoteAddress = selectionKeyOp.getRemoteAddress();
SocketAddress localAddress = selectionKeyOp.getLocalAddress();
CallbackHandler callbackHandler =
selectionKeyOp.getCallbackHandler();
SocketChannel socketChannel = SocketChannel.open();
socketChannel.socket().setReuseAddress(reuseAddress);
if (localAddress != null) {
socketChannel.socket().bind(localAddress);
}
socketChannel.configureBlocking(false);
SelectionKey key = socketChannel.register(selector,
SelectionKey.OP_CONNECT);
key.attach(ExpiringCallbackHandlerSelectionKeyAttachment.create(
key, callbackHandler));
boolean isConnected;
try {
isConnected = socketChannel.connect(remoteAddress);
} catch (Exception e) {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE,
"Exception occured when tried to connect socket",
e.getMessage());
}
if (logger.isLoggable(Level.FINEST)) {
logger.log(Level.FINEST,
"Exception occured when tried to connect socket",
e);
}
// set isConnected to true to let callback handler to know about the problem happened
isConnected = true;
}
// if channel was connected immediately or exception occured
if (isConnected) {
onConnectInterest(key, ctx);
}
}
};
selectorHandler.setPort(addr.getPort());
selectorHandler.setInet(addr.getAddress());
selectorHandler.setLinger(linger);
selectorHandler.setLogger(logger);
selectorHandler.setReuseAddress(true);
selectorHandler.setSocketTimeout(keepAliveTimeoutInSeconds * 1000);
return selectorHandler;
}