Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/Lucene.Net.Light.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/Index/IndexReader.cs')
-rw-r--r--src/core/Index/IndexReader.cs1374
1 files changed, 1374 insertions, 0 deletions
diff --git a/src/core/Index/IndexReader.cs b/src/core/Index/IndexReader.cs
new file mode 100644
index 0000000..5c3bd9b
--- /dev/null
+++ b/src/core/Index/IndexReader.cs
@@ -0,0 +1,1374 @@
+/*
+ * 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 System.Collections.Generic;
+using Lucene.Net.Documents;
+using Document = Lucene.Net.Documents.Document;
+using FieldSelector = Lucene.Net.Documents.FieldSelector;
+using Lucene.Net.Store;
+using Similarity = Lucene.Net.Search.Similarity;
+
+namespace Lucene.Net.Index
+{
+
+ /// <summary>IndexReader is an abstract class, providing an interface for accessing an
+ /// index. Search of an index is done entirely through this abstract interface,
+ /// so that any subclass which implements it is searchable.
+ /// <p/> Concrete subclasses of IndexReader are usually constructed with a call to
+ /// one of the static <c>open()</c> methods, e.g. <see cref="Open(Lucene.Net.Store.Directory, bool)" />
+ ///.
+ /// <p/> For efficiency, in this API documents are often referred to via
+ /// <i>document numbers</i>, non-negative integers which each name a unique
+ /// document in the index. These document numbers are ephemeral--they may change
+ /// as documents are added to and deleted from an index. Clients should thus not
+ /// rely on a given document having the same number between sessions.
+ /// <p/> An IndexReader can be opened on a directory for which an IndexWriter is
+ /// opened already, but it cannot be used to delete documents from the index then.
+ /// <p/>
+ /// <b>NOTE</b>: for backwards API compatibility, several methods are not listed
+ /// as abstract, but have no useful implementations in this base class and
+ /// instead always throw UnsupportedOperationException. Subclasses are
+ /// strongly encouraged to override these methods, but in many cases may not
+ /// need to.
+ /// <p/>
+ /// <p/>
+ /// <b>NOTE</b>: as of 2.4, it's possible to open a read-only
+ /// IndexReader using the static open methods that accepts the
+ /// boolean readOnly parameter. Such a reader has better
+ /// better concurrency as it's not necessary to synchronize on the
+ /// isDeleted method. You must explicitly specify false
+ /// if you want to make changes with the resulting IndexReader.
+ /// <p/>
+ /// <a name="thread-safety"></a><p/><b>NOTE</b>: <see cref="IndexReader" />
+ /// instances are completely thread
+ /// safe, meaning multiple threads can call any of its methods,
+ /// concurrently. If your application requires external
+ /// synchronization, you should <b>not</b> synchronize on the
+ /// <c>IndexReader</c> instance; use your own
+ /// (non-Lucene) objects instead.
+ /// </summary>
+ public abstract class IndexReader : System.ICloneable, System.IDisposable
+ {
+ private class AnonymousClassFindSegmentsFile : SegmentInfos.FindSegmentsFile
+ {
+ private void InitBlock(Lucene.Net.Store.Directory directory2)
+ {
+ this.directory2 = directory2;
+ }
+ private Lucene.Net.Store.Directory directory2;
+ internal AnonymousClassFindSegmentsFile(Lucene.Net.Store.Directory directory2, Lucene.Net.Store.Directory Param1):base(Param1)
+ {
+ InitBlock(directory2);
+ }
+ public override System.Object DoBody(System.String segmentFileName)
+ {
+ return (long) directory2.FileModified(segmentFileName);
+ }
+ }
+
+ /// <summary> Constants describing field properties, for example used for
+ /// <see cref="IndexReader.GetFieldNames(FieldOption)" />.
+ /// </summary>
+ public sealed class FieldOption
+ {
+ private readonly System.String option;
+ internal FieldOption()
+ {
+ }
+ internal FieldOption(System.String option)
+ {
+ this.option = option;
+ }
+ public override System.String ToString()
+ {
+ return this.option;
+ }
+ /// <summary>All fields </summary>
+ public static readonly FieldOption ALL = new FieldOption("ALL");
+ /// <summary>All indexed fields </summary>
+ public static readonly FieldOption INDEXED = new FieldOption("INDEXED");
+ /// <summary>All fields that store payloads </summary>
+ public static readonly FieldOption STORES_PAYLOADS = new FieldOption("STORES_PAYLOADS");
+ /// <summary>All fields that omit tf </summary>
+ public static readonly FieldOption OMIT_TERM_FREQ_AND_POSITIONS = new FieldOption("OMIT_TERM_FREQ_AND_POSITIONS");
+ /// <summary>All fields which are not indexed </summary>
+ public static readonly FieldOption UNINDEXED = new FieldOption("UNINDEXED");
+ /// <summary>All fields which are indexed with termvectors enabled </summary>
+ public static readonly FieldOption INDEXED_WITH_TERMVECTOR = new FieldOption("INDEXED_WITH_TERMVECTOR");
+ /// <summary>All fields which are indexed but don't have termvectors enabled </summary>
+ public static readonly FieldOption INDEXED_NO_TERMVECTOR = new FieldOption("INDEXED_NO_TERMVECTOR");
+ /// <summary>All fields with termvectors enabled. Please note that only standard termvector fields are returned </summary>
+ public static readonly FieldOption TERMVECTOR = new FieldOption("TERMVECTOR");
+ /// <summary>All fields with termvectors with position values enabled </summary>
+ public static readonly FieldOption TERMVECTOR_WITH_POSITION = new FieldOption("TERMVECTOR_WITH_POSITION");
+ /// <summary>All fields with termvectors with offset values enabled </summary>
+ public static readonly FieldOption TERMVECTOR_WITH_OFFSET = new FieldOption("TERMVECTOR_WITH_OFFSET");
+ /// <summary>All fields with termvectors with offset values and position values enabled </summary>
+ public static readonly FieldOption TERMVECTOR_WITH_POSITION_OFFSET = new FieldOption("TERMVECTOR_WITH_POSITION_OFFSET");
+ }
+
+ private bool closed;
+ protected internal bool hasChanges;
+
+ private int refCount;
+
+ protected internal static int DEFAULT_TERMS_INDEX_DIVISOR = 1;
+
+ /// <summary>Expert: returns the current refCount for this reader </summary>
+ public virtual int RefCount
+ {
+ get
+ {
+ lock (this)
+ {
+ return refCount;
+ }
+ }
+ }
+
+ /// <summary> Expert: increments the refCount of this IndexReader
+ /// instance. RefCounts are used to determine when a
+ /// reader can be closed safely, i.e. as soon as there are
+ /// no more references. Be sure to always call a
+ /// corresponding <see cref="DecRef" />, in a finally clause;
+ /// otherwise the reader may never be closed. Note that
+ /// <see cref="Close" /> simply calls decRef(), which means that
+ /// the IndexReader will not really be closed until <see cref="DecRef" />
+ /// has been called for all outstanding
+ /// references.
+ ///
+ /// </summary>
+ /// <seealso cref="DecRef">
+ /// </seealso>
+ public virtual void IncRef()
+ {
+ lock (this)
+ {
+ System.Diagnostics.Debug.Assert(refCount > 0);
+ EnsureOpen();
+ refCount++;
+ }
+ }
+
+ /// <summary> Expert: decreases the refCount of this IndexReader
+ /// instance. If the refCount drops to 0, then pending
+ /// changes (if any) are committed to the index and this
+ /// reader is closed.
+ ///
+ /// </summary>
+ /// <throws> IOException in case an IOException occurs in commit() or doClose() </throws>
+ /// <summary>
+ /// </summary>
+ /// <seealso cref="IncRef">
+ /// </seealso>
+ public virtual void DecRef()
+ {
+ lock (this)
+ {
+ System.Diagnostics.Debug.Assert(refCount > 0);
+ EnsureOpen();
+ if (refCount == 1)
+ {
+ Commit();
+ DoClose();
+ }
+ refCount--;
+ }
+ }
+
+ protected internal IndexReader()
+ {
+ refCount = 1;
+ }
+
+ /// <throws> AlreadyClosedException if this IndexReader is closed </throws>
+ protected internal void EnsureOpen()
+ {
+ if (refCount <= 0)
+ {
+ throw new AlreadyClosedException("this IndexReader is closed");
+ }
+ }
+
+ /// <summary>Returns an IndexReader reading the index in the given
+ /// Directory. You should pass readOnly=true, since it
+ /// gives much better concurrent performance, unless you
+ /// intend to do write operations (delete documents or
+ /// change norms) with the reader.
+ /// </summary>
+ /// <param name="directory">the index directory</param>
+ /// <param name="readOnly">true if no changes (deletions, norms) will be made with this IndexReader</param>
+ /// <exception cref="CorruptIndexException">CorruptIndexException if the index is corrupt</exception>
+ /// <exception cref="System.IO.IOException">IOException if there is a low-level IO error</exception>
+ public static IndexReader Open(Directory directory, bool readOnly)
+ {
+ return Open(directory, null, null, readOnly, DEFAULT_TERMS_INDEX_DIVISOR);
+ }
+
+ /// <summary>Expert: returns an IndexReader reading the index in the given
+ /// <see cref="IndexCommit" />. You should pass readOnly=true, since it
+ /// gives much better concurrent performance, unless you
+ /// intend to do write operations (delete documents or
+ /// change norms) with the reader.
+ /// </summary>
+ /// <param name="commit">the commit point to open
+ /// </param>
+ /// <param name="readOnly">true if no changes (deletions, norms) will be made with this IndexReader
+ /// </param>
+ /// <throws> CorruptIndexException if the index is corrupt </throws>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public static IndexReader Open(IndexCommit commit, bool readOnly)
+ {
+ return Open(commit.Directory, null, commit, readOnly, DEFAULT_TERMS_INDEX_DIVISOR);
+ }
+
+ /// <summary>Expert: returns an IndexReader reading the index in
+ /// the given Directory, with a custom <see cref="IndexDeletionPolicy" />
+ ///. You should pass readOnly=true,
+ /// since it gives much better concurrent performance,
+ /// unless you intend to do write operations (delete
+ /// documents or change norms) with the reader.
+ /// </summary>
+ /// <param name="directory">the index directory
+ /// </param>
+ /// <param name="deletionPolicy">a custom deletion policy (only used
+ /// if you use this reader to perform deletes or to set
+ /// norms); see <see cref="IndexWriter" /> for details.
+ /// </param>
+ /// <param name="readOnly">true if no changes (deletions, norms) will be made with this IndexReader
+ /// </param>
+ /// <throws> CorruptIndexException if the index is corrupt </throws>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public static IndexReader Open(Directory directory, IndexDeletionPolicy deletionPolicy, bool readOnly)
+ {
+ return Open(directory, deletionPolicy, null, readOnly, DEFAULT_TERMS_INDEX_DIVISOR);
+ }
+
+ /// <summary>Expert: returns an IndexReader reading the index in
+ /// the given Directory, with a custom <see cref="IndexDeletionPolicy" />
+ ///. You should pass readOnly=true,
+ /// since it gives much better concurrent performance,
+ /// unless you intend to do write operations (delete
+ /// documents or change norms) with the reader.
+ /// </summary>
+ /// <param name="directory">the index directory
+ /// </param>
+ /// <param name="deletionPolicy">a custom deletion policy (only used
+ /// if you use this reader to perform deletes or to set
+ /// norms); see <see cref="IndexWriter" /> for details.
+ /// </param>
+ /// <param name="readOnly">true if no changes (deletions, norms) will be made with this IndexReader
+ /// </param>
+ /// <param name="termInfosIndexDivisor">Subsamples which indexed
+ /// terms are loaded into RAM. This has the same effect as <see>
+ /// <cref>IndexWriter.SetTermIndexInterval</cref>
+ /// </see> except that setting
+ /// must be done at indexing time while this setting can be
+ /// set per reader. When set to N, then one in every
+ /// N*termIndexInterval terms in the index is loaded into
+ /// memory. By setting this to a value > 1 you can reduce
+ /// memory usage, at the expense of higher latency when
+ /// loading a TermInfo. The default value is 1. Set this
+ /// to -1 to skip loading the terms index entirely.
+ /// </param>
+ /// <throws> CorruptIndexException if the index is corrupt </throws>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public static IndexReader Open(Directory directory, IndexDeletionPolicy deletionPolicy, bool readOnly, int termInfosIndexDivisor)
+ {
+ return Open(directory, deletionPolicy, null, readOnly, termInfosIndexDivisor);
+ }
+
+ /// <summary>Expert: returns an IndexReader reading the index in
+ /// the given Directory, using a specific commit and with
+ /// a custom <see cref="IndexDeletionPolicy" />. You should pass
+ /// readOnly=true, since it gives much better concurrent
+ /// performance, unless you intend to do write operations
+ /// (delete documents or change norms) with the reader.
+ /// </summary>
+ /// <param name="commit">the specific <see cref="IndexCommit" /> to open;
+ /// see <see cref="IndexReader.ListCommits" /> to list all commits
+ /// in a directory
+ /// </param>
+ /// <param name="deletionPolicy">a custom deletion policy (only used
+ /// if you use this reader to perform deletes or to set
+ /// norms); see <see cref="IndexWriter" /> for details.
+ /// </param>
+ /// <param name="readOnly">true if no changes (deletions, norms) will be made with this IndexReader
+ /// </param>
+ /// <throws> CorruptIndexException if the index is corrupt </throws>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public static IndexReader Open(IndexCommit commit, IndexDeletionPolicy deletionPolicy, bool readOnly)
+ {
+ return Open(commit.Directory, deletionPolicy, commit, readOnly, DEFAULT_TERMS_INDEX_DIVISOR);
+ }
+
+ /// <summary>Expert: returns an IndexReader reading the index in
+ /// the given Directory, using a specific commit and with
+ /// a custom <see cref="IndexDeletionPolicy" />. You should pass
+ /// readOnly=true, since it gives much better concurrent
+ /// performance, unless you intend to do write operations
+ /// (delete documents or change norms) with the reader.
+ /// </summary>
+ /// <param name="commit">the specific <see cref="IndexCommit" /> to open;
+ /// see <see cref="IndexReader.ListCommits" /> to list all commits
+ /// in a directory
+ /// </param>
+ /// <param name="deletionPolicy">a custom deletion policy (only used
+ /// if you use this reader to perform deletes or to set
+ /// norms); see <see cref="IndexWriter" /> for details.
+ /// </param>
+ /// <param name="readOnly">true if no changes (deletions, norms) will be made with this IndexReader
+ /// </param>
+ /// <param name="termInfosIndexDivisor">Subsambles which indexed
+ /// terms are loaded into RAM. This has the same effect as <see>
+ /// <cref>IndexWriter.SetTermIndexInterval</cref>
+ /// </see> except that setting
+ /// must be done at indexing time while this setting can be
+ /// set per reader. When set to N, then one in every
+ /// N*termIndexInterval terms in the index is loaded into
+ /// memory. By setting this to a value > 1 you can reduce
+ /// memory usage, at the expense of higher latency when
+ /// loading a TermInfo. The default value is 1. Set this
+ /// to -1 to skip loading the terms index entirely.
+ /// </param>
+ /// <throws> CorruptIndexException if the index is corrupt </throws>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public static IndexReader Open(IndexCommit commit, IndexDeletionPolicy deletionPolicy, bool readOnly, int termInfosIndexDivisor)
+ {
+ return Open(commit.Directory, deletionPolicy, commit, readOnly, termInfosIndexDivisor);
+ }
+
+ private static IndexReader Open(Directory directory, IndexDeletionPolicy deletionPolicy, IndexCommit commit, bool readOnly, int termInfosIndexDivisor)
+ {
+ return DirectoryReader.Open(directory, deletionPolicy, commit, readOnly, termInfosIndexDivisor);
+ }
+
+ /// <summary> Refreshes an IndexReader if the index has changed since this instance
+ /// was (re)opened.
+ /// <p/>
+ /// Opening an IndexReader is an expensive operation. This method can be used
+ /// to refresh an existing IndexReader to reduce these costs. This method
+ /// tries to only load segments that have changed or were created after the
+ /// IndexReader was (re)opened.
+ /// <p/>
+ /// If the index has not changed since this instance was (re)opened, then this
+ /// call is a NOOP and returns this instance. Otherwise, a new instance is
+ /// returned. The old instance is <b>not</b> closed and remains usable.<br/>
+ /// <p/>
+ /// If the reader is reopened, even though they share
+ /// resources internally, it's safe to make changes
+ /// (deletions, norms) with the new reader. All shared
+ /// mutable state obeys "copy on write" semantics to ensure
+ /// the changes are not seen by other readers.
+ /// <p/>
+ /// You can determine whether a reader was actually reopened by comparing the
+ /// old instance with the instance returned by this method:
+ /// <code>
+ /// IndexReader reader = ...
+ /// ...
+ /// IndexReader newReader = r.reopen();
+ /// if (newReader != reader) {
+ /// ... // reader was reopened
+ /// reader.close();
+ /// }
+ /// reader = newReader;
+ /// ...
+ /// </code>
+ ///
+ /// Be sure to synchronize that code so that other threads,
+ /// if present, can never use reader after it has been
+ /// closed and before it's switched to newReader.
+ ///
+ /// <p/><b>NOTE</b>: If this reader is a near real-time
+ /// reader (obtained from <see cref="IndexWriter.GetReader()" />,
+ /// reopen() will simply call writer.getReader() again for
+ /// you, though this may change in the future.
+ ///
+ /// </summary>
+ /// <throws> CorruptIndexException if the index is corrupt </throws>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public virtual IndexReader Reopen()
+ {
+ lock (this)
+ {
+ throw new NotSupportedException("This reader does not support reopen().");
+ }
+ }
+
+
+ /// <summary>Just like <see cref="Reopen()" />, except you can change the
+ /// readOnly of the original reader. If the index is
+ /// unchanged but readOnly is different then a new reader
+ /// will be returned.
+ /// </summary>
+ public virtual IndexReader Reopen(bool openReadOnly)
+ {
+ lock (this)
+ {
+ throw new NotSupportedException("This reader does not support reopen().");
+ }
+ }
+
+ /// <summary>Expert: reopen this reader on a specific commit point.
+ /// This always returns a readOnly reader. If the
+ /// specified commit point matches what this reader is
+ /// already on, and this reader is already readOnly, then
+ /// this same instance is returned; if it is not already
+ /// readOnly, a readOnly clone is returned.
+ /// </summary>
+ public virtual IndexReader Reopen(IndexCommit commit)
+ {
+ lock (this)
+ {
+ throw new NotSupportedException("This reader does not support reopen(IndexCommit).");
+ }
+ }
+
+ /// <summary> Efficiently clones the IndexReader (sharing most
+ /// internal state).
+ /// <p/>
+ /// On cloning a reader with pending changes (deletions,
+ /// norms), the original reader transfers its write lock to
+ /// the cloned reader. This means only the cloned reader
+ /// may make further changes to the index, and commit the
+ /// changes to the index on close, but the old reader still
+ /// reflects all changes made up until it was cloned.
+ /// <p/>
+ /// Like <see cref="Reopen()" />, it's safe to make changes to
+ /// either the original or the cloned reader: all shared
+ /// mutable state obeys "copy on write" semantics to ensure
+ /// the changes are not seen by other readers.
+ /// <p/>
+ /// </summary>
+ /// <throws> CorruptIndexException if the index is corrupt </throws>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public virtual System.Object Clone()
+ {
+ throw new System.NotSupportedException("This reader does not implement clone()");
+ }
+
+ /// <summary> Clones the IndexReader and optionally changes readOnly. A readOnly
+ /// reader cannot open a writeable reader.
+ /// </summary>
+ /// <throws> CorruptIndexException if the index is corrupt </throws>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public virtual IndexReader Clone(bool openReadOnly)
+ {
+ lock (this)
+ {
+ throw new System.NotSupportedException("This reader does not implement clone()");
+ }
+ }
+
+ /// <summary> Returns the directory associated with this index. The Default
+ /// implementation returns the directory specified by subclasses when
+ /// delegating to the IndexReader(Directory) constructor, or throws an
+ /// UnsupportedOperationException if one was not specified.
+ /// </summary>
+ /// <throws> UnsupportedOperationException if no directory </throws>
+ public virtual Directory Directory()
+ {
+ EnsureOpen();
+ throw new NotSupportedException("This reader does not support this method.");
+ }
+
+ /// <summary> Returns the time the index in the named directory was last modified.
+ /// Do not use this to check whether the reader is still up-to-date, use
+ /// <see cref="IsCurrent()" /> instead.
+ /// </summary>
+ /// <throws> CorruptIndexException if the index is corrupt </throws>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public static long LastModified(Directory directory2)
+ {
+ return (long) ((System.Int64) new AnonymousClassFindSegmentsFile(directory2, directory2).Run());
+ }
+
+ /// <summary> Reads version number from segments files. The version number is
+ /// initialized with a timestamp and then increased by one for each change of
+ /// the index.
+ ///
+ /// </summary>
+ /// <param name="directory">where the index resides.
+ /// </param>
+ /// <returns> version number.
+ /// </returns>
+ /// <throws> CorruptIndexException if the index is corrupt </throws>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public static long GetCurrentVersion(Directory directory)
+ {
+ return SegmentInfos.ReadCurrentVersion(directory);
+ }
+
+ /// <summary> Reads commitUserData, previously passed to
+ /// <see cref="IndexWriter.Commit(System.Collections.Generic.IDictionary{string, string})" />,
+ /// from current index segments file. This will return null if
+ /// <see cref="IndexWriter.Commit(System.Collections.Generic.IDictionary{string, string})" />
+ /// has never been called for this index.
+ /// </summary>
+ /// <param name="directory">where the index resides.
+ /// </param>
+ /// <returns> commit userData.
+ /// </returns>
+ /// <throws> CorruptIndexException if the index is corrupt </throws>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ /// <summary>
+ /// </summary>
+ /// <seealso cref="GetCommitUserData(Store.Directory)">
+ /// </seealso>
+ public static System.Collections.Generic.IDictionary<string, string> GetCommitUserData(Directory directory)
+ {
+ return SegmentInfos.ReadCurrentUserData(directory);
+ }
+
+ /// <summary> Version number when this IndexReader was opened. Not implemented in the
+ /// IndexReader base class.
+ ///
+ /// <p/>
+ /// If this reader is based on a Directory (ie, was created by calling
+ /// <see cref="Open(Lucene.Net.Store.Directory, bool)" />, or <see cref="Reopen()" />
+ /// on a reader based on a Directory), then
+ /// this method returns the version recorded in the commit that the reader
+ /// opened. This version is advanced every time <see cref="IndexWriter.Commit()" /> is
+ /// called.
+ /// <p/>
+ ///
+ /// <p/>
+ /// If instead this reader is a near real-time reader (ie, obtained by a call
+ /// to <see cref="IndexWriter.GetReader()" />, or by calling <see cref="Reopen()" /> on a near
+ /// real-time reader), then this method returns the version of the last
+ /// commit done by the writer. Note that even as further changes are made
+ /// with the writer, the version will not changed until a commit is
+ /// completed. Thus, you should not rely on this method to determine when a
+ /// near real-time reader should be opened. Use <see cref="IsCurrent" /> instead.
+ /// <p/>
+ ///
+ /// </summary>
+ /// <throws> UnsupportedOperationException </throws>
+ /// <summary> unless overridden in subclass
+ /// </summary>
+ public virtual long Version
+ {
+ get { throw new System.NotSupportedException("This reader does not support this method."); }
+ }
+
+ /// <summary> Retrieve the String userData optionally passed to
+ /// <see cref="IndexWriter.Commit(System.Collections.Generic.IDictionary{string, string})" />.
+ /// This will return null if
+ /// <see cref="IndexWriter.Commit(System.Collections.Generic.IDictionary{string, string})" />
+ /// has never been called for this index.
+ /// </summary>
+ /// <seealso cref="GetCommitUserData(Store.Directory)">
+ /// </seealso>
+ public virtual IDictionary<string, string> CommitUserData
+ {
+ get { throw new System.NotSupportedException("This reader does not support this method."); }
+ }
+
+ /// <summary> Check whether any new changes have occurred to the index since this
+ /// reader was opened.
+ ///
+ /// <p/>
+ /// If this reader is based on a Directory (ie, was created by calling
+ /// <see>
+ /// <cref>Open(Store.Directory)</cref>
+ /// </see> , or <see cref="Reopen()" /> on a reader based on a Directory), then
+ /// this method checks if any further commits (see <see cref="IndexWriter.Commit()" />
+ /// have occurred in that directory).
+ /// <p/>
+ ///
+ /// <p/>
+ /// If instead this reader is a near real-time reader (ie, obtained by a call
+ /// to <see cref="IndexWriter.GetReader()" />, or by calling <see cref="Reopen()" /> on a near
+ /// real-time reader), then this method checks if either a new commmit has
+ /// occurred, or any new uncommitted changes have taken place via the writer.
+ /// Note that even if the writer has only performed merging, this method will
+ /// still return false.
+ /// <p/>
+ ///
+ /// <p/>
+ /// In any event, if this returns false, you should call <see cref="Reopen()" /> to
+ /// get a new reader that sees the changes.
+ /// <p/>
+ ///
+ /// </summary>
+ /// <throws> CorruptIndexException if the index is corrupt </throws>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ /// <throws> UnsupportedOperationException unless overridden in subclass </throws>
+ public virtual bool IsCurrent()
+ {
+ throw new NotSupportedException("This reader does not support this method.");
+ }
+
+ /// <summary> Checks is the index is optimized (if it has a single segment and
+ /// no deletions). Not implemented in the IndexReader base class.
+ /// </summary>
+ /// <returns> &amp;lt;c&amp;gt;true&amp;lt;/c&amp;gt; if the index is optimized; &amp;lt;c&amp;gt;false&amp;lt;/c&amp;gt; otherwise </returns>
+ /// <throws> UnsupportedOperationException unless overridden in subclass </throws>
+ public virtual bool IsOptimized()
+ {
+ throw new NotSupportedException("This reader does not support this method.");
+ }
+
+ /// <summary> Return an array of term frequency vectors for the specified document.
+ /// The array contains a vector for each vectorized field in the document.
+ /// Each vector contains terms and frequencies for all terms in a given vectorized field.
+ /// If no such fields existed, the method returns null. The term vectors that are
+ /// returned may either be of type <see cref="ITermFreqVector" />
+ /// or of type <see cref="TermPositionVector" /> if
+ /// positions or offsets have been stored.
+ ///
+ /// </summary>
+ /// <param name="docNumber">document for which term frequency vectors are returned
+ /// </param>
+ /// <returns> array of term frequency vectors. May be null if no term vectors have been
+ /// stored for the specified document.
+ /// </returns>
+ /// <throws> IOException if index cannot be accessed </throws>
+ /// <seealso cref="Lucene.Net.Documents.Field.TermVector">
+ /// </seealso>
+ abstract public ITermFreqVector[] GetTermFreqVectors(int docNumber);
+
+
+ /// <summary> Return a term frequency vector for the specified document and field. The
+ /// returned vector contains terms and frequencies for the terms in
+ /// the specified field of this document, if the field had the storeTermVector
+ /// flag set. If termvectors had been stored with positions or offsets, a
+ /// <see cref="TermPositionVector" /> is returned.
+ ///
+ /// </summary>
+ /// <param name="docNumber">document for which the term frequency vector is returned
+ /// </param>
+ /// <param name="field">field for which the term frequency vector is returned.
+ /// </param>
+ /// <returns> term frequency vector May be null if field does not exist in the specified
+ /// document or term vector was not stored.
+ /// </returns>
+ /// <throws> IOException if index cannot be accessed </throws>
+ /// <seealso cref="Lucene.Net.Documents.Field.TermVector">
+ /// </seealso>
+ abstract public ITermFreqVector GetTermFreqVector(int docNumber, String field);
+
+ /// <summary> Load the Term Vector into a user-defined data structure instead of relying on the parallel arrays of
+ /// the <see cref="ITermFreqVector" />.
+ /// </summary>
+ /// <param name="docNumber">The number of the document to load the vector for
+ /// </param>
+ /// <param name="field">The name of the field to load
+ /// </param>
+ /// <param name="mapper">The <see cref="TermVectorMapper" /> to process the vector. Must not be null
+ /// </param>
+ /// <throws> IOException if term vectors cannot be accessed or if they do not exist on the field and doc. specified. </throws>
+ /// <summary>
+ /// </summary>
+ abstract public void GetTermFreqVector(int docNumber, String field, TermVectorMapper mapper);
+
+ /// <summary> Map all the term vectors for all fields in a Document</summary>
+ /// <param name="docNumber">The number of the document to load the vector for
+ /// </param>
+ /// <param name="mapper">The <see cref="TermVectorMapper" /> to process the vector. Must not be null
+ /// </param>
+ /// <throws> IOException if term vectors cannot be accessed or if they do not exist on the field and doc. specified. </throws>
+ abstract public void GetTermFreqVector(int docNumber, TermVectorMapper mapper);
+
+ /// <summary> Returns <c>true</c> if an index exists at the specified directory.
+ /// If the directory does not exist or if there is no index in it.
+ /// </summary>
+ /// <param name="directory">the directory to check for an index
+ /// </param>
+ /// <returns> <c>true</c> if an index exists; <c>false</c> otherwise
+ /// </returns>
+ /// <throws> IOException if there is a problem with accessing the index </throws>
+ public static bool IndexExists(Directory directory)
+ {
+ return SegmentInfos.GetCurrentSegmentGeneration(directory) != - 1;
+ }
+
+ /// <summary>Returns the number of documents in this index. </summary>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")]
+ public abstract int NumDocs();
+
+ /// <summary>Returns one greater than the largest possible document number.
+ /// This may be used to, e.g., determine how big to allocate an array which
+ /// will have an element for every document number in an index.
+ /// </summary>
+ public abstract int MaxDoc { get; }
+
+ /// <summary>Returns the number of deleted documents. </summary>
+ public virtual int NumDeletedDocs
+ {
+ get { return MaxDoc - NumDocs(); }
+ }
+
+ /// <summary> Returns the stored fields of the <c>n</c><sup>th</sup>
+ /// <c>Document</c> in this index.
+ /// <p/>
+ /// <b>NOTE:</b> for performance reasons, this method does not check if the
+ /// requested document is deleted, and therefore asking for a deleted document
+ /// may yield unspecified results. Usually this is not required, however you
+ /// can call <see cref="IsDeleted(int)" /> with the requested document ID to verify
+ /// the document is not deleted.
+ ///
+ /// </summary>
+ /// <throws> CorruptIndexException if the index is corrupt </throws>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public virtual Document Document(int n)
+ {
+ EnsureOpen();
+ return Document(n, null);
+ }
+
+ /// <summary> Returns the stored fields of the <c>n</c><sup>th</sup>
+ /// <c>Document</c> in this index.
+ /// <p/>
+ /// <b>NOTE:</b> for performance reasons, this method does not check if the
+ /// requested document is deleted, and therefore asking for a deleted document
+ /// may yield unspecified results. Usually this is not required, however you
+ /// can call <see cref="IsDeleted(int)" /> with the requested document ID to verify
+ /// the document is not deleted.
+ ///
+ /// </summary>
+ /// <throws> CorruptIndexException if the index is corrupt </throws>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public Document this[int doc]
+ {
+ get { return Document(doc); }
+ }
+
+ /// <summary> Get the <see cref="Lucene.Net.Documents.Document" /> at the <c>n</c>
+ /// <sup>th</sup> position. The <see cref="FieldSelector" /> may be used to determine
+ /// what <see cref="Lucene.Net.Documents.Field" />s to load and how they should
+ /// be loaded. <b>NOTE:</b> If this Reader (more specifically, the underlying
+ /// <c>FieldsReader</c>) is closed before the lazy
+ /// <see cref="Lucene.Net.Documents.Field" /> is loaded an exception may be
+ /// thrown. If you want the value of a lazy
+ /// <see cref="Lucene.Net.Documents.Field" /> to be available after closing you
+ /// must explicitly load it or fetch the Document again with a new loader.
+ /// <p/>
+ /// <b>NOTE:</b> for performance reasons, this method does not check if the
+ /// requested document is deleted, and therefore asking for a deleted document
+ /// may yield unspecified results. Usually this is not required, however you
+ /// can call <see cref="IsDeleted(int)" /> with the requested document ID to verify
+ /// the document is not deleted.
+ ///
+ /// </summary>
+ /// <param name="n">Get the document at the <c>n</c><sup>th</sup> position
+ /// </param>
+ /// <param name="fieldSelector">The <see cref="FieldSelector" /> to use to determine what
+ /// Fields should be loaded on the Document. May be null, in which case
+ /// all Fields will be loaded.
+ /// </param>
+ /// <returns> The stored fields of the
+ /// <see cref="Lucene.Net.Documents.Document" /> at the nth position
+ /// </returns>
+ /// <throws> CorruptIndexException if the index is corrupt </throws>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ /// <seealso cref="IFieldable">
+ /// </seealso>
+ /// <seealso cref="Lucene.Net.Documents.FieldSelector">
+ /// </seealso>
+ /// <seealso cref="Lucene.Net.Documents.SetBasedFieldSelector">
+ /// </seealso>
+ /// <seealso cref="Lucene.Net.Documents.LoadFirstFieldSelector">
+ /// </seealso>
+ // TODO (1.5): When we convert to JDK 1.5 make this Set<String>
+ public abstract Document Document(int n, FieldSelector fieldSelector);
+
+ /// <summary>Returns true if document <i>n</i> has been deleted </summary>
+ public abstract bool IsDeleted(int n);
+
+ /// <summary>Returns true if any documents have been deleted </summary>
+ public abstract bool HasDeletions { get; }
+
+ /// <summary>Returns true if there are norms stored for this field. </summary>
+ public virtual bool HasNorms(System.String field)
+ {
+ // backward compatible implementation.
+ // SegmentReader has an efficient implementation.
+ EnsureOpen();
+ return Norms(field) != null;
+ }
+
+ /// <summary>
+ /// Returns the byte-encoded normalization factor for the named field of
+ /// every document. This is used by the search code to score documents.
+ /// </summary>
+ /// <seealso cref="Lucene.Net.Documents.AbstractField.Boost" />
+ public abstract byte[] Norms(System.String field);
+
+ /// <summary>
+ /// Reads the byte-encoded normalization factor for the named field of every
+ /// document. This is used by the search code to score documents.
+ /// </summary>
+ /// <seealso cref="Lucene.Net.Documents.AbstractField.Boost" />
+ public abstract void Norms(System.String field, byte[] bytes, int offset);
+
+ /// <summary>Expert: Resets the normalization factor for the named field of the named
+ /// document. The norm represents the product of the field's <see cref="IFieldable.Boost">boost</see>
+ /// and its <see cref="Similarity.LengthNorm(String,int)">length normalization</see>. Thus, to preserve the length normalization
+ /// values when resetting this, one should base the new value upon the old.
+ ///
+ /// <b>NOTE:</b> If this field does not store norms, then
+ /// this method call will silently do nothing.
+ /// </summary>
+ /// <seealso cref="Norms(String)" />
+ /// <seealso cref="Similarity.DecodeNorm(byte)" />
+ /// <exception cref="StaleReaderException">
+ /// If the index has changed since this reader was opened
+ /// </exception>
+ /// <exception cref="CorruptIndexException">
+ /// If the index is corrupt
+ /// </exception>
+ /// <exception cref="LockObtainFailedException">
+ /// If another writer has this index open (<c>write.lock</c> could not be obtained)
+ /// </exception>
+ /// <exception cref="System.IO.IOException">
+ /// If there is a low-level IO error
+ /// </exception>
+ public virtual void SetNorm(int doc, String field, byte value)
+ {
+ lock (this)
+ {
+ EnsureOpen();
+ AcquireWriteLock();
+ hasChanges = true;
+ DoSetNorm(doc, field, value);
+ }
+ }
+
+ /// <summary>Implements setNorm in subclass.</summary>
+ protected internal abstract void DoSetNorm(int doc, System.String field, byte value_Renamed);
+
+ /// <summary>
+ /// Expert: Resets the normalization factor for the named field of the named document.
+ /// </summary>
+ /// <seealso cref="Norms(String)" />
+ /// <seealso cref="Similarity.DecodeNorm(byte)" />
+ /// <exception cref="StaleReaderException">
+ /// If the index has changed since this reader was opened
+ /// </exception>
+ /// <exception cref="CorruptIndexException">
+ /// If the index is corrupt
+ /// </exception>
+ /// <exception cref="LockObtainFailedException">
+ /// If another writer has this index open (<c>write.lock</c> could not be obtained)
+ /// </exception>
+ /// <exception cref="System.IO.IOException">
+ /// If there is a low-level IO error
+ /// </exception>
+ public virtual void SetNorm(int doc, System.String field, float value)
+ {
+ EnsureOpen();
+ SetNorm(doc, field, Similarity.EncodeNorm(value));
+ }
+
+ /// <summary>Returns an enumeration of all the terms in the index. The
+ /// enumeration is ordered by Term.compareTo(). Each term is greater
+ /// than all that precede it in the enumeration. Note that after
+ /// calling terms(), <see cref="TermEnum.Next()" /> must be called
+ /// on the resulting enumeration before calling other methods such as
+ /// <see cref="TermEnum.Term" />.
+ /// </summary>
+ /// <exception cref="System.IO.IOException">
+ /// If there is a low-level IO error
+ /// </exception>
+ public abstract TermEnum Terms();
+
+ /// <summary>Returns an enumeration of all terms starting at a given term. If
+ /// the given term does not exist, the enumeration is positioned at the
+ /// first term greater than the supplied term. The enumeration is
+ /// ordered by Term.compareTo(). Each term is greater than all that
+ /// precede it in the enumeration.
+ /// </summary>
+ /// <exception cref="System.IO.IOException">
+ /// If there is a low-level IO error
+ /// </exception>
+ public abstract TermEnum Terms(Term t);
+
+ /// <summary>Returns the number of documents containing the term <c>t</c>.</summary>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public abstract int DocFreq(Term t);
+
+ /// <summary>Returns an enumeration of all the documents which contain
+ /// <c>term</c>. For each document, the document number, the frequency of
+ /// the term in that document is also provided, for use in
+ /// search scoring. If term is null, then all non-deleted
+ /// docs are returned with freq=1.
+ /// Thus, this method implements the mapping:
+ /// <p/><list>
+ /// Term &#160;&#160; =&gt; &#160;&#160; &lt;docNum, freq&gt;<sup>*</sup>
+ /// </list>
+ /// <p/>The enumeration is ordered by document number. Each document number
+ /// is greater than all that precede it in the enumeration.
+ /// </summary>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public virtual TermDocs TermDocs(Term term)
+ {
+ EnsureOpen();
+ TermDocs termDocs = TermDocs();
+ termDocs.Seek(term);
+ return termDocs;
+ }
+
+ /// <summary>Returns an unpositioned <see cref="Lucene.Net.Index.TermDocs" /> enumerator.</summary>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public abstract TermDocs TermDocs();
+
+ /// <summary>Returns an enumeration of all the documents which contain
+ /// <c>term</c>. For each document, in addition to the document number
+ /// and frequency of the term in that document, a list of all of the ordinal
+ /// positions of the term in the document is available. Thus, this method
+ /// implements the mapping:
+ ///
+ /// <p/><list>
+ /// Term &#160;&#160; =&gt; &#160;&#160; &lt;docNum, freq,
+ /// &lt;pos<sub>1</sub>, pos<sub>2</sub>, ...
+ /// pos<sub>freq-1</sub>&gt;
+ /// &gt;<sup>*</sup>
+ /// </list>
+ /// <p/> This positional information facilitates phrase and proximity searching.
+ /// <p/>The enumeration is ordered by document number. Each document number is
+ /// greater than all that precede it in the enumeration.
+ /// </summary>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public virtual TermPositions TermPositions(Term term)
+ {
+ EnsureOpen();
+ TermPositions termPositions = TermPositions();
+ termPositions.Seek(term);
+ return termPositions;
+ }
+
+ /// <summary>Returns an unpositioned <see cref="Lucene.Net.Index.TermPositions" /> enumerator.</summary>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public abstract TermPositions TermPositions();
+
+
+
+ /// <summary>
+ /// Deletes the document numbered <c>docNum</c>. Once a document is
+ /// deleted it will not appear in TermDocs or TermPostitions enumerations.
+ /// Attempts to read its field with the <see cref="Document(int)" />
+ /// method will result in an error. The presence of this document may still be
+ /// reflected in the <see cref="DocFreq" /> statistic, though
+ /// this will be corrected eventually as the index is further modified.
+ /// </summary>
+ /// <exception cref="StaleReaderException">
+ /// If the index has changed since this reader was opened
+ /// </exception>
+ /// <exception cref="CorruptIndexException">If the index is corrupt</exception>
+ /// <exception cref="LockObtainFailedException">
+ /// If another writer has this index open (<c>write.lock</c> could not be obtained)
+ /// </exception>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public virtual void DeleteDocument(int docNum)
+ {
+ lock (this)
+ {
+ EnsureOpen();
+ AcquireWriteLock();
+ hasChanges = true;
+ DoDelete(docNum);
+ }
+ }
+
+
+ /// <summary>Implements deletion of the document numbered <c>docNum</c>.
+ /// Applications should call <see cref="DeleteDocument(int)" /> or <see cref="DeleteDocuments(Term)" />.
+ /// </summary>
+ protected internal abstract void DoDelete(int docNum);
+
+
+ /// <summary>
+ /// Deletes all documents that have a given <c>term</c> indexed.
+ /// This is useful if one uses a document field to hold a unique ID string for
+ /// the document. Then to delete such a document, one merely constructs a
+ /// term with the appropriate field and the unique ID string as its text and
+ /// passes it to this method.
+ /// See <see cref="DeleteDocument(int)" /> for information about when this deletion will
+ /// become effective.
+ /// </summary>
+ /// <returns>The number of documents deleted</returns>
+ /// <exception cref="StaleReaderException">
+ /// If the index has changed since this reader was opened
+ /// </exception>
+ /// <exception cref="CorruptIndexException">If the index is corrupt</exception>
+ /// <exception cref="LockObtainFailedException">
+ /// If another writer has this index open (<c>write.lock</c> could not be obtained)
+ /// </exception>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public virtual int DeleteDocuments(Term term)
+ {
+ EnsureOpen();
+ TermDocs docs = TermDocs(term);
+ if (docs == null)
+ return 0;
+ int n = 0;
+ try
+ {
+ while (docs.Next())
+ {
+ DeleteDocument(docs.Doc);
+ n++;
+ }
+ }
+ finally
+ {
+ docs.Close();
+ }
+ return n;
+ }
+
+ /// <summary>Undeletes all documents currently marked as deleted in this index.
+ ///
+ /// </summary>
+ /// <exception cref="StaleReaderException">
+ /// If the index has changed since this reader was opened
+ /// </exception>
+ /// <exception cref="CorruptIndexException">If the index is corrupt</exception>
+ /// <exception cref="LockObtainFailedException">
+ /// If another writer has this index open (<c>write.lock</c> could not be obtained)
+ /// </exception>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public virtual void UndeleteAll()
+ {
+ lock (this)
+ {
+ EnsureOpen();
+ AcquireWriteLock();
+ hasChanges = true;
+ DoUndeleteAll();
+ }
+ }
+
+ /// <summary>Implements actual undeleteAll() in subclass. </summary>
+ protected internal abstract void DoUndeleteAll();
+
+ /// <summary>
+ /// Does nothing by default. Subclasses that require a write lock for
+ /// index modifications must implement this method.
+ /// </summary>
+ protected internal virtual void AcquireWriteLock()
+ {
+ lock (this)
+ {
+ /* NOOP */
+ }
+ }
+
+ /// <summary> </summary>
+ /// <exception cref="System.IO.IOException" />
+ public void Flush()
+ {
+ lock (this)
+ {
+ EnsureOpen();
+ Commit();
+ }
+ }
+
+ /// <param name="commitUserData">Opaque Map (String -> String)
+ /// that's recorded into the segments file in the index,
+ /// and retrievable by <see cref="IndexReader.GetCommitUserData" />
+ /// </param>
+ /// <exception cref="System.IO.IOException" />
+ public void Flush(IDictionary<string, string> commitUserData)
+ {
+ lock (this)
+ {
+ EnsureOpen();
+ Commit(commitUserData);
+ }
+ }
+
+ /// <summary> Commit changes resulting from delete, undeleteAll, or
+ /// setNorm operations
+ ///
+ /// If an exception is hit, then either no changes or all
+ /// changes will have been committed to the index
+ /// (transactional semantics).
+ /// </summary>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public /*protected internal*/ void Commit()
+ {
+ lock (this)
+ {
+ Commit(null);
+ }
+ }
+
+ /// <summary> Commit changes resulting from delete, undeleteAll, or
+ /// setNorm operations
+ ///
+ /// If an exception is hit, then either no changes or all
+ /// changes will have been committed to the index
+ /// (transactional semantics).
+ /// </summary>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public void Commit(IDictionary<string, string> commitUserData)
+ {
+ lock (this)
+ {
+ if (hasChanges)
+ {
+ DoCommit(commitUserData);
+ }
+ hasChanges = false;
+ }
+ }
+
+ /// <summary>Implements commit.</summary>
+ protected internal abstract void DoCommit(IDictionary<string, string> commitUserData);
+
+ [Obsolete("Use Dispose() instead")]
+ public void Close()
+ {
+ Dispose();
+ }
+
+ /// <summary> Closes files associated with this index.
+ /// Also saves any new deletions to disk.
+ /// No other methods should be called after this has been called.
+ /// </summary>
+ /// <exception cref="System.IO.IOException">If there is a low-level IO error</exception>
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ lock (this)
+ {
+ if (!closed)
+ {
+ DecRef();
+ closed = true;
+ }
+ }
+ }
+ }
+
+ /// <summary>Implements close. </summary>
+ protected internal abstract void DoClose();
+
+
+ /// <summary> Get a list of unique field names that exist in this index and have the specified
+ /// field option information.
+ /// </summary>
+ /// <param name="fldOption">specifies which field option should be available for the returned fields
+ /// </param>
+ /// <returns> Collection of Strings indicating the names of the fields.
+ /// </returns>
+ /// <seealso cref="IndexReader.FieldOption">
+ /// </seealso>
+ public abstract ICollection<string> GetFieldNames(FieldOption fldOption);
+
+ /// <summary> Expert: return the IndexCommit that this reader has
+ /// opened. This method is only implemented by those
+ /// readers that correspond to a Directory with its own
+ /// segments_N file.
+ ///
+ /// <p/><b>WARNING</b>: this API is new and experimental and
+ /// may suddenly change.<p/>
+ /// </summary>
+ public virtual IndexCommit IndexCommit
+ {
+ get { throw new NotSupportedException("This reader does not support this method."); }
+ }
+
+ /// <summary> Prints the filename and size of each file within a given compound file.
+ /// Add the -extract flag to extract files to the current working directory.
+ /// In order to make the extracted version of the index work, you have to copy
+ /// the segments file from the compound index into the directory where the extracted files are stored.
+ /// </summary>
+ /// <param name="args">Usage: Lucene.Net.Index.IndexReader [-extract] &lt;cfsfile&gt;
+ /// </param>
+ [STAThread]
+ public static void Main(String[] args)
+ {
+ System.String filename = null;
+ bool extract = false;
+
+ foreach (string t in args)
+ {
+ if (t.Equals("-extract"))
+ {
+ extract = true;
+ }
+ else if (filename == null)
+ {
+ filename = t;
+ }
+ }
+
+ if (filename == null)
+ {
+ System.Console.Out.WriteLine("Usage: Lucene.Net.Index.IndexReader [-extract] <cfsfile>");
+ return ;
+ }
+
+ Directory dir = null;
+ CompoundFileReader cfr = null;
+
+ try
+ {
+ var file = new System.IO.FileInfo(filename);
+ System.String dirname = new System.IO.FileInfo(file.FullName).DirectoryName;
+ filename = file.Name;
+ dir = FSDirectory.Open(new System.IO.DirectoryInfo(dirname));
+ cfr = new CompoundFileReader(dir, filename);
+
+ System.String[] files = cfr.ListAll();
+ System.Array.Sort(files); // sort the array of filename so that the output is more readable
+
+ foreach (string t in files)
+ {
+ long len = cfr.FileLength(t);
+
+ if (extract)
+ {
+ System.Console.Out.WriteLine("extract " + t + " with " + len + " bytes to local directory...");
+ IndexInput ii = cfr.OpenInput(t);
+
+ var f = new System.IO.FileStream(t, System.IO.FileMode.Create);
+
+ // read and write with a small buffer, which is more effectiv than reading byte by byte
+ var buffer = new byte[1024];
+ int chunk = buffer.Length;
+ while (len > 0)
+ {
+ var bufLen = (int) System.Math.Min(chunk, len);
+ ii.ReadBytes(buffer, 0, bufLen);
+ f.Write(buffer, 0, bufLen);
+ len -= bufLen;
+ }
+
+ f.Close();
+ ii.Close();
+ }
+ else
+ System.Console.Out.WriteLine(t + ": " + len + " bytes");
+ }
+ }
+ catch (System.IO.IOException ioe)
+ {
+ System.Console.Error.WriteLine(ioe.StackTrace);
+ }
+ finally
+ {
+ try
+ {
+ if (dir != null)
+ dir.Close();
+ if (cfr != null)
+ cfr.Close();
+ }
+ catch (System.IO.IOException ioe)
+ {
+ System.Console.Error.WriteLine(ioe.StackTrace);
+ }
+ }
+ }
+
+ /// <summary>Returns all commit points that exist in the Directory.
+ /// Normally, because the default is <see cref="KeepOnlyLastCommitDeletionPolicy" />
+ ///, there would be only
+ /// one commit point. But if you're using a custom <see cref="IndexDeletionPolicy" />
+ /// then there could be many commits.
+ /// Once you have a given commit, you can open a reader on
+ /// it by calling <see cref="IndexReader.Open(IndexCommit,bool)" />
+ /// There must be at least one commit in
+ /// the Directory, else this method throws <see cref="System.IO.IOException" />.
+ /// Note that if a commit is in
+ /// progress while this method is running, that commit
+ /// may or may not be returned array.
+ /// </summary>
+ public static System.Collections.Generic.ICollection<IndexCommit> ListCommits(Directory dir)
+ {
+ return DirectoryReader.ListCommits(dir);
+ }
+
+ /// <summary>Expert: returns the sequential sub readers that this
+ /// reader is logically composed of. For example,
+ /// IndexSearcher uses this API to drive searching by one
+ /// sub reader at a time. If this reader is not composed
+ /// of sequential child readers, it should return null.
+ /// If this method returns an empty array, that means this
+ /// reader is a null reader (for example a MultiReader
+ /// that has no sub readers).
+ /// <p/>
+ /// NOTE: You should not try using sub-readers returned by
+ /// this method to make any changes (setNorm, deleteDocument,
+ /// etc.). While this might succeed for one composite reader
+ /// (like MultiReader), it will most likely lead to index
+ /// corruption for other readers (like DirectoryReader obtained
+ /// through <see cref="IndexReader.Open(Lucene.Net.Store.Directory,bool)" />. Use the parent reader directly.
+ /// </summary>
+ public virtual IndexReader[] GetSequentialSubReaders()
+ {
+ return null;
+ }
+
+ /// <summary>Expert</summary>
+ public virtual object FieldCacheKey
+ {
+ get { return this; }
+ }
+
+ /* Expert. Warning: this returns null if the reader has
+ * no deletions
+ */
+
+ public virtual object DeletesCacheKey
+ {
+ get { return this; }
+ }
+
+ /// <summary>Returns the number of unique terms (across all fields)
+ /// in this reader.
+ ///
+ /// This method returns long, even though internally
+ /// Lucene cannot handle more than 2^31 unique terms, for
+ /// a possible future when this limitation is removed.
+ ///
+ /// </summary>
+ /// <throws> UnsupportedOperationException if this count </throws>
+ /// <summary> cannot be easily determined (eg Multi*Readers).
+ /// Instead, you should call <see cref="GetSequentialSubReaders" />
+ /// and ask each sub reader for
+ /// its unique term count.
+ /// </summary>
+ public virtual long UniqueTermCount
+ {
+ get { throw new System.NotSupportedException("this reader does not implement getUniqueTermCount()"); }
+ }
+
+ /// <summary>
+ /// For IndexReader implementations that use
+ /// TermInfosReader to read terms, this returns the
+ /// current indexDivisor as specified when the reader was
+ /// opened.
+ /// </summary>
+ public virtual int TermInfosIndexDivisor
+ {
+ get { throw new NotSupportedException("This reader does not support this method."); }
+ }
+ }
+} \ No newline at end of file