Index: lucene/core/src/java/org/apache/lucene/store/FSDirectory.java =================================================================== --- lucene/core/src/java/org/apache/lucene/store/FSDirectory.java (revision 1458763) +++ lucene/core/src/java/org/apache/lucene/store/FSDirectory.java (working copy) @@ -17,12 +17,17 @@ * limitations under the License. */ +import java.io.Closeable; import java.io.File; import java.io.FileNotFoundException; import java.io.FilenameFilter; import java.io.IOException; import java.io.RandomAccessFile; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.file.StandardOpenOption; + import java.util.Collection; import static java.util.Collections.synchronizedSet; import java.util.HashSet; @@ -392,10 +397,11 @@ return chunkSize; } - /** Base class for reading input from a RandomAccessFile */ - protected abstract static class FSIndexInput extends BufferedIndexInput { - /** the underlying RandomAccessFile */ - protected final RandomAccessFile file; + /** Base class for reading input from an object that accesses a file. This class is parameterized + * with the concrete file accessor class (for example RandomAccessFile or FileChannel) */ + protected abstract static class FSIndexInput extends BufferedIndexInput { + /** the underlying file accessor object */ + protected final T file; boolean isClone = false; /** maximum read length on a 32bit JVM to prevent incorrect OOM, see LUCENE-1566 */ protected final int chunkSize; @@ -405,16 +411,16 @@ protected final long end; /** Create a new FSIndexInput, reading the entire file from path */ - protected FSIndexInput(String resourceDesc, File path, IOContext context, int chunkSize) throws IOException { + protected FSIndexInput(String resourceDesc, T file, long fileLength, IOContext context, int chunkSize) throws IOException { super(resourceDesc, context); - this.file = new RandomAccessFile(path, "r"); + this.file = file; this.chunkSize = chunkSize; this.off = 0L; - this.end = file.length(); + this.end = fileLength; } /** Create a new FSIndexInput, representing a slice of an existing open file */ - protected FSIndexInput(String resourceDesc, RandomAccessFile file, long off, long length, int bufferSize, int chunkSize) { + protected FSIndexInput(String resourceDesc, T file, long off, long length, int bufferSize, int chunkSize) { super(resourceDesc, bufferSize); this.file = file; this.chunkSize = chunkSize; @@ -432,8 +438,9 @@ } @Override - public FSIndexInput clone() { - FSIndexInput clone = (FSIndexInput)super.clone(); + @SuppressWarnings("unchecked") + public FSIndexInput clone() { + FSIndexInput clone = (FSIndexInput)super.clone(); clone.isClone = true; return clone; } @@ -442,13 +449,6 @@ public final long length() { return end - off; } - - /** Method used for testing. Returns true if the underlying - * file descriptor is valid. - */ - boolean isFDValid() throws IOException { - return file.getFD().valid(); - } } /** Index: lucene/core/src/java/org/apache/lucene/store/MMapDirectory.java =================================================================== --- lucene/core/src/java/org/apache/lucene/store/MMapDirectory.java (revision 1458763) +++ lucene/core/src/java/org/apache/lucene/store/MMapDirectory.java (working copy) @@ -19,11 +19,11 @@ import java.io.IOException; import java.io.File; -import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.ClosedChannelException; // javadoc @link import java.nio.channels.FileChannel; import java.nio.channels.FileChannel.MapMode; +import java.nio.file.StandardOpenOption; import java.security.AccessController; import java.security.PrivilegedExceptionAction; @@ -133,7 +133,7 @@ this.chunkSizePower = 31 - Integer.numberOfLeadingZeros(maxChunkSize); assert this.chunkSizePower >= 0 && this.chunkSizePower <= 30; } - + /** * true, if this platform supports unmapping mmapped files. */ @@ -189,12 +189,9 @@ @Override public IndexInput openInput(String name, IOContext context) throws IOException { ensureOpen(); - File f = new File(getDirectory(), name); - RandomAccessFile raf = new RandomAccessFile(f, "r"); - try { - return new MMapIndexInput("MMapIndexInput(path=\"" + f + "\")", raf); - } finally { - raf.close(); + File file = new File(getDirectory(), name); + try (FileChannel c = FileChannel.open(file.toPath(), StandardOpenOption.READ)) { + return new MMapIndexInput("MMapIndexInput(path=\"" + file.toString() + "\")", c); } } @@ -218,8 +215,8 @@ private final class MMapIndexInput extends ByteBufferIndexInput { private final boolean useUnmapHack; - MMapIndexInput(String resourceDescription, RandomAccessFile raf) throws IOException { - super(resourceDescription, map(raf, 0, raf.length()), raf.length(), chunkSizePower, getUseUnmap()); + MMapIndexInput(String resourceDescription, FileChannel fc) throws IOException { + super(resourceDescription, map(fc, 0, fc.size()), fc.size(), chunkSizePower, getUseUnmap()); this.useUnmapHack = getUseUnmap(); } @@ -256,9 +253,9 @@ } /** Maps a file into a set of buffers */ - ByteBuffer[] map(RandomAccessFile raf, long offset, long length) throws IOException { + ByteBuffer[] map(FileChannel fc, long offset, long length) throws IOException { if ((length >>> chunkSizePower) >= Integer.MAX_VALUE) - throw new IllegalArgumentException("RandomAccessFile too big for chunk size: " + raf.toString()); + throw new IllegalArgumentException("RandomAccessFile too big for chunk size: " + fc.toString()); final long chunkSize = 1L << chunkSizePower; @@ -268,13 +265,12 @@ ByteBuffer buffers[] = new ByteBuffer[nrBuffers]; long bufferStart = 0L; - FileChannel rafc = raf.getChannel(); for (int bufNr = 0; bufNr < nrBuffers; bufNr++) { int bufSize = (int) ( (length > (bufferStart + chunkSize)) ? chunkSize : (length - bufferStart) ); - buffers[bufNr] = rafc.map(MapMode.READ_ONLY, offset + bufferStart, bufSize); + buffers[bufNr] = fc.map(MapMode.READ_ONLY, offset + bufferStart, bufSize); bufferStart += bufSize; } Index: lucene/core/src/java/org/apache/lucene/store/NIOFSDirectory.java =================================================================== --- lucene/core/src/java/org/apache/lucene/store/NIOFSDirectory.java (revision 1458763) +++ lucene/core/src/java/org/apache/lucene/store/NIOFSDirectory.java (working copy) @@ -20,10 +20,10 @@ import java.io.File; import java.io.EOFException; import java.io.IOException; -import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.ClosedChannelException; // javadoc @link import java.nio.channels.FileChannel; +import java.nio.file.StandardOpenOption; import java.util.concurrent.Future; // javadoc /** @@ -77,7 +77,9 @@ @Override public IndexInput openInput(String name, IOContext context) throws IOException { ensureOpen(); - return new NIOFSIndexInput(new File(getDirectory(), name), context, getReadChunkSize()); + File path = new File(getDirectory(), name); + FileChannel fc = FileChannel.open(path.toPath(), StandardOpenOption.READ); + return new NIOFSIndexInput("NIOFSIndexInput(path=\"" + path + "\")", fc, context, getReadChunkSize()); } @Override @@ -85,7 +87,7 @@ final IOContext context) throws IOException { ensureOpen(); final File path = new File(getDirectory(), name); - final RandomAccessFile descriptor = new RandomAccessFile(path, "r"); + final FileChannel descriptor = FileChannel.open(path.toPath(), StandardOpenOption.READ); return new Directory.IndexInputSlicer() { @Override @@ -95,7 +97,7 @@ @Override public IndexInput openSlice(String sliceDescription, long offset, long length) { - return new NIOFSIndexInput(sliceDescription, path, descriptor, descriptor.getChannel(), offset, + return new NIOFSIndexInput("NIOFSIndexInput(" + sliceDescription + " in path=\"" + path + "\" slice=" + offset + ":" + (offset+length) + ")", descriptor, offset, length, BufferedIndexInput.bufferSize(context), getReadChunkSize()); } }; @@ -104,20 +106,16 @@ /** * Reads bytes with {@link FileChannel#read(ByteBuffer, long)} */ - protected static class NIOFSIndexInput extends FSIndexInput { + protected static class NIOFSIndexInput extends FSIndexInput { private ByteBuffer byteBuf; // wraps the buffer for NIO - final FileChannel channel; - - public NIOFSIndexInput(File path, IOContext context, int chunkSize) throws IOException { - super("NIOFSIndexInput(path=\"" + path + "\")", path, context, chunkSize); - channel = file.getChannel(); + public NIOFSIndexInput(String resourceDesc, FileChannel fc, IOContext context, int chunkSize) throws IOException { + super(resourceDesc, fc, fc.size(), context, chunkSize); } - public NIOFSIndexInput(String sliceDescription, File path, RandomAccessFile file, FileChannel fc, long off, long length, int bufferSize, int chunkSize) { - super("NIOFSIndexInput(" + sliceDescription + " in path=\"" + path + "\" slice=" + off + ":" + (off+length) + ")", file, off, length, bufferSize, chunkSize); - channel = fc; + public NIOFSIndexInput(String resourceDesc, FileChannel fc, long off, long length, int bufferSize, int chunkSize) { + super(resourceDesc, fc, off, length, bufferSize, chunkSize); isClone = true; } @@ -164,7 +162,7 @@ limit = readOffset + readLength; } bb.limit(limit); - int i = channel.read(bb, pos); + int i = file.read(bb, pos); pos += i; readOffset += i; readLength -= i; @@ -186,5 +184,4 @@ @Override protected void seekInternal(long pos) throws IOException {} } - } Index: lucene/core/src/java/org/apache/lucene/store/SimpleFSDirectory.java =================================================================== --- lucene/core/src/java/org/apache/lucene/store/SimpleFSDirectory.java (revision 1458763) +++ lucene/core/src/java/org/apache/lucene/store/SimpleFSDirectory.java (working copy) @@ -55,7 +55,8 @@ public IndexInput openInput(String name, IOContext context) throws IOException { ensureOpen(); final File path = new File(directory, name); - return new SimpleFSIndexInput("SimpleFSIndexInput(path=\"" + path.getPath() + "\")", path, context, getReadChunkSize()); + RandomAccessFile raf = new RandomAccessFile(path, "r"); + return new SimpleFSIndexInput("SimpleFSIndexInput(path=\"" + path.getPath() + "\")", raf, context, getReadChunkSize()); } @Override @@ -83,10 +84,10 @@ * Reads bytes with {@link RandomAccessFile#seek(long)} followed by * {@link RandomAccessFile#read(byte[], int, int)}. */ - protected static class SimpleFSIndexInput extends FSIndexInput { + protected static class SimpleFSIndexInput extends FSIndexInput { - public SimpleFSIndexInput(String resourceDesc, File path, IOContext context, int chunkSize) throws IOException { - super(resourceDesc, path, context, chunkSize); + public SimpleFSIndexInput(String resourceDesc, RandomAccessFile file, IOContext context, int chunkSize) throws IOException { + super(resourceDesc, file, file.length(), context, chunkSize); } public SimpleFSIndexInput(String resourceDesc, RandomAccessFile file, long off, long length, int bufferSize, int chunkSize) { @@ -136,5 +137,12 @@ @Override protected void seekInternal(long position) { } + + /** Method used for testing. Returns true if the underlying + * file descriptor is valid. + */ + boolean isFDValid() throws IOException { + return file.getFD().valid(); + } } } Index: lucene/core/src/test/org/apache/lucene/store/TestBufferedIndexInput.java =================================================================== --- lucene/core/src/test/org/apache/lucene/store/TestBufferedIndexInput.java (revision 1458763) +++ lucene/core/src/test/org/apache/lucene/store/TestBufferedIndexInput.java (working copy) @@ -21,6 +21,9 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.io.RandomAccessFile; +import java.nio.channels.FileChannel; +import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -93,12 +96,13 @@ writeBytes(tmpInputFile, TEST_FILE_LENGTH); // run test with chunk size of 10 bytes - runReadBytesAndClose(new SimpleFSIndexInput("SimpleFSIndexInput(path=\"" + tmpInputFile + "\")", tmpInputFile, - newIOContext(random()), 10), inputBufferSize, random()); + runReadBytesAndClose(new SimpleFSIndexInput("SimpleFSIndexInput(path=\"" + tmpInputFile + "\")", + new RandomAccessFile(tmpInputFile, "r"), newIOContext(random()), 10), inputBufferSize, random()); // run test with chunk size of 10 bytes - runReadBytesAndClose(new NIOFSIndexInput(tmpInputFile, - newIOContext(random()), 10), inputBufferSize, random()); + runReadBytesAndClose(new NIOFSIndexInput("NIOFSIndexInput(path=\"" + tmpInputFile + "\")", + FileChannel.open(tmpInputFile.toPath(), StandardOpenOption.READ), newIOContext(random()), 10), + inputBufferSize, random()); } private void runReadBytesAndClose(IndexInput input, int bufferSize, Random r)