| Index: lucene/core/src/java/org/apache/lucene/store/NIOFSDirectory.java |
| =================================================================== |
| --- lucene/core/src/java/org/apache/lucene/store/NIOFSDirectory.java (revision 1384783) |
| +++ lucene/core/src/java/org/apache/lucene/store/NIOFSDirectory.java (working copy) |
| @@ -20,13 +20,12 @@ |
| 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.util.concurrent.Future; // javadoc |
| |
| -import org.apache.lucene.store.SimpleFSDirectory.SimpleFSIndexInput.Descriptor; |
| - |
| /** |
| * An {@link FSDirectory} implementation that uses java.nio's FileChannel's |
| * positional read, which allows multiple threads to read from the same file |
| @@ -85,7 +84,7 @@ |
| final IOContext context) throws IOException { |
| ensureOpen(); |
| final File path = new File(getDirectory(), name); |
| - final Descriptor descriptor = new Descriptor(path, "r"); |
| + final RandomAccessFile descriptor = new RandomAccessFile(path, "r"); |
| return new Directory.IndexInputSlicer() { |
| |
| @Override |
| @@ -104,7 +103,7 @@ |
| /** |
| * Reads bytes with {@link FileChannel#read(ByteBuffer, long)} |
| */ |
| - protected static class NIOFSIndexInput extends SimpleFSDirectory.SimpleFSIndexInput { |
| + protected static class NIOFSIndexInput extends FSIndexInput { |
| |
| private ByteBuffer byteBuf; // wraps the buffer for NIO |
| |
| @@ -115,7 +114,7 @@ |
| channel = file.getChannel(); |
| } |
| |
| - public NIOFSIndexInput(String sliceDescription, File path, Descriptor file, FileChannel fc, long off, long length, int bufferSize, int 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; |
| isClone = true; |
| @@ -128,18 +127,6 @@ |
| } |
| |
| @Override |
| - public void close() throws IOException { |
| - if (!isClone && file.isOpen) { |
| - // Close the channel & file |
| - try { |
| - channel.close(); |
| - } finally { |
| - file.close(); |
| - } |
| - } |
| - } |
| - |
| - @Override |
| protected void readInternal(byte[] b, int offset, int len) throws IOException { |
| |
| final ByteBuffer bb; |
| @@ -194,6 +181,9 @@ |
| throw new IOException(ioe.getMessage() + ": " + this, ioe); |
| } |
| } |
| + |
| + @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 1384783) |
| +++ lucene/core/src/java/org/apache/lucene/store/SimpleFSDirectory.java (working copy) |
| @@ -22,8 +22,6 @@ |
| import java.io.IOException; |
| import java.io.RandomAccessFile; |
| |
| -import org.apache.lucene.store.SimpleFSDirectory.SimpleFSIndexInput.Descriptor; |
| - |
| /** A straightforward implementation of {@link FSDirectory} |
| * using java.io.RandomAccessFile. However, this class has |
| * poor concurrent performance (multiple threads will |
| @@ -64,7 +62,7 @@ |
| final IOContext context) throws IOException { |
| ensureOpen(); |
| final File file = new File(getDirectory(), name); |
| - final Descriptor descriptor = new Descriptor(file, "r"); |
| + final RandomAccessFile descriptor = new RandomAccessFile(file, "r"); |
| return new IndexInputSlicer() { |
| |
| @Override |
| @@ -84,56 +82,14 @@ |
| * Reads bytes with {@link RandomAccessFile#seek(long)} followed by |
| * {@link RandomAccessFile#read(byte[], int, int)}. |
| */ |
| - protected static class SimpleFSIndexInput extends BufferedIndexInput { |
| + protected static class SimpleFSIndexInput extends FSIndexInput { |
| |
| - /** |
| - * Extension of RandomAccessFile that tracks if the file is |
| - * open. |
| - */ |
| - protected static class Descriptor extends RandomAccessFile { |
| - // remember if the file is open, so that we don't try to close it |
| - // more than once |
| - protected volatile boolean isOpen; |
| - long position; |
| - final long length; |
| - |
| - public Descriptor(File file, String mode) throws IOException { |
| - super(file, mode); |
| - isOpen=true; |
| - length=length(); |
| - } |
| - |
| - @Override |
| - public void close() throws IOException { |
| - if (isOpen) { |
| - isOpen=false; |
| - super.close(); |
| - } |
| - } |
| - } |
| - |
| - protected final Descriptor file; |
| - boolean isClone; |
| - // LUCENE-1566 - maximum read length on a 32bit JVM to prevent incorrect OOM |
| - protected final int chunkSize; |
| - protected final long off; |
| - protected final long end; |
| - |
| public SimpleFSIndexInput(String resourceDesc, File path, IOContext context, int chunkSize) throws IOException { |
| - super(resourceDesc, context); |
| - this.file = new Descriptor(path, "r"); |
| - this.chunkSize = chunkSize; |
| - this.off = 0L; |
| - this.end = file.length; |
| + super(resourceDesc, path, context, chunkSize); |
| } |
| |
| - public SimpleFSIndexInput(String resourceDesc, Descriptor file, long off, long length, int bufferSize, int chunkSize) { |
| - super(resourceDesc, bufferSize); |
| - this.file = file; |
| - this.chunkSize = chunkSize; |
| - this.off = off; |
| - this.end = off + length; |
| - this.isClone = true; // well, we are sorta? |
| + public SimpleFSIndexInput(String resourceDesc, RandomAccessFile file, long off, long length, int bufferSize, int chunkSize) { |
| + super(resourceDesc, file, off, length, bufferSize, chunkSize); |
| } |
| |
| /** IndexInput methods */ |
| @@ -142,10 +98,7 @@ |
| throws IOException { |
| synchronized (file) { |
| long position = off + getFilePointer(); |
| - if (position != file.position) { |
| - file.seek(position); |
| - file.position = position; |
| - } |
| + file.seek(position); |
| int total = 0; |
| |
| if (position + len > end) { |
| @@ -162,7 +115,6 @@ |
| readLength = chunkSize; |
| } |
| final int i = file.read(b, offset + total, readLength); |
| - file.position += i; |
| total += i; |
| } while (total < len); |
| } catch (OutOfMemoryError e) { |
| @@ -181,32 +133,7 @@ |
| } |
| |
| @Override |
| - public void close() throws IOException { |
| - // only close the file if this is not a clone |
| - if (!isClone) file.close(); |
| - } |
| - |
| - @Override |
| protected void seekInternal(long position) { |
| } |
| - |
| - @Override |
| - public long length() { |
| - return end - off; |
| - } |
| - |
| - @Override |
| - public SimpleFSIndexInput clone() { |
| - SimpleFSIndexInput clone = (SimpleFSIndexInput)super.clone(); |
| - clone.isClone = true; |
| - return clone; |
| - } |
| - |
| - /** 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/FSDirectory.java |
| =================================================================== |
| --- lucene/core/src/java/org/apache/lucene/store/FSDirectory.java (revision 1384783) |
| +++ lucene/core/src/java/org/apache/lucene/store/FSDirectory.java (working copy) |
| @@ -437,6 +437,65 @@ |
| return chunkSize; |
| } |
| |
| + /** Base class for reading input from a RandomAccessFile */ |
| + protected abstract static class FSIndexInput extends BufferedIndexInput { |
| + /** the underlying RandomAccessFile */ |
| + protected final RandomAccessFile file; |
| + boolean isClone = false; |
| + /** maximum read length on a 32bit JVM to prevent incorrect OOM, see LUCENE-1566 */ |
| + protected final int chunkSize; |
| + /** start offset: non-zero in the slice case */ |
| + protected final long off; |
| + /** end offset (start+length) */ |
| + protected final long end; |
| + |
| + /** Create a new FSIndexInput, reading the entire file from <code>path</code> */ |
| + protected FSIndexInput(String resourceDesc, File path, IOContext context, int chunkSize) throws IOException { |
| + super(resourceDesc, context); |
| + this.file = new RandomAccessFile(path, "r"); |
| + this.chunkSize = chunkSize; |
| + this.off = 0L; |
| + this.end = file.length(); |
| + } |
| + |
| + /** Create a new FSIndexInput, representing a slice of an existing open <code>file</code> */ |
| + protected FSIndexInput(String resourceDesc, RandomAccessFile file, long off, long length, int bufferSize, int chunkSize) { |
| + super(resourceDesc, bufferSize); |
| + this.file = file; |
| + this.chunkSize = chunkSize; |
| + this.off = off; |
| + this.end = off + length; |
| + this.isClone = true; // well, we are sorta? |
| + } |
| + |
| + @Override |
| + public void close() throws IOException { |
| + // only close the file if this is not a clone |
| + if (!isClone) { |
| + file.close(); |
| + } |
| + } |
| + |
| + @Override |
| + public FSIndexInput clone() { |
| + FSIndexInput clone = (FSIndexInput)super.clone(); |
| + clone.isClone = true; |
| + return clone; |
| + } |
| + |
| + @Override |
| + 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(); |
| + } |
| + } |
| + |
| /** |
| * Writes output with {@link RandomAccessFile#write(byte[], int, int)} |
| */ |