LUCENE-1451: Add public constructors to FSDirectory and subclasses

git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@714110 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Yonik Seeley 2008-11-14 19:22:22 +00:00
parent e213a4e828
commit 0979fdc423
5 changed files with 150 additions and 8 deletions

View File

@ -21,6 +21,10 @@ API Changes
2. LUCENE-1427: DocIdSet.iterator() is now allowed to throw 2. LUCENE-1427: DocIdSet.iterator() is now allowed to throw
IOException. (Paul Elschot, Mike McCandless) IOException. (Paul Elschot, Mike McCandless)
3. LUCENE-1451: Add public constructors to FSDirectory and subclasses,
and deprecate FSDirectory.getDirectory(). FSDirectory instances
are not required to be singletons per path. (yonik)
Bug fixes Bug fixes
1. LUCENE-1415: MultiPhraseQuery has incorrect hashCode() and equals() 1. LUCENE-1415: MultiPhraseQuery has incorrect hashCode() and equals()

View File

@ -131,7 +131,11 @@ public class FSDirectory extends Directory {
/** A buffer optionally used in renameTo method */ /** A buffer optionally used in renameTo method */
private byte[] buffer = null; private byte[] buffer = null;
/** Returns the directory instance for the named location. /** Returns the directory instance for the named location.
*
* @deprecated Use {@link #FSDirectory(File, LockFactory)}
*
* @param path the path to the directory. * @param path the path to the directory.
* @return the FSDirectory for the named file. */ * @return the FSDirectory for the named file. */
public static FSDirectory getDirectory(String path) public static FSDirectory getDirectory(String path)
@ -140,6 +144,9 @@ public class FSDirectory extends Directory {
} }
/** Returns the directory instance for the named location. /** Returns the directory instance for the named location.
*
* @deprecated Use {@link #FSDirectory(File, LockFactory)}
*
* @param path the path to the directory. * @param path the path to the directory.
* @param lockFactory instance of {@link LockFactory} providing the * @param lockFactory instance of {@link LockFactory} providing the
* locking implementation. * locking implementation.
@ -150,6 +157,9 @@ public class FSDirectory extends Directory {
} }
/** Returns the directory instance for the named location. /** Returns the directory instance for the named location.
*
* @deprecated Use {@link #FSDirectory(File, LockFactory)}
*
* @param file the path to the directory. * @param file the path to the directory.
* @return the FSDirectory for the named file. */ * @return the FSDirectory for the named file. */
public static FSDirectory getDirectory(File file) public static FSDirectory getDirectory(File file)
@ -158,6 +168,9 @@ public class FSDirectory extends Directory {
} }
/** Returns the directory instance for the named location. /** Returns the directory instance for the named location.
*
* @deprecated Use {@link #FSDirectory(File, LockFactory)}
*
* @param file the path to the directory. * @param file the path to the directory.
* @param lockFactory instance of {@link LockFactory} providing the * @param lockFactory instance of {@link LockFactory} providing the
* locking implementation. * locking implementation.
@ -165,14 +178,7 @@ public class FSDirectory extends Directory {
public static FSDirectory getDirectory(File file, LockFactory lockFactory) public static FSDirectory getDirectory(File file, LockFactory lockFactory)
throws IOException throws IOException
{ {
file = new File(file.getCanonicalPath()); file = createCanonicalDir(file);
if (file.exists() && !file.isDirectory())
throw new IOException(file + " not a directory");
if (!file.exists())
if (!file.mkdirs())
throw new IOException("Cannot create directory: " + file);
FSDirectory dir; FSDirectory dir;
synchronized (DIRECTORIES) { synchronized (DIRECTORIES) {
@ -249,11 +255,39 @@ public class FSDirectory extends Directory {
lockFactory.clearLock(IndexWriter.WRITE_LOCK_NAME); lockFactory.clearLock(IndexWriter.WRITE_LOCK_NAME);
} }
// returns the canonical version of the directory, creating it if it doesn't exist.
private static File createCanonicalDir(File file) throws IOException {
file = new File(file.getCanonicalPath());
if (file.exists() && !file.isDirectory())
throw new IOException(file + " not a directory");
if (!file.exists())
if (!file.mkdirs())
throw new IOException("Cannot create directory: " + file);
return file;
}
private File directory = null; private File directory = null;
private int refCount; private int refCount;
protected FSDirectory() {}; // permit subclassing protected FSDirectory() {}; // permit subclassing
/** Create a new FSDirectory for the named location.
*
* @param path the path of the directory
* @param lockFactory the lock factory to use, or null for the default.
* @throws IOException
*
* Use {@link #getDirectory(String)} if singletons per path are needed.
*/
public FSDirectory(File path, LockFactory lockFactory) throws IOException {
path = createCanonicalDir(path);
init(path, lockFactory);
refCount = 1;
}
private void init(File path, LockFactory lockFactory) throws IOException { private void init(File path, LockFactory lockFactory) throws IOException {
// Set up lockFactory with cascaded defaults: if an instance was passed in, // Set up lockFactory with cascaded defaults: if an instance was passed in,

View File

@ -33,6 +33,19 @@ import java.nio.channels.FileChannel.MapMode;
*/ */
public class MMapDirectory extends FSDirectory { public class MMapDirectory extends FSDirectory {
/** Create a new MMapDirectory for the named location.
* @param path the path of the directory
* @param lockFactory the lock factory to use, or null for the default.
* @throws IOException
*/
public MMapDirectory(File path, LockFactory lockFactory) throws IOException {
super(path, lockFactory);
}
// back compatibility so FSDirectory can instantiate via reflection
protected MMapDirectory() throws IOException {
}
private static class MMapIndexInput extends IndexInput { private static class MMapIndexInput extends IndexInput {
private ByteBuffer buffer; private ByteBuffer buffer;

View File

@ -43,6 +43,20 @@ import java.nio.channels.FileChannel;
public class NIOFSDirectory extends FSDirectory { public class NIOFSDirectory extends FSDirectory {
/** Create a new NIOFSDirectory for the named location.
*
* @param path the path of the directory
* @param lockFactory the lock factory to use, or null for the default.
* @throws IOException
*/
public NIOFSDirectory(File path, LockFactory lockFactory) throws IOException {
super(path, lockFactory);
}
// back compatibility so FSDirectory can instantiate via reflection
protected NIOFSDirectory() throws IOException {
}
// Inherit javadoc // Inherit javadoc
public IndexInput openInput(String name, int bufferSize) throws IOException { public IndexInput openInput(String name, int bufferSize) throws IOException {
ensureOpen(); ensureOpen();

View File

@ -19,6 +19,8 @@ package org.apache.lucene.store;
import org.apache.lucene.util.LuceneTestCase; import org.apache.lucene.util.LuceneTestCase;
import java.io.File;
public class TestDirectory extends LuceneTestCase { public class TestDirectory extends LuceneTestCase {
public void testDetectClose() throws Throwable { public void testDetectClose() throws Throwable {
@ -38,5 +40,80 @@ public class TestDirectory extends LuceneTestCase {
} catch (AlreadyClosedException ace) { } catch (AlreadyClosedException ace) {
} }
} }
// Test that different instances of FSDirectory can coexist on the same
// path, can read, write, and lock files.
public void testDirectInstantiation() throws Exception {
File path = new File(System.getProperty("tempDir"));
int sz = 3;
Directory[] dirs = new Directory[sz];
dirs[0] = new FSDirectory(path, null);
dirs[1] = new NIOFSDirectory(path, null);
dirs[2] = new MMapDirectory(path, null);
for (int i=0; i<sz; i++) {
Directory dir = dirs[i];
dir.ensureOpen();
String fname = "foo." + i;
String lockname = "foo" + i + ".lck";
IndexOutput out = dir.createOutput(fname);
out.writeByte((byte)i);
out.close();
for (int j=0; j<sz; j++) {
Directory d2 = dirs[j];
d2.ensureOpen();
assertTrue(d2.fileExists(fname));
assertEquals(1, d2.fileLength(fname));
// don't test read on MMapDirectory, since it can't really be
// closed and will cause a failure to delete the file.
if (d2 instanceof MMapDirectory) continue;
IndexInput input = d2.openInput(fname);
assertEquals((byte)i, input.readByte());
input.close();
}
// delete with a different dir
dirs[(i+1)%sz].deleteFile(fname);
for (int j=0; j<sz; j++) {
Directory d2 = dirs[j];
assertFalse(d2.fileExists(fname));
}
Lock lock = dir.makeLock(lockname);
assertTrue(lock.obtain());
for (int j=0; j<sz; j++) {
Directory d2 = dirs[j];
Lock lock2 = d2.makeLock(lockname);
try {
assertFalse(lock2.obtain(1));
} catch (LockObtainFailedException e) {
// OK
}
}
lock.release();
// now lock with different dir
lock = dirs[(i+1)%sz].makeLock(lockname);
assertTrue(lock.obtain());
lock.release();
}
for (int i=0; i<sz; i++) {
Directory dir = dirs[i];
dir.ensureOpen();
dir.close();
assertFalse(dir.isOpen);
}
}
} }