Add methods with position independent FileChannel calls to ByteBuf

Motivation

See ##3229

Modifications:

Add methods with position independent FileChannel calls to ByteBuf and its subclasses.

Results:

The user can use these new methods to read/write ByteBuff without updating FileChannel's position.
This commit is contained in:
Xiaoyan Lin 2016-02-04 19:02:40 -08:00 committed by Norman Maurer
parent b112673554
commit ccb0870600
19 changed files with 652 additions and 3 deletions

View File

@ -29,6 +29,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
import java.nio.charset.Charset;
@ -856,6 +857,15 @@ public abstract class AbstractByteBuf extends ByteBuf {
return readBytes;
}
@Override
public int readBytes(FileChannel out, long position, int length)
throws IOException {
checkReadableBytes(length);
int readBytes = getBytes(readerIndex, out, position, length);
readerIndex += readBytes;
return readBytes;
}
@Override
public ByteBuf readBytes(OutputStream out, int length) throws IOException {
checkReadableBytes(length);
@ -1049,6 +1059,17 @@ public abstract class AbstractByteBuf extends ByteBuf {
return writtenBytes;
}
@Override
public int writeBytes(FileChannel in, long position, int length) throws IOException {
ensureAccessible();
ensureWritable(length);
int writtenBytes = setBytes(writerIndex, in, position, length);
if (writtenBytes > 0) {
writerIndex += writtenBytes;
}
return writtenBytes;
}
@Override
public ByteBuf writeZero(int length) {
if (length == 0) {

View File

@ -23,6 +23,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
import java.nio.charset.Charset;
@ -880,6 +881,26 @@ public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> {
*/
public abstract int getBytes(int index, GatheringByteChannel out, int length) throws IOException;
/**
* Transfers this buffer's data starting at the specified absolute {@code index}
* to the specified channel starting at the given file position.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer. This method does not modify the channel's position.
*
* @param position the file position at which the transfer is to begin
* @param length the maximum number of bytes to transfer
*
* @return the actual number of bytes written out to the specified channel
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* if {@code index + length} is greater than
* {@code this.capacity}
* @throws IOException
* if the specified channel threw an exception during I/O
*/
public abstract int getBytes(int index, FileChannel out, long position, int length) throws IOException;
/**
* Sets the specified boolean at the specified absolute {@code index} in this
* buffer.
@ -1178,7 +1199,27 @@ public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> {
* @throws IOException
* if the specified channel threw an exception during I/O
*/
public abstract int setBytes(int index, ScatteringByteChannel in, int length) throws IOException;
public abstract int setBytes(int index, ScatteringByteChannel in, int length) throws IOException;
/**
* Transfers the content of the specified source channel starting at the given file position
* to this buffer starting at the specified absolute {@code index}.
* This method does not modify {@code readerIndex} or {@code writerIndex} of
* this buffer. This method does not modify the channel's position.
*
* @param position the file position at which the transfer is to begin
* @param length the maximum number of bytes to transfer
*
* @return the actual number of bytes read in from the specified channel.
* {@code -1} if the specified channel is closed.
*
* @throws IndexOutOfBoundsException
* if the specified {@code index} is less than {@code 0} or
* if {@code index + length} is greater than {@code this.capacity}
* @throws IOException
* if the specified channel threw an exception during I/O
*/
public abstract int setBytes(int index, FileChannel in, long position, int length) throws IOException;
/**
* Fills this buffer with <tt>NUL (0x00)</tt> starting at the specified
@ -1524,7 +1565,24 @@ public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> {
* @throws IOException
* if the specified channel threw an exception during I/O
*/
public abstract int readBytes(GatheringByteChannel out, int length) throws IOException;
public abstract int readBytes(GatheringByteChannel out, int length) throws IOException;
/**
* Transfers this buffer's data starting at the current {@code readerIndex}
* to the specified channel starting at the given file position.
* This method does not modify the channel's position.
*
* @param position the file position at which the transfer is to begin
* @param length the maximum number of bytes to transfer
*
* @return the actual number of bytes written out to the specified channel
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.readableBytes}
* @throws IOException
* if the specified channel threw an exception during I/O
*/
public abstract int readBytes(FileChannel out, long position, int length) throws IOException;
/**
* Increases the current {@code readerIndex} by the specified
@ -1783,7 +1841,25 @@ public abstract class ByteBuf implements ReferenceCounted, Comparable<ByteBuf> {
* @throws IOException
* if the specified channel threw an exception during I/O
*/
public abstract int writeBytes(ScatteringByteChannel in, int length) throws IOException;
public abstract int writeBytes(ScatteringByteChannel in, int length) throws IOException;
/**
* Transfers the content of the specified channel starting at the given file position
* to this buffer starting at the current {@code writerIndex} and increases the
* {@code writerIndex} by the number of the transferred bytes.
* This method does not modify the channel's position.
*
* @param position the file position at which the transfer is to begin
* @param length the maximum number of bytes to transfer
*
* @return the actual number of bytes read in from the specified channel
*
* @throws IndexOutOfBoundsException
* if {@code length} is greater than {@code this.writableBytes}
* @throws IOException
* if the specified channel threw an exception during I/O
*/
public abstract int writeBytes(FileChannel in, long position, int length) throws IOException;
/**
* Fills this buffer with <tt>NUL (0x00)</tt> starting at the current

View File

@ -22,6 +22,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
import java.util.ArrayList;
@ -877,6 +878,24 @@ public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements
}
}
@Override
public int getBytes(int index, FileChannel out, long position, int length)
throws IOException {
int count = nioBufferCount();
if (count == 1) {
return out.write(internalNioBuffer(index, length), position);
} else {
long writtenBytes = 0;
for (ByteBuffer buf : nioBuffers(index, length)) {
writtenBytes += out.write(buf, position + writtenBytes);
}
if (writtenBytes > Integer.MAX_VALUE) {
return Integer.MAX_VALUE;
}
return (int) writtenBytes;
}
}
@Override
public CompositeByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
checkIndex(index, length);
@ -1130,6 +1149,11 @@ public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements
ByteBuf s = c.buf;
int adjustment = c.offset;
int localLength = Math.min(length, s.capacity() - (index - adjustment));
if (localLength == 0) {
// Skip empty buffer
i++;
continue;
}
int localReadBytes = s.setBytes(index - adjustment, in, localLength);
if (localReadBytes < 0) {
if (readBytes == 0) {
@ -1168,6 +1192,11 @@ public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements
ByteBuf s = c.buf;
int adjustment = c.offset;
int localLength = Math.min(length, s.capacity() - (index - adjustment));
if (localLength == 0) {
// Skip empty buffer
i++;
continue;
}
int localReadBytes = s.setBytes(index - adjustment, in, localLength);
if (localReadBytes == 0) {
@ -1197,6 +1226,54 @@ public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements
return readBytes;
}
@Override
public int setBytes(int index, FileChannel in, long position, int length) throws IOException {
checkIndex(index, length);
if (length == 0) {
return in.read(EMPTY_NIO_BUFFER, position);
}
int i = toComponentIndex(index);
int readBytes = 0;
do {
Component c = components.get(i);
ByteBuf s = c.buf;
int adjustment = c.offset;
int localLength = Math.min(length, s.capacity() - (index - adjustment));
if (localLength == 0) {
// Skip empty buffer
i++;
continue;
}
int localReadBytes = s.setBytes(index - adjustment, in, position + readBytes, localLength);
if (localReadBytes == 0) {
break;
}
if (localReadBytes < 0) {
if (readBytes == 0) {
return -1;
} else {
break;
}
}
if (localReadBytes == localLength) {
index += localLength;
length -= localLength;
readBytes += localLength;
i ++;
} else {
index += localReadBytes;
length -= localReadBytes;
readBytes += localReadBytes;
}
} while (length > 0);
return readBytes;
}
@Override
public ByteBuf copy(int index, int length) {
checkIndex(index, length);

View File

@ -22,6 +22,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
@ -309,6 +310,12 @@ public class DuplicatedByteBuf extends AbstractDerivedByteBuf {
return buffer.getBytes(index, out, length);
}
@Override
public int getBytes(int index, FileChannel out, long position, int length)
throws IOException {
return buffer.getBytes(index, out, position, length);
}
@Override
public int setBytes(int index, InputStream in, int length)
throws IOException {
@ -321,6 +328,12 @@ public class DuplicatedByteBuf extends AbstractDerivedByteBuf {
return buffer.setBytes(index, in, length);
}
@Override
public int setBytes(int index, FileChannel in, long position, int length)
throws IOException {
return buffer.setBytes(index, in, position, length);
}
@Override
public int nioBufferCount() {
return buffer.nioBufferCount();

View File

@ -26,6 +26,7 @@ import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ReadOnlyBufferException;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
import java.nio.charset.Charset;
@ -374,6 +375,12 @@ public final class EmptyByteBuf extends ByteBuf {
return 0;
}
@Override
public int getBytes(int index, FileChannel out, long position, int length) {
checkIndex(index, length);
return 0;
}
@Override
public ByteBuf setBoolean(int index, boolean value) {
throw new IndexOutOfBoundsException();
@ -481,6 +488,12 @@ public final class EmptyByteBuf extends ByteBuf {
return 0;
}
@Override
public int setBytes(int index, FileChannel in, long position, int length) {
checkIndex(index, length);
return 0;
}
@Override
public ByteBuf setZero(int index, int length) {
return checkIndex(index, length);
@ -637,6 +650,12 @@ public final class EmptyByteBuf extends ByteBuf {
return 0;
}
@Override
public int readBytes(FileChannel out, long position, int length) {
checkLength(length);
return 0;
}
@Override
public ByteBuf skipBytes(int length) {
return checkLength(length);
@ -749,6 +768,12 @@ public final class EmptyByteBuf extends ByteBuf {
return 0;
}
@Override
public int writeBytes(FileChannel in, long position, int length) {
checkLength(length);
return 0;
}
@Override
public ByteBuf writeZero(int length) {
return checkLength(length);

View File

@ -24,6 +24,7 @@ import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ReadOnlyBufferException;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
import java.util.Collections;
@ -187,6 +188,11 @@ final class FixedCompositeByteBuf extends AbstractReferenceCountedByteBuf {
throw new ReadOnlyBufferException();
}
@Override
public int setBytes(int index, FileChannel in, long position, int length) {
throw new ReadOnlyBufferException();
}
@Override
public int capacity() {
return capacity;
@ -470,6 +476,25 @@ final class FixedCompositeByteBuf extends AbstractReferenceCountedByteBuf {
}
}
@Override
public int getBytes(int index, FileChannel out, long position, int length)
throws IOException {
int count = nioBufferCount();
if (count == 1) {
return out.write(internalNioBuffer(index, length), position);
} else {
long writtenBytes = 0;
for (ByteBuffer buf : nioBuffers(index, length)) {
writtenBytes += out.write(buf, position + writtenBytes);
}
if (writtenBytes > Integer.MAX_VALUE) {
return Integer.MAX_VALUE;
} else {
return (int) writtenBytes;
}
}
}
@Override
public ByteBuf getBytes(int index, OutputStream out, int length) throws IOException {
checkIndex(index, length);

View File

@ -23,6 +23,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
@ -233,6 +234,23 @@ final class PooledDirectByteBuf extends PooledByteBuf<ByteBuffer> {
return out.write(tmpBuf);
}
@Override
public int getBytes(int index, FileChannel out, long position, int length) throws IOException {
return getBytes(index, out, position, length, false);
}
private int getBytes(int index, FileChannel out, long position, int length, boolean internal) throws IOException {
checkIndex(index, length);
if (length == 0) {
return 0;
}
ByteBuffer tmpBuf = internal ? internalNioBuffer() : memory.duplicate();
index = idx(index);
tmpBuf.clear().position(index).limit(index + length);
return out.write(tmpBuf, position);
}
@Override
public int readBytes(GatheringByteChannel out, int length) throws IOException {
checkReadableBytes(length);
@ -241,6 +259,14 @@ final class PooledDirectByteBuf extends PooledByteBuf<ByteBuffer> {
return readBytes;
}
@Override
public int readBytes(FileChannel out, long position, int length) throws IOException {
checkReadableBytes(length);
int readBytes = getBytes(readerIndex, out, position, length, true);
readerIndex += readBytes;
return readBytes;
}
@Override
protected void _setByte(int index, int value) {
memory.put(idx(index), (byte) value);
@ -360,6 +386,19 @@ final class PooledDirectByteBuf extends PooledByteBuf<ByteBuffer> {
}
}
@Override
public int setBytes(int index, FileChannel in, long position, int length) throws IOException {
checkIndex(index, length);
ByteBuffer tmpBuf = internalNioBuffer();
index = idx(index);
tmpBuf.clear().position(index).limit(index + length);
try {
return in.read(tmpBuf, position);
} catch (ClosedChannelException ignored) {
return -1;
}
}
@Override
public ByteBuf copy(int index, int length) {
checkIndex(index, length);

View File

@ -22,6 +22,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
@ -145,6 +146,18 @@ class PooledHeapByteBuf extends PooledByteBuf<byte[]> {
return out.write((ByteBuffer) tmpBuf.clear().position(index).limit(index + length));
}
@Override
public final int getBytes(int index, FileChannel out, long position, int length) throws IOException {
return getBytes(index, out, position, length, false);
}
private int getBytes(int index, FileChannel out, long position, int length, boolean internal) throws IOException {
checkIndex(index, length);
index = idx(index);
ByteBuffer tmpBuf = internal ? internalNioBuffer() : ByteBuffer.wrap(memory);
return out.write((ByteBuffer) tmpBuf.clear().position(index).limit(index + length), position);
}
@Override
public final int readBytes(GatheringByteChannel out, int length) throws IOException {
checkReadableBytes(length);
@ -153,6 +166,14 @@ class PooledHeapByteBuf extends PooledByteBuf<byte[]> {
return readBytes;
}
@Override
public final int readBytes(FileChannel out, long position, int length) throws IOException {
checkReadableBytes(length);
int readBytes = getBytes(readerIndex, out, position, length, true);
readerIndex += readBytes;
return readBytes;
}
@Override
protected void _setByte(int index, int value) {
HeapByteBufUtil.setByte(memory, idx(index), value);
@ -243,6 +264,17 @@ class PooledHeapByteBuf extends PooledByteBuf<byte[]> {
}
}
@Override
public final int setBytes(int index, FileChannel in, long position, int length) throws IOException {
checkIndex(index, length);
index = idx(index);
try {
return in.read((ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length), position);
} catch (ClosedChannelException ignored) {
return -1;
}
}
@Override
public final ByteBuf copy(int index, int length) {
checkIndex(index, length);

View File

@ -24,6 +24,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
@ -174,6 +175,23 @@ final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
return out.write(tmpBuf);
}
@Override
public int getBytes(int index, FileChannel out, long position, int length) throws IOException {
return getBytes(index, out, position, length, false);
}
private int getBytes(int index, FileChannel out, long position, int length, boolean internal) throws IOException {
checkIndex(index, length);
if (length == 0) {
return 0;
}
ByteBuffer tmpBuf = internal ? internalNioBuffer() : memory.duplicate();
index = idx(index);
tmpBuf.clear().position(index).limit(index + length);
return out.write(tmpBuf, position);
}
@Override
public int readBytes(GatheringByteChannel out, int length)
throws IOException {
@ -183,6 +201,15 @@ final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
return readBytes;
}
@Override
public int readBytes(FileChannel out, long position, int length)
throws IOException {
checkReadableBytes(length);
int readBytes = getBytes(readerIndex, out, position, length, true);
readerIndex += readBytes;
return readBytes;
}
@Override
protected void _setByte(int index, int value) {
UnsafeByteBufUtil.setByte(addr(index), (byte) value);
@ -264,6 +291,19 @@ final class PooledUnsafeDirectByteBuf extends PooledByteBuf<ByteBuffer> {
}
}
@Override
public int setBytes(int index, FileChannel in, long position, int length) throws IOException {
checkIndex(index, length);
ByteBuffer tmpBuf = internalNioBuffer();
index = idx(index);
tmpBuf.clear().position(index).limit(index + length);
try {
return in.read(tmpBuf, position);
} catch (ClosedChannelException ignored) {
return -1;
}
}
@Override
public ByteBuf copy(int index, int length) {
return UnsafeByteBufUtil.copy(this, addr(index), index, length);

View File

@ -23,6 +23,7 @@ import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ReadOnlyBufferException;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
@ -201,12 +202,23 @@ public class ReadOnlyByteBuf extends AbstractDerivedByteBuf {
throw new ReadOnlyBufferException();
}
@Override
public int setBytes(int index, FileChannel in, long position, int length) {
throw new ReadOnlyBufferException();
}
@Override
public int getBytes(int index, GatheringByteChannel out, int length)
throws IOException {
return buffer.getBytes(index, out, length);
}
@Override
public int getBytes(int index, FileChannel out, long position, int length)
throws IOException {
return buffer.getBytes(index, out, position, length);
}
@Override
public ByteBuf getBytes(int index, OutputStream out, int length)
throws IOException {

View File

@ -23,6 +23,7 @@ import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.ReadOnlyBufferException;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
@ -281,6 +282,18 @@ class ReadOnlyByteBufferBuf extends AbstractReferenceCountedByteBuf {
return out.write(tmpBuf);
}
@Override
public int getBytes(int index, FileChannel out, long position, int length) throws IOException {
ensureAccessible();
if (length == 0) {
return 0;
}
ByteBuffer tmpBuf = internalNioBuffer();
tmpBuf.clear().position(index).limit(index + length);
return out.write(tmpBuf, position);
}
@Override
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
throw new ReadOnlyBufferException();
@ -306,6 +319,11 @@ class ReadOnlyByteBufferBuf extends AbstractReferenceCountedByteBuf {
throw new ReadOnlyBufferException();
}
@Override
public int setBytes(int index, FileChannel in, long position, int length) throws IOException {
throw new ReadOnlyBufferException();
}
protected final ByteBuffer internalNioBuffer() {
ByteBuffer tmpNioBuf = this.tmpNioBuf;
if (tmpNioBuf == null) {

View File

@ -22,6 +22,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
@ -278,6 +279,12 @@ public class SlicedByteBuf extends AbstractDerivedByteBuf {
return buffer.getBytes(idx(index), out, length);
}
@Override
public int getBytes(int index, FileChannel out, long position, int length) throws IOException {
checkIndex0(index, length);
return buffer.getBytes(idx(index), out, position, length);
}
@Override
public int setBytes(int index, InputStream in, int length) throws IOException {
checkIndex0(index, length);
@ -290,6 +297,12 @@ public class SlicedByteBuf extends AbstractDerivedByteBuf {
return buffer.setBytes(idx(index), in, length);
}
@Override
public int setBytes(int index, FileChannel in, long position, int length) throws IOException {
checkIndex0(index, length);
return buffer.setBytes(idx(index), in, position, length);
}
@Override
public int nioBufferCount() {
return buffer.nioBufferCount();

View File

@ -22,6 +22,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
import java.nio.charset.Charset;
@ -359,6 +360,11 @@ public class SwappedByteBuf extends ByteBuf {
return buf.getBytes(index, out, length);
}
@Override
public int getBytes(int index, FileChannel out, long position, int length) throws IOException {
return buf.getBytes(index, out, position, length);
}
@Override
public ByteBuf setBoolean(int index, boolean value) {
buf.setBoolean(index, value);
@ -483,6 +489,11 @@ public class SwappedByteBuf extends ByteBuf {
return buf.setBytes(index, in, length);
}
@Override
public int setBytes(int index, FileChannel in, long position, int length) throws IOException {
return buf.setBytes(index, in, position, length);
}
@Override
public ByteBuf setZero(int index, int length) {
buf.setZero(index, length);
@ -646,6 +657,11 @@ public class SwappedByteBuf extends ByteBuf {
return buf.readBytes(out, length);
}
@Override
public int readBytes(FileChannel out, long position, int length) throws IOException {
return buf.readBytes(out, position, length);
}
@Override
public ByteBuf skipBytes(int length) {
buf.skipBytes(length);
@ -776,6 +792,11 @@ public class SwappedByteBuf extends ByteBuf {
return buf.writeBytes(in, length);
}
@Override
public int writeBytes(FileChannel in, long position, int length) throws IOException {
return buf.writeBytes(in, position, length);
}
@Override
public ByteBuf writeZero(int length) {
buf.writeZero(length);

View File

@ -23,6 +23,7 @@ import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
@ -543,6 +544,22 @@ public class UnpooledDirectByteBuf extends AbstractReferenceCountedByteBuf {
return out.write(tmpBuf);
}
@Override
public int getBytes(int index, FileChannel out, long position, int length) throws IOException {
return getBytes(index, out, position, length, false);
}
private int getBytes(int index, FileChannel out, long position, int length, boolean internal) throws IOException {
ensureAccessible();
if (length == 0) {
return 0;
}
ByteBuffer tmpBuf = internal ? internalNioBuffer() : buffer.duplicate();
tmpBuf.clear().position(index).limit(index + length);
return out.write(tmpBuf, position);
}
@Override
public int readBytes(GatheringByteChannel out, int length) throws IOException {
checkReadableBytes(length);
@ -551,6 +568,14 @@ public class UnpooledDirectByteBuf extends AbstractReferenceCountedByteBuf {
return readBytes;
}
@Override
public int readBytes(FileChannel out, long position, int length) throws IOException {
checkReadableBytes(length);
int readBytes = getBytes(readerIndex, out, position, length, true);
readerIndex += readBytes;
return readBytes;
}
@Override
public int setBytes(int index, InputStream in, int length) throws IOException {
ensureAccessible();
@ -581,6 +606,18 @@ public class UnpooledDirectByteBuf extends AbstractReferenceCountedByteBuf {
}
}
@Override
public int setBytes(int index, FileChannel in, long position, int length) throws IOException {
ensureAccessible();
ByteBuffer tmpBuf = internalNioBuffer();
tmpBuf.clear().position(index).limit(index + length);
try {
return in.read(tmpNioBuf, position);
} catch (ClosedChannelException ignored) {
return -1;
}
}
@Override
public int nioBufferCount() {
return 1;

View File

@ -23,6 +23,7 @@ import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
@ -197,6 +198,12 @@ public class UnpooledHeapByteBuf extends AbstractReferenceCountedByteBuf {
return getBytes(index, out, length, false);
}
@Override
public int getBytes(int index, FileChannel out, long position, int length) throws IOException {
ensureAccessible();
return getBytes(index, out, position, length, false);
}
private int getBytes(int index, GatheringByteChannel out, int length, boolean internal) throws IOException {
ensureAccessible();
ByteBuffer tmpBuf;
@ -208,6 +215,12 @@ public class UnpooledHeapByteBuf extends AbstractReferenceCountedByteBuf {
return out.write((ByteBuffer) tmpBuf.clear().position(index).limit(index + length));
}
private int getBytes(int index, FileChannel out, long position, int length, boolean internal) throws IOException {
ensureAccessible();
ByteBuffer tmpBuf = internal ? internalNioBuffer() : ByteBuffer.wrap(array);
return out.write((ByteBuffer) tmpBuf.clear().position(index).limit(index + length), position);
}
@Override
public int readBytes(GatheringByteChannel out, int length) throws IOException {
checkReadableBytes(length);
@ -216,6 +229,14 @@ public class UnpooledHeapByteBuf extends AbstractReferenceCountedByteBuf {
return readBytes;
}
@Override
public int readBytes(FileChannel out, long position, int length) throws IOException {
checkReadableBytes(length);
int readBytes = getBytes(readerIndex, out, position, length, true);
readerIndex += readBytes;
return readBytes;
}
@Override
public ByteBuf setBytes(int index, ByteBuf src, int srcIndex, int length) {
checkSrcIndex(index, length, srcIndex, src.capacity());
@ -259,6 +280,16 @@ public class UnpooledHeapByteBuf extends AbstractReferenceCountedByteBuf {
}
}
@Override
public int setBytes(int index, FileChannel in, long position, int length) throws IOException {
ensureAccessible();
try {
return in.read((ByteBuffer) internalNioBuffer().clear().position(index).limit(index + length), position);
} catch (ClosedChannelException ignored) {
return -1;
}
}
@Override
public int nioBufferCount() {
return 1;

View File

@ -23,6 +23,7 @@ import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
@ -375,6 +376,22 @@ public class UnpooledUnsafeDirectByteBuf extends AbstractReferenceCountedByteBuf
return out.write(tmpBuf);
}
@Override
public int getBytes(int index, FileChannel out, long position, int length) throws IOException {
return getBytes(index, out, position, length, false);
}
private int getBytes(int index, FileChannel out, long position, int length, boolean internal) throws IOException {
ensureAccessible();
if (length == 0) {
return 0;
}
ByteBuffer tmpBuf = internal ? internalNioBuffer() : buffer.duplicate();
tmpBuf.clear().position(index).limit(index + length);
return out.write(tmpBuf, position);
}
@Override
public int readBytes(GatheringByteChannel out, int length) throws IOException {
checkReadableBytes(length);
@ -383,6 +400,14 @@ public class UnpooledUnsafeDirectByteBuf extends AbstractReferenceCountedByteBuf
return readBytes;
}
@Override
public int readBytes(FileChannel out, long position, int length) throws IOException {
checkReadableBytes(length);
int readBytes = getBytes(readerIndex, out, position, length, true);
readerIndex += readBytes;
return readBytes;
}
@Override
public int setBytes(int index, InputStream in, int length) throws IOException {
return UnsafeByteBufUtil.setBytes(this, addr(index), index, in, length);
@ -400,6 +425,18 @@ public class UnpooledUnsafeDirectByteBuf extends AbstractReferenceCountedByteBuf
}
}
@Override
public int setBytes(int index, FileChannel in, long position, int length) throws IOException {
ensureAccessible();
ByteBuffer tmpBuf = internalNioBuffer();
tmpBuf.clear().position(index).limit(index + length);
try {
return in.read(tmpBuf, position);
} catch (ClosedChannelException ignored) {
return -1;
}
}
@Override
public int nioBufferCount() {
return 1;

View File

@ -24,6 +24,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
import java.nio.charset.Charset;
@ -350,6 +351,11 @@ class WrappedByteBuf extends ByteBuf {
return buf.getBytes(index, out, length);
}
@Override
public int getBytes(int index, FileChannel out, long position, int length) throws IOException {
return buf.getBytes(index, out, position, length);
}
@Override
public ByteBuf setBoolean(int index, boolean value) {
buf.setBoolean(index, value);
@ -474,6 +480,11 @@ class WrappedByteBuf extends ByteBuf {
return buf.setBytes(index, in, length);
}
@Override
public int setBytes(int index, FileChannel in, long position, int length) throws IOException {
return buf.setBytes(index, in, position, length);
}
@Override
public ByteBuf setZero(int index, int length) {
buf.setZero(index, length);
@ -637,6 +648,11 @@ class WrappedByteBuf extends ByteBuf {
return buf.readBytes(out, length);
}
@Override
public int readBytes(FileChannel out, long position, int length) throws IOException {
return buf.readBytes(out, position, length);
}
@Override
public ByteBuf skipBytes(int length) {
buf.skipBytes(length);
@ -767,6 +783,11 @@ class WrappedByteBuf extends ByteBuf {
return buf.writeBytes(in, length);
}
@Override
public int writeBytes(FileChannel in, long position, int length) throws IOException {
return buf.writeBytes(in, position, length);
}
@Override
public ByteBuf writeZero(int length) {
buf.writeZero(length);

View File

@ -27,10 +27,13 @@ import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.ReadOnlyBufferException;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
import java.nio.channels.WritableByteChannel;
@ -2894,6 +2897,89 @@ public abstract class AbstractByteBufTest {
assertEquals(0, readOnlyDst.position());
}
@Test
public void testReadBytesAndWriteBytesWithFileChannel() throws IOException {
File file = File.createTempFile("file-channel", ".tmp");
RandomAccessFile randomAccessFile = null;
try {
randomAccessFile = new RandomAccessFile(file, "rw");
FileChannel channel = randomAccessFile.getChannel();
// channelPosition should never be changed
long channelPosition = channel.position();
byte[] bytes = {'a', 'b', 'c', 'd'};
int len = bytes.length;
ByteBuf buffer = releaseLater(newBuffer(len));
buffer.resetReaderIndex();
buffer.resetWriterIndex();
buffer.writeBytes(bytes);
int oldReaderIndex = buffer.readerIndex();
assertEquals(len, buffer.readBytes(channel, 10, len));
assertEquals(oldReaderIndex + len, buffer.readerIndex());
assertEquals(channelPosition, channel.position());
ByteBuf buffer2 = releaseLater(newBuffer(len));
buffer2.resetReaderIndex();
buffer2.resetWriterIndex();
int oldWriterIndex = buffer2.writerIndex();
assertEquals(len, buffer2.writeBytes(channel, 10, len));
assertEquals(channelPosition, channel.position());
assertEquals(oldWriterIndex + len, buffer2.writerIndex());
assertEquals('a', buffer2.getByte(0));
assertEquals('b', buffer2.getByte(1));
assertEquals('c', buffer2.getByte(2));
assertEquals('d', buffer2.getByte(3));
} finally {
if (randomAccessFile != null) {
randomAccessFile.close();
}
file.delete();
}
}
@Test
public void testGetBytesAndSetBytesWithFileChannel() throws IOException {
File file = File.createTempFile("file-channel", ".tmp");
RandomAccessFile randomAccessFile = null;
try {
randomAccessFile = new RandomAccessFile(file, "rw");
FileChannel channel = randomAccessFile.getChannel();
// channelPosition should never be changed
long channelPosition = channel.position();
byte[] bytes = {'a', 'b', 'c', 'd'};
int len = bytes.length;
ByteBuf buffer = releaseLater(newBuffer(len));
buffer.resetReaderIndex();
buffer.resetWriterIndex();
buffer.writeBytes(bytes);
int oldReaderIndex = buffer.readerIndex();
assertEquals(len, buffer.getBytes(oldReaderIndex, channel, 10, len));
assertEquals(oldReaderIndex, buffer.readerIndex());
assertEquals(channelPosition, channel.position());
ByteBuf buffer2 = releaseLater(newBuffer(len));
buffer2.resetReaderIndex();
buffer2.resetWriterIndex();
int oldWriterIndex = buffer2.writerIndex();
assertEquals(buffer2.setBytes(oldWriterIndex, channel, 10, len), len);
assertEquals(channelPosition, channel.position());
assertEquals(oldWriterIndex, buffer2.writerIndex());
assertEquals('a', buffer2.getByte(oldWriterIndex));
assertEquals('b', buffer2.getByte(oldWriterIndex + 1));
assertEquals('c', buffer2.getByte(oldWriterIndex + 2));
assertEquals('d', buffer2.getByte(oldWriterIndex + 3));
} finally {
if (randomAccessFile != null) {
randomAccessFile.close();
}
file.delete();
}
}
private void testRefCnt0(final boolean parameter) throws Exception {
for (int i = 0; i < 10; i++) {
final CountDownLatch latch = new CountDownLatch(1);

View File

@ -27,6 +27,7 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
import java.nio.charset.Charset;
@ -233,6 +234,12 @@ final class ReplayingDecoderByteBuf extends ByteBuf {
return 0;
}
@Override
public int getBytes(int index, FileChannel out, long position, int length) {
reject();
return 0;
}
@Override
public ByteBuf getBytes(int index, OutputStream out, int length) {
reject();
@ -557,6 +564,12 @@ final class ReplayingDecoderByteBuf extends ByteBuf {
return 0;
}
@Override
public int readBytes(FileChannel out, long position, int length) {
reject();
return 0;
}
@Override
public ByteBuf readBytes(int length) {
checkReadableBytes(length);
@ -766,6 +779,12 @@ final class ReplayingDecoderByteBuf extends ByteBuf {
return 0;
}
@Override
public int setBytes(int index, FileChannel in, long position, int length) {
reject();
return 0;
}
@Override
public ByteBuf setIndex(int readerIndex, int writerIndex) {
reject();
@ -995,6 +1014,12 @@ final class ReplayingDecoderByteBuf extends ByteBuf {
return 0;
}
@Override
public int writeBytes(FileChannel in, long position, int length) {
reject();
return 0;
}
@Override
public ByteBuf writeInt(int value) {
reject();