/**
   * Creates shard snapshot
   *
   * @param snapshotId snapshot id
   * @param snapshotStatus snapshot status
   */
  public void snapshot(final SnapshotId snapshotId, final IndexShardSnapshotStatus snapshotStatus) {
    IndexShardRepository indexShardRepository =
        repositoriesService.indexShardRepository(snapshotId.getRepository());
    if (!indexShard.routingEntry().primary()) {
      throw new IndexShardSnapshotFailedException(
          shardId, "snapshot should be performed only on primary");
    }
    if (indexShard.routingEntry().relocating()) {
      // do not snapshot when in the process of relocation of primaries so we won't get conflicts
      throw new IndexShardSnapshotFailedException(shardId, "cannot snapshot while relocating");
    }
    if (indexShard.state() == IndexShardState.CREATED
        || indexShard.state() == IndexShardState.RECOVERING) {
      // shard has just been created, or still recovering
      throw new IndexShardSnapshotFailedException(shardId, "shard didn't fully recover yet");
    }

    try {
      SnapshotIndexCommit snapshotIndexCommit = indexShard.snapshotIndex();
      try {
        indexShardRepository.snapshot(snapshotId, shardId, snapshotIndexCommit, snapshotStatus);
        if (logger.isDebugEnabled()) {
          StringBuilder sb = new StringBuilder();
          sb.append("snapshot (")
              .append(snapshotId.getSnapshot())
              .append(") completed to ")
              .append(indexShardRepository)
              .append(", took [")
              .append(TimeValue.timeValueMillis(snapshotStatus.time()))
              .append("]\n");
          sb.append("    index    : version [")
              .append(snapshotStatus.indexVersion())
              .append("], number_of_files [")
              .append(snapshotStatus.numberOfFiles())
              .append("] with total_size [")
              .append(new ByteSizeValue(snapshotStatus.totalSize()))
              .append("]\n");
          logger.debug(sb.toString());
        }
      } finally {
        snapshotIndexCommit.close();
      }
    } catch (SnapshotFailedEngineException e) {
      throw e;
    } catch (IndexShardSnapshotFailedException e) {
      throw e;
    } catch (Throwable e) {
      throw new IndexShardSnapshotFailedException(shardId, "Failed to snapshot", e);
    }
  }
 @Override
 public void readFrom(StreamInput in) throws IOException {
   super.readFrom(in);
   int n = in.readVInt();
   snapshotIds = new SnapshotId[n];
   for (int i = 0; i < n; i++) {
     snapshotIds[i] = SnapshotId.readSnapshotId(in);
   }
 }
 @Override
 public void readFrom(StreamInput in) throws IOException {
   super.readFrom(in);
   int numberOfSnapshots = in.readVInt();
   Map<SnapshotId, Map<ShardId, SnapshotIndexShardStatus>> snapshotMapBuilder =
       new HashMap<>(numberOfSnapshots);
   for (int i = 0; i < numberOfSnapshots; i++) {
     SnapshotId snapshotId = SnapshotId.readSnapshotId(in);
     int numberOfShards = in.readVInt();
     Map<ShardId, SnapshotIndexShardStatus> shardMapBuilder = new HashMap<>(numberOfShards);
     for (int j = 0; j < numberOfShards; j++) {
       ShardId shardId = ShardId.readShardId(in);
       SnapshotIndexShardStatus status = SnapshotIndexShardStatus.readShardSnapshotStatus(in);
       shardMapBuilder.put(shardId, status);
     }
     snapshotMapBuilder.put(snapshotId, unmodifiableMap(shardMapBuilder));
   }
   status = unmodifiableMap(snapshotMapBuilder);
 }