ReaderCommit(SegmentInfos infos, Directory dir) throws IOException {
   segmentsFileName = infos.getCurrentSegmentFileName();
   this.dir = dir;
   userData = infos.getUserData();
   files = Collections.unmodifiableCollection(infos.files(dir, true));
   version = infos.getVersion();
   generation = infos.getGeneration();
   segmentCount = infos.size();
 }
  /**
   * Commit changes resulting from delete, undeleteAll, or setNorm operations
   *
   * <p>If an exception is hit, then either no changes or all changes will have been committed to
   * the index (transactional semantics).
   *
   * @throws IOException if there is a low-level IO error
   */
  @Override
  protected void doCommit(Map<String, String> commitUserData) throws IOException {
    if (hasChanges) {
      segmentInfos.setUserData(commitUserData);
      // Default deleter (for backwards compatibility) is
      // KeepOnlyLastCommitDeleter:
      IndexFileDeleter deleter =
          new IndexFileDeleter(
              directory,
              deletionPolicy == null ? new KeepOnlyLastCommitDeletionPolicy() : deletionPolicy,
              segmentInfos,
              null,
              null);
      segmentInfos.updateGeneration(deleter.getLastSegmentInfos());
      segmentInfos.changed();

      // Checkpoint the state we are about to change, in
      // case we have to roll back:
      startCommit();

      final List<SegmentInfo> rollbackSegments = segmentInfos.createBackupSegmentInfos(false);

      boolean success = false;
      try {
        for (int i = 0; i < subReaders.length; i++) subReaders[i].commit();

        // Remove segments that contain only 100% deleted
        // docs:
        segmentInfos.pruneDeletedSegments();

        // Sync all files we just wrote
        directory.sync(segmentInfos.files(directory, false));
        segmentInfos.commit(directory);
        success = true;
      } finally {

        if (!success) {

          // Rollback changes that were made to
          // SegmentInfos but failed to get [fully]
          // committed.  This way this reader instance
          // remains consistent (matched to what's
          // actually in the index):
          rollbackCommit();

          // Recompute deletable files & remove them (so
          // partially written .del files, etc, are
          // removed):
          deleter.refresh();

          // Restore all SegmentInfos (in case we pruned some)
          segmentInfos.rollbackSegmentInfos(rollbackSegments);
        }
      }

      // Have the deleter remove any now unreferenced
      // files due to this commit:
      deleter.checkpoint(segmentInfos, true);
      deleter.close();

      maxIndexVersion = segmentInfos.getVersion();

      if (writeLock != null) {
        writeLock.release(); // release write lock
        writeLock = null;
      }
    }
    hasChanges = false;
  }