|
22 | 22 | import org.apache.lucene.store.Directory;
|
23 | 23 | import org.apache.lucene.store.FSDirectory;
|
24 | 24 | import org.apache.lucene.store.FileSwitchDirectory;
|
| 25 | +import org.apache.lucene.store.IOContext; |
| 26 | +import org.apache.lucene.store.IndexInput; |
25 | 27 | import org.apache.lucene.store.LockFactory;
|
26 | 28 | import org.apache.lucene.store.MMapDirectory;
|
27 | 29 | import org.apache.lucene.store.NIOFSDirectory;
|
|
31 | 33 | import org.elasticsearch.common.inject.Inject;
|
32 | 34 | import org.elasticsearch.common.settings.Setting;
|
33 | 35 | import org.elasticsearch.common.settings.Setting.Property;
|
34 |
| -import org.elasticsearch.common.util.set.Sets; |
| 36 | +import org.elasticsearch.core.internal.io.IOUtils; |
35 | 37 | import org.elasticsearch.index.IndexModule;
|
36 | 38 | import org.elasticsearch.index.IndexSettings;
|
37 | 39 | import org.elasticsearch.index.shard.ShardPath;
|
38 | 40 |
|
39 | 41 | import java.io.IOException;
|
40 | 42 | import java.nio.file.Files;
|
41 | 43 | import java.nio.file.Path;
|
42 |
| -import java.util.Collections; |
43 | 44 | import java.util.HashSet;
|
44 | 45 | import java.util.Set;
|
45 | 46 |
|
46 | 47 | public class FsDirectoryService extends DirectoryService {
|
47 |
| - /* |
48 |
| - * We are mmapping norms, docvalues as well as term dictionaries, all other files are served through NIOFS |
49 |
| - * this provides good random access performance and does not lead to page cache thrashing. |
50 |
| - */ |
51 |
| - private static final Set<String> PRIMARY_EXTENSIONS = Collections.unmodifiableSet(Sets.newHashSet("nvd", "dvd", "tim")); |
52 |
| - |
53 | 48 | protected final IndexStore indexStore;
|
54 | 49 | public static final Setting<LockFactory> INDEX_LOCK_FACTOR_SETTING = new Setting<>("index.store.fs.fs_lock", "native", (s) -> {
|
55 | 50 | switch (s) {
|
@@ -97,13 +92,7 @@ protected Directory newFSDirectory(Path location, LockFactory lockFactory) throw
|
97 | 92 | // Use Lucene defaults
|
98 | 93 | final FSDirectory primaryDirectory = FSDirectory.open(location, lockFactory);
|
99 | 94 | if (primaryDirectory instanceof MMapDirectory) {
|
100 |
| - return new FileSwitchDirectory(PRIMARY_EXTENSIONS, primaryDirectory, new NIOFSDirectory(location, lockFactory), true) { |
101 |
| - @Override |
102 |
| - public String[] listAll() throws IOException { |
103 |
| - // Avoid doing listAll twice: |
104 |
| - return primaryDirectory.listAll(); |
105 |
| - } |
106 |
| - }; |
| 95 | + return new HybridDirectory(location, lockFactory, primaryDirectory); |
107 | 96 | } else {
|
108 | 97 | return primaryDirectory;
|
109 | 98 | }
|
@@ -139,4 +128,44 @@ public String[] listAll() throws IOException {
|
139 | 128 | }
|
140 | 129 | return directory;
|
141 | 130 | }
|
| 131 | + |
| 132 | + static final class HybridDirectory extends NIOFSDirectory { |
| 133 | + private final FSDirectory randomAccessDirectory; |
| 134 | + |
| 135 | + HybridDirectory(Path location, LockFactory lockFactory, FSDirectory randomAccessDirectory) throws IOException { |
| 136 | + super(location, lockFactory); |
| 137 | + this.randomAccessDirectory = randomAccessDirectory; |
| 138 | + } |
| 139 | + |
| 140 | + @Override |
| 141 | + public IndexInput openInput(String name, IOContext context) throws IOException { |
| 142 | + String extension = FileSwitchDirectory.getExtension(name); |
| 143 | + switch(extension) { |
| 144 | + // We are mmapping norms, docvalues as well as term dictionaries, all other files are served through NIOFS |
| 145 | + // this provides good random access performance and does not lead to page cache thrashing. |
| 146 | + case "nvd": |
| 147 | + case "dvd": |
| 148 | + case "tim": |
| 149 | + // we need to do these checks on the outer directory since the inner doesn't know about pending deletes |
| 150 | + ensureOpen(); |
| 151 | + ensureCanRead(name); |
| 152 | + // we only use the mmap to open inputs. Everything else is managed by the NIOFSDirectory otherwise |
| 153 | + // we might run into trouble with files that are pendingDelete in one directory but still |
| 154 | + // listed in listAll() from the other. We on the other hand don't want to list files from both dirs |
| 155 | + // and intersect for perf reasons. |
| 156 | + return randomAccessDirectory.openInput(name, context); |
| 157 | + default: |
| 158 | + return super.openInput(name, context); |
| 159 | + } |
| 160 | + } |
| 161 | + |
| 162 | + @Override |
| 163 | + public void close() throws IOException { |
| 164 | + IOUtils.close(super::close, randomAccessDirectory); |
| 165 | + } |
| 166 | + |
| 167 | + Directory getRandomAccessDirectory() { |
| 168 | + return randomAccessDirectory; |
| 169 | + } |
| 170 | + } |
142 | 171 | }
|
0 commit comments