|
@@ -64,11 +64,7 @@ public class FsDirectoryFactory implements IndexStorePlugin.DirectoryFactory {
|
|
|
final Path location = path.resolveIndex();
|
|
|
final LockFactory lockFactory = indexSettings.getValue(INDEX_LOCK_FACTOR_SETTING);
|
|
|
Files.createDirectories(location);
|
|
|
- Directory wrapped = newFSDirectory(location, lockFactory, indexSettings);
|
|
|
- Set<String> preLoadExtensions = new HashSet<>(
|
|
|
- indexSettings.getValue(IndexModule.INDEX_STORE_PRE_LOAD_SETTING));
|
|
|
- wrapped = setPreload(wrapped, location, lockFactory, preLoadExtensions);
|
|
|
- return wrapped;
|
|
|
+ return newFSDirectory(location, lockFactory, indexSettings);
|
|
|
}
|
|
|
|
|
|
protected Directory newFSDirectory(Path location, LockFactory lockFactory, IndexSettings indexSettings) throws IOException {
|
|
@@ -80,17 +76,20 @@ public class FsDirectoryFactory implements IndexStorePlugin.DirectoryFactory {
|
|
|
} else {
|
|
|
type = IndexModule.Type.fromSettingsKey(storeType);
|
|
|
}
|
|
|
+ Set<String> preLoadExtensions = new HashSet<>(
|
|
|
+ indexSettings.getValue(IndexModule.INDEX_STORE_PRE_LOAD_SETTING));
|
|
|
switch (type) {
|
|
|
case HYBRIDFS:
|
|
|
// Use Lucene defaults
|
|
|
final FSDirectory primaryDirectory = FSDirectory.open(location, lockFactory);
|
|
|
if (primaryDirectory instanceof MMapDirectory) {
|
|
|
- return new HybridDirectory(location, lockFactory, primaryDirectory);
|
|
|
+ MMapDirectory mMapDirectory = (MMapDirectory) primaryDirectory;
|
|
|
+ return new HybridDirectory(lockFactory, setPreload(mMapDirectory, lockFactory, preLoadExtensions));
|
|
|
} else {
|
|
|
return primaryDirectory;
|
|
|
}
|
|
|
case MMAPFS:
|
|
|
- return new MMapDirectory(location, lockFactory);
|
|
|
+ return setPreload(new MMapDirectory(location, lockFactory), lockFactory, preLoadExtensions);
|
|
|
case SIMPLEFS:
|
|
|
return new SimpleFSDirectory(location, lockFactory);
|
|
|
case NIOFS:
|
|
@@ -100,26 +99,17 @@ public class FsDirectoryFactory implements IndexStorePlugin.DirectoryFactory {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private static Directory setPreload(Directory directory, Path location, LockFactory lockFactory,
|
|
|
+ public static MMapDirectory setPreload(MMapDirectory mMapDirectory, LockFactory lockFactory,
|
|
|
Set<String> preLoadExtensions) throws IOException {
|
|
|
- if (preLoadExtensions.isEmpty() == false
|
|
|
- && directory instanceof MMapDirectory
|
|
|
- && ((MMapDirectory) directory).getPreload() == false) {
|
|
|
+ assert mMapDirectory.getPreload() == false;
|
|
|
+ if (preLoadExtensions.isEmpty() == false) {
|
|
|
if (preLoadExtensions.contains("*")) {
|
|
|
- ((MMapDirectory) directory).setPreload(true);
|
|
|
- return directory;
|
|
|
+ mMapDirectory.setPreload(true);
|
|
|
+ } else {
|
|
|
+ return new PreLoadMMapDirectory(mMapDirectory, lockFactory, preLoadExtensions);
|
|
|
}
|
|
|
- MMapDirectory primary = new MMapDirectory(location, lockFactory);
|
|
|
- primary.setPreload(true);
|
|
|
- return new FileSwitchDirectory(preLoadExtensions, primary, directory, true) {
|
|
|
- @Override
|
|
|
- public String[] listAll() throws IOException {
|
|
|
- // avoid listing twice
|
|
|
- return primary.listAll();
|
|
|
- }
|
|
|
- };
|
|
|
}
|
|
|
- return directory;
|
|
|
+ return mMapDirectory;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -131,15 +121,35 @@ public class FsDirectoryFactory implements IndexStorePlugin.DirectoryFactory {
|
|
|
}
|
|
|
|
|
|
static final class HybridDirectory extends NIOFSDirectory {
|
|
|
- private final FSDirectory randomAccessDirectory;
|
|
|
+ private final MMapDirectory delegate;
|
|
|
|
|
|
- HybridDirectory(Path location, LockFactory lockFactory, FSDirectory randomAccessDirectory) throws IOException {
|
|
|
- super(location, lockFactory);
|
|
|
- this.randomAccessDirectory = randomAccessDirectory;
|
|
|
+ HybridDirectory(LockFactory lockFactory, MMapDirectory delegate) throws IOException {
|
|
|
+ super(delegate.getDirectory(), lockFactory);
|
|
|
+ this.delegate = delegate;
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
public IndexInput openInput(String name, IOContext context) throws IOException {
|
|
|
+ if (useDelegate(name)) {
|
|
|
+ // we need to do these checks on the outer directory since the inner doesn't know about pending deletes
|
|
|
+ ensureOpen();
|
|
|
+ ensureCanRead(name);
|
|
|
+ // we only use the mmap to open inputs. Everything else is managed by the NIOFSDirectory otherwise
|
|
|
+ // we might run into trouble with files that are pendingDelete in one directory but still
|
|
|
+ // listed in listAll() from the other. We on the other hand don't want to list files from both dirs
|
|
|
+ // and intersect for perf reasons.
|
|
|
+ return delegate.openInput(name, context);
|
|
|
+ } else {
|
|
|
+ return super.openInput(name, context);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void close() throws IOException {
|
|
|
+ IOUtils.close(super::close, delegate);
|
|
|
+ }
|
|
|
+
|
|
|
+ boolean useDelegate(String name) {
|
|
|
String extension = FileSwitchDirectory.getExtension(name);
|
|
|
switch(extension) {
|
|
|
// We are mmapping norms, docvalues as well as term dictionaries, all other files are served through NIOFS
|
|
@@ -148,26 +158,59 @@ public class FsDirectoryFactory implements IndexStorePlugin.DirectoryFactory {
|
|
|
case "dvd":
|
|
|
case "tim":
|
|
|
case "cfs":
|
|
|
- // we need to do these checks on the outer directory since the inner doesn't know about pending deletes
|
|
|
- ensureOpen();
|
|
|
- ensureCanRead(name);
|
|
|
- // we only use the mmap to open inputs. Everything else is managed by the NIOFSDirectory otherwise
|
|
|
- // we might run into trouble with files that are pendingDelete in one directory but still
|
|
|
- // listed in listAll() from the other. We on the other hand don't want to list files from both dirs
|
|
|
- // and intersect for perf reasons.
|
|
|
- return randomAccessDirectory.openInput(name, context);
|
|
|
+ return true;
|
|
|
default:
|
|
|
- return super.openInput(name, context);
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ MMapDirectory getDelegate() {
|
|
|
+ return delegate;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // TODO it would be nice to share code between PreLoadMMapDirectory and HybridDirectory but due to the nesting aspect of
|
|
|
+ // directories here makes it tricky. It would be nice to allow MMAPDirectory to pre-load on a per IndexInput basis.
|
|
|
+ static final class PreLoadMMapDirectory extends MMapDirectory {
|
|
|
+ private final MMapDirectory delegate;
|
|
|
+ private final Set<String> preloadExtensions;
|
|
|
+
|
|
|
+ PreLoadMMapDirectory(MMapDirectory delegate, LockFactory lockFactory, Set<String> preload) throws IOException {
|
|
|
+ super(delegate.getDirectory(), lockFactory);
|
|
|
+ super.setPreload(false);
|
|
|
+ this.delegate = delegate;
|
|
|
+ this.delegate.setPreload(true);
|
|
|
+ this.preloadExtensions = preload;
|
|
|
+ assert getPreload() == false;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void setPreload(boolean preload) {
|
|
|
+ throw new IllegalArgumentException("can't set preload on a preload-wrapper");
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public IndexInput openInput(String name, IOContext context) throws IOException {
|
|
|
+ if (useDelegate(name)) {
|
|
|
+ // we need to do these checks on the outer directory since the inner doesn't know about pending deletes
|
|
|
+ ensureOpen();
|
|
|
+ ensureCanRead(name);
|
|
|
+ return delegate.openInput(name, context);
|
|
|
}
|
|
|
+ return super.openInput(name, context);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public void close() throws IOException {
|
|
|
- IOUtils.close(super::close, randomAccessDirectory);
|
|
|
+ public synchronized void close() throws IOException {
|
|
|
+ IOUtils.close(super::close, delegate);
|
|
|
+ }
|
|
|
+
|
|
|
+ boolean useDelegate(String name) {
|
|
|
+ final String extension = FileSwitchDirectory.getExtension(name);
|
|
|
+ return preloadExtensions.contains(extension);
|
|
|
}
|
|
|
|
|
|
- Directory getRandomAccessDirectory() {
|
|
|
- return randomAccessDirectory;
|
|
|
+ MMapDirectory getDelegate() {
|
|
|
+ return delegate;
|
|
|
}
|
|
|
}
|
|
|
}
|