You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by th...@apache.org on 2009/12/10 15:08:33 UTC
svn commit: r889270 - in /jackrabbit/trunk/jackrabbit-core/src:
main/java/org/apache/jackrabbit/core/util/
test/java/org/apache/jackrabbit/core/util/
Author: thomasm
Date: Thu Dec 10 14:08:32 2009
New Revision: 889270
URL: http://svn.apache.org/viewvc?rev=889270&view=rev
Log:
JCR-2431 CooperativeFileLock improvements
Added:
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/util/CooperativeFileLockTest.java
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/CooperativeFileLock.java
jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/util/TestAll.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/CooperativeFileLock.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/CooperativeFileLock.java?rev=889270&r1=889269&r2=889270&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/CooperativeFileLock.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/util/CooperativeFileLock.java Thu Dec 10 14:08:32 2009
@@ -31,11 +31,11 @@
import javax.jcr.RepositoryException;
/**
- * The file lock is used to ensure a resource is only open once at any time.
- * It uses a cooperative locking protocol.
+ * The file lock is used to ensure a resource is only open once at any time.
+ * It uses a cooperative locking protocol.
*/
public class CooperativeFileLock implements RepositoryLockMechanism {
-
+
/**
* Logger instance.
*/
@@ -55,9 +55,11 @@
private boolean locked;
private volatile boolean stop;
+ private Thread watchdog;
+
/**
* Create a new file locking object using the given file name.
- *
+ *
* @param path basic path to append {@link #FILE_NAME} to.
*/
public void init(String path) {
@@ -68,7 +70,7 @@
* Lock the directory if possible.
* This method will also start a background watchdog thread.
* A file may only be locked once.
- *
+ *
* @throws RepositoryException if locking was not successful
*/
public synchronized void acquire() throws RepositoryException {
@@ -97,17 +99,16 @@
}
} catch (Exception e) {
LOG.warn("Error unlocking " + fileName, e);
+ } finally {
+ stop = true;
+ locked = false;
}
- stop = true;
- locked = false;
- }
-
- /**
- * This finalizer unlocks the file if necessary.
- */
- protected void finalize() {
- if (locked) {
- release();
+ try {
+ if (watchdog != null) {
+ watchdog.interrupt();
+ }
+ } catch (Exception e) {
+ LOG.debug("Error stopping watchdog " + fileName, e);
}
}
@@ -133,7 +134,7 @@
/**
* Load the properties file.
- *
+ *
* @return the properties object
*/
private Properties load() throws RepositoryException {
@@ -163,7 +164,14 @@
long last = f.lastModified();
long dist = System.currentTimeMillis() - last;
if (dist < -TIME_GRANULARITY) {
- throw error("Lock file modified in the future: dist=" + dist);
+ // lock file modified in the future -
+ // wait for a bit longer than usual
+ try {
+ Thread.sleep(2 * LOCK_SLEEP);
+ } catch (Exception e) {
+ LOG.debug("Sleep", e);
+ }
+ return;
} else if (dist > TIME_GRANULARITY) {
return;
}
@@ -186,9 +194,12 @@
if (!createNewFile(fileName)) {
waitUntilOld();
save();
- sleep(2 * LOCK_SLEEP);
- if (!load().equals(properties)) {
- throw error("Locked by another process");
+ // wait twice the watchdog sleep time
+ for (int i = 0; i < 8; i++) {
+ sleep(LOCK_SLEEP / 4);
+ if (!load().equals(properties)) {
+ throw error("Locked by another process");
+ }
}
delete(fileName);
if (!createNewFile(fileName)) {
@@ -201,7 +212,7 @@
stop = true;
throw error("Concurrent update");
}
- Thread watchdog = new Thread(new Runnable() {
+ watchdog = new Thread(new Runnable() {
public void run() {
try {
while (!stop) {
@@ -212,6 +223,12 @@
save();
}
Thread.sleep(LOCK_SLEEP);
+ } catch (OutOfMemoryError e) {
+ // ignore
+ } catch (InterruptedException e) {
+ // ignore
+ } catch (NullPointerException e) {
+ // ignore
} catch (Exception e) {
LOG.debug("Watchdog", e);
}
@@ -243,11 +260,11 @@
throw getException(e);
}
}
-
+
/**
* Create a new file, and retry if this doesn't work.
* If it still doesn't work after some time, this method returns false.
- *
+ *
* @param fileName the name of the file to create
* @return if the file was created
*/
@@ -263,11 +280,11 @@
}
return false;
}
-
+
/**
* Delete a file, and retry if this doesn't work.
* If it still doesn't work after some time, an exception is thrown.
- *
+ *
* @param fileName the name of the file to delete
* @throws RepositoryException if the file could not be deleted
*/
@@ -286,8 +303,8 @@
}
throw new RepositoryException("Could not delete file " + fileName);
}
- }
-
+ }
+
private static void wait(int i) {
if (i > 8) {
System.gc();
Added: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/util/CooperativeFileLockTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/util/CooperativeFileLockTest.java?rev=889270&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/util/CooperativeFileLockTest.java (added)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/util/CooperativeFileLockTest.java Thu Dec 10 14:08:32 2009
@@ -0,0 +1,64 @@
+/*
+ * 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.jackrabbit.core.util;
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.jcr.RepositoryException;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.io.FileUtils;
+
+/**
+ * Tests the cooperative file lock mechanism.
+ */
+public class CooperativeFileLockTest extends TestCase {
+
+ private static final String TEST_DIRECTORY = "target/tmp/testCooperativeFileLock";
+
+ public void tearDown() throws IOException {
+ setUp();
+ }
+
+ public void setUp() throws IOException {
+ FileUtils.deleteDirectory(new File(TEST_DIRECTORY));
+ }
+
+ public void testFileLock() throws RepositoryException {
+ int testRuns = 1;
+ for (int i = 0; i < testRuns; i++) {
+ new File(TEST_DIRECTORY).mkdirs();
+ CooperativeFileLock l1 = new CooperativeFileLock();
+ l1.init(TEST_DIRECTORY);
+ l1.acquire();
+ CooperativeFileLock l2 = new CooperativeFileLock();
+ l2.init(TEST_DIRECTORY);
+ try {
+ l2.acquire();
+ fail();
+ } catch (Exception e) {
+ // expected
+ }
+ l1.release();
+ l2.acquire();
+ l2.release();
+ }
+ }
+
+}
Modified: jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/util/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/util/TestAll.java?rev=889270&r1=889269&r2=889270&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/util/TestAll.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/test/java/org/apache/jackrabbit/core/util/TestAll.java Thu Dec 10 14:08:32 2009
@@ -33,6 +33,7 @@
public static Test suite() {
TestSuite suite = new TestSuite("Utility tests");
suite.addTestSuite(RepositoryLockTest.class);
+ suite.addTestSuite(CooperativeFileLockTest.class);
return suite;
}
}