First post!
[beagle.git] / Lucene.Net / Store / RAMDirectory.cs
blob16626caa141388c56773f0937a8f8abd60c67304
1 using System;
2 using System.IO;
3 using System.Threading;
4 using System.Collections;
5 using Lucene.Net.Util;
7 namespace Lucene.Net.Store
9 /* ====================================================================
10 * The Apache Software License, Version 1.1
12 * Copyright (c) 2001 The Apache Software Foundation. All rights
13 * reserved.
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in
24 * the documentation and/or other materials provided with the
25 * distribution.
27 * 3. The end-user documentation included with the redistribution,
28 * if any, must include the following acknowledgment:
29 * "This product includes software developed by the
30 * Apache Software Foundation (http://www.apache.org/)."
31 * Alternately, this acknowledgment may appear in the software itself,
32 * if and wherever such third-party acknowledgments normally appear.
34 * 4. The names "Apache" and "Apache Software Foundation" and
35 * "Apache Lucene" must not be used to endorse or promote products
36 * derived from this software without prior written permission. For
37 * written permission, please contact apache@apache.org.
39 * 5. Products derived from this software may not be called "Apache",
40 * "Apache Lucene", nor may "Apache" appear in their name, without
41 * prior written permission of the Apache Software Foundation.
43 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
44 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
45 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
46 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
47 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
48 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
49 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
50 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
51 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
52 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
53 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 * ====================================================================
57 * This software consists of voluntary contributions made by many
58 * individuals on behalf of the Apache Software Foundation. For more
59 * information on the Apache Software Foundation, please see
60 * <http://www.apache.org/>.
63 /// <summary>
64 /// A memory-resident Directory implementation.
65 /// </summary>
66 /// <version>$Id: RAMDirectory.cs,v 1.1.1.1 2004/04/29 22:53:52 trow Exp $</version>
67 public sealed class RAMDirectory : Directory
69 Hashtable files = new Hashtable();
71 /// <summary>
72 /// Constructs an empty Directory.
73 /// </summary>
74 public RAMDirectory()
78 /// <summary>
79 /// Creates a new <code>RAMDirectory</code> instance from a different
80 /// <code>Directory</code> implementation. This can be used to load
81 /// a disk-based index into memory.
82 /// <P>
83 /// This should be used only with indices that can fit into memory.
84 /// </P>
85 /// </summary>
86 /// <param name="dir">a <code>Directory</code> value</param>
87 /// <throws>IOException if an error occurs</throws>
88 public RAMDirectory(Directory dir)
90 String[] ar = dir.List();
91 for (int i = 0; i < ar.Length; i++)
93 // make place on ram disk
94 OutputStream os = CreateFile(ar[i]);
95 // read current file
96 InputStream _is = dir.OpenFile(ar[i]);
97 // and copy to ram disk
98 int len = (int) _is.Length();
99 byte[] buf = new byte[len];
100 _is.ReadBytes(buf, 0, len);
101 os.WriteBytes(buf, len);
102 // graceful cleanup
103 _is.Close();
104 os.Close();
108 /// <summary>
109 /// Creates a new <code>RAMDirectory</code> instance from the FSDirectory.
110 /// </summary>
111 /// <param name="dir">a <code>File</code> specifying the index directory</param>
112 public RAMDirectory(DirectoryInfo dir) : this(FSDirectory.GetDirectory(dir, false))
116 /// <summary>
117 /// Creates a new <code>RAMDirectory</code> instance from the FSDirectory.
118 /// </summary>
119 /// <param name="dir">a <code>String</code> specifying the full index directory path</param>
120 public RAMDirectory(String dir) : this(FSDirectory.GetDirectory(dir, false))
124 /// <summary>
125 /// Returns an array of strings, one for each file in the directory.
126 /// </summary>
127 /// <returns></returns>
128 public override String[] List()
130 String[] result = new String[files.Count];
131 int i = 0;
132 foreach (String s in files.Keys)
134 result[i++] = s;
136 return result;
139 /// <summary>
140 /// Returns true iff the named file exists in this directory.
141 /// </summary>
142 /// <param name="name"></param>
143 /// <returns></returns>
144 public override bool FileExists(String name)
146 RAMFile file = (RAMFile)files[name];
147 return file != null;
150 /// <summary>
151 /// Returns the time the named file was last modified.
152 /// </summary>
153 /// <param name="name"></param>
154 /// <returns></returns>
155 public override long FileModified(String name)
157 RAMFile file = (RAMFile)files[name];
158 return file.lastModified;
161 /// <summary>
162 /// Set the modified time of an existing file to now.
163 /// </summary>
164 /// <param name="name"></param>
165 public override void TouchFile(String name)
167 bool MONITOR = false;
168 int count = 0;
169 RAMFile file = (RAMFile)files[name];
171 long ts2, ts1 = Date.GetTime(DateTime.Now);
174 try
176 Thread.Sleep(1);
178 catch (Exception) {}
179 ts2 = Date.GetTime(DateTime.Now);
180 if (MONITOR) count++;
181 } while(ts1 == ts2);
183 file.lastModified = ts1;
185 if (MONITOR)
186 Console.WriteLine("SLEEP COUNT: " + count);
189 /// <summary>
190 /// Returns the length in bytes of a file in the directory.
191 /// </summary>
192 /// <param name="name"></param>
193 /// <returns></returns>
194 public override long FileLength(String name)
196 RAMFile file = (RAMFile)files[name];
197 return file.length;
200 /// <summary>
201 /// Removes an existing file in the directory.
202 /// </summary>
203 /// <param name="name"></param>
204 public override void DeleteFile(String name)
206 files.Remove(name);
209 /// <summary>
210 /// Removes an existing file in the directory.
211 /// </summary>
212 /// <param name="from"></param>
213 /// <param name="to"></param>
214 public override void RenameFile(String from, String to)
216 RAMFile file = (RAMFile)files[from];
217 files.Remove(from);
218 // Console.WriteLine(to);
219 files[to] = file;
222 /// <summary>
223 /// Creates a new, empty file in the directory with the given name.
224 /// Returns a stream writing this file.
225 /// </summary>
226 /// <param name="name"></param>
227 /// <returns></returns>
228 public override OutputStream CreateFile(String name)
230 RAMFile file = new RAMFile();
231 files[name] = file;
232 return new RAMOutputStream(file);
235 /// <summary>
236 /// Returns a stream reading an existing file.
237 /// </summary>
238 /// <param name="name"></param>
239 /// <returns></returns>
240 public override InputStream OpenFile(String name)
242 RAMFile file = (RAMFile)files[name];
243 return new RAMInputStream(file);
246 private class RAMDirectoryLock : Lock
248 String name;
249 RAMDirectory ramDirectory;
250 internal RAMDirectoryLock(RAMDirectory ramDirectory, String name)
252 this.ramDirectory = ramDirectory;
253 this.name = name;
256 public override bool Obtain()
258 lock (ramDirectory.files)
260 if (!ramDirectory.FileExists(name))
262 ramDirectory.CreateFile(name).Close();
263 return true;
265 return false;
269 public override void Release()
271 ramDirectory.DeleteFile(name);
274 public override bool IsLocked()
276 return ramDirectory.FileExists(name);
280 /// <summary>
281 /// </summary>
282 /// <param name="name">the name of the lock file</param>
283 /// <returns></returns>
284 public override Lock MakeLock(String name)
286 return new RAMDirectoryLock(this, name);
289 /// <summary>
290 /// Closes the store to future operations.
291 /// </summary>
292 public override void Close()
297 sealed class RAMInputStream : InputStream, ICloneable
299 internal RAMFile file;
300 internal int pointer = 0;
302 public RAMInputStream(RAMFile f)
304 file = f;
305 length = file.length;
308 /// <summary>
309 /// InputStream methods
310 /// </summary>
311 /// <param name="dest"></param>
312 /// <param name="destOffset"></param>
313 /// <param name="len"></param>
314 protected override void ReadInternal(byte[] dest, int destOffset, int len)
316 int remainder = len;
317 int start = pointer;
318 while (remainder != 0)
320 int bufferNumber = start/InputStream.BUFFER_SIZE;
321 int bufferOffset = start%InputStream.BUFFER_SIZE;
322 int bytesInBuffer = InputStream.BUFFER_SIZE - bufferOffset;
323 int bytesToCopy = bytesInBuffer >= remainder ? remainder : bytesInBuffer;
324 byte[] buffer = (byte[])file.buffers[bufferNumber];
325 Array.Copy(buffer, bufferOffset, dest, destOffset, bytesToCopy);
326 destOffset += bytesToCopy;
327 start += bytesToCopy;
328 remainder -= bytesToCopy;
330 pointer += len;
333 public override void Close()
337 /// <summary>
338 /// Random-access method
339 /// </summary>
340 /// <param name="pos"></param>
341 protected override void SeekInternal(long pos)
343 pointer = (int)pos;
347 sealed class RAMOutputStream : OutputStream
349 RAMFile file;
350 int pointer = 0;
352 public RAMOutputStream(RAMFile f)
354 file = f;
357 /// Output methods:
359 public override void FlushBuffer(byte[] src, int len)
361 int bufferNumber = pointer/OutputStream.BUFFER_SIZE;
362 int bufferOffset = pointer%OutputStream.BUFFER_SIZE;
363 int bytesInBuffer = OutputStream.BUFFER_SIZE - bufferOffset;
364 int bytesToCopy = bytesInBuffer >= len ? len : bytesInBuffer;
366 if (bufferNumber == file.buffers.Count)
367 file.buffers.Add(new byte[OutputStream.BUFFER_SIZE]);
369 byte[] buffer = (byte[])file.buffers[bufferNumber];
370 Array.Copy(src, 0, buffer, bufferOffset, bytesToCopy);
372 if (bytesToCopy < len)
373 { // not all in one buffer
374 int srcOffset = bytesToCopy;
375 bytesToCopy = len - bytesToCopy; // remaining bytes
376 bufferNumber++;
377 if (bufferNumber == file.buffers.Count)
378 file.buffers.Add(new byte[OutputStream.BUFFER_SIZE]);
379 buffer = (byte[])file.buffers[bufferNumber];
380 Array.Copy(src, srcOffset, buffer, 0, bytesToCopy);
382 pointer += len;
383 if (pointer > file.length)
384 file.length = pointer;
386 file.lastModified = Date.GetTime(DateTime.Now);
389 public override void Close()
391 base.Close();
394 /// <summary>
395 /// Random-access method
396 /// </summary>
397 /// <param name="pos"></param>
398 public override void Seek(long pos)
400 base.Seek(pos);
401 pointer = (int)pos;
403 public override long Length()
405 return file.length;
409 sealed class RAMFile
411 internal ArrayList buffers = new ArrayList();
412 internal long length;
413 internal long lastModified = Date.GetTime(DateTime.Now);