mirror of https://github.com/apache/lucene.git
added ability to wait on any Lock. changed write.lock wait to 1 sec from none.
git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@150005 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
7e199825c1
commit
b22cd77890
|
@ -100,7 +100,7 @@ public abstract class IndexReader {
|
|||
/** Returns an IndexReader reading the index in the given Directory. */
|
||||
public static IndexReader open(final Directory directory) throws IOException{
|
||||
synchronized (directory) { // in- & inter-process sync
|
||||
return (IndexReader)new Lock.With(directory.makeLock("commit.lock")) {
|
||||
return (IndexReader)new Lock.With(directory.makeLock("commit.lock"), IndexWriter.COMMIT_LOCK_TIMEOUT) {
|
||||
public Object doBody() throws IOException {
|
||||
SegmentInfos infos = new SegmentInfos();
|
||||
infos.read(directory);
|
||||
|
@ -255,7 +255,7 @@ public abstract class IndexReader {
|
|||
public final synchronized void delete(int docNum) throws IOException {
|
||||
if (writeLock == null) {
|
||||
Lock writeLock = directory.makeLock("write.lock");
|
||||
if (!writeLock.obtain()) // obtain write lock
|
||||
if (!writeLock.obtain(IndexWriter.WRITE_LOCK_TIMEOUT)) // obtain write lock
|
||||
throw new IOException("Index locked for write: " + writeLock);
|
||||
this.writeLock = writeLock;
|
||||
}
|
||||
|
|
|
@ -87,6 +87,9 @@ import org.apache.lucene.analysis.Analyzer;
|
|||
*/
|
||||
|
||||
public class IndexWriter {
|
||||
public static long WRITE_LOCK_TIMEOUT = 1000;
|
||||
public static long COMMIT_LOCK_TIMEOUT = 10000;
|
||||
|
||||
private Directory directory; // where this index resides
|
||||
private Analyzer analyzer; // how to analyze text
|
||||
|
||||
|
@ -97,7 +100,7 @@ public class IndexWriter {
|
|||
|
||||
private Lock writeLock;
|
||||
|
||||
/** Expert: Set the Similarity implementation used by this IndexWriter.
|
||||
/** Expert: Set the Similarity implementation used by this IndexWriter.
|
||||
*
|
||||
* @see Similarity#setDefault(Similarity)
|
||||
*/
|
||||
|
@ -141,12 +144,12 @@ public class IndexWriter {
|
|||
analyzer = a;
|
||||
|
||||
Lock writeLock = directory.makeLock("write.lock");
|
||||
if (!writeLock.obtain()) // obtain write lock
|
||||
if (!writeLock.obtain(WRITE_LOCK_TIMEOUT)) // obtain write lock
|
||||
throw new IOException("Index locked for write: " + writeLock);
|
||||
this.writeLock = writeLock; // save it
|
||||
|
||||
synchronized (directory) { // in- & inter-process sync
|
||||
new Lock.With(directory.makeLock("commit.lock")) {
|
||||
new Lock.With(directory.makeLock("commit.lock"), COMMIT_LOCK_TIMEOUT) {
|
||||
public Object doBody() throws IOException {
|
||||
if (create)
|
||||
segmentInfos.write(directory);
|
||||
|
@ -365,7 +368,7 @@ public class IndexWriter {
|
|||
directory));
|
||||
|
||||
synchronized (directory) { // in- & inter-process sync
|
||||
new Lock.With(directory.makeLock("commit.lock")) {
|
||||
new Lock.With(directory.makeLock("commit.lock"), COMMIT_LOCK_TIMEOUT) {
|
||||
public Object doBody() throws IOException {
|
||||
segmentInfos.write(directory); // commit before deleting
|
||||
deleteSegments(segmentsToDelete); // delete now-unused segments
|
||||
|
|
|
@ -119,7 +119,7 @@ final class SegmentReader extends IndexReader {
|
|||
final synchronized void doClose() throws IOException {
|
||||
if (deletedDocsDirty) {
|
||||
synchronized (directory) { // in- & inter-process sync
|
||||
new Lock.With(directory.makeLock("commit.lock")) {
|
||||
new Lock.With(directory.makeLock("commit.lock"), IndexWriter.COMMIT_LOCK_TIMEOUT) {
|
||||
public Object doBody() throws IOException {
|
||||
deletedDocs.write(directory, segment + ".tmp");
|
||||
directory.renameFile(segment + ".tmp", segment + ".del");
|
||||
|
|
|
@ -54,6 +54,8 @@ package org.apache.lucene.store;
|
|||
* <http://www.apache.org/>.
|
||||
*/
|
||||
|
||||
import org.apache.lucene.index.IndexWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/** An interprocess mutex lock.
|
||||
|
@ -70,12 +72,39 @@ import java.io.IOException;
|
|||
*/
|
||||
|
||||
public abstract class Lock {
|
||||
/** Attempt to obtain exclusive access.
|
||||
*
|
||||
public static long LOCK_POLL_INTERVAL = 1000;
|
||||
|
||||
/** Attempt to obtain exclusive access and immediately return
|
||||
* upon success or failure.
|
||||
* @return true iff exclusive access is obtained
|
||||
*/
|
||||
public abstract boolean obtain() throws IOException;
|
||||
|
||||
/** Attempt to obtain an exclusive lock within amount
|
||||
* of time given. Currently polls once per second until
|
||||
* lockWaitTimeout is passed.
|
||||
* @param lockWaitTimeout length of time to wait in ms
|
||||
* @return true if lock was obtained
|
||||
* @throws IOException if lock wait times out or obtain() throws an IOException
|
||||
*/
|
||||
public boolean obtain(long lockWaitTimeout) throws IOException {
|
||||
boolean locked = obtain();
|
||||
int maxSleepCount = (int)(lockWaitTimeout / LOCK_POLL_INTERVAL);
|
||||
int sleepCount = 0;
|
||||
while (!locked) {
|
||||
if (++sleepCount == maxSleepCount) {
|
||||
throw new IOException("Lock obtain timed out");
|
||||
}
|
||||
try {
|
||||
Thread.sleep(LOCK_POLL_INTERVAL);
|
||||
} catch (InterruptedException e) {
|
||||
throw new IOException(e.toString());
|
||||
}
|
||||
locked = obtain();
|
||||
}
|
||||
return locked;
|
||||
}
|
||||
|
||||
/** Release exclusive access. */
|
||||
public abstract void release();
|
||||
|
||||
|
@ -87,12 +116,21 @@ public abstract class Lock {
|
|||
/** Utility class for executing code with exclusive access. */
|
||||
public abstract static class With {
|
||||
private Lock lock;
|
||||
private int sleepInterval = 1000;
|
||||
private int maxSleeps = 10;
|
||||
private long lockWaitTimeout;
|
||||
|
||||
/** Constructs an executor that will grab the named lock.
|
||||
* Defaults lockWaitTimeout to Lock.COMMIT_LOCK_TIMEOUT.
|
||||
* @deprecated Kept only to avoid breaking existing code.
|
||||
*/
|
||||
public With(Lock lock)
|
||||
{
|
||||
this(lock, IndexWriter.COMMIT_LOCK_TIMEOUT);
|
||||
}
|
||||
|
||||
/** Constructs an executor that will grab the named lock. */
|
||||
public With(Lock lock) {
|
||||
public With(Lock lock, long lockWaitTimeout) {
|
||||
this.lock = lock;
|
||||
this.lockWaitTimeout = lockWaitTimeout;
|
||||
}
|
||||
|
||||
/** Code to execute with exclusive access. */
|
||||
|
@ -100,29 +138,16 @@ public abstract class Lock {
|
|||
|
||||
/** Calls {@link #doBody} while <i>lock</i> is obtained. Blocks if lock
|
||||
* cannot be obtained immediately. Retries to obtain lock once per second
|
||||
* until it is obtained, or until it has tried ten times. */
|
||||
* until it is obtained, or until it has tried ten times. Lock is released when
|
||||
* {@link #doBody} exits. */
|
||||
public Object run() throws IOException {
|
||||
boolean locked = false;
|
||||
try {
|
||||
locked = lock.obtain();
|
||||
int sleepCount = 0;
|
||||
while (!locked) {
|
||||
if (++sleepCount == maxSleeps) {
|
||||
throw new IOException("Timed out waiting for: " + lock);
|
||||
}
|
||||
try {
|
||||
Thread.sleep(sleepInterval);
|
||||
} catch (InterruptedException e) {
|
||||
throw new IOException(e.toString());
|
||||
}
|
||||
locked = lock.obtain();
|
||||
}
|
||||
|
||||
return doBody();
|
||||
|
||||
locked = lock.obtain(lockWaitTimeout);
|
||||
return doBody();
|
||||
} finally {
|
||||
if (locked)
|
||||
lock.release();
|
||||
if (locked)
|
||||
lock.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue