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;
+ }
+ }
}
}