Thumbnail file hits. Based on a patch from D Bera
[beagle.git] / beagled / Lucene.Net / Store / FSDirectory.cs
blob4edf84f4d74c2a81f195a49b80aea777981cc9fc
1 /*
2 * Copyright 2004 The Apache Software Foundation
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
16 using System;
17 using Constants = Lucene.Net.Util.Constants;
18 using System.Diagnostics; // FIXED joeshaw@novell.com 10 Jan 2005 - for lock debugging
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.
25 ///
26 /// </summary>
27 /// <seealso cref="Directory">
28 /// </seealso>
29 /// <author> Doug Cutting
30 /// </author>
31 public sealed 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
48 get
50 return enclosingInstance;
54 public override bool Obtain()
56 if (Lucene.Net.Store.FSDirectory.DISABLE_LOCKS)
57 return true;
59 // ADDED fhedberg@novell.com 16 Jun 2005
60 if (Enclosing_Instance.DisableLocks)
61 return true;
63 bool tmpBool;
64 if (System.IO.File.Exists(Enclosing_Instance.lockDir.FullName))
65 tmpBool = true;
66 else
67 tmpBool = System.IO.Directory.Exists(Enclosing_Instance.lockDir.FullName);
68 if (!tmpBool)
70 try
72 System.IO.Directory.CreateDirectory(Enclosing_Instance.lockDir.FullName);
74 catch (Exception)
76 throw new System.IO.IOException("Cannot create lock directory: " + Enclosing_Instance.lockDir);
80 // ADDED trow@novell.com 17 Mar 2005: Use Mono.Posix for lock creation
82 bool obtainedLock = false;
84 int fd = Mono.Posix.Syscall.open (lockFile.FullName,
85 Mono.Posix.OpenFlags.O_CREAT
86 | Mono.Posix.OpenFlags.O_EXCL,
87 Mono.Posix.FileMode.S_IRUSR
88 | Mono.Posix.FileMode.S_IWUSR);
90 if (fd != -1) {
91 Mono.Posix.Syscall.close (fd);
92 lockFile.Refresh ();
93 obtainedLock = true;
97 #if false
98 try
100 System.IO.FileStream createdFile = lockFile.Create();
101 createdFile.Close();
102 obtainedLock = true;
104 catch (Exception e)
106 // Just fall through
108 #endif
110 Log ("{0} lock {1}", obtainedLock ? "Obtained" : "Could not obtain", lockFile.FullName);
111 return obtainedLock;
114 public override void Release()
116 if (Lucene.Net.Store.FSDirectory.DISABLE_LOCKS)
117 return ;
119 // ADDED fhedberg@novell.com 16 Jun 2005 - disable locks per directory
120 if (Enclosing_Instance.DisableLocks)
121 return;
123 bool tmpBool;
124 if (System.IO.File.Exists(lockFile.FullName))
126 System.IO.File.Delete(lockFile.FullName);
127 tmpBool = true;
129 else if (System.IO.Directory.Exists(lockFile.FullName))
131 System.IO.Directory.Delete(lockFile.FullName);
132 tmpBool = true;
134 else
135 tmpBool = false;
137 // ADDED joeshaw@novell.com 10 Jan 2005 - lock debugging
138 if (tmpBool)
139 Log ("Released lock {0}", lockFile.FullName);
140 else
141 Log ("Failed to release lock {0}", lockFile.FullName);
143 public override bool IsLocked()
145 if (Lucene.Net.Store.FSDirectory.DISABLE_LOCKS)
146 return false;
148 // ADDED fhedberg@novell.com 16 Jun 2005 - disable locks per directory
149 if (Enclosing_Instance.DisableLocks)
150 return false;
152 bool tmpBool;
153 if (System.IO.File.Exists(lockFile.FullName))
154 tmpBool = true;
155 else
156 tmpBool = System.IO.Directory.Exists(lockFile.FullName);
157 return tmpBool;
160 public override System.String ToString()
162 return "Lock@" + lockFile;
165 /// <summary>This cache of directories ensures that there is a unique Directory
166 /// instance per path, so that synchronization on the Directory can be used to
167 /// synchronize access between readers and writers.
168 ///
169 /// This should be a WeakHashMap, so that entries can be GC'd, but that would
170 /// require Java 1.2. Instead we use refcounts...
171 /// </summary>
172 private static readonly System.Collections.Hashtable DIRECTORIES = System.Collections.Hashtable.Synchronized(new System.Collections.Hashtable());
174 private static readonly bool DISABLE_LOCKS;
176 /// <summary>
177 /// Get the name of the directory to use for temporary files,
178 /// and create that directory if it doesn't already exist
179 /// </summary>
180 /// FIXED trow@ximian.com 14 May 2004 Give us control over where locks are stored
181 /// FIXED trow@ximian.com 12 Sep 2004 make TempDirectoryName not be static
182 private String tempDirectoryName = null;
183 public String TempDirectoryName {
184 get {
185 if (tempDirectoryName == null) {
186 String user_name = Environment.GetEnvironmentVariable("USER");
187 if (user_name == null)
188 user_name = "unknown";
189 TempDirectoryName = "/tmp/" + user_name + "-lucene.net";
191 return tempDirectoryName;
194 set {
195 tempDirectoryName = value;
196 if (! System.IO.Directory.Exists (tempDirectoryName))
197 System.IO.Directory.CreateDirectory (tempDirectoryName);
201 // ADDED fhedberg@novell.com 16 Jun 2005 - disable locks per directory
203 private bool disable_locks = false;
205 public bool DisableLocks {
206 get { return disable_locks; }
207 set { disable_locks = value; }
210 private static System.Security.Cryptography.MD5 DIGESTER;
212 /// <summary>A buffer optionally used in renameTo method </summary>
213 private byte[] buffer = null;
215 /// <summary>Returns the directory instance for the named location.
216 ///
217 /// <p>Directories are cached, so that, for a given canonical path, the same
218 /// FSDirectory instance will always be returned. This permits
219 /// synchronization on directories.
220 ///
221 /// </summary>
222 /// <param name="path">the path to the directory.
223 /// </param>
224 /// <param name="create">if true, create, or erase any existing contents.
225 /// </param>
226 /// <returns> the FSDirectory for the named file.
227 /// </returns>
229 /// CHANGED trow@novell.com 17 Mar 2005 set tmp dir at creation-time
230 /// CHANGED fhedberg@novell.com 16 Jun 2005 - disable locks per directory
231 public static FSDirectory GetDirectory(System.String path, System.String tmpDir, bool create)
233 return GetDirectory(new System.IO.FileInfo(path), tmpDir, create, false);
236 // ADDED fhedberg@novell.com 16 Jun 2005 - disable locks per directory
237 public static FSDirectory GetDirectory(System.String path, System.String tmpDir, bool create, bool disable_locks)
239 return GetDirectory(new System.IO.FileInfo(path), tmpDir, create, disable_locks);
242 // CHANGED fhedberg@novell.com 16 Jun 2005 - disable locks per directory
243 public static FSDirectory GetDirectory(System.String path, bool create)
245 return GetDirectory(new System.IO.FileInfo(path), null, create, false);
248 /// <summary>Returns the directory instance for the named location.
249 ///
250 /// <p>Directories are cached, so that, for a given canonical path, the same
251 /// FSDirectory instance will always be returned. This permits
252 /// synchronization on directories.
253 ///
254 /// </summary>
255 /// <param name="file">the path to the directory.
256 /// </param>
257 /// <param name="create">if true, create, or erase any existing contents.
258 /// </param>
259 /// <returns> the FSDirectory for the named file.
260 /// </returns>
261 /// CHANGED fhedberg@novell.com 16 Jun 2005 - disable locks per directory
262 public static FSDirectory GetDirectory(System.IO.FileInfo file, System.String tmpDir, bool create, bool disable_locks)
264 file = new System.IO.FileInfo(file.FullName);
265 FSDirectory dir;
266 lock (DIRECTORIES.SyncRoot)
268 dir = (FSDirectory) DIRECTORIES[file];
269 if (dir == null)
271 // CHANGED fhedberg@novell.com 16 Jun 2005 - disable locks per directory
272 dir = new FSDirectory(file, tmpDir, create, disable_locks);
273 DIRECTORIES[file] = dir;
275 else if (create)
277 dir.Create();
280 lock (dir)
282 dir.refCount++;
284 return dir;
287 // CHANGED fhedberg@novell.com 16 Jun 2005 - disable locks per directory
288 public static FSDirectory GetDirectory(System.IO.FileInfo file, bool create)
290 return GetDirectory (file, null, create, false);
293 private System.IO.FileInfo directory = null;
294 private int refCount;
295 private System.IO.FileInfo lockDir;
297 /// CHANGED fhedberg@novell.com 16 Jun 2005 - disable locks per directory
298 private FSDirectory(System.IO.FileInfo path, string tmpDir, bool create, bool disable_locks)
300 directory = path;
301 this.disable_locks = disable_locks;
303 // FIXED joeshaw@novell.com 10 Jan 2005 Use TempDirectoryName to find where locks live
304 // FIXED trow@novell.com 17 Mar 2005 A fix on the fix
305 if (tmpDir != null)
306 TempDirectoryName = tmpDir;
307 lockDir = new System.IO.FileInfo (TempDirectoryName);
308 if (create)
310 Create();
313 if (!System.IO.Directory.Exists(directory.FullName))
314 throw new System.IO.IOException(path + " not a directory");
317 private void Create()
319 lock (this)
321 bool tmpBool;
322 if (System.IO.File.Exists(directory.FullName))
323 tmpBool = true;
324 else
325 tmpBool = System.IO.Directory.Exists(directory.FullName);
326 if (!tmpBool)
330 System.IO.Directory.CreateDirectory(directory.FullName);
332 catch (Exception)
334 throw new System.IO.IOException("Cannot create directory: " + directory);
338 System.String[] files = System.IO.Directory.GetFileSystemEntries(directory.FullName); // clear old files
339 for (int i = 0; i < files.Length; i++)
341 System.IO.FileInfo file = new System.IO.FileInfo(files[i]);
342 bool tmpBool2;
343 if (System.IO.File.Exists(file.FullName))
345 System.IO.File.Delete(file.FullName);
346 tmpBool2 = true;
348 else if (System.IO.Directory.Exists(file.FullName))
350 System.IO.Directory.Delete(file.FullName);
351 tmpBool2 = true;
353 else
354 tmpBool2 = false;
355 if (!tmpBool2)
356 throw new System.IO.IOException("Cannot delete " + files[i]);
359 System.String lockPrefix = GetLockPrefix().ToString(); // clear old locks
360 files = System.IO.Directory.GetFileSystemEntries(lockDir.FullName);
361 for (int i = 0; i < files.Length; i++)
363 if (!files[i].StartsWith(lockPrefix))
364 continue;
365 System.IO.FileInfo lockFile = new System.IO.FileInfo(System.IO.Path.Combine(lockDir.FullName, files[i]));
366 bool tmpBool3;
367 if (System.IO.File.Exists(lockFile.FullName))
369 System.IO.File.Delete(lockFile.FullName);
370 tmpBool3 = true;
372 else if (System.IO.Directory.Exists(lockFile.FullName))
374 System.IO.Directory.Delete(lockFile.FullName);
375 tmpBool3 = true;
377 else
378 tmpBool3 = false;
379 if (!tmpBool3)
380 throw new System.IO.IOException("Cannot delete " + files[i]);
385 /// <summary>Returns an array of strings, one for each file in the directory. </summary>
386 public override System.String[] List()
388 return System.IO.Directory.GetFileSystemEntries(directory.FullName);
391 /// <summary>Returns true iff a file with the given name exists. </summary>
392 public override bool FileExists(System.String name)
394 System.IO.FileInfo file = new System.IO.FileInfo(System.IO.Path.Combine(directory.FullName, name));
395 bool tmpBool;
396 if (System.IO.File.Exists(file.FullName))
397 tmpBool = true;
398 else
399 tmpBool = System.IO.Directory.Exists(file.FullName);
400 return tmpBool;
403 /// <summary>Returns the time the named file was last modified. </summary>
404 public override long FileModified(System.String name)
406 // FIXED joeshaw@novell.com 24 Jun 2005 - Use UTC
407 System.IO.FileInfo file = new System.IO.FileInfo(System.IO.Path.Combine(directory.FullName, name));
408 return ((file.LastWriteTimeUtc.Ticks - 621355968000000000) / 10000);
411 /// <summary>Returns the time the named file was last modified. </summary>
412 public static long FileModified(System.IO.FileInfo directory, System.String name)
414 // FIXED joeshaw@novell.com 24 Jun 2005 - Use UTC
415 System.IO.FileInfo file = new System.IO.FileInfo(System.IO.Path.Combine(directory.FullName, name));
416 return ((file.LastWriteTimeUtc.Ticks - 621355968000000000) / 10000);
419 /// <summary>Set the modified time of an existing file to now. </summary>
420 public override void TouchFile(System.String name)
422 // FIXED joeshaw@novell.com 24 Jun 2005 - Use UTC
423 System.IO.FileInfo file = new System.IO.FileInfo(System.IO.Path.Combine(directory.FullName, name));
424 file.LastWriteTimeUtc = System.DateTime.UtcNow;
427 /// <summary>Returns the length in bytes of a file in the directory. </summary>
428 public override long FileLength(System.String name)
430 System.IO.FileInfo file = new System.IO.FileInfo(System.IO.Path.Combine(directory.FullName, name));
431 return file.Exists ? file.Length : 0;
434 /// <summary>Removes an existing file in the directory. </summary>
435 public override void DeleteFile(System.String name)
437 System.IO.FileInfo file = new System.IO.FileInfo(System.IO.Path.Combine(directory.FullName, name));
438 bool tmpBool;
439 if (System.IO.File.Exists(file.FullName))
441 System.IO.File.Delete(file.FullName);
442 tmpBool = true;
444 else if (System.IO.Directory.Exists(file.FullName))
446 System.IO.Directory.Delete(file.FullName);
447 tmpBool = true;
449 else
450 tmpBool = false;
451 if (!tmpBool)
452 throw new System.IO.IOException("Cannot delete " + name);
455 /// <summary>Renames an existing file in the directory. </summary>
456 public override void RenameFile(System.String from, System.String to)
458 lock (this)
460 System.IO.FileInfo old = new System.IO.FileInfo(System.IO.Path.Combine(directory.FullName, from));
461 System.IO.FileInfo nu = new System.IO.FileInfo(System.IO.Path.Combine(directory.FullName, to));
463 /* This is not atomic. If the program crashes between the call to
464 delete() and the call to renameTo() then we're screwed, but I've
465 been unable to figure out how else to do this... */
467 bool tmpBool;
468 if (System.IO.File.Exists(nu.FullName))
469 tmpBool = true;
470 else
471 tmpBool = System.IO.Directory.Exists(nu.FullName);
472 if (tmpBool)
474 bool tmpBool2;
475 if (System.IO.File.Exists(nu.FullName))
477 System.IO.File.Delete(nu.FullName);
478 tmpBool2 = true;
480 else if (System.IO.Directory.Exists(nu.FullName))
482 System.IO.Directory.Delete(nu.FullName);
483 tmpBool2 = true;
485 else
486 tmpBool2 = false;
487 if (!tmpBool2)
488 throw new System.IO.IOException("Cannot delete " + to);
491 // Rename the old file to the new one. Unfortunately, the renameTo()
492 // method does not work reliably under some JVMs. Therefore, if the
493 // rename fails, we manually rename by copying the old file to the new one
496 old.MoveTo(nu.FullName);
498 catch (System.Exception ex)
500 System.IO.BinaryReader in_Renamed = null;
501 System.IO.Stream out_Renamed = null;
504 in_Renamed = new System.IO.BinaryReader(System.IO.File.Open(old.FullName, System.IO.FileMode.Open, System.IO.FileAccess.Read));
505 // FIXED trow@novell.com 18 Jul 2005
506 // Open the FileStream w/ FileShare.ReadWrite.
507 out_Renamed = new System.IO.FileStream(nu.FullName, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite);
508 // see if the buffer needs to be initialized. Initialization is
509 // only done on-demand since many VM's will never run into the renameTo
510 // bug and hence shouldn't waste 1K of mem for no reason.
511 if (buffer == null)
513 buffer = new byte[1024];
515 int len;
516 len = in_Renamed.Read(buffer, 0, buffer.Length);
517 out_Renamed.Write(buffer, 0, len);
519 // FIXED trow@novell.com 18 Feb 2005
520 // Commented out unused variables tmpBool3 and generatedAux
521 // to avoid compiler warnings
523 // delete the old file.
524 // bool tmpBool3;
525 if (System.IO.File.Exists(old.FullName))
527 System.IO.File.Delete(old.FullName);
528 // tmpBool3 = true;
530 else if (System.IO.Directory.Exists(old.FullName))
532 System.IO.Directory.Delete(old.FullName);
533 // tmpBool3 = true;
535 //else
536 //tmpBool3 = false;
537 //bool generatedAux = tmpBool3;
539 catch (System.IO.IOException e)
541 throw new System.IO.IOException("Cannot rename " + from + " to " + to);
543 finally
545 if (in_Renamed != null)
549 in_Renamed.Close();
551 catch (System.IO.IOException e)
553 throw new System.SystemException("Cannot close input stream: " + e.Message);
556 if (out_Renamed != null)
560 out_Renamed.Close();
562 catch (System.IO.IOException e)
564 throw new System.SystemException("Cannot close output stream: " + e.Message);
572 /// <summary>Creates a new, empty file in the directory with the given name.
573 /// Returns a stream writing this file.
574 /// </summary>
575 public override OutputStream CreateFile(System.String name)
577 return new FSOutputStream(new System.IO.FileInfo(System.IO.Path.Combine(directory.FullName, name)));
580 /// <summary>Returns a stream reading an existing file. </summary>
581 public override InputStream OpenFile(System.String name)
583 return new FSInputStream(new System.IO.FileInfo(System.IO.Path.Combine(directory.FullName, name)));
586 // ADDED trow 4 June 2004
587 static public Beagle.Util.Logger Logger = null;
588 //static public Beagle.Util.Logger Logger = Beagle.Util.Logger.Log;
589 static private void Log (string format, params object[] args)
591 if (Logger != null)
592 Logger.Debug (format, args);
594 static private void Log (Exception e)
596 if (Logger != null)
597 Logger.Debug (e);
600 /// <summary> So we can do some byte-to-hexchar conversion below</summary>
601 private static readonly char[] HEX_DIGITS = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
603 /// <summary>Constructs a {@link Lock} with the specified name. Locks are implemented
604 /// with {@link File#createNewFile() }.
605 ///
606 /// <p>In JDK 1.1 or if system property <I>disableLuceneLocks</I> is the
607 /// string "true", locks are disabled. Assigning this property any other
608 /// string will <B>not</B> prevent creation of lock files. This is useful for
609 /// using Lucene on read-only medium, such as CD-ROM.
610 ///
611 /// </summary>
612 /// <param name="name">the name of the lock file
613 /// </param>
614 /// <returns> an instance of <code>Lock</code> holding the lock
615 /// </returns>
616 public override Lock MakeLock(System.String name)
618 System.Text.StringBuilder buf = GetLockPrefix();
619 buf.Append("-");
620 buf.Append(name);
622 // create a lock file
623 System.IO.FileInfo lockFile = new System.IO.FileInfo(System.IO.Path.Combine(lockDir.FullName, buf.ToString()));
625 return new AnonymousClassLock(lockFile, this);
628 private System.Text.StringBuilder GetLockPrefix()
630 System.String dirName; // name to be hashed
633 dirName = directory.FullName;
635 catch (System.IO.IOException e)
637 throw new System.SystemException(e.ToString());
640 byte[] digest;
641 lock (DIGESTER)
643 digest = DIGESTER.ComputeHash(System.Text.Encoding.UTF8.GetBytes(dirName));
645 System.Text.StringBuilder buf = new System.Text.StringBuilder();
646 buf.Append("lucene-");
647 for (int i = 0; i < digest.Length; i++)
649 int b = digest[i];
650 buf.Append(HEX_DIGITS[(b >> 4) & 0xf]);
651 buf.Append(HEX_DIGITS[b & 0xf]);
654 return buf;
657 /// <summary>Closes the store to future operations. </summary>
658 public override void Close()
660 lock (this)
662 if (--refCount <= 0)
664 lock (DIRECTORIES.SyncRoot)
666 DIRECTORIES.Remove(directory);
672 public System.IO.FileInfo GetFile()
674 return directory;
677 /// <summary>For debug output. </summary>
678 public override System.String ToString()
680 return "FSDirectory@" + directory;
682 static FSDirectory()
684 DISABLE_LOCKS = System.Configuration.ConfigurationSettings.AppSettings.Get("disableLuceneLocks") != null;
688 DIGESTER = System.Security.Cryptography.MD5.Create();
690 catch (System.Exception e)
692 throw new System.SystemException(e.ToString());
699 sealed public class FSInputStream : InputStream, System.ICloneable
701 internal class Descriptor : System.IO.BinaryReader
703 private void InitBlock(FSInputStream enclosingInstance)
705 this.enclosingInstance = enclosingInstance;
707 private FSInputStream enclosingInstance;
708 public FSInputStream Enclosing_Instance
712 return enclosingInstance;
716 /* DEBUG */
717 //private String name;
718 /* DEBUG */
719 // {{Aroush
720 public long position;
721 public Descriptor(FSInputStream enclosingInstance, System.IO.FileInfo file, System.IO.FileAccess fileAccess)
722 : base(new System.IO.FileStream(file.FullName, System.IO.FileMode.Open, fileAccess, System.IO.FileShare.ReadWrite))
726 //{{}}// public Descriptor(FSInputStream enclosingInstance, System.IO.FileInfo file, System.String mode) : base(file, mode)
727 //{{}}// {
728 //{{}}// InitBlock(enclosingInstance);
729 //{{}}// /* DEBUG */
730 //{{}}// //name = file.ToString();
731 //{{}}// //debug_printInfo("OPEN");
732 //{{}}// /* DEBUG */
733 //{{}}// }
734 // Aroush}}
736 /* DEBUG */
737 //public void close() throws IOException {
738 // debug_printInfo("CLOSE");
739 // super.close();
742 //private void debug_printInfo(String op) {
743 // try { throw new Exception(op + " <" + name + ">");
744 // } catch (Exception e) {
745 // java.io.StringWriter sw = new java.io.StringWriter();
746 // java.io.PrintWriter pw = new java.io.PrintWriter(sw);
747 // e.printStackTrace(pw);
748 // System.out.println(sw.getBuffer().ToString());
749 // }
751 /* DEBUG */
754 internal Descriptor file = null;
755 public /*internal*/ bool isClone;
757 public FSInputStream(System.IO.FileInfo path)
759 file = new Descriptor(this, path, System.IO.FileAccess.Read);
760 length = file.BaseStream.Length;
763 /// <summary>InputStream methods </summary>
764 public override void ReadInternal(byte[] b, int offset, int len)
766 lock (file)
768 long position = GetFilePointer();
769 if (position != file.position)
771 file.BaseStream.Seek(position, System.IO.SeekOrigin.Begin);
772 file.position = position;
774 int total = 0;
777 int i = file.Read(b, offset + total, len - total);
778 if (i <= 0)
779 throw new System.IO.IOException("read past EOF");
780 file.position += i;
781 total += i;
783 while (total < len);
787 public override void Close()
789 if (!isClone && file != null)
790 file.Close();
791 System.GC.SuppressFinalize(this);
794 /// <summary>Random-access methods </summary>
795 public override void SeekInternal(long position)
799 ~FSInputStream()
801 Close(); // close the file
804 public override System.Object Clone()
806 FSInputStream clone = (FSInputStream) base.Clone();
807 clone.isClone = true;
808 return clone;
811 /// <summary>Method used for testing. Returns true if the underlying
812 /// file descriptor is valid.
813 /// </summary>
814 public /*internal*/ bool IsFDValid()
816 return file.BaseStream.CanRead;
821 sealed class FSOutputStream : OutputStream
823 internal System.IO.BinaryWriter file = null;
825 public FSOutputStream(System.IO.FileInfo path)
827 file = new System.IO.BinaryWriter(new System.IO.FileStream(path.FullName, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write, System.IO.FileShare.ReadWrite));
830 /// <summary>output methods: </summary>
831 public override void FlushBuffer(byte[] b, int size)
833 file.Write(b, 0, size);
835 public override void Close()
837 base.Close();
838 file.Close();
839 System.GC.SuppressFinalize(this);
842 /// <summary>Random-access methods </summary>
843 public override void Seek(long pos)
845 base.Seek(pos);
846 file.BaseStream.Seek(pos, System.IO.SeekOrigin.Begin);
848 public override long Length()
850 return file.BaseStream.Length;
853 ~FSOutputStream()
855 file.Close(); // close the file