/**
   * {@link SnapshotDeletionPolicy} wraps another {@link IndexDeletionPolicy} to enable flexible
   * snapshotting.
   *
   * @param primary the {@link IndexDeletionPolicy} that is used on non-snapshotted commits.
   *     Snapshotted commits, are not deleted until explicitly released via {@link #release(String)}
   * @param snapshotsInfo A mapping of snapshot ID to the segments filename that is being
   *     snapshotted. The expected input would be the output of {@link #getSnapshots()}. A null
   *     value signals that there are no initial snapshots to maintain.
   */
  public SnapshotDeletionPolicy(IndexDeletionPolicy primary, Map<String, String> snapshotsInfo) {
    this(primary);

    if (snapshotsInfo != null) {
      // Add the ID->segmentIDs here - the actual IndexCommits will be
      // reconciled on the call to onInit()
      for (Entry<String, String> e : snapshotsInfo.entrySet()) {
        registerSnapshotInfo(e.getKey(), e.getValue(), null);
      }
    }
  }
  /**
   * Snapshots the last commit. Once a commit is 'snapshotted,' it is protected from deletion (as
   * long as this {@link IndexDeletionPolicy} is used). The commit can be removed by calling {@link
   * #release(String)} using the same ID parameter followed by a call to {@link
   * IndexWriter#deleteUnusedFiles()}.
   *
   * <p><b>NOTE:</b> ID must be unique in the system. If the same ID is used twice, an {@link
   * IllegalStateException} is thrown.
   *
   * <p><b>NOTE:</b> while the snapshot is held, the files it references will not be deleted, which
   * will consume additional disk space in your index. If you take a snapshot at a particularly bad
   * time (say just before you call forceMerge) then in the worst case this could consume an extra
   * 1X of your total index size, until you release the snapshot.
   *
   * @param id a unique identifier of the commit that is being snapshotted.
   * @throws IllegalStateException if either there is no 'last commit' to snapshot, or if the
   *     parameter 'ID' refers to an already snapshotted commit.
   * @return the {@link IndexCommit} that was snapshotted.
   */
  public synchronized IndexCommit snapshot(String id) throws IOException {
    if (lastCommit == null) {
      // no commit exists. Really shouldn't happen, but might be if SDP is
      // accessed before onInit or onCommit were called.
      throw new IllegalStateException("No index commit to snapshot");
    }

    // Can't use the same snapshot ID twice...
    checkSnapshotted(id);

    registerSnapshotInfo(id, lastCommit.getSegmentsFileName(), lastCommit);
    return lastCommit;
  }