You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by md...@apache.org on 2018/09/18 09:33:19 UTC
svn commit: r1841209 - in /jackrabbit/oak/trunk:
oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/
oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/
oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/
Author: mduerig
Date: Tue Sep 18 09:33:19 2018
New Revision: 1841209
URL: http://svn.apache.org/viewvc?rev=1841209&view=rev
Log:
OAK-7760: Use NIO in the implementation of FileAccess.Mapped#read
Modified:
jackrabbit/oak/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/IOUtils.java
jackrabbit/oak/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/package-info.java
jackrabbit/oak/trunk/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/IOUtilsTest.java
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/FileAccess.java
Modified: jackrabbit/oak/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/IOUtils.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/IOUtils.java?rev=1841209&r1=1841208&r2=1841209&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/IOUtils.java (original)
+++ jackrabbit/oak/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/IOUtils.java Tue Sep 18 09:33:19 2018
@@ -22,6 +22,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
import java.util.Locale;
/**
@@ -44,7 +46,7 @@ public final class IOUtils {
* @param buffer the output buffer
* @param off the offset in the buffer
* @param max the number of bytes to read at most
- * @return the number of bytes read, 0 meaning EOF
+ * @return the number of bytes read, 0 meaning EOF or no space in buffer
* @throws java.io.IOException If an error occurs.
*/
public static int readFully(InputStream in, byte[] buffer, int off, int max) throws IOException {
@@ -61,6 +63,31 @@ public final class IOUtils {
}
return result;
}
+
+ /**
+ * Try to read the given number of bytes starting at the specified position
+ * into the buffer. This method reads until the maximum number of bytes have
+ * been read or until the end of the channel.
+ *
+ * @param channel the input channel
+ * @param position the position to start reading from the channel
+ * @param buffer the output buffer
+ * @return the number of bytes read, 0 meaning EOF or no space in buffer
+ * @throws java.io.IOException If an error occurs.
+ */
+ public static int readFully(FileChannel channel, int position, ByteBuffer buffer)
+ throws IOException {
+ int result = 0;
+ while (buffer.remaining() > 0) {
+ int count = channel.read(buffer, position);
+ if (count < 0) {
+ break;
+ }
+ result += count;
+ position += count;
+ }
+ return result;
+ }
/**
* Skip a number of bytes in an input stream.
Modified: jackrabbit/oak/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/package-info.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/package-info.java?rev=1841209&r1=1841208&r2=1841209&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/package-info.java (original)
+++ jackrabbit/oak/trunk/oak-commons/src/main/java/org/apache/jackrabbit/oak/commons/package-info.java Tue Sep 18 09:33:19 2018
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-@Version("1.1.1")
+@Version("1.2.1")
package org.apache.jackrabbit.oak.commons;
import org.osgi.annotation.versioning.Version;
Modified: jackrabbit/oak/trunk/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/IOUtilsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/IOUtilsTest.java?rev=1841209&r1=1841208&r2=1841209&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/IOUtilsTest.java (original)
+++ jackrabbit/oak/trunk/oak-commons/src/test/java/org/apache/jackrabbit/oak/commons/IOUtilsTest.java Tue Sep 18 09:33:19 2018
@@ -16,12 +16,17 @@
*/
package org.apache.jackrabbit.oak.commons;
+import static org.apache.commons.io.FileUtils.writeByteArrayToFile;
+
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
+import java.io.File;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.RandomAccessFile;
+import java.nio.ByteBuffer;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
@@ -33,6 +38,90 @@ import junit.framework.TestCase;
*/
public class IOUtilsTest extends TestCase {
+ private File testFile;
+
+ @Override
+ protected void setUp() throws Exception {
+ testFile = new File("target", "test");
+ writeByteArrayToFile(
+ testFile,
+ new byte[]{0,1,2,3,4,5,6,7});
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ testFile.delete();
+ }
+
+ public void testReadAll() throws IOException {
+ try (RandomAccessFile file = new RandomAccessFile(testFile, "r")) {
+ ByteBuffer buffer = ByteBuffer.allocate(8);
+ assertEquals(8, IOUtils.readFully(file.getChannel(), 0, buffer));
+ assertEquals(3, buffer.array()[3]);
+ }
+ }
+
+ public void testReadWithLargeBuffer() throws IOException {
+ try (RandomAccessFile file = new RandomAccessFile(testFile, "r")) {
+ ByteBuffer buffer = ByteBuffer.allocate(10);
+ assertEquals(8, IOUtils.readFully(file.getChannel(), 0, buffer));
+ assertEquals(3, buffer.array()[3]);
+ }
+ }
+
+ public void testReadWithSmallBuffer() throws IOException {
+ try (RandomAccessFile file = new RandomAccessFile(testFile, "r")) {
+ ByteBuffer buffer = ByteBuffer.allocate(6);
+ assertEquals(6, IOUtils.readFully(file.getChannel(), 0, buffer));
+ assertEquals(3, buffer.array()[3]);
+ }
+ }
+
+ public void testReadWithEmptyBuffer() throws IOException {
+ try (RandomAccessFile file = new RandomAccessFile(testFile, "r")) {
+ ByteBuffer buffer = ByteBuffer.allocate(0);
+ assertEquals(0, IOUtils.readFully(file.getChannel(), 0, buffer));
+ }
+ }
+
+ public void testReadAllFromOffset() throws IOException {
+ try (RandomAccessFile file = new RandomAccessFile(testFile, "r")) {
+ ByteBuffer buffer = ByteBuffer.allocate(7);
+ assertEquals(7, IOUtils.readFully(file.getChannel(), 1, buffer));
+ assertEquals(4, buffer.array()[3]);
+ }
+ }
+
+ public void testReadWithLargeBufferFromOffset() throws IOException {
+ try (RandomAccessFile file = new RandomAccessFile(testFile, "r")) {
+ ByteBuffer buffer = ByteBuffer.allocate(10);
+ assertEquals(7, IOUtils.readFully(file.getChannel(), 1, buffer));
+ assertEquals(4, buffer.array()[3]);
+ }
+ }
+
+ public void testReadWithSmallBufferFromOffset() throws IOException {
+ try (RandomAccessFile file = new RandomAccessFile(testFile, "r")) {
+ ByteBuffer buffer = ByteBuffer.allocate(6);
+ assertEquals(6, IOUtils.readFully(file.getChannel(), 1, buffer));
+ assertEquals(4, buffer.array()[3]);
+ }
+ }
+
+ public void testReadWithEmptyBufferFromOffset() throws IOException {
+ try (RandomAccessFile file = new RandomAccessFile(testFile, "r")) {
+ ByteBuffer buffer = ByteBuffer.allocate(0);
+ assertEquals(0, IOUtils.readFully(file.getChannel(), 1, buffer));
+ }
+ }
+
+ public void testReadOffsetOutOfBound() throws IOException {
+ try (RandomAccessFile file = new RandomAccessFile(testFile, "r")) {
+ ByteBuffer buffer = ByteBuffer.allocate(10);
+ assertEquals(0, IOUtils.readFully(file.getChannel(), 10, buffer));
+ }
+ }
+
public void testReadFully() throws IOException {
final Random r = new Random(1);
byte[] data = new byte[1000];
Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/FileAccess.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/FileAccess.java?rev=1841209&r1=1841208&r2=1841209&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/FileAccess.java (original)
+++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/FileAccess.java Tue Sep 18 09:33:19 2018
@@ -20,11 +20,14 @@ package org.apache.jackrabbit.oak.segmen
import static com.google.common.base.Preconditions.checkState;
import static java.nio.channels.FileChannel.MapMode.READ_ONLY;
+import static org.apache.jackrabbit.oak.commons.IOUtils.readFully;
+import java.io.EOFException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
/**
* A wrapper around either memory mapped files or random access files, to allow
@@ -88,9 +91,11 @@ abstract class FileAccess {
static class Random extends FileAccess {
private final RandomAccessFile file;
+ private final FileChannel channel;
Random(RandomAccessFile file) {
this.file = file;
+ this.channel = file.getChannel();
}
@Override
@@ -109,8 +114,10 @@ abstract class FileAccess {
public synchronized ByteBuffer read(int position, int length)
throws IOException {
ByteBuffer entry = ByteBuffer.allocate(length);
- file.seek(position);
- file.readFully(entry.array());
+ if (readFully(channel, position, entry) < length) {
+ throw new EOFException();
+ }
+ entry.flip();
return entry;
}