📄 segmentinfos.cs
字号:
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using Directory = Lucene.Net.Store.Directory;
using IndexInput = Lucene.Net.Store.IndexInput;
using IndexOutput = Lucene.Net.Store.IndexOutput;
namespace Lucene.Net.Index
{
[Serializable]
public sealed class SegmentInfos : System.Collections.ArrayList
{
private class AnonymousClassFindSegmentsFile:FindSegmentsFile
{
private void InitBlock(SegmentInfos enclosingInstance)
{
this.enclosingInstance = enclosingInstance;
}
private SegmentInfos enclosingInstance;
public SegmentInfos Enclosing_Instance
{
get
{
return enclosingInstance;
}
}
internal AnonymousClassFindSegmentsFile(SegmentInfos enclosingInstance, Lucene.Net.Store.Directory Param1):base(Param1)
{
InitBlock(enclosingInstance);
}
public override System.Object DoBody(System.String segmentFileName)
{
Enclosing_Instance.Read(directory, segmentFileName);
return null;
}
}
private class AnonymousClassFindSegmentsFile1:FindSegmentsFile
{
internal AnonymousClassFindSegmentsFile1(Lucene.Net.Store.Directory Param1):base(Param1)
{
}
public override System.Object DoBody(System.String segmentFileName)
{
IndexInput input = directory.OpenInput(segmentFileName);
int format = 0;
long version = 0;
try
{
format = input.ReadInt();
if (format < 0)
{
if (format < Lucene.Net.Index.SegmentInfos.FORMAT_SINGLE_NORM_FILE)
throw new System.IO.IOException("Unknown format version: " + format);
version = input.ReadLong(); // read version
}
}
finally
{
input.Close();
}
if (format < 0)
return (long) version;
// We cannot be sure about the format of the file.
// Therefore we have to read the whole file and cannot simply seek to the version entry.
SegmentInfos sis = new SegmentInfos();
sis.Read(directory, segmentFileName);
return (long) sis.GetVersion();
}
}
/// <summary>The file format version, a negative number. </summary>
/* Works since counter, the old 1st entry, is always >= 0 */
public const int FORMAT = - 1;
/// <summary>This format adds details used for lockless commits. It differs
/// slightly from the previous format in that file names
/// are never re-used (write once). Instead, each file is
/// written to the next generation. For example,
/// segments_1, segments_2, etc. This allows us to not use
/// a commit lock. See <a
/// href="http://lucene.apache.org/java/docs/fileformats.html">file
/// formats</a> for details.
/// </summary>
public const int FORMAT_LOCKLESS = - 2;
/// <summary>This is the current file format written. It adds a
/// "hasSingleNormFile" flag into each segment info.
/// See <a href="http://issues.apache.org/jira/browse/LUCENE-756">LUCENE-756</a>
/// for details.
/// </summary>
public const int FORMAT_SINGLE_NORM_FILE = - 3;
public int counter = 0; // used to name new segments
/// <summary> counts how often the index has been changed by adding or deleting docs.
/// starting with the current time in milliseconds forces to create unique version numbers.
/// </summary>
private long version = System.DateTime.Now.Millisecond;
private long generation = 0; // generation of the "segments_N" for the next commit
private long lastGeneration = 0; // generation of the "segments_N" file we last successfully read
// or wrote; this is normally the same as generation except if
// there was an IOException that had interrupted a commit
/// <summary> If non-null, information about loading segments_N files</summary>
/// <seealso cref="#setInfoStream.">
/// </seealso>
private static System.IO.TextWriter infoStream;
public SegmentInfo Info(int i)
{
return (SegmentInfo) this[i];
}
/// <summary> Get the generation (N) of the current segments_N file
/// from a list of files.
///
/// </summary>
/// <param name="files">-- array of file names to check
/// </param>
public static long GetCurrentSegmentGeneration(System.String[] files)
{
if (files == null)
{
return - 1;
}
long max = - 1;
int prefixLen = IndexFileNames.SEGMENTS.Length + 1;
for (int i = 0; i < files.Length; i++)
{
System.String file = files[i];
if (file.StartsWith(IndexFileNames.SEGMENTS) && !file.Equals(IndexFileNames.SEGMENTS_GEN))
{
if (file.Equals(IndexFileNames.SEGMENTS))
{
// Pre lock-less commits:
if (max == - 1)
{
max = 0;
}
}
else
{
long v = System.Convert.ToInt64(file.Substring(prefixLen), 16);
if (v > max)
{
max = v;
}
}
}
}
return max;
}
/// <summary> Get the generation (N) of the current segments_N file
/// in the directory.
///
/// </summary>
/// <param name="directory">-- directory to search for the latest segments_N file
/// </param>
public static long GetCurrentSegmentGeneration(Directory directory)
{
System.String[] files = directory.List();
if (files == null)
{
throw new System.IO.IOException("Cannot read directory " + directory);
}
return GetCurrentSegmentGeneration(files);
}
/// <summary> Get the filename of the current segments_N file
/// from a list of files.
///
/// </summary>
/// <param name="files">-- array of file names to check
/// </param>
public static System.String GetCurrentSegmentFileName(System.String[] files)
{
return IndexFileNames.FileNameFromGeneration(IndexFileNames.SEGMENTS, "", GetCurrentSegmentGeneration(files));
}
/// <summary> Get the filename of the current segments_N file
/// in the directory.
///
/// </summary>
/// <param name="directory">-- directory to search for the latest segments_N file
/// </param>
public static System.String GetCurrentSegmentFileName(Directory directory)
{
return IndexFileNames.FileNameFromGeneration(IndexFileNames.SEGMENTS, "", GetCurrentSegmentGeneration(directory));
}
/// <summary> Get the segments_N filename in use by this segment infos.</summary>
public System.String GetCurrentSegmentFileName()
{
return IndexFileNames.FileNameFromGeneration(IndexFileNames.SEGMENTS, "", lastGeneration);
}
/// <summary> Get the next segments_N filename that will be written.</summary>
public System.String GetNextSegmentFileName()
{
long nextGeneration;
if (generation == - 1)
{
nextGeneration = 1;
}
else
{
nextGeneration = generation + 1;
}
return IndexFileNames.FileNameFromGeneration(IndexFileNames.SEGMENTS, "", nextGeneration);
}
/// <summary> Read a particular segmentFileName. Note that this may
/// throw an IOException if a commit is in process.
///
/// </summary>
/// <param name="directory">-- directory containing the segments file
/// </param>
/// <param name="segmentFileName">-- segment file to load
/// </param>
public void Read(Directory directory, System.String segmentFileName)
{
bool success = false;
IndexInput input = directory.OpenInput(segmentFileName);
if (segmentFileName.Equals(IndexFileNames.SEGMENTS))
{
generation = 0;
}
else
{
generation = System.Convert.ToInt64(segmentFileName.Substring(1 + IndexFileNames.SEGMENTS.Length), 16);
}
lastGeneration = generation;
try
{
int format = input.ReadInt();
if (format < 0)
{
// file contains explicit format info
// check that it is a format we can understand
if (format < FORMAT_SINGLE_NORM_FILE)
throw new System.IO.IOException("Unknown format version: " + format);
version = input.ReadLong(); // read version
counter = input.ReadInt(); // read counter
}
else
{
// file is in old format without explicit format info
counter = format;
}
for (int i = input.ReadInt(); i > 0; i--)
{
// read segmentInfos
Add(new SegmentInfo(directory, format, input));
}
if (format >= 0)
{
// in old format the version number may be at the end of the file
if (input.GetFilePointer() >= input.Length())
version = System.DateTime.Now.Millisecond;
// old file format without version number
else
version = input.ReadLong(); // read version
}
success = true;
}
finally
{
input.Close();
if (!success)
{
// Clear any segment infos we had loaded so we
// have a clean slate on retry:
Clear();
}
}
}
/// <summary> This version of read uses the retry logic (for lock-less
/// commits) to find the right segments file to load.
/// </summary>
public void Read(Directory directory)
{
generation = lastGeneration = - 1;
new AnonymousClassFindSegmentsFile(this, directory).run();
}
public void Write(Directory directory)
{
System.String segmentFileName = GetNextSegmentFileName();
// Always advance the generation on write:
if (generation == - 1)
{
generation = 1;
}
else
{
generation++;
}
IndexOutput output = directory.CreateOutput(segmentFileName);
try
{
output.WriteInt(FORMAT_SINGLE_NORM_FILE); // write FORMAT
output.WriteLong(++version); // every write changes
// the index
output.WriteInt(counter); // write counter
output.WriteInt(Count); // write infos
for (int i = 0; i < Count; i++)
{
Info(i).Write(output);
}
}
finally
{
output.Close();
}
try
{
output = directory.CreateOutput(IndexFileNames.SEGMENTS_GEN);
try
{
output.WriteInt(FORMAT_LOCKLESS);
output.WriteLong(generation);
output.WriteLong(generation);
}
finally
{
output.Close();
}
}
catch (System.IO.IOException e)
{
// It's OK if we fail to write this file since it's
// used only as one of the retry fallbacks.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -