pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.4.0 / lucene / src / java / org / apache / lucene / store / NativeFSLockFactory.java
diff --git a/lucene-java-3.4.0/lucene/src/java/org/apache/lucene/store/NativeFSLockFactory.java b/lucene-java-3.4.0/lucene/src/java/org/apache/lucene/store/NativeFSLockFactory.java
deleted file mode 100755 (executable)
index f4f63e6..0000000
+++ /dev/null
@@ -1,330 +0,0 @@
-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.nio.channels.FileChannel;
-import java.nio.channels.FileLock;
-import java.io.File;
-import java.io.RandomAccessFile;
-import java.io.IOException;
-import java.util.HashSet;
-
-/**
- * <p>Implements {@link LockFactory} using native OS file
- * locks.  Note that because this LockFactory relies on
- * java.nio.* APIs for locking, any problems with those APIs
- * will cause locking to fail.  Specifically, on certain NFS
- * environments the java.nio.* locks will fail (the lock can
- * incorrectly be double acquired) whereas {@link
- * SimpleFSLockFactory} worked perfectly in those same
- * environments.  For NFS based access to an index, it's
- * recommended that you try {@link SimpleFSLockFactory}
- * first and work around the one limitation that a lock file
- * could be left when the JVM exits abnormally.</p>
- *
- * <p>The primary benefit of {@link NativeFSLockFactory} is
- * that lock files will be properly removed (by the OS) if
- * the JVM has an abnormal exit.</p>
- * 
- * <p>Note that, unlike {@link 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>If you suspect that this or any other LockFactory is
- * not working properly in your environment, you can easily
- * test it by using {@link VerifyingLockFactory}, {@link
- * LockVerifyServer} and {@link LockStressTest}.</p>
- *
- * @see LockFactory
- */
-
-public class NativeFSLockFactory extends FSLockFactory {
-
-  /**
-   * Create a NativeFSLockFactory instance, with null (unset)
-   * lock directory. When you pass this factory to a {@link FSDirectory}
-   * subclass, the lock directory is automatically set to the
-   * directory itself. Be sure to create one instance for each directory
-   * your create!
-   */
-  public NativeFSLockFactory() throws IOException {
-    this((File) null);
-  }
-
-  /**
-   * Create a NativeFSLockFactory instance, storing lock
-   * files into the specified lockDirName:
-   *
-   * @param lockDirName where lock files are created.
-   */
-  public NativeFSLockFactory(String lockDirName) throws IOException {
-    this(new File(lockDirName));
-  }
-
-  /**
-   * Create a NativeFSLockFactory instance, storing lock
-   * files into the specified lockDir:
-   * 
-   * @param lockDir where lock files are created.
-   */
-  public NativeFSLockFactory(File lockDir) throws IOException {
-    setLockDir(lockDir);
-  }
-
-  @Override
-  public synchronized Lock makeLock(String lockName) {
-    if (lockPrefix != null)
-      lockName = lockPrefix + "-" + lockName;
-    return new NativeFSLock(lockDir, lockName);
-  }
-
-  @Override
-  public void clearLock(String lockName) 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()) {
-      
-      // Try to release the lock first - if it's held by another process, this
-      // method should not silently fail.
-      // NOTE: makeLock fixes the lock name by prefixing it w/ lockPrefix.
-      // Therefore it should be called before the code block next which prefixes
-      // the given name.
-      makeLock(lockName).release();
-
-      if (lockPrefix != null) {
-        lockName = lockPrefix + "-" + lockName;
-      }
-      
-      // As mentioned above, we don't care if the deletion of the file failed.
-      new File(lockDir, lockName).delete();
-    }
-  }
-}
-
-class NativeFSLock extends Lock {
-
-  private RandomAccessFile f;
-  private FileChannel channel;
-  private FileLock lock;
-  private File path;
-  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 (locks are tracked per 
-   * FileChannel instance in Java 1.4/1.5). Even using the same 
-   * FileChannel instance is not completely thread-safe with Java 
-   * 1.4/1.5 though. To work around this, we have a single (static) 
-   * HashSet that contains the file paths of all currently 
-   * locked locks.  This protects against possible cases 
-   * where different Directory instances in one JVM (each 
-   * with their own NativeFSLockFactory instance) have set 
-   * the same lock dir and lock prefix. However, this will not 
-   * work when LockFactorys are created by different 
-   * classloaders (eg multiple webapps). 
-   * 
-   * TODO: Java 1.6 tracks system wide locks in a thread safe manner 
-   * (same FileChannel instance or not), so we may want to 
-   * change this when Lucene moves to Java 1.6.
-   */
-  private static HashSet<String> LOCK_HELD = new HashSet<String>();
-
-  public NativeFSLock(File lockDir, String lockFileName) {
-    this.lockDir = lockDir;
-    path = new File(lockDir, lockFileName);
-  }
-
-  private synchronized boolean lockExists() {
-    return lock != null;
-  }
-
-  @Override
-  public synchronized boolean obtain() throws IOException {
-
-    if (lockExists()) {
-      // Our instance is 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());
-    }
-
-    String canonicalPath = path.getCanonicalPath();
-
-    boolean markedHeld = false;
-
-    try {
-
-      // Make sure nobody else in-process has this lock held
-      // already, and, mark it held if not:
-
-      synchronized(LOCK_HELD) {
-        if (LOCK_HELD.contains(canonicalPath)) {
-          // Someone else in this JVM already has the lock:
-          return false;
-        } else {
-          // This "reserves" the fact that we are the one
-          // thread trying to obtain this lock, so we own
-          // the only instance of a channel against this
-          // file:
-          LOCK_HELD.add(canonicalPath);
-          markedHeld = true;
-        }
-      }
-
-      try {
-        f = new RandomAccessFile(path, "rw");
-      } catch (IOException e) {
-        // On Windows, we can get intermittent "Access
-        // Denied" here.  So, we treat this as failure to
-        // acquire the lock, but, store the reason in case
-        // there is in fact a real error case.
-        failureReason = e;
-        f = null;
-      }
-
-      if (f != null) {
-        try {
-          channel = f.getChannel();
-          try {
-            lock = channel.tryLock();
-          } catch (IOException e) {
-            // At least on OS X, we will sometimes get an
-            // intermittent "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;
-            }
-          }
-        }
-      }
-
-    } finally {
-      if (markedHeld && !lockExists()) {
-        synchronized(LOCK_HELD) {
-          if (LOCK_HELD.contains(canonicalPath)) {
-            LOCK_HELD.remove(canonicalPath);
-          }
-        }
-      }
-    }
-    return lockExists();
-  }
-
-  @Override
-  public synchronized void release() throws IOException {
-    if (lockExists()) {
-      try {
-        lock.release();
-      } finally {
-        lock = null;
-        try {
-          channel.close();
-        } finally {
-          channel = null;
-          try {
-            f.close();
-          } finally {
-            f = null;
-            synchronized(LOCK_HELD) {
-              LOCK_HELD.remove(path.getCanonicalPath());
-            }
-          }
-        }
-      }
-      // LUCENE-2421: we don't care anymore if the file cannot be deleted
-      // because it's held up by another process (e.g. AntiVirus). NativeFSLock
-      // does not depend on the existence/absence of the lock file
-      path.delete();
-    } else {
-      // if we don't hold the lock, and somebody still called release(), for
-      // example as a result of calling IndexWriter.unlock(), we should attempt
-      // to obtain the lock and release it. If the obtain fails, it means the
-      // lock cannot be released, and we should throw a proper exception rather
-      // than silently failing/not doing anything.
-      boolean obtained = false;
-      try {
-        if (!(obtained = obtain())) {
-          throw new LockReleaseFailedException(
-              "Cannot forcefully unlock a NativeFSLock which is held by another indexer component: "
-                  + path);
-        }
-      } finally {
-        if (obtained) {
-          release();
-        }
-      }
-    }
-  }
-
-  @Override
-  public synchronized boolean isLocked() {
-    // The test for is isLocked is not directly possible with native file locks:
-    
-    // First a shortcut, if a lock reference in this instance is available
-    if (lockExists()) return true;
-    
-    // Look if lock file is present; if not, there can definitely be no lock!
-    if (!path.exists()) return false;
-    
-    // Try to obtain and release (if was locked) the lock
-    try {
-      boolean obtained = obtain();
-      if (obtained) release();
-      return !obtained;
-    } catch (IOException ioe) {
-      return false;
-    }    
-  }
-
-  @Override
-  public String toString() {
-    return "NativeFSLock@" + path;
-  }
-}