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

📄 lockfile.java

📁 hsql是很有名的嵌入式数据库
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/* Copyright (c) 2001-2005, The HSQL Development Group
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * Neither the name of the HSQL Development Group nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


package org.hsqldb.persist;import java.io.DataInputStream;import java.io.File;import java.io.FileInputStream;import java.io.RandomAccessFile;import org.hsqldb.DatabaseManager;import org.hsqldb.HsqlDateTime;import org.hsqldb.HsqlException;import org.hsqldb.Trace;import org.hsqldb.lib.FileUtil;import org.hsqldb.lib.HsqlTimer;import org.hsqldb.lib.java.JavaSystem;/** * The base HSQLDB cooperative file locking implementation and factory. <p> * * <hr> * * Here is the way this class operates: <p> * * <ol> * <li>A file with a well-known path relative to each database instance *     is used to implement cooperative locking of database files across *     process boundaries (database instances running in different JVM *     host processes) and class loader contexts (databases whose classes *     have been loaded by distinct class loaders such that their open *     database repositories are distinct and are inaccessible across *     the class loader context boundaries).<p> * * <li>A background thread periodically writes a timestamp to this object's *     lock file at {@link #HEARTBEAT_INTERVAL} millisecond intervals, *     acting as a heartbeat to indicate that a lock is still held.<p> * * <li>The generic lock attempt rules are: <p> *    <ul> *    <li>If a lock condition is already held by this object, do nothing and *        signify that the lock attempt was successful, else...<p> * *    <li>If no lock file exists, go ahead and create one, silently issue the *        {@link java.io.File#deleteOnExit File.deleteOnExit()} directive via *        refelective method invocation (in order to stay JDK 1.1 compliant), *        schedule a periodic heartbeat task and signify that the lock attempt *        was successful, else...<p> * *    <li>The lock file must already exist, so try to read its heartbeat *        timestamp. If the read fails, assume that a lock condition is held by *        another process or a database in an inaccessible class loader context *        and signify that the attempt failed, else if the read value *        is less than <code>HEARTBEAT_INTERVAL</code> milliseconds into the *        past or futuer, assume that a lock condition is held by another *        process or a database in an inaccessible class loader context and *        signify that the lock attempt failed, else assume that the file is *        not in use, schedule a periodic heartbeat task and signify that the *        lock attempt was successful.<p> * *    </ul> * <li>The generic release attempt rules are:<p> *    <ul> *    <li>If a lock condition is not currently held, do nothing and signify *        that the release attempt was successful, else...<p> * *    <li>A lock condition is currently held, so try to release it.  By *        default, releasing the lock condition consists of closing and *        nullifying any objects that have a file descriptor open on the *        lock file. If the release is successful, cancel the periodic *        heartbeat task and signify that the release succeeded, else signify *        that the release attempt failed.<p> *    </ul> * </ol> <p> * * In addition to the generic lock and release rules, the protected methods * {@link #lockImpl() lockImpl()} and {@link #releaseImpl() releaseImpl()} * are called during lock and release attempts, respectively.  This allows * transparent, JDK 1.1 compliant integration of extended strategies for * locking and releasing, based on subclassing and reflective construction * of such specializations in the factory method * {@link #newLockFile newLockFile()}, determined by information gathered * at run-time. <p> * * In particular, if it is available at runtime, then newLockFile() retrieves * instances of {@link org.hsqldb.NIOLockFile  NIOLockFile} to capitalize, * when possible, on the existence of the {@link java.nio.channels.FileLock * FileLock} class. If the <code>NIOLockFile</code> class does not exist at * run-time or the java.nio classes it uses are not supported under the * run-time JVM, then newLockFile() produces vanilla LockFile instances, * meaning that only purely cooperative locking takes place, as opposed to * possibly O/S-enforced file locking which, at least in theory, is made * available through the {@link java.nio.channels} package). However, it * must be noted that even if a JVM implementation provides the full * java.nio.channels package, it is not absolutely required to guarantee * that the underlying platform (the current operating system) provides * true process-wide file locking. <p> * * <b>Note:</b> <p> * * The <code>NIOLockFile</code> descendent exists because it has been determined * though experimenatation that <code>java.nio.channels.FileLock</code> * does not always exhibit the correct/desired behaviour under reflective * method invocation. That is, it has been discovered that under some operating * system/JVM combinations, after calling <code>FileLock.release()</code> * 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 <code>LockFile</code> instances * or any other objects or processes to successfully obtain a lock * condition on the lock file, despite the fact that the <code>FileLock</code> * object reports that its lock is invalid (was released successfully). * Frustratingly, this condition appears to persist until full exit of the * JVM process in which the <code>FileLock.tryLock()</code> method was * reflectively invoked. <p> * * To solve this, the original <code>LockFile</code> class was split in two and * instead of reflective method invocation, reflection-based class * instantiation is now performed at the level of the <code>newLockFile()</code> * factory method. Similarly, the HSQLDB ANT build script detects the presence * or abscence of JDK 1.4 features such as java.nio and only attempts to build * and deploy <code>NIOLockFile</code> to the hsqldb.jar if such features are * reported present. </p> * * @author boucherb@users * @version 1.7.2 * @since 1.7.2 */public class LockFile {    /** Canonical reference to this object's lock file. */    protected File f;    /** Cached value of the lock file's canonical path. */    private String cpath = null;    /**     * A RandomAccessFile constructed from this object's reference, f, to its     * lock file. <p>     *     * This RandomAccessFile is used to periodically write out the heartbeat     * timestamp to this object's lock file.     */    protected RandomAccessFile raf;    /**     * The period, in milliseconds, at which heartbeat timestamps are written     * to this object's lock file.     */    public static final long HEARTBEAT_INTERVAL = 10000;    /**     * A magic value to place at the beginning of the lock file to     * differentiate it from other files. The value is "HSQLLOCK".getBytes().     */    public static final byte[] MAGIC = "HSQLLOCK".getBytes();    /** Indicates whether this object has a lock condition on its lock file. */    protected boolean locked;    /**     * The timed scheduler with which to register this object's     * heartbeat task.     */    protected static final HsqlTimer timer = DatabaseManager.getTimer();    /**     * An opaque reference to this object's heatbeat task.     */    private Object timerTask;    /**     * Attempts to read the hearbeat timestamp from this object's lock file     * and compare it with the current time. <p>     *     * An exception is thrown if it must be presumned that another process has     * locked the file, using the following rules: <p>     *     * <ol>     * <li>If the file does not exist, this method returns immediately.     *     * <li>If an exception is raised reading the file, then an exeption is     *     thrown.     *     * <li>If the read is successful and the timestamp read in is less than     *     <code>HEARTBEAT_INTERVAL</code> milliseconds into the past or     *     future, then an exception is thrown.     *     * <li>If no exception is thrown in 2.) or 3.), this method simply returns.     * </ol>     * @throws Exception if it must be presumed that another process     *        or isolated class loader context currently has a     *        lock condition on this object's lock file     */    private void checkHeartbeat() throws Exception {        long   lastHeartbeat;        String mn;        String path;        mn   = "checkHeartbeat(): ";        path = "lock file [" + cpath + "]";        trace(mn + "entered.");        if (!f.exists()) {            trace(mn + path + " does not exist. Check OK.");            return;        }        if (f.length() != 16) {            trace(mn + path + " length != 16; Check OK.");            return;        }        try {            lastHeartbeat = System.currentTimeMillis() - readHeartbeat();        } catch (Exception e) {            // e.printStackTrace();            throw new Exception(                Trace.getMessage(                    Trace.LockFile_checkHeartbeat, true, new Object[] {                e.getMessage(), cpath            }));        }        trace(mn + path + " last heartbeat " + lastHeartbeat + " ms ago.");        if (Math.abs(lastHeartbeat) < HEARTBEAT_INTERVAL) {            throw new Exception(                Trace.getMessage(                    Trace.LockFile_checkHeartbeat2, true, new Object[] {                mn, path            }));        }    }    /**     * Closes this object's {@link #raf RandomAccessFile}.     *     * @throws Exception if an IOException occurs     */    private void closeRAF() throws Exception {        String mn;        mn = "closeRAF(): ";        trace(mn + "entered.");        if (raf == null) {            trace(mn + "raf was null upon entry. Exiting immediately.");        } else {            trace(mn + "closing " + raf);            raf.close();            trace(mn + raf + " closed successfully. Setting raf null");            raf = null;        }    }    /**     * Initializes this object with the specified <code>File</code>     * object. <p>     *     * The file argument is a reference to this object's lock file. <p>     *     * This action has the effect of attempting to release any existing     * lock condition and reinitializing all lock-related member attributes     * @param file a reference to the file this object is to use as its     *      lock file     */    private void setFile(File file) throws Exception {        if (isLocked()) {            try {                tryRelease();            } catch (Exception e) {                trace(e);            }        }        f      = FileUtil.canonicalFile(file);        cpath  = f.getPath();        raf    = null;        locked = false;    }    /**     * Provides any specialized locking actions for the     * {@link #tryLock() tryLock()} method. <p>     *     * Descendents are free to provide additional functionality here,     * using the following rules:     *     * <pre>

⌨️ 快捷键说明

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