Index: src/java/org/apache/lucene/store/FSDirectory.java =================================================================== --- src/java/org/apache/lucene/store/FSDirectory.java (revision 809390) +++ src/java/org/apache/lucene/store/FSDirectory.java (working copy) @@ -129,6 +129,9 @@ * Set whether Lucene's use of lock files is disabled. By default, * lock files are enabled. They should only be disabled if the index * is on a read-only medium like a CD-ROM. + * @deprecated Use a {@link #open(File, LockFactory)} or a constructor + * that takes a {@link LockFactory} and supply + * {@link NoLockFactory#getNoLockFactory}. */ public static void setDisableLocks(boolean doDisableLocks) { FSDirectory.disableLocks = doDisableLocks; @@ -138,6 +141,8 @@ * Returns whether Lucene's use of lock files is disabled. * @return true if locks are disabled, false if locks are enabled. * @see #setDisableLocks + * @deprecated Use a constructor that takes a {@link LockFactory} and + * supply {@link NoLockFactory#getNoLockFactory}. */ public static boolean getDisableLocks() { return FSDirectory.disableLocks; @@ -358,17 +363,23 @@ /** Create a new FSDirectory for the named location (ctor for subclasses). * @param path the path of the directory - * @param lockFactory the lock factory to use, or null for the default. + * @param lockFactory the lock factory to use, or null for the default + * ({@link NativeFSLockFactory}); * @throws IOException */ protected FSDirectory(File path, LockFactory lockFactory) throws IOException { path = getCanonicalPath(path); + // new ctors use always NativeFSLockFactory as default: + if (lockFactory == null) { + lockFactory = new NativeFSLockFactory(path); + } init(path, lockFactory); refCount = 1; } /** Creates an FSDirectory instance, trying to pick the * best implementation given the current environment. + * The directory returned uses the {@link NativeFSLockFactory}. * *

Currently this returns {@link NIOFSDirectory} * on non-Windows JREs and {@link SimpleFSDirectory} @@ -419,8 +430,6 @@ if (directory.exists() && !directory.isDirectory()) throw new NoSuchDirectoryException("file '" + directory + "' exists but is not a directory"); - boolean doClearLockID = false; - if (lockFactory == null) { if (disableLocks) { @@ -448,26 +457,26 @@ throw new IOException("unable to cast LockClass " + lockClassName + " instance to a LockFactory"); } - if (lockFactory instanceof NativeFSLockFactory) { - ((NativeFSLockFactory) lockFactory).setLockDir(path); - } else if (lockFactory instanceof SimpleFSLockFactory) { - ((SimpleFSLockFactory) lockFactory).setLockDir(path); + if (lockFactory instanceof FSLockFactory) { + ((FSLockFactory) lockFactory).setLockDir(directory); } } else { // Our default lock is SimpleFSLockFactory; // default lockDir is our index directory: - lockFactory = new SimpleFSLockFactory(path); - doClearLockID = true; + lockFactory = new SimpleFSLockFactory(directory); } } } setLockFactory(lockFactory); - - if (doClearLockID) { - // Clear the prefix because write.lock will be - // stored in our directory: - lockFactory.setLockPrefix(null); + + // for filesystem based LockFactory, delete the lockPrefix, if the locks are placed + // in index dir. + if (lockFactory instanceof FSLockFactory) { + File dir = ((FSLockFactory) lockFactory).getLockDir(); + if (dir != null & dir.getCanonicalPath().equals(directory.getCanonicalPath())) { + lockFactory.setLockPrefix(null); + } } } Index: src/java/org/apache/lucene/store/FSLockFactory.java =================================================================== --- src/java/org/apache/lucene/store/FSLockFactory.java (revision 0) +++ src/java/org/apache/lucene/store/FSLockFactory.java (revision 0) @@ -0,0 +1,51 @@ +package org.apache.lucene.store; + +/** + * 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. + */ + +import java.io.File; +import java.io.IOException; + +/** + * Base class for file system based Locking implementation. + */ + +public abstract class FSLockFactory extends LockFactory { + + /** + * Directory specified by org.apache.lucene.lockDir + * system property. If that is not set, then java.io.tmpdir + * system property is used. + */ + protected File lockDir; + + /** + * Set the lock directory. This is protected and is + * only used externally by FSDirectory when creating this + * LockFactory via the System property + * org.apache.lucene.store.FSDirectoryLockFactoryClass. + * It is also used by the ctor. + */ + protected void setLockDir(File lockDir) { + this.lockDir = lockDir; + } + + public File getLockDir() { + return lockDir; + } + +} Property changes on: src\java\org\apache\lucene\store\FSLockFactory.java ___________________________________________________________________ Added: svn:keywords + Date Author Id Revision HeadURL Added: svn:eol-style + native Index: src/java/org/apache/lucene/store/LockFactory.java =================================================================== --- src/java/org/apache/lucene/store/LockFactory.java (revision 809390) +++ src/java/org/apache/lucene/store/LockFactory.java (working copy) @@ -35,7 +35,7 @@ public abstract class LockFactory { - protected String lockPrefix = ""; + protected String lockPrefix = null; /** * Set the prefix in use for all locks created in this Index: src/java/org/apache/lucene/store/MMapDirectory.java =================================================================== --- src/java/org/apache/lucene/store/MMapDirectory.java (revision 809390) +++ src/java/org/apache/lucene/store/MMapDirectory.java (working copy) @@ -74,14 +74,15 @@ /** 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. + * @param lockFactory the lock factory to use, or null for the default + * ({@link NativeFSLockFactory}); * @throws IOException */ public MMapDirectory(File path, LockFactory lockFactory) throws IOException { super(path, lockFactory); } - /** Create a new MMapDirectory for the named location and the default lock factory. + /** Create a new MMapDirectory for the named location and {@link NativeFSLockFactory}. * * @param path the path of the directory * @throws IOException Index: src/java/org/apache/lucene/store/NativeFSLockFactory.java =================================================================== --- src/java/org/apache/lucene/store/NativeFSLockFactory.java (revision 809390) +++ src/java/org/apache/lucene/store/NativeFSLockFactory.java (working copy) @@ -55,35 +55,40 @@ * @see LockFactory */ -public class NativeFSLockFactory extends LockFactory { +public class NativeFSLockFactory extends FSLockFactory { - /** - * Directory specified by org.apache.lucene.lockDir - * system property. If that is not set, then java.io.tmpdir - * system property is used. - */ + private volatile boolean tested = false; - private File lockDir; - // 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 { + // time). + private synchronized void acquireTestLock() { + if (tested) return; + tested = true; + + // Ensure that lockDir exists and is a directory. + if (!lockDir.exists()) { + if (!lockDir.mkdirs()) + throw new RuntimeException("Cannot create directory: " + + lockDir.getAbsolutePath()); + } else if (!lockDir.isDirectory()) { + throw new RuntimeException("Found regular file where directory expected: " + + lockDir.getAbsolutePath()); + } + String randomLockName = "lucene-" + Long.toString(new Random().nextInt(), Character.MAX_RADIX) + "-test.lock"; Lock l = makeLock(randomLockName); try { l.obtain(); + l.release(); } catch (IOException e) { - IOException e2 = new IOException("Failed to acquire random test lock; please verify filesystem for lock directory '" + lockDir + "' supports locking"); + RuntimeException e2 = new RuntimeException("Failed to acquire random test lock; please verify filesystem for lock directory '" + lockDir + "' supports locking"); e2.initCause(e); throw e2; - } - - l.release(); + } } /** @@ -117,30 +122,8 @@ setLockDir(lockDir); } - /** - * Set the lock directory. This is package-private and is - * only used externally by FSDirectory when creating this - * LockFactory via the System property - * org.apache.lucene.store.FSDirectoryLockFactoryClass. - */ - void setLockDir(File lockDir) throws IOException { - this.lockDir = lockDir; - if (lockDir != null) { - // 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(); - } - } - public synchronized Lock makeLock(String lockName) { + acquireTestLock(); if (lockPrefix != null) lockName = lockPrefix + "-n-" + lockName; return new NativeFSLock(lockDir, lockName); @@ -188,9 +171,13 @@ path = new File(lockDir, lockFileName); } + private synchronized boolean lockExists() { + return lock != null; + } + public synchronized boolean obtain() throws IOException { - if (isLocked()) { + if (lockExists()) { // Our instance is already locked: return false; } @@ -276,7 +263,7 @@ } } finally { - if (markedHeld && !isLocked()) { + if (markedHeld && !lockExists()) { synchronized(LOCK_HELD) { if (LOCK_HELD.contains(canonicalPath)) { LOCK_HELD.remove(canonicalPath); @@ -284,11 +271,11 @@ } } } - return isLocked(); + return lockExists(); } public synchronized void release() throws IOException { - if (isLocked()) { + if (lockExists()) { try { lock.release(); } finally { @@ -313,7 +300,19 @@ } public synchronized boolean isLocked() { - return lock != null; + // the test for is isLocked is not directly possible with native file locks: + + // if we have a lock instance in this class, it is for sure locked: + if (lockExists()) return true; + + // else try to obtain and release (if was locked) the lock to test + try { + boolean obtained = obtain(); + if (obtained) release(); + return !obtained; + } catch (IOException ioe) { + return false; + } } public String toString() { Index: src/java/org/apache/lucene/store/NIOFSDirectory.java =================================================================== --- src/java/org/apache/lucene/store/NIOFSDirectory.java (revision 809390) +++ src/java/org/apache/lucene/store/NIOFSDirectory.java (working copy) @@ -43,14 +43,15 @@ /** 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. + * @param lockFactory the lock factory to use, or null for the default + * ({@link NativeFSLockFactory}); * @throws IOException */ public NIOFSDirectory(File path, LockFactory lockFactory) throws IOException { super(path, lockFactory); } - /** Create a new NIOFSDirectory for the named location and the default lock factory. + /** Create a new NIOFSDirectory for the named location and {@link NativeFSLockFactory}. * * @param path the path of the directory * @throws IOException Index: src/java/org/apache/lucene/store/SimpleFSDirectory.java =================================================================== --- src/java/org/apache/lucene/store/SimpleFSDirectory.java (revision 809390) +++ src/java/org/apache/lucene/store/SimpleFSDirectory.java (working copy) @@ -32,14 +32,15 @@ /** Create a new SimpleFSDirectory for the named location. * * @param path the path of the directory - * @param lockFactory the lock factory to use, or null for the default. + * @param lockFactory the lock factory to use, or null for the default + * ({@link NativeFSLockFactory}); * @throws IOException */ public SimpleFSDirectory(File path, LockFactory lockFactory) throws IOException { super(path, lockFactory); } - /** Create a new SimpleFSDirectory for the named location and the default lock factory. + /** Create a new SimpleFSDirectory for the named location and {@link NativeFSLockFactory}. * * @param path the path of the directory * @throws IOException Index: src/java/org/apache/lucene/store/SimpleFSLockFactory.java =================================================================== --- src/java/org/apache/lucene/store/SimpleFSLockFactory.java (revision 809390) +++ src/java/org/apache/lucene/store/SimpleFSLockFactory.java (working copy) @@ -22,8 +22,7 @@ /** *

Implements {@link LockFactory} using {@link - * File#createNewFile()}. This is the default LockFactory - * for {@link FSDirectory}.

+ * File#createNewFile()}.

* *

NOTE: the javadocs @@ -52,17 +51,9 @@ * @see LockFactory */ -public class SimpleFSLockFactory extends LockFactory { +public class SimpleFSLockFactory extends FSLockFactory { /** - * Directory specified by org.apache.lucene.lockDir - * system property. If that is not set, then java.io.tmpdir - * system property is used. - */ - - private File lockDir; - - /** * Create a SimpleFSLockFactory instance, with null (unset) * lock directory. This is package-private and is only * used by FSDirectory when creating this LockFactory via @@ -90,16 +81,6 @@ setLockDir(lockDir); } - /** - * Set the lock directory. This is package-private and is - * only used externally by FSDirectory when creating this - * LockFactory via the System property - * org.apache.lucene.store.FSDirectoryLockFactoryClass. - */ - void setLockDir(File lockDir) throws IOException { - this.lockDir = lockDir; - } - public Lock makeLock(String lockName) { if (lockPrefix != null) { lockName = lockPrefix + "-" + lockName; Index: src/test/org/apache/lucene/store/TestLockFactory.java =================================================================== --- src/test/org/apache/lucene/store/TestLockFactory.java (revision 809390) +++ src/test/org/apache/lucene/store/TestLockFactory.java (working copy) @@ -386,21 +386,21 @@ l.release(); } - // Verify: NativeFSLockFactory assigns different lock - // prefixes to different directories: + // Verify: NativeFSLockFactory assigns null as lockPrefix if the lockDir is inside directory public void testNativeFSLockFactoryPrefix() throws IOException { - // Make sure we get identical instances: File fdir1 = _TestUtil.getTempDir("TestLockFactory.8"); + File fdir2 = _TestUtil.getTempDir("TestLockFactory.8.Lockdir"); Directory dir1 = FSDirectory.open(fdir1, new NativeFSLockFactory(fdir1)); - File fdir2 = _TestUtil.getTempDir("TestLockFactory.9"); - Directory dir2 = FSDirectory.open(fdir2, new NativeFSLockFactory(fdir2)); + // same directory, but locks are stored somewhere else. The prefix of the lock factory should != null + Directory dir2 = FSDirectory.open(fdir1, new NativeFSLockFactory(fdir2)); String prefix1 = dir1.getLockFactory().getLockPrefix(); + assertNull("Lock prefix for lockDir same as directory should be null", prefix1); + String prefix2 = dir2.getLockFactory().getLockPrefix(); + assertNotNull("Lock prefix for lockDir outside of directory should be not null", prefix2); - assertTrue("Native Lock Factories are incorrectly shared: dir1 and dir2 have same lock prefix '" + prefix1 + "'; they should be different", - !prefix1.equals(prefix2)); _TestUtil.rmDir(fdir1); _TestUtil.rmDir(fdir2); }