/** * SPI: Creates a new {@link ByteBuffer} optimally sized for network read/write operations. * * @return a new {@link ByteBuffer} optimally sized for network read/write operations. */ protected ByteBufferQueue newByteBufferQueue() { return new ByteBufferQueue(CAPACITY); }
/** * Flush the send queue. * * @throws IOException if something goes wrong. */ private void flushSendQueue() throws IOException { if (sendQueue == null) { return; } ByteBuffer tmp = sendQueue.newByteBuffer(); while (sendQueue.hasRemaining()) { tmp.clear(); sendQueue.get(tmp); tmp.flip(); while (tmp.hasRemaining()) { try { write(tmp); } catch (IOException e) { // store what ever we know was not written tmp.compact(); sendQueue.unget(tmp); throw e; } } } sendQueue = null; }
/** * {@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); } } }
/** * 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; }
@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)); }
@Test public void readLimit() throws Exception { String str = "AbCdEfGhIjKlMnOpQrStUvWxYz"; ByteBufferQueue queue = new ByteBufferQueue(10); queue.put(ByteBuffer.wrap(str.getBytes(StandardCharsets.UTF_8))); ByteBufferQueueInputStream instance = new ByteBufferQueueInputStream(queue, 10); assertThat(read(instance, 10), is("AbCdEfGhIj")); }
@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); } } }
@Test public void putEmptyBufferAndStillEmpty() { ByteBufferQueue queue = new ByteBufferQueue(100); ByteBuffer src = ByteBuffer.allocate(1); src.flip(); queue.put(src); assertThat(queue.hasRemaining(), is(false)); }
boolean sendHasRemaining; synchronized (sendQueue) { sendQueue.get(send); sendHasRemaining = sendQueue.hasRemaining(); if (send.hasRemaining()) { synchronized (sendQueue) { this.sendQueue.unget(send); sendHasRemaining = true;
@Test public void newInstanceIsEmpty() { assertThat(new ByteBufferQueue(100).hasRemaining(), is(false)); }
data.clear(); synchronized (writeQueue) { writeQueue.get(data); done = !writeQueue.hasRemaining();
/** * {@inheritDoc} */ @Override public void write(byte[] b, int off, int len) throws IOException { queue.put(b, off, len); } }
/** * {@inheritDoc} */ @Override public int read() throws IOException { return pos++ >= length ? -1 : (queue.get() & 0xff); }
compact(); if (writeIndex + 1 >= buffers.length) { buffers[writeIndex] = newByteBuffer(); } else { buffers[writeIndex].clear();
/** * {@inheritDoc} */ @Override public long skip(long n) throws IOException { if (mark == null || mark.remaining() < n) { mark = null; if (length != -1) { if (pos >= length) { return -1; } if (pos + n >= length) { n = length - pos; } } long skipped = queue.skip(n); pos += skipped; return skipped; } int l = mark.limit(); int p = mark.position(); mark.limit(mark.position() + (int)n); queue.get(mark); int skipped = mark.position() - p; mark.limit(l); return skipped; }
/** * {@inheritDoc} */ @Override public void onRegistered(SelectionKey selectionKey) { if (setRecvKey) { recvKey = selectionKey; } if (setSendKey) { sendLock.lock(); try { sendKey = selectionKey; // check if some outgoing data has been buffered while we were waiting to register if (!pendingWrite) { boolean nowPendingWrite; synchronized (sendQueue) { nowPendingWrite = sendQueue.hasRemaining(); } if (nowPendingWrite) { sendKey.interestOps(sendKey.interestOps() | SelectionKey.OP_WRITE); } } } finally { sendLock.unlock(); } } }
/** * {@inheritDoc} */ @Override public int available() throws IOException { if (length == -1) { long remaining = queue.remaining(); return remaining > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) remaining; } else { return pos >= length ? -1 : length - pos; } }
/** * {@inheritDoc} */ @Override public synchronized void reset() throws IOException { if (mark == null) { throw new IOException(); } mark.flip(); pos -= mark.remaining(); queue.unget(mark); mark.clear(); }
int limit = src.limit(); src.limit(src.position() + bufferSize); inject[injectIndex++] = newByteBuffer().put(src); src.limit(limit); } else { inject[injectIndex++] = newByteBuffer().put(src);