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 [18/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/ sr...

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/BufferedIndexOutput.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Store/BufferedIndexOutput.cs?view=diff&rev=534192&r1=534191&r2=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/BufferedIndexOutput.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/BufferedIndexOutput.cs Tue May  1 11:45:26 2007
@@ -48,51 +48,51 @@
 		/// </seealso>
 		public override void  WriteBytes(byte[] b, int length)
 		{
-            int bytesLeft = BUFFER_SIZE - bufferPosition;
-            // is there enough space in the buffer?
-            if (bytesLeft >= length)
-            {
-                // we add the data to the end of the buffer
-                Array.Copy(b, 0, buffer, bufferPosition, length);
-                bufferPosition += length;
-                // if the buffer is full, flush it
-                if (BUFFER_SIZE - bufferPosition == 0)
-                    Flush();
-            }
-            else
-            {
-                // is data larger then buffer?
-                if (length > BUFFER_SIZE)
-                {
-                    // we flush the buffer
-                    if (bufferPosition > 0)
-                        Flush();
-                    // and write data at once
-                    FlushBuffer(b, length);
-                    bufferStart += length;
-                }
-                else
-                {
-                    // we fill/flush the buffer (until the input is written)
-                    int pos = 0; // position in the input data
-                    int pieceLength;
-                    while (pos < length)
-                    {
-                        pieceLength = (length - pos < bytesLeft)?length - pos:bytesLeft;
-                        Array.Copy(b, pos, buffer, bufferPosition, pieceLength);
-                        pos += pieceLength;
-                        bufferPosition += pieceLength;
-                        // if the buffer is full, flush it
-                        bytesLeft = BUFFER_SIZE - bufferPosition;
-                        if (bytesLeft == 0)
-                        {
-                            Flush();
-                            bytesLeft = BUFFER_SIZE;
-                        }
-                    }
-                }
-            }
-        }
+			int bytesLeft = BUFFER_SIZE - bufferPosition;
+			// is there enough space in the buffer?
+			if (bytesLeft >= length)
+			{
+				// we add the data to the end of the buffer
+				Array.Copy(b, 0, buffer, bufferPosition, length);
+				bufferPosition += length;
+				// if the buffer is full, flush it
+				if (BUFFER_SIZE - bufferPosition == 0)
+					Flush();
+			}
+			else
+			{
+				// is data larger then buffer?
+				if (length > BUFFER_SIZE)
+				{
+					// we flush the buffer
+					if (bufferPosition > 0)
+						Flush();
+					// and write data at once
+					FlushBuffer(b, length);
+					bufferStart += length;
+				}
+				else
+				{
+					// we fill/flush the buffer (until the input is written)
+					int pos = 0; // position in the input data
+					int pieceLength;
+					while (pos < length)
+					{
+						pieceLength = (length - pos < bytesLeft)?length - pos:bytesLeft;
+						Array.Copy(b, pos, buffer, bufferPosition, pieceLength);
+						pos += pieceLength;
+						bufferPosition += pieceLength;
+						// if the buffer is full, flush it
+						bytesLeft = BUFFER_SIZE - bufferPosition;
+						if (bytesLeft == 0)
+						{
+							Flush();
+							bytesLeft = BUFFER_SIZE;
+						}
+					}
+				}
+			}
+		}
 		
 		/// <summary>Forces any buffered output to be written. </summary>
 		public override void  Flush()
@@ -120,7 +120,7 @@
 		/// <summary>Returns the current position in this file, where the next write will
 		/// occur.
 		/// </summary>
-		/// <seealso cref="Seek(long)">
+		/// <seealso cref="#Seek(long)">
 		/// </seealso>
 		public override long GetFilePointer()
 		{
@@ -128,7 +128,7 @@
 		}
 		
 		/// <summary>Sets current position in this file, where the next write will occur.</summary>
-		/// <seealso cref="GetFilePointer()">
+		/// <seealso cref="#GetFilePointer()">
 		/// </seealso>
 		public override void  Seek(long pos)
 		{

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/Directory.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Store/Directory.cs?view=diff&rev=534192&r1=534191&r2=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/Directory.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/Directory.cs Tue May  1 11:45:26 2007
@@ -31,11 +31,23 @@
 	/// <li> implementation of an index as a single file;
 	/// </ul>
 	/// 
+	/// Directory locking is implemented by an instance of {@link
+	/// LockFactory}, and can be changed for each Directory
+	/// instance using {@link #setLockFactory}.
+	/// 
 	/// </summary>
 	/// <author>  Doug Cutting
 	/// </author>
+	[Serializable]
 	public abstract class Directory
 	{
+		
+		/// <summary>Holds the LockFactory instance (implements locking for
+		/// this Directory instance). 
+		/// </summary>
+		[NonSerialized]
+		protected internal LockFactory lockFactory;
+		
 		/// <summary>Returns an array of strings, one for each file in the directory. </summary>
 		public abstract System.String[] List();
 		
@@ -53,8 +65,10 @@
 		
 		/// <summary>Renames an existing file in the directory.
 		/// If a file already exists with the new name, then it is replaced.
-		/// This replacement should be atomic. 
+		/// This replacement is not guaranteed to be atomic.
 		/// </summary>
+		/// <deprecated> 
+		/// </deprecated>
 		public abstract void  RenameFile(System.String from, System.String to);
 		
 		/// <summary>Returns the length of a file in the directory. </summary>
@@ -73,9 +87,118 @@
 		/// <summary>Construct a {@link Lock}.</summary>
 		/// <param name="name">the name of the lock file
 		/// </param>
-		public abstract Lock MakeLock(System.String name);
+		public virtual Lock MakeLock(System.String name)
+		{
+			return lockFactory.MakeLock(name);
+		}
+		/// <summary> Attempt to clear (forcefully unlock and remove) the
+		/// specified lock.  Only call this at a time when you are
+		/// certain this lock is no longer in use.
+		/// </summary>
+		/// <param name="lockName">name of the lock to be cleared.
+		/// </param>
+		public virtual void  ClearLock(System.String name)
+		{
+			if (lockFactory != null)
+			{
+				lockFactory.ClearLock(name);
+			}
+		}
 		
 		/// <summary>Closes the store. </summary>
 		public abstract void  Close();
+		
+		/// <summary> Set the LockFactory that this Directory instance should
+		/// use for its locking implementation.  Each * instance of
+		/// LockFactory should only be used for one directory (ie,
+		/// do not share a single instance across multiple
+		/// Directories).
+		/// 
+		/// </summary>
+		/// <param name="lockFactory">instance of {@link LockFactory}.
+		/// </param>
+		public virtual void  SetLockFactory(LockFactory lockFactory)
+		{
+			this.lockFactory = lockFactory;
+			lockFactory.SetLockPrefix(this.GetLockID());
+		}
+		
+		/// <summary> Get the LockFactory that this Directory instance is
+		/// using for its locking implementation.  Note that this
+		/// may be null for Directory implementations that provide
+		/// their own locking implementation.
+		/// </summary>
+		public virtual LockFactory GetLockFactory()
+		{
+			return this.lockFactory;
+		}
+		
+		/// <summary> Return a string identifier that uniquely differentiates
+		/// this Directory instance from other Directory instances.
+		/// This ID should be the same if two Directory instances
+		/// (even in different JVMs and/or on different machines)
+		/// are considered "the same index".  This is how locking
+		/// "scopes" to the right index.
+		/// </summary>
+		public virtual System.String GetLockID()
+		{
+			return this.ToString();
+		}
+		
+		/// <summary> Copy contents of a directory src to a directory dest.
+		/// If a file in src already exists in dest then the
+		/// one in dest will be blindly overwritten.
+		/// 
+		/// </summary>
+		/// <param name="src">source directory
+		/// </param>
+		/// <param name="dest">destination directory
+		/// </param>
+		/// <param name="closeDirSrc">if <code>true</code>, call {@link #close()} method on source directory
+		/// </param>
+		/// <throws>  IOException </throws>
+		public static void  Copy(Directory src, Directory dest, bool closeDirSrc)
+		{
+			System.String[] files = src.List();
+			byte[] buf = new byte[BufferedIndexOutput.BUFFER_SIZE];
+			for (int i = 0; i < files.Length; i++)
+			{
+				IndexOutput os = null;
+				IndexInput is_Renamed = null;
+				try
+				{
+					// create file in dest directory
+					os = dest.CreateOutput(files[i]);
+					// read current file
+					is_Renamed = src.OpenInput(files[i]);
+					// and copy to dest directory
+					long len = is_Renamed.Length();
+					long readCount = 0;
+					while (readCount < len)
+					{
+						int toRead = readCount + BufferedIndexOutput.BUFFER_SIZE > len?(int) (len - readCount):BufferedIndexOutput.BUFFER_SIZE;
+						is_Renamed.ReadBytes(buf, 0, toRead);
+						os.WriteBytes(buf, toRead);
+						readCount += toRead;
+					}
+				}
+				finally
+				{
+					// graceful cleanup
+					try
+					{
+						if (os != null)
+							os.Close();
+					}
+					finally
+					{
+						if (is_Renamed != null)
+							is_Renamed.Close();
+					}
+				}
+			}
+			if (closeDirSrc)
+				src.Close();
+		}
 	}
 }

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/FSDirectory.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Store/FSDirectory.cs?view=diff&rev=534192&r1=534191&r2=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/FSDirectory.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/FSDirectory.cs Tue May  1 11:45:26 2007
@@ -16,12 +16,25 @@
  */
 
 using System;
+
 using IndexFileNameFilter = Lucene.Net.Index.IndexFileNameFilter;
+// Used only for WRITE_LOCK_NAME in deprecated create=true case:
+using IndexWriter = Lucene.Net.Index.IndexWriter;
 
 namespace Lucene.Net.Store
 {
 	
 	/// <summary> Straightforward implementation of {@link Directory} as a directory of files.
+	/// Locking implementation is by default the {@link SimpleFSLockFactory}, but
+	/// can be changed either by passing in a {@link LockFactory} instance to
+	/// <code>getDirectory</code>, or specifying the LockFactory class by setting
+	/// <code>Lucene.Net.Store.FSDirectoryLockFactoryClass</code> Java system
+	/// property, or by calling {@link #setLockFactory} after creating
+	/// the Directory.
+	/// <p>Directories are cached, so that, for a given canonical
+	/// path, the same FSDirectory instance will always be
+	/// returned by <code>getDirectory</code>.  This permits
+	/// synchronization on directories.</p>
 	/// 
 	/// </summary>
 	/// <seealso cref="Directory">
@@ -30,128 +43,52 @@
 	/// </author>
 	public class FSDirectory : Directory
 	{
-		private class AnonymousClassLock : Lock
-		{
-			public AnonymousClassLock(System.IO.FileInfo lockFile, FSDirectory enclosingInstance)
-			{
-				InitBlock(lockFile, enclosingInstance);
-			}
-			private void  InitBlock(System.IO.FileInfo lockFile, FSDirectory enclosingInstance)
-			{
-				this.lockFile = lockFile;
-				this.enclosingInstance = enclosingInstance;
-			}
-			private System.IO.FileInfo lockFile;
-			private FSDirectory enclosingInstance;
-            override public bool IsLocked()
-            {
-                if (Lucene.Net.Store.FSDirectory.disableLocks)
-                    return false;
-                bool tmpBool;
-                if (System.IO.File.Exists(lockFile.FullName))
-                    tmpBool = true;
-                else
-                    tmpBool = System.IO.Directory.Exists(lockFile.FullName);
-                return tmpBool;
-            }
-            public FSDirectory Enclosing_Instance
-			{
-				get
-				{
-					return enclosingInstance;
-				}
-				
-			}
-			public override bool Obtain()
-			{
-				if (Lucene.Net.Store.FSDirectory.disableLocks)
-					return true;
-				
-				bool tmpBool;
-				if (System.IO.File.Exists(Enclosing_Instance.lockDir.FullName))
-					tmpBool = true;
-				else
-					tmpBool = System.IO.Directory.Exists(Enclosing_Instance.lockDir.FullName);
-				if (!tmpBool)
-				{
-                    try
-                    {
-					    System.IO.Directory.CreateDirectory(Enclosing_Instance.lockDir.FullName);
-                    }
-                    catch (Exception)
-					{
-						throw new System.IO.IOException("Cannot create lock directory: " + Enclosing_Instance.lockDir);
-					}
-				}
-				
-                try
-                {
-                    System.IO.FileStream createdFile = lockFile.Create();
-                    createdFile.Close();
-                    return true;
-                }
-                catch (Exception)
-                {
-                    return false;
-                }
-            }
-			public override void  Release()
-			{
-				if (Lucene.Net.Store.FSDirectory.disableLocks)
-					return ;
-				bool tmpBool;
-				if (System.IO.File.Exists(lockFile.FullName))
-				{
-					System.IO.File.Delete(lockFile.FullName);
-					tmpBool = true;
-				}
-				else if (System.IO.Directory.Exists(lockFile.FullName))
-				{
-					System.IO.Directory.Delete(lockFile.FullName);
-					tmpBool = true;
-				}
-				else
-					tmpBool = false;
-				bool generatedAux = tmpBool;
-			}
-			
-			public override System.String ToString()
-			{
-				return "Lock@" + lockFile;
-			}
-		}
 		
 		/// <summary>This cache of directories ensures that there is a unique Directory
 		/// instance per path, so that synchronization on the Directory can be used to
-		/// synchronize access between readers and writers.
-		/// 
-		/// This should be a WeakHashMap, so that entries can be GC'd, but that would
-		/// require Java 1.2.  Instead we use refcounts...
+		/// synchronize access between readers and writers.  We use
+		/// refcounts to ensure when the last use of an FSDirectory
+		/// instance for a given canonical path is closed, we remove the
+		/// instance from the cache.  See LUCENE-776
+		/// for some relevant discussion.
 		/// </summary>
 		private static readonly System.Collections.Hashtable DIRECTORIES = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable());
 		
 		private static bool disableLocks = false;
 		
-        /// <summary> Set whether Lucene's use of lock files is disabled. By default, 
-        /// lock files are enabled. They should only be disabled if the index
-        /// is on a read-only medium like a CD-ROM.
-        /// </summary>
-        public static void  SetDisableLocks(bool doDisableLocks)
+		// TODO: should this move up to the Directory base class?  Also: should we
+		// make a per-instance (in addition to the static "default") version?
+		
+		/// <summary> Set whether Lucene's use of lock files is disabled. By default, 
+		/// lock files are enabled. They should only be disabled if the index
+		/// is on a read-only medium like a CD-ROM.
+		/// </summary>
+		public static void  SetDisableLocks(bool doDisableLocks)
 		{
 			FSDirectory.disableLocks = doDisableLocks;
 		}
 		
-        /// <summary> Returns whether Lucene's use of lock files is disabled.</summary>
-        /// <returns> true if locks are disabled, false if locks are enabled.
-        /// </returns>
-        public static bool GetDisableLocks()
+		/// <summary> Returns whether Lucene's use of lock files is disabled.</summary>
+		/// <returns> true if locks are disabled, false if locks are enabled.
+		/// </returns>
+		public static bool GetDisableLocks()
 		{
 			return FSDirectory.disableLocks;
 		}
 		
 		/// <summary> Directory specified by <code>Lucene.Net.lockDir</code>
-		/// or <code>java.io.tmpdir</code> system property
+		/// or <code>java.io.tmpdir</code> system property.
 		/// </summary>
+		/// <deprecated> As of 2.1, <code>LOCK_DIR</code> is unused
+		/// because the write.lock is now stored by default in the
+		/// index directory.  If you really want to store locks
+		/// elsewhere you can create your own {@link
+		/// SimpleFSLockFactory} (or {@link NativeFSLockFactory},
+		/// etc.) passing in your preferred lock directory.  Then,
+		/// pass this <code>LockFactory</code> instance to one of
+		/// the <code>getDirectory</code> methods that take a
+		/// <code>lockFactory</code> (for example, {@link #GetDirectory(String, LockFactory)}).
+		/// </deprecated>
 		public static readonly System.String LOCK_DIR = SupportClass.AppSettings.Get("Lucene.Net.lockDir", System.IO.Path.GetTempPath());
 		
 		/// <summary>The default class which implements filesystem-based directories. </summary>
@@ -162,40 +99,76 @@
 		/// <summary>A buffer optionally used in renameTo method </summary>
 		private byte[] buffer = null;
 		
-		/// <summary>Returns the directory instance for the named location.
-		/// 
-		/// <p>Directories are cached, so that, for a given canonical path, the same
-		/// FSDirectory instance will always be returned.  This permits
-		/// synchronization on directories.
-		/// 
-		/// </summary>
+		/// <summary>Returns the directory instance for the named location.</summary>
 		/// <param name="path">the path to the directory.
 		/// </param>
-		/// <param name="create">if true, create, or erase any existing contents.
+		/// <returns> the FSDirectory for the named file.  
+		/// </returns>
+		public static FSDirectory GetDirectory(System.String path)
+		{
+			return GetDirectory(new System.IO.FileInfo(path), null);
+		}
+		
+		/// <summary>Returns the directory instance for the named location.</summary>
+		/// <param name="path">the path to the directory.
+		/// </param>
+		/// <param name="lockFactory">instance of {@link LockFactory} providing the
+		/// locking implementation.
 		/// </param>
 		/// <returns> the FSDirectory for the named file.  
 		/// </returns>
-		public static FSDirectory GetDirectory(System.String path, bool create)
+		public static FSDirectory GetDirectory(System.String path, LockFactory lockFactory)
 		{
-			return GetDirectory(new System.IO.FileInfo(path), create);
+			return GetDirectory(new System.IO.FileInfo(path), lockFactory);
 		}
 		
-		/// <summary>Returns the directory instance for the named location.
-		/// 
-		/// <p>Directories are cached, so that, for a given canonical path, the same
-		/// FSDirectory instance will always be returned.  This permits
-		/// synchronization on directories.
-		/// 
-		/// </summary>
+		/// <summary>Returns the directory instance for the named location.</summary>
 		/// <param name="file">the path to the directory.
 		/// </param>
-		/// <param name="create">if true, create, or erase any existing contents.
+		/// <returns> the FSDirectory for the named file.  
+		/// </returns>
+		public static FSDirectory GetDirectory(System.IO.FileInfo file)
+		{
+			return GetDirectory(file, null);
+		}
+		
+		/// <summary>Returns the directory instance for the named location.</summary>
+		/// <param name="file">the path to the directory.
+		/// </param>
+		/// <param name="lockFactory">instance of {@link LockFactory} providing the
+		/// locking implementation.
 		/// </param>
 		/// <returns> the FSDirectory for the named file.  
 		/// </returns>
-		public static FSDirectory GetDirectory(System.IO.FileInfo file, bool create)
+		public static FSDirectory GetDirectory(System.IO.FileInfo file, LockFactory lockFactory)
 		{
 			file = new System.IO.FileInfo(file.FullName);
+			
+			bool tmpBool;
+			if (System.IO.File.Exists(file.FullName))
+				tmpBool = true;
+			else
+				tmpBool = System.IO.Directory.Exists(file.FullName);
+			if (tmpBool && !System.IO.Directory.Exists(file.FullName))
+				throw new System.IO.IOException(file + " not a directory");
+			
+			bool tmpBool2;
+			if (System.IO.File.Exists(file.FullName))
+				tmpBool2 = true;
+			else
+				tmpBool2 = System.IO.Directory.Exists(file.FullName);
+			if (!tmpBool2)
+			{
+                try
+                {
+                    System.IO.Directory.CreateDirectory(file.FullName);
+                }
+                catch
+                {
+                    throw new System.IO.IOException("Cannot create directory: " + file);
+                }
+			}
+			
 			FSDirectory dir;
 			lock (DIRECTORIES.SyncRoot)
 			{
@@ -208,14 +181,19 @@
 					}
 					catch (System.Exception e)
 					{
-						throw new System.SystemException("cannot load FSDirectory class: " + e.ToString());
+						throw new System.SystemException("cannot load FSDirectory class: " + e.ToString(), e);
 					}
-					dir.Init(file, create);
+					dir.Init(file, lockFactory);
 					DIRECTORIES[file] = dir;
 				}
-				else if (create)
+				else
 				{
-					dir.Create();
+					// Catch the case where a Directory is pulled from the cache, but has a
+					// different LockFactory instance.
+					if (lockFactory != null && lockFactory != dir.GetLockFactory())
+					{
+						throw new System.IO.IOException("Directory was previously created with a different LockFactory instance; please pass null as the lockFactory instance and use setLockFactory to change it");
+					}
 				}
 			}
 			lock (dir)
@@ -225,93 +203,65 @@
 			return dir;
 		}
 		
-		private System.IO.FileInfo directory = null;
-		private int refCount;
-		private System.IO.FileInfo lockDir;
 		
-		public FSDirectory()
+		/// <summary>Returns the directory instance for the named location.
+		/// 
+		/// </summary>
+		/// <deprecated> Use IndexWriter's create flag, instead, to
+		/// create a new index.
+		/// 
+		/// </deprecated>
+		/// <param name="path">the path to the directory.
+		/// </param>
+		/// <param name="create">if true, create, or erase any existing contents.
+		/// </param>
+		/// <returns> the FSDirectory for the named file.  
+		/// </returns>
+		public static FSDirectory GetDirectory(System.String path, bool create)
 		{
+			return GetDirectory(new System.IO.FileInfo(path), create);
 		}
 		
-		// permit subclassing
-		
-		private void  Init(System.IO.FileInfo path, bool create)
+		/// <summary>Returns the directory instance for the named location.
+		/// 
+		/// </summary>
+		/// <deprecated> Use IndexWriter's create flag, instead, to
+		/// create a new index.
+		/// 
+		/// </deprecated>
+		/// <param name="file">the path to the directory.
+		/// </param>
+		/// <param name="create">if true, create, or erase any existing contents.
+		/// </param>
+		/// <returns> the FSDirectory for the named file.  
+		/// </returns>
+		public static FSDirectory GetDirectory(System.IO.FileInfo file, bool create)
 		{
-			directory = path;
+			FSDirectory dir = GetDirectory(file, null);
 			
-			if (LOCK_DIR == null)
-			{
-				lockDir = directory;
-			}
-			else
-			{
-				lockDir = new System.IO.FileInfo(LOCK_DIR);
-			}
-			// Ensure that lockDir exists and is a directory.
-			bool tmpBool;
-			if (System.IO.File.Exists(lockDir.FullName))
-				tmpBool = true;
-			else
-				tmpBool = System.IO.Directory.Exists(lockDir.FullName);
-			if (!tmpBool)
-			{
-                try
-                {
-                    System.IO.Directory.CreateDirectory(lockDir.FullName);
-                }
-                catch (Exception)
-                {
-                    throw new System.IO.IOException("Cannot create directory: " + lockDir);
-                }
-			}
-			else if (!System.IO.Directory.Exists(lockDir.FullName))
-			{
-				throw new System.IO.IOException("Found regular file where directory expected: " + lockDir);
-			}
+			// This is now deprecated (creation should only be done
+			// by IndexWriter):
 			if (create)
 			{
-				Create();
+				dir.Create();
 			}
 			
-			if (!System.IO.Directory.Exists(directory.FullName))
-				throw new System.IO.IOException(path + " not a directory");
+			return dir;
 		}
 		
 		private void  Create()
 		{
-			lock (this)
+			bool tmpBool;
+			if (System.IO.File.Exists(directory.FullName))
+				tmpBool = true;
+			else
+				tmpBool = System.IO.Directory.Exists(directory.FullName);
+			if (tmpBool)
 			{
-				bool tmpBool;
-				if (System.IO.File.Exists(directory.FullName))
-					tmpBool = true;
-				else
-					tmpBool = System.IO.Directory.Exists(directory.FullName);
-				if (!tmpBool)
-				{
-                    try
-                    {
-                        System.IO.Directory.CreateDirectory(directory.FullName);
-                    }
-                    catch (Exception)
-                    {
-                        throw new System.IO.IOException("Cannot create directory: " + directory);
-                    }
-				}
-				
-                try
-                {
-                    System.IO.Directory.Exists(directory.FullName);
-                }
-                catch (Exception)
-                {
-                    throw new System.IO.IOException(directory + " not a directory");
-                }
-				
-                System.String[] files = System.IO.Directory.GetFileSystemEntries(directory.FullName); // clear old files    // {{Aroush-1.9}} we want the line below, not this one; how do we make the line below work in C#?!
-                //// System.String[] files = System.IO.Directory.GetFileSystemEntries(new IndexFileNameFilter()); // clear old files 
-                //// if (files == null)
-                ////    throw new System.IO.IOException("Cannot read directory " + directory.FullName);
-                for (int i = 0; i < files.Length; i++)
+                System.String[] files = System.IO.Directory.GetFileSystemEntries(directory.FullName);   // directory.list(IndexFileNameFilter.GetFilter()); // clear old files  // {{Aroush-2.1}} we don't want all files in the directory but a filtered list
+				if (files == null)
+					throw new System.IO.IOException("Cannot read directory " + directory.FullName);
+				for (int i = 0; i < files.Length; i++)
 				{
 					System.IO.FileInfo file = new System.IO.FileInfo(System.IO.Path.Combine(directory.FullName, files[i]));
 					bool tmpBool2;
@@ -328,41 +278,105 @@
 					else
 						tmpBool2 = false;
 					if (!tmpBool2)
-						throw new System.IO.IOException("Cannot delete " + files[i]);
+						throw new System.IO.IOException("Cannot delete " + file);
 				}
+			}
+			lockFactory.ClearLock(IndexWriter.WRITE_LOCK_NAME);
+		}
+		
+		private System.IO.FileInfo directory = null;
+		private int refCount;
+		
+		public FSDirectory()
+		{
+		}
+		
+		// permit subclassing
+		
+		private void  Init(System.IO.FileInfo path, LockFactory lockFactory)
+		{
+			
+			// Set up lockFactory with cascaded defaults: if an instance was passed in,
+			// use that; else if locks are disabled, use NoLockFactory; else if the
+			// system property Lucene.Net.Store.FSDirectoryLockFactoryClass is set,
+			// instantiate that; else, use SimpleFSLockFactory:
+			
+			directory = path;
+			
+			bool doClearLockID = false;
+			
+			if (lockFactory == null)
+			{
 				
-				System.String lockPrefix = GetLockPrefix().ToString(); // clear old locks
-				files = System.IO.Directory.GetFileSystemEntries(lockDir.FullName);
-				if (files == null)
-					throw new System.IO.IOException("Cannot read lock directory " + lockDir.FullName);
-				for (int i = 0; i < files.Length; i++)
+				if (disableLocks)
+				{
+					// Locks are disabled:
+					lockFactory = NoLockFactory.GetNoLockFactory();
+				}
+				else
 				{
-					if (!files[i].StartsWith(lockPrefix))
-						continue;
-					System.IO.FileInfo lockFile = new System.IO.FileInfo(System.IO.Path.Combine(lockDir.FullName, files[i]));
-					bool tmpBool3;
-					if (System.IO.File.Exists(lockFile.FullName))
+					System.String lockClassName = SupportClass.AppSettings.Get("Lucene.Net.Store.FSDirectoryLockFactoryClass", "");
+					
+					if (lockClassName != null && !lockClassName.Equals(""))
 					{
-						System.IO.File.Delete(lockFile.FullName);
-						tmpBool3 = true;
-					}
-					else if (System.IO.Directory.Exists(lockFile.FullName))
+						System.Type c;
+						
+						try
+						{
+							c = System.Type.GetType(lockClassName);
+						}
+						catch (System.Exception)
+						{
+							throw new System.IO.IOException("unable to find LockClass " + lockClassName);
+						}
+						
+						try
+						{
+							lockFactory = (LockFactory) System.Activator.CreateInstance(c);
+						}
+						catch (System.UnauthorizedAccessException e)
+						{
+							throw new System.IO.IOException("IllegalAccessException when instantiating LockClass " + lockClassName);
+						}
+						catch (System.InvalidCastException)
+						{
+							throw new System.IO.IOException("unable to cast LockClass " + lockClassName + " instance to a LockFactory");
+						}
+                        catch (System.Exception)
+                        {
+                            throw new System.IO.IOException("InstantiationException when instantiating LockClass " + lockClassName);
+                        }
+                    }
+					else
 					{
-						System.IO.Directory.Delete(lockFile.FullName);
-						tmpBool3 = true;
+						// Our default lock is SimpleFSLockFactory;
+						// default lockDir is our index directory:
+						lockFactory = new SimpleFSLockFactory(path);
+						doClearLockID = true;
 					}
-					else
-						tmpBool3 = false;
-					if (!tmpBool3)
-						throw new System.IO.IOException("Cannot delete " + files[i]);
 				}
 			}
+			
+			SetLockFactory(lockFactory);
+			
+			if (doClearLockID)
+			{
+				// Clear the prefix because write.lock will be
+				// stored in our directory:
+				lockFactory.SetLockPrefix(null);
+			}
 		}
 		
-		/// <summary>Returns an array of strings, one for each file in the directory. </summary>
+		/// <summary>Returns an array of strings, one for each Lucene index file in the directory. </summary>
 		public override System.String[] List()
 		{
-			return System.IO.Directory.GetFileSystemEntries(directory.FullName);
+            System.String[] files = System.IO.Directory.GetFileSystemEntries(directory.FullName);   // IndexFileNameFilter.GetFilter());   // {{Aroush-2.1}} we want to limit the files to the list
+            for (int i = 0; i < files.Length; i++)
+            {
+                System.IO.FileInfo fi = new System.IO.FileInfo(files[i]);
+                files[i] = fi.Name;
+            }
+			return files;
 		}
 		
 		/// <summary>Returns true iff a file with the given name exists. </summary>
@@ -395,7 +409,7 @@
 		public override void  TouchFile(System.String name)
 		{
 			System.IO.FileInfo file = new System.IO.FileInfo(System.IO.Path.Combine(directory.FullName, name));
-            file.LastWriteTime = System.DateTime.Now;
+			file.LastWriteTime = System.DateTime.Now;
 		}
 		
 		/// <summary>Returns the length in bytes of a file in the directory. </summary>
@@ -426,7 +440,11 @@
 				throw new System.IO.IOException("Cannot delete " + file);
 		}
 		
-		/// <summary>Renames an existing file in the directory. </summary>
+		/// <summary>Renames an existing file in the directory. 
+		/// Warning: This is not atomic.
+		/// </summary>
+		/// <deprecated> 
+		/// </deprecated>
 		public override void  RenameFile(System.String from, System.String to)
 		{
 			lock (this)
@@ -469,7 +487,7 @@
                 {
                     old.MoveTo(nu.FullName);
                 }
-                catch (System.Exception)
+                catch
 				{
 					System.IO.Stream in_Renamed = null;
 					System.IO.Stream out_Renamed = null;
@@ -484,10 +502,10 @@
 						{
 							buffer = new byte[1024];
 						}
-						int len; 
-						while ((len = in_Renamed.Read(buffer, 0, buffer.Length)) > 0) 
-						{ 
-							out_Renamed.Write(buffer, 0, len); 
+						int len;
+						while ((len = in_Renamed.Read(buffer, 0, buffer.Length)) >= 0)
+						{
+							out_Renamed.Write(buffer, 0, len);
 						}
 						
 						// delete the old file.
@@ -508,31 +526,37 @@
 					}
 					catch (System.IO.IOException ioe)
 					{
-                        System.IO.IOException newExc = new System.IO.IOException("Cannot rename " + old + " to " + nu, ioe);
-                        throw newExc;
-                    }
+						System.IO.IOException newExc = new System.IO.IOException("Cannot rename " + old + " to " + nu, ioe);
+						throw newExc;
+					}
 					finally
 					{
-						if (in_Renamed != null)
+						try
 						{
-							try
-							{
-								in_Renamed.Close();
-							}
-							catch (System.IO.IOException e)
+							if (in_Renamed != null)
 							{
-								throw new System.SystemException("Cannot close input stream: " + e.ToString());
+								try
+								{
+									in_Renamed.Close();
+								}
+								catch (System.IO.IOException e)
+								{
+									throw new System.SystemException("Cannot close input stream: " + e.ToString(), e);
+								}
 							}
 						}
-						if (out_Renamed != null)
+						finally
 						{
-							try
+							if (out_Renamed != null)
 							{
-								out_Renamed.Close();
-							}
-							catch (System.IO.IOException e)
-							{
-								throw new System.SystemException("Cannot close output stream: " + e.ToString());
+								try
+								{
+									out_Renamed.Close();
+								}
+								catch (System.IO.IOException e)
+								{
+									throw new System.SystemException("Cannot close output stream: " + e.ToString(), e);
+								}
 							}
 						}
 					}
@@ -545,6 +569,7 @@
 		/// </summary>
 		public override IndexOutput CreateOutput(System.String name)
 		{
+			
 			System.IO.FileInfo file = new System.IO.FileInfo(System.IO.Path.Combine(directory.FullName, name));
 			bool tmpBool;
 			if (System.IO.File.Exists(file.FullName))
@@ -580,27 +605,8 @@
 		/// <summary> So we can do some byte-to-hexchar conversion below</summary>
 		private static readonly char[] HEX_DIGITS = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
 		
-		/// <summary>Constructs a {@link Lock} with the specified name.  Locks are implemented
-		/// with {@link File#createNewFile()}.
-		/// 
-		/// </summary>
-		/// <param name="name">the name of the lock file
-		/// </param>
-		/// <returns> an instance of <code>Lock</code> holding the lock
-		/// </returns>
-		public override Lock MakeLock(System.String name)
-		{
-			System.Text.StringBuilder buf = GetLockPrefix();
-			buf.Append("-");
-			buf.Append(name);
-			
-			// create a lock file
-			System.IO.FileInfo lockFile = new System.IO.FileInfo(System.IO.Path.Combine(lockDir.FullName, buf.ToString()));
-			
-			return new AnonymousClassLock(lockFile, this);
-		}
 		
-		private System.Text.StringBuilder GetLockPrefix()
+		public override System.String GetLockID()
 		{
 			System.String dirName; // name to be hashed
 			try
@@ -609,7 +615,7 @@
 			}
 			catch (System.IO.IOException e)
 			{
-				throw new System.SystemException(e.ToString());
+				throw new System.SystemException(e.ToString(), e);
 			}
 			
 			byte[] digest;
@@ -626,7 +632,7 @@
 				buf.Append(HEX_DIGITS[b & 0xf]);
 			}
 			
-			return buf;
+			return buf.ToString();
 		}
 		
 		/// <summary>Closes the store to future operations. </summary>
@@ -671,12 +677,12 @@
 					}
 					catch (System.Exception e)
 					{
-						throw new System.SystemException("cannot load default FSDirectory class: " + e.ToString());
+						throw new System.SystemException("cannot load default FSDirectory class: " + e.ToString(), e);
 					}
 				}
                 catch (System.Exception e)
                 {
-                    throw new System.SystemException("cannot load FSDirectory class: " + e.ToString());
+                    throw new System.SystemException("cannot load FSDirectory class: " + e.ToString(), e);
                 }
             }
 			{
@@ -686,7 +692,7 @@
 				}
 				catch (System.Exception e)
 				{
-					throw new System.SystemException(e.ToString());
+					throw new System.SystemException(e.ToString(), e);
 				}
 			}
 		}
@@ -695,42 +701,60 @@
 	
 	public class FSIndexInput : BufferedIndexInput, System.ICloneable
 	{
-		private class Descriptor : System.IO.BinaryReader
+		/// <summary>Method used for testing. Returns true if the underlying
+		/// file descriptor is valid.
+		/// </summary>
+		virtual internal bool FDValid
 		{
-			private void  InitBlock(FSIndexInput enclosingInstance)
+			get
 			{
-				this.enclosingInstance = enclosingInstance;
+				return true; // return file.getFD().valid();    // {{Aroush-2.1 in .NET, how do we do this?
+			}
+			
+		}
+		
+		private class Descriptor : System.IO.BinaryReader
+		{
+			// remember if the file is open, so that we don't try to close it
+			// more than once
+			private bool isOpen;
+			internal long position;
+			internal long length;
+			
+            public Descriptor(FSIndexInput enclosingInstance, System.IO.FileInfo file, System.IO.FileAccess mode) 
+                : base(new System.IO.FileStream(file.FullName, System.IO.FileMode.Open, mode, System.IO.FileShare.ReadWrite))
+            {
+				isOpen = true;
+                length = file.Length;
 			}
-			private FSIndexInput enclosingInstance;
-			public FSIndexInput Enclosing_Instance
+			
+			public override void  Close()
 			{
-				get
+				if (isOpen)
 				{
-					return enclosingInstance;
+					isOpen = false;
+					base.Close();
 				}
-				
 			}
-			public long position;
-			public Descriptor(FSIndexInput enclosingInstance, System.IO.FileInfo file, System.IO.FileAccess mode) 
-                : base(new System.IO.FileStream(file.FullName, System.IO.FileMode.Open, mode, System.IO.FileShare.ReadWrite))
+			
+			~Descriptor()
 			{
-				InitBlock(enclosingInstance);
+				try
+				{
+					Close();
+				}
+				finally
+				{
+				}
 			}
 		}
 		
-		private Descriptor file = null;
+		private Descriptor file;
 		internal bool isClone;
-		private long length;
 		
-        public bool IsClone
-        {
-            get { return (isClone); }
-        }
-
 		public FSIndexInput(System.IO.FileInfo path)
 		{
 			file = new Descriptor(this, path, System.IO.FileAccess.Read);
-			length = file.BaseStream.Length;
 		}
 		
 		/// <summary>IndexInput methods </summary>
@@ -759,7 +783,8 @@
 		
 		public override void  Close()
 		{
-			if (!isClone && file != null)
+			// only close the file if this is not a clone
+			if (!isClone)
 				file.Close();
             System.GC.SuppressFinalize(this);
 		}
@@ -770,12 +795,7 @@
 		
 		public override long Length()
 		{
-			return length;
-		}
-		
-		~FSIndexInput()
-		{
-			Close(); // close the file
+			return file.length;
 		}
 		
 		public override System.Object Clone()
@@ -784,16 +804,6 @@
 			clone.isClone = true;
 			return clone;
 		}
-		
-		/// <summary>Method used for testing. Returns true if the underlying
-		/// file descriptor is valid.
-		/// </summary>
-		public /*internal*/ virtual bool IsFDValid()
-		{
-            if (file.BaseStream == null)
-                return false;
-			return file.BaseStream.CanRead;
-		}
 	}
 	
 	
@@ -801,9 +811,14 @@
 	{
 		internal System.IO.BinaryWriter file = null;
 		
+		// remember if the file is open, so that we don't try to close it
+		// more than once
+		private bool isOpen;
+		
 		public FSIndexOutput(System.IO.FileInfo path)
 		{
 			file = new System.IO.BinaryWriter(new System.IO.FileStream(path.FullName, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite));
+			isOpen = true;
 		}
 		
 		/// <summary>output methods: </summary>
@@ -813,9 +828,14 @@
 		}
 		public override void  Close()
 		{
-			base.Close();
-			file.Close();
-			System.GC.SuppressFinalize(this);
+			// only close the file if it has not been closed yet
+			if (isOpen)
+			{
+				base.Close();
+				file.Close();
+				isOpen = false;
+                System.GC.SuppressFinalize(this);
+			}
 		}
 		
 		/// <summary>Random-access methods </summary>
@@ -827,11 +847,6 @@
 		public override long Length()
 		{
 			return file.BaseStream.Length;
-		}
-		
-		~FSIndexOutput()
-		{
-			file.Close(); // close the file
 		}
 	}
 }

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/IndexInput.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Store/IndexInput.cs?view=diff&rev=534192&r1=534191&r2=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/IndexInput.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/IndexInput.cs Tue May  1 11:45:26 2007
@@ -72,7 +72,7 @@
 		}
 		
 		/// <summary>Reads eight bytes and returns a long.</summary>
-		/// <seealso cref="IndexOutput.WriteLong(long)">
+		/// <seealso cref="IndexOutput#WriteLong(long)">
 		/// </seealso>
 		public virtual long ReadLong()
 		{
@@ -132,6 +132,38 @@
 					buffer[i] = (char) (((b & 0x0F) << 12) | ((ReadByte() & 0x3F) << 6) | (ReadByte() & 0x3F));
 			}
 		}
+		
+		/// <summary> Expert
+		/// 
+		/// Similar to {@link #ReadChars(char[], int, int)} but does not do any conversion operations on the bytes it is reading in.  It still
+		/// has to invoke {@link #ReadByte()} just as {@link #ReadChars(char[], int, int)} does, but it does not need a buffer to store anything
+		/// and it does not have to do any of the bitwise operations, since we don't actually care what is in the byte except to determine
+		/// how many more bytes to read
+		/// </summary>
+		/// <param name="length">The number of chars to read
+		/// </param>
+		public virtual void  SkipChars(int length)
+		{
+			for (int i = 0; i < length; i++)
+			{
+				byte b = ReadByte();
+				if ((b & 0x80) == 0)
+				{
+					//do nothing, we only need one byte
+				}
+				else if ((b & 0xE0) != 0xE0)
+				{
+					ReadByte(); //read an additional byte
+				}
+				else
+				{
+					//read two additional bytes.
+					ReadByte();
+					ReadByte();
+				}
+			}
+		}
+		
 		
 		/// <summary>Closes the stream to futher operations. </summary>
 		public abstract void  Close();

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/IndexOutput.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Store/IndexOutput.cs?view=diff&rev=534192&r1=534191&r2=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/IndexOutput.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/IndexOutput.cs Tue May  1 11:45:26 2007
@@ -91,7 +91,7 @@
 			while ((i & ~ 0x7F) != 0)
 			{
 				WriteByte((byte) ((i & 0x7f) | 0x80));
-				i = (int) (((uint) i) >> 7);    // {{Aroush-1.9}} Is this OK?!  long to uint, to int conversion.
+				i = SupportClass.Number.URShift(i, 7);
 			}
 			WriteByte((byte) i);
 		}

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/Lock.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Store/Lock.cs?view=diff&rev=534192&r1=534191&r2=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/Lock.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/Lock.cs Tue May  1 11:45:26 2007
@@ -16,7 +16,6 @@
  */
 
 using System;
-using IndexWriter = Lucene.Net.Index.IndexWriter;
 
 namespace Lucene.Net.Store
 {
@@ -27,15 +26,15 @@
 	/// public Object doBody() {
 	/// <i>... code to execute while locked ...</i>
 	/// }
-	/// }.Run();
+	/// }.run();
 	/// </pre>
 	/// 
 	/// </summary>
 	/// <author>  Doug Cutting
 	/// </author>
-	/// <version>  $Id: Lock.java 179414 2005-06-01 20:10:58Z dnaber $
+	/// <version>  $Id: Lock.java 472959 2006-11-09 16:21:50Z yonik $
 	/// </version>
-	/// <seealso cref="Directory.MakeLock(String)">
+	/// <seealso cref="Directory#MakeLock(String)">
 	/// </seealso>
 	public abstract class Lock
 	{
@@ -48,6 +47,12 @@
 		/// </returns>
 		public abstract bool Obtain();
 		
+		/// <summary> If a lock obtain called, this failureReason may be set
+		/// with the "root cause" Exception as to why the lock was
+		/// not obtained.
+		/// </summary>
+		protected internal System.Exception failureReason;
+		
 		/// <summary>Attempts to obtain an exclusive lock within amount
 		/// of time given. Currently polls once per second until
 		/// lockWaitTimeout is passed.
@@ -59,6 +64,7 @@
 		/// <throws>  IOException if lock wait times out or obtain() throws an IOException </throws>
 		public virtual bool Obtain(long lockWaitTimeout)
 		{
+			failureReason = null;
 			bool locked = Obtain();
 			int maxSleepCount = (int) (lockWaitTimeout / LOCK_POLL_INTERVAL);
 			int sleepCount = 0;
@@ -66,7 +72,17 @@
 			{
 				if (sleepCount++ == maxSleepCount)
 				{
-					throw new System.IO.IOException("Lock obtain timed out: " + this.ToString());
+					System.String reason = "Lock obtain timed out: " + this.ToString();
+					if (failureReason != null)
+					{
+						reason += (": " + failureReason);
+					}
+					System.IO.IOException e = new System.IO.IOException(reason);
+					if (failureReason != null)
+					{
+                        e = new System.IO.IOException(reason, failureReason);
+					}
+					throw e;
 				}
 				try
 				{
@@ -105,7 +121,7 @@
 			}
 			
 			/// <summary>Code to execute with exclusive access. </summary>
-			public abstract System.Object DoBody();
+			protected internal abstract System.Object DoBody();
 			
 			/// <summary>Calls {@link #doBody} while <i>lock</i> is obtained.  Blocks if lock
 			/// cannot be obtained immediately.  Retries to obtain lock once per second

Added: incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/LockFactory.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Store/LockFactory.cs?view=auto&rev=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/LockFactory.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/LockFactory.cs Tue May  1 11:45:26 2007
@@ -0,0 +1,65 @@
+/*
+ * 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.Store
+{
+	
+	/// <summary> Base class for Locking implementation.  {@link Directory} uses
+	/// instances of this class to implement locking.
+	/// </summary>
+	
+	public abstract class LockFactory
+	{
+		
+		protected internal System.String lockPrefix = "";
+		
+		/// <summary> Set the prefix in use for all locks created in this
+		/// LockFactory.  This is normally called once, when a
+		/// Directory gets this LockFactory instance.  However, you
+		/// can also call this (after this instance is assigned to
+		/// a Directory) to override the prefix in use.  This
+		/// is helpful if you're running Lucene on machines that
+		/// have different mount points for the same shared
+		/// directory.
+		/// </summary>
+		public virtual void  SetLockPrefix(System.String lockPrefix)
+		{
+			this.lockPrefix = lockPrefix;
+		}
+		
+		/// <summary> Get the prefix in use for all locks created in this LockFactory.</summary>
+		public virtual System.String GetLockPrefix()
+		{
+			return this.lockPrefix;
+		}
+		
+		/// <summary> Return a new Lock instance identified by lockName.</summary>
+		/// <param name="lockName">name of the lock to be created.
+		/// </param>
+		public abstract Lock MakeLock(System.String lockName);
+		
+		/// <summary> Attempt to clear (forcefully unlock and remove) the
+		/// specified lock.  Only call this at a time when you are
+		/// certain this lock is no longer in use.
+		/// </summary>
+		/// <param name="lockName">name of the lock to be cleared.
+		/// </param>
+		abstract public void  ClearLock(System.String lockName);
+	}
+}
\ No newline at end of file

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/MMapDirectory.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Store/MMapDirectory.cs?view=diff&rev=534192&r1=534191&r2=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/MMapDirectory.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/MMapDirectory.cs Tue May  1 11:45:26 2007
@@ -16,9 +16,6 @@
  */
 
 using System;
-// using ByteBuffer = java.nio.ByteBuffer;                  // {{Aroush-1.9}}
-// using FileChannel = java.nio.channels.FileChannel;       // {{Aroush-1.9}}
-// using MapMode = java.nio.channels.FileChannel.MapMode;   // {{Aroush-1.9}}
 
 namespace Lucene.Net.Store
 {
@@ -27,7 +24,7 @@
 	/// 
 	/// <p>To use this, invoke Java with the System property
 	/// Lucene.Net.FSDirectory.class set to
-	/// Lucene.Net.store.MMapDirectory.  This will cause {@link
+	/// Lucene.Net.Store.MMapDirectory.  This will cause {@link
 	/// FSDirectory#GetDirectory(File,boolean)} to return instances of this class.
 	/// </summary>
 	public class MMapDirectory : FSDirectory
@@ -36,23 +33,25 @@
 		private class MMapIndexInput : IndexInput, System.ICloneable
 		{
 			
-			private System.IO.FileStream buffer;    // private ByteBuffer buffer;   // {{Aroush-1.9}}
+			private System.IO.MemoryStream buffer;
 			private long length;
 			
 			internal MMapIndexInput(System.IO.FileStream raf)
 			{
+                byte[] data = new byte[raf.Length];
+                raf.Read(data, 0, (int) raf.Length);
 				this.length = raf.Length;
-				// this.buffer = raf.getChannel().map(MapMode.READ_ONLY, 0, length);    // {{Aroush-1.9}}
+                this.buffer = new System.IO.MemoryStream(data);  // this.buffer = raf.getChannel().map(MapMode.READ_ONLY, 0, length);    // {{Aroush-1.9}}
 			}
 			
 			public override byte ReadByte()
 			{
-				return 0;   // return buffer.get_Renamed(); // {{Aroush-1.9}}
+                return (byte) buffer.ReadByte();
 			}
 			
 			public override void  ReadBytes(byte[] b, int offset, int len)
 			{
-				// buffer.get_Renamed(b, offset, len);  // {{Aroush-1.9}}
+                buffer.Read(b, offset, len);
 			}
 			
 			public override long GetFilePointer()
@@ -85,7 +84,7 @@
 		private class MultiMMapIndexInput : IndexInput, System.ICloneable
 		{
 			
-			private System.IO.FileStream[] buffers; // private ByteBuffer[] buffers;    // {{Aroush-1.9}}
+			private System.IO.MemoryStream[] buffers;
 			private int[] bufSizes; // keep here, ByteBuffer.size() method is optional
 			
 			private long length;
@@ -93,7 +92,7 @@
 			private int curBufIndex;
 			private int maxBufSize;
 			
-			private System.IO.FileStream curBuf;    // private ByteBuffer curBuf; // {{Aroush-1.9}}    // redundant for speed: buffers[curBufIndex]
+			private System.IO.MemoryStream curBuf;    // redundant for speed: buffers[curBufIndex]
 			private int curAvail; // redundant for speed: (bufSizes[curBufIndex] - curBuf.position())
 			
 			
@@ -114,15 +113,18 @@
 				if ((nrBuffers * maxBufSize) < length)
 					nrBuffers++;
 				
-				this.buffers = new System.IO.FileStream[nrBuffers]; // this.buffers = new ByteBuffer[nrBuffers];   // {{Aroush-1.9}}
+				this.buffers = new System.IO.MemoryStream[nrBuffers];   // {{Aroush-1.9}}
 				this.bufSizes = new int[nrBuffers];
 				
 				long bufferStart = 0;
-				System.IO.FileStream rafc = null;   // FileChannel rafc = raf.getChannel();    // {{Aroush-1.9}}
+				System.IO.FileStream rafc = raf;
 				for (int bufNr = 0; bufNr < nrBuffers; bufNr++)
 				{
+                    byte[] data = new byte[rafc.Length];
+                    raf.Read(data, 0, (int) rafc.Length);
+
 					int bufSize = (length > (bufferStart + maxBufSize))?maxBufSize:(int) (length - bufferStart);
-					// this.buffers[bufNr] = rafc.map(MapMode.READ_ONLY, bufferStart, bufSize);    // {{Aroush-1.9}}
+					this.buffers[bufNr] = new System.IO.MemoryStream(data);     // rafc.map(MapMode.READ_ONLY, bufferStart, bufSize);     // {{Aroush-1.9}}
 					this.bufSizes[bufNr] = bufSize;
 					bufferStart += bufSize;
 				}
@@ -141,14 +143,14 @@
 					curAvail = bufSizes[curBufIndex];
 				}
 				curAvail--;
-				return 0;   // return curBuf.get_Renamed();     // {{Aroush-1.9}}
+				return (byte) curBuf.ReadByte();
 			}
 			
 			public override void  ReadBytes(byte[] b, int offset, int len)
 			{
 				while (len > curAvail)
 				{
-					// curBuf.get_Renamed(b, offset, curAvail);    // {{Aroush-1.9}}
+					curBuf.Read(b, offset, curAvail);
 					len -= curAvail;
 					offset += curAvail;
 					curBufIndex++;
@@ -156,7 +158,7 @@
 					curBuf.Seek(0, System.IO.SeekOrigin.Begin);
 					curAvail = bufSizes[curBufIndex];
 				}
-				// curBuf.get_Renamed(b, offset, len); // {{Aroush-1.9}}
+				curBuf.Read(b, offset, len);
 				curAvail -= len;
 			}
 			
@@ -182,13 +184,13 @@
 			public override System.Object Clone()
 			{
 				MultiMMapIndexInput clone = (MultiMMapIndexInput) base.Clone();
-				// clone.buffers = new ByteBuffer[buffers.length];  // {{Aroush-1.9}}
+				clone.buffers = new System.IO.MemoryStream[buffers.Length];
 				// No need to clone bufSizes.
 				// Since most clones will use only one buffer, duplicate() could also be
 				// done lazy in clones, eg. when adapting curBuf.
 				for (int bufNr = 0; bufNr < buffers.Length; bufNr++)
 				{
-					// clone.buffers[bufNr] = buffers[bufNr].duplicate();   // {{Aroush-1.9}}
+					clone.buffers[bufNr] = buffers[bufNr];    // clone.buffers[bufNr] = buffers[bufNr].duplicate();   // {{Aroush-1.9}} how do we clone?!
 				}
 				try
 				{
@@ -196,9 +198,9 @@
 				}
 				catch (System.IO.IOException ioe)
 				{
-                    System.Exception newException = new System.Exception("", ioe);  // {{Aroush-2.0}} This should be SystemException
-                    throw newException;
-                }
+					System.Exception newException = new System.Exception("", ioe);  // {{Aroush-2.0}} This should be SystemException
+					throw newException;
+				}
 				return clone;
 			}
 			

Added: incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/NativeFSLockFactory.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Store/NativeFSLockFactory.cs?view=auto&rev=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/NativeFSLockFactory.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/NativeFSLockFactory.cs Tue May  1 11:45:26 2007
@@ -0,0 +1,461 @@
+/*
+ * 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 FileChannel = java.nio.channels.FileChannel;
+// using FileLock = java.nio.channels.FileLock;
+
+namespace Lucene.Net.Store
+{
+	
+	/// <summary> Implements {@link LockFactory} using native OS file locks
+	/// (available through java.nio.*).  Note that for certain
+	/// filesystems native locks are possible but must be
+	/// explicity configured and enabled (and may be disabled by
+	/// default).  For example, for NFS servers there sometimes
+	/// must be a separate lockd process running, and other
+	/// configuration may be required such as running the server
+	/// in kernel mode.  Other filesystems may not even support
+	/// native OS locks in which case you must use a different
+	/// {@link LockFactory} implementation.
+	/// 
+	/// <p>The advantage of this lock factory over
+	/// {@link SimpleFSLockFactory} is that the locks should be
+	/// "correct", whereas {@link SimpleFSLockFactory} uses
+	/// java.io.File.createNewFile which
+	/// <a target="_top" href="http://java.sun.com/j2se/1.4.2/docs/api/java/io/File.html#createNewFile()">has warnings</a> about not
+	/// using it for locking.  Furthermore, if the JVM crashes,
+	/// the OS will free any held locks, whereas
+	/// {@link SimpleFSLockFactory} will keep the locks held, requiring
+	/// manual removal before re-running Lucene.</p>
+	/// 
+	/// <p>Note that, unlike {@link SimpleFSLockFactory}, the existence of
+	/// leftover lock files in the filesystem on exiting the JVM
+	/// is fine because the OS will free the locks held against
+	/// these files even though the files still remain.</p>
+	/// 
+	/// <p>Native locks file names have the substring "-n-", which
+	/// you can use to differentiate them from lock files created
+	/// by {@link SimpleFSLockFactory}.</p>
+	/// 
+	/// </summary>
+	/// <seealso cref="LockFactory">
+	/// </seealso>
+	
+	public class NativeFSLockFactory : LockFactory
+	{
+		
+		/// <summary> Directory specified by <code>Lucene.Net.lockDir</code>
+		/// system property.  If that is not set, then <code>java.io.tmpdir</code>
+		/// system property is used.
+		/// </summary>
+		
+		private System.IO.FileInfo lockDir;
+		
+		// Simple test to verify locking system is "working".  On
+		// NFS, if it's misconfigured, you can hit long (35
+		// second) timeouts which cause Lock.obtain to take far
+		// too long (it assumes the obtain() call takes zero
+		// time).  Since it's a configuration problem, we test up
+		// front once on creating the LockFactory:
+		private void  AcquireTestLock()
+		{
+			System.String randomLockName = "lucene-" + System.Convert.ToString(new System.Random().Next(), 16) + "-test.lock";
+			
+			Lock l = MakeLock(randomLockName);
+			try
+			{
+				l.Obtain();
+			}
+			catch (System.IO.IOException e)
+			{
+				System.IO.IOException e2 = new System.IO.IOException("Failed to acquire random test lock; please verify filesystem for lock directory '" + lockDir + "' supports locking", e);
+				throw e2;
+			}
+			
+			l.Release();
+		}
+		
+		/// <summary> Create a NativeFSLockFactory instance, storing lock
+		/// files into the specified lockDirName:
+		/// 
+		/// </summary>
+		/// <param name="lockDirName">where lock files are created.
+		/// </param>
+		public NativeFSLockFactory(System.String lockDirName) : this(new System.IO.FileInfo(lockDirName))
+		{
+		}
+		
+		/// <summary> Create a NativeFSLockFactory instance, storing lock
+		/// files into the specified lockDir:
+		/// 
+		/// </summary>
+		/// <param name="lockDir">where lock files are created.
+		/// </param>
+		public NativeFSLockFactory(System.IO.FileInfo lockDir)
+		{
+			
+			this.lockDir = lockDir;
+			
+			// Ensure that lockDir exists and is a directory.
+			bool tmpBool;
+			if (System.IO.File.Exists(lockDir.FullName))
+				tmpBool = true;
+			else
+				tmpBool = System.IO.Directory.Exists(lockDir.FullName);
+			if (!tmpBool)
+			{
+                try
+                {
+                    System.IO.Directory.CreateDirectory(lockDir.FullName);
+                }
+                catch
+                {
+                    throw new System.IO.IOException("Cannot create directory: " + lockDir.FullName);
+                }
+			}
+			else if (!System.IO.Directory.Exists(lockDir.FullName))
+			{
+				throw new System.IO.IOException("Found regular file where directory expected: " + lockDir.FullName);
+			}
+			
+			AcquireTestLock();
+		}
+		
+		public override Lock MakeLock(System.String lockName)
+		{
+			lock (this)
+			{
+				if (lockPrefix != null)
+					lockName = lockPrefix + "-n-" + lockName;
+				return new NativeFSLock(lockDir, lockName);
+			}
+		}
+		
+		public override void  ClearLock(System.String lockName)
+		{
+			// Note that this isn't strictly required anymore
+			// because the existence of these files does not mean
+			// they are locked, but, still do this in case people
+			// really want to see the files go away:
+			bool tmpBool;
+			if (System.IO.File.Exists(lockDir.FullName))
+				tmpBool = true;
+			else
+				tmpBool = System.IO.Directory.Exists(lockDir.FullName);
+			if (tmpBool)
+			{
+				if (lockPrefix != null)
+				{
+					lockName = lockPrefix + "-n-" + lockName;
+				}
+				System.IO.FileInfo lockFile = new System.IO.FileInfo(System.IO.Path.Combine(lockDir.FullName, lockName));
+				bool tmpBool2;
+				if (System.IO.File.Exists(lockFile.FullName))
+					tmpBool2 = true;
+				else
+					tmpBool2 = System.IO.Directory.Exists(lockFile.FullName);
+				bool tmpBool3;
+				if (System.IO.File.Exists(lockFile.FullName))
+				{
+					System.IO.File.Delete(lockFile.FullName);
+					tmpBool3 = true;
+				}
+				else if (System.IO.Directory.Exists(lockFile.FullName))
+				{
+					System.IO.Directory.Delete(lockFile.FullName);
+					tmpBool3 = true;
+				}
+				else
+					tmpBool3 = false;
+				if (tmpBool2 && !tmpBool3)
+				{
+					throw new System.IO.IOException("Cannot delete " + lockFile);
+				}
+			}
+		}
+	}
+	
+	
+	class NativeFSLock : Lock
+	{
+		
+		private System.IO.FileStream f;
+		private System.IO.FileStream channel;   // private FileChannel B; // {{Aroush-2.1}}
+		private bool lock_Renamed;              // FileLock lock_Renamed;   // {{Aroush-2.1}}
+		private System.IO.FileInfo path;
+		private System.IO.FileInfo lockDir;
+		
+		/*
+		* The javadocs for FileChannel state that you should have
+		* a single instance of a FileChannel (per JVM) for all
+		* locking against a given file.  To ensure this, we have
+		* a single (static) HashSet that contains the file paths
+		* of all currently locked locks.  This protects against
+		* possible cases where different Directory instances in
+		* one JVM (each with their own NativeFSLockFactory
+		* instance) have set the same lock dir and lock prefix.
+		*/
+		private static System.Collections.Hashtable LOCK_HELD = new System.Collections.Hashtable();
+		
+		public NativeFSLock(System.IO.FileInfo lockDir, System.String lockFileName)
+		{
+			this.lockDir = lockDir;
+			path = new System.IO.FileInfo(System.IO.Path.Combine(lockDir.FullName, lockFileName));
+		}
+		
+		public override bool Obtain()
+		{
+			lock (this)
+			{
+				
+				if (IsLocked())
+				{
+					// Our instance is already locked:
+					return false;
+				}
+				
+				// Ensure that lockDir exists and is a directory.
+				bool tmpBool;
+				if (System.IO.File.Exists(lockDir.FullName))
+					tmpBool = true;
+				else
+					tmpBool = System.IO.Directory.Exists(lockDir.FullName);
+				if (!tmpBool)
+				{
+                    try
+                    {
+                        System.IO.Directory.CreateDirectory(lockDir.FullName);
+                    }
+                    catch
+                    {
+                        throw new System.IO.IOException("Cannot create directory: " + lockDir.FullName);
+                    }
+				}
+				else
+				{
+                    try
+                    {
+                         System.IO.Directory.Exists(lockDir.FullName);
+                    }
+                    catch
+                    {
+                        throw new System.IO.IOException("Found regular file where directory expected: " + lockDir.FullName);
+                    }
+				}
+				
+				System.String canonicalPath = path.FullName;
+				
+				bool markedHeld = false;
+				
+				try
+				{
+					
+					// Make sure nobody else in-process has this lock held
+					// already, and, mark it held if not:
+					
+					lock (LOCK_HELD)
+					{
+						if (LOCK_HELD.Contains(canonicalPath))
+						{
+							// Someone else in this JVM already has the lock:
+							return false;
+						}
+						else
+						{
+							// This "reserves" the fact that we are the one
+							// thread trying to obtain this lock, so we own
+							// the only instance of a channel against this
+							// file:
+							LOCK_HELD.Add(canonicalPath, canonicalPath);
+							markedHeld = true;
+						}
+					}
+					
+					try
+					{
+						f = new System.IO.FileStream(path.FullName, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite); 
+					}
+					catch (System.IO.IOException e)
+					{
+						// On Windows, we can get intermittant "Access
+						// Denied" here.  So, we treat this as failure to
+						// acquire the lock, but, store the reason in case
+						// there is in fact a real error case.
+						failureReason = e;
+						f = null;
+					}
+					
+					if (f != null)
+					{
+						try
+						{
+							channel = f; // f.getChannel();     // {{Aroush-2.1}}
+                            lock_Renamed = false;
+							try
+							{
+								channel.Lock(0, channel.Length);
+                                lock_Renamed = true;
+							}
+							catch (System.IO.IOException e)
+							{
+								// At least on OS X, we will sometimes get an
+								// intermittant "Permission Denied" IOException,
+								// which seems to simply mean "you failed to get
+								// the lock".  But other IOExceptions could be
+								// "permanent" (eg, locking is not supported via
+								// the filesystem).  So, we record the failure
+								// reason here; the timeout obtain (usually the
+								// one calling us) will use this as "root cause"
+								// if it fails to get the lock.
+								failureReason = e;
+							}
+							finally
+							{
+								if (lock_Renamed == false)
+								{
+									try
+									{
+										channel.Close();
+									}
+									finally
+									{
+										channel = null;
+									}
+								}
+							}
+						}
+						finally
+						{
+							if (channel == null)
+							{
+								try
+								{
+									f.Close();
+								}
+								finally
+								{
+									f = null;
+								}
+							}
+						}
+					}
+				}
+				finally
+				{
+					if (markedHeld && !IsLocked())
+					{
+						lock (LOCK_HELD)
+						{
+							if (LOCK_HELD.Contains(canonicalPath))
+							{
+								LOCK_HELD.Remove(canonicalPath);
+							}
+						}
+					}
+				}
+				return IsLocked();
+			}
+		}
+		
+		public override void  Release()
+		{
+			lock (this)
+			{
+				try
+				{
+					if (IsLocked())
+					{
+						try
+						{
+                            channel.Unlock(0, channel.Length);
+						}
+						finally
+						{
+							lock_Renamed = false;
+							try
+							{
+								channel.Close();
+							}
+							finally
+							{
+								channel = null;
+								try
+								{
+									f.Close();
+								}
+								finally
+								{
+									f = null;
+									lock (LOCK_HELD)
+									{
+										LOCK_HELD.Remove(path.FullName);
+									}
+								}
+							}
+						}
+						bool tmpBool;
+						if (System.IO.File.Exists(path.FullName))
+						{
+							System.IO.File.Delete(path.FullName);
+							tmpBool = true;
+						}
+						else if (System.IO.Directory.Exists(path.FullName))
+						{
+							System.IO.Directory.Delete(path.FullName);
+							tmpBool = true;
+						}
+						else
+							tmpBool = false;
+						bool generatedAux = tmpBool;
+					}
+				}
+				catch (System.IO.IOException e)
+				{
+					// Not sure how to better message/handle this without
+					// changing API?
+					throw new System.SystemException("", e);
+				}
+			}
+		}
+		
+		public override bool IsLocked()
+		{
+			return lock_Renamed;
+		}
+		
+		public override System.String ToString()
+		{
+			return "NativeFSLock@" + path;
+		}
+		
+		~NativeFSLock()
+		{
+			try
+			{
+				if (IsLocked())
+				{
+					Release();
+				}
+			}
+			finally
+			{
+			}
+		}
+	}
+}
\ No newline at end of file

Added: incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/NoLockFactory.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Store/NoLockFactory.cs?view=auto&rev=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/NoLockFactory.cs (added)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/NoLockFactory.cs Tue May  1 11:45:26 2007
@@ -0,0 +1,77 @@
+/*
+ * 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.Store
+{
+	
+	/// <summary> Use this {@link LockFactory} to disable locking entirely.
+	/// This LockFactory is used when you call {@link FSDirectory#setDisableLocks}.
+	/// Only one instance of this lock is created.  You should call {@link
+	/// #GetNoLockFactory()} to get the instance.
+	/// 
+	/// </summary>
+	/// <seealso cref="LockFactory">
+	/// </seealso>
+	
+	public class NoLockFactory : LockFactory
+	{
+		
+		// Single instance returned whenever makeLock is called.
+		private static NoLock singletonLock = new NoLock();
+		private static NoLockFactory singleton = new NoLockFactory();
+		
+		public static NoLockFactory GetNoLockFactory()
+		{
+			return singleton;
+		}
+		
+		public override Lock MakeLock(System.String lockName)
+		{
+			return singletonLock;
+		}
+		
+		public override void  ClearLock(System.String lockName)
+		{
+		}
+		
+	}
+	
+	
+	class NoLock:Lock
+	{
+		public override bool Obtain()
+		{
+			return true;
+		}
+		
+		public override void  Release()
+		{
+		}
+		
+		public override bool IsLocked()
+		{
+			return false;
+		}
+		
+		public override System.String ToString()
+		{
+			return "NoLock";
+		}
+	}
+}
\ No newline at end of file

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/Package.html
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Store/Package.html?view=diff&rev=534192&r1=534191&r2=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/Package.html (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/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>
-Binary i/o API, used for all index data.
-</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>
+Binary i/o API, used for all index data.
+</body>
+</html>

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/RAMDirectory.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Store/RAMDirectory.cs?view=diff&rev=534192&r1=534191&r2=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/RAMDirectory.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/RAMDirectory.cs Tue May  1 11:45:26 2007
@@ -20,60 +20,30 @@
 namespace Lucene.Net.Store
 {
 	
-	/// <summary> A memory-resident {@link Directory} implementation.
+	/// <summary> A memory-resident {@link Directory} implementation.  Locking
+	/// implementation is by default the {@link SingleInstanceLockFactory}
+	/// but can be changed with {@link #setLockFactory}.
 	/// 
 	/// </summary>
-	/// <version>  $Id: RAMDirectory.java 351779 2005-12-02 17:37:50Z bmesser $
+	/// <version>  $Id: RAMDirectory.java 503911 2007-02-05 22:49:42Z dnaber $
 	/// </version>
-	public sealed class RAMDirectory : Directory
+	[Serializable]
+	public class RAMDirectory : Directory
 	{
-		private class AnonymousClassLock : Lock
-		{
-			public AnonymousClassLock(System.String name, RAMDirectory enclosingInstance)
-			{
-				InitBlock(name, enclosingInstance);
-			}
-			private void  InitBlock(System.String name, RAMDirectory enclosingInstance)
-			{
-				this.name = name;
-				this.enclosingInstance = enclosingInstance;
-			}
-			private System.String name;
-			private RAMDirectory enclosingInstance;
-			public RAMDirectory Enclosing_Instance
-			{
-				get
-				{
-					return enclosingInstance;
-				}
-				
-			}
-			public override bool Obtain()
-			{
-				lock (Enclosing_Instance.files.SyncRoot)
-				{
-					if (!Enclosing_Instance.FileExists(name))
-					{
-						Enclosing_Instance.CreateOutput(name).Close();
-						return true;
-					}
-					return false;
-				}
-			}
-			public override void  Release()
-			{
-				Enclosing_Instance.DeleteFile(name);
-			}
-			public override bool IsLocked()
-			{
-				return Enclosing_Instance.FileExists(name);
-			}
-		}
-		internal System.Collections.Hashtable files = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable());
+		
+		private const long serialVersionUID = 1L;
+		
+		internal System.Collections.Hashtable fileMap = new System.Collections.Hashtable();
+		internal long sizeInBytes = 0;
+		
+		// *****
+		// Lock acquisition sequence:  RAMDirectory, then RAMFile
+		// *****
 		
 		/// <summary>Constructs an empty {@link Directory}. </summary>
 		public RAMDirectory()
 		{
+			SetLockFactory(new SingleInstanceLockFactory());
 		}
 		
 		/// <summary> Creates a new <code>RAMDirectory</code> instance from a different
@@ -81,51 +51,36 @@
 		/// a disk-based index into memory.
 		/// <P>
 		/// This should be used only with indices that can fit into memory.
+		/// <P>
+		/// Note that the resulting <code>RAMDirectory</code> instance is fully
+		/// independent from the original <code>Directory</code> (it is a
+		/// complete copy).  Any subsequent changes to the
+		/// original <code>Directory</code> will not be visible in the
+		/// <code>RAMDirectory</code> instance.
 		/// 
 		/// </summary>
 		/// <param name="dir">a <code>Directory</code> value
 		/// </param>
-		/// <exception cref="IOException">if an error occurs
+		/// <exception cref=""> IOException if an error occurs
 		/// </exception>
 		public RAMDirectory(Directory dir):this(dir, false)
 		{
 		}
 		
-		private RAMDirectory(Directory dir, bool closeDir)
+		private RAMDirectory(Directory dir, bool closeDir):this()
 		{
-			System.String[] files = dir.List();
-			byte[] buf = new byte[BufferedIndexOutput.BUFFER_SIZE];
-			for (int i = 0; i < files.Length; i++)
-			{
-				// make place on ram disk
-				IndexOutput os = CreateOutput(System.IO.Path.GetFileName(files[i]));
-				// read current file
-				IndexInput is_Renamed = dir.OpenInput(files[i]);
-				// and copy to ram disk
-				long len = (int) is_Renamed.Length();
-				long readCount = 0;
-				while (readCount < len)
-				{
-					int toRead = readCount + BufferedIndexOutput.BUFFER_SIZE > len ? (int) (len - readCount) : BufferedIndexOutput.BUFFER_SIZE;
-					is_Renamed.ReadBytes(buf, 0, toRead);
-					os.WriteBytes(buf, toRead);
-					readCount += toRead;
-				}
-				
-				// graceful cleanup
-				is_Renamed.Close();
-				os.Close();
-			}
-			if (closeDir)
-				dir.Close();
+			Directory.Copy(dir, this, closeDir);
 		}
 		
 		/// <summary> Creates a new <code>RAMDirectory</code> instance from the {@link FSDirectory}.
 		/// 
 		/// </summary>
 		/// <param name="dir">a <code>File</code> specifying the index directory
+		/// 
 		/// </param>
-		public RAMDirectory(System.IO.FileInfo dir) : this(FSDirectory.GetDirectory(dir, false), true)
+		/// <seealso cref="#RAMDirectory(Directory)">
+		/// </seealso>
+		public RAMDirectory(System.IO.FileInfo dir):this(FSDirectory.GetDirectory(dir), true)
 		{
 		}
 		
@@ -133,44 +88,67 @@
 		/// 
 		/// </summary>
 		/// <param name="dir">a <code>String</code> specifying the full index directory path
+		/// 
 		/// </param>
-		public RAMDirectory(System.String dir) : this(FSDirectory.GetDirectory(dir, false), true)
+		/// <seealso cref="#RAMDirectory(Directory)">
+		/// </seealso>
+		public RAMDirectory(System.String dir) : this(FSDirectory.GetDirectory(dir), true)
 		{
 		}
 		
 		/// <summary>Returns an array of strings, one for each file in the directory. </summary>
 		public override System.String[] List()
 		{
-			System.String[] result = new System.String[files.Count];
-			int i = 0;
-			System.Collections.IEnumerator names = files.Keys.GetEnumerator();
-			while (names.MoveNext())
+			lock (this)
 			{
-				result[i++] = ((System.String) names.Current);
+				System.String[] result = new System.String[fileMap.Count];
+				int i = 0;
+				System.Collections.IEnumerator it = fileMap.Keys.GetEnumerator();
+				while (it.MoveNext())
+				{
+					result[i++] = ((System.String) it.Current);
+				}
+				return result;
 			}
-			return result;
 		}
 		
 		/// <summary>Returns true iff the named file exists in this directory. </summary>
 		public override bool FileExists(System.String name)
 		{
-			RAMFile file = (RAMFile) files[name];
+			RAMFile file;
+			lock (this)
+			{
+				file = (RAMFile) fileMap[name];
+			}
 			return file != null;
 		}
 		
-		/// <summary>Returns the time the named file was last modified. </summary>
+		/// <summary>Returns the time the named file was last modified.</summary>
+		/// <throws>  IOException if the file does not exist </throws>
 		public override long FileModified(System.String name)
 		{
-			RAMFile file = (RAMFile) files[name];
-			return file.lastModified;
+			RAMFile file;
+			lock (this)
+			{
+				file = (RAMFile) fileMap[name];
+			}
+			if (file == null)
+				throw new System.IO.FileNotFoundException(name);
+			return file.GetLastModified();
 		}
 		
-		/// <summary>Set the modified time of an existing file to now. </summary>
+		/// <summary>Set the modified time of an existing file to now.</summary>
+		/// <throws>  IOException if the file does not exist </throws>
 		public override void  TouchFile(System.String name)
 		{
-			//     final boolean MONITOR = false;
+			RAMFile file;
+			lock (this)
+			{
+				file = (RAMFile) fileMap[name];
+			}
+			if (file == null)
+				throw new System.IO.FileNotFoundException(name);
 			
-			RAMFile file = (RAMFile) files[name];
 			long ts2, ts1 = System.DateTime.Now.Ticks;
 			do 
 			{
@@ -182,67 +160,112 @@
 				{
 				}
 				ts2 = System.DateTime.Now.Ticks;
-				//       if (MONITOR) {
-				//         count++;
-				//       }
 			}
 			while (ts1 == ts2);
 			
-			file.lastModified = ts2;
-			
-			//     if (MONITOR)
-			//         System.out.println("SLEEP COUNT: " + count);
+			file.SetLastModified(ts2);
 		}
 		
-		/// <summary>Returns the length in bytes of a file in the directory. </summary>
+		/// <summary>Returns the length in bytes of a file in the directory.</summary>
+		/// <throws>  IOException if the file does not exist </throws>
 		public override long FileLength(System.String name)
 		{
-			RAMFile file = (RAMFile) files[name];
-			return file.length;
+			RAMFile file;
+			lock (this)
+			{
+				file = (RAMFile) fileMap[name];
+			}
+			if (file == null)
+				throw new System.IO.FileNotFoundException(name);
+			return file.GetLength();
 		}
 		
-		/// <summary>Removes an existing file in the directory. </summary>
+		/// <summary>Return total size in bytes of all files in this
+		/// directory.  This is currently quantized to
+		/// BufferedIndexOutput.BUFFER_SIZE. 
+		/// </summary>
+		public long SizeInBytes()
+		{
+			lock (this)
+			{
+				return sizeInBytes;
+			}
+		}
+		
+		/// <summary>Removes an existing file in the directory.</summary>
+		/// <throws>  IOException if the file does not exist </throws>
 		public override void  DeleteFile(System.String name)
 		{
-			files.Remove(name);
+			lock (this)
+			{
+				RAMFile file = (RAMFile) fileMap[name];
+				if (file != null)
+				{
+					fileMap.Remove(name);
+					file.directory = null;
+					sizeInBytes -= file.sizeInBytes; // updates to RAMFile.sizeInBytes synchronized on directory
+				}
+				else
+					throw new System.IO.FileNotFoundException(name);
+			}
 		}
 		
-		/// <summary>Removes an existing file in the directory. </summary>
+		/// <summary>Renames an existing file in the directory.</summary>
+		/// <throws>  FileNotFoundException if from does not exist </throws>
+		/// <deprecated>
+		/// </deprecated>
 		public override void  RenameFile(System.String from, System.String to)
 		{
-			RAMFile file = (RAMFile) files[from];
-			files.Remove(from);
-			files[to] = file;
+			lock (this)
+			{
+				RAMFile fromFile = (RAMFile) fileMap[from];
+				if (fromFile == null)
+					throw new System.IO.FileNotFoundException(from);
+				RAMFile toFile = (RAMFile) fileMap[to];
+				if (toFile != null)
+				{
+					sizeInBytes -= toFile.sizeInBytes; // updates to RAMFile.sizeInBytes synchronized on directory
+					toFile.directory = null;
+				}
+				fileMap.Remove(from);
+				fileMap[to] = fromFile;
+			}
 		}
 		
-		/// <summary>Creates a new, empty file in the directory with the given name.
-		/// Returns a stream writing this file. 
-		/// </summary>
+		/// <summary>Creates a new, empty file in the directory with the given name. Returns a stream writing this file. </summary>
 		public override IndexOutput CreateOutput(System.String name)
 		{
-			RAMFile file = new RAMFile();
-			files[name] = file;
+			RAMFile file = new RAMFile(this);
+			lock (this)
+			{
+				RAMFile existing = (RAMFile) fileMap[name];
+				if (existing != null)
+				{
+					sizeInBytes -= existing.sizeInBytes;
+					existing.directory = null;
+				}
+				fileMap[name] = file;
+			}
 			return new RAMOutputStream(file);
 		}
 		
 		/// <summary>Returns a stream reading an existing file. </summary>
 		public override IndexInput OpenInput(System.String name)
 		{
-			RAMFile file = (RAMFile) files[name];
+			RAMFile file;
+			lock (this)
+			{
+				file = (RAMFile) fileMap[name];
+			}
+			if (file == null)
+				throw new System.IO.FileNotFoundException(name);
 			return new RAMInputStream(file);
 		}
 		
-		/// <summary>Construct a {@link Lock}.</summary>
-		/// <param name="name">the name of the lock file
-		/// </param>
-		public override Lock MakeLock(System.String name)
-		{
-			return new AnonymousClassLock(name, this);
-		}
-		
-		/// <summary>Closes the store to future operations. </summary>
+		/// <summary>Closes the store to future operations, releasing associated memory. </summary>
 		public override void  Close()
 		{
+			fileMap = null;
 		}
 	}
 }

Modified: incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/RAMFile.cs
URL: http://svn.apache.org/viewvc/incubator/lucene.net/trunk/C%23/src/Lucene.Net/Store/RAMFile.cs?view=diff&rev=534192&r1=534191&r2=534192
==============================================================================
--- incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/RAMFile.cs (original)
+++ incubator/lucene.net/trunk/C#/src/Lucene.Net/Store/RAMFile.cs Tue May  1 11:45:26 2007
@@ -20,10 +20,88 @@
 namespace Lucene.Net.Store
 {
 	
-	class RAMFile
+	[Serializable]
+	public class RAMFile
 	{
-		internal System.Collections.ArrayList buffers = System.Collections.ArrayList.Synchronized(new System.Collections.ArrayList(10));
+		
+		private const long serialVersionUID = 1L;
+		
+		// Direct read-only access to state supported for streams since a writing stream implies no other concurrent streams
+		internal System.Collections.ArrayList buffers = new System.Collections.ArrayList();
 		internal long length;
-		internal long lastModified = System.DateTime.Now.Ticks;
+		internal RAMDirectory directory;
+		internal long sizeInBytes; // Only maintained if in a directory; updates synchronized on directory
+		
+		// This is publicly modifiable via Directory.touchFile(), so direct access not supported
+		private long lastModified = System.DateTime.Now.Ticks;
+		
+		// File used as buffer, in no RAMDirectory
+		internal RAMFile()
+		{
+		}
+		
+		internal RAMFile(RAMDirectory directory)
+		{
+			this.directory = directory;
+		}
+		
+		// For non-stream access from thread that might be concurrent with writing
+		internal virtual long GetLength()
+		{
+			lock (this)
+			{
+				return length;
+			}
+		}
+		
+		internal virtual void  SetLength(long length)
+		{
+			lock (this)
+			{
+				this.length = length;
+			}
+		}
+		
+		// For non-stream access from thread that might be concurrent with writing
+		internal virtual long GetLastModified()
+		{
+			lock (this)
+			{
+				return lastModified;
+			}
+		}
+		
+		internal virtual void  SetLastModified(long lastModified)
+		{
+			lock (this)
+			{
+				this.lastModified = lastModified;
+			}
+		}
+		
+		internal byte[] AddBuffer(int size)
+		{
+			byte[] buffer = new byte[size];
+			if (directory != null)
+				lock (directory)
+				{
+					// Ensure addition of buffer and adjustment to directory size are atomic wrt directory
+					buffers.Add(buffer);
+					directory.sizeInBytes += size;
+					sizeInBytes += size;
+				}
+			else
+				buffers.Add(buffer);
+			return buffer;
+		}
+		
+		// Only valid if in a directory
+		internal virtual long GetSizeInBytes()
+		{
+			lock (directory)
+			{
+				return sizeInBytes;
+			}
+		}
 	}
 }