@Override public void close() { // Due to certain code paths, close may be called in a recursive // fashion. Rather than trying to handle all of the cases, simply keep // track of whether we've been called before and only perform the logic // once. if (!isClosed.compareAndSet(false, true)) return; completeClientRequest(); closeInternal(); }
public synchronized void addClientRequest( ClientRequest<?> clientRequest, long timeoutMs, long elapsedNs) { if (logger.isTraceEnabled()) logger.trace("Associating client with " + socketChannel.socket()); this.clientRequest = clientRequest; computeExpirationTime(timeoutMs, elapsedNs); outputStream.getBuffer().clear(); boolean wasSuccessful = clientRequest.formatRequest(outputStream); outputStream.getBuffer().flip(); if (wasSuccessful) { SelectionKey selectionKey = socketChannel.keyFor(selector); if (selectionKey != null) { selectionKey.interestOps(SelectionKey.OP_WRITE); // This wakeup is required because it's invoked by the calling // code in a different thread than the SelectorManager. selector.wakeup(); } else { if (logger.isDebugEnabled()) logger.debug( "Client associated with " + socketChannel.socket() + " was not registered with Selector " + selector + ", assuming initial protocol negotiation"); } } else { if (logger.isEnabledFor(Level.WARN)) logger.warn( "Client associated with " + socketChannel.socket() + " did not successfully buffer output for request"); completeClientRequest(); } }