mirror of https://github.com/apache/lucene.git
NativeFSLockFactory: LUCENE-678
git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@464611 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
cb4f27f25f
commit
70472ad2cd
|
@ -33,6 +33,10 @@ New features
|
||||||
|
|
||||||
3. LUCENE-676: Move Solr's PrefixFilter to Lucene core. (Yura Smolsky, Yonik Seeley)
|
3. LUCENE-676: Move Solr's PrefixFilter to Lucene core. (Yura Smolsky, Yonik Seeley)
|
||||||
|
|
||||||
|
4. LUCENE-678: Added NativeFSLockFactory, which implements locking
|
||||||
|
using OS native locking (via java.nio.*). (Michael McCandless via Yonik Seeley)
|
||||||
|
|
||||||
|
|
||||||
API Changes
|
API Changes
|
||||||
|
|
||||||
1. LUCENE-438: Remove "final" from Token, implement Cloneable, allow
|
1. LUCENE-438: Remove "final" from Token, implement Cloneable, allow
|
||||||
|
|
|
@ -55,7 +55,7 @@ final class FieldsReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cloeses the underlying {@link org.apache.lucene.store.IndexInput} streams, including any ones associated with a
|
* Closes the underlying {@link org.apache.lucene.store.IndexInput} streams, including any ones associated with a
|
||||||
* lazy implementation of a Field. This means that the Fields values will not be accessible.
|
* lazy implementation of a Field. This means that the Fields values will not be accessible.
|
||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
|
|
|
@ -228,8 +228,8 @@ public class FSDirectory extends Directory {
|
||||||
|
|
||||||
// Set up lockFactory with cascaded defaults: if an instance was passed in,
|
// Set up lockFactory with cascaded defaults: if an instance was passed in,
|
||||||
// use that; else if locks are disabled, use NoLockFactory; else if the
|
// use that; else if locks are disabled, use NoLockFactory; else if the
|
||||||
// system property org.apache.lucene.lockClass is set, instantiate that;
|
// system property org.apache.lucene.store.FSDirectoryLockFactoryClass is set,
|
||||||
// else, use SimpleFSLockFactory:
|
// instantiate that; else, use SimpleFSLockFactory:
|
||||||
|
|
||||||
if (lockFactory == null) {
|
if (lockFactory == null) {
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,13 @@ public abstract class Lock {
|
||||||
*/
|
*/
|
||||||
public abstract boolean obtain() throws IOException;
|
public abstract boolean obtain() throws IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If a lock obtain called, this failureReason may be set
|
||||||
|
* with the "root cause" Exception as to why the lock was
|
||||||
|
* not obtained.
|
||||||
|
*/
|
||||||
|
protected Throwable failureReason;
|
||||||
|
|
||||||
/** Attempts to obtain an exclusive lock within amount
|
/** Attempts to obtain an exclusive lock within amount
|
||||||
* of time given. Currently polls once per second until
|
* of time given. Currently polls once per second until
|
||||||
* lockWaitTimeout is passed.
|
* lockWaitTimeout is passed.
|
||||||
|
@ -48,12 +55,21 @@ public abstract class Lock {
|
||||||
* @throws IOException if lock wait times out or obtain() throws an IOException
|
* @throws IOException if lock wait times out or obtain() throws an IOException
|
||||||
*/
|
*/
|
||||||
public boolean obtain(long lockWaitTimeout) throws IOException {
|
public boolean obtain(long lockWaitTimeout) throws IOException {
|
||||||
|
failureReason = null;
|
||||||
boolean locked = obtain();
|
boolean locked = obtain();
|
||||||
int maxSleepCount = (int)(lockWaitTimeout / LOCK_POLL_INTERVAL);
|
int maxSleepCount = (int)(lockWaitTimeout / LOCK_POLL_INTERVAL);
|
||||||
int sleepCount = 0;
|
int sleepCount = 0;
|
||||||
while (!locked) {
|
while (!locked) {
|
||||||
if (sleepCount++ == maxSleepCount) {
|
if (sleepCount++ == maxSleepCount) {
|
||||||
throw new IOException("Lock obtain timed out: " + this.toString());
|
String reason = "Lock obtain timed out: " + this.toString();
|
||||||
|
if (failureReason != null) {
|
||||||
|
reason += ": " + failureReason;
|
||||||
|
}
|
||||||
|
IOException e = new IOException(reason);
|
||||||
|
if (failureReason != null) {
|
||||||
|
e.initCause(failureReason);
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Thread.sleep(LOCK_POLL_INTERVAL);
|
Thread.sleep(LOCK_POLL_INTERVAL);
|
||||||
|
|
|
@ -28,7 +28,14 @@ public abstract class LockFactory {
|
||||||
protected String lockPrefix = "";
|
protected String lockPrefix = "";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the prefix in use for all locks created in this LockFactory.
|
* Set the prefix in use for all locks created in this
|
||||||
|
* LockFactory. This is normally called once, when a
|
||||||
|
* Directory gets this LockFactory instance. However, you
|
||||||
|
* can also call this (after this instance is assigned to
|
||||||
|
* a Directory) to override the prefix in use. This
|
||||||
|
* is helpful if you're running Lucene on machines that
|
||||||
|
* have different mount points for the same shared
|
||||||
|
* directory.
|
||||||
*/
|
*/
|
||||||
public void setLockPrefix(String lockPrefix) {
|
public void setLockPrefix(String lockPrefix) {
|
||||||
this.lockPrefix = lockPrefix;
|
this.lockPrefix = lockPrefix;
|
||||||
|
|
|
@ -0,0 +1,313 @@
|
||||||
|
package org.apache.lucene.store;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copyright 2006 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.nio.channels.FileChannel;
|
||||||
|
import java.nio.channels.FileLock;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.RandomAccessFile;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements {@link LockFactory} using native OS file locks
|
||||||
|
* (available through java.nio.*). Note that for certain
|
||||||
|
* filesystems native locks are possible but must be
|
||||||
|
* explicity configured and enabled (and may be disabled by
|
||||||
|
* default). For example, for NFS servers there sometimes
|
||||||
|
* must be a separate lockd process running, and other
|
||||||
|
* configuration may be required such as running the server
|
||||||
|
* in kernel mode. Other filesystems may not even support
|
||||||
|
* native OS locks in which case you must use a different
|
||||||
|
* {@link LockFactory} implementation.
|
||||||
|
*
|
||||||
|
* <p>The advantage of this lock factory over
|
||||||
|
* SimpleFSLockFactory is that the locks should be
|
||||||
|
* "correct", whereas SimpleFSLockFactory uses
|
||||||
|
* java.io.File.createNewFile which has warnings about not
|
||||||
|
* using it for locking. Furthermore, if the JVM crashes,
|
||||||
|
* the OS will free any held locks, whereas
|
||||||
|
* SimpleFSLockFactory will keep the locks held, requiring
|
||||||
|
* manual removal before re-running Lucene.</p>
|
||||||
|
*
|
||||||
|
* <p>Note that, unlike SimpleFSLockFactory, the existence of
|
||||||
|
* leftover lock files in the filesystem on exiting the JVM
|
||||||
|
* is fine because the OS will free the locks held against
|
||||||
|
* these files even though the files still remain.</p>
|
||||||
|
*
|
||||||
|
* <p>Native locks file names have the substring "-n-", which
|
||||||
|
* you can use to differentiate them from lock files created
|
||||||
|
* by SimpleFSLockFactory.</p>
|
||||||
|
*
|
||||||
|
* @see LockFactory
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class NativeFSLockFactory extends LockFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Directory specified by <code>org.apache.lucene.lockDir</code>
|
||||||
|
* system property. If that is not set, then <code>java.io.tmpdir</code>
|
||||||
|
* system property is used.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static final String LOCK_DIR =
|
||||||
|
System.getProperty("org.apache.lucene.lockDir",
|
||||||
|
System.getProperty("java.io.tmpdir"));
|
||||||
|
|
||||||
|
private File lockDir;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The javadocs for FileChannel state that you should have
|
||||||
|
* a single instance of a FileChannel (per JVM) for all
|
||||||
|
* locking against a given file. To do this, we ensure
|
||||||
|
* there's a single instance of NativeFSLockFactory per
|
||||||
|
* canonical lock directory, and then we always use a
|
||||||
|
* single lock instance (per lock name) if it's present.
|
||||||
|
*/
|
||||||
|
private static Hashtable LOCK_FACTORIES = new Hashtable();
|
||||||
|
|
||||||
|
private Hashtable locks = new Hashtable();
|
||||||
|
|
||||||
|
protected NativeFSLockFactory(File lockDir)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
this.lockDir = lockDir;
|
||||||
|
|
||||||
|
// Ensure that lockDir exists and is a directory.
|
||||||
|
if (!lockDir.exists()) {
|
||||||
|
if (!lockDir.mkdirs())
|
||||||
|
throw new IOException("Cannot create directory: " +
|
||||||
|
lockDir.getAbsolutePath());
|
||||||
|
} else if (!lockDir.isDirectory()) {
|
||||||
|
throw new IOException("Found regular file where directory expected: " +
|
||||||
|
lockDir.getAbsolutePath());
|
||||||
|
}
|
||||||
|
acquireTestLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple test to verify locking system is "working". On
|
||||||
|
// NFS, if it's misconfigured, you can hit long (35
|
||||||
|
// second) timeouts which cause Lock.obtain to take far
|
||||||
|
// too long (it assumes the obtain() call takes zero
|
||||||
|
// time). Since it's a configuration problem, we test up
|
||||||
|
// front once on creating the LockFactory:
|
||||||
|
private void acquireTestLock() throws IOException {
|
||||||
|
String randomLockName = "lucene-" + Long.toString(new Random().nextInt(), Character.MAX_RADIX) + "-test.lock";
|
||||||
|
|
||||||
|
Lock l = makeLock(randomLockName);
|
||||||
|
try {
|
||||||
|
l.obtain();
|
||||||
|
} catch (IOException e) {
|
||||||
|
IOException e2 = new IOException("Failed to acquire random test lock; please verify filesystem for lock directory '" + lockDir + "' supports locking");
|
||||||
|
e2.initCause(e);
|
||||||
|
throw e2;
|
||||||
|
}
|
||||||
|
|
||||||
|
l.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a NativeFSLockFactory instance, storing lock
|
||||||
|
* files into the default LOCK_DIR:
|
||||||
|
* <code>org.apache.lucene.lockDir</code> system property,
|
||||||
|
* or (if that is null) then <code>java.io.tmpdir</code>.
|
||||||
|
*/
|
||||||
|
public static NativeFSLockFactory getLockFactory() throws IOException {
|
||||||
|
return getLockFactory(new File(LOCK_DIR));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a NativeFSLockFactory instance, storing lock
|
||||||
|
* files into the specified lockDirName:
|
||||||
|
*
|
||||||
|
* @param lockDirName where lock files are created.
|
||||||
|
*/
|
||||||
|
public static NativeFSLockFactory getLockFactory(String lockDirName) throws IOException {
|
||||||
|
return getLockFactory(new File(lockDirName));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a NativeFSLockFactory instance, storing lock
|
||||||
|
* files into the specified lockDir:
|
||||||
|
*
|
||||||
|
* @param lockDir where lock files are created.
|
||||||
|
*/
|
||||||
|
public static NativeFSLockFactory getLockFactory(File lockDir) throws IOException {
|
||||||
|
lockDir = new File(lockDir.getCanonicalPath());
|
||||||
|
|
||||||
|
NativeFSLockFactory f;
|
||||||
|
|
||||||
|
synchronized(LOCK_FACTORIES) {
|
||||||
|
f = (NativeFSLockFactory) LOCK_FACTORIES.get(lockDir);
|
||||||
|
if (f == null) {
|
||||||
|
f = new NativeFSLockFactory(lockDir);
|
||||||
|
LOCK_FACTORIES.put(lockDir, f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized Lock makeLock(String lockName) {
|
||||||
|
Lock l = (Lock) locks.get(lockName);
|
||||||
|
if (l == null) {
|
||||||
|
String fullName;
|
||||||
|
if (lockPrefix.equals("")) {
|
||||||
|
fullName = lockName;
|
||||||
|
} else {
|
||||||
|
fullName = lockPrefix + "-n-" + lockName;
|
||||||
|
}
|
||||||
|
|
||||||
|
l = new NativeFSLock(lockDir, fullName);
|
||||||
|
locks.put(lockName, l);
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearAllLocks() throws IOException {
|
||||||
|
// Note that this isn't strictly required anymore
|
||||||
|
// because the existence of these files does not mean
|
||||||
|
// they are locked, but, still do this in case people
|
||||||
|
// really want to see the files go away:
|
||||||
|
if (lockDir.exists()) {
|
||||||
|
String[] files = lockDir.list();
|
||||||
|
if (files == null)
|
||||||
|
throw new IOException("Cannot read lock directory " +
|
||||||
|
lockDir.getAbsolutePath());
|
||||||
|
String prefix = lockPrefix + "-n-";
|
||||||
|
for (int i = 0; i < files.length; i++) {
|
||||||
|
if (files[i].startsWith(prefix)) {
|
||||||
|
File lockFile = new File(lockDir, files[i]);
|
||||||
|
if (!lockFile.delete())
|
||||||
|
throw new IOException("Cannot delete " + lockFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class NativeFSLock extends Lock {
|
||||||
|
|
||||||
|
private RandomAccessFile f;
|
||||||
|
private FileChannel channel;
|
||||||
|
private FileLock lock;
|
||||||
|
private File path;
|
||||||
|
private File lockDir;
|
||||||
|
|
||||||
|
public NativeFSLock(File lockDir, String lockFileName) {
|
||||||
|
this.lockDir = lockDir;
|
||||||
|
path = new File(lockDir, lockFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean obtain() throws IOException {
|
||||||
|
|
||||||
|
if (isLocked()) {
|
||||||
|
// We are already locked:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that lockDir exists and is a directory.
|
||||||
|
if (!lockDir.exists()) {
|
||||||
|
if (!lockDir.mkdirs())
|
||||||
|
throw new IOException("Cannot create directory: " +
|
||||||
|
lockDir.getAbsolutePath());
|
||||||
|
} else if (!lockDir.isDirectory()) {
|
||||||
|
throw new IOException("Found regular file where directory expected: " +
|
||||||
|
lockDir.getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
f = new RandomAccessFile(path, "rw");
|
||||||
|
try {
|
||||||
|
channel = f.getChannel();
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
lock = channel.tryLock();
|
||||||
|
} catch (IOException e) {
|
||||||
|
// At least on OS X, we will sometimes get an
|
||||||
|
// intermittant "Permission Denied" IOException,
|
||||||
|
// which seems to simply mean "you failed to get
|
||||||
|
// the lock". But other IOExceptions could be
|
||||||
|
// "permanent" (eg, locking is not supported via
|
||||||
|
// the filesystem). So, we record the failure
|
||||||
|
// reason here; the timeout obtain (usually the
|
||||||
|
// one calling us) will use this as "root cause"
|
||||||
|
// if it fails to get the lock.
|
||||||
|
failureReason = e;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (lock == null) {
|
||||||
|
try {
|
||||||
|
channel.close();
|
||||||
|
} finally {
|
||||||
|
channel = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (channel == null) {
|
||||||
|
try {
|
||||||
|
f.close();
|
||||||
|
} finally {
|
||||||
|
f = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return lock != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized void release() {
|
||||||
|
try {
|
||||||
|
if (isLocked()) {
|
||||||
|
try {
|
||||||
|
lock.release();
|
||||||
|
} finally {
|
||||||
|
lock = null;
|
||||||
|
try {
|
||||||
|
channel.close();
|
||||||
|
} finally {
|
||||||
|
channel = null;
|
||||||
|
try {
|
||||||
|
f.close();
|
||||||
|
} finally {
|
||||||
|
f = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
path.delete();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
// Not sure how to better message/handle this without
|
||||||
|
// changing API?
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLocked() {
|
||||||
|
return lock != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "NativeFSLock@" + path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void finalize() {
|
||||||
|
if (isLocked()) {
|
||||||
|
release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -80,17 +80,19 @@ public class SimpleFSLockFactory extends LockFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clearAllLocks() throws IOException {
|
public void clearAllLocks() throws IOException {
|
||||||
String[] files = lockDir.list();
|
if (lockDir.exists()) {
|
||||||
if (files == null)
|
String[] files = lockDir.list();
|
||||||
throw new IOException("Cannot read lock directory " +
|
if (files == null)
|
||||||
lockDir.getAbsolutePath());
|
throw new IOException("Cannot read lock directory " +
|
||||||
String prefix = lockPrefix + "-";
|
lockDir.getAbsolutePath());
|
||||||
for (int i = 0; i < files.length; i++) {
|
String prefix = lockPrefix + "-";
|
||||||
if (!files[i].startsWith(prefix))
|
for (int i = 0; i < files.length; i++) {
|
||||||
continue;
|
if (!files[i].startsWith(prefix))
|
||||||
File lockFile = new File(lockDir, files[i]);
|
continue;
|
||||||
if (!lockFile.delete())
|
File lockFile = new File(lockDir, files[i]);
|
||||||
throw new IOException("Cannot delete " + lockFile);
|
if (!lockFile.delete())
|
||||||
|
throw new IOException("Cannot delete " + lockFile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -130,7 +130,8 @@ public class TestLockFactory extends TestCase {
|
||||||
IndexWriter writer = new IndexWriter(indexDirName, new WhitespaceAnalyzer(), true);
|
IndexWriter writer = new IndexWriter(indexDirName, new WhitespaceAnalyzer(), true);
|
||||||
|
|
||||||
assertTrue("FSDirectory did not use correct LockFactory: got " + writer.getDirectory().getLockFactory(),
|
assertTrue("FSDirectory did not use correct LockFactory: got " + writer.getDirectory().getLockFactory(),
|
||||||
SimpleFSLockFactory.class.isInstance(writer.getDirectory().getLockFactory()));
|
SimpleFSLockFactory.class.isInstance(writer.getDirectory().getLockFactory()) ||
|
||||||
|
NativeFSLockFactory.class.isInstance(writer.getDirectory().getLockFactory()));
|
||||||
|
|
||||||
IndexWriter writer2 = null;
|
IndexWriter writer2 = null;
|
||||||
|
|
||||||
|
@ -157,7 +158,10 @@ public class TestLockFactory extends TestCase {
|
||||||
IndexWriter writer = new IndexWriter(indexDirName, new WhitespaceAnalyzer(), true);
|
IndexWriter writer = new IndexWriter(indexDirName, new WhitespaceAnalyzer(), true);
|
||||||
|
|
||||||
assertTrue("FSDirectory did not use correct LockFactory: got " + writer.getDirectory().getLockFactory(),
|
assertTrue("FSDirectory did not use correct LockFactory: got " + writer.getDirectory().getLockFactory(),
|
||||||
SimpleFSLockFactory.class.isInstance(writer.getDirectory().getLockFactory()));
|
SimpleFSLockFactory.class.isInstance(writer.getDirectory().getLockFactory()) ||
|
||||||
|
NativeFSLockFactory.class.isInstance(writer.getDirectory().getLockFactory()));
|
||||||
|
|
||||||
|
writer.close();
|
||||||
|
|
||||||
// Create a 2nd IndexWriter. This should not fail:
|
// Create a 2nd IndexWriter. This should not fail:
|
||||||
IndexWriter writer2 = null;
|
IndexWriter writer2 = null;
|
||||||
|
@ -218,10 +222,6 @@ public class TestLockFactory extends TestCase {
|
||||||
fail("Should not have hit an IOException with locking disabled");
|
fail("Should not have hit an IOException with locking disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Put back to the correct default for subsequent tests:
|
|
||||||
System.setProperty("org.apache.lucene.store.FSDirectoryLockFactoryClass",
|
|
||||||
"org.apache.lucene.store.SimpleFSLockFactory");
|
|
||||||
|
|
||||||
FSDirectory.setDisableLocks(false);
|
FSDirectory.setDisableLocks(false);
|
||||||
writer.close();
|
writer.close();
|
||||||
if (writer2 != null) {
|
if (writer2 != null) {
|
||||||
|
@ -266,9 +266,19 @@ public class TestLockFactory extends TestCase {
|
||||||
// IndexWriters over & over in 2 threads and making sure
|
// IndexWriters over & over in 2 threads and making sure
|
||||||
// no unexpected exceptions are raised:
|
// no unexpected exceptions are raised:
|
||||||
public void testStressLocks() throws IOException {
|
public void testStressLocks() throws IOException {
|
||||||
|
_testStressLocks(null, "index.TestLockFactory6");
|
||||||
|
}
|
||||||
|
|
||||||
String indexDirName = "index.TestLockFactory6";
|
// Verify: do stress test, by opening IndexReaders and
|
||||||
FSDirectory fs1 = FSDirectory.getDirectory(indexDirName, true);
|
// IndexWriters over & over in 2 threads and making sure
|
||||||
|
// no unexpected exceptions are raised, but use
|
||||||
|
// NativeFSLockFactory:
|
||||||
|
public void testStressLocksNativeFSLockFactory() throws IOException {
|
||||||
|
_testStressLocks(NativeFSLockFactory.getLockFactory(), "index.TestLockFactory7");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void _testStressLocks(LockFactory lockFactory, String indexDirName) throws IOException {
|
||||||
|
FSDirectory fs1 = FSDirectory.getDirectory(indexDirName, true, lockFactory);
|
||||||
// fs1.setLockFactory(NoLockFactory.getNoLockFactory());
|
// fs1.setLockFactory(NoLockFactory.getNoLockFactory());
|
||||||
|
|
||||||
// First create a 1 doc index:
|
// First create a 1 doc index:
|
||||||
|
@ -295,6 +305,31 @@ public class TestLockFactory extends TestCase {
|
||||||
rmDir(indexDirName);
|
rmDir(indexDirName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify: NativeFSLockFactory works correctly
|
||||||
|
public void testNativeFSLockFactory() throws IOException {
|
||||||
|
|
||||||
|
// Make sure we get identical instances:
|
||||||
|
NativeFSLockFactory f = NativeFSLockFactory.getLockFactory();
|
||||||
|
NativeFSLockFactory f2 = NativeFSLockFactory.getLockFactory();
|
||||||
|
assertTrue("got different NativeFSLockFactory instances for same directory",
|
||||||
|
f == f2);
|
||||||
|
|
||||||
|
// Make sure we get identical locks:
|
||||||
|
f.setLockPrefix("test");
|
||||||
|
Lock l = f.makeLock("commit");
|
||||||
|
Lock l2 = f.makeLock("commit");
|
||||||
|
assertTrue("got different Lock instances for same lock name",
|
||||||
|
l == l2);
|
||||||
|
|
||||||
|
assertTrue("failed to obtain lock", l.obtain());
|
||||||
|
assertTrue("succeeded in obtaining lock twice", !l.obtain());
|
||||||
|
l.release();
|
||||||
|
|
||||||
|
// Make sure we can obtain it again:
|
||||||
|
assertTrue("failed to obtain lock", l.obtain());
|
||||||
|
l.release();
|
||||||
|
}
|
||||||
|
|
||||||
private class WriterThread extends Thread {
|
private class WriterThread extends Thread {
|
||||||
private Directory dir;
|
private Directory dir;
|
||||||
private int numIteration;
|
private int numIteration;
|
||||||
|
|
Loading…
Reference in New Issue