/// <summary>
/// Walk through all files referenced by the current
/// segmentInfos and ask the Directory to sync each file,
/// if it wasn't already. If that succeeds, then we
/// prepare a new segments_N file but do not fully commit
/// it.
/// </summary>
private void StartCommit(SegmentInfos toSync)
{
Debug.Assert(TestPoint("startStartCommit"));
Debug.Assert(PendingCommit == null);
if (HitOOM)
{
throw new InvalidOperationException("this writer hit an OutOfMemoryError; cannot commit");
}
try
{
if (infoStream.IsEnabled("IW"))
{
infoStream.Message("IW", "startCommit(): start");
}
lock (this)
{
Debug.Assert(LastCommitChangeCount <= ChangeCount, "lastCommitChangeCount=" + LastCommitChangeCount + " changeCount=" + ChangeCount);
if (PendingCommitChangeCount == LastCommitChangeCount)
{
if (infoStream.IsEnabled("IW"))
{
infoStream.Message("IW", " skip startCommit(): no changes pending");
}
Deleter.DecRef(FilesToCommit);
FilesToCommit = null;
return;
}
if (infoStream.IsEnabled("IW"))
{
infoStream.Message("IW", "startCommit index=" + SegString(ToLiveInfos(toSync).Segments) + " changeCount=" + ChangeCount);
}
Debug.Assert(FilesExist(toSync));
}
Debug.Assert(TestPoint("midStartCommit"));
bool pendingCommitSet = false;
try
{
Debug.Assert(TestPoint("midStartCommit2"));
lock (this)
{
Debug.Assert(PendingCommit == null);
Debug.Assert(segmentInfos.Generation == toSync.Generation);
// Exception here means nothing is prepared
// (this method unwinds everything it did on
// an exception)
toSync.PrepareCommit(directory);
//System.out.println("DONE prepareCommit");
pendingCommitSet = true;
PendingCommit = toSync;
}
// this call can take a long time -- 10s of seconds
// or more. We do it without syncing on this:
bool success = false;
ICollection<string> filesToSync;
try
{
filesToSync = toSync.Files(directory, false);
directory.Sync(filesToSync);
success = true;
}
finally
{
if (!success)
{
pendingCommitSet = false;
PendingCommit = null;
toSync.RollbackCommit(directory);
}
}
if (infoStream.IsEnabled("IW"))
{
infoStream.Message("IW", "done all syncs: " + filesToSync);
}
Debug.Assert(TestPoint("midStartCommitSuccess"));
}
finally
{
lock (this)
{
// Have our master segmentInfos record the
// generations we just prepared. We do this
// on error or success so we don't
// double-write a segments_N file.
segmentInfos.UpdateGeneration(toSync);
if (!pendingCommitSet)
{
if (infoStream.IsEnabled("IW"))
{
infoStream.Message("IW", "hit exception committing segments file");
}
// Hit exception
Deleter.DecRef(FilesToCommit);
FilesToCommit = null;
}
}
}
}
catch (System.OutOfMemoryException oom)
{
HandleOOM(oom, "startCommit");
}
Debug.Assert(TestPoint("finishStartCommit"));
}