📄 segmentinfos.cs
字号:
}
lastGeneration = generation;
}
/// <summary> Returns a copy of this instance, also copying each
/// SegmentInfo.
/// </summary>
public override System.Object Clone()
{
SegmentInfos sis = new SegmentInfos();
for (int i = 0; i < sis.Count; i++)
{
sis.Add(((SegmentInfo) this[i]).Clone());
}
return sis;
}
/// <summary> version number when this SegmentInfos was generated.</summary>
public long GetVersion()
{
return version;
}
/// <summary> Current version number from segments file.</summary>
public static long ReadCurrentVersion(Directory directory)
{
return (long) ((System.Int64) new AnonymousClassFindSegmentsFile1(directory).run());
}
/// <summary>If non-null, information about retries when loading
/// the segments file will be printed to this.
/// </summary>
public static void SetInfoStream(System.IO.TextWriter infoStream)
{
SegmentInfos.infoStream = infoStream;
}
/* Advanced configuration of retry logic in loading
segments_N file */
private static int defaultGenFileRetryCount = 10;
private static int defaultGenFileRetryPauseMsec = 50;
private static int defaultGenLookaheadCount = 10;
/// <summary> Advanced: set how many times to try loading the
/// segments.gen file contents to determine current segment
/// generation. This file is only referenced when the
/// primary method (listing the directory) fails.
/// </summary>
public static void SetDefaultGenFileRetryCount(int count)
{
defaultGenFileRetryCount = count;
}
/// <seealso cref="#setDefaultGenFileRetryCount">
/// </seealso>
public static int GetDefaultGenFileRetryCount()
{
return defaultGenFileRetryCount;
}
/// <summary> Advanced: set how many milliseconds to pause in between
/// attempts to load the segments.gen file.
/// </summary>
public static void SetDefaultGenFileRetryPauseMsec(int msec)
{
defaultGenFileRetryPauseMsec = msec;
}
/// <seealso cref="#setDefaultGenFileRetryPauseMsec">
/// </seealso>
public static int GetDefaultGenFileRetryPauseMsec()
{
return defaultGenFileRetryPauseMsec;
}
/// <summary> Advanced: set how many times to try incrementing the
/// gen when loading the segments file. This only runs if
/// the primary (listing directory) and secondary (opening
/// segments.gen file) methods fail to find the segments
/// file.
/// </summary>
public static void SetDefaultGenLookaheadCount(int count)
{
defaultGenLookaheadCount = count;
}
/// <seealso cref="#setDefaultGenLookaheadCount">
/// </seealso>
public static int GetDefaultGenLookahedCount()
{
return defaultGenLookaheadCount;
}
/// <seealso cref="#setInfoStream">
/// </seealso>
public static System.IO.TextWriter GetInfoStream()
{
return infoStream;
}
private static void Message(System.String message)
{
if (infoStream != null)
{
infoStream.WriteLine(SupportClass.ThreadClass.Current().Name + ": " + message);
}
}
/// <summary> Utility class for executing code that needs to do
/// something with the current segments file. This is
/// necessary with lock-less commits because from the time
/// you locate the current segments file name, until you
/// actually open it, read its contents, or check modified
/// time, etc., it could have been deleted due to a writer
/// commit finishing.
/// </summary>
public abstract class FindSegmentsFile
{
internal System.IO.FileInfo fileDirectory;
internal Directory directory;
public FindSegmentsFile(System.IO.FileInfo directory)
{
this.fileDirectory = directory;
}
public FindSegmentsFile(Directory directory)
{
this.directory = directory;
}
public System.Object run()
{
System.String segmentFileName = null;
long lastGen = - 1;
long gen = 0;
int genLookaheadCount = 0;
System.IO.IOException exc = null;
bool retry = false;
int method = 0;
// Loop until we succeed in calling doBody() without
// hitting an IOException. An IOException most likely
// means a commit was in process and has finished, in
// the time it took us to load the now-old infos files
// (and segments files). It's also possible it's a
// true error (corrupt index). To distinguish these,
// on each retry we must see "forward progress" on
// which generation we are trying to load. If we
// don't, then the original error is real and we throw
// it.
// We have three methods for determining the current
// generation. We try each in sequence.
while (true)
{
// Method 1: list the directory and use the highest
// segments_N file. This method works well as long
// as there is no stale caching on the directory
// contents:
System.String[] files = null;
if (0 == method)
{
if (directory != null)
{
files = directory.List();
}
else
{
files = System.IO.Directory.GetFileSystemEntries(fileDirectory.FullName);
for (int i = 0; i < files.Length; i++)
{
System.IO.FileInfo fi = new System.IO.FileInfo(files[i]);
files[i] = fi.Name;
}
}
gen = Lucene.Net.Index.SegmentInfos.GetCurrentSegmentGeneration(files);
if (gen == - 1)
{
System.String s = "";
for (int i = 0; i < files.Length; i++)
{
s += (" " + files[i]);
}
throw new System.IO.FileNotFoundException("no segments* file found: files:" + s);
}
}
// Method 2 (fallback if Method 1 isn't reliable):
// if the directory listing seems to be stale, then
// try loading the "segments.gen" file.
if (1 == method || (0 == method && lastGen == gen && retry))
{
method = 1;
for (int i = 0; i < Lucene.Net.Index.SegmentInfos.defaultGenFileRetryCount; i++)
{
IndexInput genInput = null;
try
{
genInput = directory.OpenInput(IndexFileNames.SEGMENTS_GEN);
}
catch (System.IO.IOException e)
{
Lucene.Net.Index.SegmentInfos.Message("segments.gen open: IOException " + e);
}
if (genInput != null)
{
try
{
int version = genInput.ReadInt();
if (version == Lucene.Net.Index.SegmentInfos.FORMAT_LOCKLESS)
{
long gen0 = genInput.ReadLong();
long gen1 = genInput.ReadLong();
Lucene.Net.Index.SegmentInfos.Message("fallback check: " + gen0 + "; " + gen1);
if (gen0 == gen1)
{
// The file is consistent.
if (gen0 > gen)
{
Lucene.Net.Index.SegmentInfos.Message("fallback to '" + IndexFileNames.SEGMENTS_GEN + "' check: now try generation " + gen0 + " > " + gen);
gen = gen0;
}
break;
}
}
}
catch (System.IO.IOException err2)
{
// will retry
}
finally
{
genInput.Close();
}
}
try
{
System.Threading.Thread.Sleep(new System.TimeSpan((System.Int64) 10000 * Lucene.Net.Index.SegmentInfos.defaultGenFileRetryPauseMsec));
}
catch (System.Threading.ThreadInterruptedException e)
{
// will retry
}
}
}
// Method 3 (fallback if Methods 2 & 3 are not
// reliable): since both directory cache and file
// contents cache seem to be stale, just advance the
// generation.
if (2 == method || (1 == method && lastGen == gen && retry))
{
method = 2;
if (genLookaheadCount < Lucene.Net.Index.SegmentInfos.defaultGenLookaheadCount)
{
gen++;
genLookaheadCount++;
Lucene.Net.Index.SegmentInfos.Message("look ahead increment gen to " + gen);
}
}
if (lastGen == gen)
{
// This means we're about to try the same
// segments_N last tried. This is allowed,
// exactly once, because writer could have been in
// the process of writing segments_N last time.
if (retry)
{
// OK, we've tried the same segments_N file
// twice in a row, so this must be a real
// error. We throw the original exception we
// got.
throw exc;
}
else
{
retry = true;
}
}
else
{
// Segment file has advanced since our last loop, so
// reset retry:
retry = false;
}
lastGen = gen;
segmentFileName = IndexFileNames.FileNameFromGeneration(IndexFileNames.SEGMENTS, "", gen);
try
{
System.Object v = DoBody(segmentFileName);
if (exc != null)
{
Lucene.Net.Index.SegmentInfos.Message("success on " + segmentFileName);
}
return v;
}
catch (System.IO.IOException err)
{
// Save the original root cause:
if (exc == null)
{
exc = err;
}
Lucene.Net.Index.SegmentInfos.Message("primary Exception on '" + segmentFileName + "': " + err + "'; will retry: retry=" + retry + "; gen = " + gen);
if (!retry && gen > 1)
{
// This is our first time trying this segments
// file (because retry is false), and, there is
// possibly a segments_(N-1) (because gen > 1).
// So, check if the segments_(N-1) exists and
// try it if so:
System.String prevSegmentFileName = IndexFileNames.FileNameFromGeneration(IndexFileNames.SEGMENTS, "", gen - 1);
if (directory.FileExists(prevSegmentFileName))
{
Lucene.Net.Index.SegmentInfos.Message("fallback to prior segment file '" + prevSegmentFileName + "'");
try
{
System.Object v = DoBody(prevSegmentFileName);
if (exc != null)
{
Lucene.Net.Index.SegmentInfos.Message("success on fallback " + prevSegmentFileName);
}
return v;
}
catch (System.IO.IOException err2)
{
Lucene.Net.Index.SegmentInfos.Message("secondary Exception on '" + prevSegmentFileName + "': " + err2 + "'; will retry");
}
}
}
}
}
}
/// <summary> Subclass must implement this. The assumption is an
/// IOException will be thrown if something goes wrong
/// during the processing that could have been caused by
/// a writer committing.
/// </summary>
public abstract System.Object DoBody(System.String segmentFileName);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -