package org.infinispan.client.hotrod.impl.protocol; import java.io.IOException; import java.io.InputStream; import org.infinispan.client.hotrod.VersionedMetadata; import org.infinispan.client.hotrod.impl.transport.Transport; import org.infinispan.client.hotrod.impl.transport.tcp.TcpTransport; import net.jcip.annotations.NotThreadSafe; /** * Implements an {@link InputStream} around a {@link Transport}. * The transport is marked as <b>busy</b> so that it won't be released automatically * * @author Tristan Tarrant * @since 9.0 */ @NotThreadSafe class TransportInputStream extends InputStream implements VersionedMetadata { private final Transport transport; private final int totalLength; private final Runnable afterClose; private final VersionedMetadata versionedMetadata; private int totalPosition; private byte[] buffer; private int bufferPosition; private int bufferLimit; TransportInputStream(Transport transport, VersionedMetadata versionedMetadata, Runnable afterClose) { this.transport = transport; totalLength = transport.readVInt(); buffer = new byte[TcpTransport.SOCKET_STREAM_BUFFER]; this.versionedMetadata = versionedMetadata; this.afterClose = afterClose; } @Override public long getVersion() { return versionedMetadata.getVersion(); } @Override public long getCreated() { return versionedMetadata.getCreated(); } @Override public int getLifespan() { return versionedMetadata.getLifespan(); } @Override public long getLastUsed() { return versionedMetadata.getLastUsed(); } @Override public int getMaxIdle() { return versionedMetadata.getMaxIdle(); } private void fill() { bufferLimit = Math.min(TcpTransport.SOCKET_STREAM_BUFFER, totalLength - totalPosition); if (bufferLimit > 0) { transport.readByteArray(buffer, bufferLimit); totalPosition += bufferLimit; } bufferPosition = 0; } @Override public int read() throws IOException { if (bufferPosition >= bufferLimit) { fill(); if (bufferPosition >= bufferLimit) return -1; } return buffer[bufferPosition++] & 0xff; } private int read1(byte[] b, int off, int len) { int available = bufferLimit - bufferPosition; if (available <= 0) { fill(); available = bufferLimit - bufferPosition; if (available <= 0) return -1; } int amount = (available < len) ? available : len; System.arraycopy(buffer, bufferPosition, b, off, amount); bufferPosition += amount; return amount; } @Override public synchronized int read(byte b[], int off, int len) throws IOException { if ((off | len | (off + len) | (b.length - (off + len))) < 0) { throw new IndexOutOfBoundsException(); } else if (len == 0) { return 0; } int n = 0; for (;;) { int nread = read1(b, off + n, len - n); if (nread <= 0) return (n == 0) ? nread : n; n += nread; if (n >= len) return n; } } @Override public void close() throws IOException { super.close(); if (afterClose != null) { afterClose.run(); } } }