1 package org.apache.lucene.store;
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 import java.io.FileNotFoundException;
21 import java.io.IOException;
22 import java.io.Closeable;
23 import java.util.Collection;
25 import org.apache.lucene.index.IndexFileNameFilter;
26 import org.apache.lucene.util.IOUtils;
28 /** A Directory is a flat list of files. Files may be written once, when they
29 * are created. Once a file is created it may only be opened for read, or
30 * deleted. Random access is permitted both when reading and writing.
32 * <p> Java's i/o APIs not used directly, but rather all i/o is
33 * through this API. This permits things such as: <ul>
34 * <li> implementation of RAM-based indices;
35 * <li> implementation indices stored in a database, via JDBC;
36 * <li> implementation of an index as a single file;
39 * Directory locking is implemented by an instance of {@link
40 * LockFactory}, and can be changed for each Directory
41 * instance using {@link #setLockFactory}.
44 public abstract class Directory implements Closeable {
46 volatile protected boolean isOpen = true;
48 /** Holds the LockFactory instance (implements locking for
49 * this Directory instance). */
50 protected LockFactory lockFactory;
53 * Returns an array of strings, one for each file in the directory.
55 * @throws NoSuchDirectoryException if the directory is not prepared for any
56 * write operations (such as {@link #createOutput(String)}).
57 * @throws IOException in case of other IO errors
59 public abstract String[] listAll() throws IOException;
61 /** Returns true iff a file with the given name exists. */
62 public abstract boolean fileExists(String name)
65 /** Returns the time the named file was last modified. */
66 public abstract long fileModified(String name)
69 /** Set the modified time of an existing file to now.
71 * @deprecated Lucene never uses this API; it will be
74 public abstract void touchFile(String name)
77 /** Removes an existing file in the directory. */
78 public abstract void deleteFile(String name)
82 * Returns the length of a file in the directory. This method follows the
85 * <li>Throws {@link FileNotFoundException} if the file does not exist
86 * <li>Returns a value ≥0 if the file exists, which specifies its length.
89 * @param name the name of the file for which to return the length.
90 * @throws FileNotFoundException if the file does not exist.
91 * @throws IOException if there was an IO error while retrieving the file's
94 public abstract long fileLength(String name) throws IOException;
97 /** Creates a new, empty file in the directory with the given name.
98 Returns a stream writing this file. */
99 public abstract IndexOutput createOutput(String name)
103 * Ensure that any writes to this file are moved to
104 * stable storage. Lucene uses this to properly commit
105 * changes to the index, to prevent a machine/OS crash
106 * from corrupting the index.
107 * @deprecated use {@link #sync(Collection)} instead.
108 * For easy migration you can change your code to call
109 * sync(Collections.singleton(name))
112 public void sync(String name) throws IOException { // TODO 4.0 kill me
116 * Ensure that any writes to these files are moved to
117 * stable storage. Lucene uses this to properly commit
118 * changes to the index, to prevent a machine/OS crash
119 * from corrupting the index.<br/>
121 * NOTE: Clients may call this method for same files over
122 * and over again, so some impls might optimize for that.
123 * For other impls the operation can be a noop, for various
126 public void sync(Collection<String> names) throws IOException { // TODO 4.0 make me abstract
127 for (String name : names)
131 /** Returns a stream reading an existing file. */
132 public abstract IndexInput openInput(String name)
135 /** Returns a stream reading an existing file, with the
136 * specified read buffer size. The particular Directory
137 * implementation may ignore the buffer size. Currently
138 * the only Directory implementations that respect this
139 * parameter are {@link FSDirectory} and {@link
140 * org.apache.lucene.index.CompoundFileReader}.
142 public IndexInput openInput(String name, int bufferSize) throws IOException {
143 return openInput(name);
146 /** Construct a {@link Lock}.
147 * @param name the name of the lock file
149 public Lock makeLock(String name) {
150 return lockFactory.makeLock(name);
153 * Attempt to clear (forcefully unlock and remove) the
154 * specified lock. Only call this at a time when you are
155 * certain this lock is no longer in use.
156 * @param name name of the lock to be cleared.
158 public void clearLock(String name) throws IOException {
159 if (lockFactory != null) {
160 lockFactory.clearLock(name);
164 /** Closes the store. */
165 public abstract void close()
169 * Set the LockFactory that this Directory instance should
170 * use for its locking implementation. Each * instance of
171 * LockFactory should only be used for one directory (ie,
172 * do not share a single instance across multiple
175 * @param lockFactory instance of {@link LockFactory}.
177 public void setLockFactory(LockFactory lockFactory) throws IOException {
178 assert lockFactory != null;
179 this.lockFactory = lockFactory;
180 lockFactory.setLockPrefix(this.getLockID());
184 * Get the LockFactory that this Directory instance is
185 * using for its locking implementation. Note that this
186 * may be null for Directory implementations that provide
187 * their own locking implementation.
189 public LockFactory getLockFactory() {
190 return this.lockFactory;
194 * Return a string identifier that uniquely differentiates
195 * this Directory instance from other Directory instances.
196 * This ID should be the same if two Directory instances
197 * (even in different JVMs and/or on different machines)
198 * are considered "the same index". This is how locking
199 * "scopes" to the right index.
201 public String getLockID() {
202 return this.toString();
206 public String toString() {
207 return super.toString() + " lockFactory=" + getLockFactory();
211 * Copies the file <i>src</i> to {@link Directory} <i>to</i> under the new
212 * file name <i>dest</i>.
214 * If you want to copy the entire source directory to the destination one, you
215 * can do so like this:
218 * Directory to; // the directory to copy to
219 * for (String file : dir.listAll()) {
220 * dir.copy(to, file, newFile); // newFile can be either file, or a new name
224 * <b>NOTE:</b> this method does not check whether <i>dest<i> exist and will
225 * overwrite it if it does.
227 public void copy(Directory to, String src, String dest) throws IOException {
228 IndexOutput os = null;
229 IndexInput is = null;
230 IOException priorException = null;
232 os = to.createOutput(dest);
234 is.copyBytes(os, is.length());
235 } catch (IOException ioe) {
236 priorException = ioe;
238 IOUtils.closeWhileHandlingException(priorException, os, is);
243 * Copy contents of a directory src to a directory dest. If a file in src
244 * already exists in dest then the one in dest will be blindly overwritten.
246 * <b>NOTE:</b> the source directory cannot change while this method is
247 * running. Otherwise the results are undefined and you could easily hit a
248 * FileNotFoundException.
250 * <b>NOTE:</b> this method only copies files that look like index files (ie,
251 * have extensions matching the known extensions of index files).
253 * @param src source directory
254 * @param dest destination directory
255 * @param closeDirSrc if <code>true</code>, call {@link #close()} method on
257 * @deprecated should be replaced with calls to
258 * {@link #copy(Directory, String, String)} for every file that
259 * needs copying. You can use the following code:
262 * IndexFileNameFilter filter = IndexFileNameFilter.getFilter();
263 * for (String file : src.listAll()) {
264 * if (filter.accept(null, file)) {
265 * src.copy(dest, file, file);
271 public static void copy(Directory src, Directory dest, boolean closeDirSrc) throws IOException {
272 IndexFileNameFilter filter = IndexFileNameFilter.getFilter();
273 for (String file : src.listAll()) {
274 if (filter.accept(null, file)) {
275 src.copy(dest, file, file);
284 * @throws AlreadyClosedException if this Directory is closed
286 protected final void ensureOpen() throws AlreadyClosedException {
288 throw new AlreadyClosedException("this Directory is closed");