Skip to content

Commit 57e697e

Browse files
committed
iter
1 parent 8765efa commit 57e697e

File tree

2 files changed

+133
-8
lines changed

2 files changed

+133
-8
lines changed

server/src/main/java/org/elasticsearch/index/IndexModule.java

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,7 @@ public void addSimilarity(String name, TriFunction<Settings, IndexVersion, Scrip
370370
/**
371371
* Adds a new instance of factory creating new {@link DirectoryReader} wrapper instances.
372372
* The factory ({@link Function}) is called once the IndexService is fully constructed.
373-
* All added wrappers are applied in the order they have been added.
373+
* The order of execution of wrappers is not guaranteed.
374374
* <p>
375375
* The {@link CheckedFunction} is invoked each time a {@link Engine.Searcher} is requested to do an operation,
376376
* for example search, and must return a new directory reader wrapping the provided directory reader or if no
@@ -499,13 +499,25 @@ public IndexService newIndexService(
499499
QueryRewriteInterceptor queryRewriteInterceptor
500500
) throws IOException {
501501
final IndexEventListener eventListener = freeze();
502-
Function<IndexService, CheckedFunction<DirectoryReader, DirectoryReader, IOException>> readerWrapperFactory = indexReaderWrappers
503-
.isEmpty() ? indexService -> null : indexService -> (directoryReader) -> {
504-
var wrapped = indexReaderWrappers.get(0).apply(indexService).apply(directoryReader);
505-
for (int i = 1; i < indexReaderWrappers.size(); i++) {
506-
wrapped = indexReaderWrappers.get(i).apply(indexService).apply(wrapped);
507-
}
508-
return wrapped;
502+
Function<IndexService, CheckedFunction<DirectoryReader, DirectoryReader, IOException>> readerWrapperFactory =
503+
switch (indexReaderWrappers.size()) {
504+
case 0 -> indexService -> null;
505+
case 1 -> indexReaderWrappers.get(0);
506+
default -> indexService -> {
507+
// Call factories only one time when creating index service to avoid duplicate work.
508+
var wrappers = new ArrayList<CheckedFunction<DirectoryReader, DirectoryReader, IOException>>();
509+
for (var indexReaderWrapper : indexReaderWrappers) {
510+
wrappers.add(indexReaderWrapper.apply(indexService));
511+
}
512+
513+
return directoryReader -> {
514+
var wrapped = wrappers.get(0).apply(directoryReader);
515+
for (int i = 1; i < wrappers.size(); i++) {
516+
wrapped = wrappers.get(i).apply(wrapped);
517+
}
518+
return wrapped;
519+
};
520+
};
509521
};
510522
eventListener.beforeIndexCreated(indexSettings.getIndex(), indexSettings.getSettings());
511523
final IndexStorePlugin.DirectoryFactory directoryFactory = getDirectoryFactory(indexSettings, directoryFactories);

server/src/test/java/org/elasticsearch/index/IndexModuleTests.java

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212
import org.apache.lucene.analysis.standard.StandardTokenizer;
1313
import org.apache.lucene.index.DirectoryReader;
1414
import org.apache.lucene.index.FieldInvertState;
15+
import org.apache.lucene.index.FilterDirectoryReader;
1516
import org.apache.lucene.index.IndexCommit;
17+
import org.apache.lucene.index.IndexWriter;
18+
import org.apache.lucene.index.LeafReader;
1619
import org.apache.lucene.search.CollectionStatistics;
1720
import org.apache.lucene.search.QueryCachingPolicy;
1821
import org.apache.lucene.search.TermStatistics;
@@ -275,6 +278,70 @@ public void testWrapperIsBound() throws IOException {
275278
closeIndexService(indexService);
276279
}
277280

281+
public void testMultipleReaderWrappers() throws IOException {
282+
final MockEngineFactory engineFactory = new MockEngineFactory(AssertingDirectoryReader.class);
283+
IndexModule module = new IndexModule(
284+
indexSettings,
285+
emptyAnalysisRegistry,
286+
engineFactory,
287+
Collections.emptyMap(),
288+
() -> true,
289+
indexNameExpressionResolver,
290+
Collections.emptyMap(),
291+
mock(SlowLogFieldProvider.class),
292+
MapperMetrics.NOOP,
293+
emptyList(),
294+
new IndexingStatsSettings(ClusterSettings.createBuiltInClusterSettings()),
295+
new SearchStatsSettings(ClusterSettings.createBuiltInClusterSettings()),
296+
MergeMetrics.NOOP
297+
);
298+
299+
class Wrapper extends FilterDirectoryReader {
300+
final String name;
301+
final DirectoryReader wrappedReader;
302+
303+
Wrapper(String name, DirectoryReader in) throws IOException {
304+
super(in, new SubReaderWrapper() {
305+
@Override
306+
public LeafReader wrap(LeafReader reader) {
307+
return reader;
308+
}
309+
});
310+
this.name = name;
311+
this.wrappedReader = in;
312+
}
313+
314+
@Override
315+
protected DirectoryReader doWrapDirectoryReader(DirectoryReader in) throws IOException {
316+
return null;
317+
}
318+
319+
@Override
320+
public CacheHelper getReaderCacheHelper() {
321+
return null;
322+
}
323+
}
324+
325+
module.addReaderWrapper(s -> reader -> new Wrapper("A", reader));
326+
module.addReaderWrapper(s -> reader -> new Wrapper("B", reader));
327+
328+
IndexService indexService = newIndexService(module);
329+
330+
var wrapper = indexService.getReaderWrapper();
331+
332+
try (var directory = newDirectory(); var reader = new DummyDirectoryReader(directory)) {
333+
var wrapped = wrapper.apply(reader);
334+
// B is the outermost wrapper since it was added last.
335+
assertTrue(wrapped instanceof Wrapper w && w.name.equals("B"));
336+
var secondLevel = ((Wrapper) wrapped).wrappedReader;
337+
assertTrue(secondLevel instanceof Wrapper w && w.name.equals("A"));
338+
var thirdLevel = ((Wrapper) secondLevel).wrappedReader;
339+
assertTrue(thirdLevel instanceof DummyDirectoryReader);
340+
}
341+
342+
closeIndexService(indexService);
343+
}
344+
278345
public void testRegisterIndexStore() throws IOException {
279346
final Settings settings = Settings.builder()
280347
.put(IndexMetadata.SETTING_VERSION_CREATED, IndexVersion.current())
@@ -894,4 +961,50 @@ protected WrappedDirectory(Directory in, ShardRouting shardRouting) {
894961
this.shardRouting = shardRouting;
895962
}
896963
}
964+
965+
private static class DummyDirectoryReader extends DirectoryReader {
966+
DummyDirectoryReader(Directory directory) throws IOException {
967+
super(directory, new LeafReader[0], null);
968+
}
969+
970+
@Override
971+
protected DirectoryReader doOpenIfChanged() throws IOException {
972+
return null;
973+
}
974+
975+
@Override
976+
protected DirectoryReader doOpenIfChanged(IndexCommit commit) throws IOException {
977+
return null;
978+
}
979+
980+
@Override
981+
protected DirectoryReader doOpenIfChanged(IndexWriter writer, boolean applyAllDeletes) throws IOException {
982+
return null;
983+
}
984+
985+
@Override
986+
public long getVersion() {
987+
return 0;
988+
}
989+
990+
@Override
991+
public boolean isCurrent() throws IOException {
992+
return false;
993+
}
994+
995+
@Override
996+
public IndexCommit getIndexCommit() throws IOException {
997+
return null;
998+
}
999+
1000+
@Override
1001+
protected void doClose() throws IOException {
1002+
1003+
}
1004+
1005+
@Override
1006+
public CacheHelper getReaderCacheHelper() {
1007+
return null;
1008+
}
1009+
}
8971010
}

0 commit comments

Comments
 (0)