/** * {@inheritDoc} */ @Override public String toString() { final StringBuilder sb = new StringBuilder(); sb.append(getClass().getName()); sb.append("[hasRemaining="); sb.append(hasRemaining()); sb.append(",readIndex="); sb.append(readIndex); sb.append(",writeIndex="); sb.append(writeIndex); sb.append(",capacity="); sb.append(buffers.length); sb.append(",bufSize="); sb.append(bufferSize); sb.append(']'); return sb.toString(); }
/** * Flush the receive queue. * * @throws IOException if something goes wrong. */ private void flushRecvQueue() throws IOException { if (recvQueue == null) { return; } ByteBuffer tmp = recvQueue.newByteBuffer(); while (recvQueue.hasRemaining()) { tmp.clear(); recvQueue.get(tmp); tmp.flip(); ptr.onRecv(tmp); } recvQueue = null; }
/** * {@inheritDoc} */ @Override protected void write(@Nonnull ByteBuffer data) throws IOException { if (LOGGER.isLoggable(Level.FINEST)) { LOGGER.log(Level.FINEST, "[{0}] SEND: {1} bytes", new Object[]{stack().name(), data.remaining()}); } if (!data.hasRemaining()) { return; } if (!out.isOpen()) { throw new ClosedChannelException(); } boolean sendHadRemaining; synchronized (sendQueue) { sendHadRemaining = sendQueue.hasRemaining(); sendQueue.put(data); } if (!sendHadRemaining && out.isOpen() && sendKey != null && sendKey.isValid()) { getIoHub().addInterestWrite(sendKey); } }
/** * {@inheritDoc} */ @Override protected void write(@Nonnull ByteBuffer data) throws IOException { if (LOGGER.isLoggable(Level.FINEST)) { LOGGER.log(Level.FINEST, "[{0}] SEND: {1} bytes", new Object[]{stack().name(), data.remaining()}); } if (!data.hasRemaining()) { // no-op return immediately return; } if (!out.isOpen()) { throw new ClosedChannelException(); } synchronized (writeQueue) { if (!writeQueue.hasRemaining()) { // if the writer is running, it will bail as when it last held the lock it detected a drain // thus we need to start a new writer. The writer will not be able to make progress until we // release the lock, so it's safe to start it as the write queue will be non-empty when we leave // here and any subsequent calls to write() before our submitted writer starts will detect remaining getIoHub().execute(writer); } writeQueue.put(data); } }
/** * {@inheritDoc} */ @Override public final void doSend(@Nonnull ByteBuffer data) throws IOException { ByteBufferQueue sendQueue = this.sendQueue; if (ptr == null) { sendQueue.put(data); } else { if (sendQueue != null && sendQueue.hasRemaining()) { sendQueue.put(data); flushSendQueue(); } else { write(data); } } }
@Test public void putOneByteAndHasRemaining() { ByteBufferQueue queue = new ByteBufferQueue(100); ByteBuffer src = ByteBuffer.allocate(1); src.put((byte) 0); src.flip(); queue.put(src); assertThat(queue.hasRemaining(), is(true)); }
@Test public void putGetDrainsQueue() { ByteBufferQueue queue = new ByteBufferQueue(100); ByteBuffer src = ByteBuffer.allocate(1); src.put((byte) 0); src.flip(); queue.put(src); queue.get(ByteBuffer.allocate(2)); assertThat(queue.hasRemaining(), is(false)); }
/** * SPI: Performed the handling of te actual read from the recipient. * * @param data the data received. Any data consumed from the {@link ByteBuffer} can be assumed as processed. * Any data not consumed from the {@link ByteBuffer} will be the responsibility of the caller * to resubmit in subsequent calls. * @throws IOException if something goes wrong */ protected final void onRead(ByteBuffer data) throws IOException { ByteBufferQueue recvQueue = this.recvQueue; if (ptr == null) { recvQueue.put(data); } else { if (recvQueue != null && recvQueue.hasRemaining()) { recvQueue.put(data); flushRecvQueue(); } else { ptr.onRecv(data); } } }
@Test public void putEmptyBufferAndStillEmpty() { ByteBufferQueue queue = new ByteBufferQueue(100); ByteBuffer src = ByteBuffer.allocate(1); src.flip(); queue.put(src); assertThat(queue.hasRemaining(), is(false)); }
@Test public void putOneByteGetSequences() { ByteBufferQueue queue = new ByteBufferQueue(100); ByteBuffer src = ByteBuffer.allocate(1); for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) { byte b = (byte)i; src.clear(); src.put(b); src.flip(); queue.put(src); assertThat(queue.hasRemaining(), is(true)); } for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) { byte b = (byte) i; assertThat(queue.hasRemaining(), is(true)); assertThat(queue.get(), is(b)); } assertThat(queue.hasRemaining(), is(false)); }
@Test public void putGetOneByteSequences() { ByteBufferQueue queue = new ByteBufferQueue(100); ByteBuffer src = ByteBuffer.allocate(1); for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) { byte b = (byte)i; queue.put(b); assertThat(queue.hasRemaining(), is(true)); } for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) { byte b = (byte) i; assertThat(queue.hasRemaining(), is(true)); src.clear(); queue.get(src); src.flip(); assertThat(src.get(), is(b)); } assertThat(queue.hasRemaining(), is(false)); }
@Test public void putGetByteSequences() { ByteBufferQueue queue = new ByteBufferQueue(100); for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) { byte b = (byte)i; queue.put(b); assertThat(queue.hasRemaining(), is(true)); } for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) { byte b = (byte) i; assertThat(queue.hasRemaining(), is(true)); assertThat(queue.get(), is(b)); } assertThat(queue.hasRemaining(), is(false)); }
public void internalBufferOverflow(int intSize, int srcSize, int dstSize) { ByteBufferQueue queue = new ByteBufferQueue(intSize); ByteBuffer src = ByteBuffer.allocate(srcSize); for (byte v = 0; src.hasRemaining(); v++) { src.put(v); } assertThat("No more room to write", src.hasRemaining(), is(false)); src.flip(); assertThat("We have data to read", src.hasRemaining(), is(true)); assertThat("The queue has no data", queue.hasRemaining(), is(false)); queue.put(src); assertThat("No more data to read", src.hasRemaining(), is(false)); assertThat("The queue has data", queue.hasRemaining(), is(true)); ByteBuffer dst = ByteBuffer.allocate(dstSize); byte v = 0; while (queue.hasRemaining()) { dst.clear(); queue.get(dst); dst.flip(); while (dst.hasRemaining()) { assertThat(dst.get(), is(v++)); } } }
@Test public void putGetByteAndHasRemaining() { ByteBufferQueue queue = new ByteBufferQueue(100); for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) { byte b = (byte)i; queue.put(b); assertThat(queue.hasRemaining(), is(true)); assertThat(queue.get(), is(b)); assertThat(queue.hasRemaining(), is(false)); } }
@Test public void newInstanceIsEmpty() { assertThat(new ByteBufferQueue(100).hasRemaining(), is(false)); }
@Test public void putGetFillsDestLeavingRemaining() { ByteBufferQueue queue = new ByteBufferQueue(100); ByteBuffer src = ByteBuffer.allocate(4); src.put((byte) 0); src.put((byte) 2); src.put((byte) 4); src.put((byte) 8); src.flip(); queue.put(src); ByteBuffer dst = ByteBuffer.allocate(2); queue.get(dst); assertThat(queue.hasRemaining(), is(true)); dst.flip(); assertThat(dst.get(), is((byte) 0)); assertThat(dst.get(), is((byte) 2)); dst.clear(); queue.get(dst); assertThat(queue.hasRemaining(), is(false)); dst.flip(); assertThat(dst.get(), is((byte) 4)); assertThat(dst.get(), is((byte) 8)); }
@Test public void putGetByteArraySequences() { ByteBufferQueue queue = new ByteBufferQueue(100); byte[] dst = new byte[1]; for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) { byte b = (byte)i; queue.put(b); assertThat(queue.hasRemaining(), is(true)); } for (int i = Byte.MIN_VALUE; i <= Byte.MAX_VALUE; i++) { byte b = (byte) i; assertThat(queue.hasRemaining(), is(true)); assertThat(queue.get(dst, 0, 1), is(1)); assertThat(dst[0], is(b)); } assertThat(queue.hasRemaining(), is(false)); }
/** * {@inheritDoc} */ @Override public synchronized void doSend(@Nonnull ByteBuffer data) throws IOException { if (sendProtocol.hasRemaining()) { sendQueue.put(data); next().doSend(sendProtocol); return; } if (next() != null) { if (sendQueue.hasRemaining()) { sendQueue.put(data); flushSend(sendQueue); } else { try { next().doSend(data); } catch (IOException e) { throw e; } } completed(); } }
@Override public void doSend(@NonNull ByteBuffer data) throws IOException { synchronized (holdLock) { if (holding) { synchronized (sendQueue) { sendQueue.put(data); } return; } } synchronized (sendQueue) { if (sendQueue.hasRemaining()) { sendQueue.put(data); ByteBuffer tempBuffer = sendQueue.newByteBuffer(); while (sendQueue.hasRemaining()) { tempBuffer.clear(); sendQueue.get(tempBuffer); next().doSend(tempBuffer); } } else if (data.hasRemaining()) { next().doSend(data); } } }
@Override public void onRecv(@NonNull ByteBuffer data) throws IOException { synchronized (holdLock) { if (holding) { synchronized (recvQueue) { recvQueue.put(data); } return; } } synchronized (recvQueue) { if (recvQueue.hasRemaining()) { recvQueue.put(data); ByteBuffer tempBuffer = recvQueue.newByteBuffer(); while (recvQueue.hasRemaining()) { tempBuffer.clear(); recvQueue.get(tempBuffer); next().onRecv(tempBuffer); } } else if (data.hasRemaining()) { next().onRecv(data); } } }