You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by cc...@apache.org on 2013/04/03 19:39:52 UTC
[09/51] [partial] Mass convert mixed tabs to spaces
http://git-wip-us.apache.org/repos/asf/lucenenet/blob/62f018ab/src/core/Index/IndexWriter.cs
----------------------------------------------------------------------
diff --git a/src/core/Index/IndexWriter.cs b/src/core/Index/IndexWriter.cs
index dda1738..049d821 100644
--- a/src/core/Index/IndexWriter.cs
+++ b/src/core/Index/IndexWriter.cs
@@ -33,109 +33,109 @@ using Similarity = Lucene.Net.Search.Similarity;
namespace Lucene.Net.Index
{
-
- /// <summary>An <c>IndexWriter</c> creates and maintains an index.
- /// <p/>The <c>create</c> argument to the
+
+ /// <summary>An <c>IndexWriter</c> creates and maintains an index.
+ /// <p/>The <c>create</c> argument to the
/// <see cref="IndexWriter(Directory, Analyzer, bool, MaxFieldLength)">constructor</see> determines
- /// whether a new index is created, or whether an existing index is
- /// opened. Note that you can open an index with <c>create=true</c>
- /// even while readers are using the index. The old readers will
- /// continue to search the "point in time" snapshot they had opened,
- /// and won't see the newly created index until they re-open. There are
- /// also <see cref="IndexWriter(Directory, Analyzer, MaxFieldLength)">constructors</see>
- /// with no <c>create</c> argument which will create a new index
- /// if there is not already an index at the provided path and otherwise
- /// open the existing index.<p/>
- /// <p/>In either case, documents are added with <see cref="AddDocument(Document)" />
- /// and removed with <see cref="DeleteDocuments(Term)" /> or
- /// <see cref="DeleteDocuments(Query)" />. A document can be updated with
- /// <see cref="UpdateDocument(Term, Document)" /> (which just deletes
- /// and then adds the entire document). When finished adding, deleting
- /// and updating documents, <see cref="Close()" /> should be called.<p/>
- /// <a name="flush"></a>
- /// <p/>These changes are buffered in memory and periodically
- /// flushed to the <see cref="Directory" /> (during the above method
- /// calls). A flush is triggered when there are enough
- /// buffered deletes (see <see cref="SetMaxBufferedDeleteTerms" />)
- /// or enough added documents since the last flush, whichever
- /// is sooner. For the added documents, flushing is triggered
- /// either by RAM usage of the documents (see
- /// <see cref="SetRAMBufferSizeMB" />) or the number of added documents.
- /// The default is to flush when RAM usage hits 16 MB. For
- /// best indexing speed you should flush by RAM usage with a
- /// large RAM buffer. Note that flushing just moves the
- /// internal buffered state in IndexWriter into the index, but
- /// these changes are not visible to IndexReader until either
- /// <see cref="Commit()" /> or <see cref="Close()" /> is called. A flush may
- /// also trigger one or more segment merges which by default
- /// run with a background thread so as not to block the
- /// addDocument calls (see <a href="#mergePolicy">below</a>
- /// for changing the <see cref="MergeScheduler" />).
- /// <p/>
- /// If an index will not have more documents added for a while and optimal search
- /// performance is desired, then either the full <see cref="Optimize()" />
- /// method or partial <see cref="Optimize(int)" /> method should be
- /// called before the index is closed.
- /// <p/>
- /// Opening an <c>IndexWriter</c> creates a lock file for the directory in use. Trying to open
- /// another <c>IndexWriter</c> on the same directory will lead to a
- /// <see cref="LockObtainFailedException" />. The <see cref="LockObtainFailedException" />
- /// is also thrown if an IndexReader on the same directory is used to delete documents
- /// from the index.<p/>
- /// </summary>
- /// <summary><a name="deletionPolicy"></a>
- /// <p/>Expert: <c>IndexWriter</c> allows an optional
- /// <see cref="IndexDeletionPolicy" /> implementation to be
- /// specified. You can use this to control when prior commits
- /// are deleted from the index. The default policy is <see cref="KeepOnlyLastCommitDeletionPolicy" />
- /// which removes all prior
- /// commits as soon as a new commit is done (this matches
- /// behavior before 2.2). Creating your own policy can allow
- /// you to explicitly keep previous "point in time" commits
- /// alive in the index for some time, to allow readers to
- /// refresh to the new commit without having the old commit
- /// deleted out from under them. This is necessary on
- /// filesystems like NFS that do not support "delete on last
- /// close" semantics, which Lucene's "point in time" search
- /// normally relies on. <p/>
- /// <a name="mergePolicy"></a> <p/>Expert:
- /// <c>IndexWriter</c> allows you to separately change
- /// the <see cref="MergePolicy" /> and the <see cref="MergeScheduler" />.
- /// The <see cref="MergePolicy" /> is invoked whenever there are
- /// changes to the segments in the index. Its role is to
- /// select which merges to do, if any, and return a <see cref="Index.MergePolicy.MergeSpecification" />
- /// describing the merges. It
- /// also selects merges to do for optimize(). (The default is
- /// <see cref="LogByteSizeMergePolicy" />. Then, the <see cref="MergeScheduler" />
- /// is invoked with the requested merges and
- /// it decides when and how to run the merges. The default is
- /// <see cref="ConcurrentMergeScheduler" />. <p/>
- /// <a name="OOME"></a><p/><b>NOTE</b>: if you hit an
- /// OutOfMemoryError then IndexWriter will quietly record this
- /// fact and block all future segment commits. This is a
- /// defensive measure in case any internal state (buffered
- /// documents and deletions) were corrupted. Any subsequent
- /// calls to <see cref="Commit()" /> will throw an
- /// IllegalStateException. The only course of action is to
- /// call <see cref="Close()" />, which internally will call <see cref="Rollback()" />
- ///, to undo any changes to the index since the
- /// last commit. You can also just call <see cref="Rollback()" />
- /// directly.<p/>
- /// <a name="thread-safety"></a><p/><b>NOTE</b>:
+ /// whether a new index is created, or whether an existing index is
+ /// opened. Note that you can open an index with <c>create=true</c>
+ /// even while readers are using the index. The old readers will
+ /// continue to search the "point in time" snapshot they had opened,
+ /// and won't see the newly created index until they re-open. There are
+ /// also <see cref="IndexWriter(Directory, Analyzer, MaxFieldLength)">constructors</see>
+ /// with no <c>create</c> argument which will create a new index
+ /// if there is not already an index at the provided path and otherwise
+ /// open the existing index.<p/>
+ /// <p/>In either case, documents are added with <see cref="AddDocument(Document)" />
+ /// and removed with <see cref="DeleteDocuments(Term)" /> or
+ /// <see cref="DeleteDocuments(Query)" />. A document can be updated with
+ /// <see cref="UpdateDocument(Term, Document)" /> (which just deletes
+ /// and then adds the entire document). When finished adding, deleting
+ /// and updating documents, <see cref="Close()" /> should be called.<p/>
+ /// <a name="flush"></a>
+ /// <p/>These changes are buffered in memory and periodically
+ /// flushed to the <see cref="Directory" /> (during the above method
+ /// calls). A flush is triggered when there are enough
+ /// buffered deletes (see <see cref="SetMaxBufferedDeleteTerms" />)
+ /// or enough added documents since the last flush, whichever
+ /// is sooner. For the added documents, flushing is triggered
+ /// either by RAM usage of the documents (see
+ /// <see cref="SetRAMBufferSizeMB" />) or the number of added documents.
+ /// The default is to flush when RAM usage hits 16 MB. For
+ /// best indexing speed you should flush by RAM usage with a
+ /// large RAM buffer. Note that flushing just moves the
+ /// internal buffered state in IndexWriter into the index, but
+ /// these changes are not visible to IndexReader until either
+ /// <see cref="Commit()" /> or <see cref="Close()" /> is called. A flush may
+ /// also trigger one or more segment merges which by default
+ /// run with a background thread so as not to block the
+ /// addDocument calls (see <a href="#mergePolicy">below</a>
+ /// for changing the <see cref="MergeScheduler" />).
+ /// <p/>
+ /// If an index will not have more documents added for a while and optimal search
+ /// performance is desired, then either the full <see cref="Optimize()" />
+ /// method or partial <see cref="Optimize(int)" /> method should be
+ /// called before the index is closed.
+ /// <p/>
+ /// Opening an <c>IndexWriter</c> creates a lock file for the directory in use. Trying to open
+ /// another <c>IndexWriter</c> on the same directory will lead to a
+ /// <see cref="LockObtainFailedException" />. The <see cref="LockObtainFailedException" />
+ /// is also thrown if an IndexReader on the same directory is used to delete documents
+ /// from the index.<p/>
+ /// </summary>
+ /// <summary><a name="deletionPolicy"></a>
+ /// <p/>Expert: <c>IndexWriter</c> allows an optional
+ /// <see cref="IndexDeletionPolicy" /> implementation to be
+ /// specified. You can use this to control when prior commits
+ /// are deleted from the index. The default policy is <see cref="KeepOnlyLastCommitDeletionPolicy" />
+ /// which removes all prior
+ /// commits as soon as a new commit is done (this matches
+ /// behavior before 2.2). Creating your own policy can allow
+ /// you to explicitly keep previous "point in time" commits
+ /// alive in the index for some time, to allow readers to
+ /// refresh to the new commit without having the old commit
+ /// deleted out from under them. This is necessary on
+ /// filesystems like NFS that do not support "delete on last
+ /// close" semantics, which Lucene's "point in time" search
+ /// normally relies on. <p/>
+ /// <a name="mergePolicy"></a> <p/>Expert:
+ /// <c>IndexWriter</c> allows you to separately change
+ /// the <see cref="MergePolicy" /> and the <see cref="MergeScheduler" />.
+ /// The <see cref="MergePolicy" /> is invoked whenever there are
+ /// changes to the segments in the index. Its role is to
+ /// select which merges to do, if any, and return a <see cref="Index.MergePolicy.MergeSpecification" />
+ /// describing the merges. It
+ /// also selects merges to do for optimize(). (The default is
+ /// <see cref="LogByteSizeMergePolicy" />. Then, the <see cref="MergeScheduler" />
+ /// is invoked with the requested merges and
+ /// it decides when and how to run the merges. The default is
+ /// <see cref="ConcurrentMergeScheduler" />. <p/>
+ /// <a name="OOME"></a><p/><b>NOTE</b>: if you hit an
+ /// OutOfMemoryError then IndexWriter will quietly record this
+ /// fact and block all future segment commits. This is a
+ /// defensive measure in case any internal state (buffered
+ /// documents and deletions) were corrupted. Any subsequent
+ /// calls to <see cref="Commit()" /> will throw an
+ /// IllegalStateException. The only course of action is to
+ /// call <see cref="Close()" />, which internally will call <see cref="Rollback()" />
+ ///, to undo any changes to the index since the
+ /// last commit. You can also just call <see cref="Rollback()" />
+ /// directly.<p/>
+ /// <a name="thread-safety"></a><p/><b>NOTE</b>:
/// <see cref="IndexWriter" /> 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>IndexWriter</c> instance as
- /// this may cause deadlock; use your own (non-Lucene) objects
- /// instead. <p/>
- /// <b>NOTE:</b> if you call
- /// <c>Thread.Interrupt()</c> on a thread that's within
- /// IndexWriter, IndexWriter will try to catch this (eg, if
- /// it's in a Wait() or Thread.Sleep()), and will then throw
- /// the unchecked exception <see cref="System.Threading.ThreadInterruptedException"/>
- /// and <b>clear</b> the interrupt status on the thread<p/>
- /// </summary>
+ /// 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>IndexWriter</c> instance as
+ /// this may cause deadlock; use your own (non-Lucene) objects
+ /// instead. <p/>
+ /// <b>NOTE:</b> if you call
+ /// <c>Thread.Interrupt()</c> on a thread that's within
+ /// IndexWriter, IndexWriter will try to catch this (eg, if
+ /// it's in a Wait() or Thread.Sleep()), and will then throw
+ /// the unchecked exception <see cref="System.Threading.ThreadInterruptedException"/>
+ /// and <b>clear</b> the interrupt status on the thread<p/>
+ /// </summary>
/*
* Clarification: Check Points (and commits)
@@ -158,367 +158,367 @@ namespace Lucene.Net.Index
* keeps track of the last non commit checkpoint.
*/
public class IndexWriter : System.IDisposable
- {
- private void InitBlock()
- {
- similarity = Search.Similarity.Default;
- mergePolicy = new LogByteSizeMergePolicy(this);
- readerPool = new ReaderPool(this);
- }
-
- /// <summary> Default value for the write lock timeout (1,000).</summary>
- /// <seealso cref="DefaultWriteLockTimeout">
- /// </seealso>
- public static long WRITE_LOCK_TIMEOUT = 1000;
-
- private long writeLockTimeout = WRITE_LOCK_TIMEOUT;
-
- /// <summary> Name of the write lock in the index.</summary>
- public const System.String WRITE_LOCK_NAME = "write.lock";
-
- /// <summary> Value to denote a flush trigger is disabled</summary>
- public const int DISABLE_AUTO_FLUSH = - 1;
-
- /// <summary> Disabled by default (because IndexWriter flushes by RAM usage
- /// by default). Change using <see cref="SetMaxBufferedDocs(int)" />.
- /// </summary>
- public static readonly int DEFAULT_MAX_BUFFERED_DOCS = DISABLE_AUTO_FLUSH;
-
- /// <summary> Default value is 16 MB (which means flush when buffered
- /// docs consume 16 MB RAM). Change using <see cref="SetRAMBufferSizeMB" />.
- /// </summary>
- public const double DEFAULT_RAM_BUFFER_SIZE_MB = 16.0;
-
- /// <summary> Disabled by default (because IndexWriter flushes by RAM usage
- /// by default). Change using <see cref="SetMaxBufferedDeleteTerms(int)" />.
- /// </summary>
- public static readonly int DEFAULT_MAX_BUFFERED_DELETE_TERMS = DISABLE_AUTO_FLUSH;
-
- /// <summary> Default value is 10,000. Change using <see cref="SetMaxFieldLength(int)" />.</summary>
- public const int DEFAULT_MAX_FIELD_LENGTH = 10000;
-
- /// <summary> Default value is 128. Change using <see cref="TermIndexInterval" />.</summary>
- public const int DEFAULT_TERM_INDEX_INTERVAL = 128;
-
- /// <summary> Absolute hard maximum length for a term. If a term
- /// arrives from the analyzer longer than this length, it
- /// is skipped and a message is printed to infoStream, if
- /// set (see <see cref="SetInfoStream" />).
- /// </summary>
- public static readonly int MAX_TERM_LENGTH;
-
- // The normal read buffer size defaults to 1024, but
- // increasing this during merging seems to yield
- // performance gains. However we don't want to increase
- // it too much because there are quite a few
- // BufferedIndexInputs created during merging. See
- // LUCENE-888 for details.
- private const int MERGE_READ_BUFFER_SIZE = 4096;
-
- // Used for printing messages
- private static System.Object MESSAGE_ID_LOCK = new System.Object();
- private static int MESSAGE_ID = 0;
- private int messageID = - 1;
- private volatile bool hitOOM;
-
- private Directory directory; // where this index resides
- private Analyzer analyzer; // how to analyze text
-
- private Similarity similarity; // how to normalize
-
- private volatile uint changeCount; // increments every time a change is completed
- private long lastCommitChangeCount; // last changeCount that was committed
-
- private SegmentInfos rollbackSegmentInfos; // segmentInfos we will fallback to if the commit fails
- private HashMap<SegmentInfo, int?> rollbackSegments;
-
- internal volatile SegmentInfos pendingCommit; // set when a commit is pending (after prepareCommit() & before commit())
- internal volatile uint pendingCommitChangeCount;
-
- private SegmentInfos localRollbackSegmentInfos; // segmentInfos we will fallback to if the commit fails
- private int localFlushedDocCount; // saved docWriter.getFlushedDocCount during local transaction
-
- private SegmentInfos segmentInfos = new SegmentInfos(); // the segments
+ {
+ private void InitBlock()
+ {
+ similarity = Search.Similarity.Default;
+ mergePolicy = new LogByteSizeMergePolicy(this);
+ readerPool = new ReaderPool(this);
+ }
+
+ /// <summary> Default value for the write lock timeout (1,000).</summary>
+ /// <seealso cref="DefaultWriteLockTimeout">
+ /// </seealso>
+ public static long WRITE_LOCK_TIMEOUT = 1000;
+
+ private long writeLockTimeout = WRITE_LOCK_TIMEOUT;
+
+ /// <summary> Name of the write lock in the index.</summary>
+ public const System.String WRITE_LOCK_NAME = "write.lock";
+
+ /// <summary> Value to denote a flush trigger is disabled</summary>
+ public const int DISABLE_AUTO_FLUSH = - 1;
+
+ /// <summary> Disabled by default (because IndexWriter flushes by RAM usage
+ /// by default). Change using <see cref="SetMaxBufferedDocs(int)" />.
+ /// </summary>
+ public static readonly int DEFAULT_MAX_BUFFERED_DOCS = DISABLE_AUTO_FLUSH;
+
+ /// <summary> Default value is 16 MB (which means flush when buffered
+ /// docs consume 16 MB RAM). Change using <see cref="SetRAMBufferSizeMB" />.
+ /// </summary>
+ public const double DEFAULT_RAM_BUFFER_SIZE_MB = 16.0;
+
+ /// <summary> Disabled by default (because IndexWriter flushes by RAM usage
+ /// by default). Change using <see cref="SetMaxBufferedDeleteTerms(int)" />.
+ /// </summary>
+ public static readonly int DEFAULT_MAX_BUFFERED_DELETE_TERMS = DISABLE_AUTO_FLUSH;
+
+ /// <summary> Default value is 10,000. Change using <see cref="SetMaxFieldLength(int)" />.</summary>
+ public const int DEFAULT_MAX_FIELD_LENGTH = 10000;
+
+ /// <summary> Default value is 128. Change using <see cref="TermIndexInterval" />.</summary>
+ public const int DEFAULT_TERM_INDEX_INTERVAL = 128;
+
+ /// <summary> Absolute hard maximum length for a term. If a term
+ /// arrives from the analyzer longer than this length, it
+ /// is skipped and a message is printed to infoStream, if
+ /// set (see <see cref="SetInfoStream" />).
+ /// </summary>
+ public static readonly int MAX_TERM_LENGTH;
+
+ // The normal read buffer size defaults to 1024, but
+ // increasing this during merging seems to yield
+ // performance gains. However we don't want to increase
+ // it too much because there are quite a few
+ // BufferedIndexInputs created during merging. See
+ // LUCENE-888 for details.
+ private const int MERGE_READ_BUFFER_SIZE = 4096;
+
+ // Used for printing messages
+ private static System.Object MESSAGE_ID_LOCK = new System.Object();
+ private static int MESSAGE_ID = 0;
+ private int messageID = - 1;
+ private volatile bool hitOOM;
+
+ private Directory directory; // where this index resides
+ private Analyzer analyzer; // how to analyze text
+
+ private Similarity similarity; // how to normalize
+
+ private volatile uint changeCount; // increments every time a change is completed
+ private long lastCommitChangeCount; // last changeCount that was committed
+
+ private SegmentInfos rollbackSegmentInfos; // segmentInfos we will fallback to if the commit fails
+ private HashMap<SegmentInfo, int?> rollbackSegments;
+
+ internal volatile SegmentInfos pendingCommit; // set when a commit is pending (after prepareCommit() & before commit())
+ internal volatile uint pendingCommitChangeCount;
+
+ private SegmentInfos localRollbackSegmentInfos; // segmentInfos we will fallback to if the commit fails
+ private int localFlushedDocCount; // saved docWriter.getFlushedDocCount during local transaction
+
+ private SegmentInfos segmentInfos = new SegmentInfos(); // the segments
private int optimizeMaxNumSegments;
- private DocumentsWriter docWriter;
- private IndexFileDeleter deleter;
+ private DocumentsWriter docWriter;
+ private IndexFileDeleter deleter;
private ISet<SegmentInfo> segmentsToOptimize = Lucene.Net.Support.Compatibility.SetFactory.CreateHashSet<SegmentInfo>(); // used by optimize to note those needing optimization
-
- private Lock writeLock;
-
- private int termIndexInterval = DEFAULT_TERM_INDEX_INTERVAL;
-
- private bool closed;
- private bool closing;
-
- // Holds all SegmentInfo instances currently involved in
- // merges
+
+ private Lock writeLock;
+
+ private int termIndexInterval = DEFAULT_TERM_INDEX_INTERVAL;
+
+ private bool closed;
+ private bool closing;
+
+ // Holds all SegmentInfo instances currently involved in
+ // merges
private HashSet<SegmentInfo> mergingSegments = new HashSet<SegmentInfo>();
-
- private MergePolicy mergePolicy;
- private MergeScheduler mergeScheduler = new ConcurrentMergeScheduler();
+
+ private MergePolicy mergePolicy;
+ private MergeScheduler mergeScheduler = new ConcurrentMergeScheduler();
private LinkedList<MergePolicy.OneMerge> pendingMerges = new LinkedList<MergePolicy.OneMerge>();
- private ISet<MergePolicy.OneMerge> runningMerges = Lucene.Net.Support.Compatibility.SetFactory.CreateHashSet<MergePolicy.OneMerge>();
- private IList<MergePolicy.OneMerge> mergeExceptions = new List<MergePolicy.OneMerge>();
- private long mergeGen;
- private bool stopMerges;
-
- private int flushCount;
- private int flushDeletesCount;
-
- // Used to only allow one addIndexes to proceed at once
- // TODO: use ReadWriteLock once we are on 5.0
- private int readCount; // count of how many threads are holding read lock
- private ThreadClass writeThread; // non-null if any thread holds write lock
- internal ReaderPool readerPool;
- private int upgradeCount;
+ private ISet<MergePolicy.OneMerge> runningMerges = Lucene.Net.Support.Compatibility.SetFactory.CreateHashSet<MergePolicy.OneMerge>();
+ private IList<MergePolicy.OneMerge> mergeExceptions = new List<MergePolicy.OneMerge>();
+ private long mergeGen;
+ private bool stopMerges;
+
+ private int flushCount;
+ private int flushDeletesCount;
+
+ // Used to only allow one addIndexes to proceed at once
+ // TODO: use ReadWriteLock once we are on 5.0
+ private int readCount; // count of how many threads are holding read lock
+ private ThreadClass writeThread; // non-null if any thread holds write lock
+ internal ReaderPool readerPool;
+ private int upgradeCount;
private int readerTermsIndexDivisor = IndexReader.DEFAULT_TERMS_INDEX_DIVISOR;
-
- // This is a "write once" variable (like the organic dye
- // on a DVD-R that may or may not be heated by a laser and
- // then cooled to permanently record the event): it's
- // false, until getReader() is called for the first time,
- // at which point it's switched to true and never changes
- // back to false. Once this is true, we hold open and
- // reuse SegmentReader instances internally for applying
- // deletes, doing merges, and reopening near real-time
- // readers.
- private volatile bool poolReaders;
-
- /// <summary> Expert: returns a readonly reader, covering all committed as well as
- /// un-committed changes to the index. This provides "near real-time"
- /// searching, in that changes made during an IndexWriter session can be
- /// quickly made available for searching without closing the writer nor
- /// calling <see cref="Commit()" />.
- ///
- /// <p/>
- /// Note that this is functionally equivalent to calling {#commit} and then
- /// using <see cref="IndexReader.Open(Lucene.Net.Store.Directory, bool)" /> to open a new reader. But the turarnound
- /// time of this method should be faster since it avoids the potentially
- /// costly <see cref="Commit()" />.
- /// <p/>
- ///
+
+ // This is a "write once" variable (like the organic dye
+ // on a DVD-R that may or may not be heated by a laser and
+ // then cooled to permanently record the event): it's
+ // false, until getReader() is called for the first time,
+ // at which point it's switched to true and never changes
+ // back to false. Once this is true, we hold open and
+ // reuse SegmentReader instances internally for applying
+ // deletes, doing merges, and reopening near real-time
+ // readers.
+ private volatile bool poolReaders;
+
+ /// <summary> Expert: returns a readonly reader, covering all committed as well as
+ /// un-committed changes to the index. This provides "near real-time"
+ /// searching, in that changes made during an IndexWriter session can be
+ /// quickly made available for searching without closing the writer nor
+ /// calling <see cref="Commit()" />.
+ ///
+ /// <p/>
+ /// Note that this is functionally equivalent to calling {#commit} and then
+ /// using <see cref="IndexReader.Open(Lucene.Net.Store.Directory, bool)" /> to open a new reader. But the turarnound
+ /// time of this method should be faster since it avoids the potentially
+ /// costly <see cref="Commit()" />.
+ /// <p/>
+ ///
/// You must close the <see cref="IndexReader" /> returned by this method once you are done using it.
///
- /// <p/>
- /// It's <i>near</i> real-time because there is no hard
- /// guarantee on how quickly you can get a new reader after
- /// making changes with IndexWriter. You'll have to
- /// experiment in your situation to determine if it's
- /// faster enough. As this is a new and experimental
- /// feature, please report back on your findings so we can
- /// learn, improve and iterate.<p/>
- ///
- /// <p/>The resulting reader suppports <see cref="IndexReader.Reopen()" />
- ///, but that call will simply forward
- /// back to this method (though this may change in the
- /// future).<p/>
- ///
- /// <p/>The very first time this method is called, this
- /// writer instance will make every effort to pool the
- /// readers that it opens for doing merges, applying
- /// deletes, etc. This means additional resources (RAM,
- /// file descriptors, CPU time) will be consumed.<p/>
- ///
- /// <p/>For lower latency on reopening a reader, you should call <see cref="MergedSegmentWarmer" />
+ /// <p/>
+ /// It's <i>near</i> real-time because there is no hard
+ /// guarantee on how quickly you can get a new reader after
+ /// making changes with IndexWriter. You'll have to
+ /// experiment in your situation to determine if it's
+ /// faster enough. As this is a new and experimental
+ /// feature, please report back on your findings so we can
+ /// learn, improve and iterate.<p/>
+ ///
+ /// <p/>The resulting reader suppports <see cref="IndexReader.Reopen()" />
+ ///, but that call will simply forward
+ /// back to this method (though this may change in the
+ /// future).<p/>
+ ///
+ /// <p/>The very first time this method is called, this
+ /// writer instance will make every effort to pool the
+ /// readers that it opens for doing merges, applying
+ /// deletes, etc. This means additional resources (RAM,
+ /// file descriptors, CPU time) will be consumed.<p/>
+ ///
+ /// <p/>For lower latency on reopening a reader, you should call <see cref="MergedSegmentWarmer" />
/// to call <see cref="MergedSegmentWarmer" /> to
- /// pre-warm a newly merged segment before it's committed
- /// to the index. This is important for minimizing index-to-search
+ /// pre-warm a newly merged segment before it's committed
+ /// to the index. This is important for minimizing index-to-search
/// delay after a large merge.
- ///
- /// <p/>If an addIndexes* call is running in another thread,
- /// then this reader will only search those segments from
- /// the foreign index that have been successfully copied
- /// over, so far<p/>.
- ///
- /// <p/><b>NOTE</b>: Once the writer is closed, any
- /// outstanding readers may continue to be used. However,
- /// if you attempt to reopen any of those readers, you'll
- /// hit an <see cref="AlreadyClosedException" />.<p/>
- ///
- /// <p/><b>NOTE:</b> This API is experimental and might
- /// change in incompatible ways in the next release.<p/>
- ///
- /// </summary>
- /// <returns> IndexReader that covers entire index plus all
- /// changes made so far by this IndexWriter instance
- ///
- /// </returns>
- /// <throws> IOException </throws>
- public virtual IndexReader GetReader()
- {
+ ///
+ /// <p/>If an addIndexes* call is running in another thread,
+ /// then this reader will only search those segments from
+ /// the foreign index that have been successfully copied
+ /// over, so far<p/>.
+ ///
+ /// <p/><b>NOTE</b>: Once the writer is closed, any
+ /// outstanding readers may continue to be used. However,
+ /// if you attempt to reopen any of those readers, you'll
+ /// hit an <see cref="AlreadyClosedException" />.<p/>
+ ///
+ /// <p/><b>NOTE:</b> This API is experimental and might
+ /// change in incompatible ways in the next release.<p/>
+ ///
+ /// </summary>
+ /// <returns> IndexReader that covers entire index plus all
+ /// changes made so far by this IndexWriter instance
+ ///
+ /// </returns>
+ /// <throws> IOException </throws>
+ public virtual IndexReader GetReader()
+ {
return GetReader(readerTermsIndexDivisor);
- }
-
- /// <summary>Expert: like <see cref="GetReader()" />, except you can
- /// specify which termInfosIndexDivisor should be used for
- /// any newly opened readers.
- /// </summary>
- /// <param name="termInfosIndexDivisor">Subsambles which indexed
- /// terms are loaded into RAM. This has the same effect as <see cref="IndexWriter.TermIndexInterval" />
- /// 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>
- public virtual IndexReader GetReader(int termInfosIndexDivisor)
- {
+ }
+
+ /// <summary>Expert: like <see cref="GetReader()" />, except you can
+ /// specify which termInfosIndexDivisor should be used for
+ /// any newly opened readers.
+ /// </summary>
+ /// <param name="termInfosIndexDivisor">Subsambles which indexed
+ /// terms are loaded into RAM. This has the same effect as <see cref="IndexWriter.TermIndexInterval" />
+ /// 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>
+ public virtual IndexReader GetReader(int termInfosIndexDivisor)
+ {
EnsureOpen();
- if (infoStream != null)
- {
- Message("flush at getReader");
- }
-
- // Do this up front before flushing so that the readers
- // obtained during this flush are pooled, the first time
- // this method is called:
- poolReaders = true;
-
- // Prevent segmentInfos from changing while opening the
- // reader; in theory we could do similar retry logic,
- // just like we do when loading segments_N
+ if (infoStream != null)
+ {
+ Message("flush at getReader");
+ }
+
+ // Do this up front before flushing so that the readers
+ // obtained during this flush are pooled, the first time
+ // this method is called:
+ poolReaders = true;
+
+ // Prevent segmentInfos from changing while opening the
+ // reader; in theory we could do similar retry logic,
+ // just like we do when loading segments_N
IndexReader r;
- lock (this)
- {
+ lock (this)
+ {
Flush(false, true, true);
r = new ReadOnlyDirectoryReader(this, segmentInfos, termInfosIndexDivisor);
- }
+ }
MaybeMerge();
return r;
- }
-
- /// <summary>Holds shared SegmentReader instances. IndexWriter uses
- /// SegmentReaders for 1) applying deletes, 2) doing
- /// merges, 3) handing out a real-time reader. This pool
- /// reuses instances of the SegmentReaders in all these
- /// places if it is in "near real-time mode" (getReader()
- /// has been called on this instance).
- /// </summary>
-
- internal class ReaderPool : IDisposable
- {
- public ReaderPool(IndexWriter enclosingInstance)
- {
- InitBlock(enclosingInstance);
- }
- private void InitBlock(IndexWriter enclosingInstance)
- {
- this.enclosingInstance = enclosingInstance;
- }
- private IndexWriter enclosingInstance;
- public IndexWriter Enclosing_Instance
- {
- get
- {
- return enclosingInstance;
- }
-
- }
+ }
+
+ /// <summary>Holds shared SegmentReader instances. IndexWriter uses
+ /// SegmentReaders for 1) applying deletes, 2) doing
+ /// merges, 3) handing out a real-time reader. This pool
+ /// reuses instances of the SegmentReaders in all these
+ /// places if it is in "near real-time mode" (getReader()
+ /// has been called on this instance).
+ /// </summary>
+
+ internal class ReaderPool : IDisposable
+ {
+ public ReaderPool(IndexWriter enclosingInstance)
+ {
+ InitBlock(enclosingInstance);
+ }
+ private void InitBlock(IndexWriter enclosingInstance)
+ {
+ this.enclosingInstance = enclosingInstance;
+ }
+ private IndexWriter enclosingInstance;
+ public IndexWriter Enclosing_Instance
+ {
+ get
+ {
+ return enclosingInstance;
+ }
+
+ }
private IDictionary<SegmentInfo, SegmentReader> readerMap = new HashMap<SegmentInfo, SegmentReader>();
-
- /// <summary>Forcefully clear changes for the specifed segments,
- /// and remove from the pool. This is called on succesful merge.
- /// </summary>
- internal virtual void Clear(SegmentInfos infos)
- {
- lock (this)
- {
- if (infos == null)
- {
+
+ /// <summary>Forcefully clear changes for the specifed segments,
+ /// and remove from the pool. This is called on succesful merge.
+ /// </summary>
+ internal virtual void Clear(SegmentInfos infos)
+ {
+ lock (this)
+ {
+ if (infos == null)
+ {
foreach(KeyValuePair<SegmentInfo, SegmentReader> ent in readerMap)
- {
- ent.Value.hasChanges = false;
- }
- }
- else
- {
+ {
+ ent.Value.hasChanges = false;
+ }
+ }
+ else
+ {
foreach(SegmentInfo info in infos)
- {
- if (readerMap.ContainsKey(info))
- {
- readerMap[info].hasChanges = false;
- }
- }
- }
- }
- }
-
- // used only by asserts
- public virtual bool InfoIsLive(SegmentInfo info)
- {
- lock (this)
- {
- int idx = Enclosing_Instance.segmentInfos.IndexOf(info);
- System.Diagnostics.Debug.Assert(idx != -1);
+ {
+ if (readerMap.ContainsKey(info))
+ {
+ readerMap[info].hasChanges = false;
+ }
+ }
+ }
+ }
+ }
+
+ // used only by asserts
+ public virtual bool InfoIsLive(SegmentInfo info)
+ {
+ lock (this)
+ {
+ int idx = Enclosing_Instance.segmentInfos.IndexOf(info);
+ System.Diagnostics.Debug.Assert(idx != -1);
System.Diagnostics.Debug.Assert(Enclosing_Instance.segmentInfos[idx] == info);
- return true;
- }
- }
-
- public virtual SegmentInfo MapToLive(SegmentInfo info)
- {
- lock (this)
- {
- int idx = Enclosing_Instance.segmentInfos.IndexOf(info);
- if (idx != - 1)
- {
- info = Enclosing_Instance.segmentInfos[idx];
- }
- return info;
- }
- }
-
- /// <summary> Release the segment reader (i.e. decRef it and close if there
- /// are no more references.
- /// </summary>
- /// <param name="sr">
- /// </param>
- /// <throws> IOException </throws>
- public virtual void Release(SegmentReader sr)
- {
- lock (this)
- {
- Release(sr, false);
- }
- }
-
- /// <summary> Release the segment reader (i.e. decRef it and close if there
- /// are no more references.
- /// </summary>
- /// <param name="sr">
- /// </param>
- /// <param name="drop"></param>
- /// <throws> IOException </throws>
- public virtual void Release(SegmentReader sr, bool drop)
- {
- lock (this)
- {
-
- bool pooled = readerMap.ContainsKey(sr.SegmentInfo);
+ return true;
+ }
+ }
+
+ public virtual SegmentInfo MapToLive(SegmentInfo info)
+ {
+ lock (this)
+ {
+ int idx = Enclosing_Instance.segmentInfos.IndexOf(info);
+ if (idx != - 1)
+ {
+ info = Enclosing_Instance.segmentInfos[idx];
+ }
+ return info;
+ }
+ }
+
+ /// <summary> Release the segment reader (i.e. decRef it and close if there
+ /// are no more references.
+ /// </summary>
+ /// <param name="sr">
+ /// </param>
+ /// <throws> IOException </throws>
+ public virtual void Release(SegmentReader sr)
+ {
+ lock (this)
+ {
+ Release(sr, false);
+ }
+ }
+
+ /// <summary> Release the segment reader (i.e. decRef it and close if there
+ /// are no more references.
+ /// </summary>
+ /// <param name="sr">
+ /// </param>
+ /// <param name="drop"></param>
+ /// <throws> IOException </throws>
+ public virtual void Release(SegmentReader sr, bool drop)
+ {
+ lock (this)
+ {
+
+ bool pooled = readerMap.ContainsKey(sr.SegmentInfo);
System.Diagnostics.Debug.Assert(!pooled || readerMap[sr.SegmentInfo] == sr);
// Drop caller's ref; for an external reader (not
// pooled), this decRef will close it
- sr.DecRef();
-
- if (pooled && (drop || (!Enclosing_Instance.poolReaders && sr.RefCount == 1)))
- {
+ sr.DecRef();
+
+ if (pooled && (drop || (!Enclosing_Instance.poolReaders && sr.RefCount == 1)))
+ {
// We invoke deleter.checkpoint below, so we must be
// sync'd on IW if there are changes:
-
+
// TODO: Java 1.5 has this, .NET can't.
- // System.Diagnostics.Debug.Assert(!sr.hasChanges || Thread.holdsLock(enclosingInstance));
+ // System.Diagnostics.Debug.Assert(!sr.hasChanges || Thread.holdsLock(enclosingInstance));
// Discard (don't save) changes when we are dropping
// the reader; this is used only on the sub-readers
@@ -526,9 +526,9 @@ namespace Lucene.Net.Index
sr.hasChanges &= !drop;
bool hasChanges = sr.hasChanges;
-
- // Drop our ref -- this will commit any pending
- // changes to the dir
+
+ // Drop our ref -- this will commit any pending
+ // changes to the dir
sr.Close();
// We are the last ref to this reader; since we're
@@ -542,17 +542,17 @@ namespace Lucene.Net.Index
// file.
enclosingInstance.deleter.Checkpoint(enclosingInstance.segmentInfos, false);
}
- }
- }
- }
+ }
+ }
+ }
/// <summary>Remove all our references to readers, and commits
/// any pending changes.
/// </summary>
- public void Dispose()
- {
- Dispose(true);
- }
+ public void Dispose()
+ {
+ Dispose(true);
+ }
protected void Dispose(bool disposing)
{
@@ -593,359 +593,359 @@ namespace Lucene.Net.Index
}
}
}
-
- /// <summary> Commit all segment reader in the pool.</summary>
- /// <throws> IOException </throws>
- internal virtual void Commit()
- {
+
+ /// <summary> Commit all segment reader in the pool.</summary>
+ /// <throws> IOException </throws>
+ internal virtual void Commit()
+ {
// We invoke deleter.checkpoint below, so we must be
// sync'd on IW:
// TODO: assert Thread.holdsLock(IndexWriter.this);
lock (this)
- {
+ {
foreach(KeyValuePair<SegmentInfo,SegmentReader> ent in readerMap)
- {
- SegmentReader sr = ent.Value;
- if (sr.hasChanges)
- {
- System.Diagnostics.Debug.Assert(InfoIsLive(sr.SegmentInfo));
- sr.DoCommit(null);
+ {
+ SegmentReader sr = ent.Value;
+ if (sr.hasChanges)
+ {
+ System.Diagnostics.Debug.Assert(InfoIsLive(sr.SegmentInfo));
+ sr.DoCommit(null);
// Must checkpoint w/ deleter, because this
// segment reader will have created new _X_N.del
// file.
enclosingInstance.deleter.Checkpoint(enclosingInstance.segmentInfos, false);
- }
- }
- }
- }
-
- /// <summary> Returns a ref to a clone. NOTE: this clone is not
- /// enrolled in the pool, so you should simply close()
- /// it when you're done (ie, do not call release()).
- /// </summary>
- public virtual SegmentReader GetReadOnlyClone(SegmentInfo info, bool doOpenStores, int termInfosIndexDivisor)
- {
- lock (this)
- {
- SegmentReader sr = Get(info, doOpenStores, BufferedIndexInput.BUFFER_SIZE, termInfosIndexDivisor);
- try
- {
- return (SegmentReader) sr.Clone(true);
- }
- finally
- {
- sr.DecRef();
- }
- }
- }
-
- /// <summary> Obtain a SegmentReader from the readerPool. The reader
- /// must be returned by calling <see cref="Release(SegmentReader)" />
- /// </summary>
- /// <seealso cref="Release(SegmentReader)">
- /// </seealso>
- /// <param name="info">
- /// </param>
- /// <param name="doOpenStores">
- /// </param>
- /// <throws> IOException </throws>
- public virtual SegmentReader Get(SegmentInfo info, bool doOpenStores)
- {
- lock (this)
- {
+ }
+ }
+ }
+ }
+
+ /// <summary> Returns a ref to a clone. NOTE: this clone is not
+ /// enrolled in the pool, so you should simply close()
+ /// it when you're done (ie, do not call release()).
+ /// </summary>
+ public virtual SegmentReader GetReadOnlyClone(SegmentInfo info, bool doOpenStores, int termInfosIndexDivisor)
+ {
+ lock (this)
+ {
+ SegmentReader sr = Get(info, doOpenStores, BufferedIndexInput.BUFFER_SIZE, termInfosIndexDivisor);
+ try
+ {
+ return (SegmentReader) sr.Clone(true);
+ }
+ finally
+ {
+ sr.DecRef();
+ }
+ }
+ }
+
+ /// <summary> Obtain a SegmentReader from the readerPool. The reader
+ /// must be returned by calling <see cref="Release(SegmentReader)" />
+ /// </summary>
+ /// <seealso cref="Release(SegmentReader)">
+ /// </seealso>
+ /// <param name="info">
+ /// </param>
+ /// <param name="doOpenStores">
+ /// </param>
+ /// <throws> IOException </throws>
+ public virtual SegmentReader Get(SegmentInfo info, bool doOpenStores)
+ {
+ lock (this)
+ {
return Get(info, doOpenStores, BufferedIndexInput.BUFFER_SIZE, enclosingInstance.readerTermsIndexDivisor);
- }
- }
- /// <summary> Obtain a SegmentReader from the readerPool. The reader
- /// must be returned by calling <see cref="Release(SegmentReader)" />
- ///
- /// </summary>
- /// <seealso cref="Release(SegmentReader)">
- /// </seealso>
- /// <param name="info">
- /// </param>
- /// <param name="doOpenStores">
- /// </param>
- /// <param name="readBufferSize">
- /// </param>
- /// <param name="termsIndexDivisor">
- /// </param>
- /// <throws> IOException </throws>
- public virtual SegmentReader Get(SegmentInfo info, bool doOpenStores, int readBufferSize, int termsIndexDivisor)
- {
- lock (this)
- {
- if (Enclosing_Instance.poolReaders)
- {
- readBufferSize = BufferedIndexInput.BUFFER_SIZE;
- }
-
- SegmentReader sr = readerMap[info];
- if (sr == null)
- {
- // TODO: we may want to avoid doing this while
- // synchronized
- // Returns a ref, which we xfer to readerMap:
- sr = SegmentReader.Get(false, info.dir, info, readBufferSize, doOpenStores, termsIndexDivisor);
+ }
+ }
+ /// <summary> Obtain a SegmentReader from the readerPool. The reader
+ /// must be returned by calling <see cref="Release(SegmentReader)" />
+ ///
+ /// </summary>
+ /// <seealso cref="Release(SegmentReader)">
+ /// </seealso>
+ /// <param name="info">
+ /// </param>
+ /// <param name="doOpenStores">
+ /// </param>
+ /// <param name="readBufferSize">
+ /// </param>
+ /// <param name="termsIndexDivisor">
+ /// </param>
+ /// <throws> IOException </throws>
+ public virtual SegmentReader Get(SegmentInfo info, bool doOpenStores, int readBufferSize, int termsIndexDivisor)
+ {
+ lock (this)
+ {
+ if (Enclosing_Instance.poolReaders)
+ {
+ readBufferSize = BufferedIndexInput.BUFFER_SIZE;
+ }
+
+ SegmentReader sr = readerMap[info];
+ if (sr == null)
+ {
+ // TODO: we may want to avoid doing this while
+ // synchronized
+ // Returns a ref, which we xfer to readerMap:
+ sr = SegmentReader.Get(false, info.dir, info, readBufferSize, doOpenStores, termsIndexDivisor);
if (info.dir == enclosingInstance.directory)
{
// Only pool if reader is not external
readerMap[info]=sr;
}
- }
- else
- {
- if (doOpenStores)
- {
- sr.OpenDocStores();
- }
- if (termsIndexDivisor != - 1 && !sr.TermsIndexLoaded())
- {
- // If this reader was originally opened because we
- // needed to merge it, we didn't load the terms
- // index. But now, if the caller wants the terms
- // index (eg because it's doing deletes, or an NRT
- // reader is being opened) we ask the reader to
- // load its terms index.
- sr.LoadTermsIndex(termsIndexDivisor);
- }
- }
-
- // Return a ref to our caller
+ }
+ else
+ {
+ if (doOpenStores)
+ {
+ sr.OpenDocStores();
+ }
+ if (termsIndexDivisor != - 1 && !sr.TermsIndexLoaded())
+ {
+ // If this reader was originally opened because we
+ // needed to merge it, we didn't load the terms
+ // index. But now, if the caller wants the terms
+ // index (eg because it's doing deletes, or an NRT
+ // reader is being opened) we ask the reader to
+ // load its terms index.
+ sr.LoadTermsIndex(termsIndexDivisor);
+ }
+ }
+
+ // Return a ref to our caller
if (info.dir == enclosingInstance.directory)
{
// Only incRef if we pooled (reader is not external)
sr.IncRef();
}
- return sr;
- }
- }
-
- // Returns a ref
- public virtual SegmentReader GetIfExists(SegmentInfo info)
- {
- lock (this)
- {
- SegmentReader sr = readerMap[info];
- if (sr != null)
- {
- sr.IncRef();
- }
- return sr;
- }
- }
- }
-
- /// <summary> Obtain the number of deleted docs for a pooled reader.
- /// If the reader isn't being pooled, the segmentInfo's
- /// delCount is returned.
- /// </summary>
- public virtual int NumDeletedDocs(SegmentInfo info)
- {
- SegmentReader reader = readerPool.GetIfExists(info);
- try
- {
- if (reader != null)
- {
- return reader.NumDeletedDocs;
- }
- else
- {
- return info.GetDelCount();
- }
- }
- finally
- {
- if (reader != null)
- {
- readerPool.Release(reader);
- }
- }
- }
-
- internal virtual void AcquireWrite()
- {
- lock (this)
- {
- System.Diagnostics.Debug.Assert(writeThread != ThreadClass.Current());
- while (writeThread != null || readCount > 0)
- DoWait();
-
- // We could have been closed while we were waiting:
- EnsureOpen();
-
- writeThread = ThreadClass.Current();
- }
- }
-
- internal virtual void ReleaseWrite()
- {
- lock (this)
- {
- System.Diagnostics.Debug.Assert(ThreadClass.Current() == writeThread);
- writeThread = null;
- System.Threading.Monitor.PulseAll(this);
- }
- }
-
- internal virtual void AcquireRead()
- {
- lock (this)
- {
- ThreadClass current = ThreadClass.Current();
- while (writeThread != null && writeThread != current)
- DoWait();
-
- readCount++;
- }
- }
-
- // Allows one readLock to upgrade to a writeLock even if
- // there are other readLocks as long as all other
- // readLocks are also blocked in this method:
- internal virtual void UpgradeReadToWrite()
- {
- lock (this)
- {
- System.Diagnostics.Debug.Assert(readCount > 0);
- upgradeCount++;
- while (readCount > upgradeCount || writeThread != null)
- {
- DoWait();
- }
-
- writeThread = ThreadClass.Current();
- readCount--;
- upgradeCount--;
- }
- }
-
- internal virtual void ReleaseRead()
- {
- lock (this)
- {
- readCount--;
- System.Diagnostics.Debug.Assert(readCount >= 0);
- System.Threading.Monitor.PulseAll(this);
- }
- }
-
- internal bool IsOpen(bool includePendingClose)
- {
- lock (this)
- {
- return !(closed || (includePendingClose && closing));
- }
- }
-
- /// <summary> Used internally to throw an <see cref="AlreadyClosedException" />
- /// if this IndexWriter has been
- /// closed.
- /// </summary>
- /// <throws> AlreadyClosedException if this IndexWriter is </throws>
- protected internal void EnsureOpen(bool includePendingClose)
- {
- lock (this)
- {
- if (!IsOpen(includePendingClose))
- {
- throw new AlreadyClosedException("this IndexWriter is closed");
- }
- }
- }
-
- protected internal void EnsureOpen()
- {
- lock (this)
- {
- EnsureOpen(true);
- }
- }
-
- /// <summary> Prints a message to the infoStream (if non-null),
- /// prefixed with the identifying information for this
- /// writer and the thread that's calling it.
- /// </summary>
- public virtual void Message(System.String message)
- {
- if (infoStream != null)
+ return sr;
+ }
+ }
+
+ // Returns a ref
+ public virtual SegmentReader GetIfExists(SegmentInfo info)
+ {
+ lock (this)
+ {
+ SegmentReader sr = readerMap[info];
+ if (sr != null)
+ {
+ sr.IncRef();
+ }
+ return sr;
+ }
+ }
+ }
+
+ /// <summary> Obtain the number of deleted docs for a pooled reader.
+ /// If the reader isn't being pooled, the segmentInfo's
+ /// delCount is returned.
+ /// </summary>
+ public virtual int NumDeletedDocs(SegmentInfo info)
+ {
+ SegmentReader reader = readerPool.GetIfExists(info);
+ try
+ {
+ if (reader != null)
+ {
+ return reader.NumDeletedDocs;
+ }
+ else
+ {
+ return info.GetDelCount();
+ }
+ }
+ finally
+ {
+ if (reader != null)
+ {
+ readerPool.Release(reader);
+ }
+ }
+ }
+
+ internal virtual void AcquireWrite()
+ {
+ lock (this)
+ {
+ System.Diagnostics.Debug.Assert(writeThread != ThreadClass.Current());
+ while (writeThread != null || readCount > 0)
+ DoWait();
+
+ // We could have been closed while we were waiting:
+ EnsureOpen();
+
+ writeThread = ThreadClass.Current();
+ }
+ }
+
+ internal virtual void ReleaseWrite()
+ {
+ lock (this)
+ {
+ System.Diagnostics.Debug.Assert(ThreadClass.Current() == writeThread);
+ writeThread = null;
+ System.Threading.Monitor.PulseAll(this);
+ }
+ }
+
+ internal virtual void AcquireRead()
+ {
+ lock (this)
+ {
+ ThreadClass current = ThreadClass.Current();
+ while (writeThread != null && writeThread != current)
+ DoWait();
+
+ readCount++;
+ }
+ }
+
+ // Allows one readLock to upgrade to a writeLock even if
+ // there are other readLocks as long as all other
+ // readLocks are also blocked in this method:
+ internal virtual void UpgradeReadToWrite()
+ {
+ lock (this)
+ {
+ System.Diagnostics.Debug.Assert(readCount > 0);
+ upgradeCount++;
+ while (readCount > upgradeCount || writeThread != null)
+ {
+ DoWait();
+ }
+
+ writeThread = ThreadClass.Current();
+ readCount--;
+ upgradeCount--;
+ }
+ }
+
+ internal virtual void ReleaseRead()
+ {
+ lock (this)
+ {
+ readCount--;
+ System.Diagnostics.Debug.Assert(readCount >= 0);
+ System.Threading.Monitor.PulseAll(this);
+ }
+ }
+
+ internal bool IsOpen(bool includePendingClose)
+ {
+ lock (this)
+ {
+ return !(closed || (includePendingClose && closing));
+ }
+ }
+
+ /// <summary> Used internally to throw an <see cref="AlreadyClosedException" />
+ /// if this IndexWriter has been
+ /// closed.
+ /// </summary>
+ /// <throws> AlreadyClosedException if this IndexWriter is </throws>
+ protected internal void EnsureOpen(bool includePendingClose)
+ {
+ lock (this)
+ {
+ if (!IsOpen(includePendingClose))
+ {
+ throw new AlreadyClosedException("this IndexWriter is closed");
+ }
+ }
+ }
+
+ protected internal void EnsureOpen()
+ {
+ lock (this)
+ {
+ EnsureOpen(true);
+ }
+ }
+
+ /// <summary> Prints a message to the infoStream (if non-null),
+ /// prefixed with the identifying information for this
+ /// writer and the thread that's calling it.
+ /// </summary>
+ public virtual void Message(System.String message)
+ {
+ if (infoStream != null)
infoStream.WriteLine("IW " + messageID + " [" + DateTime.Now.ToString() + "; " + ThreadClass.Current().Name + "]: " + message);
- }
-
- private void SetMessageID(System.IO.StreamWriter infoStream)
- {
- lock (this)
- {
- if (infoStream != null && messageID == - 1)
- {
- lock (MESSAGE_ID_LOCK)
- {
- messageID = MESSAGE_ID++;
- }
- }
- this.infoStream = infoStream;
- }
- }
-
- /// <summary> Casts current mergePolicy to LogMergePolicy, and throws
- /// an exception if the mergePolicy is not a LogMergePolicy.
- /// </summary>
- private LogMergePolicy LogMergePolicy
- {
- get
- {
- if (mergePolicy is LogMergePolicy)
- return (LogMergePolicy) mergePolicy;
-
- throw new System.ArgumentException(
- "this method can only be called when the merge policy is the default LogMergePolicy");
- }
- }
-
- /// <summary><p/>Gets or sets the current setting of whether newly flushed
- /// segments will use the compound file format. Note that
- /// this just returns the value previously set with
- /// setUseCompoundFile(boolean), or the default value
- /// (true). You cannot use this to query the status of
- /// previously flushed segments.<p/>
- ///
- /// <p/>Note that this method is a convenience method: it
- /// just calls mergePolicy.getUseCompoundFile as long as
- /// mergePolicy is an instance of <see cref="LogMergePolicy" />.
- /// Otherwise an IllegalArgumentException is thrown.<p/>
- ///
- /// </summary>
- public virtual bool UseCompoundFile
- {
- get { return LogMergePolicy.GetUseCompoundFile(); }
- set
- {
- LogMergePolicy.SetUseCompoundFile(value);
- LogMergePolicy.SetUseCompoundDocStore(value);
- }
- }
-
- /// <summary>Expert: Set the Similarity implementation used by this IndexWriter.
- /// </summary>
- public virtual void SetSimilarity(Similarity similarity)
- {
- EnsureOpen();
- this.similarity = similarity;
- docWriter.SetSimilarity(similarity);
- }
-
- /// <summary>Expert: Return the Similarity implementation used by this IndexWriter.
- ///
- /// <p/>This defaults to the current value of <see cref="Search.Similarity.Default" />.
- /// </summary>
- public virtual Similarity Similarity
- {
- get
- {
- EnsureOpen();
- return this.similarity;
- }
- }
+ }
+
+ private void SetMessageID(System.IO.StreamWriter infoStream)
+ {
+ lock (this)
+ {
+ if (infoStream != null && messageID == - 1)
+ {
+ lock (MESSAGE_ID_LOCK)
+ {
+ messageID = MESSAGE_ID++;
+ }
+ }
+ this.infoStream = infoStream;
+ }
+ }
+
+ /// <summary> Casts current mergePolicy to LogMergePolicy, and throws
+ /// an exception if the mergePolicy is not a LogMergePolicy.
+ /// </summary>
+ private LogMergePolicy LogMergePolicy
+ {
+ get
+ {
+ if (mergePolicy is LogMergePolicy)
+ return (LogMergePolicy) mergePolicy;
+
+ throw new System.ArgumentException(
+ "this method can only be called when the merge policy is the default LogMergePolicy");
+ }
+ }
+
+ /// <summary><p/>Gets or sets the current setting of whether newly flushed
+ /// segments will use the compound file format. Note that
+ /// this just returns the value previously set with
+ /// setUseCompoundFile(boolean), or the default value
+ /// (true). You cannot use this to query the status of
+ /// previously flushed segments.<p/>
+ ///
+ /// <p/>Note that this method is a convenience method: it
+ /// just calls mergePolicy.getUseCompoundFile as long as
+ /// mergePolicy is an instance of <see cref="LogMergePolicy" />.
+ /// Otherwise an IllegalArgumentException is thrown.<p/>
+ ///
+ /// </summary>
+ public virtual bool UseCompoundFile
+ {
+ get { return LogMergePolicy.GetUseCompoundFile(); }
+ set
+ {
+ LogMergePolicy.SetUseCompoundFile(value);
+ LogMergePolicy.SetUseCompoundDocStore(value);
+ }
+ }
+
+ /// <summary>Expert: Set the Similarity implementation used by this IndexWriter.
+ /// </summary>
+ public virtual void SetSimilarity(Similarity similarity)
+ {
+ EnsureOpen();
+ this.similarity = similarity;
+ docWriter.SetSimilarity(similarity);
+ }
+
+ /// <summary>Expert: Return the Similarity implementation used by this IndexWriter.
+ ///
+ /// <p/>This defaults to the current value of <see cref="Search.Similarity.Default" />.
+ /// </summary>
+ public virtual Similarity Similarity
+ {
+ get
+ {
+ EnsureOpen();
+ return this.similarity;
+ }
+ }
/// <summary>Expert: Gets or sets the interval between indexed terms. Large values cause less
@@ -970,361 +970,361 @@ namespace Lucene.Net.Index
/// </summary>
/// <seealso cref="DEFAULT_TERM_INDEX_INTERVAL">
/// </seealso>
- public virtual int TermIndexInterval
- {
- get
- {
- // We pass false because this method is called by SegmentMerger while we are in the process of closing
- EnsureOpen(false);
- return termIndexInterval;
- }
- set
- {
- EnsureOpen();
- this.termIndexInterval = value;
- }
- }
-
- /// <summary> Constructs an IndexWriter for the index in <c>d</c>.
- /// Text will be analyzed with <c>a</c>. If <c>create</c>
- /// is true, then a new, empty index will be created in
- /// <c>d</c>, replacing the index already there, if any.
- ///
- /// </summary>
- /// <param name="d">the index directory
- /// </param>
- /// <param name="a">the analyzer to use
- /// </param>
- /// <param name="create"><c>true</c> to create the index or overwrite
- /// the existing one; <c>false</c> to append to the existing
- /// index
- /// </param>
- /// <param name="mfl">Maximum field length in number of terms/tokens: LIMITED, UNLIMITED, or user-specified
- /// via the MaxFieldLength constructor.
- /// </param>
- /// <throws> CorruptIndexException if the index is corrupt </throws>
- /// <throws> LockObtainFailedException if another writer </throws>
- /// <summary> has this index open (<c>write.lock</c> could not
- /// be obtained)
- /// </summary>
- /// <throws> IOException if the directory cannot be read/written to, or </throws>
- /// <summary> if it does not exist and <c>create</c> is
- /// <c>false</c> or if there is any other low-level
- /// IO error
- /// </summary>
- public IndexWriter(Directory d, Analyzer a, bool create, MaxFieldLength mfl)
- {
- InitBlock();
- Init(d, a, create, null, mfl.Limit, null, null);
- }
-
- /// <summary> Constructs an IndexWriter for the index in
- /// <c>d</c>, first creating it if it does not
- /// already exist.
- ///
- /// </summary>
- /// <param name="d">the index directory
- /// </param>
- /// <param name="a">the analyzer to use
- /// </param>
- /// <param name="mfl">Maximum field length in number of terms/tokens: LIMITED, UNLIMITED, or user-specified
- /// via the MaxFieldLength constructor.
- /// </param>
- /// <throws> CorruptIndexException if the index is corrupt </throws>
- /// <throws> LockObtainFailedException if another writer </throws>
- /// <summary> has this index open (<c>write.lock</c> could not
- /// be obtained)
- /// </summary>
- /// <throws> IOException if the directory cannot be </throws>
- /// <summary> read/written to or if there is any other low-level
- /// IO error
- /// </summary>
- public IndexWriter(Directory d, Analyzer a, MaxFieldLength mfl)
- {
- InitBlock();
- Init(d, a, null, mfl.Limit, null, null);
- }
-
- /// <summary> Expert: constructs an IndexWriter with a custom <see cref="IndexDeletionPolicy" />
- ///, for the index in <c>d</c>,
- /// first creating it if it does not already exist. Text
- /// will be analyzed with <c>a</c>.
- ///
- /// </summary>
- /// <param name="d">the index directory
- /// </param>
- /// <param name="a">the analyzer to use
- /// </param>
- /// <param name="deletionPolicy">see <a href="#deletionPolicy">above</a>
- /// </param>
- /// <param name="mfl">whether or not to limit field lengths
- /// </param>
- /// <throws> CorruptIndexException if the index is corrupt </throws>
- /// <throws> LockObtainFailedException if another writer </throws>
- /// <summary> has this index open (<c>write.lock</c> could not
- /// be obtained)
- /// </summary>
- /// <throws> IOException if the directory cannot be </throws>
- /// <summary> read/written to or if there is any other low-level
- /// IO error
- /// </summary>
- public IndexWriter(Directory d, Analyzer a, IndexDeletionPolicy deletionPolicy, MaxFieldLength mfl)
- {
- InitBlock();
- Init(d, a, deletionPolicy, mfl.Limit, null, null);
- }
-
- /// <summary> Expert: constructs an IndexWriter with a custom <see cref="IndexDeletionPolicy" />
- ///, for the index in <c>d</c>.
- /// Text will be analyzed with <c>a</c>. If
- /// <c>create</c> is true, then a new, empty index
- /// will be created in <c>d</c>, replacing the index
- /// already there, if any.
- ///
- /// </summary>
- /// <param name="d">the index directory
- /// </param>
- /// <param name="a">the analyzer to use
- /// </param>
- /// <param name="create"><c>true</c> to create the index or overwrite
- /// the existing one; <c>false</c> to append to the existing
- /// index
- /// </param>
- /// <param name="deletionPolicy">see <a href="#deletionPolicy">above</a>
- /// </param>
- /// <param name="mfl"><see cref="Lucene.Net.Index.IndexWriter.MaxFieldLength" />, whether or not to limit field lengths. Value is in number of terms/tokens
- /// </param>
- /// <throws> CorruptIndexException if the index is corrupt </throws>
- /// <throws> LockObtainFailedException if another writer </throws>
- /// <summary> has this index open (<c>write.lock</c> could not
- /// be obtained)
- /// </summary>
- /// <throws> IOException if the directory cannot be read/written to, or </throws>
- /// <summary> if it does not exist and <c>create</c> is
- /// <c>false</c> or if there is any other low-level
- /// IO error
- /// </summary>
- public IndexWriter(Directory d, Analyzer a, bool create, IndexDeletionPolicy deletionPolicy, MaxFieldLength mfl)
- {
- InitBlock();
- Init(d, a, create, deletionPolicy, mfl.Limit, null, null);
- }
-
- /// <summary> Expert: constructs an IndexWriter with a custom <see cref="IndexDeletionPolicy" />
- /// and <see cref="IndexingChain" />,
- /// for the index in <c>d</c>.
- /// Text will be analyzed with <c>a</c>. If
- /// <c>create</c> is true, then a new, empty index
- /// will be created in <c>d</c>, replacing the index
- /// already there, if any.
- ///
- /// </summary>
- /// <param name="d">the index directory
- /// </param>
- /// <param name="a">the analyzer to use
- /// </param>
- /// <param name="create"><c>true</c> to create the index or overwrite
- /// the existing one; <c>false</c> to append to the existing
- /// index
- /// </param>
- /// <param name="deletionPolicy">see <a href="#deletionPolicy">above</a>
- /// </param>
- /// <param name="mfl">whether or not to limit field lengths, value is in number of terms/tokens. See <see cref="Lucene.Net.Index.IndexWriter.MaxFieldLength" />.
- /// </param>
- /// <param name="indexingChain">the <see cref="DocConsumer" /> chain to be used to
- /// process documents
- /// </param>
- /// <param name="commit">which commit to open
- /// </param>
- /// <throws> CorruptIndexException if the index is corrupt </throws>
- /// <throws> LockObtainFailedException if another writer </throws>
- /// <summary> has this index open (<c>write.lock</c> could not
- /// be obtained)
- /// </summary>
- /// <throws> IOException if the directory cannot be read/written to, or </throws>
- /// <summary> if it does not exist and <c>create</c> is
- /// <c>false</c> or if there is any other low-level
- /// IO error
- /// </summary>
- internal IndexWriter(Directory d, Analyzer a, bool create, IndexDeletionPolicy deletionPolicy, MaxFieldLength mfl, IndexingChain indexingChain, IndexCommit commit)
- {
- InitBlock();
- Init(d, a, create, deletionPolicy, mfl.Limit, indexingChain, commit);
- }
-
- /// <summary> Expert: constructs an IndexWriter on specific commit
- /// point, with a custom <see cref="IndexDeletionPolicy" />, for
- /// the index in <c>d</c>. Text will be analyzed
- /// with <c>a</c>.
- ///
- /// <p/> This is only meaningful if you've used a <see cref="IndexDeletionPolicy" />
- /// in that past that keeps more than
- /// just the last commit.
- ///
- /// <p/>This operation is similar to <see cref="Rollback()" />,
- /// except that method can only rollback what's been done
- /// with the current instance of IndexWriter since its last
- /// commit, whereas this method can rollback to an
- /// arbitrary commit point from the past, assuming the
- /// <see cref="IndexDeletionPolicy" /> has preserved past
- /// commits.
- ///
- /// </summary>
- /// <param name="d">the index directory
- /// </param>
- /// <param name="a">the analyzer to use
- /// </param>
- /// <param name="deletionPolicy">see <a href="#deletionPolicy">above</a>
- /// </param>
- /// <param name="mfl">whether or not to limit field lengths, value is in number of terms/tokens. See <see cref="Lucene.Net.Index.IndexWriter.MaxFieldLength" />.
- /// </param>
- /// <param name="commit">which commit to open
- /// </param>
- /// <throws> CorruptIndexException if the index is corrupt </throws>
- /// <throws> LockObtainFailedException if another writer </throws>
- /// <summary> has this index open (<c>write.lock</c> could not
- /// be obtained)
- /// </summary>
- /// <throws> IOException if the directory cannot be read/written to, or </throws>
- /// <summary> if it does not exist and <c>create</c> is
- /// <c>false</c> or if there is any other low-level
- /// IO error
- /// </summary>
- public IndexWriter(Directory d, Analyzer a, IndexDeletionPolicy deletionPolicy, MaxFieldLength mfl, IndexCommit commit)
- {
- InitBlock();
- Init(d, a, false, deletionPolicy, mfl.Limit, null, commit);
- }
-
- private void Init(Directory d, Analyzer a, IndexDeletionPolicy deletionPolicy, int maxFieldLength, IndexingChain indexingChain, IndexCommit commit)
- {
- if (IndexReader.IndexExists(d))
- {
- Init(d, a, false, deletionPolicy, maxFieldLength, indexingChain, commit);
- }
- else
- {
- Init(d, a, true, deletionPolicy, maxFieldLength, indexingChain, commit);
- }
- }
-
- private void Init(Directory d, Analyzer a, bool create, IndexDeletionPolicy deletionPolicy, int maxFieldLength, IndexingChain indexingChain, IndexCommit commit)
- {
- directory = d;
- analyzer = a;
- SetMessageID(defaultInfoStream);
- this.maxFieldLength = maxFieldLength;
-
- if (indexingChain == null)
- indexingChain = DocumentsWriter.DefaultIndexingChain;
-
- if (create)
- {
- // Clear the write lock in case it's leftover:
- directory.ClearLock(WRITE_LOCK_NAME);
- }
-
- Lock writeLock = directory.MakeLock(WRITE_LOCK_NAME);
- if (!writeLock.Obtain(writeLockTimeout))
- // obtain write lock
- {
- throw new LockObtainFailedException("Index locked for write: " + writeLock);
- }
- this.writeLock = writeLock; // save it
-
- bool success = false;
- try
- {
- if (create)
- {
- // Try to read first. This is to allow create
- // against an index that's currently open for
- // searching. In this case we write the next
- // segments_N file with no segments:
- bool doCommit;
- try
- {
- segmentInfos.Read(directory);
- segmentInfos.Clear();
- doCommit = false;
- }
- catch (System.IO.IOException)
- {
- // Likely this means it's a fresh directory
- doCommit = true;
- }
-
- if (doCommit)
- {
- // Only commit if there is no segments file
- // in this dir already.
- segmentInfos.Commit(directory);
- synced.UnionWith(segmentInfos.Files(directory, true));
- }
- else
- {
- // Record that we have a change (zero out all
- // segments) pending:
- changeCount++;
- }
- }
- else
- {
- segmentInfos.Read(directory);
-
- if (commit != null)
- {
- // Swap out all segments, but, keep metadata in
- // SegmentInfos, like version & generation, to
- // preserve write-once. This is important if
- // readers are open against the future commit
- // points.
- if (commit.Directory != directory)
- throw new System.ArgumentException("IndexCommit's directory doesn't match my directory");
- SegmentInfos oldInfos = new SegmentInfos();
- oldInfos.Read(directory, commit.SegmentsFileName);
- segmentInfos.Replace(oldInfos);
- changeCount++;
- if (infoStream != null)
- Message("init: loaded commit \"" + commit.SegmentsFileName + "\"");
- }
-
- // We assume that this segments_N was previously
- // properly sync'd:
- synced.UnionWith(segmentInfos.Files(directory, true));
- }
-
- SetRollbackSegmentInfos(segmentInfos);
-
- docWriter = new DocumentsWriter(directory, this, indexingChain);
- docWriter.SetInfoStream(infoStream);
- docWriter.SetMaxFieldLength(maxFieldLength);
-
- // Default deleter (for backwards compatibility) is
- // KeepOnlyLastCommitDeleter:
- deleter = new IndexFileDeleter(directory, deletionPolicy == null?new KeepOnlyLastCommitDeletionPolicy():deletionPolicy, segmentInfos, infoStream, docWriter, synced);
-
- if (deleter.startingCommitDeleted)
- // Deletion policy deleted the "head" commit point.
- // We have to mark ourself as changed so that if we
- // are closed w/o any further changes we write a new
- // segments_N file.
- changeCount++;
-
- PushMaxBufferedDocs();
-
- if (infoStream != null)
- {
- Message("init: create=" + create);
- MessageState();
- }
+ public virtual int TermIndexInterval
+ {
+ get
+ {
+ // We pass false because this method is called by SegmentMerger while we are in the process of closing
+ EnsureOpen(false);
+ return termIndexInterval;
+ }
+ set
+ {
+ EnsureOpen();
+ this.termIndexInterval = value;
+ }
+ }
- success = true;
- }
- finally
- {
- if (!success)
- {
+ /// <summary> Constructs an IndexWriter for the index in <c>d</c>.
+ /// Text will be analyzed with <c>a</c>. If <c>create</c>
+ /// is true, then a new, empty index will be created in
+ /// <c>d</c>, replacing the index already there, if any.
+ ///
+ /// </summary>
+ /// <param name="d">the index directory
+ /// </param>
+ /// <param name="a">the analyzer to use
+ /// </param>
+ /// <param name="create"><c>true</c> to create the index or overwrite
+ /// the existing one; <c>false</c> to append to the existing
+ /// index
+ /// </param>
+ /// <param name="mfl">Maximum field length in number of terms/tokens: LIMITED, UNLIMITED, or user-specified
+ /// via the MaxFieldLength constructor.
+ /// </param>
+ /// <throws> CorruptIndexException if the index is corrupt </throws>
+ /// <throws> LockObtainFailedException if another writer </throws>
+ /// <summary> has this index open (<c>write.lock</c> could not
+ /// be obtained)
+ /// </summary>
+ /// <throws> IOException if the directory cannot be read/written to, or </throws>
+ /// <summary> if it does not exist and <c>create</c> is
+ /// <c>false</c> or if there is any other low-level
+ /// IO error
+ /// </summary>
+ public IndexWriter(Directory d, Analyzer a, bool create, MaxFieldLength mfl)
+ {
+ InitBlock();
+ Init(d, a, create, null, mfl.Limit, null, null);
+ }
+
+ /// <summary> Constructs an IndexWriter for the index in
+ /// <c>d</c>, first creating it if it does not
+ /// already exist.
+ ///
+ /// </summary>
+ /// <param name="d">the index directory
+ /// </param>
+ /// <param name="a">the analyzer to use
+ /// </param>
+ /// <param name="mfl">Maximum field length in number of terms/tokens: LIMITED, UNLIMITED, or user-specified
+ /// via the MaxFieldLength constructor.
+ /// </param>
+ /// <throws> CorruptIndexException if the index is corrupt </throws>
+ /// <throws> LockObtainFailedException if another writer </throws>
+ /// <summary> has this index open (<c>write.lock</c> could not
+ /// be obtained)
+ /// </summary>
+ /// <throws> IOException if the directory cannot be </throws>
+ /// <summary> read/written to or if there is any other low-level
+ /// IO error
+ /// </summary>
+ public IndexWriter(Directory d, Analyzer a, MaxFieldLength mfl)
+ {
+ InitBlock();
+ Init(d, a, null, mfl.Limit, null, null);
+ }
+
+ /// <summary> Expert: constructs an IndexWriter with a custom <see cref="IndexDeletionPolicy" />
+ ///, for the index in <c>d</c>,
+ /// first creating it if it does not already exist. Text
+ /// will be analyzed with <c>a</c>.
+ ///
+ /// </summary>
+ /// <param name="d">the index directory
+ /// </param>
+ /// <param name="a">the analyzer to use
+ /// </param>
+ /// <param name="deletionPolicy">see <a href="#deletionPolicy">above</a>
+ /// </param>
+ /// <param name="mfl">whether or not to limit field lengths
+ /// </param>
+ /// <throws> CorruptIndexException if the index is corrupt </throws>
+ /// <throws> LockObtainFailedException if another writer </throws>
+ /// <summary> has this index open (<c>write.lock</c> could not
+ /// be obtained)
+ /// </summary>
+ /// <throws> IOException if the directory cannot be </throws>
+ /// <summary> read/written to or if there is any other low-level
+ /// IO error
+ /// </summary>
+ public IndexWriter(Directory d, Analyzer a, IndexDeletionPolicy deletionPolicy, MaxFieldLength mfl)
+ {
+ InitBlock();
+ Init(d, a, deletionPolicy, mfl.Limit, null, null);
+ }
+
+ /// <summary> Expert: constructs an IndexWriter with a custom <see cref="IndexDeletionPolicy" />
+ ///, for the index in <c>d</c>.
+ /// Text will be analyzed with <c>a</c>. If
+ /// <c>create</c> is true, then a new, empty index
+ /// will be created in <c>d</c>, replacing the index
+ /// already there, if any.
+ ///
+ /// </summary>
+ /// <param name="d">the index directory
+ /// </param>
+ /// <param name="a">the analyzer to use
+ /// </param>
+ /// <param name="create"><c>true</c> to create the index or overwrite
+ /// the existing one; <c>false</c> to append to the existing
+ /// index
+ /// </param>
+ /// <param name="deletionPolicy">see <a href="#deletionPolicy">above</a>
+ /// </param>
+ /// <param name="mfl"><see cref="Lucene.Net.Index.IndexWriter.MaxFieldLength" />, whether or not to limit field lengths. Value is in number of terms/tokens
+ /// </param>
+ /// <throws> CorruptIndexException if the index is corrupt </throws>
+ /// <throws> LockObtainFailedException if another writer </throws>
+ /// <summary> has this index open (<c>write.lock</c> could not
+ /// be obtained)
+ /// </summary>
+ /// <throws> IOException if the directory cannot be read/written to, or </throws>
+ /// <summary> if it does not exist and <c>create</c> is
+ /// <c>false</c> or if there is any other low-level
+ /// IO error
+ /// </summary>
+ public IndexWriter(Directory d, Analyzer a, bool create, IndexDeletionPolicy deletionPolicy, MaxFieldLength mfl)
+ {
+ InitBlock();
+ Init(d, a, create, deletionPolicy, mfl.Limit, null, null);
+ }
+
+ /// <summary> Expert: constructs an IndexWriter with a custom <see cref="IndexDeletionPolicy" />
+ /// and <see cref="IndexingChain" />,
+ /// for the index in <c>d</c>.
+ /// Text will be analyzed with <c>a</c>. If
+ /// <c>create</c> is true, then a new, empty index
+ /// will be created in <c>d</c>, replacing the index
+ /// already there, if any.
+ ///
+ /// </summary>
+ /// <param name="d">the index directory
+ /// </param>
+ /// <param name="a">the analyzer to use
+ /// </param>
+ /// <param name="create"><c>true</c> to create the index or overwrite
+ /// the existing one; <c>false</c> to append to the existing
+ /// index
+ /// </param>
+ /// <param name="deletionPolicy">see <a href="#deletionPolicy">above</a>
+ /// </param>
+ /// <param name="mfl">whether or not to limit field lengths, value is in number of terms/tokens. See <see cref="Lucene.Net.Index.IndexWriter.MaxFieldLength" />.
+ /// </param>
+ /// <param name="indexingChain">the <see cref="DocConsumer" /> chain to be used to
+ /// process documents
+ /// </param>
+ /// <param name="commit">which commit to open
+ /// </param>
+ /// <throws> CorruptIndexException if the index is corrupt </throws>
+ /// <throws> LockObtainFailedException if another writer </throws>
+ /// <summary> has this index open (<c>write.lock</c> could not
+ /// be obtained)
+ /// </summary>
+ /// <throws> IOException if the directory cannot be read/written to, or </throws>
+ /// <summary> if it does not exist and <c>create</c> is
+ /// <c>false</c> or if there is any other low-level
+ /// IO error
+ /// </summary>
+ internal IndexWriter(Directory d, Analyzer a, bool create, IndexDeletionPolicy deletionPolicy, MaxFieldLength mfl, IndexingChain indexingChain, IndexCommit commit)
+ {
+ InitBlock();
+ Init(d, a, create, deletionPolicy, mfl.Limit, indexingChain, commit);
+ }
+
+ /// <summary> Expert: constructs an IndexWriter on specific commit
+ /// point, with a custom <see cref="IndexDeletionPolicy" />, for
+ /// the index in <c>d</c>. Text will be analyzed
+ /// with <c>a</c>.
+ ///
+ /// <p/> This is only meaningful if you've used a <see cref="IndexDeletionPolicy" />
+ /// in that past that keeps more than
+ /// just the last commit.
+ ///
+ /// <p/>This operation is similar to <see cref="Rollback()" />,
+ /// except that method can only rollback what's been done
+ /// with the current instance of IndexWriter since its last
+ /// commit, whereas this method can rollback to an
+ /// arbitrary commit point from the past, assuming the
+ /// <see cref="IndexDeletionPolicy" /> has preserved past
+ /// commits.
+ ///
+ /// </summary>
+ /// <param name="d">the index directory
+ /// </param>
+ /// <param name="a">the analyzer to use
+ /// </param>
+ /// <param name="deletionPolicy">see <a href="#deletionPolicy">above</a>
+ /// </param>
+ /// <param name="mfl">whether or not to limit field lengths, value is in number of terms/tokens. See <see cref="Lucene.Net.Index.IndexWriter.MaxFieldLength" />.
+ /// </param>
+ /// <param name="commit">which commit to open
+ /// </param>
+ /// <throws> CorruptIndexException if the index is corrupt </throws>
+ ///
<TRUNCATED>