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)");
     }
   }
 }
    public static void toXContent(
        IndexMetaData indexMetaData, XContentBuilder builder, ToXContent.Params params)
        throws IOException {
      builder.startObject(indexMetaData.index(), XContentBuilder.FieldCaseConversion.NONE);

      builder.field("version", indexMetaData.version());
      builder.field("state", indexMetaData.state().toString().toLowerCase(Locale.ENGLISH));

      boolean binary = params.paramAsBoolean("binary", false);

      builder.startObject("settings");
      for (Map.Entry<String, String> entry : indexMetaData.settings().getAsMap().entrySet()) {
        builder.field(entry.getKey(), entry.getValue());
      }
      builder.endObject();

      builder.startArray("mappings");
      for (Map.Entry<String, MappingMetaData> entry : indexMetaData.mappings().entrySet()) {
        if (binary) {
          builder.value(entry.getValue().source().compressed());
        } else {
          byte[] data = entry.getValue().source().uncompressed();
          XContentParser parser = XContentFactory.xContent(data).createParser(data);
          Map<String, Object> mapping = parser.mapOrdered();
          parser.close();
          builder.map(mapping);
        }
      }
      builder.endArray();

      for (Map.Entry<String, Custom> entry : indexMetaData.customs().entrySet()) {
        builder.startObject(entry.getKey(), XContentBuilder.FieldCaseConversion.NONE);
        lookupFactorySafe(entry.getKey()).toXContent(entry.getValue(), builder, params);
        builder.endObject();
      }

      builder.startObject("aliases");
      for (AliasMetaData alias : indexMetaData.aliases().values()) {
        AliasMetaData.Builder.toXContent(alias, builder, params);
      }
      builder.endObject();

      builder.endObject();
    }
 public static void writeTo(IndexMetaData indexMetaData, StreamOutput out) throws IOException {
   out.writeUTF(indexMetaData.index());
   out.writeLong(indexMetaData.version());
   out.writeByte(indexMetaData.state().id());
   writeSettingsToStream(indexMetaData.settings(), out);
   out.writeVInt(indexMetaData.mappings().size());
   for (MappingMetaData mappingMd : indexMetaData.mappings().values()) {
     MappingMetaData.writeTo(mappingMd, out);
   }
   out.writeVInt(indexMetaData.aliases().size());
   for (AliasMetaData aliasMd : indexMetaData.aliases().values()) {
     AliasMetaData.Builder.writeTo(aliasMd, out);
   }
   out.writeVInt(indexMetaData.customs().size());
   for (Map.Entry<String, Custom> entry : indexMetaData.customs().entrySet()) {
     out.writeUTF(entry.getKey());
     lookupFactorySafe(entry.getKey()).writeTo(entry.getValue(), out);
   }
 }
 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)");
         }
       }
     }
   }
 }