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>