lucenenet-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aro...@apache.org
Subject svn commit: r411501 [10/30] - in /incubator/lucene.net/trunk/C#/src: ./ Demo/DeleteFiles/ Demo/DemoLib/ Demo/DemoLib/HTML/ Demo/IndexFiles/ Demo/IndexHtml/ Demo/SearchFiles/ Lucene.Net/ Lucene.Net/Analysis/ Lucene.Net/Analysis/Standard/ Lucene.Net/Docu...
Date Sun, 04 Jun 2006 02:41:25 GMT
Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/IndexWriter.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/IndexWriter.cs?rev=411501&r1=411500&r2=411501&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/IndexWriter.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/IndexWriter.cs Sat Jun  3 19:41:13 2006
@@ -13,31 +13,41 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 using System;
 using Analyzer = Lucene.Net.Analysis.Analyzer;
 using Document = Lucene.Net.Documents.Document;
 using Similarity = Lucene.Net.Search.Similarity;
 using Directory = Lucene.Net.Store.Directory;
 using FSDirectory = Lucene.Net.Store.FSDirectory;
-using InputStream = Lucene.Net.Store.InputStream;
+using IndexInput = Lucene.Net.Store.IndexInput;
+using IndexOutput = Lucene.Net.Store.IndexOutput;
 using Lock = Lucene.Net.Store.Lock;
-using OutputStream = Lucene.Net.Store.OutputStream;
 using RAMDirectory = Lucene.Net.Store.RAMDirectory;
+
 namespace Lucene.Net.Index
 {
 	
 	
 	/// <summary>An IndexWriter creates and maintains an index.
-	/// The third argument to the <a href="#IndexWriter"><b>constructor</b></a>
+	/// The third argument to the 
+	/// <a href="#IndexWriter(Lucene.Net.store.Directory, Lucene.Net.analysis.Analyzer, boolean)"><b>constructor</b></a>
 	/// determines whether a new index is created, or whether an existing index is
 	/// opened for the addition of new documents.
 	/// In either case, documents are added with the <a
-	/// href="#addDocument"><b>addDocument</b></a> method.  When finished adding
-	/// documents, <a href="#close"><b>close</b></a> should be called.
-	/// If an index will not have more documents added for a while and optimal search
-	/// performance is desired, then the <a href="#optimize"><b>optimize</b></a>
+	/// href="#addDocument(Lucene.Net.document.Document)"><b>addDocument</b></a> method.  
+	/// When finished adding documents, <a href="#close()"><b>close</b></a> should be called.
+	/// <p>If an index will not have more documents added for a while and optimal search
+	/// performance is desired, then the <a href="#optimize()"><b>optimize</b></a>
 	/// method should be called before the index is closed.
 	/// </summary>
+	/// <summary><p>Opening an IndexWriter creates a lock file for the directory in use. Trying to open
+	/// another IndexWriter on the same directory will lead to an IOException. The IOException
+	/// is also thrown if an IndexReader on the same directory is used to delete documents
+	/// from the index.
+	/// </summary>
+	/// <seealso cref="IndexModifier IndexModifier supports the important methods of IndexWriter plus deletion">
+	/// </seealso>
 	
 	public class IndexWriter
 	{
@@ -58,7 +68,7 @@
 				}
 				
 			}
-			internal AnonymousClassWith(bool create, IndexWriter enclosingInstance, Lucene.Net.Store.Lock Param1, long Param2):base(Param1, Param2)
+			internal AnonymousClassWith(bool create, IndexWriter enclosingInstance, Lucene.Net.Store.Lock Param1, long Param2) : base(Param1, Param2)
 			{
 				InitBlock(create, enclosingInstance);
 			}
@@ -73,10 +83,12 @@
 		}
 		private class AnonymousClassWith1 : Lock.With
 		{
-			private void  InitBlock(IndexWriter enclosingInstance)
+			private void  InitBlock(System.Collections.ArrayList segmentsToDelete, IndexWriter enclosingInstance)
 			{
+				this.segmentsToDelete = segmentsToDelete;
 				this.enclosingInstance = enclosingInstance;
 			}
+			private System.Collections.ArrayList segmentsToDelete;
 			private IndexWriter enclosingInstance;
 			public IndexWriter Enclosing_Instance
 			{
@@ -86,18 +98,51 @@
 				}
 				
 			}
-			internal AnonymousClassWith1(IndexWriter enclosingInstance, Lucene.Net.Store.Lock Param1, long Param2):base(Param1, Param2)
+			internal AnonymousClassWith1(System.Collections.ArrayList segmentsToDelete, IndexWriter enclosingInstance, Lucene.Net.Store.Lock Param1, long Param2):base(Param1, Param2)
 			{
-				InitBlock(enclosingInstance);
+				InitBlock(segmentsToDelete, enclosingInstance);
 			}
 			public override System.Object DoBody()
 			{
 				Enclosing_Instance.segmentInfos.Write(Enclosing_Instance.directory); // commit changes
+				Enclosing_Instance.DeleteSegments(segmentsToDelete); // delete now-unused segments
 				return null;
 			}
 		}
 		private class AnonymousClassWith2 : Lock.With
 		{
+			private void  InitBlock(System.String mergedName, System.Collections.ArrayList filesToDelete, IndexWriter enclosingInstance)
+			{
+				this.mergedName = mergedName;
+				this.filesToDelete = filesToDelete;
+				this.enclosingInstance = enclosingInstance;
+			}
+			private System.String mergedName;
+			private System.Collections.ArrayList filesToDelete;
+			private IndexWriter enclosingInstance;
+			public IndexWriter Enclosing_Instance
+			{
+				get
+				{
+					return enclosingInstance;
+				}
+				
+			}
+			internal AnonymousClassWith2(System.String mergedName, System.Collections.ArrayList filesToDelete, IndexWriter enclosingInstance, Lucene.Net.Store.Lock Param1, long Param2):base(Param1, Param2)
+			{
+				InitBlock(mergedName, filesToDelete, enclosingInstance);
+			}
+			public override System.Object DoBody()
+			{
+				// make compound file visible for SegmentReaders
+				Enclosing_Instance.directory.RenameFile(mergedName + ".tmp", mergedName + ".cfs");
+				// delete now unused files of segment 
+				Enclosing_Instance.DeleteFiles(filesToDelete);
+				return null;
+			}
+		}
+		private class AnonymousClassWith3 : Lock.With
+		{
 			private void  InitBlock(System.Collections.ArrayList segmentsToDelete, IndexWriter enclosingInstance)
 			{
 				this.segmentsToDelete = segmentsToDelete;
@@ -113,7 +158,7 @@
 				}
 				
 			}
-			internal AnonymousClassWith2(System.Collections.ArrayList segmentsToDelete, IndexWriter enclosingInstance, Lucene.Net.Store.Lock Param1, long Param2):base(Param1, Param2)
+			internal AnonymousClassWith3(System.Collections.ArrayList segmentsToDelete, IndexWriter enclosingInstance, Lucene.Net.Store.Lock Param1, long Param2):base(Param1, Param2)
 			{
 				InitBlock(segmentsToDelete, enclosingInstance);
 			}
@@ -124,44 +169,70 @@
 				return null;
 			}
 		}
+		private class AnonymousClassWith4 : Lock.With
+		{
+			private void  InitBlock(System.String mergedName, System.Collections.ArrayList filesToDelete, IndexWriter enclosingInstance)
+			{
+				this.mergedName = mergedName;
+				this.filesToDelete = filesToDelete;
+				this.enclosingInstance = enclosingInstance;
+			}
+			private System.String mergedName;
+			private System.Collections.ArrayList filesToDelete;
+			private IndexWriter enclosingInstance;
+			public IndexWriter Enclosing_Instance
+			{
+				get
+				{
+					return enclosingInstance;
+				}
+				
+			}
+			internal AnonymousClassWith4(System.String mergedName, System.Collections.ArrayList filesToDelete, IndexWriter enclosingInstance, Lucene.Net.Store.Lock Param1, long Param2):base(Param1, Param2)
+			{
+				InitBlock(mergedName, filesToDelete, enclosingInstance);
+			}
+			public override System.Object DoBody()
+			{
+				// make compound file visible for SegmentReaders
+				Enclosing_Instance.directory.RenameFile(mergedName + ".tmp", mergedName + ".cfs");
+				// delete now unused files of segment 
+				Enclosing_Instance.DeleteFiles(filesToDelete);
+				return null;
+			}
+		}
 		private void  InitBlock()
 		{
 			similarity = Similarity.GetDefault();
 		}
 		
-		/// <summary> Default value is 1000.  Use <code>Lucene.Net.writeLockTimeout</code>
-		/// system property to override.
-		/// </summary>
-		public static long WRITE_LOCK_TIMEOUT = SupportClass.AppSettings.Get("Lucene.Net.writeLockTimeout", 1000L);
+		/// <summary> Default value is 1,000.</summary>
+		public const long WRITE_LOCK_TIMEOUT = 1000;
 		
-		/// <summary> Default value is 10000.  Use <code>Lucene.Net.commitLockTimeout</code>
-		/// system property to override.
-		/// </summary>
-		public static long COMMIT_LOCK_TIMEOUT = System.Int32.Parse(SupportClass.AppSettings.Get("Lucene.Net.commitLockTimeout", "10000"));
+		/// <summary> Default value is 10,000.</summary>
+		public const long COMMIT_LOCK_TIMEOUT = 10000;
 		
 		public const System.String WRITE_LOCK_NAME = "write.lock";
 		public const System.String COMMIT_LOCK_NAME = "commit.lock";
 		
-		/// <summary> Default value is 10.  Use <code>Lucene.Net.mergeFactor</code>
-		/// system property to override.
-		/// </summary>
-		public static readonly int DEFAULT_MERGE_FACTOR = System.Int32.Parse(SupportClass.AppSettings.Get("Lucene.Net.mergeFactor", "10"));
+		/// <summary> Default value is 10. Change using {@link #SetMergeFactor(int)}.</summary>
+		public const int DEFAULT_MERGE_FACTOR = 10;
 		
-		/// <summary> Default value is 10.  Use <code>Lucene.Net.minMergeDocs</code>
-		/// system property to override.
-		/// </summary>
-		public static readonly int DEFAULT_MIN_MERGE_DOCS = System.Int32.Parse(SupportClass.AppSettings.Get("Lucene.Net.minMergeDocs", "10"));
+		/// <summary> Default value is 10. Change using {@link #SetMaxBufferedDocs(int)}.</summary>
+		public const int DEFAULT_MAX_BUFFERED_DOCS = 10;
 		
-		/// <summary> Default value is {@link Integer#MAX_VALUE}.
-		/// Use <code>Lucene.Net.maxMergeDocs</code> system property to override.
-		/// </summary>
-		public static readonly int DEFAULT_MAX_MERGE_DOCS = System.Int32.Parse(SupportClass.AppSettings.Get("Lucene.Net.maxMergeDocs", System.Convert.ToString(System.Int32.MaxValue)));
+		/// <deprecated> use {@link #DEFAULT_MAX_BUFFERED_DOCS} instead
+		/// </deprecated>
+		public static readonly int DEFAULT_MIN_MERGE_DOCS = DEFAULT_MAX_BUFFERED_DOCS;
 		
-		/// <summary> Default value is 10000.  Use <code>Lucene.Net.maxFieldLength</code>
-		/// system property to override.
-		/// </summary>
-		public static readonly int DEFAULT_MAX_FIELD_LENGTH = System.Int32.Parse(SupportClass.AppSettings.Get("Lucene.Net.maxFieldLength", "10000")); //// "5000000")); // "2147483647"));
+		/// <summary> Default value is {@link Integer#MAX_VALUE}. Change using {@link #SetMaxMergeDocs(int)}.</summary>
+		public static readonly int DEFAULT_MAX_MERGE_DOCS = System.Int32.MaxValue;
 		
+		/// <summary> Default value is 10,000. Change using {@link #SetMaxFieldLength(int)}.</summary>
+		public const int DEFAULT_MAX_FIELD_LENGTH = 10000;
+		
+		/// <summary> Default value is 128. Change using {@link #SetTermIndexInterval(int)}.</summary>
+		public const int DEFAULT_TERM_INDEX_INTERVAL = 128;
 		
 		private Directory directory; // where this index resides
 		private Analyzer analyzer; // how to analyze text
@@ -173,6 +244,8 @@
 		
 		private Lock writeLock;
 		
+		private int termIndexInterval = DEFAULT_TERM_INDEX_INTERVAL;
+		
 		/// <summary>Use compound file setting. Defaults to true, minimizing the number of
 		/// files used.  Setting this to false may improve indexing performance, but
 		/// may also cause file handle problems.
@@ -181,10 +254,12 @@
 		
 		private bool closeDir;
 		
-		/// <summary>Setting to turn on usage of a compound file. When on, multiple files
-		/// for each segment are merged into a single file once the segment creation
-		/// is finished. This is done regardless of what directory is in use.
+		/// <summary>Get the current setting of whether to use the compound file format.
+		/// Note that this just returns the value you set with setUseCompoundFile(boolean)
+		/// or the default. You cannot use this to query the status of an existing index.
 		/// </summary>
+		/// <seealso cref="SetUseCompoundFile(boolean)">
+		/// </seealso>
 		public virtual bool GetUseCompoundFile()
 		{
 			return useCompoundFile;
@@ -199,11 +274,10 @@
 			useCompoundFile = value_Renamed;
 		}
 		
-		
 		/// <summary>Expert: Set the Similarity implementation used by this IndexWriter.
 		/// 
 		/// </summary>
-		/// <seealso cref="Similarity#SetDefault(Similarity)">
+		/// <seealso cref="Similarity.SetDefault(Similarity)">
 		/// </seealso>
 		public virtual void  SetSimilarity(Similarity similarity)
 		{
@@ -219,6 +293,43 @@
 			return this.similarity;
 		}
 		
+		/// <summary>Expert: Set the interval between indexed terms.  Large values cause less
+		/// memory to be used by IndexReader, but slow random-access to terms.  Small
+		/// values cause more memory to be used by an IndexReader, and speed
+		/// random-access to terms.
+		/// 
+		/// This parameter determines the amount of computation required per query
+		/// term, regardless of the number of documents that contain that term.  In
+		/// particular, it is the maximum number of other terms that must be
+		/// scanned before a term is located and its frequency and position information
+		/// may be processed.  In a large index with user-entered query terms, query
+		/// processing time is likely to be dominated not by term lookup but rather
+		/// by the processing of frequency and positional data.  In a small index
+		/// or when many uncommon query terms are generated (e.g., by wildcard
+		/// queries) term lookup may become a dominant cost.
+		/// 
+		/// In particular, <code>numUniqueTerms/interval</code> terms are read into
+		/// memory by an IndexReader, and, on average, <code>interval/2</code> terms
+		/// must be scanned for each random term access.
+		/// 
+		/// </summary>
+		/// <seealso cref="DEFAULT_TERM_INDEX_INTERVAL">
+		/// </seealso>
+		public virtual void  SetTermIndexInterval(int interval)
+		{
+			this.termIndexInterval = interval;
+		}
+		
+		/// <summary>Expert: Return the interval between indexed terms.
+		/// 
+		/// </summary>
+		/// <seealso cref="SetTermIndexInterval(int)">
+		/// </seealso>
+		public virtual int GetTermIndexInterval()
+		{
+			return termIndexInterval;
+		}
+		
 		/// <summary> Constructs an IndexWriter for the index in <code>path</code>.
 		/// Text will be analyzed with <code>a</code>.  If <code>create</code>
 		/// is true, then a new, empty index will be created in
@@ -237,7 +348,7 @@
 		/// <summary>  if it does not exist, and <code>create</code> is
 		/// <code>false</code>
 		/// </summary>
-		public IndexWriter(System.String path, Analyzer a, bool create) :this(FSDirectory.GetDirectory(path, create), a, create, true)
+		public IndexWriter(System.String path, Analyzer a, bool create) : this(FSDirectory.GetDirectory(path, create), a, create, true)
 		{
 		}
 		
@@ -259,7 +370,7 @@
 		/// <summary>  if it does not exist, and <code>create</code> is
 		/// <code>false</code>
 		/// </summary>
-		public IndexWriter(System.IO.FileInfo path, Analyzer a, bool create):this(FSDirectory.GetDirectory(path, create), a, create, true)
+		public IndexWriter(System.IO.FileInfo path, Analyzer a, bool create) : this(FSDirectory.GetDirectory(path, create), a, create, true)
 		{
 		}
 		
@@ -281,7 +392,7 @@
 		/// <summary>  if it does not exist, and <code>create</code> is
 		/// <code>false</code>
 		/// </summary>
-		public IndexWriter(Directory d, Analyzer a, bool create):this(d, a, create, false)
+		public IndexWriter(Directory d, Analyzer a, bool create) : this(d, a, create, false)
 		{
 		}
 		
@@ -293,7 +404,7 @@
 			analyzer = a;
 			
 			Lock writeLock = directory.MakeLock(IndexWriter.WRITE_LOCK_NAME);
-			if (!writeLock.Obtain(WRITE_LOCK_TIMEOUT))
+			if (!writeLock.obtain(WRITE_LOCK_TIMEOUT))
 			// obtain write lock
 			{
 				throw new System.IO.IOException("Index locked for write: " + writeLock);
@@ -307,6 +418,111 @@
 			}
 		}
 		
+		/// <summary>Determines the largest number of documents ever merged by addDocument().
+		/// Small values (e.g., less than 10,000) are best for interactive indexing,
+		/// as this limits the length of pauses while indexing to a few seconds.
+		/// Larger values are best for batched indexing and speedier searches.
+		/// 
+		/// <p>The default value is {@link Integer#MAX_VALUE}.
+		/// </summary>
+		public virtual void  SetMaxMergeDocs(int maxMergeDocs)
+		{
+			this.maxMergeDocs = maxMergeDocs;
+		}
+		
+		/// <seealso cref="setMaxMergeDocs">
+		/// </seealso>
+		public virtual int GetMaxMergeDocs()
+		{
+			return maxMergeDocs;
+		}
+		
+		/// <summary> The maximum number of terms that will be indexed for a single field in a
+		/// document.  This limits the amount of memory required for indexing, so that
+		/// collections with very large files will not crash the indexing process by
+		/// running out of memory.<p/>
+		/// Note that this effectively truncates large documents, excluding from the
+		/// index terms that occur further in the document.  If you know your source
+		/// documents are large, be sure to set this value high enough to accomodate
+		/// the expected size.  If you set it to Integer.MAX_VALUE, then the only limit
+		/// is your memory, but you should anticipate an OutOfMemoryError.<p/>
+		/// By default, no more than 10,000 terms will be indexed for a field.
+		/// </summary>
+		public virtual void  SetMaxFieldLength(int maxFieldLength)
+		{
+			this.maxFieldLength = maxFieldLength;
+		}
+		
+		/// <seealso cref="setMaxFieldLength">
+		/// </seealso>
+		public virtual int GetMaxFieldLength()
+		{
+			return maxFieldLength;
+		}
+		
+		/// <summary>Determines the minimal number of documents required before the buffered
+		/// in-memory documents are merging and a new Segment is created.
+		/// Since Documents are merged in a {@link Lucene.Net.store.RAMDirectory},
+		/// large value gives faster indexing.  At the same time, mergeFactor limits
+		/// the number of files open in a FSDirectory.
+		/// 
+		/// <p> The default value is 10.
+		/// 
+		/// </summary>
+		/// <throws>  IllegalArgumentException if maxBufferedDocs is smaller than 1  </throws>
+		public virtual void  SetMaxBufferedDocs(int maxBufferedDocs)
+		{
+			if (maxBufferedDocs < 1)
+				throw new System.ArgumentException("maxBufferedDocs must at least be 1");
+			this.minMergeDocs = maxBufferedDocs;
+		}
+		
+		/// <seealso cref="setMaxBufferedDocs">
+		/// </seealso>
+		public virtual int GetMaxBufferedDocs()
+		{
+			return minMergeDocs;
+		}
+		
+		/// <summary>Determines how often segment indices are merged by addDocument().  With
+		/// smaller values, less RAM is used while indexing, and searches on
+		/// unoptimized indices are faster, but indexing speed is slower.  With larger
+		/// values, more RAM is used during indexing, and while searches on unoptimized
+		/// indices are slower, indexing is faster.  Thus larger values (> 10) are best
+		/// for batch index creation, and smaller values (< 10) for indices that are
+		/// interactively maintained.
+		/// 
+		/// <p>This must never be less than 2.  The default value is 10.
+		/// </summary>
+		public virtual void  SetMergeFactor(int mergeFactor)
+		{
+			if (mergeFactor < 2)
+				throw new System.ArgumentException("mergeFactor cannot be less than 2");
+			this.mergeFactor = mergeFactor;
+		}
+		
+		/// <seealso cref="setMergeFactor">
+		/// </seealso>
+		public virtual int GetMergeFactor()
+		{
+			return mergeFactor;
+		}
+		
+		/// <summary>If non-null, information about merges and a message when
+		/// maxFieldLength is reached will be printed to this.
+		/// </summary>
+		public virtual void  SetInfoStream(System.IO.TextWriter infoStream)
+		{
+			this.infoStream = infoStream;
+		}
+		
+		/// <seealso cref="setInfoStream">
+		/// </seealso>
+		public virtual System.IO.TextWriter GetInfoStream()
+		{
+			return infoStream;
+		}
+		
 		/// <summary>Flushes all changes to an index and closes all associated files. </summary>
 		public virtual void  Close()
 		{
@@ -314,12 +530,15 @@
 			{
 				FlushRamSegments();
 				ramDirectory.Close();
-				writeLock.Release(); // release write lock
-				writeLock = null;
+				if (writeLock != null)
+				{
+					writeLock.Release(); // release write lock
+					writeLock = null;
+				}
 				if (closeDir)
 					directory.Close();
-				System.GC.SuppressFinalize(this);
-			}
+                System.GC.SuppressFinalize(this);
+            }
 		}
 		
 		/// <summary>Release the write lock, if needed. </summary>
@@ -332,6 +551,12 @@
 			}
 		}
 		
+		/// <summary>Returns the Directory used by this index. </summary>
+		public virtual Directory GetDirectory()
+		{
+			return directory;
+		}
+		
 		/// <summary>Returns the analyzer used by this index. </summary>
 		public virtual Analyzer GetAnalyzer()
 		{
@@ -354,7 +579,7 @@
 			}
 		}
 		
-		/// <summary> The maximum number of terms that will be indexed for a single Field in a
+		/// <summary> The maximum number of terms that will be indexed for a single field in a
 		/// document.  This limits the amount of memory required for indexing, so that
 		/// collections with very large files will not crash the indexing process by
 		/// running out of memory.<p/>
@@ -363,12 +588,15 @@
 		/// documents are large, be sure to set this value high enough to accomodate
 		/// the expected size.  If you set it to Integer.MAX_VALUE, then the only limit
 		/// is your memory, but you should anticipate an OutOfMemoryError.<p/>
-		/// By default, no more than 10,000 terms will be indexed for a Field.
+		/// By default, no more than 10,000 terms will be indexed for a field.
+		/// 
 		/// </summary>
+		/// <deprecated> use {@link #setMaxFieldLength} instead
+		/// </deprecated>
 		public int maxFieldLength = DEFAULT_MAX_FIELD_LENGTH;
 		
 		/// <summary> Adds a document to this index.  If the document contains more than
-		/// {@link #maxFieldLength} terms for a given Field, the remainder are
+		/// {@link #SetMaxFieldLength(int)} terms for a given field, the remainder are
 		/// discarded.
 		/// </summary>
 		public virtual void  AddDocument(Document doc)
@@ -378,12 +606,13 @@
 		
 		/// <summary> Adds a document to this index, using the provided analyzer instead of the
 		/// value of {@link #GetAnalyzer()}.  If the document contains more than
-		/// {@link #maxFieldLength} terms for a given Field, the remainder are
+		/// {@link #SetMaxFieldLength(int)} terms for a given field, the remainder are
 		/// discarded.
 		/// </summary>
 		public virtual void  AddDocument(Document doc, Analyzer analyzer)
 		{
-			DocumentWriter dw = new DocumentWriter(ramDirectory, analyzer, similarity, maxFieldLength);
+			DocumentWriter dw = new DocumentWriter(ramDirectory, analyzer, this);
+			dw.SetInfoStream(infoStream);
 			System.String segmentName = NewSegmentName();
 			dw.AddDocument(segmentName, doc);
 			lock (this)
@@ -402,7 +631,7 @@
 		{
 			lock (this)
 			{
-				return "_" + SupportClass.Number.ToString(segmentInfos.counter++, SupportClass.Number.MAX_RADIX);
+                return "_" + SupportClass.Number.ToString(segmentInfos.counter++, SupportClass.Number.MAX_RADIX);
 			}
 		}
 		
@@ -416,16 +645,20 @@
 		/// 
 		/// <p>This must never be less than 2.  The default value is 10.
 		/// </summary>
+		/// <deprecated> use {@link #setMergeFactor} instead
+		/// </deprecated>
 		public int mergeFactor = DEFAULT_MERGE_FACTOR;
 		
 		/// <summary>Determines the minimal number of documents required before the buffered
 		/// in-memory documents are merging and a new Segment is created.
-		/// Since Documents are merged in a {@link Lucene.Net.Store.RAMDirectory},
+		/// Since Documents are merged in a {@link Lucene.Net.store.RAMDirectory},
 		/// large value gives faster indexing.  At the same time, mergeFactor limits
 		/// the number of files open in a FSDirectory.
 		/// 
 		/// <p> The default value is 10.
 		/// </summary>
+		/// <deprecated> use {@link #setMaxBufferedDocs} instead
+		/// </deprecated>
 		public int minMergeDocs = DEFAULT_MIN_MERGE_DOCS;
 		
 		
@@ -434,11 +667,15 @@
 		/// as this limits the length of pauses while indexing to a few seconds.
 		/// Larger values are best for batched indexing and speedier searches.
 		/// 
-		/// <p>The default value is {@link Integer#MAX_VALUE}. 
+		/// <p>The default value is {@link Integer#MAX_VALUE}.
 		/// </summary>
+		/// <deprecated> use {@link #setMaxMergeDocs} instead
+		/// </deprecated>
 		public int maxMergeDocs = DEFAULT_MAX_MERGE_DOCS;
 		
-		/// <summary>If non-null, information about merges will be printed to this. </summary>
+		/// <summary>If non-null, information about merges will be printed to this.</summary>
+		/// <deprecated> use {@link #setInfoStream} instead 
+		/// </deprecated>
 		public System.IO.TextWriter infoStream = null;
 		
 		/// <summary>Merges all segments together into a single segment, optimizing an index
@@ -472,6 +709,9 @@
 			lock (this)
 			{
 				Optimize(); // start with zero or 1 seg
+				
+				int start = segmentInfos.Count;
+				
 				for (int i = 0; i < dirs.Length; i++)
 				{
 					SegmentInfos sis = new SegmentInfos(); // read infos from dir
@@ -481,6 +721,18 @@
 						segmentInfos.Add(sis.Info(j)); // add each info
 					}
 				}
+				
+				// merge newly added segments in log(n) passes
+				while (segmentInfos.Count > start + mergeFactor)
+				{
+					for (int base_Renamed = start + 1; base_Renamed < segmentInfos.Count; base_Renamed++)
+					{
+						int end = System.Math.Min(segmentInfos.Count, base_Renamed + mergeFactor);
+						if (end - base_Renamed > 1)
+							MergeSegments(base_Renamed, end);
+					}
+				}
+				
 				Optimize(); // final cleanup
 			}
 		}
@@ -497,25 +749,44 @@
 				Optimize(); // start with zero or 1 seg
 				
 				System.String mergedName = NewSegmentName();
-				SegmentMerger merger = new SegmentMerger(directory, mergedName, false);
+				SegmentMerger merger = new SegmentMerger(this, mergedName);
 				
+				System.Collections.ArrayList segmentsToDelete = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
+				IndexReader sReader = null;
 				if (segmentInfos.Count == 1)
-				// add existing index, if any
-					merger.Add(new SegmentReader(segmentInfos.Info(0)));
+				{
+					// add existing index, if any
+					sReader = SegmentReader.Get(segmentInfos.Info(0));
+					merger.Add(sReader);
+					segmentsToDelete.Add(sReader); // queue segment for deletion
+				}
 				
 				for (int i = 0; i < readers.Length; i++)
-				// add new indexes
+    				// add new indexes
 					merger.Add(readers[i]);
 				
 				int docCount = merger.Merge(); // merge 'em
 				
-				segmentInfos.Clear(); // pop old infos & add new
+				segmentInfos.RemoveRange(0, segmentInfos.Count - 0);  // pop old infos & add new
 				segmentInfos.Add(new SegmentInfo(mergedName, docCount, directory));
 				
+				if (sReader != null)
+					sReader.Close();
+				
 				lock (directory)
 				{
 					// in- & inter-process sync
-					new AnonymousClassWith1(this, directory.MakeLock("commit.lock"), COMMIT_LOCK_TIMEOUT).Run();
+					new AnonymousClassWith1(segmentsToDelete, this, directory.MakeLock(COMMIT_LOCK_NAME), COMMIT_LOCK_TIMEOUT).Run();
+				}
+				
+				if (useCompoundFile)
+				{
+					System.Collections.ArrayList filesToDelete = merger.CreateCompoundFile(mergedName + ".tmp");
+					lock (directory)
+					{
+						// in- & inter-process sync
+						new AnonymousClassWith2(mergedName, filesToDelete, this, directory.MakeLock(COMMIT_LOCK_NAME), COMMIT_LOCK_TIMEOUT).Run();
+					}
 				}
 			}
 		}
@@ -569,18 +840,26 @@
 		/// </summary>
 		private void  MergeSegments(int minSegment)
 		{
+			MergeSegments(minSegment, segmentInfos.Count);
+		}
+		
+		/// <summary>Merges the named range of segments, replacing them in the stack with a
+		/// single segment. 
+		/// </summary>
+		private void  MergeSegments(int minSegment, int end)
+		{
 			System.String mergedName = NewSegmentName();
 			if (infoStream != null)
 				infoStream.Write("merging segments");
-			SegmentMerger merger = new SegmentMerger(directory, mergedName, useCompoundFile);
+			SegmentMerger merger = new SegmentMerger(this, mergedName);
 			
 			System.Collections.ArrayList segmentsToDelete = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
-			for (int i = minSegment; i < segmentInfos.Count; i++)
+			for (int i = minSegment; i < end; i++)
 			{
 				SegmentInfo si = segmentInfos.Info(i);
 				if (infoStream != null)
 					infoStream.Write(" " + si.name + " (" + si.docCount + " docs)");
-				IndexReader reader = new SegmentReader(si);
+				IndexReader reader = SegmentReader.Get(si);
 				merger.Add(reader);
 				if ((reader.Directory() == this.directory) || (reader.Directory() == this.ramDirectory))
 					segmentsToDelete.Add(reader); // queue segment for deletion
@@ -593,7 +872,9 @@
 				infoStream.WriteLine(" into " + mergedName + " (" + mergedDocCount + " docs)");
 			}
 			
-			segmentInfos.RemoveRange(minSegment, segmentInfos.Count - minSegment); // pop old infos & add new
+			for (int i = end - 1; i >= minSegment; i--)
+    			// remove old infos & add new
+				segmentInfos.RemoveAt(i);
 			segmentInfos.Add(new SegmentInfo(mergedName, mergedDocCount, directory));
 			
 			// close readers before we attempt to delete now-obsolete segments
@@ -602,14 +883,26 @@
 			lock (directory)
 			{
 				// in- & inter-process sync
-				new AnonymousClassWith2(segmentsToDelete, this, directory.MakeLock(IndexWriter.COMMIT_LOCK_NAME), COMMIT_LOCK_TIMEOUT).Run();
+				new AnonymousClassWith3(segmentsToDelete, this, directory.MakeLock(COMMIT_LOCK_NAME), COMMIT_LOCK_TIMEOUT).Run();
+			}
+			
+			if (useCompoundFile)
+			{
+				System.Collections.ArrayList filesToDelete = merger.CreateCompoundFile(mergedName + ".tmp");
+				lock (directory)
+				{
+					// in- & inter-process sync
+					new AnonymousClassWith4(mergedName, filesToDelete, this, directory.MakeLock(COMMIT_LOCK_NAME), COMMIT_LOCK_TIMEOUT).Run();
+				}
 			}
 		}
 		
-		/* Some operating systems (e.g. Windows) don't permit a file to be deleted
-		while it is opened for read (e.g. by another process or thread).  So we
-		assume that when a delete fails it is because the file is open in another
-		process, and queue the file for subsequent deletion. */
+		/*
+		* Some operating systems (e.g. Windows) don't permit a file to be deleted
+		* while it is opened for read (e.g. by another process or thread). So we
+		* assume that when a delete fails it is because the file is open in another
+		* process, and queue the file for subsequent deletion.
+		*/
 		
 		private void  DeleteSegments(System.Collections.ArrayList segments)
 		{
@@ -630,6 +923,14 @@
 			WriteDeleteableFiles(deletable); // note files we can't delete
 		}
 		
+		private void  DeleteFiles(System.Collections.ArrayList files)
+		{
+			System.Collections.ArrayList deletable = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
+			DeleteFiles(ReadDeleteableFiles(), deletable); // try to delete deleteable
+			DeleteFiles(files, deletable); // try to delete our files
+			WriteDeleteableFiles(deletable); // note files we can't delete
+		}
+		
 		private void  DeleteFiles(System.Collections.ArrayList files, Directory directory)
 		{
 			for (int i = 0; i < files.Count; i++)
@@ -652,7 +953,7 @@
 					{
 						if (infoStream != null)
 						{
-							infoStream.WriteLine(e.Message + "; Will re-try later.");
+							infoStream.WriteLine(e.ToString() + "; Will re-try later.");
 						}
 						deletable.Add(file); // add to deletable
 					}
@@ -663,10 +964,10 @@
 		private System.Collections.ArrayList ReadDeleteableFiles()
 		{
 			System.Collections.ArrayList result = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
-			if (!directory.FileExists("deletable"))
+			if (!directory.FileExists(IndexFileNames.DELETABLE))
 				return result;
 			
-			InputStream input = directory.OpenFile("deletable");
+			IndexInput input = directory.OpenInput(IndexFileNames.DELETABLE);
 			try
 			{
 				for (int i = input.ReadInt(); i > 0; i--)
@@ -682,7 +983,7 @@
 		
 		private void  WriteDeleteableFiles(System.Collections.ArrayList files)
 		{
-			OutputStream output = directory.CreateFile("deleteable.new");
+			IndexOutput output = directory.CreateOutput("deleteable.new");
 			try
 			{
 				output.WriteInt(files.Count);
@@ -693,7 +994,7 @@
 			{
 				output.Close();
 			}
-			directory.RenameFile("deleteable.new", "deletable");
+			directory.RenameFile("deleteable.new", IndexFileNames.DELETABLE);
 		}
 	}
 }

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/MultiReader.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/MultiReader.cs?rev=411501&r1=411500&r2=411501&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/MultiReader.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/MultiReader.cs Sat Jun  3 19:41:13 2006
@@ -13,16 +13,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 using System;
 using Document = Lucene.Net.Documents.Document;
+using Field = Lucene.Net.Documents.Field;
 using Directory = Lucene.Net.Store.Directory;
+
 namespace Lucene.Net.Index
 {
 	
 	/// <summary>An IndexReader which reads multiple indexes, appending their content.
 	/// 
 	/// </summary>
-	/// <version>  $Id: MultiReader.java,v 1.7 2004/05/17 12:56:47 goller Exp $
+	/// <version>  $Id: MultiReader.java 355181 2005-12-08 19:53:06Z cutting $
 	/// </version>
 	public class MultiReader : IndexReader
 	{
@@ -30,7 +33,7 @@
 		private int[] starts; // 1st docno for each segment
 		private System.Collections.Hashtable normsCache = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable());
 		private int maxDoc = 0;
-		private int numDocs = -1;
+		private int numDocs = - 1;
 		private bool hasDeletions = false;
 		
 		/// <summary> <p>Construct a MultiReader aggregating the named set of (sub)readers.
@@ -47,7 +50,7 @@
 		}
 		
 		/// <summary>Construct reading the named set of readers. </summary>
-		public /*internal*/ MultiReader(Directory directory, SegmentInfos sis, bool closeDirectory, IndexReader[] subReaders):base(directory, sis, closeDirectory)
+		public /*internal*/ MultiReader(Directory directory, SegmentInfos sis, bool closeDirectory, IndexReader[] subReaders) : base(directory, sis, closeDirectory)
 		{
 			Initialize(subReaders);
 		}
@@ -69,9 +72,9 @@
 		
 		
 		/// <summary>Return an array of term frequency vectors for the specified document.
-		/// The array contains a vector for each vectorized Field in the document.
+		/// The array contains a vector for each vectorized field in the document.
 		/// Each vector vector contains term numbers and frequencies for all terms
-		/// in a given vectorized Field.
+		/// in a given vectorized field.
 		/// If no such fields existed, the method returns null.
 		/// </summary>
 		public override TermFreqVector[] GetTermFreqVectors(int n)
@@ -137,6 +140,7 @@
 			for (int i = 0; i < subReaders.Length; i++)
 				subReaders[i].UndeleteAll();
 			hasDeletions = false;
+			numDocs = - 1; // invalidate cache
 		}
 		
 		private int ReaderIndex(int n)
@@ -166,6 +170,24 @@
 			return hi;
 		}
 		
+		public override bool HasNorms(System.String field)
+		{
+			for (int i = 0; i < subReaders.Length; i++)
+			{
+				if (subReaders[i].HasNorms(field))
+					return true;
+			}
+			return false;
+		}
+		
+		private byte[] ones;
+		private byte[] FakeNorms()
+		{
+			if (ones == null)
+				ones = SegmentReader.CreateFakeNorms(MaxDoc());
+			return ones;
+		}
+		
 		public override byte[] Norms(System.String field)
 		{
 			lock (this)
@@ -173,6 +195,8 @@
 				byte[] bytes = (byte[]) normsCache[field];
 				if (bytes != null)
 					return bytes; // cache hit
+				if (!HasNorms(field))
+					return FakeNorms();
 				
 				bytes = new byte[MaxDoc()];
 				for (int i = 0; i < subReaders.Length; i++)
@@ -187,12 +211,14 @@
 			lock (this)
 			{
 				byte[] bytes = (byte[]) normsCache[field];
+				if (bytes == null && !HasNorms(field))
+					bytes = FakeNorms();
 				if (bytes != null)
-				// cache hit
+				    // cache hit
 					Array.Copy(bytes, 0, result, offset, MaxDoc());
 				
 				for (int i = 0; i < subReaders.Length; i++)
-				// read from segments
+				    // read from segments
 					subReaders[i].Norms(field, result, offset + starts[i]);
 			}
 		}
@@ -247,35 +273,34 @@
 			}
 		}
 		
-		/// <seealso cref="IndexReader#GetFieldNames()">
+		/// <seealso cref="IndexReader.GetFieldNames()">
 		/// </seealso>
 		public override System.Collections.ICollection GetFieldNames()
 		{
-			// maintain a unique set of Field names
+			// maintain a unique set of field names
 			System.Collections.Hashtable fieldSet = new System.Collections.Hashtable();
 			for (int i = 0; i < subReaders.Length; i++)
 			{
 				IndexReader reader = subReaders[i];
 				System.Collections.ICollection names = reader.GetFieldNames();
-				// iterate through the Field names and add them to the set
-				for (System.Collections.IEnumerator iterator = names.GetEnumerator(); iterator.MoveNext(); )
-				{
+                for (System.Collections.IEnumerator iterator = names.GetEnumerator(); iterator.MoveNext(); )
+                {
                     System.Collections.DictionaryEntry fi = (System.Collections.DictionaryEntry) iterator.Current;
-					System.String s = fi.Key.ToString();
+                    System.String s = fi.Key.ToString();
                     if (fieldSet.ContainsKey(s) == false)
                     {
                         fieldSet.Add(s, s);
                     }
-				}
-			}
+                }
+            }
 			return fieldSet;
 		}
 		
-		/// <seealso cref="IndexReader#GetFieldNames(boolean)">
+		/// <seealso cref="IndexReader.GetFieldNames(boolean)">
 		/// </seealso>
 		public override System.Collections.ICollection GetFieldNames(bool indexed)
 		{
-			// maintain a unique set of Field names
+			// maintain a unique set of field names
 			System.Collections.Hashtable fieldSet = new System.Collections.Hashtable();
 			for (int i = 0; i < subReaders.Length; i++)
 			{
@@ -294,14 +319,35 @@
 			return fieldSet;
 		}
 		
-		public override System.Collections.ICollection GetIndexedFieldNames(bool storedTermVector)
+		public override System.Collections.ICollection GetIndexedFieldNames(Field.TermVector tvSpec)
+		{
+			// maintain a unique set of field names
+			System.Collections.Hashtable fieldSet = new System.Collections.Hashtable();
+			for (int i = 0; i < subReaders.Length; i++)
+			{
+				IndexReader reader = subReaders[i];
+				System.Collections.ICollection names = reader.GetIndexedFieldNames(tvSpec);
+                foreach (object item in names)
+                {
+                    if (fieldSet.ContainsKey(item) == false)
+                    {
+                        fieldSet.Add(item, item);
+                    }
+                }
+            }
+			return fieldSet;
+		}
+		
+		/// <seealso cref="IndexReader.GetFieldNames(IndexReader.FieldOption)">
+		/// </seealso>
+		public override System.Collections.ICollection GetFieldNames(IndexReader.FieldOption fieldNames)
 		{
-			// maintain a unique set of Field names
+			// maintain a unique set of field names
 			System.Collections.Hashtable fieldSet = new System.Collections.Hashtable();
 			for (int i = 0; i < subReaders.Length; i++)
 			{
 				IndexReader reader = subReaders[i];
-				System.Collections.ICollection names = reader.GetIndexedFieldNames(storedTermVector);
+				System.Collections.ICollection names = reader.GetFieldNames(fieldNames);
                 foreach (object item in names)
                 {
                     if (fieldSet.ContainsKey(item) == false)
@@ -314,7 +360,7 @@
 		}
 	}
 	
-	class MultiTermEnum:TermEnum
+	class MultiTermEnum : TermEnum
 	{
 		private SegmentMergeQueue queue;
 		
@@ -523,7 +569,7 @@
 		}
 	}
 	
-	class MultiTermPositions:MultiTermDocs, TermPositions
+	class MultiTermPositions : MultiTermDocs, TermPositions
 	{
 		public MultiTermPositions(IndexReader[] r, int[] s):base(r, s)
 		{

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/MultipleTermPositions.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/MultipleTermPositions.cs?rev=411501&r1=411500&r2=411501&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/MultipleTermPositions.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/MultipleTermPositions.cs Sat Jun  3 19:41:13 2006
@@ -13,12 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 using System;
 using PriorityQueue = Lucene.Net.Util.PriorityQueue;
+
 namespace Lucene.Net.Index
 {
 	
-	
 	/// <summary> Describe class <code>MultipleTermPositions</code> here.
 	/// 
 	/// </summary>
@@ -28,6 +29,7 @@
 	/// </version>
 	public class MultipleTermPositions : TermPositions
 	{
+		
 		private sealed class TermPositionsQueue:PriorityQueue
 		{
 			internal TermPositionsQueue(System.Collections.IList termPositions)
@@ -65,10 +67,8 @@
 				_array = new int[_arraySize];
 			}
 			private int _arraySize = 16;
-			
 			private int _index = 0;
 			private int _lastIndex = 0;
-			
 			private int[] _array;
 			
 			internal void  Add(int i)
@@ -111,18 +111,13 @@
 		
 		private int _doc;
 		private int _freq;
-		
 		private TermPositionsQueue _termPositionsQueue;
 		private IntQueue _posList;
 		
 		/// <summary> Creates a new <code>MultipleTermPositions</code> instance.
 		/// 
 		/// </summary>
-		/// <param name="indexReader">an <code>IndexReader</code> value
-		/// </param>
-		/// <param name="terms">a <code>Term[]</code> value
-		/// </param>
-		/// <exception cref=""> IOException if an error occurs
+		/// <exception cref="IOException">
 		/// </exception>
 		public MultipleTermPositions(IndexReader indexReader, Term[] terms)
 		{
@@ -135,15 +130,6 @@
 			_posList = new IntQueue();
 		}
 		
-		/// <summary> Describe <code>next</code> method here.
-		/// 
-		/// </summary>
-		/// <returns> a <code>boolean</code> value
-		/// </returns>
-		/// <exception cref=""> IOException if an error occurs
-		/// </exception>
-		/// <seealso cref="TermDocs#Next()">
-		/// </seealso>
 		public bool Next()
 		{
 			if (_termPositionsQueue.Size() == 0)
@@ -176,116 +162,56 @@
 			return true;
 		}
 		
-		/// <summary> Describe <code>nextPosition</code> method here.
-		/// 
-		/// </summary>
-		/// <returns> an <code>int</code> value
-		/// </returns>
-		/// <exception cref=""> IOException if an error occurs
-		/// </exception>
-		/// <seealso cref="TermPositions#NextPosition()">
-		/// </seealso>
 		public int NextPosition()
 		{
 			return _posList.Next();
 		}
 		
-		/// <summary> Describe <code>skipTo</code> method here.
-		/// 
-		/// </summary>
-		/// <param name="target">an <code>int</code> value
-		/// </param>
-		/// <returns> a <code>boolean</code> value
-		/// </returns>
-		/// <exception cref=""> IOException if an error occurs
-		/// </exception>
-		/// <seealso cref="TermDocs#SkipTo(int)">
-		/// </seealso>
 		public bool SkipTo(int target)
 		{
-			while (target > _termPositionsQueue.Peek().Doc())
+			while (_termPositionsQueue.Peek() != null && target > _termPositionsQueue.Peek().Doc())
 			{
 				TermPositions tp = (TermPositions) _termPositionsQueue.Pop();
-				
 				if (tp.SkipTo(target))
 					_termPositionsQueue.Put(tp);
 				else
 					tp.Close();
 			}
-			
 			return Next();
 		}
 		
-		/// <summary> Describe <code>doc</code> method here.
-		/// 
-		/// </summary>
-		/// <returns> an <code>int</code> value
-		/// </returns>
-		/// <seealso cref="TermDocs#Doc()">
-		/// </seealso>
 		public int Doc()
 		{
 			return _doc;
 		}
 		
-		/// <summary> Describe <code>freq</code> method here.
-		/// 
-		/// </summary>
-		/// <returns> an <code>int</code> value
-		/// </returns>
-		/// <seealso cref="TermDocs#Freq()">
-		/// </seealso>
 		public int Freq()
 		{
 			return _freq;
 		}
 		
-		/// <summary> Describe <code>close</code> method here.
-		/// 
-		/// </summary>
-		/// <exception cref=""> IOException if an error occurs
-		/// </exception>
-		/// <seealso cref="TermDocs#Close()">
-		/// </seealso>
 		public void  Close()
 		{
 			while (_termPositionsQueue.Size() > 0)
 				((TermPositions) _termPositionsQueue.Pop()).Close();
 		}
 		
-		/// <summary> Describe <code>seek</code> method here.
-		/// 
-		/// </summary>
-		/// <param name="arg0">a <code>Term</code> value
-		/// </param>
-		/// <exception cref=""> IOException if an error occurs
-		/// </exception>
-		/// <seealso cref="TermDocs#Seek(Term)">
-		/// </seealso>
+		/// <summary> Not implemented.</summary>
+		/// <throws>  UnsupportedOperationException </throws>
 		public virtual void  Seek(Term arg0)
 		{
 			throw new System.NotSupportedException();
 		}
 		
+		/// <summary> Not implemented.</summary>
+		/// <throws>  UnsupportedOperationException </throws>
 		public virtual void  Seek(TermEnum termEnum)
 		{
 			throw new System.NotSupportedException();
 		}
 		
-		
-		/// <summary> Describe <code>read</code> method here.
-		/// 
-		/// </summary>
-		/// <param name="arg0">an <code>int[]</code> value
-		/// </param>
-		/// <param name="arg1">an <code>int[]</code> value
-		/// </param>
-		/// <returns> an <code>int</code> value
-		/// </returns>
-		/// <exception cref=""> IOException if an error occurs
-		/// </exception>
-		/// <seealso cref="int[])">
-		/// </seealso>
+		/// <summary> Not implemented.</summary>
+		/// <throws>  UnsupportedOperationException </throws>
 		public virtual int Read(int[] arg0, int[] arg1)
 		{
 			throw new System.NotSupportedException();

Added: incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/ParallelReader.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/ParallelReader.cs?rev=411501&view=auto
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/ParallelReader.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/ParallelReader.cs Sat Jun  3 19:41:13 2006
@@ -0,0 +1,495 @@
+/*
+ * Copyright 2004 The Apache Software Foundation
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using Document = Lucene.Net.Documents.Document;
+using Field = Lucene.Net.Documents.Field;
+
+namespace Lucene.Net.Index
+{
+	
+	/// <summary>An IndexReader which reads multiple, parallel indexes.  Each index added
+	/// must have the same number of documents, but typically each contains
+	/// different fields.  Each document contains the union of the fields of all
+	/// documents with the same document number.  When searching, matches for a
+	/// query term are from the first index added that has the field.
+	/// 
+	/// <p>This is useful, e.g., with collections that have large fields which
+	/// change rarely and small fields that change more frequently.  The smaller
+	/// fields may be re-indexed in a new index and both indexes may be searched
+	/// together.
+	/// 
+	/// <p><strong>Warning:</strong> It is up to you to make sure all indexes
+	/// are created and modified the same way. For example, if you add
+	/// documents to one index, you need to add the same documents in the
+	/// same order to the other indexes. <em>Failure to do so will result in
+	/// undefined behavior</em>.
+	/// </summary>
+	public class ParallelReader : IndexReader
+	{
+		private System.Collections.ArrayList readers = new System.Collections.ArrayList();
+		private System.Collections.SortedList fieldToReader = new System.Collections.SortedList();
+		private System.Collections.ArrayList storedFieldReaders = new System.Collections.ArrayList();
+		
+		private int maxDoc;
+		private int numDocs;
+		private bool hasDeletions;
+		
+		/// <summary>Construct a ParallelReader. </summary>
+		public ParallelReader() : base(null)
+		{
+		}
+		
+		/// <summary>Add an IndexReader. </summary>
+		public virtual void  Add(IndexReader reader)
+		{
+			Add(reader, false);
+		}
+		
+		/// <summary>Add an IndexReader whose stored fields will not be returned.  This can
+		/// accellerate search when stored fields are only needed from a subset of
+		/// the IndexReaders.
+		/// 
+		/// </summary>
+		/// <throws>  IllegalArgumentException if not all indexes contain the same number  </throws>
+		/// <summary>     of documents
+		/// </summary>
+		/// <throws>  IllegalArgumentException if not all indexes have the same value  </throws>
+		/// <summary>     of {@link IndexReader#MaxDoc()}
+		/// </summary>
+		public virtual void  Add(IndexReader reader, bool ignoreStoredFields)
+		{
+			
+			if (readers.Count == 0)
+			{
+				this.maxDoc = reader.MaxDoc();
+				this.numDocs = reader.NumDocs();
+				this.hasDeletions = reader.HasDeletions();
+			}
+			
+			if (reader.MaxDoc() != maxDoc)
+			// check compatibility
+				throw new System.ArgumentException("All readers must have same maxDoc: " + maxDoc + "!=" + reader.MaxDoc());
+			if (reader.NumDocs() != numDocs)
+				throw new System.ArgumentException("All readers must have same numDocs: " + numDocs + "!=" + reader.NumDocs());
+			
+			System.Collections.IEnumerator i = reader.GetFieldNames(IndexReader.FieldOption.ALL).GetEnumerator();
+			while (i.MoveNext())
+			{
+				// update fieldToReader map
+				System.String field = (System.String) i.Current;
+				if (fieldToReader[field] == null)
+					fieldToReader[field] = reader;
+			}
+			
+			if (!ignoreStoredFields)
+				storedFieldReaders.Add(reader); // add to storedFieldReaders
+			readers.Add(reader);
+		}
+		
+		public override int NumDocs()
+		{
+			return numDocs;
+		}
+		
+		public override int MaxDoc()
+		{
+			return maxDoc;
+		}
+		
+		public override bool HasDeletions()
+		{
+			return hasDeletions;
+		}
+		
+		// check first reader
+		public override bool IsDeleted(int n)
+		{
+			if (readers.Count > 0)
+				return ((IndexReader) readers[0]).IsDeleted(n);
+			return false;
+		}
+		
+		// delete in all readers
+		protected internal override void  DoDelete(int n)
+		{
+			for (int i = 0; i < readers.Count; i++)
+			{
+				((IndexReader) readers[i]).DoDelete(n);
+			}
+			hasDeletions = true;
+		}
+		
+		// undeleteAll in all readers
+		protected internal override void  DoUndeleteAll()
+		{
+			for (int i = 0; i < readers.Count; i++)
+			{
+				((IndexReader) readers[i]).DoUndeleteAll();
+			}
+			hasDeletions = false;
+		}
+		
+		// append fields from storedFieldReaders
+		public override Document Document(int n)
+		{
+			Document result = new Document();
+			for (int i = 0; i < storedFieldReaders.Count; i++)
+			{
+				IndexReader reader = (IndexReader) storedFieldReaders[i];
+				System.Collections.IEnumerator fields = reader.Document(n).Fields();
+				while (fields.MoveNext())
+				{
+					result.Add((Field) fields.Current);
+				}
+			}
+			return result;
+		}
+		
+		// get all vectors
+		public override TermFreqVector[] GetTermFreqVectors(int n)
+		{
+			System.Collections.ArrayList results = new System.Collections.ArrayList();
+			System.Collections.IEnumerator i = new System.Collections.Hashtable(fieldToReader).GetEnumerator();
+			while (i.MoveNext())
+			{
+				System.Collections.DictionaryEntry e = (System.Collections.DictionaryEntry) i.Current;
+				IndexReader reader = (IndexReader) e.Key;
+				System.String field = (System.String) e.Value;
+				TermFreqVector vector = reader.GetTermFreqVector(n, field);
+				if (vector != null)
+					results.Add(vector);
+			}
+			return (TermFreqVector[]) (results.ToArray(typeof(TermFreqVector)));
+		}
+		
+		public override TermFreqVector GetTermFreqVector(int n, System.String field)
+		{
+			return ((IndexReader) fieldToReader[field]).GetTermFreqVector(n, field);
+		}
+		
+		public override bool HasNorms(System.String field)
+		{
+			return ((IndexReader) fieldToReader[field]).HasNorms(field);
+		}
+		
+		public override byte[] Norms(System.String field)
+		{
+			return ((IndexReader) fieldToReader[field]).Norms(field);
+		}
+		
+		public override void  Norms(System.String field, byte[] result, int offset)
+		{
+			((IndexReader) fieldToReader[field]).Norms(field, result, offset);
+		}
+		
+		protected internal override void  DoSetNorm(int n, System.String field, byte value_Renamed)
+		{
+			((IndexReader) fieldToReader[field]).DoSetNorm(n, field, value_Renamed);
+		}
+		
+		public override TermEnum Terms()
+		{
+			return new ParallelTermEnum(this);
+		}
+		
+		public override TermEnum Terms(Term term)
+		{
+			return new ParallelTermEnum(this, term);
+		}
+		
+		public override int DocFreq(Term term)
+		{
+			return ((IndexReader) fieldToReader[term.Field()]).DocFreq(term);
+		}
+		
+		public override TermDocs TermDocs(Term term)
+		{
+			return new ParallelTermDocs(this, term);
+		}
+		
+		public override TermDocs TermDocs()
+		{
+			return new ParallelTermDocs(this);
+		}
+		
+		public override TermPositions TermPositions(Term term)
+		{
+			return new ParallelTermPositions(this, term);
+		}
+		
+		public override TermPositions TermPositions()
+		{
+			return new ParallelTermPositions(this);
+		}
+		
+		protected internal override void  DoCommit()
+		{
+			for (int i = 0; i < readers.Count; i++)
+				((IndexReader) readers[i]).Commit();
+		}
+		
+		protected internal override void  DoClose()
+		{
+			lock (this)
+			{
+				for (int i = 0; i < readers.Count; i++)
+					((IndexReader) readers[i]).Close();
+			}
+		}
+		
+		public override System.Collections.ICollection GetFieldNames()
+		{
+            System.Collections.Hashtable result = new System.Collections.Hashtable(fieldToReader.Count);
+            System.Collections.ICollection items = fieldToReader.Keys;
+            foreach (object item in items)
+            {
+                result.Add(item, item);
+            }
+            return result;
+		}
+		
+		public override System.Collections.ICollection GetFieldNames(bool indexed)
+		{
+			System.Collections.Hashtable fieldSet = new System.Collections.Hashtable();
+			for (int i = 0; i < readers.Count; i++)
+			{
+				IndexReader reader = ((IndexReader) readers[i]);
+				System.Collections.ICollection names = reader.GetFieldNames(indexed);
+                foreach (object item in names)
+                {
+                    if (fieldSet.ContainsKey(item) == false)
+                    {
+                        fieldSet.Add(item, item);
+                    }
+                }
+			}
+			return fieldSet;
+		}
+		
+		public override System.Collections.ICollection GetIndexedFieldNames(Field.TermVector tvSpec)
+		{
+			System.Collections.Hashtable fieldSet = new System.Collections.Hashtable();
+			for (int i = 0; i < readers.Count; i++)
+			{
+				IndexReader reader = ((IndexReader) readers[i]);
+				System.Collections.ICollection names = reader.GetIndexedFieldNames(tvSpec);
+                foreach (object item in names)
+                {
+                    if (fieldSet.ContainsKey(item) == false)
+                    {
+                        fieldSet.Add(item, item);
+                    }
+                }
+            }
+			return fieldSet;
+		}
+		
+		public override System.Collections.ICollection GetFieldNames(IndexReader.FieldOption fieldNames)
+		{
+			System.Collections.Hashtable fieldSet = new System.Collections.Hashtable();
+			for (int i = 0; i < readers.Count; i++)
+			{
+				IndexReader reader = ((IndexReader) readers[i]);
+				System.Collections.ICollection names = reader.GetFieldNames(fieldNames);
+                foreach (object item in names)
+                {
+                    if (fieldSet.ContainsKey(item) == false)
+                    {
+                        fieldSet.Add(item, item);
+                    }
+                }
+            }
+			return fieldSet;
+		}
+		
+		private class ParallelTermEnum : TermEnum
+		{
+			private void  InitBlock(ParallelReader enclosingInstance)
+			{
+				this.enclosingInstance = enclosingInstance;
+			}
+			private ParallelReader enclosingInstance;
+			public ParallelReader Enclosing_Instance
+			{
+				get
+				{
+					return enclosingInstance;
+				}
+				
+			}
+			private System.String field;
+			private TermEnum termEnum;
+			
+			public ParallelTermEnum(ParallelReader enclosingInstance)
+			{
+				InitBlock(enclosingInstance);
+				field = ((System.String) Enclosing_Instance.fieldToReader.GetKey(0));
+				if (field != null)
+					termEnum = ((IndexReader) Enclosing_Instance.fieldToReader[field]).Terms();
+			}
+			
+			public ParallelTermEnum(ParallelReader enclosingInstance, Term term)
+			{
+				InitBlock(enclosingInstance);
+				field = term.Field();
+				termEnum = ((IndexReader) Enclosing_Instance.fieldToReader[field]).Terms(term);
+			}
+			
+			public override bool Next()
+			{
+				if (field == null)
+					return false;
+				
+				bool next = termEnum.Next();
+				
+				// still within field?
+				if (next && (System.Object) termEnum.Term().Field() == (System.Object) field)
+					return true; // yes, keep going
+				
+				termEnum.Close(); // close old termEnum
+				
+				// find the next field, if any
+				field = ((System.String) SupportClass.TailMap(Enclosing_Instance.fieldToReader, field).GetKey(0));
+				if (field != null)
+				{
+					termEnum = ((IndexReader) Enclosing_Instance.fieldToReader[field]).Terms();
+					return true;
+				}
+				
+				return false; // no more fields
+			}
+			
+			public override Term Term()
+			{
+				return termEnum.Term();
+			}
+			public override int DocFreq()
+			{
+				return termEnum.DocFreq();
+			}
+			public override void  Close()
+			{
+				termEnum.Close();
+			}
+		}
+		
+		// wrap a TermDocs in order to support seek(Term)
+		private class ParallelTermDocs : TermDocs
+		{
+			private void  InitBlock(ParallelReader enclosingInstance)
+			{
+				this.enclosingInstance = enclosingInstance;
+			}
+			private ParallelReader enclosingInstance;
+			public ParallelReader Enclosing_Instance
+			{
+				get
+				{
+					return enclosingInstance;
+				}
+				
+			}
+			protected internal TermDocs termDocs;
+			
+			public ParallelTermDocs(ParallelReader enclosingInstance)
+			{
+				InitBlock(enclosingInstance);
+			}
+			public ParallelTermDocs(ParallelReader enclosingInstance, Term term)
+			{
+				InitBlock(enclosingInstance);
+				Seek(term);
+			}
+			
+			public virtual int Doc()
+			{
+				return termDocs.Doc();
+			}
+			public virtual int Freq()
+			{
+				return termDocs.Freq();
+			}
+			
+			public virtual void  Seek(Term term)
+			{
+				termDocs = ((IndexReader) Enclosing_Instance.fieldToReader[term.Field()]).TermDocs(term);
+			}
+			
+			public virtual void  Seek(TermEnum termEnum)
+			{
+				Seek(termEnum.Term());
+			}
+			
+			public virtual bool Next()
+			{
+				return termDocs.Next();
+			}
+			
+			public virtual int Read(int[] docs, int[] freqs)
+			{
+				return termDocs.Read(docs, freqs);
+			}
+			
+			public virtual bool SkipTo(int target)
+			{
+				return termDocs.SkipTo(target);
+			}
+			
+			public virtual void  Close()
+			{
+				termDocs.Close();
+			}
+		}
+		
+		private class ParallelTermPositions : ParallelTermDocs, TermPositions
+		{
+			private void  InitBlock(ParallelReader enclosingInstance)
+			{
+				this.enclosingInstance = enclosingInstance;
+			}
+			private ParallelReader enclosingInstance;
+			public new ParallelReader Enclosing_Instance
+			{
+				get
+				{
+					return enclosingInstance;
+				}
+				
+			}
+			
+			public ParallelTermPositions(ParallelReader enclosingInstance) : base(enclosingInstance)
+			{
+				InitBlock(enclosingInstance);
+			}
+			public ParallelTermPositions(ParallelReader enclosingInstance, Term term) : base(enclosingInstance)
+			{
+				InitBlock(enclosingInstance);
+				Seek(term);
+			}
+			
+			public override void  Seek(Term term)
+			{
+				termDocs = ((IndexReader) Enclosing_Instance.fieldToReader[term.Field()]).TermPositions(term);
+			}
+			
+			public virtual int NextPosition()
+			{
+				return ((TermPositions) termDocs).NextPosition();
+			}
+		}
+	}
+}
\ No newline at end of file

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/SegmentInfo.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/SegmentInfo.cs?rev=411501&r1=411500&r2=411501&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/SegmentInfo.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/SegmentInfo.cs Sat Jun  3 19:41:13 2006
@@ -13,12 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 using System;
 using Directory = Lucene.Net.Store.Directory;
+
 namespace Lucene.Net.Index
 {
 	
-	sealed public class SegmentInfo
+	public sealed class SegmentInfo
 	{
 		public System.String name; // unique name in dir
 		public int docCount; // number of docs in seg

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/SegmentInfos.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/SegmentInfos.cs?rev=411501&r1=411500&r2=411501&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/SegmentInfos.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/SegmentInfos.cs Sat Jun  3 19:41:13 2006
@@ -13,14 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 using System;
 using Directory = Lucene.Net.Store.Directory;
-using InputStream = Lucene.Net.Store.InputStream;
-using OutputStream = Lucene.Net.Store.OutputStream;
+using IndexInput = Lucene.Net.Store.IndexInput;
+using IndexOutput = Lucene.Net.Store.IndexOutput;
+using Constants = Lucene.Net.Util.Constants;
+
 namespace Lucene.Net.Index
 {
+	
 	[Serializable]
-	sealed public class SegmentInfos : System.Collections.ArrayList
+	public sealed class SegmentInfos : System.Collections.ArrayList
 	{
 		
 		/// <summary>The file format version, a negative number. </summary>
@@ -28,7 +32,10 @@
 		public const int FORMAT = - 1;
 		
 		public int counter = 0; // used to name new segments
-		private long version = 0; //counts how often the index has been changed by adding or deleting docs
+		/// <summary> counts how often the index has been changed by adding or deleting docs.
+		/// starting with the current time in milliseconds forces to create unique version numbers.
+		/// </summary>
+		private long version = System.DateTime.Now.Ticks;
 		
 		public SegmentInfo Info(int i)
 		{
@@ -38,7 +45,7 @@
 		public void  Read(Directory directory)
 		{
 			
-			InputStream input = directory.OpenFile("segments");
+			IndexInput input = directory.OpenInput(IndexFileNames.SEGMENTS);
 			try
 			{
 				int format = input.ReadInt();
@@ -68,7 +75,7 @@
 				{
 					// in old format the version number may be at the end of the file
 					if (input.GetFilePointer() >= input.Length())
-						version = 0;
+						version = (System.DateTime.Now.Ticks - 621355968000000000) / 10000;
 					// old file format without version number
 					else
 						version = input.ReadLong(); // read version
@@ -82,7 +89,7 @@
 		
 		public void  Write(Directory directory)
 		{
-			OutputStream output = directory.CreateFile("segments.new");
+			IndexOutput output = directory.CreateOutput("segments.new");
 			try
 			{
 				output.WriteInt(FORMAT); // write FORMAT
@@ -102,7 +109,7 @@
 			}
 			
 			// install new segment info
-			directory.RenameFile("segments.new", "segments");
+			directory.RenameFile("segments.new", IndexFileNames.SEGMENTS);
 		}
 		
 		/// <summary> version number when this SegmentInfos was generated.</summary>
@@ -115,7 +122,7 @@
 		public static long ReadCurrentVersion(Directory directory)
 		{
 			
-			InputStream input = directory.OpenFile("segments");
+			IndexInput input = directory.OpenInput(IndexFileNames.SEGMENTS);
 			int format = 0;
 			long version = 0;
 			try

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/SegmentMergeInfo.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/SegmentMergeInfo.cs?rev=411501&r1=411500&r2=411501&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/SegmentMergeInfo.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/SegmentMergeInfo.cs Sat Jun  3 19:41:13 2006
@@ -13,7 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 using System;
+
 namespace Lucene.Net.Index
 {
 	
@@ -23,8 +25,8 @@
 		internal int base_Renamed;
 		internal TermEnum termEnum;
 		internal IndexReader reader;
-		internal TermPositions postings;
-		internal int[] docMap = null; // maps around deleted docs
+		private TermPositions postings; // use getPositions()
+		private int[] docMap; // use getDocMap()
 		
 		internal SegmentMergeInfo(int b, TermEnum te, IndexReader r)
 		{
@@ -32,22 +34,38 @@
 			reader = r;
 			termEnum = te;
 			term = te.Term();
-			postings = reader.TermPositions();
-			
-			// build array which maps document numbers around deletions 
-			if (reader.HasDeletions())
+		}
+		
+		// maps around deleted docs
+		internal int[] GetDocMap()
+		{
+			if (docMap == null)
 			{
-				int maxDoc = reader.MaxDoc();
-				docMap = new int[maxDoc];
-				int j = 0;
-				for (int i = 0; i < maxDoc; i++)
+				// build array which maps document numbers around deletions 
+				if (reader.HasDeletions())
 				{
-					if (reader.IsDeleted(i))
-						docMap[i] = - 1;
-					else
-						docMap[i] = j++;
+					int maxDoc = reader.MaxDoc();
+					docMap = new int[maxDoc];
+					int j = 0;
+					for (int i = 0; i < maxDoc; i++)
+					{
+						if (reader.IsDeleted(i))
+							docMap[i] = - 1;
+						else
+							docMap[i] = j++;
+					}
 				}
 			}
+			return docMap;
+		}
+		
+		internal TermPositions GetPositions()
+		{
+			if (postings == null)
+			{
+				postings = reader.TermPositions();
+			}
+			return postings;
 		}
 		
 		internal bool Next()
@@ -67,7 +85,10 @@
 		internal void  Close()
 		{
 			termEnum.Close();
-			postings.Close();
+			if (postings != null)
+			{
+				postings.Close();
+			}
 		}
 	}
 }

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/SegmentMergeQueue.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/SegmentMergeQueue.cs?rev=411501&r1=411500&r2=411501&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/SegmentMergeQueue.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/SegmentMergeQueue.cs Sat Jun  3 19:41:13 2006
@@ -13,8 +13,10 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 using System;
 using PriorityQueue = Lucene.Net.Util.PriorityQueue;
+
 namespace Lucene.Net.Index
 {
 	

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/SegmentMerger.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/SegmentMerger.cs?rev=411501&r1=411500&r2=411501&view=diff
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/SegmentMerger.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/SegmentMerger.cs Sat Jun  3 19:41:13 2006
@@ -13,10 +13,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 using System;
 using Directory = Lucene.Net.Store.Directory;
-using OutputStream = Lucene.Net.Store.OutputStream;
+using IndexOutput = Lucene.Net.Store.IndexOutput;
 using RAMOutputStream = Lucene.Net.Store.RAMOutputStream;
+
 namespace Lucene.Net.Index
 {
 	
@@ -28,39 +30,47 @@
 	/// 
 	/// 
 	/// </summary>
-	/// <seealso cref="#merge">
+	/// <seealso cref="merge">
 	/// </seealso>
-	/// <seealso cref="#add">
+	/// <seealso cref="add">
 	/// </seealso>
-	sealed public class SegmentMerger
+	public sealed class SegmentMerger
 	{
-		private bool useCompoundFile;
+		private void  InitBlock()
+		{
+			termIndexInterval = IndexWriter.DEFAULT_TERM_INDEX_INTERVAL;
+		}
 		private Directory directory;
 		private System.String segment;
+		private int termIndexInterval;
 		
 		private System.Collections.ArrayList readers = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
 		private FieldInfos fieldInfos;
 		
-		// File extensions of old-style index files
-		private static readonly System.String[] COMPOUND_EXTENSIONS = new System.String[]{"fnm", "frq", "prx", "fdx", "fdt", "tii", "tis"};
-		private static readonly System.String[] VECTOR_EXTENSIONS = new System.String[]{"tvx", "tvd", "tvf"};
-		
-		/// <summary> </summary>
+		/// <summary>This ctor used only by test code.
+		/// 
+		/// </summary>
 		/// <param name="dir">The Directory to merge the other segments into
 		/// </param>
 		/// <param name="name">The name of the new segment
 		/// </param>
-		/// <param name="compoundFile">true if the new segment should use a compoundFile
-		/// </param>
-		public /*internal*/ SegmentMerger(Directory dir, System.String name, bool compoundFile)
+		public /*internal*/ SegmentMerger(Directory dir, System.String name)
 		{
+			InitBlock();
 			directory = dir;
 			segment = name;
-			useCompoundFile = compoundFile;
+		}
+		
+		internal SegmentMerger(IndexWriter writer, System.String name)
+		{
+			InitBlock();
+			directory = writer.GetDirectory();
+			segment = name;
+			termIndexInterval = writer.GetTermIndexInterval();
 		}
 		
 		/// <summary> Add an IndexReader to the collection of readers that are to be merged</summary>
-		/// <param name="">reader
+		/// <param name="reader">
 		/// </param>
 		public /*internal*/ void  Add(IndexReader reader)
 		{
@@ -92,9 +102,6 @@
 			if (fieldInfos.HasVectors())
 				MergeVectors();
 			
-			if (useCompoundFile)
-				CreateCompoundFile();
-			
 			return value_Renamed;
 		}
 		
@@ -112,23 +119,23 @@
 			}
 		}
 		
-		private void  CreateCompoundFile()
+		public System.Collections.ArrayList CreateCompoundFile(System.String fileName)
 		{
-			CompoundFileWriter cfsWriter = new CompoundFileWriter(directory, segment + ".cfs");
+			CompoundFileWriter cfsWriter = new CompoundFileWriter(directory, fileName);
 			
-			System.Collections.ArrayList files = new System.Collections.ArrayList(COMPOUND_EXTENSIONS.Length + fieldInfos.Size());
+			System.Collections.ArrayList files = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(IndexFileNames.COMPOUND_EXTENSIONS.Length + fieldInfos.Size()));
 			
 			// Basic files
-			for (int i = 0; i < COMPOUND_EXTENSIONS.Length; i++)
+			for (int i = 0; i < IndexFileNames.COMPOUND_EXTENSIONS.Length; i++)
 			{
-				files.Add(segment + "." + COMPOUND_EXTENSIONS[i]);
+				files.Add(segment + "." + IndexFileNames.COMPOUND_EXTENSIONS[i]);
 			}
 			
 			// Field norm files
 			for (int i = 0; i < fieldInfos.Size(); i++)
 			{
 				FieldInfo fi = fieldInfos.FieldInfo(i);
-				if (fi.isIndexed)
+				if (fi.isIndexed && !fi.omitNorms)
 				{
 					files.Add(segment + ".f" + i);
 				}
@@ -137,9 +144,9 @@
 			// Vector files
 			if (fieldInfos.HasVectors())
 			{
-				for (int i = 0; i < VECTOR_EXTENSIONS.Length; i++)
+				for (int i = 0; i < IndexFileNames.VECTOR_EXTENSIONS.Length; i++)
 				{
-					files.Add(segment + "." + VECTOR_EXTENSIONS[i]);
+					files.Add(segment + "." + IndexFileNames.VECTOR_EXTENSIONS[i]);
 				}
 			}
 			
@@ -153,11 +160,17 @@
 			// Perform the merge
 			cfsWriter.Close();
 			
-			// Now delete the source files
-			it = files.GetEnumerator();
-			while (it.MoveNext())
+			return files;
+		}
+		
+		private void  AddIndexed(IndexReader reader, FieldInfos fieldInfos, System.Collections.ICollection names, bool storeTermVectors, bool storePositionWithTermVector, bool storeOffsetWithTermVector)
+		{
+			System.Collections.IEnumerator i = names.GetEnumerator();
+			while (i.MoveNext())
 			{
-				directory.DeleteFile((System.String) it.Current);
+                System.Collections.DictionaryEntry e = (System.Collections.DictionaryEntry) i.Current;
+                System.String field = (System.String) e.Key;
+				fieldInfos.Add(field, true, storeTermVectors, storePositionWithTermVector, storeOffsetWithTermVector, !reader.HasNorms(field));
 			}
 		}
 		
@@ -167,14 +180,17 @@
 		/// <throws>  IOException </throws>
 		private int MergeFields()
 		{
-			fieldInfos = new FieldInfos(); // merge Field names
+			fieldInfos = new FieldInfos(); // merge field names
 			int docCount = 0;
 			for (int i = 0; i < readers.Count; i++)
 			{
 				IndexReader reader = (IndexReader) readers[i];
-				fieldInfos.AddIndexed(reader.GetIndexedFieldNames(true), true);
-				fieldInfos.AddIndexed(reader.GetIndexedFieldNames(false), false);
-				fieldInfos.Add(reader.GetFieldNames(false), false);
+				AddIndexed(reader, fieldInfos, reader.GetFieldNames(IndexReader.FieldOption.TERMVECTOR_WITH_POSITION_OFFSET), true, true, true);
+				AddIndexed(reader, fieldInfos, reader.GetFieldNames(IndexReader.FieldOption.TERMVECTOR_WITH_POSITION), true, true, false);
+				AddIndexed(reader, fieldInfos, reader.GetFieldNames(IndexReader.FieldOption.TERMVECTOR_WITH_OFFSET), true, false, true);
+				AddIndexed(reader, fieldInfos, reader.GetFieldNames(IndexReader.FieldOption.TERMVECTOR), true, false, false);
+				AddIndexed(reader, fieldInfos, reader.GetFieldNames(IndexReader.FieldOption.INDEXED), false, false, false);
+				fieldInfos.Add(reader.GetFieldNames(IndexReader.FieldOption.UNINDEXED), false);
 			}
 			fieldInfos.Write(directory, segment + ".fnm");
 			
@@ -217,31 +233,8 @@
 					{
 						// skip deleted docs
 						if (reader.IsDeleted(docNum))
-						{
 							continue;
-						}
-						termVectorsWriter.OpenDocument();
-						
-						// get all term vectors
-						TermFreqVector[] sourceTermVector = reader.GetTermFreqVectors(docNum);
-						
-						if (sourceTermVector != null)
-						{
-							for (int f = 0; f < sourceTermVector.Length; f++)
-							{
-								// translate Field numbers
-								TermFreqVector termVector = sourceTermVector[f];
-								termVectorsWriter.OpenField(termVector.GetField());
-								System.String[] terms = termVector.GetTerms();
-								int[] freqs = termVector.GetTermFrequencies();
-								
-								for (int t = 0; t < terms.Length; t++)
-								{
-									termVectorsWriter.AddTerm(terms[t], freqs[t]);
-								}
-							}
-							termVectorsWriter.CloseDocument();
-						}
+						termVectorsWriter.AddAllDocVectors(reader.GetTermFreqVectors(docNum));
 					}
 				}
 			}
@@ -251,8 +244,8 @@
 			}
 		}
 		
-		private OutputStream freqOutput = null;
-		private OutputStream proxOutput = null;
+		private IndexOutput freqOutput = null;
+		private IndexOutput proxOutput = null;
 		private TermInfosWriter termInfosWriter = null;
 		private int skipInterval;
 		private SegmentMergeQueue queue = null;
@@ -261,9 +254,9 @@
 		{
 			try
 			{
-				freqOutput = directory.CreateFile(segment + ".frq");
-				proxOutput = directory.CreateFile(segment + ".prx");
-				termInfosWriter = new TermInfosWriter(directory, segment, fieldInfos);
+				freqOutput = directory.CreateOutput(segment + ".frq");
+				proxOutput = directory.CreateOutput(segment + ".prx");
+				termInfosWriter = new TermInfosWriter(directory, segment, fieldInfos, termIndexInterval);
 				skipInterval = termInfosWriter.skipInterval;
 				queue = new SegmentMergeQueue(readers.Count);
 				
@@ -374,9 +367,9 @@
 			for (int i = 0; i < n; i++)
 			{
 				SegmentMergeInfo smi = smis[i];
-				TermPositions postings = smi.postings;
+				TermPositions postings = smi.GetPositions();
 				int base_Renamed = smi.base_Renamed;
-				int[] docMap = smi.docMap;
+				int[] docMap = smi.GetDocMap();
 				postings.Seek(smi.termEnum);
 				while (postings.Next())
 				{
@@ -428,7 +421,7 @@
 		
 		private void  ResetSkip()
 		{
-			skipBuffer.Leset();
+			skipBuffer.Reset();
 			lastSkipDoc = 0;
 			lastSkipFreqPointer = freqOutput.GetFilePointer();
 			lastSkipProxPointer = proxOutput.GetFilePointer();
@@ -460,22 +453,22 @@
 			for (int i = 0; i < fieldInfos.Size(); i++)
 			{
 				FieldInfo fi = fieldInfos.FieldInfo(i);
-				if (fi.isIndexed)
+				if (fi.isIndexed && !fi.omitNorms)
 				{
-					OutputStream output = directory.CreateFile(segment + ".f" + i);
+					IndexOutput output = directory.CreateOutput(segment + ".f" + i);
 					try
 					{
 						for (int j = 0; j < readers.Count; j++)
 						{
 							IndexReader reader = (IndexReader) readers[j];
-							byte[] input = reader.Norms(fi.name);
 							int maxDoc = reader.MaxDoc();
+							byte[] input = new byte[maxDoc];
+							reader.Norms(fi.name, input, 0);
 							for (int k = 0; k < maxDoc; k++)
 							{
-								byte norm = input != null?input[k]:(byte) 0;
 								if (!reader.IsDeleted(k))
 								{
-									output.WriteByte(norm);
+									output.WriteByte(input[k]);
 								}
 							}
 						}



Mime
View raw message