| RAMDirectory.java |
1 package org.apache.lucene.store;
2
3 /**
4 * Licensed to the Apache Software Foundation (ASF) under one or more
5 * contributor license agreements. See the NOTICE file distributed with
6 * this work for additional information regarding copyright ownership.
7 * The ASF licenses this file to You under the Apache License, Version 2.0
8 * (the "License"); you may not use this file except in compliance with
9 * the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 */
19
20 import java.io.IOException;
21 import java.io.FileNotFoundException;
22 import java.io.File;
23 import java.io.Serializable;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.Set;
27
28 /**
29 * A memory-resident {@link Directory} implementation. Locking
30 * implementation is by default the {@link SingleInstanceLockFactory}
31 * but can be changed with {@link #setLockFactory}.
32 *
33 * @version $Id: RAMDirectory.java 675485 2008-07-10 09:27:44Z mikemccand $
34 */
35 public class RAMDirectory extends Directory implements Serializable {
36
37 private static final long serialVersionUID = 1l;
38
39 HashMap fileMap = new HashMap();
40 long sizeInBytes = 0;
41
42 // *****
43 // Lock acquisition sequence: RAMDirectory, then RAMFile
44 // *****
45
46 /** Constructs an empty {@link Directory}. */
47 public RAMDirectory() {
48 setLockFactory(new SingleInstanceLockFactory());
49 }
50
51 /**
52 * Creates a new <code>RAMDirectory</code> instance from a different
53 * <code>Directory</code> implementation. This can be used to load
54 * a disk-based index into memory.
55 * <P>
56 * This should be used only with indices that can fit into memory.
57 * <P>
58 * Note that the resulting <code>RAMDirectory</code> instance is fully
59 * independent from the original <code>Directory</code> (it is a
60 * complete copy). Any subsequent changes to the
61 * original <code>Directory</code> will not be visible in the
62 * <code>RAMDirectory</code> instance.
63 *
64 * @param dir a <code>Directory</code> value
65 * @exception IOException if an error occurs
66 */
67 public RAMDirectory(Directory dir) throws IOException {
68 this(dir, false);
69 }
70
71 private RAMDirectory(Directory dir, boolean closeDir) throws IOException {
72 this();
73 Directory.copy(dir, this, closeDir);
74 }
75
76 /**
77 * Creates a new <code>RAMDirectory</code> instance from the {@link FSDirectory}.
78 *
79 * @param dir a <code>File</code> specifying the index directory
80 *
81 * @see #RAMDirectory(Directory)
82 */
83 public RAMDirectory(File dir) throws IOException {
84 this(FSDirectory.getDirectory(dir), true);
85 }
86
87 /**
88 * Creates a new <code>RAMDirectory</code> instance from the {@link FSDirectory}.
89 *
90 * @param dir a <code>String</code> specifying the full index directory path
91 *
92 * @see #RAMDirectory(Directory)
93 */
94 public RAMDirectory(String dir) throws IOException {
95 this(FSDirectory.getDirectory(dir), true);
96 }
97
98 /** Returns an array of strings, one for each file in the directory. */
99 public synchronized final String[] list() {
100 ensureOpen();
101 Set fileNames = fileMap.keySet();
102 String[] result = new String[fileNames.size()];
103 int i = 0;
104 Iterator it = fileNames.iterator();
105 while (it.hasNext())
106 result[i++] = (String)it.next();
107 return result;
108 }
109
110 /** Returns true iff the named file exists in this directory. */
111 public final boolean fileExists(String name) {
112 ensureOpen();
113 RAMFile file;
114 synchronized (this) {
115 file = (RAMFile)fileMap.get(name);
116 }
117 return file != null;
118 }
119
120 /** Returns the time the named file was last modified.
121 * @throws IOException if the file does not exist
122 */
123 public final long fileModified(String name) throws IOException {
124 ensureOpen();
125 RAMFile file;
126 synchronized (this) {
127 file = (RAMFile)fileMap.get(name);
128 }
129 if (file==null)
130 throw new FileNotFoundException(name);
131 return file.getLastModified();
132 }
133
134 /** Set the modified time of an existing file to now.
135 * @throws IOException if the file does not exist
136 */
137 public void touchFile(String name) throws IOException {
138 ensureOpen();
139 RAMFile file;
140 synchronized (this) {
141 file = (RAMFile)fileMap.get(name);
142 }
143 if (file==null)
144 throw new FileNotFoundException(name);
145
146 long ts2, ts1 = System.currentTimeMillis();
147 do {
148 try {
149 Thread.sleep(0, 1);
150 } catch (InterruptedException e) {}
151 ts2 = System.currentTimeMillis();
152 } while(ts1 == ts2);
153
154 file.setLastModified(ts2);
155 }
156
157 /** Returns the length in bytes of a file in the directory.
158 * @throws IOException if the file does not exist
159 */
160 public final long fileLength(String name) throws IOException {
161 ensureOpen();
162 RAMFile file;
163 synchronized (this) {
164 file = (RAMFile)fileMap.get(name);
165 }
166 if (file==null)
167 throw new FileNotFoundException(name);
168 return file.getLength();
169 }
170
171 /** Return total size in bytes of all files in this
172 * directory. This is currently quantized to
173 * RAMOutputStream.BUFFER_SIZE. */
174 public synchronized final long sizeInBytes() {
175 ensureOpen();
176 return sizeInBytes;
177 }
178
179 /** Removes an existing file in the directory.
180 * @throws IOException if the file does not exist
181 */
182 public synchronized void deleteFile(String name) throws IOException {
183 ensureOpen();
184 RAMFile file = (RAMFile)fileMap.get(name);
185 if (file!=null) {
186 fileMap.remove(name);
187 file.directory = null;
188 sizeInBytes -= file.sizeInBytes; // updates to RAMFile.sizeInBytes synchronized on directory
189 } else
190 throw new FileNotFoundException(name);
191 }
192
193 /** Renames an existing file in the directory.
194 * @throws FileNotFoundException if from does not exist
195 * @deprecated
196 */
197 public synchronized final void renameFile(String from, String to) throws IOException {
198 ensureOpen();
199 RAMFile fromFile = (RAMFile)fileMap.get(from);
200 if (fromFile==null)
201 throw new FileNotFoundException(from);
202 RAMFile toFile = (RAMFile)fileMap.get(to);
203 if (toFile!=null) {
204 sizeInBytes -= toFile.sizeInBytes; // updates to RAMFile.sizeInBytes synchronized on directory
205 toFile.directory = null;
206 }
207 fileMap.remove(from);
208 fileMap.put(to, fromFile);
209 }
210
211 /** Creates a new, empty file in the directory with the given name. Returns a stream writing this file. */
212 public IndexOutput createOutput(String name) throws IOException {
213 ensureOpen();
214 RAMFile file = new RAMFile(this);
215 synchronized (this) {
216 RAMFile existing = (RAMFile)fileMap.get(name);
217 if (existing!=null) {
218 sizeInBytes -= existing.sizeInBytes;
219 existing.directory = null;
220 }
221 fileMap.put(name, file);
222 }
223 return new RAMOutputStream(file);
224 }
225
226 /** Returns a stream reading an existing file. */
227 public IndexInput openInput(String name) throws IOException {
228 ensureOpen();
229 RAMFile file;
230 synchronized (this) {
231 file = (RAMFile)fileMap.get(name);
232 }
233 if (file == null)
234 throw new FileNotFoundException(name);
235 return new RAMInputStream(file);
236 }
237
238 /** Closes the store to future operations, releasing associated memory. */
239 public void close() {
240 isOpen = false;
241 fileMap = null;
242 }
243 }
244 | RAMDirectory.java |