@Override protected void write(SelectionKey selectionKey) throws IOException { if (!checkTimeout()) return; if (outputStream.getBuffer().hasRemaining()) { // If we have data, write what we can now... int count = socketChannel.write(outputStream.getBuffer()); if (logger.isTraceEnabled()) logger.trace( "Wrote " + count + " bytes, remaining: " + outputStream.getBuffer().remaining() + " for " + socketChannel.socket()); } else { if (logger.isTraceEnabled()) logger.trace("Wrote no bytes for " + socketChannel.socket()); } // If there's more to write but we didn't write it, we'll take that to // mean that we're done here. We don't clear or reset anything. We leave // our buffer state where it is and try our luck next time. if (outputStream.getBuffer().hasRemaining()) return; resetStreams(); // If we're not streaming writes, signal the Selector that we're // ready to read the next request. selectionKey.interestOps(SelectionKey.OP_READ); }
@Override protected void read(SelectionKey selectionKey) throws IOException { if (!checkTimeout()) return; int count = 0; if ((count = socketChannel.read(inputStream.getBuffer())) == -1) throw new EOFException("EOF for " + socketChannel.socket()); if (logger.isTraceEnabled()) traceInputBufferState("Read " + count + " bytes"); if (count == 0) return; // Take note of the position after we read the bytes. We'll need it in // case of incomplete reads later on down the method. final int position = inputStream.getBuffer().position(); // Flip the buffer, set our limit to the current position and then set // the position to 0 in preparation for reading in the RequestHandler. inputStream.getBuffer().flip(); // uses a local variable to point to request to prevent racing condition // when atomicNullOutClientRequest() is called by another thread ClientRequest<?> request = clientRequest; if (request != null) { if (!request.isCompleteResponse(inputStream.getBuffer())) { // Ouch - we're missing some data for a full request, so handle // that and return. handleIncompleteRequest(position); return; } // At this point we have the full request (and it's not streaming), // so rewind the buffer for reading and execute the request. inputStream.getBuffer().rewind(); if (logger.isTraceEnabled()) logger.trace("Starting read for " + socketChannel.socket()); request.parseResponse(new DataInputStream(inputStream)); // At this point we've completed a full stand-alone request. So // clear our input buffer and prepare for outputting back to the // client. if (logger.isTraceEnabled()) logger.trace("Finished read for " + socketChannel.socket()); resetStreams(); selectionKey.interestOps(0); } ClientRequest<?> originalRequest = completeClientRequest(); if (originalRequest == null && logger.isEnabledFor(Level.WARN)) logger.warn("No client associated with " + socketChannel.socket()); }