diff --git a/CHANGES.txt b/CHANGES.txt index 7a3e345b053..9ebc7d1430a 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -144,6 +144,10 @@ Bug fixes timeout argument is very large (eg Long.MAX_VALUE). Also added Lock.LOCK_OBTAIN_WAIT_FOREVER constant to never timeout. (Nikolay Diakov via Mike McCandless) + +23. LUCENE-1050: Throw LockReleaseFailedException in + Simple/NativeFSLockFactory if we fail to delete the lock file when + releasing the lock. (Nikolay Diakov via Mike McCandless) New features diff --git a/src/java/org/apache/lucene/index/IndexWriter.java b/src/java/org/apache/lucene/index/IndexWriter.java index cf0e2d78d88..f6c440d1446 100644 --- a/src/java/org/apache/lucene/index/IndexWriter.java +++ b/src/java/org/apache/lucene/index/IndexWriter.java @@ -1220,11 +1220,6 @@ public class IndexWriter { if (infoStream != null) message("at close: " + segString()); - if (writeLock != null) { - writeLock.release(); // release write lock - writeLock = null; - } - closed = true; docWriter = null; synchronized(this) { @@ -1233,6 +1228,13 @@ public class IndexWriter { if (closeDir) directory.close(); + + if (writeLock != null) { + writeLock.release(); // release write lock + writeLock = null; + } + closed = true; + } finally { synchronized(this) { if (!closed) diff --git a/src/java/org/apache/lucene/store/Lock.java b/src/java/org/apache/lucene/store/Lock.java index 79087c31d7e..bd62d6e41df 100644 --- a/src/java/org/apache/lucene/store/Lock.java +++ b/src/java/org/apache/lucene/store/Lock.java @@ -99,7 +99,7 @@ public abstract class Lock { } /** Releases exclusive access. */ - public abstract void release(); + public abstract void release() throws IOException; /** Returns true if the resource is currently locked. Note that one must * still call {@link #obtain()} before using the resource. */ diff --git a/src/java/org/apache/lucene/store/LockReleaseFailedException.java b/src/java/org/apache/lucene/store/LockReleaseFailedException.java new file mode 100644 index 00000000000..4f15b4800e1 --- /dev/null +++ b/src/java/org/apache/lucene/store/LockReleaseFailedException.java @@ -0,0 +1,31 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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. + */ + +package org.apache.lucene.store; + +import java.io.IOException; + +/** + * This exception is thrown when the write.lock + * could not be released. + * @see Lock#release(). + */ +public class LockReleaseFailedException extends IOException { + public LockReleaseFailedException(String message) { + super(message); + } +} diff --git a/src/java/org/apache/lucene/store/NativeFSLockFactory.java b/src/java/org/apache/lucene/store/NativeFSLockFactory.java index d34f5aada66..d73ef436ab2 100755 --- a/src/java/org/apache/lucene/store/NativeFSLockFactory.java +++ b/src/java/org/apache/lucene/store/NativeFSLockFactory.java @@ -287,33 +287,28 @@ class NativeFSLock extends Lock { return isLocked(); } - public synchronized void release() { - try { - if (isLocked()) { + public synchronized void release() throws IOException { + if (isLocked()) { + try { + lock.release(); + } finally { + lock = null; try { - lock.release(); + channel.close(); } finally { - lock = null; + channel = null; try { - channel.close(); + f.close(); } finally { - channel = null; - try { - f.close(); - } finally { - f = null; - synchronized(LOCK_HELD) { - LOCK_HELD.remove(path.getCanonicalPath()); - } + f = null; + synchronized(LOCK_HELD) { + LOCK_HELD.remove(path.getCanonicalPath()); } } } - path.delete(); } - } catch (IOException e) { - // Not sure how to better message/handle this without - // changing API? - throw new RuntimeException(e); + if (!path.delete()) + throw new LockReleaseFailedException("failed to delete " + path); } } diff --git a/src/java/org/apache/lucene/store/SimpleFSLockFactory.java b/src/java/org/apache/lucene/store/SimpleFSLockFactory.java index 8c8fc775b0f..68ef6a99512 100755 --- a/src/java/org/apache/lucene/store/SimpleFSLockFactory.java +++ b/src/java/org/apache/lucene/store/SimpleFSLockFactory.java @@ -144,8 +144,9 @@ class SimpleFSLock extends Lock { return lockFile.createNewFile(); } - public void release() { - lockFile.delete(); + public void release() throws LockReleaseFailedException { + if (!lockFile.delete()) + throw new LockReleaseFailedException("failed to delete " + lockFile); } public boolean isLocked() { diff --git a/src/java/org/apache/lucene/store/VerifyingLockFactory.java b/src/java/org/apache/lucene/store/VerifyingLockFactory.java index ef674c2bda0..6f9f45eea3f 100644 --- a/src/java/org/apache/lucene/store/VerifyingLockFactory.java +++ b/src/java/org/apache/lucene/store/VerifyingLockFactory.java @@ -85,7 +85,7 @@ public class VerifyingLockFactory extends LockFactory { return lock.isLocked(); } - public synchronized void release() { + public synchronized void release() throws IOException { if (isLocked()) { verify((byte) 0); lock.release(); diff --git a/src/test/org/apache/lucene/store/TestLockFactory.java b/src/test/org/apache/lucene/store/TestLockFactory.java index 66b0136b67e..6d125bea518 100755 --- a/src/test/org/apache/lucene/store/TestLockFactory.java +++ b/src/test/org/apache/lucene/store/TestLockFactory.java @@ -188,7 +188,12 @@ public class TestLockFactory extends LuceneTestCase { writer.close(); if (writer2 != null) { + try { writer2.close(); + fail("writer2.close() should have hit LockReleaseFailedException"); + } catch (LockReleaseFailedException e) { + // expected + } } // Cleanup