2 * Copyright 2004 The Apache Software Foundation
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
18 using IndexFileNameFilter
= Lucene
.Net
.Index
.IndexFileNameFilter
;
19 using Mono
.Unix
.Native
;
21 namespace Lucene
.Net
.Store
24 /// <summary> Straightforward implementation of {@link Directory} as a directory of files.
27 /// <seealso cref="Directory">
29 /// <author> Doug Cutting
31 public class FSDirectory
: Directory
33 private class AnonymousClassLock
: Lock
35 public AnonymousClassLock(System
.IO
.FileInfo lockFile
, FSDirectory enclosingInstance
)
37 InitBlock(lockFile
, enclosingInstance
);
39 private void InitBlock(System
.IO
.FileInfo lockFile
, FSDirectory enclosingInstance
)
41 this.lockFile
= lockFile
;
42 this.enclosingInstance
= enclosingInstance
;
44 private System
.IO
.FileInfo lockFile
;
45 private FSDirectory enclosingInstance
;
46 public FSDirectory Enclosing_Instance
50 return enclosingInstance
;
54 public override bool Obtain()
56 Log ("Trying to obtain lock " + lockFile
.FullName
);
57 if (Lucene
.Net
.Store
.FSDirectory
.disableLocks
|| Enclosing_Instance
.InstanceDisableLock
)
61 if (System
.IO
.File
.Exists(Enclosing_Instance
.lockDir
.FullName
))
64 tmpBool
= System
.IO
.Directory
.Exists(Enclosing_Instance
.lockDir
.FullName
);
69 System
.IO
.Directory
.CreateDirectory(Enclosing_Instance
.lockDir
.FullName
);
73 throw new System
.IO
.IOException("Cannot create lock directory: " + Enclosing_Instance
.lockDir
);
79 int fd
= Mono
.Unix
.Native
.Syscall
.open (
81 Mono
.Unix
.Native
.OpenFlags
.O_RDWR
|
82 Mono
.Unix
.Native
.OpenFlags
.O_CREAT
|
83 Mono
.Unix
.Native
.OpenFlags
.O_EXCL
,
84 Mono
.Unix
.Native
.FilePermissions
.S_IRUSR
);
86 throw new System
.IO
.IOException ("Could not create lock file: "
87 + Mono
.Unix
.Native
.Stdlib
.strerror (
88 Mono
.Unix
.Native
.Stdlib
.GetLastError ()
91 // This code replaces the commented-out code below because
92 // it ends up being much faster. The reason for this is
93 // that closing a UnixStream causes Syscall.fsync() to be
94 // called, and that apparently is extremely slow!
96 // Time(ms) Count P/call(ms) Method name
97 // 1563.926 68 22.999 Mono.Unix.Native.Syscall::fsync(int)
99 // Since the lock file is written out very often, this time
100 // adds up and noticably slows down indexing.
101 IntPtr ptr
= IntPtr
.Zero
;
105 string s
= System
.Diagnostics
.Process
.GetCurrentProcess ().Id
.ToString () + "\n";
106 ptr
= Mono
.Unix
.UnixMarshal
.StringToHeap (s
);
109 ret
= Mono
.Unix
.Native
.Syscall
.write (fd
, ptr
, (ulong) s
.Length
);
110 } while (Mono
.Unix
.UnixMarshal
.ShouldRetrySyscall ((int) ret
));
111 Mono
.Unix
.UnixMarshal
.ThrowExceptionForLastErrorIf ((int) ret
);
113 Mono
.Unix
.UnixMarshal
.FreeHeap (ptr
);
116 ret
= Mono
.Unix
.Native
.Syscall
.close (fd
);
117 } while (Mono
.Unix
.UnixMarshal
.ShouldRetrySyscall ((int) ret
));
118 Mono
.Unix
.UnixMarshal
.ThrowExceptionForLastErrorIf ((int) ret
);
121 //System.IO.StreamWriter w = new System.IO.StreamWriter (new Mono.Unix.UnixStream (fd, true));
122 //w.WriteLine (System.Diagnostics.Process.GetCurrentProcess ().Id);
128 Log ("Exception in CreateNew for file:" + lockFile
.FullName
+ ":" + e
);
132 public override void Release()
134 if (Lucene
.Net
.Store
.FSDirectory
.disableLocks
|| Enclosing_Instance
.InstanceDisableLock
)
137 if (System
.IO
.File
.Exists(lockFile
.FullName
))
139 System
.IO
.File
.Delete(lockFile
.FullName
);
142 else if (System
.IO
.Directory
.Exists(lockFile
.FullName
))
144 System
.IO
.Directory
.Delete(lockFile
.FullName
);
149 if (System
.IO
.File
.Exists(lockFile
.FullName
)) {
150 Log ("Release didnt delete lockfile {0}.", lockFile
.FullName
);
153 bool generatedAux
= tmpBool
;
155 Log ("Released lock {0}", lockFile
.FullName
);
157 Log ("Failed to release lock {0}", lockFile
.FullName
);
159 public override bool IsLocked()
161 if (Lucene
.Net
.Store
.FSDirectory
.disableLocks
|| Enclosing_Instance
.InstanceDisableLock
)
164 if (System
.IO
.File
.Exists(lockFile
.FullName
))
167 tmpBool
= System
.IO
.Directory
.Exists(lockFile
.FullName
);
171 public override System
.String
ToString()
173 return lockFile
.FullName
;
177 /// <summary>This cache of directories ensures that there is a unique Directory
178 /// instance per path, so that synchronization on the Directory can be used to
179 /// synchronize access between readers and writers.
181 /// This should be a WeakHashMap, so that entries can be GC'd, but that would
182 /// require Java 1.2. Instead we use refcounts...
184 private static readonly System
.Collections
.Hashtable DIRECTORIES
= System
.Collections
.Hashtable
.Synchronized(new System
.Collections
.Hashtable());
186 private static bool disableLocks
= false;
188 /// <summary> Set whether Lucene's use of lock files is disabled. By default,
189 /// lock files are enabled. They should only be disabled if the index
190 /// is on a read-only medium like a CD-ROM.
192 public static void SetDisableLocks(bool doDisableLocks
)
194 FSDirectory
.disableLocks
= doDisableLocks
;
197 /// <summary> Returns whether Lucene's use of lock files is disabled.</summary>
198 /// <returns> true if locks are disabled, false if locks are enabled.
200 public static bool GetDisableLocks()
202 return FSDirectory
.disableLocks
;
205 private bool instance_disable_lock
= false;
206 public bool InstanceDisableLock
{
207 get { return instance_disable_lock; }
208 set { instance_disable_lock = value; }
211 /// <summary> Directory specified by <code>Lucene.Net.lockDir</code>
212 /// or <code>java.io.tmpdir</code> system property
214 public static readonly System
.String LOCK_DIR
= SupportClass
.AppSettings
.Get("Lucene.Net.lockDir", System
.IO
.Path
.GetTempPath());
216 /// <summary>The default class which implements filesystem-based directories. </summary>
217 private static System
.Type IMPL
;
219 private static System
.Security
.Cryptography
.MD5 DIGESTER
;
221 /// <summary>A buffer optionally used in renameTo method </summary>
222 private byte[] buffer
= null;
224 /// <summary>Returns the directory instance for the named location.
226 /// <p>Directories are cached, so that, for a given canonical path, the same
227 /// FSDirectory instance will always be returned. This permits
228 /// synchronization on directories.
231 /// <param name="path">the path to the directory.
233 /// <param name="create">if true, create, or erase any existing contents.
235 /// <returns> the FSDirectory for the named file.
237 public static FSDirectory
GetDirectory(System
.String path
, bool create
)
239 return GetDirectory(new System
.IO
.FileInfo(path
), null, create
, false);
242 /// <summary>Returns the directory instance for the named location.
244 /// <p>Directories are cached, so that, for a given canonical path, the same
245 /// FSDirectory instance will always be returned. This permits
246 /// synchronization on directories.
249 /// <param name="file">the path to the directory.
251 /// <param name="create">if true, create, or erase any existing contents.
253 /// <returns> the FSDirectory for the named file.
255 public static FSDirectory
GetDirectory(System
.IO
.FileInfo file
, bool create
)
257 return GetDirectory(file
, null, create
, false);
260 /// <summary>Returns the directory instance for the named location.
262 /// <p>Directories are cached, so that, for a given canonical path, the same
263 /// FSDirectory instance will always be returned. This permits
264 /// synchronization on directories.
267 /// <param name="path">the path to the directory.
269 /// <param name="tmpDir">the path to use as lock directory.
271 /// <param name="create">if true, create, or erase any existing contents.
273 /// <returns> the FSDirectory for the named file.
275 public static FSDirectory
GetDirectory(System
.String path
, System
.String tmpDir
, bool create
)
277 return GetDirectory(new System
.IO
.FileInfo(path
), tmpDir
, create
, false);
280 /// <summary>Returns the directory instance for the named location.
282 /// <p>Directories are cached, so that, for a given canonical path, the same
283 /// FSDirectory instance will always be returned. This permits
284 /// synchronization on directories.
287 /// <param name="path">the path to the directory.
289 /// <param name="tmpDir">the path to use as lock directory.
291 /// <param name="create">if true, create, or erase any existing contents.
293 /// <param name="disable_locks">if true, disable internal locking
295 /// <returns> the FSDirectory for the named file.
297 public static FSDirectory
GetDirectory(System
.String path
, System
.String tmpDir
, bool create
, bool disable_locks
)
299 return GetDirectory(new System
.IO
.FileInfo(path
), tmpDir
, create
, disable_locks
);
302 /// <summary>Returns the directory instance for the named location.
304 /// <p>Directories are cached, so that, for a given canonical path, the same
305 /// FSDirectory instance will always be returned. This permits
306 /// synchronization on directories.
309 /// <param name="file">the path to the directory.
311 /// <param name="tmpDir">the path to use as lock directory.
313 /// <param name="create">if true, create, or erase any existing contents.
315 /// <param name="disable_locks">if true, disable internal locking
317 /// <returns> the FSDirectory for the named file.
319 public static FSDirectory
GetDirectory(System
.IO
.FileInfo file
, System
.String tmpdir
, bool create
, bool disable_locks
)
321 file
= new System
.IO
.FileInfo(file
.FullName
);
323 lock (DIRECTORIES
.SyncRoot
)
325 dir
= (FSDirectory
) DIRECTORIES
[file
];
330 dir
= (FSDirectory
) System
.Activator
.CreateInstance(IMPL
);
332 catch (System
.Exception e
)
334 throw new System
.SystemException("cannot load FSDirectory class: " + e
.ToString());
336 dir
.Init(file
, tmpdir
, create
, disable_locks
);
337 DIRECTORIES
[file
] = dir
;
351 private System
.IO
.FileInfo directory
= null;
352 private int refCount
;
353 private System
.IO
.FileInfo lockDir
;
355 public FSDirectory() // protected internal FSDirectory() // {{Aroush}} this shouldn't be 'public' but if it's not the line 'System.Activator.CreateInstance(IMPL);' in function GetDirectory() will fail.
359 // permit subclassing
361 private void Init(System
.IO
.FileInfo path
, System
.String tmpDir
, bool create
, bool disable_locks
)
364 this.instance_disable_lock
= disable_locks
;
369 lockDir
= new System
.IO
.FileInfo(tmpDir
);
371 else if (LOCK_DIR
== null)
377 lockDir
= new System
.IO
.FileInfo(LOCK_DIR
);
379 // Ensure that lockDir exists and is a directory.
381 if (System
.IO
.File
.Exists(lockDir
.FullName
))
384 tmpBool
= System
.IO
.Directory
.Exists(lockDir
.FullName
);
389 System
.IO
.Directory
.CreateDirectory(lockDir
.FullName
);
393 throw new System
.IO
.IOException("Cannot create directory: " + lockDir
);
396 else if (!System
.IO
.Directory
.Exists(lockDir
.FullName
))
398 throw new System
.IO
.IOException("Found regular file where directory expected: " + lockDir
);
405 if (!System
.IO
.Directory
.Exists(directory
.FullName
))
406 throw new System
.IO
.IOException(path
+ " not a directory");
409 private void Create()
414 if (System
.IO
.File
.Exists(directory
.FullName
))
417 tmpBool
= System
.IO
.Directory
.Exists(directory
.FullName
);
422 System
.IO
.Directory
.CreateDirectory(directory
.FullName
);
426 throw new System
.IO
.IOException("Cannot create directory: " + directory
);
432 System
.IO
.Directory
.Exists(directory
.FullName
);
436 throw new System
.IO
.IOException(directory
+ " not a directory");
439 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#?!
440 //// System.String[] files = System.IO.Directory.GetFileSystemEntries(new IndexFileNameFilter()); // clear old files
441 for (int i
= 0; i
< files
.Length
; i
++)
443 System
.IO
.FileInfo file
= new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
.FullName
, files
[i
]));
445 if (System
.IO
.File
.Exists(file
.FullName
))
447 System
.IO
.File
.Delete(file
.FullName
);
450 else if (System
.IO
.Directory
.Exists(file
.FullName
))
452 System
.IO
.Directory
.Delete(file
.FullName
);
458 throw new System
.IO
.IOException("Cannot delete " + files
[i
]);
461 System
.String lockPrefix
= GetLockPrefix().ToString(); // clear old locks
462 files
= System
.IO
.Directory
.GetFileSystemEntries(lockDir
.FullName
);
464 throw new System
.IO
.IOException("Cannot read lock directory " + lockDir
.FullName
);
465 for (int i
= 0; i
< files
.Length
; i
++)
467 if (!files
[i
].StartsWith(lockPrefix
))
469 System
.IO
.FileInfo lockFile
= new System
.IO
.FileInfo(System
.IO
.Path
.Combine(lockDir
.FullName
, files
[i
]));
471 if (System
.IO
.File
.Exists(lockFile
.FullName
))
473 System
.IO
.File
.Delete(lockFile
.FullName
);
476 else if (System
.IO
.Directory
.Exists(lockFile
.FullName
))
478 System
.IO
.Directory
.Delete(lockFile
.FullName
);
484 throw new System
.IO
.IOException("Cannot delete " + files
[i
]);
489 /// <summary>Returns an array of strings, one for each file in the directory. </summary>
490 public override System
.String
[] List()
492 return System
.IO
.Directory
.GetFileSystemEntries(directory
.FullName
);
495 /// <summary>Returns true iff a file with the given name exists. </summary>
496 public override bool FileExists(System
.String name
)
498 string path
= System
.IO
.Path
.Combine (directory
.FullName
, name
);
500 return System
.IO
.File
.Exists (path
) || System
.IO
.Directory
.Exists (path
);
503 /// <summary>Returns the time the named file was last modified. </summary>
504 public override long FileModified(System
.String name
)
506 System
.IO
.FileInfo file
= new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
.FullName
, name
));
507 return (file
.LastWriteTimeUtc
.Ticks
);
510 /// <summary>Returns the time the named file was last modified. </summary>
511 public static long FileModified(System
.IO
.FileInfo directory
, System
.String name
)
513 System
.IO
.FileInfo file
= new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
.FullName
, name
));
514 return (file
.LastWriteTimeUtc
.Ticks
);
517 /// <summary>Set the modified time of an existing file to now. </summary>
518 public override void TouchFile(System
.String name
)
520 System
.IO
.FileInfo file
= new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
.FullName
, name
));
521 file
.LastWriteTime
= System
.DateTime
.UtcNow
;
524 /// <summary>Returns the length in bytes of a file in the directory. </summary>
525 public override long FileLength(System
.String name
)
527 System
.IO
.FileInfo file
= new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
.FullName
, name
));
528 return file
.Exists
? file
.Length
: 0;
531 /// <summary>Removes an existing file in the directory. </summary>
532 public override void DeleteFile(System
.String name
)
534 System
.IO
.FileInfo file
= new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
.FullName
, name
));
536 if (System
.IO
.File
.Exists(file
.FullName
))
538 System
.IO
.File
.Delete(file
.FullName
);
541 else if (System
.IO
.Directory
.Exists(file
.FullName
))
543 System
.IO
.Directory
.Delete(file
.FullName
);
549 throw new System
.IO
.IOException("Cannot delete " + file
);
552 /// <summary>Renames an existing file in the directory. </summary>
553 public override void RenameFile(System
.String
from, System
.String to
)
557 System
.IO
.FileInfo old
= new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
.FullName
, from));
558 System
.IO
.FileInfo nu
= new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
.FullName
, to
));
560 /* This is not atomic. If the program crashes between the call to
561 delete() and the call to renameTo() then we're screwed, but I've
562 been unable to figure out how else to do this... */
565 if (System
.IO
.File
.Exists(nu
.FullName
))
568 tmpBool
= System
.IO
.Directory
.Exists(nu
.FullName
);
572 if (System
.IO
.File
.Exists(nu
.FullName
))
574 System
.IO
.File
.Delete(nu
.FullName
);
577 else if (System
.IO
.Directory
.Exists(nu
.FullName
))
579 System
.IO
.Directory
.Delete(nu
.FullName
);
585 throw new System
.IO
.IOException("Cannot delete " + nu
);
588 // Rename the old file to the new one. Unfortunately, the renameTo()
589 // method does not work reliably under some JVMs. Therefore, if the
590 // rename fails, we manually rename by copying the old file to the new one
593 old
.MoveTo(nu
.FullName
);
595 catch (System
.Exception
)
597 System
.IO
.Stream in_Renamed
= null;
598 System
.IO
.Stream out_Renamed
= null;
601 in_Renamed
= new System
.IO
.FileStream(old
.FullName
, System
.IO
.FileMode
.Open
, System
.IO
.FileAccess
.Read
);
602 out_Renamed
= new System
.IO
.FileStream(nu
.FullName
, System
.IO
.FileMode
.Create
, System
.IO
.FileAccess
.Write
, System
.IO
.FileShare
.ReadWrite
);
603 // see if the buffer needs to be initialized. Initialization is
604 // only done on-demand since many VM's will never run into the renameTo
605 // bug and hence shouldn't waste 1K of mem for no reason.
608 buffer
= new byte[1024];
611 while ((len
= in_Renamed
.Read(buffer
, 0, buffer
.Length
)) > 0)
613 out_Renamed
.Write(buffer
, 0, len
);
616 // delete the old file.
618 if (System
.IO
.File
.Exists(old
.FullName
))
620 System
.IO
.File
.Delete(old
.FullName
);
623 else if (System
.IO
.Directory
.Exists(old
.FullName
))
625 System
.IO
.Directory
.Delete(old
.FullName
);
630 bool generatedAux
= tmpBool3
;
632 catch (System
.IO
.IOException ioe
)
634 throw new System
.IO
.IOException("Cannot rename " + old
+ " to " + nu
);
638 if (in_Renamed
!= null)
644 catch (System
.IO
.IOException e
)
646 throw new System
.SystemException("Cannot close input stream: " + e
.ToString());
649 if (out_Renamed
!= null)
655 catch (System
.IO
.IOException e
)
657 throw new System
.SystemException("Cannot close output stream: " + e
.ToString());
665 /// <summary>Creates a new, empty file in the directory with the given name.
666 /// Returns a stream writing this file.
668 public override IndexOutput
CreateOutput(System
.String name
)
670 System
.IO
.FileInfo file
= new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
.FullName
, name
));
672 if (System
.IO
.File
.Exists(file
.FullName
))
675 tmpBool
= System
.IO
.Directory
.Exists(file
.FullName
);
677 if (System
.IO
.File
.Exists(file
.FullName
))
679 System
.IO
.File
.Delete(file
.FullName
);
682 else if (System
.IO
.Directory
.Exists(file
.FullName
))
684 System
.IO
.Directory
.Delete(file
.FullName
);
689 if (tmpBool
&& !tmpBool2
)
690 // delete existing, if any
691 throw new System
.IO
.IOException("Cannot overwrite: " + file
);
693 return new FSIndexOutput(file
);
696 /// <summary>Returns a stream reading an existing file. </summary>
697 public override IndexInput
OpenInput(System
.String name
)
699 return new FSIndexInput(new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
.FullName
, name
)));
702 static public Beagle
.Util
.Logger Logger
= null;
703 //static public Beagle.Util.Logger Logger = Beagle.Util.Logger.Log;
704 static public void Log (string format
, params object[] args
)
707 Logger
.Debug (format
, args
);
710 static public void Log (Exception e
)
716 /// <summary> So we can do some byte-to-hexchar conversion below</summary>
717 private static readonly char[] HEX_DIGITS
= new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}
;
719 /// <summary>Constructs a {@link Lock} with the specified name. Locks are implemented
720 /// with {@link File#createNewFile()}.
723 /// <param name="name">the name of the lock file
725 /// <returns> an instance of <code>Lock</code> holding the lock
727 public override Lock
MakeLock(System
.String name
)
729 System
.Text
.StringBuilder buf
= GetLockPrefix();
733 // create a lock file
734 System
.IO
.FileInfo lockFile
= new System
.IO
.FileInfo(System
.IO
.Path
.Combine(lockDir
.FullName
, buf
.ToString()));
736 return new AnonymousClassLock(lockFile
, this);
739 private System
.Text
.StringBuilder
GetLockPrefix()
741 System
.String dirName
; // name to be hashed
744 dirName
= directory
.FullName
;
746 catch (System
.IO
.IOException e
)
748 throw new System
.SystemException(e
.ToString());
754 digest
= DIGESTER
.ComputeHash(System
.Text
.Encoding
.UTF8
.GetBytes(dirName
));
756 System
.Text
.StringBuilder buf
= new System
.Text
.StringBuilder();
757 buf
.Append("lucene-");
758 for (int i
= 0; i
< digest
.Length
; i
++)
761 buf
.Append(HEX_DIGITS
[(b
>> 4) & 0xf]);
762 buf
.Append(HEX_DIGITS
[b
& 0xf]);
768 /// <summary>Closes the store to future operations. </summary>
769 public override void Close()
775 lock (DIRECTORIES
.SyncRoot
)
777 DIRECTORIES
.Remove(directory
);
783 public virtual System
.IO
.FileInfo
GetFile()
788 /// <summary>For debug output. </summary>
789 public override System
.String
ToString()
791 return this.GetType().FullName
+ "@" + directory
;
799 System
.String name
= SupportClass
.AppSettings
.Get("Lucene.Net.FSDirectory.class", typeof(FSDirectory
).FullName
);
800 IMPL
= System
.Type
.GetType(name
);
802 catch (System
.Security
.SecurityException
)
806 IMPL
= System
.Type
.GetType(typeof(FSDirectory
).FullName
);
808 catch (System
.Exception e
)
810 throw new System
.SystemException("cannot load default FSDirectory class: " + e
.ToString());
813 catch (System
.Exception e
)
815 throw new System
.SystemException("cannot load FSDirectory class: " + e
.ToString());
821 DIGESTER
= System
.Security
.Cryptography
.MD5
.Create();
823 catch (System
.Exception e
)
825 throw new System
.SystemException(e
.ToString());
832 public class FSIndexInput
: BufferedIndexInput
, System
.ICloneable
834 private class Descriptor
: System
.IO
.BinaryReader
836 private void InitBlock(FSIndexInput enclosingInstance
)
838 this.enclosingInstance
= enclosingInstance
;
840 private FSIndexInput enclosingInstance
;
841 public FSIndexInput Enclosing_Instance
845 return enclosingInstance
;
849 public long position
;
850 public Descriptor(FSIndexInput enclosingInstance
, System
.IO
.FileInfo file
, System
.IO
.FileAccess mode
)
851 : base(new System
.IO
.FileStream(file
.FullName
, System
.IO
.FileMode
.Open
, mode
, System
.IO
.FileShare
.ReadWrite
))
853 InitBlock(enclosingInstance
);
857 private Descriptor file
= null;
858 internal bool isClone
;
863 get { return (isClone); }
866 public FSIndexInput(System
.IO
.FileInfo path
)
868 file
= new Descriptor(this, path
, System
.IO
.FileAccess
.Read
);
869 length
= file
.BaseStream
.Length
;
872 /// <summary>IndexInput methods </summary>
873 public override void ReadInternal(byte[] b
, int offset
, int len
)
877 long position
= GetFilePointer();
878 if (position
!= file
.position
)
880 file
.BaseStream
.Seek(position
, System
.IO
.SeekOrigin
.Begin
);
881 file
.position
= position
;
886 int i
= file
.Read(b
, offset
+ total
, len
- total
);
888 throw new System
.IO
.IOException("read past EOF");
896 public override void Close()
898 if (!isClone
&& file
!= null)
900 System
.GC
.SuppressFinalize(this);
903 public override void SeekInternal(long position
)
907 public override long Length()
914 Close(); // close the file
917 public override System
.Object
Clone()
919 FSIndexInput clone
= (FSIndexInput
) base.Clone();
920 clone
.isClone
= true;
924 /// <summary>Method used for testing. Returns true if the underlying
925 /// file descriptor is valid.
927 public /*internal*/ virtual bool IsFDValid()
929 if (file
.BaseStream
== null)
931 return file
.BaseStream
.CanRead
;
936 class FSIndexOutput
: BufferedIndexOutput
938 internal System
.IO
.BinaryWriter file
= null;
940 public FSIndexOutput(System
.IO
.FileInfo path
)
942 file
= new System
.IO
.BinaryWriter(new System
.IO
.FileStream(path
.FullName
, System
.IO
.FileMode
.OpenOrCreate
, System
.IO
.FileAccess
.Write
, System
.IO
.FileShare
.ReadWrite
));
945 /// <summary>output methods: </summary>
946 public override void FlushBuffer(byte[] b
, int size
)
948 file
.Write(b
, 0, size
);
950 public override void Close()
954 System
.GC
.SuppressFinalize(this);
957 /// <summary>Random-access methods </summary>
958 public override void Seek(long pos
)
961 file
.BaseStream
.Seek(pos
, System
.IO
.SeekOrigin
.Begin
);
963 public override long Length()
965 return file
.BaseStream
.Length
;
970 file
.Close(); // close the file