|  | @@ -19,14 +19,16 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  package org.elasticsearch.index;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +import com.google.common.base.Function;
 | 
	
		
			
				|  |  |  import com.google.common.collect.ImmutableMap;
 | 
	
		
			
				|  |  | -import com.google.common.collect.ImmutableSet;
 | 
	
		
			
				|  |  | -import com.google.common.collect.UnmodifiableIterator;
 | 
	
		
			
				|  |  | +import com.google.common.collect.Iterators;
 | 
	
		
			
				|  |  |  import org.apache.lucene.util.IOUtils;
 | 
	
		
			
				|  |  |  import org.elasticsearch.ElasticsearchException;
 | 
	
		
			
				|  |  |  import org.elasticsearch.ElasticsearchIllegalStateException;
 | 
	
		
			
				|  |  |  import org.elasticsearch.cluster.metadata.IndexMetaData;
 | 
	
		
			
				|  |  |  import org.elasticsearch.common.Nullable;
 | 
	
		
			
				|  |  | +import org.elasticsearch.common.Strings;
 | 
	
		
			
				|  |  | +import org.elasticsearch.common.collect.Tuple;
 | 
	
		
			
				|  |  |  import org.elasticsearch.common.inject.*;
 | 
	
		
			
				|  |  |  import org.elasticsearch.common.settings.Settings;
 | 
	
		
			
				|  |  |  import org.elasticsearch.env.NodeEnvironment;
 | 
	
	
		
			
				|  | @@ -79,7 +81,8 @@ import org.elasticsearch.plugins.ShardsPluginsModule;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import java.io.Closeable;
 | 
	
		
			
				|  |  |  import java.io.IOException;
 | 
	
		
			
				|  |  | -import java.util.Map;
 | 
	
		
			
				|  |  | +import java.util.HashMap;
 | 
	
		
			
				|  |  | +import java.util.Iterator;
 | 
	
		
			
				|  |  |  import java.util.Set;
 | 
	
		
			
				|  |  |  import java.util.concurrent.TimeUnit;
 | 
	
		
			
				|  |  |  import java.util.concurrent.atomic.AtomicBoolean;
 | 
	
	
		
			
				|  | @@ -122,11 +125,10 @@ public class IndexService extends AbstractIndexComponent implements IndexCompone
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      private final NodeEnvironment nodeEnv;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    private volatile ImmutableMap<Integer, Injector> shardsInjectors = ImmutableMap.of();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    private volatile ImmutableMap<Integer, IndexShard> shards = ImmutableMap.of();
 | 
	
		
			
				|  |  | +    private volatile ImmutableMap<Integer, Tuple<IndexShard, Injector>> shards = ImmutableMap.of();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      private final AtomicBoolean closed = new AtomicBoolean(false);
 | 
	
		
			
				|  |  | +    private final AtomicBoolean deleted = new AtomicBoolean(false);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Inject
 | 
	
		
			
				|  |  |      public IndexService(Injector injector, Index index, @IndexSettings Settings indexSettings, NodeEnvironment nodeEnv,
 | 
	
	
		
			
				|  | @@ -163,8 +165,13 @@ public class IndexService extends AbstractIndexComponent implements IndexCompone
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      @Override
 | 
	
		
			
				|  |  | -    public UnmodifiableIterator<IndexShard> iterator() {
 | 
	
		
			
				|  |  | -        return shards.values().iterator();
 | 
	
		
			
				|  |  | +    public Iterator<IndexShard> iterator() {
 | 
	
		
			
				|  |  | +        return Iterators.transform(shards.values().iterator(), new Function<Tuple<IndexShard, Injector>, IndexShard>() {
 | 
	
		
			
				|  |  | +            @Override
 | 
	
		
			
				|  |  | +            public IndexShard apply(Tuple<IndexShard, Injector> input) {
 | 
	
		
			
				|  |  | +                return input.v1();
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public boolean hasShard(int shardId) {
 | 
	
	
		
			
				|  | @@ -176,7 +183,11 @@ public class IndexService extends AbstractIndexComponent implements IndexCompone
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  |      @Nullable
 | 
	
		
			
				|  |  |      public IndexShard shard(int shardId) {
 | 
	
		
			
				|  |  | -        return shards.get(shardId);
 | 
	
		
			
				|  |  | +        Tuple<IndexShard, Injector> indexShardInjectorTuple = shards.get(shardId);
 | 
	
		
			
				|  |  | +        if (indexShardInjectorTuple != null) {
 | 
	
		
			
				|  |  | +            return indexShardInjectorTuple.v1();
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        return null;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      /**
 | 
	
		
			
				|  |  |       * Return the shard with the provided id, or throw an exception if it doesn't exist.
 | 
	
	
		
			
				|  | @@ -189,7 +200,7 @@ public class IndexService extends AbstractIndexComponent implements IndexCompone
 | 
	
		
			
				|  |  |          return indexShard;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    public ImmutableSet<Integer> shardIds() {
 | 
	
		
			
				|  |  | +    public Set<Integer> shardIds() {
 | 
	
		
			
				|  |  |          return shards.keySet();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -237,8 +248,9 @@ public class IndexService extends AbstractIndexComponent implements IndexCompone
 | 
	
		
			
				|  |  |          return aliasesService;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    public synchronized void close(final String reason) {
 | 
	
		
			
				|  |  | +    public synchronized void close(final String reason, boolean delete) {
 | 
	
		
			
				|  |  |          if (closed.compareAndSet(false, true)) {
 | 
	
		
			
				|  |  | +            deleted.compareAndSet(false, delete);
 | 
	
		
			
				|  |  |              final Set<Integer> shardIds = shardIds();
 | 
	
		
			
				|  |  |              for (final int shardId : shardIds) {
 | 
	
		
			
				|  |  |                  try {
 | 
	
	
		
			
				|  | @@ -250,23 +262,15 @@ public class IndexService extends AbstractIndexComponent implements IndexCompone
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    /**
 | 
	
		
			
				|  |  | -     * Return the shard injector for the provided id, or null if there is no such shard.
 | 
	
		
			
				|  |  | -     */
 | 
	
		
			
				|  |  | -    @Nullable
 | 
	
		
			
				|  |  | -    public Injector shardInjector(int shardId) throws ElasticsearchException {
 | 
	
		
			
				|  |  | -        return shardsInjectors.get(shardId);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      /**
 | 
	
		
			
				|  |  |       * Return the shard injector for the provided id, or throw an exception if there is no such shard.
 | 
	
		
			
				|  |  |       */
 | 
	
		
			
				|  |  |      public Injector shardInjectorSafe(int shardId) throws IndexShardMissingException {
 | 
	
		
			
				|  |  | -        Injector shardInjector = shardInjector(shardId);
 | 
	
		
			
				|  |  | -        if (shardInjector == null) {
 | 
	
		
			
				|  |  | +        Tuple<IndexShard, Injector> tuple = shards.get(shardId);
 | 
	
		
			
				|  |  | +        if (tuple == null) {
 | 
	
		
			
				|  |  |              throw new IndexShardMissingException(new ShardId(index, shardId));
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        return shardInjector;
 | 
	
		
			
				|  |  | +        return tuple.v2();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public String indexUUID() {
 | 
	
	
		
			
				|  | @@ -282,12 +286,13 @@ public class IndexService extends AbstractIndexComponent implements IndexCompone
 | 
	
		
			
				|  |  |          if (closed.get()) {
 | 
	
		
			
				|  |  |              throw new ElasticsearchIllegalStateException("Can't create shard [" + index.name() + "][" + sShardId + "], closed");
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        ShardId shardId = new ShardId(index, sShardId);
 | 
	
		
			
				|  |  | +        final ShardId shardId = new ShardId(index, sShardId);
 | 
	
		
			
				|  |  |          ShardLock lock = null;
 | 
	
		
			
				|  |  |          boolean success = false;
 | 
	
		
			
				|  |  | +        Injector shardInjector = null;
 | 
	
		
			
				|  |  |          try {
 | 
	
		
			
				|  |  |              lock = nodeEnv.shardLock(shardId, TimeUnit.SECONDS.toMillis(5));
 | 
	
		
			
				|  |  | -            if (shardsInjectors.containsKey(shardId.id())) {
 | 
	
		
			
				|  |  | +            if (shards.containsKey(shardId.id())) {
 | 
	
		
			
				|  |  |                  throw new IndexShardAlreadyExistsException(shardId + " already exists");
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -301,7 +306,8 @@ public class IndexService extends AbstractIndexComponent implements IndexCompone
 | 
	
		
			
				|  |  |              modules.add(new ShardIndexingModule());
 | 
	
		
			
				|  |  |              modules.add(new ShardSearchModule());
 | 
	
		
			
				|  |  |              modules.add(new ShardGetModule());
 | 
	
		
			
				|  |  | -            modules.add(new StoreModule(indexSettings, injector.getInstance(IndexStore.class), lock));
 | 
	
		
			
				|  |  | +            modules.add(new StoreModule(indexSettings, injector.getInstance(IndexStore.class), lock,
 | 
	
		
			
				|  |  | +                    new StoreCloseListener(shardId)));
 | 
	
		
			
				|  |  |              modules.add(new DeletionPolicyModule(indexSettings));
 | 
	
		
			
				|  |  |              modules.add(new MergePolicyModule(indexSettings));
 | 
	
		
			
				|  |  |              modules.add(new MergeSchedulerModule(indexSettings));
 | 
	
	
		
			
				|  | @@ -316,8 +322,6 @@ public class IndexService extends AbstractIndexComponent implements IndexCompone
 | 
	
		
			
				|  |  |              modules.add(new ShardTermVectorsModule());
 | 
	
		
			
				|  |  |              modules.add(new IndexShardSnapshotModule());
 | 
	
		
			
				|  |  |              modules.add(new SuggestShardModule());
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -            Injector shardInjector;
 | 
	
		
			
				|  |  |              try {
 | 
	
		
			
				|  |  |                  shardInjector = modules.createChildInjector(injector);
 | 
	
		
			
				|  |  |              } catch (CreationException e) {
 | 
	
	
		
			
				|  | @@ -326,13 +330,11 @@ public class IndexService extends AbstractIndexComponent implements IndexCompone
 | 
	
		
			
				|  |  |                  throw new IndexShardCreationException(shardId, e);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            shardsInjectors = newMapBuilder(shardsInjectors).put(shardId.id(), shardInjector).immutableMap();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |              IndexShard indexShard = shardInjector.getInstance(IndexShard.class);
 | 
	
		
			
				|  |  |              indicesLifecycle.indexShardStateChanged(indexShard, null, "shard created");
 | 
	
		
			
				|  |  |              indicesLifecycle.afterIndexShardCreated(indexShard);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            shards = newMapBuilder(shards).put(shardId.id(), indexShard).immutableMap();
 | 
	
		
			
				|  |  | +            shards = newMapBuilder(shards).put(shardId.id(), new Tuple<>(indexShard, shardInjector)).immutableMap();
 | 
	
		
			
				|  |  |              success = true;
 | 
	
		
			
				|  |  |              return indexShard;
 | 
	
		
			
				|  |  |          } catch (IOException ex) {
 | 
	
	
		
			
				|  | @@ -340,26 +342,34 @@ public class IndexService extends AbstractIndexComponent implements IndexCompone
 | 
	
		
			
				|  |  |          } finally {
 | 
	
		
			
				|  |  |              if (success == false) {
 | 
	
		
			
				|  |  |                  IOUtils.closeWhileHandlingException(lock);
 | 
	
		
			
				|  |  | +                if (shardInjector != null) {
 | 
	
		
			
				|  |  | +                    IndexShard indexShard = shardInjector.getInstance(IndexShard.class);
 | 
	
		
			
				|  |  | +                    closeShardInjector("initialization failed", shardId, shardInjector, indexShard);
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      public synchronized void removeShard(int shardId, String reason) throws ElasticsearchException {
 | 
	
		
			
				|  |  |          final ShardId sId = new ShardId(index, shardId);
 | 
	
		
			
				|  |  | -        try {
 | 
	
		
			
				|  |  | -            final Injector shardInjector;
 | 
	
		
			
				|  |  | -            final IndexShard indexShard;
 | 
	
		
			
				|  |  | -            Map<Integer, Injector> tmpShardInjectors = newHashMap(shardsInjectors);
 | 
	
		
			
				|  |  | -            shardInjector = tmpShardInjectors.remove(shardId);
 | 
	
		
			
				|  |  | -            if (shardInjector == null) {
 | 
	
		
			
				|  |  | -                return;
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +        final Injector shardInjector;
 | 
	
		
			
				|  |  | +        final IndexShard indexShard;
 | 
	
		
			
				|  |  | +        if (shards.containsKey(shardId) == false) {
 | 
	
		
			
				|  |  | +            return;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        logger.debug("[{}] closing... (reason: [{}])", shardId, reason);
 | 
	
		
			
				|  |  | +        HashMap<Integer, Tuple<IndexShard, Injector>> tmpShardsMap = newHashMap(shards);
 | 
	
		
			
				|  |  | +        Tuple<IndexShard, Injector> tuple = tmpShardsMap.remove(shardId);
 | 
	
		
			
				|  |  | +        indexShard = tuple.v1();
 | 
	
		
			
				|  |  | +        shardInjector = tuple.v2();
 | 
	
		
			
				|  |  | +        shards = ImmutableMap.copyOf(tmpShardsMap);
 | 
	
		
			
				|  |  | +        closeShardInjector(reason, sId, shardInjector, indexShard);
 | 
	
		
			
				|  |  | +        logger.debug("[{}] closed (reason: [{}])", shardId, reason);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            logger.debug("[{}] closing... (reason: [{}])", shardId, reason);
 | 
	
		
			
				|  |  | -            shardsInjectors = ImmutableMap.copyOf(tmpShardInjectors);
 | 
	
		
			
				|  |  | -            Map<Integer, IndexShard> tmpShardsMap = newHashMap(shards);
 | 
	
		
			
				|  |  | -            indexShard = tmpShardsMap.remove(shardId);
 | 
	
		
			
				|  |  | -            shards = ImmutableMap.copyOf(tmpShardsMap);
 | 
	
		
			
				|  |  | +    private void closeShardInjector(String reason, ShardId sId, Injector shardInjector, IndexShard indexShard) {
 | 
	
		
			
				|  |  | +        final int shardId = sId.id();
 | 
	
		
			
				|  |  | +        try {
 | 
	
		
			
				|  |  |              indicesLifecycle.beforeIndexShardClosed(sId, indexShard);
 | 
	
		
			
				|  |  |              for (Class<? extends Closeable> closeable : pluginsService.shardServices()) {
 | 
	
		
			
				|  |  |                  try {
 | 
	
	
		
			
				|  | @@ -368,78 +378,76 @@ public class IndexService extends AbstractIndexComponent implements IndexCompone
 | 
	
		
			
				|  |  |                      logger.debug("[{}] failed to clean plugin shard service [{}]", e, shardId, closeable);
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            try {
 | 
	
		
			
				|  |  | -                // now we can close the translog service, we need to close it before the we close the shard
 | 
	
		
			
				|  |  | -                shardInjector.getInstance(TranslogService.class).close();
 | 
	
		
			
				|  |  | -            } catch (Throwable e) {
 | 
	
		
			
				|  |  | -                logger.debug("[{}] failed to close translog service", e, shardId);
 | 
	
		
			
				|  |  | -                // ignore
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | +            // now we can close the translog service, we need to close it before the we close the shard
 | 
	
		
			
				|  |  | +            closeInjectorResource(sId, shardInjector, TranslogService.class);
 | 
	
		
			
				|  |  |              // this logic is tricky, we want to close the engine so we rollback the changes done to it
 | 
	
		
			
				|  |  |              // and close the shard so no operations are allowed to it
 | 
	
		
			
				|  |  |              if (indexShard != null) {
 | 
	
		
			
				|  |  |                  try {
 | 
	
		
			
				|  |  | -                    ((IndexShard) indexShard).close(reason);
 | 
	
		
			
				|  |  | +                    indexShard.close(reason);
 | 
	
		
			
				|  |  |                  } catch (Throwable e) {
 | 
	
		
			
				|  |  |                      logger.debug("[{}] failed to close index shard", e, shardId);
 | 
	
		
			
				|  |  |                      // ignore
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | +            closeInjectorResource(sId, shardInjector,
 | 
	
		
			
				|  |  | +                    Engine.class,
 | 
	
		
			
				|  |  | +                    MergeSchedulerProvider.class,
 | 
	
		
			
				|  |  | +                    MergePolicyProvider.class,
 | 
	
		
			
				|  |  | +                    IndexShardGatewayService.class,
 | 
	
		
			
				|  |  | +                    Translog.class,
 | 
	
		
			
				|  |  | +                    PercolatorQueriesRegistry.class);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            // call this before we close the store, so we can release resources for it
 | 
	
		
			
				|  |  | +            indicesLifecycle.afterIndexShardClosed(sId, indexShard);
 | 
	
		
			
				|  |  | +        } finally {
 | 
	
		
			
				|  |  |              try {
 | 
	
		
			
				|  |  | -                shardInjector.getInstance(Engine.class).close();
 | 
	
		
			
				|  |  | -            } catch (Throwable e) {
 | 
	
		
			
				|  |  | -                logger.debug("[{}] failed to close engine", e, shardId);
 | 
	
		
			
				|  |  | -                // ignore
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            try {
 | 
	
		
			
				|  |  | -                shardInjector.getInstance(MergeSchedulerProvider.class).close();
 | 
	
		
			
				|  |  | -            } catch (Throwable e) {
 | 
	
		
			
				|  |  | -                logger.debug("[{}] failed to close merge policy scheduler", e, shardId);
 | 
	
		
			
				|  |  | -                // ignore
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            try {
 | 
	
		
			
				|  |  | -                shardInjector.getInstance(MergePolicyProvider.class).close();
 | 
	
		
			
				|  |  | -            } catch (Throwable e) {
 | 
	
		
			
				|  |  | -                logger.debug("[{}] failed to close merge policy provider", e, shardId);
 | 
	
		
			
				|  |  | -                // ignore
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            try {
 | 
	
		
			
				|  |  | -                shardInjector.getInstance(IndexShardGatewayService.class).close();
 | 
	
		
			
				|  |  | -            } catch (Throwable e) {
 | 
	
		
			
				|  |  | -                logger.debug("[{}] failed to close index shard gateway", e, shardId);
 | 
	
		
			
				|  |  | -                // ignore
 | 
	
		
			
				|  |  | -            }
 | 
	
		
			
				|  |  | -            try {
 | 
	
		
			
				|  |  | -                // now we can close the translog
 | 
	
		
			
				|  |  | -                shardInjector.getInstance(Translog.class).close();
 | 
	
		
			
				|  |  | +                shardInjector.getInstance(Store.class).close();
 | 
	
		
			
				|  |  |              } catch (Throwable e) {
 | 
	
		
			
				|  |  | -                logger.debug("[{}] failed to close translog", e, shardId);
 | 
	
		
			
				|  |  | -                // ignore
 | 
	
		
			
				|  |  | +                logger.warn("[{}] failed to close store on shard removal (reason: [{}])", e, shardId, reason);
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    /**
 | 
	
		
			
				|  |  | +     * This method gets an instance for each of the given classes passed and calls #close() on the returned instance.
 | 
	
		
			
				|  |  | +     * NOTE: this method swallows all exceptions thrown from the close method of the injector and logs them as debug log
 | 
	
		
			
				|  |  | +     */
 | 
	
		
			
				|  |  | +    private void closeInjectorResource(ShardId shardId, Injector shardInjector, Class<? extends Closeable>... toClose) {
 | 
	
		
			
				|  |  | +        for (Class<? extends Closeable> closeable : toClose) {
 | 
	
		
			
				|  |  |              try {
 | 
	
		
			
				|  |  | -                // now we can close the translog
 | 
	
		
			
				|  |  | -                shardInjector.getInstance(PercolatorQueriesRegistry.class).close();
 | 
	
		
			
				|  |  | -            } catch (Throwable e) {
 | 
	
		
			
				|  |  | -                logger.debug("[{}] failed to close PercolatorQueriesRegistry", e, shardId);
 | 
	
		
			
				|  |  | -                // ignore
 | 
	
		
			
				|  |  | +                final Closeable instance = shardInjector.getInstance(closeable);
 | 
	
		
			
				|  |  | +                if (instance == null) {
 | 
	
		
			
				|  |  | +                    throw new NullPointerException("No instance available for " + closeable.getName());
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +                IOUtils.close(instance);
 | 
	
		
			
				|  |  | +            } catch (Throwable t) {
 | 
	
		
			
				|  |  | +                logger.debug("{} failed to close {}", t, shardId, Strings.toUnderscoreCase(closeable.getSimpleName()));
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            // call this before we close the store, so we can release resources for it
 | 
	
		
			
				|  |  | -            indicesLifecycle.afterIndexShardClosed(sId, indexShard);
 | 
	
		
			
				|  |  | -            // if we delete or have no gateway or the store is not persistent, clean the store...
 | 
	
		
			
				|  |  | -            final Store store = shardInjector.getInstance(Store.class);
 | 
	
		
			
				|  |  | -            // and close it
 | 
	
		
			
				|  |  | +    private void onShardClose(ShardLock lock) {
 | 
	
		
			
				|  |  | +        if (deleted.get()) { // we remove that shards content if this index has been deleted
 | 
	
		
			
				|  |  |              try {
 | 
	
		
			
				|  |  | -                    store.close();
 | 
	
		
			
				|  |  | -            } catch (Throwable e) {
 | 
	
		
			
				|  |  | -                logger.warn("[{}] failed to close store on shard deletion", e, shardId);
 | 
	
		
			
				|  |  | +                nodeEnv.deleteShardDirectoryUnderLock(lock, indexSettings);
 | 
	
		
			
				|  |  | +            } catch (IOException e) {
 | 
	
		
			
				|  |  | +                logger.warn("{} failed to delete shard content", e, lock.getShardId());
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  | -            Injectors.close(injector);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    private class StoreCloseListener implements Store.OnClose {
 | 
	
		
			
				|  |  | +        private final ShardId shardId;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -            logger.debug("[{}] closed (reason: [{}])", shardId, reason);
 | 
	
		
			
				|  |  | -        } catch (Throwable t) {
 | 
	
		
			
				|  |  | -            throw t;
 | 
	
		
			
				|  |  | +        public StoreCloseListener(ShardId shardId) {
 | 
	
		
			
				|  |  | +            this.shardId = shardId;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        @Override
 | 
	
		
			
				|  |  | +        public void handle(ShardLock lock) {
 | 
	
		
			
				|  |  | +            assert lock.getShardId().equals(shardId) : "shard Id mismatch, expected: "  + shardId + " but got: " + lock.getShardId();
 | 
	
		
			
				|  |  | +            onShardClose(lock);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 |