143 lines
5.0 KiB
Java
143 lines
5.0 KiB
Java
|
package it.cavallium.dbengine.lucene;
|
||
|
|
||
|
import static it.cavallium.dbengine.lucene.LuceneUtils.alignUnsigned;
|
||
|
import static it.cavallium.dbengine.lucene.LuceneUtils.readInternalAligned;
|
||
|
|
||
|
import com.sun.nio.file.ExtendedOpenOption;
|
||
|
import java.io.Closeable;
|
||
|
import java.io.EOFException;
|
||
|
import java.io.IOException;
|
||
|
import java.nio.ByteBuffer;
|
||
|
import java.nio.channels.FileChannel;
|
||
|
import java.nio.file.OpenOption;
|
||
|
import java.nio.file.Path;
|
||
|
import java.nio.file.StandardOpenOption;
|
||
|
import org.apache.lucene.store.BufferedIndexInput;
|
||
|
import org.apache.lucene.store.FSDirectory;
|
||
|
import org.apache.lucene.store.FSLockFactory;
|
||
|
import org.apache.lucene.store.IOContext;
|
||
|
import org.apache.lucene.store.IndexInput;
|
||
|
import org.apache.lucene.store.LockFactory;
|
||
|
import org.apache.lucene.util.IOUtils;
|
||
|
|
||
|
@SuppressWarnings({"RedundantArrayCreation", "unused", "unused", "RedundantCast"})
|
||
|
public class DirectNIOFSDirectory extends FSDirectory {
|
||
|
|
||
|
private final OpenOption[] openOptions = {StandardOpenOption.READ, ExtendedOpenOption.DIRECT};
|
||
|
|
||
|
public DirectNIOFSDirectory(Path path, LockFactory lockFactory) throws IOException {
|
||
|
super(path, lockFactory);
|
||
|
}
|
||
|
|
||
|
public DirectNIOFSDirectory(Path path) throws IOException {
|
||
|
this(path, FSLockFactory.getDefault());
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public IndexInput openInput(String name, IOContext context) throws IOException {
|
||
|
this.ensureOpen();
|
||
|
this.ensureCanRead(name);
|
||
|
Path path = this.getDirectory().resolve(name);
|
||
|
FileChannel fc = FileChannel.open(path, openOptions);
|
||
|
boolean success = false;
|
||
|
|
||
|
DirectNIOFSDirectory.NIOFSIndexInput var7;
|
||
|
try {
|
||
|
DirectNIOFSDirectory.NIOFSIndexInput indexInput = new DirectNIOFSDirectory.NIOFSIndexInput("NIOFSIndexInput(path=\"" + path + "\")", fc, context);
|
||
|
success = true;
|
||
|
var7 = indexInput;
|
||
|
} finally {
|
||
|
if (!success) {
|
||
|
IOUtils.closeWhileHandlingException(new Closeable[]{fc});
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
return var7;
|
||
|
}
|
||
|
|
||
|
static final class NIOFSIndexInput extends BufferedIndexInput {
|
||
|
private static final int CHUNK_SIZE = 16384;
|
||
|
protected final FileChannel channel;
|
||
|
boolean isClone = false;
|
||
|
protected final long off;
|
||
|
protected final long end;
|
||
|
|
||
|
public NIOFSIndexInput(String resourceDesc, FileChannel fc, IOContext context) throws IOException {
|
||
|
super(resourceDesc, context);
|
||
|
this.channel = fc;
|
||
|
this.off = 0L;
|
||
|
this.end = fc.size();
|
||
|
}
|
||
|
|
||
|
public NIOFSIndexInput(String resourceDesc, FileChannel fc, long off, long length, int bufferSize) {
|
||
|
super(resourceDesc, bufferSize);
|
||
|
this.channel = fc;
|
||
|
this.off = off;
|
||
|
this.end = off + length;
|
||
|
this.isClone = true;
|
||
|
}
|
||
|
|
||
|
public void close() throws IOException {
|
||
|
if (!this.isClone) {
|
||
|
this.channel.close();
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
public DirectNIOFSDirectory.NIOFSIndexInput clone() {
|
||
|
DirectNIOFSDirectory.NIOFSIndexInput clone = (DirectNIOFSDirectory.NIOFSIndexInput)super.clone();
|
||
|
clone.isClone = true;
|
||
|
return clone;
|
||
|
}
|
||
|
|
||
|
public IndexInput slice(String sliceDescription, long offset, long length) throws IOException {
|
||
|
if (offset >= 0L && length >= 0L && offset + length <= this.length()) {
|
||
|
return new DirectNIOFSDirectory.NIOFSIndexInput(this.getFullSliceDescription(sliceDescription), this.channel, this.off + offset, length, this.getBufferSize());
|
||
|
} else {
|
||
|
throw new IllegalArgumentException("slice() " + sliceDescription + " out of bounds: offset=" + offset + ",length=" + length + ",fileLength=" + this.length() + ": " + this);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public final long length() {
|
||
|
return this.end - this.off;
|
||
|
}
|
||
|
|
||
|
protected void readInternal(ByteBuffer b) throws IOException {
|
||
|
long pos = this.getFilePointer() + this.off;
|
||
|
if (pos + (long)b.remaining() > this.end) {
|
||
|
throw new EOFException("read past EOF: " + this);
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
if (pos % 4096 == 0 && b.remaining() % 4096 == 0) {
|
||
|
readInternalAligned(this, this.channel, pos, b, b.remaining(), b.remaining(), end);
|
||
|
} else {
|
||
|
long startOffsetAligned = alignUnsigned(pos, false);
|
||
|
int size = b.remaining();
|
||
|
long endOffsetAligned = alignUnsigned(pos + size, true);
|
||
|
long expectedTempBufferSize = endOffsetAligned - startOffsetAligned;
|
||
|
if (expectedTempBufferSize > Integer.MAX_VALUE || expectedTempBufferSize < 0) {
|
||
|
throw new IllegalStateException("Invalid temp buffer size: " + expectedTempBufferSize);
|
||
|
}
|
||
|
ByteBuffer alignedBuf = ByteBuffer.allocate((int) expectedTempBufferSize);
|
||
|
int sliceStartOffset = (int) (pos - startOffsetAligned);
|
||
|
int sliceEndOffset = sliceStartOffset + (int) size;
|
||
|
readInternalAligned(this, this.channel, startOffsetAligned, alignedBuf, (int) expectedTempBufferSize, sliceEndOffset, end);
|
||
|
var slice = alignedBuf.slice(sliceStartOffset, sliceEndOffset - sliceStartOffset);
|
||
|
b.put(slice.array(), slice.arrayOffset(), sliceEndOffset - sliceStartOffset);
|
||
|
b.limit(b.position());
|
||
|
}
|
||
|
} catch (IOException var7) {
|
||
|
throw new IOException(var7.getMessage() + ": " + this, var7);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
protected void seekInternal(long pos) throws IOException {
|
||
|
if (pos > this.length()) {
|
||
|
throw new EOFException("read past EOF: pos=" + pos + " vs length=" + this.length() + ": " + this);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|