1818 */
1919package org .elasticsearch .index ;
2020
21+ import org .apache .lucene .analysis .Analyzer ;
2122import org .apache .lucene .index .AssertingDirectoryReader ;
2223import org .apache .lucene .index .DirectoryReader ;
2324import org .apache .lucene .index .FieldInvertState ;
4041import org .elasticsearch .common .settings .Settings ;
4142import org .elasticsearch .common .util .BigArrays ;
4243import org .elasticsearch .common .util .PageCacheRecycler ;
44+ import org .elasticsearch .common .util .concurrent .EsRejectedExecutionException ;
4345import org .elasticsearch .core .internal .io .IOUtils ;
4446import org .elasticsearch .env .Environment ;
4547import org .elasticsearch .env .NodeEnvironment ;
4648import org .elasticsearch .env .ShardLock ;
4749import org .elasticsearch .env .TestEnvironment ;
4850import org .elasticsearch .index .analysis .AnalysisRegistry ;
51+ import org .elasticsearch .index .analysis .AnalyzerProvider ;
52+ import org .elasticsearch .index .analysis .AnalyzerScope ;
4953import org .elasticsearch .index .cache .query .DisabledQueryCache ;
5054import org .elasticsearch .index .cache .query .IndexQueryCache ;
5155import org .elasticsearch .index .cache .query .QueryCache ;
6569import org .elasticsearch .index .store .IndexStore ;
6670import org .elasticsearch .indices .IndicesModule ;
6771import org .elasticsearch .indices .IndicesQueryCache ;
72+ import org .elasticsearch .indices .analysis .AnalysisModule ;
6873import org .elasticsearch .indices .breaker .CircuitBreakerService ;
6974import org .elasticsearch .indices .breaker .NoneCircuitBreakerService ;
7075import org .elasticsearch .indices .cluster .IndicesClusterStateService .AllocatedIndices .IndexRemovalReason ;
8388
8489import java .io .IOException ;
8590import java .util .Collections ;
91+ import java .util .HashSet ;
8692import java .util .Map ;
93+ import java .util .Set ;
8794import java .util .concurrent .TimeUnit ;
8895import java .util .concurrent .atomic .AtomicBoolean ;
8996import java .util .function .Function ;
9097
9198import static java .util .Collections .emptyMap ;
99+ import static java .util .Collections .singletonMap ;
92100import static org .hamcrest .Matchers .containsString ;
101+ import static org .hamcrest .Matchers .empty ;
93102import static org .hamcrest .Matchers .hasToString ;
94103import static org .hamcrest .Matchers .instanceOf ;
95104
@@ -351,11 +360,19 @@ public void testForceCustomQueryCache() throws IOException {
351360 .put (IndexMetaData .SETTING_VERSION_CREATED , Version .CURRENT ).build ();
352361 final IndexSettings indexSettings = IndexSettingsModule .newIndexSettings ("foo" , settings );
353362 IndexModule module = new IndexModule (indexSettings , emptyAnalysisRegistry , new InternalEngineFactory (), Collections .emptyMap ());
354- module .forceQueryCacheProvider ((a , b ) -> new CustomQueryCache ());
355- expectThrows (AlreadySetException .class , () -> module .forceQueryCacheProvider ((a , b ) -> new CustomQueryCache ()));
363+ final Set <CustomQueryCache > liveQueryCaches = new HashSet <>();
364+ module .forceQueryCacheProvider ((a , b ) -> {
365+ final CustomQueryCache customQueryCache = new CustomQueryCache (liveQueryCaches );
366+ liveQueryCaches .add (customQueryCache );
367+ return customQueryCache ;
368+ });
369+ expectThrows (AlreadySetException .class , () -> module .forceQueryCacheProvider ((a , b ) -> {
370+ throw new AssertionError ("never called" );
371+ }));
356372 IndexService indexService = newIndexService (module );
357373 assertTrue (indexService .cache ().query () instanceof CustomQueryCache );
358374 indexService .close ("simon says" , false );
375+ assertThat (liveQueryCaches , empty ());
359376 }
360377
361378 public void testDefaultQueryCacheImplIsSelected () throws IOException {
@@ -376,12 +393,73 @@ public void testDisableQueryCacheHasPrecedenceOverForceQueryCache() throws IOExc
376393 .put (IndexMetaData .SETTING_VERSION_CREATED , Version .CURRENT ).build ();
377394 final IndexSettings indexSettings = IndexSettingsModule .newIndexSettings ("foo" , settings );
378395 IndexModule module = new IndexModule (indexSettings , emptyAnalysisRegistry , new InternalEngineFactory (), Collections .emptyMap ());
379- module .forceQueryCacheProvider ((a , b ) -> new CustomQueryCache ());
396+ module .forceQueryCacheProvider ((a , b ) -> new CustomQueryCache (null ));
380397 IndexService indexService = newIndexService (module );
381398 assertTrue (indexService .cache ().query () instanceof DisabledQueryCache );
382399 indexService .close ("simon says" , false );
383400 }
384401
402+ public void testCustomQueryCacheCleanedUpIfIndexServiceCreationFails () {
403+ Settings settings = Settings .builder ()
404+ .put (Environment .PATH_HOME_SETTING .getKey (), createTempDir ().toString ())
405+ .put (IndexMetaData .SETTING_VERSION_CREATED , Version .CURRENT ).build ();
406+ final IndexSettings indexSettings = IndexSettingsModule .newIndexSettings ("foo" , settings );
407+ IndexModule module = new IndexModule (indexSettings , emptyAnalysisRegistry , new InternalEngineFactory (), Collections .emptyMap ());
408+ final Set <CustomQueryCache > liveQueryCaches = new HashSet <>();
409+ module .forceQueryCacheProvider ((a , b ) -> {
410+ final CustomQueryCache customQueryCache = new CustomQueryCache (liveQueryCaches );
411+ liveQueryCaches .add (customQueryCache );
412+ return customQueryCache ;
413+ });
414+ threadPool .shutdown (); // causes index service creation to fail
415+ expectThrows (EsRejectedExecutionException .class , () -> newIndexService (module ));
416+ assertThat (liveQueryCaches , empty ());
417+ }
418+
419+ public void testIndexAnalyzersCleanedUpIfIndexServiceCreationFails () {
420+ Settings settings = Settings .builder ()
421+ .put (Environment .PATH_HOME_SETTING .getKey (), createTempDir ().toString ())
422+ .put (IndexMetaData .SETTING_VERSION_CREATED , Version .CURRENT ).build ();
423+ final IndexSettings indexSettings = IndexSettingsModule .newIndexSettings ("foo" , settings );
424+
425+ final HashSet <Analyzer > openAnalyzers = new HashSet <>();
426+ final AnalysisModule .AnalysisProvider <AnalyzerProvider <?>> analysisProvider = (i ,e ,n ,s ) -> new AnalyzerProvider <Analyzer >() {
427+ @ Override
428+ public String name () {
429+ return "test" ;
430+ }
431+
432+ @ Override
433+ public AnalyzerScope scope () {
434+ return AnalyzerScope .INDEX ;
435+ }
436+
437+ @ Override
438+ public Analyzer get () {
439+ final Analyzer analyzer = new Analyzer () {
440+ @ Override
441+ protected TokenStreamComponents createComponents (String fieldName ) {
442+ throw new AssertionError ("should not be here" );
443+ }
444+
445+ @ Override
446+ public void close () {
447+ super .close ();
448+ openAnalyzers .remove (this );
449+ }
450+ };
451+ openAnalyzers .add (analyzer );
452+ return analyzer ;
453+ }
454+ };
455+ final AnalysisRegistry analysisRegistry = new AnalysisRegistry (environment , emptyMap (), emptyMap (), emptyMap (),
456+ singletonMap ("test" , analysisProvider ), emptyMap (), emptyMap (), emptyMap (), emptyMap (), emptyMap ());
457+ IndexModule module = new IndexModule (indexSettings , analysisRegistry , new InternalEngineFactory (), Collections .emptyMap ());
458+ threadPool .shutdown (); // causes index service creation to fail
459+ expectThrows (EsRejectedExecutionException .class , () -> newIndexService (module ));
460+ assertThat (openAnalyzers , empty ());
461+ }
462+
385463 public void testMmapNotAllowed () {
386464 String storeType = randomFrom (IndexModule .Type .HYBRIDFS .getSettingsKey (), IndexModule .Type .MMAPFS .getSettingsKey ());
387465 final Settings settings = Settings .builder ()
@@ -400,12 +478,19 @@ public void testMmapNotAllowed() {
400478
401479 class CustomQueryCache implements QueryCache {
402480
481+ private final Set <CustomQueryCache > liveQueryCaches ;
482+
483+ CustomQueryCache (Set <CustomQueryCache > liveQueryCaches ) {
484+ this .liveQueryCaches = liveQueryCaches ;
485+ }
486+
403487 @ Override
404488 public void clear (String reason ) {
405489 }
406490
407491 @ Override
408- public void close () throws IOException {
492+ public void close () {
493+ assertTrue (liveQueryCaches == null || liveQueryCaches .remove (this ));
409494 }
410495
411496 @ Override
0 commit comments