You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucenenet.apache.org by ar...@apache.org on 2007/05/01 20:45:35 UTC

svn commit: r534192 [6/19] - in /incubator/lucene.net/trunk/C#: ./ src/ src/Demo/ src/Demo/DeleteFiles/ src/Demo/DemoLib/ src/Demo/DemoLib/HTML/ src/Demo/IndexFiles/ src/Demo/IndexHtml/ src/Demo/SearchFiles/ src/Lucene.Net/ src/Lucene.Net/Analysis/ src...

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Document/Package.html
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Document/Package.html?view=diff&rev=534192&r1=534191&r2=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Document/Package.html (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Document/Package.html Tue May  1 11:45:26 2007
@@ -1,10 +1,10 @@
-<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
-<html>
-<head>
-   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
-   <meta name="Author" content="Doug Cutting">
-</head>
-<body>
-The Document abstraction.
-</body>
-</html>
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+   <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+   <meta name="Author" content="Doug Cutting">
+</head>
+<body>
+The Document abstraction.
+</body>
+</html>

Added: incubator/lucene.net/trunk/C#/src/Lucene.Net/Document/SetBasedFieldSelector.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Document/SetBasedFieldSelector.cs?view=auto&rev=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Document/SetBasedFieldSelector.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Document/SetBasedFieldSelector.cs Tue May  1 11:45:26 2007
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Lucene.Net.Documents
+{
+	/// <summary> Declare what fields to load normally and what fields to load lazily
+	/// 
+	/// 
+	/// </summary>
+	public class SetBasedFieldSelector : FieldSelector
+	{
+		
+		private System.Collections.Hashtable fieldsToLoad;
+		private System.Collections.Hashtable lazyFieldsToLoad;
+		
+		
+		
+		/// <summary> Pass in the Set of {@link Field} names to load and the Set of {@link Field} names to load lazily.  If both are null, the
+		/// Document will not have any {@link Field} on it.  
+		/// </summary>
+		/// <param name="fieldsToLoad">A Set of {@link String} field names to load.  May be empty, but not null
+		/// </param>
+		/// <param name="lazyFieldsToLoad">A Set of {@link String} field names to load lazily.  May be empty, but not null  
+		/// </param>
+		public SetBasedFieldSelector(System.Collections.Hashtable fieldsToLoad, System.Collections.Hashtable lazyFieldsToLoad)
+		{
+			this.fieldsToLoad = fieldsToLoad;
+			this.lazyFieldsToLoad = lazyFieldsToLoad;
+		}
+		
+		/// <summary> Indicate whether to load the field with the given name or not. If the {@link Field#Name()} is not in either of the 
+		/// initializing Sets, then {@link Lucene.Net.Documents.FieldSelectorResult#NO_LOAD} is returned.  If a Field name
+		/// is in both <code>fieldsToLoad</code> and <code>lazyFieldsToLoad</code>, lazy has precedence.
+		/// 
+		/// </summary>
+		/// <param name="fieldName">The {@link Field} name to check
+		/// </param>
+		/// <returns> The {@link FieldSelectorResult}
+		/// </returns>
+		public virtual FieldSelectorResult Accept(System.String fieldName)
+		{
+			FieldSelectorResult result = FieldSelectorResult.NO_LOAD;
+			if (fieldsToLoad.Contains(fieldName) == true)
+			{
+				result = FieldSelectorResult.LOAD;
+			}
+			if (lazyFieldsToLoad.Contains(fieldName) == true)
+			{
+				result = FieldSelectorResult.LAZY_LOAD;
+			}
+			return result;
+		}
+	}
+}
\ No newline at end of file

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/CompoundFileReader.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/CompoundFileReader.cs?view=diff&rev=534192&r1=534191&r2=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/CompoundFileReader.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/CompoundFileReader.cs Tue May  1 11:45:26 2007
@@ -16,9 +16,9 @@
  */
 
 using System;
-using BufferedIndexInput = Lucene.Net.Store.BufferedIndexInput;
 using Directory = Lucene.Net.Store.Directory;
 using IndexInput = Lucene.Net.Store.IndexInput;
+using BufferedIndexInput = Lucene.Net.Store.BufferedIndexInput;
 using IndexOutput = Lucene.Net.Store.IndexOutput;
 using Lock = Lucene.Net.Store.Lock;
 
@@ -33,7 +33,7 @@
 	/// </summary>
 	/// <author>  Dmitry Serebrennikov
 	/// </author>
-	/// <version>  $Id: CompoundFileReader.java 208905 2005-07-03 10:40:01Z dnaber $
+	/// <version>  $Id: CompoundFileReader.java 472959 2006-11-09 16:21:50Z yonik $
 	/// </version>
 	public class CompoundFileReader : Directory
 	{
@@ -148,9 +148,9 @@
 		public override System.String[] List()
 		{
 			System.String[] res = new System.String[entries.Count];
-            entries.Keys.CopyTo(res, 0);
+			entries.Keys.CopyTo(res, 0);
 			return res;
-		}
+        }
 		
 		/// <summary>Returns true iff a file with the given name exists. </summary>
 		public override bool FileExists(System.String name)
@@ -251,7 +251,7 @@
 			/// <summary>Expert: implements seek.  Sets current position in this file, where
 			/// the next {@link #ReadInternal(byte[],int,int)} will occur.
 			/// </summary>
-			/// <seealso cref="ReadInternal(byte[],int,int)">
+			/// <seealso cref="#ReadInternal(byte[],int,int)">
 			/// </seealso>
 			public override void  SeekInternal(long pos)
 			{

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/CompoundFileWriter.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/CompoundFileWriter.cs?view=diff&rev=534192&r1=534191&r2=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/CompoundFileWriter.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/CompoundFileWriter.cs Tue May  1 11:45:26 2007
@@ -17,8 +17,8 @@
 
 using System;
 using Directory = Lucene.Net.Store.Directory;
-using IndexInput = Lucene.Net.Store.IndexInput;
 using IndexOutput = Lucene.Net.Store.IndexOutput;
+using IndexInput = Lucene.Net.Store.IndexInput;
 
 namespace Lucene.Net.Index
 {
@@ -46,7 +46,7 @@
 	/// </summary>
 	/// <author>  Dmitry Serebrennikov
 	/// </author>
-	/// <version>  $Id: CompoundFileWriter.java 179621 2005-06-02 18:18:50Z dnaber $
+	/// <version>  $Id: CompoundFileWriter.java 472959 2006-11-09 16:21:50Z yonik $
 	/// </version>
 	public sealed class CompoundFileWriter
 	{
@@ -117,14 +117,14 @@
 			if (file == null)
 				throw new System.NullReferenceException("file cannot be null");
 			
-            try
-            {
-                ids.Add(file, file);
-            }
-            catch (Exception)
-            {
-                throw new System.ArgumentException("File " + file + " already added");
-            }
+			try
+			{
+				ids.Add(file, file);
+			}
+			catch (Exception)
+			{
+				throw new System.ArgumentException("File " + file + " already added");
+			}
 			
 			FileEntry entry = new FileEntry();
 			entry.file = file;

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/DocumentWriter.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/DocumentWriter.cs?view=diff&rev=534192&r1=534191&r2=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/DocumentWriter.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/DocumentWriter.cs Tue May  1 11:45:26 2007
@@ -20,7 +20,7 @@
 using Token = Lucene.Net.Analysis.Token;
 using TokenStream = Lucene.Net.Analysis.TokenStream;
 using Document = Lucene.Net.Documents.Document;
-using Field = Lucene.Net.Documents.Field;
+using Fieldable = Lucene.Net.Documents.Fieldable;
 using Similarity = Lucene.Net.Search.Similarity;
 using Directory = Lucene.Net.Store.Directory;
 using IndexOutput = Lucene.Net.Store.IndexOutput;
@@ -72,7 +72,7 @@
 			this.termIndexInterval = writer.GetTermIndexInterval();
 		}
 		
-		public /*internal*/ void  AddDocument(System.String segment, Document doc)
+		public void  AddDocument(System.String segment, Document doc)
 		{
 			// write field names
 			fieldInfos = new FieldInfos();
@@ -97,11 +97,11 @@
 			fieldOffsets = new int[fieldInfos.Size()]; // init fieldOffsets
 			
 			fieldBoosts = new float[fieldInfos.Size()]; // init fieldBoosts
-            float boost = doc.GetBoost();
-            for (int i = 0; i < fieldBoosts.Length; i++)
-            {
-                fieldBoosts[i] = boost;
-            }
+			float boost = doc.GetBoost();
+			for (int i = 0; i < fieldBoosts.Length; i++)
+			{
+				fieldBoosts[i] = boost;
+			}
 			
 			InvertDocument(doc);
 			
@@ -139,8 +139,10 @@
 		// Tokenizes the fields of a document into Postings.
 		private void  InvertDocument(Document doc)
 		{
-			foreach(Field field in doc.Fields())
+			System.Collections.IEnumerator fieldIterator = doc.GetFields().GetEnumerator();
+			while (fieldIterator.MoveNext())
 			{
+				Fieldable field = (Fieldable) fieldIterator.Current;
 				System.String fieldName = field.Name();
 				int fieldNumber = fieldInfos.FieldNumber(fieldName);
 				
@@ -188,7 +190,7 @@
 									AddPosition(fieldName, t.TermText(), position++, null);
 								
 								lastToken = t;
-								if (++length > maxFieldLength)
+								if (++length >= maxFieldLength)
 								{
 									if (infoStream != null)
 										infoStream.WriteLine("maxFieldLength " + maxFieldLength + " reached, ignoring following tokens");
@@ -229,9 +231,7 @@
 					// positions array is full
 					int[] newPositions = new int[freq * 2]; // double size
 					int[] positions = ti.positions;
-					for (int i = 0; i < freq; i++)
-					// copy old positions to new
-						newPositions[i] = positions[i];
+					Array.Copy(positions, 0, newPositions, 0, freq);
 					ti.positions = newPositions;
 				}
 				ti.positions[freq] = position; // add new position
@@ -242,10 +242,7 @@
 					{
 						TermVectorOffsetInfo[] newOffsets = new TermVectorOffsetInfo[freq * 2];
 						TermVectorOffsetInfo[] offsets = ti.offsets;
-						for (int i = 0; i < freq; i++)
-						{
-							newOffsets[i] = offsets[i];
-						}
+						Array.Copy(offsets, 0, newOffsets, 0, freq);
 						ti.offsets = newOffsets;
 					}
 					ti.offsets[freq] = offset;

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/FieldInfo.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/FieldInfo.cs?view=diff&rev=534192&r1=534191&r2=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/FieldInfo.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/FieldInfo.cs Tue May  1 11:45:26 2007
@@ -27,16 +27,16 @@
 		internal int number;
 		
 		// true if term vector for this field should be stored
-		public /*internal*/ bool storeTermVector;
-		public /*internal*/ bool storeOffsetWithTermVector;
-		public /*internal*/ bool storePositionWithTermVector;
+		public bool storeTermVector;
+		public bool storeOffsetWithTermVector;
+		public bool storePositionWithTermVector;
 		
-		public /*internal*/ bool omitNorms; // omit norms associated with indexed fields
+		public bool omitNorms; // omit norms associated with indexed fields
 		
-        public bool IsIndexed()
-        {
-            return isIndexed;
-        }
+		public bool IsIndexed()
+		{
+			return isIndexed;
+		}
 
 		internal FieldInfo(System.String na, bool tk, int nu, bool storeTermVector, bool storePositionWithTermVector, bool storeOffsetWithTermVector, bool omitNorms)
 		{

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/FieldInfos.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/FieldInfos.cs?view=diff&rev=534192&r1=534191&r2=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/FieldInfos.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/FieldInfos.cs Tue May  1 11:45:26 2007
@@ -17,7 +17,7 @@
 
 using System;
 using Document = Lucene.Net.Documents.Document;
-using Field = Lucene.Net.Documents.Field;
+using Fieldable = Lucene.Net.Documents.Fieldable;
 using Directory = Lucene.Net.Store.Directory;
 using IndexInput = Lucene.Net.Store.IndexInput;
 using IndexOutput = Lucene.Net.Store.IndexOutput;
@@ -25,8 +25,8 @@
 namespace Lucene.Net.Index
 {
 	
-	/// <summary>Access to the Field Info file that describes document fields and whether or
-	/// not they are indexed. Each segment has a separate Field Info file. Objects
+	/// <summary>Access to the Fieldable Info file that describes document fields and whether or
+	/// not they are indexed. Each segment has a separate Fieldable Info file. Objects
 	/// of this class are thread-safe for multiple readers, but only one thread can
 	/// be adding documents at a time, with no other reader or writer threads
 	/// accessing this object.
@@ -43,7 +43,7 @@
 		private System.Collections.ArrayList byNumber = new System.Collections.ArrayList();
 		private System.Collections.Hashtable byName = new System.Collections.Hashtable();
 		
-		public /*internal*/ FieldInfos()
+		public FieldInfos()
 		{
 		}
 		
@@ -55,7 +55,7 @@
 		/// <param name="name">The name of the file to open the IndexInput from in the Directory
 		/// </param>
 		/// <throws>  IOException </throws>
-		public /*internal*/ FieldInfos(Directory d, System.String name)
+		public FieldInfos(Directory d, System.String name)
 		{
 			IndexInput input = d.OpenInput(name);
 			try
@@ -71,8 +71,11 @@
 		/// <summary>Adds field info for a Document. </summary>
 		public void  Add(Document doc)
 		{
-            foreach (Field field in doc.Fields())
-            {
+			System.Collections.IList fields = doc.GetFields();
+			System.Collections.IEnumerator fieldIterator = fields.GetEnumerator();
+			while (fieldIterator.MoveNext())
+			{
+				Fieldable field = (Fieldable) fieldIterator.Current;
 				Add(field.Name(), field.IsIndexed(), field.IsTermVectorStored(), field.IsStorePositionWithTermVector(), field.IsStoreOffsetWithTermVector(), field.GetOmitNorms());
 			}
 		}
@@ -106,7 +109,7 @@
 		/// <param name="isIndexed">Whether the fields are indexed or not
 		/// 
 		/// </param>
-		/// <seealso cref="Add(String, boolean)">
+		/// <seealso cref="boolean)">
 		/// </seealso>
 		public void  Add(System.Collections.ICollection names, bool isIndexed)
 		{
@@ -121,11 +124,11 @@
 		/// <summary> Calls 5 parameter add with false for all TermVector parameters.
 		/// 
 		/// </summary>
-		/// <param name="name">The name of the Field
+		/// <param name="name">The name of the Fieldable
 		/// </param>
 		/// <param name="isIndexed">true if the field is indexed
 		/// </param>
-		/// <seealso cref="Add(String, boolean, boolean, boolean, boolean)">
+		/// <seealso cref="boolean, boolean, boolean, boolean)">
 		/// </seealso>
 		public void  Add(System.String name, bool isIndexed)
 		{
@@ -249,7 +252,7 @@
 		/// <summary> Return the fieldName identified by its number.
 		/// 
 		/// </summary>
-		/// <param name="fieldNumber">
+		/// <param name="">fieldNumber
 		/// </param>
 		/// <returns> the fieldName or an empty string when the field
 		/// with the given number doesn't exist.
@@ -260,21 +263,10 @@
 			if (fi != null)
 				return fi.name;
 			return "";
-
-			/*
-			try
-			{
-				return FieldInfo(fieldNumber).name;
-			}
-			catch (System.NullReferenceException)
-			{
-				return "";
-			}
-			*/
 		}
 		
 		/// <summary> Return the fieldinfo object referenced by the fieldNumber.</summary>
-		/// <param name="fieldNumber">
+		/// <param name="">fieldNumber
 		/// </param>
 		/// <returns> the FieldInfo object or null when the given fieldNumber
 		/// doesn't exist.
@@ -284,17 +276,6 @@
 			if (fieldNumber > -1 && fieldNumber < byNumber.Count)
 				return (FieldInfo) byNumber[fieldNumber];
 			return null;
-
-			/*
-            try
-			{
-				return (FieldInfo) byNumber[fieldNumber];
-			}
-			catch (System.ArgumentOutOfRangeException) // (System.IndexOutOfRangeException)
-			{
-				return null;
-			}
-			*/
 		}
 		
 		public int Size()

Added: incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/FieldReaderException.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/FieldReaderException.cs?view=auto&rev=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/FieldReaderException.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/FieldReaderException.cs Tue May  1 11:45:26 2007
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+
+namespace Lucene.Net.Index
+{
+	/// <summary> 
+	/// 
+	/// 
+	/// </summary>
+	[Serializable]
+	public class FieldReaderException : System.SystemException
+	{
+		/// <summary> Constructs a new runtime exception with <code>null</code> as its
+		/// detail message.  The cause is not initialized, and may subsequently be
+		/// initialized by a call to {@link #initCause}.
+		/// </summary>
+		public FieldReaderException()
+		{
+		}
+		
+		/// <summary> Constructs a new runtime exception with the specified cause and a
+		/// detail message of <tt>(cause==null ? null : cause.toString())</tt>
+		/// (which typically contains the class and detail message of
+		/// <tt>cause</tt>).  This constructor is useful for runtime exceptions
+		/// that are little more than wrappers for other throwables.
+		/// 
+		/// </summary>
+		/// <param name="cause">the cause (which is saved for later retrieval by the
+		/// {@link #getCause()} method).  (A <tt>null</tt> value is
+		/// permitted, and indicates that the cause is nonexistent or
+		/// unknown.)
+		/// </param>
+		/// <since> 1.4
+		/// </since>
+		public FieldReaderException(System.Exception cause)
+		{
+		}
+		
+		/// <summary> Constructs a new runtime exception with the specified detail message.
+		/// The cause is not initialized, and may subsequently be initialized by a
+		/// call to {@link #initCause}.
+		/// 
+		/// </summary>
+		/// <param name="message">the detail message. The detail message is saved for
+		/// later retrieval by the {@link #getMessage()} method.
+		/// </param>
+		public FieldReaderException(System.String message)
+		{
+		}
+		
+		/// <summary> Constructs a new runtime exception with the specified detail message and
+		/// cause.  <p>Note that the detail message associated with
+		/// <code>cause</code> is <i>not</i> automatically incorporated in
+		/// this runtime exception's detail message.
+		/// 
+		/// </summary>
+		/// <param name="message">the detail message (which is saved for later retrieval
+		/// by the {@link #getMessage()} method).
+		/// </param>
+		/// <param name="cause">  the cause (which is saved for later retrieval by the
+		/// {@link #getCause()} method).  (A <tt>null</tt> value is
+		/// permitted, and indicates that the cause is nonexistent or
+		/// unknown.)
+		/// </param>
+		/// <since> 1.4
+		/// </since>
+		public FieldReaderException(System.String message, System.Exception cause)
+		{
+		}
+	}
+}
\ No newline at end of file

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/FieldsReader.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/FieldsReader.cs?view=diff&rev=534192&r1=534191&r2=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/FieldsReader.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/FieldsReader.cs Tue May  1 11:45:26 2007
@@ -16,8 +16,7 @@
  */
 
 using System;
-using Document = Lucene.Net.Documents.Document;
-using Field = Lucene.Net.Documents.Field;
+using Lucene.Net.Documents;
 using Directory = Lucene.Net.Store.Directory;
 using IndexInput = Lucene.Net.Store.IndexInput;
 
@@ -25,41 +24,62 @@
 {
 	
 	/// <summary> Class responsible for access to stored document fields.
-	/// 
+	/// <p/>
 	/// It uses &lt;segment&gt;.fdt and &lt;segment&gt;.fdx; files.
 	/// 
 	/// </summary>
-	/// <version>  $Id: FieldsReader.java 329524 2005-10-30 05:38:46Z yonik $
+	/// <version>  $Id: FieldsReader.java 507009 2007-02-13 14:06:52Z gsingers $
 	/// </version>
 	public sealed class FieldsReader
 	{
 		private FieldInfos fieldInfos;
+		
+		// The main fieldStream, used only for cloning.
+		private IndexInput cloneableFieldsStream;
+		
+		// This is a clone of cloneableFieldsStream used for reading documents.
+		// It should not be cloned outside of a synchronized context.
 		private IndexInput fieldsStream;
+		
 		private IndexInput indexStream;
 		private int size;
 		
-		public /*internal*/ FieldsReader(Directory d, System.String segment, FieldInfos fn)
+		private System.LocalDataStoreSlot fieldsStreamTL = System.Threading.Thread.AllocateDataSlot();
+		
+		public FieldsReader(Directory d, System.String segment, FieldInfos fn)
 		{
 			fieldInfos = fn;
 			
-			fieldsStream = d.OpenInput(segment + ".fdt");
+			cloneableFieldsStream = d.OpenInput(segment + ".fdt");
+			fieldsStream = (IndexInput) cloneableFieldsStream.Clone();
 			indexStream = d.OpenInput(segment + ".fdx");
-			
 			size = (int) (indexStream.Length() / 8);
 		}
 		
-		public /*internal*/ void  Close()
+		/// <summary> Closes the underlying {@link Lucene.Net.Store.IndexInput} streams, including any ones associated with a
+		/// lazy implementation of a Field.  This means that the Fields values will not be accessible.
+		/// 
+		/// </summary>
+		/// <throws>  IOException </throws>
+		public void  Close()
 		{
 			fieldsStream.Close();
+			cloneableFieldsStream.Close();
 			indexStream.Close();
+			IndexInput localFieldsStream = (IndexInput) System.Threading.Thread.GetData(fieldsStreamTL);
+			if (localFieldsStream != null)
+			{
+				localFieldsStream.Close();
+				System.Threading.Thread.SetData(fieldsStreamTL, null);
+			}
 		}
 		
-		public /*internal*/ int Size()
+		public int Size()
 		{
 			return size;
 		}
 		
-		public /*internal*/ Document Doc(int n)
+		public Document Doc(int n, FieldSelector fieldSelector)
 		{
 			indexStream.Seek(n * 8L);
 			long position = indexStream.ReadLong();
@@ -71,86 +91,426 @@
 			{
 				int fieldNumber = fieldsStream.ReadVInt();
 				FieldInfo fi = fieldInfos.FieldInfo(fieldNumber);
+				FieldSelectorResult acceptField = fieldSelector == null ? FieldSelectorResult.LOAD : fieldSelector.Accept(fi.name);
 				
 				byte bits = fieldsStream.ReadByte();
-				
 				bool compressed = (bits & FieldsWriter.FIELD_IS_COMPRESSED) != 0;
 				bool tokenize = (bits & FieldsWriter.FIELD_IS_TOKENIZED) != 0;
+				bool binary = (bits & FieldsWriter.FIELD_IS_BINARY) != 0;
+				//TODO: Find an alternative approach here if this list continues to grow beyond the
+				//list of 5 or 6 currently here.  See Lucene 762 for discussion
+				if (acceptField.Equals(FieldSelectorResult.LOAD))
+				{
+					AddField(doc, fi, binary, compressed, tokenize);
+				}
+				else if (acceptField.Equals(FieldSelectorResult.LOAD_FOR_MERGE))
+				{
+					AddFieldForMerge(doc, fi, binary, compressed, tokenize);
+				}
+				else if (acceptField.Equals(FieldSelectorResult.LOAD_AND_BREAK))
+				{
+					AddField(doc, fi, binary, compressed, tokenize);
+					break; //Get out of this loop
+				}
+				else if (acceptField.Equals(FieldSelectorResult.LAZY_LOAD))
+				{
+					AddFieldLazy(doc, fi, binary, compressed, tokenize);
+				}
+				else if (acceptField.Equals(FieldSelectorResult.SIZE))
+				{
+					SkipField(binary, compressed, AddFieldSize(doc, fi, binary, compressed));
+				}
+				else if (acceptField.Equals(FieldSelectorResult.SIZE_AND_BREAK))
+				{
+					AddFieldSize(doc, fi, binary, compressed);
+					break;
+				}
+				else
+				{
+					SkipField(binary, compressed);
+				}
+			}
+			
+			return doc;
+		}
+		
+		/// <summary> Skip the field.  We still have to read some of the information about the field, but can skip past the actual content.
+		/// This will have the most payoff on large fields.
+		/// </summary>
+		private void  SkipField(bool binary, bool compressed)
+		{
+			SkipField(binary, compressed, fieldsStream.ReadVInt());
+		}
+		
+		private void  SkipField(bool binary, bool compressed, int toRead)
+		{
+			if (binary || compressed)
+			{
+				long pointer = fieldsStream.GetFilePointer();
+				fieldsStream.Seek(pointer + toRead);
+			}
+			else
+			{
+				//We need to skip chars.  This will slow us down, but still better
+				fieldsStream.SkipChars(toRead);
+			}
+		}
+		
+		private void  AddFieldLazy(Document doc, FieldInfo fi, bool binary, bool compressed, bool tokenize)
+		{
+			if (binary == true)
+			{
+				int toRead = fieldsStream.ReadVInt();
+				long pointer = fieldsStream.GetFilePointer();
+				if (compressed)
+				{
+					//was: doc.add(new Fieldable(fi.name, uncompress(b), Fieldable.Store.COMPRESS));
+					doc.Add(new LazyField(this, fi.name, Field.Store.COMPRESS, toRead, pointer));
+				}
+				else
+				{
+					//was: doc.add(new Fieldable(fi.name, b, Fieldable.Store.YES));
+					doc.Add(new LazyField(this, fi.name, Field.Store.YES, toRead, pointer));
+				}
+				//Need to move the pointer ahead by toRead positions
+				fieldsStream.Seek(pointer + toRead);
+			}
+			else
+			{
+				Field.Store store = Field.Store.YES;
+				Field.Index index = GetIndexType(fi, tokenize);
+				Field.TermVector termVector = GetTermVectorType(fi);
 				
-				if ((bits & FieldsWriter.FIELD_IS_BINARY) != 0)
+				Fieldable f;
+				if (compressed)
 				{
-					byte[] b = new byte[fieldsStream.ReadVInt()];
-					fieldsStream.ReadBytes(b, 0, b.Length);
-					if (compressed)
-						doc.Add(new Field(fi.name, Uncompress(b), Field.Store.COMPRESS));
-					else
-						doc.Add(new Field(fi.name, b, Field.Store.YES));
+					store = Field.Store.COMPRESS;
+					int toRead = fieldsStream.ReadVInt();
+					long pointer = fieldsStream.GetFilePointer();
+					f = new LazyField(this, fi.name, store, toRead, pointer);
+					//skip over the part that we aren't loading
+					fieldsStream.Seek(pointer + toRead);
+					f.SetOmitNorms(fi.omitNorms);
 				}
 				else
 				{
-					Field.Index index;
-					Field.Store store = Field.Store.YES;
+					int length = fieldsStream.ReadVInt();
+					long pointer = fieldsStream.GetFilePointer();
+					//Skip ahead of where we are by the length of what is stored
+					fieldsStream.SkipChars(length);
+					f = new LazyField(this, fi.name, store, index, termVector, length, pointer);
+					f.SetOmitNorms(fi.omitNorms);
+				}
+				doc.Add(f);
+			}
+		}
+		
+		// in merge mode we don't uncompress the data of a compressed field
+		private void  AddFieldForMerge(Document doc, FieldInfo fi, bool binary, bool compressed, bool tokenize)
+		{
+			System.Object data;
+			
+			if (binary || compressed)
+			{
+				int toRead = fieldsStream.ReadVInt();
+				byte[] b = new byte[toRead];
+				fieldsStream.ReadBytes(b, 0, b.Length);
+				data = b;
+			}
+			else
+			{
+				data = fieldsStream.ReadString();
+			}
+			
+			doc.Add(new FieldForMerge(data, fi, binary, compressed, tokenize));
+		}
+		
+		private void  AddField(Document doc, FieldInfo fi, bool binary, bool compressed, bool tokenize)
+		{
+			
+			//we have a binary stored field, and it may be compressed
+			if (binary)
+			{
+				int toRead = fieldsStream.ReadVInt();
+				byte[] b = new byte[toRead];
+				fieldsStream.ReadBytes(b, 0, b.Length);
+				if (compressed)
+					doc.Add(new Field(fi.name, Uncompress(b), Field.Store.COMPRESS));
+				else
+					doc.Add(new Field(fi.name, b, Field.Store.YES));
+			}
+			else
+			{
+				Field.Store store = Field.Store.YES;
+				Field.Index index = GetIndexType(fi, tokenize);
+				Field.TermVector termVector = GetTermVectorType(fi);
+				
+				Fieldable f;
+				if (compressed)
+				{
+					store = Field.Store.COMPRESS;
+					int toRead = fieldsStream.ReadVInt();
 					
-					if (fi.isIndexed && tokenize)
-						index = Field.Index.TOKENIZED;
-					else if (fi.isIndexed && !tokenize)
-						index = Field.Index.UN_TOKENIZED;
+					byte[] b = new byte[toRead];
+					fieldsStream.ReadBytes(b, 0, b.Length);
+					f = new Field(fi.name, System.Text.Encoding.GetEncoding("UTF-8").GetString(Uncompress(b)), store, index, termVector);
+					f.SetOmitNorms(fi.omitNorms);
+				}
+				else
+				{
+					f = new Field(fi.name, fieldsStream.ReadString(), store, index, termVector);
+					f.SetOmitNorms(fi.omitNorms);
+				}
+				doc.Add(f);
+			}
+		}
+		
+		// Add the size of field as a byte[] containing the 4 bytes of the integer byte size (high order byte first; char = 2 bytes)
+		// Read just the size -- caller must skip the field content to continue reading fields
+		// Return the size in bytes or chars, depending on field type
+		private int AddFieldSize(Document doc, FieldInfo fi, bool binary, bool compressed)
+		{
+			int size = fieldsStream.ReadVInt(), bytesize = binary || compressed ? size : 2 * size;
+			byte[] sizebytes = new byte[4];
+			sizebytes[0] = (byte) (SupportClass.Number.URShift(bytesize, 24));
+			sizebytes[1] = (byte) (SupportClass.Number.URShift(bytesize, 16));
+			sizebytes[2] = (byte) (SupportClass.Number.URShift(bytesize, 8));
+			sizebytes[3] = (byte) bytesize;
+			doc.Add(new Field(fi.name, sizebytes, Field.Store.YES));
+			return size;
+		}
+		
+		private Field.TermVector GetTermVectorType(FieldInfo fi)
+		{
+			Field.TermVector termVector = null;
+			if (fi.storeTermVector)
+			{
+				if (fi.storeOffsetWithTermVector)
+				{
+					if (fi.storePositionWithTermVector)
+					{
+						termVector = Field.TermVector.WITH_POSITIONS_OFFSETS;
+					}
 					else
-						index = Field.Index.NO;
-					
-					Field.TermVector termVector = null;
-					if (fi.storeTermVector)
 					{
-						if (fi.storeOffsetWithTermVector)
-						{
-							if (fi.storePositionWithTermVector)
-							{
-								termVector = Field.TermVector.WITH_POSITIONS_OFFSETS;
-							}
-							else
-							{
-								termVector = Field.TermVector.WITH_OFFSETS;
-							}
-						}
-						else if (fi.storePositionWithTermVector)
+						termVector = Field.TermVector.WITH_OFFSETS;
+					}
+				}
+				else if (fi.storePositionWithTermVector)
+				{
+					termVector = Field.TermVector.WITH_POSITIONS;
+				}
+				else
+				{
+					termVector = Field.TermVector.YES;
+				}
+			}
+			else
+			{
+				termVector = Field.TermVector.NO;
+			}
+			return termVector;
+		}
+		
+		private Field.Index GetIndexType(FieldInfo fi, bool tokenize)
+		{
+			Field.Index index;
+			if (fi.isIndexed && tokenize)
+				index = Field.Index.TOKENIZED;
+			else if (fi.isIndexed && !tokenize)
+				index = Field.Index.UN_TOKENIZED;
+			else
+				index = Field.Index.NO;
+			return index;
+		}
+		
+		/// <summary> A Lazy implementation of Fieldable that differs loading of fields until asked for, instead of when the Document is
+		/// loaded.
+		/// </summary>
+		[Serializable]
+		private class LazyField:AbstractField, Fieldable
+		{
+			private void  InitBlock(FieldsReader enclosingInstance)
+			{
+				this.enclosingInstance = enclosingInstance;
+			}
+			private FieldsReader enclosingInstance;
+			public FieldsReader Enclosing_Instance
+			{
+				get
+				{
+					return enclosingInstance;
+				}
+				
+			}
+			private int toRead;
+			private long pointer;
+			
+			public LazyField(FieldsReader enclosingInstance, System.String name, Field.Store store, int toRead, long pointer):base(name, store, Field.Index.NO, Field.TermVector.NO)
+			{
+				InitBlock(enclosingInstance);
+				this.toRead = toRead;
+				this.pointer = pointer;
+				lazy = true;
+			}
+			
+			public LazyField(FieldsReader enclosingInstance, System.String name, Field.Store store, Field.Index index, Field.TermVector termVector, int toRead, long pointer):base(name, store, index, termVector)
+			{
+				InitBlock(enclosingInstance);
+				this.toRead = toRead;
+				this.pointer = pointer;
+				lazy = true;
+			}
+			
+			private IndexInput GetFieldStream()
+			{
+				IndexInput localFieldsStream = (IndexInput) System.Threading.Thread.GetData(Enclosing_Instance.fieldsStreamTL);
+				if (localFieldsStream == null)
+				{
+					localFieldsStream = (IndexInput) Enclosing_Instance.cloneableFieldsStream.Clone();
+					System.Threading.Thread.SetData(Enclosing_Instance.fieldsStreamTL, localFieldsStream);
+				}
+				return localFieldsStream;
+			}
+			
+			/// <summary> The value of the field in Binary, or null.  If null, the Reader or
+			/// String value is used.  Exactly one of stringValue(), readerValue() and
+			/// binaryValue() must be set.
+			/// </summary>
+			public override byte[] BinaryValue()
+			{
+				if (fieldsData == null)
+				{
+					byte[] b = new byte[toRead];
+					IndexInput localFieldsStream = GetFieldStream();
+					//Throw this IO Exception since IndexREader.document does so anyway, so probably not that big of a change for people
+					//since they are already handling this exception when getting the document
+					try
+					{
+						localFieldsStream.Seek(pointer);
+						localFieldsStream.ReadBytes(b, 0, b.Length);
+						if (isCompressed == true)
 						{
-							termVector = Field.TermVector.WITH_POSITIONS;
+							fieldsData = Enclosing_Instance.Uncompress(b);
 						}
 						else
 						{
-							termVector = Field.TermVector.YES;
+							fieldsData = b;
 						}
 					}
-					else
+					catch (System.IO.IOException e)
 					{
-						termVector = Field.TermVector.NO;
+						throw new FieldReaderException(e);
 					}
-					
-					if (compressed)
+				}
+				return fieldsData is byte[] ? (byte[]) fieldsData : null;
+			}
+			
+			/// <summary> The value of the field as a Reader, or null.  If null, the String value
+			/// or binary value is  used.  Exactly one of stringValue(), readerValue(),
+			/// and binaryValue() must be set.
+			/// </summary>
+			public override System.IO.TextReader ReaderValue()
+			{
+				return fieldsData is System.IO.TextReader ? (System.IO.TextReader) fieldsData : null;
+			}
+			
+			/// <summary> The value of the field as a String, or null.  If null, the Reader value
+			/// or binary value is used.  Exactly one of stringValue(), readerValue(), and
+			/// binaryValue() must be set.
+			/// </summary>
+			public override System.String StringValue()
+			{
+				if (fieldsData == null)
+				{
+					IndexInput localFieldsStream = GetFieldStream();
+					try
 					{
-						store = Field.Store.COMPRESS;
-						byte[] b = new byte[fieldsStream.ReadVInt()];
-						fieldsStream.ReadBytes(b, 0, b.Length);
-						Field f = new Field(fi.name, System.Text.Encoding.GetEncoding("UTF-8").GetString(Uncompress(b)), store, index, termVector);
-						f.SetOmitNorms(fi.omitNorms);
-						doc.Add(f);
+						localFieldsStream.Seek(pointer);
+						if (isCompressed)
+						{
+							byte[] b = new byte[toRead];
+							localFieldsStream.ReadBytes(b, 0, b.Length);
+							fieldsData = System.Text.Encoding.GetEncoding("UTF-8").GetString(Enclosing_Instance.Uncompress(b));
+						}
+						else
+						{
+							//read in chars b/c we already know the length we need to read
+							char[] chars = new char[toRead];
+							localFieldsStream.ReadChars(chars, 0, toRead);
+							fieldsData = new System.String(chars);
+						}
 					}
-					else
+					catch (System.IO.IOException e)
 					{
-						Field f = new Field(fi.name, fieldsStream.ReadString(), store, index, termVector);
-						f.SetOmitNorms(fi.omitNorms);
-						doc.Add(f);
+						throw new FieldReaderException(e);
 					}
 				}
+				return fieldsData is System.String ? (System.String) fieldsData : null;
 			}
 			
-			return doc;
+			public long GetPointer()
+			{
+				return pointer;
+			}
+			
+			public void  SetPointer(long pointer)
+			{
+				this.pointer = pointer;
+			}
+			
+			public int GetToRead()
+			{
+				return toRead;
+			}
+			
+			public void  SetToRead(int toRead)
+			{
+				this.toRead = toRead;
+			}
 		}
 		
 		private byte[] Uncompress(byte[] input)
 		{
-            // {{Aroush-2.0}} For .NET 2.0, replace this call to use the built-in compression support
-            return SupportClass.CompressionSupport.Uncompress(input);
+			return SupportClass.CompressionSupport.Uncompress(input);
+        }
+		
+		// Instances of this class hold field properties and data
+		// for merge
+		[Serializable]
+		public sealed class FieldForMerge : AbstractField
+		{
+			public override System.String StringValue()
+			{
+				return (System.String) this.fieldsData;
+			}
+			
+			public override System.IO.TextReader ReaderValue()
+			{
+				// not needed for merge
+				return null;
+			}
+			
+			public override byte[] BinaryValue()
+			{
+				return (byte[]) this.fieldsData;
+			}
+			
+			public FieldForMerge(System.Object value_Renamed, FieldInfo fi, bool binary, bool compressed, bool tokenize)
+			{
+				this.isStored = true;
+				this.fieldsData = value_Renamed;
+				this.isCompressed = compressed;
+				this.isBinary = binary;
+				this.isTokenized = tokenize;
+				
+				this.name = String.Intern(fi.name);
+				this.isIndexed = fi.isIndexed;
+				this.omitNorms = fi.omitNorms;
+				this.storeOffsetWithTermVector = fi.storeOffsetWithTermVector;
+				this.storePositionWithTermVector = fi.storePositionWithTermVector;
+				this.storeTermVector = fi.storeTermVector;
+			}
 		}
 	}
 }

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/FieldsWriter.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/FieldsWriter.cs?view=diff&rev=534192&r1=534191&r2=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/FieldsWriter.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/FieldsWriter.cs Tue May  1 11:45:26 2007
@@ -17,7 +17,7 @@
 
 using System;
 using Document = Lucene.Net.Documents.Document;
-using Field = Lucene.Net.Documents.Field;
+using Fieldable = Lucene.Net.Documents.Fieldable;
 using Directory = Lucene.Net.Store.Directory;
 using IndexOutput = Lucene.Net.Store.IndexOutput;
 
@@ -54,15 +54,23 @@
 			indexStream.WriteLong(fieldsStream.GetFilePointer());
 			
 			int storedCount = 0;
-            foreach (Field field  in doc.Fields())
-            {
+			System.Collections.IEnumerator fieldIterator = doc.GetFields().GetEnumerator();
+			while (fieldIterator.MoveNext())
+			{
+				Fieldable field = (Fieldable) fieldIterator.Current;
 				if (field.IsStored())
 					storedCount++;
 			}
 			fieldsStream.WriteVInt(storedCount);
 			
-			foreach (Field field in doc.Fields())
+			fieldIterator = doc.GetFields().GetEnumerator();
+			while (fieldIterator.MoveNext())
 			{
+				Fieldable field = (Fieldable) fieldIterator.Current;
+				// if the field as an instanceof FieldsReader.FieldForMerge, we're in merge mode
+				// and field.binaryValue() already returns the compressed value for a field
+				// with isCompressed()==true, so we disable compression in that case
+				bool disableCompression = (field is FieldsReader.FieldForMerge);
 				if (field.IsStored())
 				{
 					fieldsStream.WriteVInt(fieldInfos.FieldNumber(field.Name()));
@@ -81,14 +89,24 @@
 					{
 						// compression is enabled for the current field
 						byte[] data = null;
-						// check if it is a binary field
-						if (field.IsBinary())
+						
+						if (disableCompression)
 						{
-							data = Compress(field.BinaryValue());
+							// optimized case for merging, the data
+							// is already compressed
+							data = field.BinaryValue();
 						}
 						else
 						{
-							data = Compress(System.Text.Encoding.GetEncoding("UTF-8").GetBytes(field.StringValue()));
+							// check if it is a binary field
+							if (field.IsBinary())
+							{
+								data = Compress(field.BinaryValue());
+							}
+							else
+							{
+								data = Compress(System.Text.Encoding.GetEncoding("UTF-8").GetBytes(field.StringValue()));
+							}
 						}
 						int len = data.Length;
 						fieldsStream.WriteVInt(len);
@@ -115,8 +133,7 @@
 		
 		private byte[] Compress(byte[] input)
 		{
-            // {{Aroush-2.0}} For .NET 2.0, replace this call to use the built-in compression support
-            return SupportClass.CompressionSupport.Compress(input);
-		}
+			return SupportClass.CompressionSupport.Compress(input);
+        }
 	}
 }

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/FilterIndexReader.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/FilterIndexReader.cs?view=diff&rev=534192&r1=534191&r2=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/FilterIndexReader.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/FilterIndexReader.cs Tue May  1 11:45:26 2007
@@ -17,6 +17,7 @@
 
 using System;
 using Document = Lucene.Net.Documents.Document;
+using FieldSelector = Lucene.Net.Documents.FieldSelector;
 
 namespace Lucene.Net.Index
 {
@@ -152,9 +153,9 @@
 			return in_Renamed.MaxDoc();
 		}
 		
-		public override Document Document(int n)
+		public override Document Document(int n, FieldSelector fieldSelector)
 		{
-			return in_Renamed.Document(n);
+			return in_Renamed.Document(n, fieldSelector);
 		}
 		
 		public override bool IsDeleted(int n)
@@ -226,19 +227,19 @@
 		}
 		
 		
-        public override System.Collections.ICollection  GetFieldNames(IndexReader.FieldOption fieldNames)
-        {
-            return in_Renamed.GetFieldNames(fieldNames);
-        }
-		
-        public override long GetVersion()
-        {
-                return in_Renamed.GetVersion();
-        }
-		
-        public override bool IsCurrent()
-        {
-                return in_Renamed.IsCurrent();
-        }
-    }
+		public override System.Collections.ICollection GetFieldNames(IndexReader.FieldOption fieldNames)
+		{
+			return in_Renamed.GetFieldNames(fieldNames);
+		}
+		
+		public override long GetVersion()
+		{
+			return in_Renamed.GetVersion();
+		}
+
+		public override bool IsCurrent()
+		{
+			return in_Renamed.IsCurrent();
+		}
+	}
 }

Added: incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/IndexFileDeleter.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/IndexFileDeleter.cs?view=auto&rev=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/IndexFileDeleter.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/IndexFileDeleter.cs Tue May  1 11:45:26 2007
@@ -0,0 +1,356 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using Directory = Lucene.Net.Store.Directory;
+using Pattern = System.Text.RegularExpressions.Regex;
+
+namespace Lucene.Net.Index
+{
+	
+	/// <summary> A utility class (used by both IndexReader and
+	/// IndexWriter) to keep track of files that need to be
+	/// deleted because they are no longer referenced by the
+	/// index.
+	/// </summary>
+	sealed public class IndexFileDeleter
+	{
+		private System.Collections.ArrayList deletable;
+		private System.Collections.Hashtable pending;
+		private Directory directory;
+		private SegmentInfos segmentInfos;
+		private System.IO.TextWriter infoStream;
+		
+		internal IndexFileDeleter(SegmentInfos segmentInfos, Directory directory)
+		{
+			this.segmentInfos = segmentInfos;
+			this.directory = directory;
+		}
+		internal void  SetSegmentInfos(SegmentInfos segmentInfos)
+		{
+			this.segmentInfos = segmentInfos;
+		}
+		internal SegmentInfos GetSegmentInfos()
+		{
+			return segmentInfos;
+		}
+		
+		internal void  SetInfoStream(System.IO.TextWriter infoStream)
+		{
+			this.infoStream = infoStream;
+		}
+		
+		/// <summary>Determine index files that are no longer referenced
+		/// and therefore should be deleted.  This is called once
+		/// (by the writer), and then subsequently we add onto
+		/// deletable any files that are no longer needed at the
+		/// point that we create the unused file (eg when merging
+		/// segments), and we only remove from deletable when a
+		/// file is successfully deleted.
+		/// </summary>
+		
+		internal void  FindDeletableFiles()
+		{
+			
+			// Gather all "current" segments:
+			System.Collections.Hashtable current = new System.Collections.Hashtable();
+			for (int j = 0; j < segmentInfos.Count; j++)
+			{
+				SegmentInfo segmentInfo = (SegmentInfo) segmentInfos[j];
+				current[segmentInfo.name] = segmentInfo;
+			}
+			
+			// Then go through all files in the Directory that are
+			// Lucene index files, and add to deletable if they are
+			// not referenced by the current segments info:
+			
+			System.String segmentsInfosFileName = segmentInfos.GetCurrentSegmentFileName();
+			IndexFileNameFilter filter = IndexFileNameFilter.GetFilter();
+			
+			System.String[] files = directory.List();
+			
+			for (int i = 0; i < files.Length; i++)
+			{
+				
+				if (filter.Accept(null, files[i]) && !files[i].Equals(segmentsInfosFileName) && !files[i].Equals(IndexFileNames.SEGMENTS_GEN))
+				{
+					
+					System.String segmentName;
+					System.String extension;
+					
+					// First remove any extension:
+					int loc = files[i].IndexOf((System.Char) '.');
+					if (loc != - 1)
+					{
+						extension = files[i].Substring(1 + loc);
+						segmentName = files[i].Substring(0, (loc) - (0));
+					}
+					else
+					{
+						extension = null;
+						segmentName = files[i];
+					}
+					
+					// Then, remove any generation count:
+					loc = segmentName.IndexOf((System.Char) '_', 1);
+					if (loc != - 1)
+					{
+						segmentName = segmentName.Substring(0, (loc) - (0));
+					}
+					
+					// Delete this file if it's not a "current" segment,
+					// or, it is a single index file but there is now a
+					// corresponding compound file:
+					bool doDelete = false;
+					
+					if (!current.ContainsKey(segmentName))
+					{
+						// Delete if segment is not referenced:
+						doDelete = true;
+					}
+					else
+					{
+						// OK, segment is referenced, but file may still
+						// be orphan'd:
+						SegmentInfo info = (SegmentInfo) current[segmentName];
+						
+						if (filter.IsCFSFile(files[i]) && info.GetUseCompoundFile())
+						{
+							// This file is in fact stored in a CFS file for
+							// this segment:
+							doDelete = true;
+						}
+						else
+						{
+                            Pattern p = new System.Text.RegularExpressions.Regex("s\\d+");
+							
+							if ("del".Equals(extension))
+							{
+								// This is a _segmentName_N.del file:
+								if (!files[i].Equals(info.GetDelFileName()))
+								{
+									// If this is a seperate .del file, but it
+									// doesn't match the current del filename for
+									// this segment, then delete it:
+									doDelete = true;
+								}
+							}
+							else if (extension != null && extension.StartsWith("s") && p.Match(extension).Success)
+							{
+
+								int field = System.Int32.Parse(extension.Substring(1));
+								// This is a _segmentName_N.sX file:
+								if (!files[i].Equals(info.GetNormFileName(field)))
+								{
+									// This is an orphan'd separate norms file:
+									doDelete = true;
+								}
+							}
+							else if ("cfs".Equals(extension) && !info.GetUseCompoundFile())
+							{
+								// This is a partially written
+								// _segmentName.cfs:
+								doDelete = true;
+							}
+						}
+					}
+					
+					if (doDelete)
+					{
+						AddDeletableFile(files[i]);
+						if (infoStream != null)
+						{
+							infoStream.WriteLine("IndexFileDeleter: file \"" + files[i] + "\" is unreferenced in index and will be deleted on next commit");
+						}
+					}
+				}
+			}
+		}
+		
+		/*
+		* 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.
+		*/
+		
+		internal void  DeleteSegments(System.Collections.ArrayList segments)
+		{
+			
+			DeleteFiles(); // try to delete files that we couldn't before
+			
+			for (int i = 0; i < segments.Count; i++)
+			{
+				SegmentReader reader = (SegmentReader) segments[i];
+				if (reader.Directory() == this.directory)
+					DeleteFiles(reader.Files());
+				// try to delete our files
+				else
+					DeleteFiles(reader.Files(), reader.Directory()); // delete other files
+			}
+		}
+		
+		/// <summary> Delete these segments, as long as they are not listed
+		/// in protectedSegments.  If they are, then, instead, add
+		/// them to the pending set.
+		/// </summary>
+		
+		internal void  DeleteSegments(System.Collections.ArrayList segments, System.Collections.Hashtable protectedSegments)
+		{
+			
+			DeleteFiles(); // try to delete files that we couldn't before
+			
+			for (int i = 0; i < segments.Count; i++)
+			{
+				SegmentReader reader = (SegmentReader) segments[i];
+				if (reader.Directory() == this.directory)
+				{
+					if (protectedSegments.Contains(reader.GetSegmentName()))
+					{
+						AddPendingFiles(reader.Files()); // record these for deletion on commit
+					}
+					else
+					{
+						DeleteFiles(reader.Files()); // try to delete our files
+					}
+				}
+				else
+				{
+					DeleteFiles(reader.Files(), reader.Directory()); // delete other files
+				}
+			}
+		}
+		
+		internal void  DeleteFiles(System.Collections.ArrayList files, Directory directory)
+		{
+			for (int i = 0; i < files.Count; i++)
+				directory.DeleteFile((System.String) files[i]);
+		}
+		
+		internal void  DeleteFiles(System.Collections.ArrayList files)
+		{
+			DeleteFiles(); // try to delete files that we couldn't before
+			for (int i = 0; i < files.Count; i++)
+			{
+				DeleteFile((System.String) files[i]);
+			}
+		}
+		
+		internal void  DeleteFile(System.String file)
+		{
+			try
+			{
+				directory.DeleteFile(file); // try to delete each file
+			}
+			catch (System.IO.IOException e)
+			{
+				// if delete fails
+				if (directory.FileExists(file))
+				{
+					if (infoStream != null)
+					{
+						infoStream.WriteLine("IndexFileDeleter: unable to remove file \"" + file + "\": " + e.ToString() + "; Will re-try later.");
+					}
+					AddDeletableFile(file); // add to deletable
+				}
+			}
+		}
+		
+		internal void  ClearPendingFiles()
+		{
+			pending = null;
+		}
+		
+		/*
+		Record that the files for these segments should be
+		deleted, once the pending deletes are committed.
+		*/
+		internal void  AddPendingSegments(System.Collections.ArrayList segments)
+		{
+			for (int i = 0; i < segments.Count; i++)
+			{
+				SegmentReader reader = (SegmentReader) segments[i];
+				if (reader.Directory() == this.directory)
+				{
+					AddPendingFiles(reader.Files());
+				}
+			}
+		}
+		
+		/*
+		Record list of files for deletion, but do not delete
+		them until commitPendingFiles is called.
+		*/
+		internal void  AddPendingFiles(System.Collections.ArrayList files)
+		{
+			for (int i = 0; i < files.Count; i++)
+			{
+				AddPendingFile((System.String) files[i]);
+			}
+		}
+		
+		/*
+		Record a file for deletion, but do not delete it until
+		commitPendingFiles is called.
+		*/
+		internal void  AddPendingFile(System.String fileName)
+		{
+			if (pending == null)
+			{
+				pending = new System.Collections.Hashtable();
+			}
+			pending.Add(fileName, fileName);
+		}
+		
+		internal void  CommitPendingFiles()
+		{
+			if (pending != null)
+			{
+				if (deletable == null)
+				{
+					deletable = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
+				}
+				System.Collections.IEnumerator it = pending.GetEnumerator();
+				while (it.MoveNext())
+				{
+					deletable.Add(it.Current);
+				}
+				pending = null;
+				DeleteFiles();
+			}
+		}
+		
+		internal void  AddDeletableFile(System.String fileName)
+		{
+			if (deletable == null)
+			{
+				deletable = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
+			}
+			deletable.Add(fileName);
+		}
+		
+		internal void  DeleteFiles()
+		{
+			if (deletable != null)
+			{
+				System.Collections.ArrayList oldDeletable = deletable;
+				deletable = null;
+				DeleteFiles(oldDeletable); // try to delete deletable
+			}
+		}
+	}
+}
\ No newline at end of file

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/IndexFileNameFilter.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/IndexFileNameFilter.cs?view=diff&rev=534192&r1=534191&r2=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/IndexFileNameFilter.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/IndexFileNameFilter.cs Tue May  1 11:45:26 2007
@@ -17,6 +17,8 @@
 
 using System;
 
+using Pattern = System.Text.RegularExpressions.Regex;
+
 namespace Lucene.Net.Index
 {
 	
@@ -30,23 +32,76 @@
 	public class IndexFileNameFilter // : FilenameFilter {{Aroush-1.9}}
 	{
 		
+		internal static IndexFileNameFilter singleton = new IndexFileNameFilter();
+		private System.Collections.Hashtable extensions;
+		
+		public IndexFileNameFilter()
+		{
+			extensions = new System.Collections.Hashtable();
+			for (int i = 0; i < IndexFileNames.INDEX_EXTENSIONS.Length; i++)
+			{
+				extensions.Add(IndexFileNames.INDEX_EXTENSIONS[i], IndexFileNames.INDEX_EXTENSIONS[i]);
+			}
+		}
+		
 		/* (non-Javadoc)
 		* @see java.io.FilenameFilter#accept(java.io.File, java.lang.String)
 		*/
 		public virtual bool Accept(System.IO.FileInfo dir, System.String name)
 		{
-			for (int i = 0; i < IndexFileNames.INDEX_EXTENSIONS.Length; i++)
+			int i = name.LastIndexOf((System.Char) '.');
+			if (i != - 1)
+			{
+				System.String extension = name.Substring(1 + i);
+				if (extensions.Contains(extension))
+				{
+					return true;
+				}
+				else if (extension.StartsWith("f") && (new System.Text.RegularExpressions.Regex("f\\d+")).Match(extension).Success)
+				{
+					return true;
+				}
+				else if (extension.StartsWith("s") && (new System.Text.RegularExpressions.Regex("s\\d+")).Match(extension).Success)
+				{
+					return true;
+				}
+			}
+			else
 			{
-				if (name.EndsWith("." + IndexFileNames.INDEX_EXTENSIONS[i]))
+				if (name.Equals(IndexFileNames.DELETABLE))
+					return true;
+				else if (name.StartsWith(IndexFileNames.SEGMENTS))
 					return true;
 			}
-			if (name.Equals(IndexFileNames.DELETABLE))
-				return true;
-			else if (name.Equals(IndexFileNames.SEGMENTS))
-				return true;
-			else if (true) // else if (name.Matches(".+\\.f\\d+")) // {{Aroush-1.9}}
-				return true;
 			return false;
+		}
+		
+		/// <summary> Returns true if this is a file that would be contained
+		/// in a CFS file.  This function should only be called on
+		/// files that pass the above "accept" (ie, are already
+		/// known to be a Lucene index file).
+		/// </summary>
+		public virtual bool IsCFSFile(System.String name)
+		{
+			int i = name.LastIndexOf((System.Char) '.');
+			if (i != - 1)
+			{
+				System.String extension = name.Substring(1 + i);
+				if (extensions.Contains(extension) && !extension.Equals("del") && !extension.Equals("gen") && !extension.Equals("cfs"))
+				{
+					return true;
+				}
+				if (extension.StartsWith("f") && (new System.Text.RegularExpressions.Regex("f\\d+")).Match(extension).Success)
+				{
+					return true;
+				}
+			}
+			return false;
+		}
+		
+		public static IndexFileNameFilter GetFilter()
+		{
+			return singleton;
 		}
 	}
 }

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/IndexFileNames.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/IndexFileNames.cs?view=diff&rev=534192&r1=534191&r2=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/IndexFileNames.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/IndexFileNames.cs Tue May  1 11:45:26 2007
@@ -33,20 +33,58 @@
 		/// <summary>Name of the index segment file </summary>
 		internal const System.String SEGMENTS = "segments";
 		
-		/// <summary>Name of the index deletable file </summary>
+		/// <summary>Name of the generation reference file name </summary>
+		internal const System.String SEGMENTS_GEN = "segments.gen";
+		
+		/// <summary>Name of the index deletable file (only used in
+		/// pre-lockless indices) 
+		/// </summary>
 		internal const System.String DELETABLE = "deletable";
 		
-		/// <summary> This array contains all filename extensions used by Lucene's index files, with
-		/// one exception, namely the extension made up from <code>.f</code> + a number.
-		/// Also note that two of Lucene's files (<code>deletable</code> and
-		/// <code>segments</code>) don't have any filename extension.
+		/// <summary>Extension of norms file </summary>
+		internal const System.String NORMS_EXTENSION = "nrm";
+		
+		/// <summary> This array contains all filename extensions used by
+		/// Lucene's index files, with two exceptions, namely the
+		/// extension made up from <code>.f</code> + a number and
+		/// from <code>.s</code> + a number.  Also note that
+		/// Lucene's <code>segments_N</code> files do not have any
+		/// filename extension.
 		/// </summary>
-		internal static readonly System.String[] INDEX_EXTENSIONS = new System.String[]{"cfs", "fnm", "fdx", "fdt", "tii", "tis", "frq", "prx", "del", "tvx", "tvd", "tvf", "tvp"};
+		internal static readonly System.String[] INDEX_EXTENSIONS = new System.String[]{"cfs", "fnm", "fdx", "fdt", "tii", "tis", "frq", "prx", "del", "tvx", "tvd", "tvf", "gen", "nrm"};
 		
 		/// <summary>File extensions of old-style index files </summary>
 		internal static readonly System.String[] COMPOUND_EXTENSIONS = new System.String[]{"fnm", "frq", "prx", "fdx", "fdt", "tii", "tis"};
 		
 		/// <summary>File extensions for term vector support </summary>
 		internal static readonly System.String[] VECTOR_EXTENSIONS = new System.String[]{"tvx", "tvd", "tvf"};
+		
+		/// <summary> Computes the full file name from base, extension and
+		/// generation.  If the generation is -1, the file name is
+		/// null.  If it's 0, the file name is <base><extension>.
+		/// If it's > 0, the file name is <base>_<generation><extension>.
+		/// 
+		/// </summary>
+		/// <param name="base">-- main part of the file name
+		/// </param>
+		/// <param name="extension">-- extension of the filename (including .)
+		/// </param>
+		/// <param name="gen">-- generation
+		/// </param>
+		public static System.String FileNameFromGeneration(System.String base_Renamed, System.String extension, long gen)
+		{
+			if (gen == - 1)
+			{
+				return null;
+			}
+			else if (gen == 0)
+			{
+				return base_Renamed + extension;
+			}
+			else
+			{
+				return base_Renamed + "_" + System.Convert.ToString(gen, 16) + extension;
+			}
+		}
 	}
 }

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/IndexModifier.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Index/IndexModifier.cs?view=diff&rev=534192&r1=534191&r2=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/IndexModifier.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Index/IndexModifier.cs Tue May  1 11:45:26 2007
@@ -24,7 +24,12 @@
 namespace Lucene.Net.Index
 {
 	
-	/// <summary> A class to modify an index, i.e. to delete and add documents. This
+	/// <summary> <p>[Note that as of <b>2.1</b>, all but one of the
+	/// methods in this class are available via {@link
+	/// IndexWriter}.  The one method that is not available is
+	/// {@link #DeleteDocument(int)}.]</p>
+	/// 
+	/// A class to modify an index, i.e. to delete and add documents. This
 	/// class hides {@link IndexReader} and {@link IndexWriter} so that you
 	/// do not need to care about implementation details such as that adding
 	/// documents is done via IndexWriter and deletion is done via IndexReader.
@@ -133,7 +138,7 @@
 		public IndexModifier(System.String dirName, Analyzer analyzer, bool create)
 		{
 			InitBlock();
-			Directory dir = FSDirectory.GetDirectory(dirName, create);
+			Directory dir = FSDirectory.GetDirectory(dirName);
 			Init(dir, analyzer, create);
 		}
 		
@@ -150,7 +155,7 @@
 		public IndexModifier(System.IO.FileInfo file, Analyzer analyzer, bool create)
 		{
 			InitBlock();
-			Directory dir = FSDirectory.GetDirectory(file, create);
+			Directory dir = FSDirectory.GetDirectory(file);
 			Init(dir, analyzer, create);
 		}
 		
@@ -239,7 +244,7 @@
 		/// {@link #SetMaxFieldLength(int)} terms for a given field, the remainder are
 		/// discarded.
 		/// </summary>
-		/// <seealso cref="IndexWriter.AddDocument(Document, Analyzer)">
+		/// <seealso cref="Analyzer)">
 		/// </seealso>
 		/// <throws>  IllegalStateException if the index is closed </throws>
 		public virtual void  AddDocument(Document doc, Analyzer docAnalyzer)
@@ -259,7 +264,7 @@
 		/// {@link #SetMaxFieldLength(int)} terms for a given field, the remainder are
 		/// discarded.
 		/// </summary>
-		/// <seealso cref="IndexWriter.AddDocument(Document)">
+		/// <seealso cref="IndexWriter#AddDocument(Document)">
 		/// </seealso>
 		/// <throws>  IllegalStateException if the index is closed </throws>
 		public virtual void  AddDocument(Document doc)
@@ -275,7 +280,7 @@
 		/// </summary>
 		/// <returns> the number of documents deleted
 		/// </returns>
-		/// <seealso cref="IndexReader.DeleteDocuments(Term)">
+		/// <seealso cref="IndexReader#DeleteDocuments(Term)">
 		/// </seealso>
 		/// <throws>  IllegalStateException if the index is closed </throws>
 		public virtual int DeleteDocuments(Term term)
@@ -289,7 +294,7 @@
 		}
 		
 		/// <summary> Deletes the document numbered <code>docNum</code>.</summary>
-		/// <seealso cref="IndexReader.DeleteDocument(int)">
+		/// <seealso cref="IndexReader#DeleteDocument(int)">
 		/// </seealso>
 		/// <throws>  IllegalStateException if the index is closed </throws>
 		public virtual void  DeleteDocument(int docNum)
@@ -303,10 +308,10 @@
 		}
 		
 		
-        /// <summary> Returns the number of documents currently in this index.</summary>
-		/// <seealso cref="IndexWriter.DocCount()">
+		/// <summary> Returns the number of documents currently in this index.</summary>
+		/// <seealso cref="IndexWriter#DocCount()">
 		/// </seealso>
-		/// <seealso cref="IndexReader.NumDocs()">
+		/// <seealso cref="IndexReader#NumDocs()">
 		/// </seealso>
 		/// <throws>  IllegalStateException if the index is closed </throws>
 		public virtual int DocCount()
@@ -328,7 +333,7 @@
 		/// <summary> Merges all segments together into a single segment, optimizing an index
 		/// for search.
 		/// </summary>
-		/// <seealso cref="IndexWriter.Optimize()">
+		/// <seealso cref="IndexWriter#Optimize()">
 		/// </seealso>
 		/// <throws>  IllegalStateException if the index is closed </throws>
 		public virtual void  Optimize()
@@ -345,7 +350,7 @@
 		/// {@link #GetMaxFieldLength()} is reached will be printed to this.
 		/// <p>Example: <tt>index.setInfoStream(System.err);</tt>
 		/// </summary>
-		/// <seealso cref="IndexWriter.SetInfoStream(PrintStream)">
+		/// <seealso cref="IndexWriter#SetInfoStream(PrintStream)">
 		/// </seealso>
 		/// <throws>  IllegalStateException if the index is closed </throws>
 		public virtual void  SetInfoStream(System.IO.StreamWriter infoStream)
@@ -362,7 +367,7 @@
 		}
 		
 		/// <throws>  IOException </throws>
-		/// <seealso cref="IndexModifier.SetInfoStream(PrintStream)">
+		/// <seealso cref="IndexModifier#SetInfoStream(PrintStream)">
 		/// </seealso>
 		public virtual System.IO.TextWriter GetInfoStream()
 		{
@@ -378,7 +383,7 @@
 		/// 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>
-		/// <seealso cref="IndexWriter.SetUseCompoundFile(boolean)">
+		/// <seealso cref="IndexWriter#SetUseCompoundFile(boolean)">
 		/// </seealso>
 		/// <throws>  IllegalStateException if the index is closed </throws>
 		public virtual void  SetUseCompoundFile(bool useCompoundFile)
@@ -395,7 +400,7 @@
 		}
 		
 		/// <throws>  IOException </throws>
-		/// <seealso cref="IndexModifier.SetUseCompoundFile(boolean)">
+		/// <seealso cref="IndexModifier#SetUseCompoundFile(boolean)">
 		/// </seealso>
 		public virtual bool GetUseCompoundFile()
 		{
@@ -418,7 +423,7 @@
 		/// 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>
-		/// <seealso cref="IndexWriter.SetMaxFieldLength(int)">
+		/// <seealso cref="IndexWriter#SetMaxFieldLength(int)">
 		/// </seealso>
 		/// <throws>  IllegalStateException if the index is closed </throws>
 		public virtual void  SetMaxFieldLength(int maxFieldLength)
@@ -435,7 +440,7 @@
 		}
 		
 		/// <throws>  IOException </throws>
-		/// <seealso cref="IndexModifier.SetMaxFieldLength(int)">
+		/// <seealso cref="IndexModifier#SetMaxFieldLength(int)">
 		/// </seealso>
 		public virtual int GetMaxFieldLength()
 		{
@@ -447,20 +452,19 @@
 			}
 		}
 		
-		/// <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> 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>
-		/// <seealso cref="IndexWriter.SetMaxBufferedDocs(int)">
+		/// <seealso cref="IndexWriter#SetMaxBufferedDocs(int)">
 		/// </seealso>
 		/// <throws>  IllegalStateException if the index is closed </throws>
+		/// <throws>  IllegalArgumentException if maxBufferedDocs is smaller than 2 </throws>
 		public virtual void  SetMaxBufferedDocs(int maxBufferedDocs)
 		{
 			lock (directory)
@@ -475,7 +479,7 @@
 		}
 		
 		/// <throws>  IOException </throws>
-		/// <seealso cref="IndexModifier.SetMaxBufferedDocs(int)">
+		/// <seealso cref="IndexModifier#SetMaxBufferedDocs(int)">
 		/// </seealso>
 		public virtual int GetMaxBufferedDocs()
 		{
@@ -497,7 +501,7 @@
 		/// <p>This must never be less than 2.  The default value is 10.
 		/// 
 		/// </summary>
-		/// <seealso cref="IndexWriter.SetMergeFactor(int)">
+		/// <seealso cref="IndexWriter#SetMergeFactor(int)">
 		/// </seealso>
 		/// <throws>  IllegalStateException if the index is closed </throws>
 		public virtual void  SetMergeFactor(int mergeFactor)
@@ -514,7 +518,7 @@
 		}
 		
 		/// <throws>  IOException </throws>
-		/// <seealso cref="IndexModifier.SetMergeFactor(int)">
+		/// <seealso cref="IndexModifier#SetMergeFactor(int)">
 		/// </seealso>
 		public virtual int GetMergeFactor()
 		{
@@ -562,8 +566,8 @@
 		// create an index in /tmp/index, overwriting an existing one:
 		IndexModifier indexModifier = new IndexModifier("/tmp/index", analyzer, true);
 		Document doc = new Document();
-		doc.add(new Field("id", "1", Field.Store.YES, Field.Index.UN_TOKENIZED));
-		doc.add(new Field("body", "a simple test", Field.Store.YES, Field.Index.TOKENIZED));
+		doc.add(new Fieldable("id", "1", Fieldable.Store.YES, Fieldable.Index.UN_TOKENIZED));
+		doc.add(new Fieldable("body", "a simple test", Fieldable.Store.YES, Fieldable.Index.TOKENIZED));
 		indexModifier.addDocument(doc);
 		int deleted = indexModifier.delete(new Term("id", "1"));
 		System.out.println("Deleted " + deleted + " document");