blob: b23943500d705100a6da909b8e4e1ce1098b54dc [file] [log] [blame]
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
namespace Lucene.Net.Index
{
using System.Text.RegularExpressions;
/*
* 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 Codec = Lucene.Net.Codecs.Codec;
using Directory = Lucene.Net.Store.Directory;
using Lucene3xSegmentInfoFormat = Lucene.Net.Codecs.Lucene3x.Lucene3xSegmentInfoFormat;
using TrackingDirectoryWrapper = Lucene.Net.Store.TrackingDirectoryWrapper;
/// <summary>
/// Information about a segment such as it's name, directory, and files related
/// to the segment.
///
/// @lucene.experimental
/// </summary>
public sealed class SegmentInfo
{
// TODO: remove these from this class, for now this is the representation
/// <summary>
/// Used by some member fields to mean not present (e.g.,
/// norms, deletions).
/// </summary>
public const int NO = -1; // e.g. no norms; no deletes;
/// <summary>
/// Used by some member fields to mean present (e.g.,
/// norms, deletions).
/// </summary>
public const int YES = 1; // e.g. have norms; have deletes;
/// <summary>
/// Unique segment name in the directory. </summary>
public readonly string Name;
private int DocCount_Renamed; // number of docs in seg
/// <summary>
/// Where this segment resides. </summary>
public readonly Directory Dir;
private bool IsCompoundFile;
private Codec Codec_Renamed;
private IDictionary<string, string> Diagnostics_Renamed;
/// @deprecated not used anymore
[Obsolete("not used anymore")]
private IDictionary<string, string> Attributes_Renamed;
// Tracks the Lucene version this segment was created with, since 3.1. Null
// indicates an older than 3.0 index, and it's used to detect a too old index.
// The format expected is "x.y" - "2.x" for pre-3.0 indexes (or null), and
// specific versions afterwards ("3.0", "3.1" etc.).
// see Constants.LUCENE_MAIN_VERSION.
private string Version_Renamed;
public IDictionary<string, string> Diagnostics
{
set
{
this.Diagnostics_Renamed = value;
}
get
{
return Diagnostics_Renamed;
}
}
/// <summary>
/// Construct a new complete SegmentInfo instance from input.
/// <p>Note: this is public only to allow access from
/// the codecs package.</p>
/// </summary>
public SegmentInfo(Directory dir, string version, string name, int docCount, bool isCompoundFile, Codec codec, IDictionary<string, string> diagnostics)
: this(dir, version, name, docCount, isCompoundFile, codec, diagnostics, null)
{
}
/// <summary>
/// Construct a new complete SegmentInfo instance from input.
/// <p>Note: this is public only to allow access from
/// the codecs package.</p>
/// </summary>
public SegmentInfo(Directory dir, string version, string name, int docCount, bool isCompoundFile, Codec codec, IDictionary<string, string> diagnostics, IDictionary<string, string> attributes)
{
Debug.Assert(!(dir is TrackingDirectoryWrapper));
this.Dir = dir;
this.Version_Renamed = version;
this.Name = name;
this.DocCount_Renamed = docCount;
this.IsCompoundFile = isCompoundFile;
this.Codec_Renamed = codec;
this.Diagnostics_Renamed = diagnostics;
this.Attributes_Renamed = attributes;
}
/// @deprecated separate norms are not supported in >= 4.0
[Obsolete("separate norms are not supported in >= 4.0")]
internal bool HasSeparateNorms()
{
return GetAttribute(Lucene3xSegmentInfoFormat.NORMGEN_KEY) != null;
}
/// <summary>
/// Mark whether this segment is stored as a compound file.
/// </summary>
/// <param name="isCompoundFile"> true if this is a compound file;
/// else, false </param>
public bool UseCompoundFile
{
set
{
this.IsCompoundFile = value;
}
get
{
return IsCompoundFile;
}
}
/// <summary>
/// Can only be called once. </summary>
public Codec Codec
{
set
{
Debug.Assert(this.Codec_Renamed == null);
if (value == null)
{
throw new System.ArgumentException("codec must be non-null");
}
this.Codec_Renamed = value;
}
get
{
return Codec_Renamed;
}
}
/// <summary>
/// Returns number of documents in this segment (deletions
/// are not taken into account).
/// </summary>
public int DocCount
{
get
{
if (this.DocCount_Renamed == -1)
{
throw new InvalidOperationException("docCount isn't set yet");
}
return DocCount_Renamed;
}
set
{
if (this.DocCount_Renamed != -1)
{
throw new InvalidOperationException("docCount was already set");
}
this.DocCount_Renamed = value;
}
}
// NOTE: leave package private
/// <summary>
/// Return all files referenced by this SegmentInfo. </summary>
public override string ToString()
{
return ToString(Dir, 0);
}
/// <summary>
/// Used for debugging. Format may suddenly change.
///
/// <p>Current format looks like
/// <code>_a(3.1):c45/4</code>, which means the segment's
/// name is <code>_a</code>; it was created with Lucene 3.1 (or
/// '?' if it's unknown); it's using compound file
/// format (would be <code>C</code> if not compound); it
/// has 45 documents; it has 4 deletions (this part is
/// left off when there are no deletions).</p>
/// </summary>
public string ToString(Directory dir, int delCount)
{
StringBuilder s = new StringBuilder();
s.Append(Name).Append('(').Append(Version_Renamed == null ? "?" : Version_Renamed).Append(')').Append(':');
char cfs = UseCompoundFile ? 'c' : 'C';
s.Append(cfs);
if (this.Dir != dir)
{
s.Append('x');
}
s.Append(DocCount_Renamed);
if (delCount != 0)
{
s.Append('/').Append(delCount);
}
// TODO: we could append toString of attributes() here?
return s.ToString();
}
/// <summary>
/// We consider another SegmentInfo instance equal if it
/// has the same dir and same name.
/// </summary>
public override bool Equals(object obj)
{
if (this == obj)
{
return true;
}
if (obj is SegmentInfo)
{
SegmentInfo other = (SegmentInfo)obj;
return other.Dir == Dir && other.Name.Equals(Name);
}
else
{
return false;
}
}
public override int GetHashCode()
{
return Dir.GetHashCode() + Name.GetHashCode();
}
/// <summary>
/// Used by DefaultSegmentInfosReader to upgrade a 3.0 segment to record its
/// version is "3.0". this method can be removed when we're not required to
/// support 3x indexes anymore, e.g. in 5.0.
/// <p>
/// <b>NOTE:</b> this method is used for internal purposes only - you should
/// not modify the version of a SegmentInfo, or it may result in unexpected
/// exceptions thrown when you attempt to open the index.
///
/// @lucene.internal
/// </summary>
public string Version
{
set
{
this.Version_Renamed = value;
}
get
{
return Version_Renamed;
}
}
private ISet<string> SetFiles;
/// <summary>
/// Sets the files written for this segment. </summary>
public ISet<string> Files
{
get
{
if (SetFiles == null)
{
throw new InvalidOperationException("files were not computed yet");
}
return SetFiles;//CollectionsHelper.UnmodifiableSet(SetFiles);
}
set
{
CheckFileNames(value);
SetFiles = value;
}
}
/// <summary>
/// Add these files to the set of files written for this
/// segment.
/// </summary>
public void AddFiles(ICollection<string> files)
{
CheckFileNames(files);
//SetFiles.AddAll(files);
SetFiles.UnionWith(files);
}
/// <summary>
/// Add this file to the set of files written for this
/// segment.
/// </summary>
public void AddFile(string file)
{
//CheckFileNames(Collections.Singleton(file));
CheckFileNames(new[] { file });
SetFiles.Add(file);
}
private void CheckFileNames(ICollection<string> files)
{
Regex r = IndexFileNames.CODEC_FILE_PATTERN;
foreach (string file in files)
{
if (!r.IsMatch(file))
{
throw new System.ArgumentException("invalid codec filename '" + file + "', must match: " + IndexFileNames.CODEC_FILE_PATTERN.ToString());
}
}
}
/// <summary>
/// Get a codec attribute value, or null if it does not exist
/// </summary>
/// @deprecated no longer supported
[Obsolete("no longer supported")]
public string GetAttribute(string key)
{
if (Attributes_Renamed == null)
{
return null;
}
else
{
return Attributes_Renamed[key];
}
}
/// <summary>
/// Puts a codec attribute value.
/// <p>
/// this is a key-value mapping for the field that the codec can use to store
/// additional metadata, and will be available to the codec when reading the
/// segment via <seealso cref="#getAttribute(String)"/>
/// <p>
/// If a value already exists for the field, it will be replaced with the new
/// value.
/// </summary>
/// @deprecated no longer supported
[Obsolete("no longer supported")]
public string PutAttribute(string key, string value)
{
if (Attributes_Renamed == null)
{
Attributes_Renamed = new Dictionary<string, string>();
}
return Attributes_Renamed[key] = value;
}
/// <summary>
/// Returns the internal codec attributes map.
/// </summary>
/// <returns> internal codec attributes map. May be null if no mappings exist.
/// </returns>
/// @deprecated no longer supported
[Obsolete("no longer supported")]
public IDictionary<string, string> Attributes()
{
return Attributes_Renamed;
}
}
}