| 
12 | 12 | import org.apache.lucene.analysis.standard.StandardTokenizer;  | 
13 | 13 | import org.apache.lucene.index.DirectoryReader;  | 
14 | 14 | import org.apache.lucene.index.FieldInvertState;  | 
 | 15 | +import org.apache.lucene.index.FilterDirectoryReader;  | 
15 | 16 | import org.apache.lucene.index.IndexCommit;  | 
 | 17 | +import org.apache.lucene.index.IndexWriter;  | 
 | 18 | +import org.apache.lucene.index.LeafReader;  | 
16 | 19 | import org.apache.lucene.search.CollectionStatistics;  | 
17 | 20 | import org.apache.lucene.search.QueryCachingPolicy;  | 
18 | 21 | import org.apache.lucene.search.TermStatistics;  | 
@@ -275,6 +278,70 @@ public void testWrapperIsBound() throws IOException {  | 
275 | 278 |         closeIndexService(indexService);  | 
276 | 279 |     }  | 
277 | 280 | 
 
  | 
 | 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 | + | 
278 | 345 |     public void testRegisterIndexStore() throws IOException {  | 
279 | 346 |         final Settings settings = Settings.builder()  | 
280 | 347 |             .put(IndexMetadata.SETTING_VERSION_CREATED, IndexVersion.current())  | 
@@ -894,4 +961,50 @@ protected WrappedDirectory(Directory in, ShardRouting shardRouting) {  | 
894 | 961 |             this.shardRouting = shardRouting;  | 
895 | 962 |         }  | 
896 | 963 |     }  | 
 | 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 | +    }  | 
897 | 1010 | }  | 
0 commit comments