001: package org.apache.lucene.store;
002:
003: /**
004: * Licensed to the Apache Software Foundation (ASF) under one or more
005: * contributor license agreements. See the NOTICE file distributed with
006: * this work for additional information regarding copyright ownership.
007: * The ASF licenses this file to You under the Apache License, Version 2.0
008: * (the "License"); you may not use this file except in compliance with
009: * the License. You may obtain a copy of the License at
010: *
011: * http://www.apache.org/licenses/LICENSE-2.0
012: *
013: * Unless required by applicable law or agreed to in writing, software
014: * distributed under the License is distributed on an "AS IS" BASIS,
015: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016: * See the License for the specific language governing permissions and
017: * limitations under the License.
018: */
019:
020: import java.io.IOException;
021:
022: /** A Directory is a flat list of files. Files may be written once, when they
023: * are created. Once a file is created it may only be opened for read, or
024: * deleted. Random access is permitted both when reading and writing.
025: *
026: * <p> Java's i/o APIs not used directly, but rather all i/o is
027: * through this API. This permits things such as: <ul>
028: * <li> implementation of RAM-based indices;
029: * <li> implementation indices stored in a database, via JDBC;
030: * <li> implementation of an index as a single file;
031: * </ul>
032: *
033: * Directory locking is implemented by an instance of {@link
034: * LockFactory}, and can be changed for each Directory
035: * instance using {@link #setLockFactory}.
036: *
037: * @author Doug Cutting
038: */
039: public abstract class Directory {
040:
041: /** Holds the LockFactory instance (implements locking for
042: * this Directory instance). */
043: protected LockFactory lockFactory;
044:
045: /** Returns an array of strings, one for each file in the
046: * directory. This method may return null (for example for
047: * {@link FSDirectory} if the underlying directory doesn't
048: * exist in the filesystem or there are permissions
049: * problems).*/
050: public abstract String[] list() throws IOException;
051:
052: /** Returns true iff a file with the given name exists. */
053: public abstract boolean fileExists(String name) throws IOException;
054:
055: /** Returns the time the named file was last modified. */
056: public abstract long fileModified(String name) throws IOException;
057:
058: /** Set the modified time of an existing file to now. */
059: public abstract void touchFile(String name) throws IOException;
060:
061: /** Removes an existing file in the directory. */
062: public abstract void deleteFile(String name) throws IOException;
063:
064: /** Renames an existing file in the directory.
065: * If a file already exists with the new name, then it is replaced.
066: * This replacement is not guaranteed to be atomic.
067: * @deprecated
068: */
069: public abstract void renameFile(String from, String to)
070: throws IOException;
071:
072: /** Returns the length of a file in the directory. */
073: public abstract long fileLength(String name) throws IOException;
074:
075: /** Creates a new, empty file in the directory with the given name.
076: Returns a stream writing this file. */
077: public abstract IndexOutput createOutput(String name)
078: throws IOException;
079:
080: /** Returns a stream reading an existing file. */
081: public abstract IndexInput openInput(String name)
082: throws IOException;
083:
084: /** Returns a stream reading an existing file, with the
085: * specified read buffer size. The particular Directory
086: * implementation may ignore the buffer size. Currently
087: * the only Directory implementations that respect this
088: * parameter are {@link FSDirectory} and {@link
089: * org.apache.lucene.index.CompoundFileReader}.
090: */
091: public IndexInput openInput(String name, int bufferSize)
092: throws IOException {
093: return openInput(name);
094: }
095:
096: /** Construct a {@link Lock}.
097: * @param name the name of the lock file
098: */
099: public Lock makeLock(String name) {
100: return lockFactory.makeLock(name);
101: }
102:
103: /**
104: * Attempt to clear (forcefully unlock and remove) the
105: * specified lock. Only call this at a time when you are
106: * certain this lock is no longer in use.
107: * @param name name of the lock to be cleared.
108: */
109: public void clearLock(String name) throws IOException {
110: if (lockFactory != null) {
111: lockFactory.clearLock(name);
112: }
113: }
114:
115: /** Closes the store. */
116: public abstract void close() throws IOException;
117:
118: /**
119: * Set the LockFactory that this Directory instance should
120: * use for its locking implementation. Each * instance of
121: * LockFactory should only be used for one directory (ie,
122: * do not share a single instance across multiple
123: * Directories).
124: *
125: * @param lockFactory instance of {@link LockFactory}.
126: */
127: public void setLockFactory(LockFactory lockFactory) {
128: this .lockFactory = lockFactory;
129: lockFactory.setLockPrefix(this .getLockID());
130: }
131:
132: /**
133: * Get the LockFactory that this Directory instance is
134: * using for its locking implementation. Note that this
135: * may be null for Directory implementations that provide
136: * their own locking implementation.
137: */
138: public LockFactory getLockFactory() {
139: return this .lockFactory;
140: }
141:
142: /**
143: * Return a string identifier that uniquely differentiates
144: * this Directory instance from other Directory instances.
145: * This ID should be the same if two Directory instances
146: * (even in different JVMs and/or on different machines)
147: * are considered "the same index". This is how locking
148: * "scopes" to the right index.
149: */
150: public String getLockID() {
151: return this .toString();
152: }
153:
154: /**
155: * Copy contents of a directory src to a directory dest.
156: * If a file in src already exists in dest then the
157: * one in dest will be blindly overwritten.
158: *
159: * @param src source directory
160: * @param dest destination directory
161: * @param closeDirSrc if <code>true</code>, call {@link #close()} method on source directory
162: * @throws IOException
163: */
164: public static void copy(Directory src, Directory dest,
165: boolean closeDirSrc) throws IOException {
166: final String[] files = src.list();
167:
168: if (files == null)
169: throw new IOException("cannot read directory " + src
170: + ": list() returned null");
171:
172: byte[] buf = new byte[BufferedIndexOutput.BUFFER_SIZE];
173: for (int i = 0; i < files.length; i++) {
174: IndexOutput os = null;
175: IndexInput is = null;
176: try {
177: // create file in dest directory
178: os = dest.createOutput(files[i]);
179: // read current file
180: is = src.openInput(files[i]);
181: // and copy to dest directory
182: long len = is.length();
183: long readCount = 0;
184: while (readCount < len) {
185: int toRead = readCount
186: + BufferedIndexOutput.BUFFER_SIZE > len ? (int) (len - readCount)
187: : BufferedIndexOutput.BUFFER_SIZE;
188: is.readBytes(buf, 0, toRead);
189: os.writeBytes(buf, toRead);
190: readCount += toRead;
191: }
192: } finally {
193: // graceful cleanup
194: try {
195: if (os != null)
196: os.close();
197: } finally {
198: if (is != null)
199: is.close();
200: }
201: }
202: }
203: if (closeDirSrc)
204: src.close();
205: }
206: }
|