/**
   * 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);
    }
  }