private void Write(Directory directory)
{
string segmentsFileName = NextSegmentFileName;
// Always advance the generation on write:
if (_generation == -1)
{
_generation = 1;
}
else
{
_generation++;
}
IndexOutput segnOutput = null;
bool success = false;
var upgradedSIFiles = new HashSet<string>();
try
{
segnOutput = directory.CreateOutput(segmentsFileName, IOContext.DEFAULT);
CodecUtil.WriteHeader(segnOutput, "segments", VERSION_48);
segnOutput.WriteLong(Version);
segnOutput.WriteInt(Counter); // write counter
segnOutput.WriteInt(Size()); // write infos
foreach (SegmentCommitInfo siPerCommit in segments)
{
SegmentInfo si = siPerCommit.Info;
segnOutput.WriteString(si.Name);
segnOutput.WriteString(si.Codec.Name);
segnOutput.WriteLong(siPerCommit.DelGen);
int delCount = siPerCommit.DelCount;
if (delCount < 0 || delCount > si.DocCount)
{
throw new InvalidOperationException("cannot write segment: invalid docCount segment=" + si.Name + " docCount=" + si.DocCount + " delCount=" + delCount);
}
segnOutput.WriteInt(delCount);
segnOutput.WriteLong(siPerCommit.FieldInfosGen);
IDictionary<long, ISet<string>> genUpdatesFiles = siPerCommit.UpdatesFiles;
segnOutput.WriteInt(genUpdatesFiles.Count);
foreach (KeyValuePair<long, ISet<string>> e in genUpdatesFiles)
{
segnOutput.WriteLong(e.Key);
segnOutput.WriteStringSet(e.Value);
}
Debug.Assert(si.Dir == directory);
// If this segment is pre-4.x, perform a one-time
// "ugprade" to write the .si file for it:
string version = si.Version;
if (version == null || StringHelper.VersionComparator.Compare(version, "4.0") < 0)
{
if (!SegmentWasUpgraded(directory, si))
{
string markerFileName = IndexFileNames.SegmentFileName(si.Name, "upgraded", Lucene3xSegmentInfoFormat.UPGRADED_SI_EXTENSION);
si.AddFile(markerFileName);
string segmentFileName = Write3xInfo(directory, si, IOContext.DEFAULT);
upgradedSIFiles.Add(segmentFileName);
directory.Sync(/*Collections.singletonList(*/new[] { segmentFileName }/*)*/);
// Write separate marker file indicating upgrade
// is completed. this way, if there is a JVM
// kill/crash, OS crash, power loss, etc. while
// writing the upgraded file, the marker file
// will be missing:
IndexOutput @out = directory.CreateOutput(markerFileName, IOContext.DEFAULT);
try
{
CodecUtil.WriteHeader(@out, SEGMENT_INFO_UPGRADE_CODEC, SEGMENT_INFO_UPGRADE_VERSION);
}
finally
{
@out.Dispose();
}
upgradedSIFiles.Add(markerFileName);
directory.Sync(/*Collections.SingletonList(*/new[] { markerFileName }/*)*/);
}
}
}
segnOutput.WriteStringStringMap(_userData);
PendingSegnOutput = segnOutput;
success = true;
}
finally
{
if (!success)
{
// We hit an exception above; try to close the file
// but suppress any exception:
IOUtils.CloseWhileHandlingException(segnOutput);
foreach (string fileName in upgradedSIFiles)
{
try
{
directory.DeleteFile(fileName);
}
catch (Exception)
{
// Suppress so we keep throwing the original exception
}
}
try
{
// Try not to leave a truncated segments_N file in
// the index:
directory.DeleteFile(segmentsFileName);
}
catch (Exception)
{
// Suppress so we keep throwing the original exception
}
}
}
}