⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nativefslockfactory.java

📁 Lucene a java open-source SearchEngine Framework
💻 JAVA
字号:
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;import java.util.Random;/** * <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 LockFactory {  /**   * Directory specified by <code>org.apache.lucene.lockDir</code>   * system property.  If that is not set, then <code>java.io.tmpdir</code>   * system property is used.   */  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 {    String randomLockName = "lucene-" + Long.toString(new Random().nextInt(), Character.MAX_RADIX) + "-test.lock";        Lock l = makeLock(randomLockName);    try {      l.obtain();    } catch (IOException e) {      IOException e2 = new IOException("Failed to acquire random test lock; please verify filesystem for lock directory '" + lockDir + "' supports locking");      e2.initCause(e);      throw e2;    }    l.release();  }  /**   * Create a NativeFSLockFactory instance, with null (unset)   * lock directory.  This is package-private and is only   * used by FSDirectory when creating this LockFactory via   * the System property   * org.apache.lucene.store.FSDirectoryLockFactoryClass.   */  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);  }  /**   * 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) {    if (lockPrefix != null)      lockName = lockPrefix + "-n-" + lockName;    return new NativeFSLock(lockDir, lockName);  }  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()) {      if (lockPrefix != null) {        lockName = lockPrefix + "-n-" + lockName;      }      File lockFile = new File(lockDir, lockName);      if (lockFile.exists() && !lockFile.delete()) {        throw new IOException("Cannot delete " + lockFile);      }    }  }};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.  To ensure 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.   */  private static HashSet LOCK_HELD = new HashSet();  public NativeFSLock(File lockDir, String lockFileName) {    this.lockDir = lockDir;    path = new File(lockDir, lockFileName);  }  public synchronized boolean obtain() throws IOException {    if (isLocked()) {      // 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 intermittant "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            // intermittant "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 && !isLocked()) {        synchronized(LOCK_HELD) {          if (LOCK_HELD.contains(canonicalPath)) {            LOCK_HELD.remove(canonicalPath);          }        }      }    }    return isLocked();  }  public synchronized void release() throws IOException {    if (isLocked()) {      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());            }          }        }      }      if (!path.delete())        throw new LockReleaseFailedException("failed to delete " + path);    }  }  public synchronized boolean isLocked() {    return lock != null;  }  public String toString() {    return "NativeFSLock@" + path;  }  public void finalize() throws Throwable {    try {      if (isLocked()) {        release();      }    } finally {      super.finalize();    }  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -