/** * @param bytebuffer ByteBuffer * @param flip boolean * @return int * @throws IOException TODO Fix non blocking write properly */ private synchronized int writeToSocket(ByteBuffer bytebuffer, boolean block, boolean flip) throws IOException { if (flip) bytebuffer.flip(); int written = 0; NioEndpoint.KeyAttachment att = (NioEndpoint.KeyAttachment) socket.getAttachment(false); if (att == null) throw new IOException("Key must be cancelled"); long writeTimeout = att.getTimeout(); Selector selector = null; try { selector = pool.get(); } catch (IOException x) { // ignore } try { written = pool.write(bytebuffer, socket, selector, writeTimeout, block, lastWrite); // make sure we are flushed do { if (socket.flush(true, selector, writeTimeout, lastWrite)) break; } while (true); } finally { if (selector != null) pool.put(selector); } if (block) bytebuffer.clear(); // only clear return written; }
/** * Read a sequence of bytes in non-blocking mode from he current channel * * @param bb the byte buffer which will contain the bytes read from the current channel */ private void nonBlockingRead(final ByteBuffer bb, long timeout, TimeUnit unit) { final NioChannel ch = this.channel; try { ch.read(bb, ch, this.completionHandler); } catch (Throwable t) { if (log.isDebugEnabled()) { log.debug("An error occurs when trying a non-blocking read ", t); } } }
/** Send an acknowledgment. */ @Override public void sendAck() throws IOException { if (!committed) { // Socket.send(socket, Constants.ACK_BYTES, 0, Constants.ACK_BYTES.length) < 0 socket .getBufHandler() .getWriteBuffer() .put(Constants.ACK_BYTES, 0, Constants.ACK_BYTES.length); writeToSocket(socket.getBufHandler().getWriteBuffer(), true, true); } }
/** Callback to write data from the buffer. */ private void flushBuffer() throws IOException { // prevent timeout for async, SelectionKey key = socket.getIOChannel().keyFor(socket.getPoller().getSelector()); if (key != null) { NioEndpoint.KeyAttachment attach = (NioEndpoint.KeyAttachment) key.attachment(); attach.access(); } // write to the socket, if there is anything to write if (socket.getBufHandler().getWriteBuffer().position() > 0) { socket.getBufHandler().getWriteBuffer().flip(); writeToSocket(socket.getBufHandler().getWriteBuffer(), true, false); } }
/** Recycle the output buffer. This should be called when closing the connection. */ @Override public void recycle() { super.recycle(); if (socket != null) { socket.getBufHandler().getWriteBuffer().clear(); socket = null; } lastWrite.set(1); }
private synchronized void addToBB(byte[] buf, int offset, int length) throws IOException { while (length > 0) { int thisTime = length; if (socket.getBufHandler().getWriteBuffer().position() == socket.getBufHandler().getWriteBuffer().capacity() || socket.getBufHandler().getWriteBuffer().remaining() == 0) { flushBuffer(); } if (thisTime > socket.getBufHandler().getWriteBuffer().remaining()) { thisTime = socket.getBufHandler().getWriteBuffer().remaining(); } socket.getBufHandler().getWriteBuffer().put(buf, offset, thisTime); length = length - thisTime; offset = offset + thisTime; } NioEndpoint.KeyAttachment ka = (NioEndpoint.KeyAttachment) socket.getAttachment(false); if (ka != null) ka.access(); // prevent timeouts for just doing client writes }