private void applyCleanedIndices(final ClusterChangedEvent event) {
   // handle closed indices, since they are not allocated on a node once they are closed
   // so applyDeletedIndices might not take them into account
   for (IndexService indexService : indicesService) {
     String index = indexService.index().getName();
     IndexMetaData indexMetaData = event.state().metaData().index(index);
     if (indexMetaData != null && indexMetaData.state() == IndexMetaData.State.CLOSE) {
       for (Integer shardId : indexService.shardIds()) {
         logger.debug("[{}][{}] removing shard (index is closed)", index, shardId);
         try {
           indexService.removeShard(shardId, "removing shard (index is closed)");
         } catch (Throwable e) {
           logger.warn("[{}] failed to remove shard (index is closed)", e, index);
         }
       }
     }
   }
   for (IndexService indexService : indicesService) {
     String index = indexService.index().getName();
     if (indexService.shardIds().isEmpty()) {
       if (logger.isDebugEnabled()) {
         logger.debug("[{}] cleaning index (no shards allocated)", index);
       }
       // clean the index
       removeIndex(index, "removing index (no shards allocated)");
     }
   }
 }
  @Override
  public void clusterChanged(final ClusterChangedEvent event) {
    if (!indicesService.changesAllowed()) {
      return;
    }

    if (!lifecycle.started()) {
      return;
    }

    synchronized (mutex) {
      // we need to clean the shards and indices we have on this node, since we
      // are going to recover them again once state persistence is disabled (no master / not
      // recovered)
      // TODO: this feels a bit hacky here, a block disables state persistence, and then we clean
      // the allocated shards, maybe another flag in blocks?
      if (event.state().blocks().disableStatePersistence()) {
        for (IndexService indexService : indicesService) {
          String index = indexService.index().getName();
          for (Integer shardId : indexService.shardIds()) {
            logger.debug("[{}][{}] removing shard (disabled block persistence)", index, shardId);
            try {
              indexService.removeShard(shardId, "removing shard (disabled block persistence)");
            } catch (Throwable e) {
              logger.warn("[{}] failed to remove shard (disabled block persistence)", e, index);
            }
          }
          removeIndex(index, "cleaning index (disabled block persistence)");
        }
        return;
      }

      cleanFailedShards(event);

      applyDeletedIndices(event);
      applyNewIndices(event);
      applyMappings(event);
      applyAliases(event);
      applyNewOrUpdatedShards(event);
      applyDeletedShards(event);
      applyCleanedIndices(event);
      applySettings(event);
    }
  }
 private void applyDeletedShards(final ClusterChangedEvent event) {
   RoutingNodes.RoutingNodeIterator routingNode =
       event.state().readOnlyRoutingNodes().routingNodeIter(event.state().nodes().localNodeId());
   if (routingNode == null) {
     return;
   }
   IntHashSet newShardIds = new IntHashSet();
   for (IndexService indexService : indicesService) {
     String index = indexService.index().name();
     IndexMetaData indexMetaData = event.state().metaData().index(index);
     if (indexMetaData == null) {
       continue;
     }
     // now, go over and delete shards that needs to get deleted
     newShardIds.clear();
     for (ShardRouting shard : routingNode) {
       if (shard.index().equals(index)) {
         newShardIds.add(shard.id());
       }
     }
     for (Integer existingShardId : indexService.shardIds()) {
       if (!newShardIds.contains(existingShardId)) {
         if (indexMetaData.state() == IndexMetaData.State.CLOSE) {
           if (logger.isDebugEnabled()) {
             logger.debug("[{}][{}] removing shard (index is closed)", index, existingShardId);
           }
           indexService.removeShard(existingShardId, "removing shard (index is closed)");
         } else {
           // we can just remove the shard, without cleaning it locally, since we will clean it
           // when all shards are allocated in the IndicesStore
           if (logger.isDebugEnabled()) {
             logger.debug("[{}][{}] removing shard (not allocated)", index, existingShardId);
           }
           indexService.removeShard(existingShardId, "removing shard (not allocated)");
         }
       }
     }
   }
 }