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.
17 using Mono
.Unix
.Native
;
18 using Constants
= Lucene
.Net
.Util
.Constants
;
19 namespace Lucene
.Net
.Store
22 /// <summary> Straightforward implementation of {@link Directory} as a directory of files.
23 /// <p>If the system property 'disableLuceneLocks' has the String value of
24 /// "true", lock creation will be disabled.
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
.DISABLE_LOCKS
|| Enclosing_Instance
.DisableLocks
)
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);
125 Log ("Obtained lock " + lockFile
.FullName
);
130 Log ("Exception in CreateNew for file:" + lockFile
.FullName
+ ":" + e
);
134 public override void Release()
136 if (Lucene
.Net
.Store
.FSDirectory
.DISABLE_LOCKS
|| Enclosing_Instance
.DisableLocks
)
139 if (System
.IO
.File
.Exists(lockFile
.FullName
))
141 System
.IO
.File
.Delete(lockFile
.FullName
);
144 else if (System
.IO
.Directory
.Exists(lockFile
.FullName
))
146 System
.IO
.Directory
.Delete(lockFile
.FullName
);
151 if (System
.IO
.File
.Exists(lockFile
.FullName
)) {
152 Log ("Release didnt delete lockfile {0}.", lockFile
.FullName
);
155 bool generatedAux
= tmpBool
;
157 Log ("Released lock {0}", lockFile
.FullName
);
159 Log ("Failed to release lock {0}", lockFile
.FullName
);
161 public override bool IsLocked()
163 if (Lucene
.Net
.Store
.FSDirectory
.DISABLE_LOCKS
|| Enclosing_Instance
.DisableLocks
)
166 if (System
.IO
.File
.Exists(lockFile
.FullName
))
169 tmpBool
= System
.IO
.Directory
.Exists(lockFile
.FullName
);
173 public override System
.String
ToString()
175 return lockFile
.FullName
;
178 /// <summary>This cache of directories ensures that there is a unique Directory
179 /// instance per path, so that synchronization on the Directory can be used to
180 /// synchronize access between readers and writers.
182 /// This should be a WeakHashMap, so that entries can be GC'd, but that would
183 /// require Java 1.2. Instead we use refcounts...
185 private static readonly System
.Collections
.Hashtable DIRECTORIES
= System
.Collections
.Hashtable
.Synchronized(new System
.Collections
.Hashtable());
187 private static readonly bool DISABLE_LOCKS
;
189 /// <summary> Directory specified by <code>Lucene.Net.lockdir</code>
190 /// or <code>java.io.tmpdir</code> system property
192 public static readonly System
.String LOCK_DIR
= SupportClass
.AppSettings
.Get("Lucene.Net.lockdir", System
.IO
.Path
.GetTempPath());
194 /// <summary>The default class which implements filesystem-based directories. </summary>
195 private static System
.Type IMPL
;
197 private static System
.Security
.Cryptography
.MD5 DIGESTER
;
199 private bool disable_locks
= false;
200 public bool DisableLocks
{
201 get { return disable_locks; }
202 set { disable_locks = value; }
205 /// <summary>A buffer optionally used in renameTo method </summary>
206 private byte[] buffer
= null;
208 /// <summary>Returns the directory instance for the named location.
210 /// <p>Directories are cached, so that, for a given canonical path, the same
211 /// FSDirectory instance will always be returned. This permits
212 /// synchronization on directories.
215 /// <param name="path">the path to the directory.
217 /// <param name="create">if true, create, or erase any existing contents.
219 /// <returns> the FSDirectory for the named file.
221 public static FSDirectory
GetDirectory(System
.String path
, bool create
)
223 return GetDirectory(new System
.IO
.FileInfo(path
), null, create
, false);
226 /// <summary>Returns the directory instance for the named location.
228 /// <p>Directories are cached, so that, for a given canonical path, the same
229 /// FSDirectory instance will always be returned. This permits
230 /// synchronization on directories.
233 /// <param name="file">the path to the directory.
235 /// <param name="create">if true, create, or erase any existing contents.
237 /// <returns> the FSDirectory for the named file.
239 public static FSDirectory
GetDirectory(System
.IO
.FileInfo file
, bool create
)
241 return GetDirectory(file
, null, create
, false);
244 /// <summary>Returns the directory instance for the named location.
246 /// <p>Directories are cached, so that, for a given canonical path, the same
247 /// FSDirectory instance will always be returned. This permits
248 /// synchronization on directories.
251 /// <param name="path">the path to the directory.
253 /// <param name="tmpDir">the path to use as lock directory.
255 /// <param name="create">if true, create, or erase any existing contents.
257 /// <returns> the FSDirectory for the named file.
259 public static FSDirectory
GetDirectory(System
.String path
, System
.String tmpDir
, bool create
)
261 return GetDirectory(new System
.IO
.FileInfo(path
), tmpDir
, create
, false);
264 /// <summary>Returns the directory instance for the named location.
266 /// <p>Directories are cached, so that, for a given canonical path, the same
267 /// FSDirectory instance will always be returned. This permits
268 /// synchronization on directories.
271 /// <param name="path">the path to the directory.
273 /// <param name="tmpDir">the path to use as lock directory.
275 /// <param name="create">if true, create, or erase any existing contents.
277 /// <param name="disable_locks">if true, disable internal locking
279 /// <returns> the FSDirectory for the named file.
281 public static FSDirectory
GetDirectory(System
.String path
, System
.String tmpDir
, bool create
, bool disable_locks
)
283 return GetDirectory(new System
.IO
.FileInfo(path
), tmpDir
, create
, disable_locks
);
286 /// <summary>Returns the directory instance for the named location.
288 /// <p>Directories are cached, so that, for a given canonical path, the same
289 /// FSDirectory instance will always be returned. This permits
290 /// synchronization on directories.
293 /// <param name="file">the path to the directory.
295 /// <param name="tmpDir">the path to use as lock directory.
297 /// <param name="create">if true, create, or erase any existing contents.
299 /// <param name="disable_locks">if true, disable internal locking
301 /// <returns> the FSDirectory for the named file.
303 public static FSDirectory
GetDirectory(System
.IO
.FileInfo file
, System
.String tmpdir
, bool create
, bool disable_locks
)
305 file
= new System
.IO
.FileInfo(file
.FullName
);
307 lock (DIRECTORIES
.SyncRoot
)
309 dir
= (FSDirectory
) DIRECTORIES
[file
];
314 dir
= (FSDirectory
) System
.Activator
.CreateInstance(IMPL
);
316 catch (System
.Exception e
)
318 throw new System
.SystemException("cannot load FSDirectory class: " + e
.ToString());
320 dir
.Init(file
, tmpdir
, create
, disable_locks
);
321 DIRECTORIES
[file
] = dir
;
335 private System
.IO
.FileInfo directory
= null;
336 private int refCount
;
337 private System
.IO
.FileInfo lockDir
;
343 // permit subclassing
345 private void Init(System
.IO
.FileInfo path
, System
.String tmpDir
, bool create
, bool disable_locks
)
348 this.disable_locks
= disable_locks
;
352 lockDir
= new System
.IO
.FileInfo(tmpDir
);
354 else if (LOCK_DIR
== null)
360 lockDir
= new System
.IO
.FileInfo(LOCK_DIR
);
367 if (!System
.IO
.Directory
.Exists(directory
.FullName
))
368 throw new System
.IO
.IOException(path
+ " not a directory");
371 private void Create()
376 if (System
.IO
.File
.Exists(directory
.FullName
))
379 tmpBool
= System
.IO
.Directory
.Exists(directory
.FullName
);
384 System
.IO
.Directory
.CreateDirectory(directory
.FullName
);
388 throw new System
.IO
.IOException("Cannot create directory: " + directory
);
392 System
.String
[] files
= System
.IO
.Directory
.GetFileSystemEntries(directory
.FullName
); // clear old files
393 for (int i
= 0; i
< files
.Length
; i
++)
395 System
.IO
.FileInfo file
= new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
.FullName
, files
[i
]));
397 if (System
.IO
.File
.Exists(file
.FullName
))
399 System
.IO
.File
.Delete(file
.FullName
);
402 else if (System
.IO
.Directory
.Exists(file
.FullName
))
404 System
.IO
.Directory
.Delete(file
.FullName
);
410 throw new System
.IO
.IOException("Cannot delete " + files
[i
]);
413 System
.String lockPrefix
= GetLockPrefix().ToString(); // clear old locks
414 files
= System
.IO
.Directory
.GetFileSystemEntries(lockDir
.FullName
);
415 for (int i
= 0; i
< files
.Length
; i
++)
417 if (!files
[i
].StartsWith(lockPrefix
))
419 System
.IO
.FileInfo lockFile
= new System
.IO
.FileInfo(System
.IO
.Path
.Combine(lockDir
.FullName
, files
[i
]));
421 if (System
.IO
.File
.Exists(lockFile
.FullName
))
423 System
.IO
.File
.Delete(lockFile
.FullName
);
426 else if (System
.IO
.Directory
.Exists(lockFile
.FullName
))
428 System
.IO
.Directory
.Delete(lockFile
.FullName
);
434 throw new System
.IO
.IOException("Cannot delete " + files
[i
]);
439 /// <summary>Returns an array of strings, one for each file in the directory. </summary>
440 public override System
.String
[] List()
442 return System
.IO
.Directory
.GetFileSystemEntries(directory
.FullName
);
445 /// <summary>Returns true iff a file with the given name exists. </summary>
446 public override bool FileExists(System
.String name
)
448 string path
= System
.IO
.Path
.Combine (directory
.FullName
, name
);
450 return System
.IO
.File
.Exists (path
) || System
.IO
.Directory
.Exists (path
);
453 /// <summary>Returns the time the named file was last modified. </summary>
454 public override long FileModified(System
.String name
)
456 System
.IO
.FileInfo file
= new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
.FullName
, name
));
457 return (file
.LastWriteTimeUtc
.Ticks
);
460 /// <summary>Returns the time the named file was last modified. </summary>
461 public static long FileModified(System
.IO
.FileInfo directory
, System
.String name
)
463 System
.IO
.FileInfo file
= new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
.FullName
, name
));
464 return (file
.LastWriteTimeUtc
.Ticks
);
467 /// <summary>Set the modified time of an existing file to now. </summary>
468 public override void TouchFile(System
.String name
)
470 System
.IO
.FileInfo file
= new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
.FullName
, name
));
471 file
.LastWriteTime
= System
.DateTime
.UtcNow
;
474 /// <summary>Returns the length in bytes of a file in the directory. </summary>
475 public override long FileLength(System
.String name
)
477 System
.IO
.FileInfo file
= new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
.FullName
, name
));
478 return file
.Exists
? file
.Length
: 0;
481 /// <summary>Removes an existing file in the directory. </summary>
482 public override void DeleteFile(System
.String name
)
484 System
.IO
.FileInfo file
= new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
.FullName
, name
));
486 if (System
.IO
.File
.Exists(file
.FullName
))
488 System
.IO
.File
.Delete(file
.FullName
);
491 else if (System
.IO
.Directory
.Exists(file
.FullName
))
493 System
.IO
.Directory
.Delete(file
.FullName
);
499 throw new System
.IO
.IOException("Cannot delete " + name
);
502 /// <summary>Renames an existing file in the directory. </summary>
503 public override void RenameFile(System
.String
from, System
.String to
)
507 System
.IO
.FileInfo old
= new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
.FullName
, from));
508 System
.IO
.FileInfo nu
= new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
.FullName
, to
));
510 /* This is not atomic. If the program crashes between the call to
511 delete() and the call to renameTo() then we're screwed, but I've
512 been unable to figure out how else to do this... */
515 if (System
.IO
.File
.Exists(nu
.FullName
))
518 tmpBool
= System
.IO
.Directory
.Exists(nu
.FullName
);
522 if (System
.IO
.File
.Exists(nu
.FullName
))
524 System
.IO
.File
.Delete(nu
.FullName
);
527 else if (System
.IO
.Directory
.Exists(nu
.FullName
))
529 System
.IO
.Directory
.Delete(nu
.FullName
);
535 throw new System
.IO
.IOException("Cannot delete " + to
);
538 // Rename the old file to the new one. Unfortunately, the renameTo()
539 // method does not work reliably under some JVMs. Therefore, if the
540 // rename fails, we manually rename by copying the old file to the new one
543 old
.MoveTo(nu
.FullName
);
545 catch (System
.Exception ex
)
547 System
.IO
.BinaryReader in_Renamed
= null;
548 System
.IO
.Stream out_Renamed
= null;
551 in_Renamed
= new System
.IO
.BinaryReader(System
.IO
.File
.Open(old
.FullName
, System
.IO
.FileMode
.Open
, System
.IO
.FileAccess
.Read
));
552 out_Renamed
= new System
.IO
.FileStream(nu
.FullName
, System
.IO
.FileMode
.Create
, System
.IO
.FileAccess
.Write
, System
.IO
.FileShare
.ReadWrite
);
553 // see if the buffer needs to be initialized. Initialization is
554 // only done on-demand since many VM's will never run into the renameTo
555 // bug and hence shouldn't waste 1K of mem for no reason.
558 buffer
= new byte[1024];
561 len
= in_Renamed
.Read(buffer
, 0, buffer
.Length
);
562 out_Renamed
.Write(buffer
, 0, len
);
564 // delete the old file.
566 if (System
.IO
.File
.Exists(old
.FullName
))
568 System
.IO
.File
.Delete(old
.FullName
);
571 else if (System
.IO
.Directory
.Exists(old
.FullName
))
573 System
.IO
.Directory
.Delete(old
.FullName
);
578 bool generatedAux
= tmpBool3
;
580 catch (System
.IO
.IOException e
)
582 throw new System
.IO
.IOException("Cannot rename " + from + " to " + to
);
586 if (in_Renamed
!= null)
592 catch (System
.IO
.IOException e
)
594 throw new System
.SystemException("Cannot close input stream: " + e
.ToString());
597 if (out_Renamed
!= null)
603 catch (System
.IO
.IOException e
)
605 throw new System
.SystemException("Cannot close output stream: " + e
.ToString());
613 /// <summary>Creates a new, empty file in the directory with the given name.
614 /// Returns a stream writing this file.
616 public override IndexOutput
CreateOutput(System
.String name
)
618 return new FSIndexOutput(new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
.FullName
, name
)));
621 /// <summary>Returns a stream reading an existing file. </summary>
622 public override IndexInput
OpenInput(System
.String name
)
624 return new FSIndexInput(new System
.IO
.FileInfo(System
.IO
.Path
.Combine(directory
.FullName
, name
)));
627 static public Beagle
.Util
.Logger Logger
= null;
628 //static public Beagle.Util.Logger Logger = Beagle.Util.Logger.Log;
629 static public void Log (string format
, params object[] args
)
632 Logger
.Debug (format
, args
);
635 static public void Log (Exception e
)
641 /// <summary> So we can do some byte-to-hexchar conversion below</summary>
642 private static readonly char[] HEX_DIGITS
= new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}
;
644 /// <summary>Constructs a {@link Lock} with the specified name. Locks are implemented
645 /// with {@link File#createNewFile() }.
647 /// <p>In JDK 1.1 or if system property <I>disableLuceneLocks</I> is the
648 /// string "true", locks are disabled. Assigning this property any other
649 /// string will <B>not</B> prevent creation of lock files. This is useful for
650 /// using Lucene on read-only medium, such as CD-ROM.
653 /// <param name="name">the name of the lock file
655 /// <returns> an instance of <code>Lock</code> holding the lock
657 public override Lock
MakeLock(System
.String name
)
659 System
.Text
.StringBuilder buf
= GetLockPrefix();
663 // create a lock file
664 System
.IO
.FileInfo lockFile
= new System
.IO
.FileInfo(System
.IO
.Path
.Combine(lockDir
.FullName
, buf
.ToString()));
666 return new AnonymousClassLock(lockFile
, this);
669 private System
.Text
.StringBuilder
GetLockPrefix()
671 System
.String dirName
; // name to be hashed
674 dirName
= directory
.FullName
;
676 catch (System
.IO
.IOException e
)
678 throw new System
.SystemException(e
.ToString());
684 digest
= DIGESTER
.ComputeHash(System
.Text
.Encoding
.UTF8
.GetBytes(dirName
));
686 System
.Text
.StringBuilder buf
= new System
.Text
.StringBuilder();
687 buf
.Append("lucene-");
688 for (int i
= 0; i
< digest
.Length
; i
++)
691 buf
.Append(HEX_DIGITS
[(b
>> 4) & 0xf]);
692 buf
.Append(HEX_DIGITS
[b
& 0xf]);
698 /// <summary>Closes the store to future operations. </summary>
699 public override void Close()
705 lock (DIRECTORIES
.SyncRoot
)
707 DIRECTORIES
.Remove(directory
);
713 public virtual System
.IO
.FileInfo
GetFile()
718 /// <summary>For debug output. </summary>
719 public override System
.String
ToString()
721 return this.GetType().FullName
+ "@" + directory
;
725 DISABLE_LOCKS
= System
.Configuration
.ConfigurationSettings
.AppSettings
.Get("disableLuceneLocks") != null;
729 System
.String name
= SupportClass
.AppSettings
.Get("Lucene.Net.FSDirectory.class", typeof(FSDirectory
).FullName
);
730 IMPL
= System
.Type
.GetType(name
);
732 catch (System
.Exception e
)
734 throw new System
.SystemException("cannot load FSDirectory class: " + e
.ToString());
740 DIGESTER
= System
.Security
.Cryptography
.MD5
.Create();
742 catch (System
.Exception e
)
744 throw new System
.SystemException(e
.ToString());
751 public class FSIndexInput
: BufferedIndexInput
, System
.ICloneable
753 private class Descriptor
: System
.IO
.BinaryReader
755 private void InitBlock(FSIndexInput enclosingInstance
)
757 this.enclosingInstance
= enclosingInstance
;
759 private FSIndexInput enclosingInstance
;
760 public FSIndexInput Enclosing_Instance
764 return enclosingInstance
;
768 public long position
;
769 // {{Aroush-1.4.3 is this right?
770 public Descriptor(FSIndexInput enclosingInstance
, System
.IO
.FileInfo file
, System
.IO
.FileAccess fileAccess
)
771 : base(new System
.IO
.FileStream(file
.FullName
, System
.IO
.FileMode
.Open
, fileAccess
, System
.IO
.FileShare
.ReadWrite
))
773 InitBlock(enclosingInstance
);
778 //public void close() throws IOException {
779 // debug_printInfo("CLOSE");
783 //private void debug_printInfo(String op) {
784 // try { throw new Exception(op + " <" + name + ">");
785 // } catch (Exception e) {
786 // java.io.StringWriter sw = new java.io.StringWriter();
787 // java.io.PrintWriter pw = new java.io.PrintWriter(sw);
788 // e.printStackTrace(pw);
789 // System.out.println(sw.getBuffer().ToString());
795 private Descriptor file
= null;
796 internal bool isClone
;
799 public FSIndexInput(System
.IO
.FileInfo path
)
801 file
= new Descriptor(this, path
, System
.IO
.FileAccess
.Read
);
802 length
= file
.BaseStream
.Length
;
805 /// <summary>InputStream methods </summary>
806 public override void ReadInternal(byte[] b
, int offset
, int len
)
810 long position
= GetFilePointer();
811 if (position
!= file
.position
)
813 file
.BaseStream
.Seek(position
, System
.IO
.SeekOrigin
.Begin
);
814 file
.position
= position
;
819 int i
= file
.Read(b
, offset
+ total
, len
- total
);
821 throw new System
.IO
.IOException("read past EOF");
829 public override void Close()
831 if (!isClone
&& file
!= null)
833 System
.GC
.SuppressFinalize(this);
836 /// <summary>Random-access methods </summary>
837 public override void SeekInternal(long position
)
841 public override long Length()
848 Close(); // close the file
851 public override System
.Object
Clone()
853 FSIndexInput clone
= (FSIndexInput
) base.Clone();
854 clone
.isClone
= true;
858 /// <summary>Method used for testing. Returns true if the underlying
859 /// file descriptor is valid.
861 public /*internal*/ virtual bool IsFDValid()
863 return file
.BaseStream
.CanRead
;
868 class FSIndexOutput
: BufferedIndexOutput
870 internal System
.IO
.BinaryWriter file
= null;
872 public FSIndexOutput(System
.IO
.FileInfo path
)
874 file
= new System
.IO
.BinaryWriter(new System
.IO
.FileStream(path
.FullName
, System
.IO
.FileMode
.OpenOrCreate
, System
.IO
.FileAccess
.Write
, System
.IO
.FileShare
.ReadWrite
));
877 /// <summary>output methods: </summary>
878 public override void FlushBuffer(byte[] b
, int size
)
880 file
.Write(b
, 0, size
);
882 public override void Close()
886 System
.GC
.SuppressFinalize(this);
889 /// <summary>Random-access methods </summary>
890 public override void Seek(long pos
)
893 file
.BaseStream
.Seek(pos
, System
.IO
.SeekOrigin
.Begin
);
895 public override long Length()
897 return file
.BaseStream
.Length
;
902 file
.Close(); // close the file