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

📄 lockfile.java

📁 纯Java的数据库
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
 * limitations/capabilites, as well as under usability considerations and * external security or operating constraints that may need to be imposed.<p> * * Alternate approaches that have been considered and rejected for now * include: <p> * * <ul> *    <li>Socket-based locks (with/without broadcast protocol) *    <li>Pure NIO locking *    <li>Simple lock file (no heartbeat or polling) *    <li>JNI and native configuration alternatives * </ul> * * Of course, discussions involving and patches implementing improvements * or better alternatives are always welcome. <p> * * As a final note and sign post for developers starting to work with * Java NIO: <p> * * A separate <tt>NIOLockFile</tt> descendent exists specifically * because it was determined though experimenatation that * <tt>java.nio.channels.FileLock</tt> does not always exhibit the correct * or desired behaviour under reflective method invocation. That is, it was * discovered that under some operating system/JVM combinations, after calling * <tt>FileLock.release()</tt> via a reflective method invocation, the lock is * not released properly, deletion of the lock file is not possible even from * the owning object (this) and it is impossible for other <tt>LockFile</tt> * instances, other in-process objects or other processes to successfully obtain * a lock condition on the lock file, despite the fact that the * <tt>FileLock</tt> object reports that its lock is invalid (was released * successfully). Frustratingly, this condition appears to persist until full * exit of the process hosting the JVM in which the <tt>FileLock.tryLock()</tt> * method was reflectively invoked. <p> * * To solve this, the original <tt>LockFile</tt> class was split in two and * instead of reflective method invocation, subclass instantiation is now * performed at the level of the <tt>newLockFile()</tt> factory method. * Similarly, the HSQLDB ANT build script now detects the presence or abscence * of JDK 1.4+ features such as java.nio and only attempts to build and deploy * <tt>NIOLockFile</tt> to the hsqldb.jar if such features are reported * present. <p> * * @author boucherb@users * @version 1.8.0.10 * @since 1.7.2 */public class LockFile {    /**     * Arbitary period, in milliseconds, at which heartbeat timestamps are     * written to this object's lock file. <p>     *     * This value was selected to be very conservative, just in case timing     * jitters are experienced on the order introduced by brief network     * partitions, accidentally removed media and transient high load     * CPU bursts.     */    public static final long HEARTBEAT_INTERVAL = 10000;    /**     * {@link #HEARTBEAT_INTERVAL} + 100. <p>     *     * Interval used by {@link #checkHeartbeat(boolean) checkHeartbeat} to     * test whether the timestamp in the underlying lock file is live or stale.     * Padding added in the hope of reducing potential timing jitter issues     * under the polling scheme introduced in 1.8.0.3     */    public static final long HEARTBEAT_INTERVAL_PADDED = 10100;    /**     * Value written at the beginning of an HSQLDB lock file to distinguish it     * from other file types. <p>     *     * The value is the octet sequence: {0x48, 0x53, 0x51, 0x4c, 0x4c, 0x4f,     * 0x43, 0x4b}, which is the ASCII sequence {'H', 'S', 'Q', 'L', 'L', 'O',     * 'C', 'K'}. <p>     *     * <b>Design Note</b>: <p>     *     * "HSQLLOCK".getBytes() is no longer used because it is dependent on the     * underlying platform's default character set.     */    protected static final byte[] MAGIC = {        0x48, 0x53, 0x51, 0x4c, 0x4c, 0x4f, 0x43, 0x4b    };    /**     * Size, in bytes, of the region at the beginning of a lock file that is     * actually used to record lock information. <p>     *     * Value is currently MAGIC.length + sizeof(long) = (8 + 8) = 16     */    public static final int USED_REGION = 16;    /**     * Number of retries used by default in {@link #pollHeartbeat()     * pollHeartbeat}.     */    public static final int POLL_RETRIES_DEFAULT = 10;    /**     * System property that can be used to override the default number of     * heartbeat poll retries.     */    public static final String POLL_RETRIES_PROPERTY =        "hsqldb.lockfile.poll.retries";    /**     * System property that can be used to override the default number of     * milliseconds between each heartbeat poll retry.     */    public static final String POLL_INTERVAL_PROPERTY =        "hsqldb.lockfile.poll.interval";    /** Whether <tt>java.nio</tt> file locking is attempted by default. */    public static final boolean USE_NIO_FILELOCK_DEFAULT = false;    /**     * System property that can be used to control whether nio file locking is     * attempted.     */    public static final String USE_NIO_FILELOCK_PROPERTY =        "hsqldb.lockfile.nio.filelock";    /**     * Statically computed indication of <tt>java.nio.channels.FileLock</tt>     * runtime availability. <p>     *     * <b>Design Note</b>:<p>     *     * Computed in a static initializer block.  Will be <tt>false</tt> if     * <tt>USE_NIO_FILELOCK_PROPERTY</tt> is <tt>false</tt> at static     * initialization, regardless of actual availability.     */    public static final boolean NIO_FILELOCK_AVAILABLE;    /**     * Statically computed reference to the <tt>NIOLockFile</tt> class. <p>     *     * <b>Design Note</b>:<p>     *     * Computed in a static initializer block.  Will be <tt>null</tt> if     * <tt>USE_NIO_FILELOCK_PROPERTY</tt> is <tt>false</tt> at static     * initialization, regardless of actual availability.     */    public static final Class NIO_LOCKFILE_CLASS;    /**     * The timed scheduler with which to register this object's     * heartbeat task.     */    protected static final HsqlTimer timer = DatabaseManager.getTimer();    // This static initializer comes last, since it references a subclass    //    // That is, it is best practice to ensure the static fields of this class    // are all initialized before referecing a subclass whose static    // field initializtion may in turn reference static fields in this class.    static {        synchronized (LockFile.class) {            boolean use = USE_NIO_FILELOCK_DEFAULT;            try {                use = "true".equalsIgnoreCase(                    System.getProperty(USE_NIO_FILELOCK_PROPERTY, use ? "true"                                                                      : "false"));            } catch (Exception e) {}            boolean avail = false;            Class   clazz = null;            if (use) {                try {                    Class.forName("java.nio.channels.FileLock");                    clazz = Class.forName("org.hsqldb.persist.NIOLockFile");                    avail = true;                } catch (Exception e) {}            }            NIO_FILELOCK_AVAILABLE = avail;            NIO_LOCKFILE_CLASS     = clazz;        }    }    /**     * Canonical reference to this object's lock file. <p>     *     * <b>Design Note</b>:<p>     *     * Should really be final, but finality makes reflective construction     * and adherence to desirable <tt>LockFile</tt> factory method event     * sequence more complicated.     */    protected File file;    /**     * Cached value of the lock file's canonical path     *     * <b>Design Note</b>:<p>     *     * Should really be final, but finality makes reflective construction     * and adherence to desirable <tt>LockFile</tt> factory method event     * sequence much more complicated.     */    private String cpath;    /**     * A <tt>RandomAccessFile</tt> constructed from this object's canonical file     * reference. <p>     *     * This <tt>RandomAccessFile</tt> is used to periodically write out the     * heartbeat timestamp to this object's lock file.     */    protected volatile RandomAccessFile raf;    /** Indicates presence or absence of the cooperative lock condition. */    protected volatile boolean locked;    /** Opaque reference to this object's heatbeat task. */    private volatile Object timerTask;    /**     * Retrieves a new <tt>NIOLockFile</tt>, or <tt>null</tt> if not available     * under the current runtime environment.     *     * @return a new <tt>NIOLockFile</tt>, or <tt>null</tt> if not available     *      under the current runtime environment     */    private static final LockFile newNIOLockFile() {        if (NIO_FILELOCK_AVAILABLE && NIO_LOCKFILE_CLASS != null) {            try {                return (LockFile) NIO_LOCKFILE_CLASS.newInstance();            } catch (Exception e) {                // e.printStackTrace()            }        }        return null;    }    /**     * To allow subclassing without exposing a public constructor.     */    protected LockFile() {}    /**     * Retrieves a <tt>LockFile</tt> instance, initialized with a <tt>File</tt>     * object whose path is the canonical form of the one specified by the     * given <tt>path</tt> argument. <p>     *     * The resulting <tt>LockFile</tt> instance does not yet hold a lock     * condition on the file with the given path, nor does it guarantee that the     * file pre-exists or is created.     *     * However, upon successful execution, it is guaranteed that all required     * parent directories have been created and that the underlying platform has     * verified the specified path is legal on the file system of the underlying     * storage partition.     *     * @return a <tt>LockFile</tt> instance initialized with a <tt>File</tt>     *         object whose path is the one specified by the given <tt>path</tt>     *         argument.     * @param path the path of the <tt>File</tt> object with which the retrieved     *        <tt>LockFile</tt> object is to be initialized     * @throws FileCanonicalizationException if an I/O error occurs upon     *         canonicalization of the given path, which is possible because     *         it may be illegal on the runtime file system or because     *         construction of the canonical path name may require native file     *         system queries     * @throws FileSecurityException if a required system property value cannot     *         be accessed, or if a security manager exists and its <tt>{@link     *         java.lang.SecurityManager#checkRead}</tt> method denies read     *         access to the file; or if its <tt>{@link     *         java.lang.SecurityManager#checkRead(java.lang.String)}</tt>     *         method does not permit verification of the existence of all     *         necessary parent directories; or if the <tt>{@link     *         java.lang.SecurityManager#checkWrite(java.lang.String)}</tt>     *         method does not permit all necessary parent directories to be     *         created     */    public static final LockFile newLockFile(final String path)    throws FileCanonicalizationException, FileSecurityException {        LockFile lockFile = newNIOLockFile();        if (lockFile == null) {            lockFile = new LockFile();        }        lockFile.setPath(path);        return lockFile;    }    /**     * {@link org.hsqldb.persist.Logger#acquireLock(java.lang.String)}     * delegate.<p>     *     * Retrieves a new <tt>LockFile</tt> object holding a cooperative lock     * condition upon the file with the given path, appended with the     * extension '.lck'. <p>     *     * @param path of the lock file, to which will be appended '.lck'     * @throws org.hsqldb.HsqlException if the lock condition cannot     *      be obtained for any reason.     * @return a new <tt>LockFile</tt> object holding a cooperative lock     *      condition upon the file with the given path, appended with the     *      extension '.lck'     */

⌨️ 快捷键说明

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