/// <summary> Commit changes resulting from delete, undeleteAll, or /// setNorm operations /// /// If an exception is hit, then either no changes or all /// changes will have been committed to the index /// (transactional semantics). /// /// </summary> /// <throws> IOException </throws> public void Commit() { lock (this) { if (hasChanges) { if (deleter == null) { // In the MultiReader case, we share this deleter // across all SegmentReaders: SetDeleter(new IndexFileDeleter(segmentInfos, directory)); } if (directoryOwner) { // Should not be necessary: no prior commit should // have left pending files, so just defensive: deleter.ClearPendingFiles(); System.String oldInfoFileName = segmentInfos.GetCurrentSegmentFileName(); System.String nextSegmentsFileName = segmentInfos.GetNextSegmentFileName(); // Checkpoint the state we are about to change, in // case we have to roll back: StartCommit(); bool success = false; try { DoCommit(); segmentInfos.Write(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(); // Erase any pending files that we were going to delete: deleter.ClearPendingFiles(); // Remove possibly partially written next // segments file: deleter.DeleteFile(nextSegmentsFileName); // Recompute deletable files & remove them (so // partially written .del files, etc, are // removed): deleter.FindDeletableFiles(); deleter.DeleteFiles(); } } // Attempt to delete all files we just obsoleted: deleter.DeleteFile(oldInfoFileName); deleter.CommitPendingFiles(); if (writeLock != null) { writeLock.Release(); // release write lock writeLock = null; } } else { DoCommit(); } } hasChanges = false; } }