Skip to content

Commit

Permalink
ChunkedNioFile can use absolute FileChannel::read to read chunks
Browse files Browse the repository at this point in the history
Motivation:

Users can reuse the same FileChannel for different ChunkedNioFile
instances without being worried that FileChannel::position will be
changed concurrently by them.
In addition, FileChannel::read with absolute position allows to
use on *nix pread that is more efficient then fread.

Modifications:

Always use absolute FileChannel::read ops

Result:

Faster and more flexible uses of FileChannel for ChunkedNioFile
  • Loading branch information
franz1981 committed Sep 23, 2019
1 parent 4499384 commit da8d633
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 4 deletions.
Expand Up @@ -23,6 +23,7 @@
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.FileChannel;

/**
Expand Down Expand Up @@ -101,9 +102,8 @@ public ChunkedNioFile(FileChannel in, long offset, long length, int chunkSize)
"chunkSize: " + chunkSize +
" (expected: a positive integer)");
}

if (offset != 0) {
in.position(offset);
if (!in.isOpen()) {
throw new ClosedChannelException();
}
this.in = in;
this.chunkSize = chunkSize;
Expand Down Expand Up @@ -161,7 +161,7 @@ public ByteBuf readChunk(ByteBufAllocator allocator) throws Exception {
try {
int readBytes = 0;
for (;;) {
int localReadBytes = buffer.writeBytes(in, chunkSize - readBytes);
int localReadBytes = buffer.writeBytes(in, offset + readBytes, chunkSize - readBytes);
if (localReadBytes < 0) {
break;
}
Expand Down
Expand Up @@ -26,13 +26,17 @@
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.util.CharsetUtil;
import io.netty.util.ReferenceCountUtil;
import org.junit.Assert;
import org.junit.Test;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.channels.Channels;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.FileChannel;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
Expand Down Expand Up @@ -102,6 +106,41 @@ public void testChunkedNioFile() throws IOException {
check(new ChunkedNioFile(TMP), new ChunkedNioFile(TMP), new ChunkedNioFile(TMP));
}

@Test
public void testChunkedNioFileLeftPositionUnchanged() throws IOException {
FileChannel in = null;
final long expectedPosition = 10;
try {
in = new RandomAccessFile(TMP, "r").getChannel();
in.position(expectedPosition);
check(new ChunkedNioFile(in) {
@Override
public void close() throws Exception {
//no op
}
});
Assert.assertTrue(in.isOpen());
Assert.assertEquals(expectedPosition, in.position());
} finally {
if (in != null) {
in.close();
}
}
}

@Test(expected = ClosedChannelException.class)
public void testChunkedNioFileFailOnClosedFileChannel() throws IOException {
final FileChannel in = new RandomAccessFile(TMP, "r").getChannel();
in.close();
check(new ChunkedNioFile(in) {
@Override
public void close() throws Exception {
//no op
}
});
Assert.fail();
}

@Test
public void testUnchunkedData() throws IOException {
check(Unpooled.wrappedBuffer(BYTES));
Expand Down

0 comments on commit da8d633

Please sign in to comment.