/** * {@inheritDoc} */ @Override public int read() throws IOException { return pos++ >= length ? -1 : (queue.get() & 0xff); }
/** * {@inheritDoc} */ @Override public int read(byte[] b, int off, int len) throws IOException { int rem = length - pos; if (rem <= 0) { return -1; } int read = queue.get(b, off, len > rem ? rem : len); if (read <= 0) { return -1; } pos += read; return read; }
/** * {@inheritDoc} */ @Override public int read(byte[] b, int off, int len) throws IOException { if (length != -1) { int rem = length - pos; if (rem <= 0) { return -1; } else if (len > rem) { len = rem; } } int read = queue.get(b, off, len); if (read <= 0) { return -1; } pos += read; if (mark != null) { if (mark.remaining() > read) { mark.put(b, off, read); } else { // mark was invalidated as there was more data than reserved mark = null; } } return read; }
/** * {@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; }
/** * 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; }
private String read(ByteBufferQueue queue) { ByteBuffer buf = ByteBuffer.allocate((int) queue.remaining()); queue.get(buf); buf.flip(); StringBuilder r = new StringBuilder(buf.remaining()); while (buf.hasRemaining()) { r.append((char) buf.get()); } return r.toString(); }
/** * 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; }
/** * Flushes the supplied {@link ByteBufferQueue} to {@link #next()}'s {@link ProtocolStack.Ptr#doSend(ByteBuffer)} * This method is especially helpful for {@link FilterLayer} implementations that are involved in initial * handshaking as they will need to queue up data until the handshake is completed and then flush the data to * the remainder of the stack. * * @param queue the data to send. * @throws IOException if there is an I/O error during the receive. */ protected final void flushSend(ByteBufferQueue queue) throws IOException { ProtocolStack<?>.Ptr ptr; synchronized (this) { ptr = this.ptr; } if (ptr == null) { throw new IllegalStateException(); } ByteBuffer tmp = queue.newByteBuffer(); while (queue.hasRemaining()) { tmp.clear(); queue.get(tmp); tmp.flip(); try { ptr.doSend(tmp); } catch (IOException e) { queue.unget(tmp); throw e; } } }
/** * Flushes the supplied {@link ByteBufferQueue} to {@link #next()}'s {@link ProtocolStack.Ptr#onRecv(ByteBuffer)}. * This method is especially helpful for {@link FilterLayer} implementations that are involved in initial * handshaking as they will need to queue up data until the handshake is completed and then flush the data to * the remainder of the stack. * * @param queue the data to receive. * @throws IOException if there is an I/O error during the receive. */ protected final void flushRecv(ByteBufferQueue queue) throws IOException { ProtocolStack<?>.Ptr ptr; synchronized (this) { ptr = this.ptr; } if (ptr == null) { throw new IllegalStateException(); } ByteBuffer tmp = queue.newByteBuffer(); while (queue.hasRemaining()) { tmp.clear(); queue.get(tmp); tmp.flip(); try { ptr.onRecv(tmp); } catch (IOException e) { queue.unget(tmp); throw e; } } }
/** * {@inheritDoc} */ @Override public final void write(Command cmd, boolean last) throws IOException { ByteBufferQueueOutputStream bqos = new ByteBufferQueueOutputStream(sendStaging); ObjectOutputStream oos = AnonymousClassWarnings.checkingObjectOutputStream(bqos); try { cmd.writeTo(channel, oos); } finally { oos.close(); } long remaining = sendStaging.remaining(); channel.notifyWrite(cmd, remaining); while (remaining > 0L) { int frame = remaining > transportFrameSize ? transportFrameSize : (int) remaining; // # of bytes we send in this chunk writeChunkHeader.clear(); ChunkHeader.write(writeChunkHeader, frame, remaining > transportFrameSize); writeChunkHeader.flip(); writeChunkBody.clear(); writeChunkBody.limit(frame); sendStaging.get(writeChunkBody); writeChunkBody.flip(); write(writeChunkHeader, writeChunkBody); remaining -= frame; } }
@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 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)); }
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 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 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 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)); }
@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)); }
@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); } } }