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

📄 lockfile.java

📁 纯Java的数据库
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
    public static final LockFile newLockFileLock(final String path)    throws HsqlException {        LockFile lockFile = null;        try {            lockFile = LockFile.newLockFile(path + ".lck");        } catch (LockFile.BaseException e) {            throw Trace.error(Trace.LOCK_FILE_ACQUISITION_FAILURE,                              e.getMessage());        }        boolean locked = false;        try {            locked = lockFile.tryLock();        } catch (LockFile.BaseException e) {            throw Trace.error(Trace.LOCK_FILE_ACQUISITION_FAILURE,                              e.getMessage());        }        // Paranoia mode: In theory, this case can't happen, given the way        // tryLock now works; by all current understanding of the involved API        // contracts, an exception will always be thrown instead by the code        // above.        if (!locked) {            throw Trace.error(Trace.LOCK_FILE_ACQUISITION_FAILURE,                              lockFile.toString());        }        return lockFile;    }    /**     * Checks whether the underlying file is an HSQLDB lock file and, if so,     * whether its heartbeat timestamp is live (is, as far as can be known,     * presumably in use by another <tt>LockFile</tt> instance) or stale. <p>     *     * The check conforms to the following rules: <p>     *     * <ol>     * <li>If the parameter <tt>withCreateNewFile</tt> is true, {@link     *     java.io.File#createNewFile()} is available and its invocation     *     upon this object's <tt>file</tt> object indicates the underlying     *     file was atomically created if and only if it did not yet exist,     *     then return immediately (we have won the <em>race</em> to establish     *     a lock file). <p>     *     * <li>Test again if the file exists, returning immediately if it does not     *     (there's no file and hence no heartbeat to check). <p>     *     *     An immediate return can occur here only under pre-JDK 1.2 runtimes;     *     or when the underlying platform does not correctly support     *     <tt>File.createNewFile()</tt>; or when the underlying file is deleted     *     within a very short time after i.), above (typically on the order of     *     microseconds). <p>     *     *     If the underlying platform employs a kernel-enforced mandatory file     *     locking blanket policy for open files (e.g. <em>Windows</em><sup>tm     *     </sup>), then this is likely a non-issue. And if this case makes     *     possible a race condition with another <tt>LockFile</tt> object     *     (because the test for existence yeilds false and subsequent file     *     creation is not atomic relative to all other file system actions), it     *     is still <em>very</em> unlikely that so unfortunate a timing will     *     occur as to allow simultaneous lock conditions to be established.     *     Finally, if some non-<tt>LockFile</tt> entity deleted the file, then     *     there are much worse things to worry about, in particular that the     *     files this object is supposed to protect are in reality subject to     *     arbitrary external modification and deletion by some uncooperative     *     process.<p>     *     * <li>If a Java security exception is thrown while testing for existence,     *     it is rethrown as a <tt>FileSecurityException</tt>.     *     * <li>Read the file's length.     *     * <li>If a Java security exception is thrown reading length, it is rethrown     *     as a <tt>FileSecurityException</tt> (it <em>is</em> possible somebody     *     concurrently refreshed the system Policy in the interim).     *     * <li>If the file does not have the expected length, a     *     <tt>WrongLengthException</tt> is thrown (we're trying to check     *     something that is not an HSQLDB lock file).     *     * <li>Open an input steam to read the file's <tt>MAGIC</tt> and heartbeat     *     timestamp values.     *     * <li>If a file not found exception is thrown above, it is rethrown as an     *     <tt>UnexpectedFileNotFoundException</tt> (we've already tested for     *     existence).     *     * <li>If a Java security exception is thrown above, it is rethrown as a     *     <tt>FileSecurityException</tt> (it <em>is</em> possible somebody     *     concurrently refreshed the system Policy in the interim).     *     * <li>Read the <tt>MAGIC</tt> value.     *     * <li>If an end of file exepction is thrown above, it is rethrown as an     *     <tt>UnexpectedEndOfFileException</tt> (we've already tested the     *     length... did someone truncate the file in the interim?).     *     * <li>If an I/O exception is thrown, it is rethrown as an     *     <tt>UnexpectedFileIOException</tt> (we've already tested for     *     existence, length and successfully opened a stream...did someone,     *     for example, force unmount or physically remove the underlying device     *     in the interim?)     *     * <li>If the value read in does not match the expected <tt>MAGIC</tt> value,     *     a <tt>WrongMagicException</tt> is thrown (we're trying to check     *     something that is not an HSQLDB lock file).     *     * <li>Read the heartbeat timestamp.     *     * <li>If a Java security exception is thrown above, it is rethrown as a     *     <tt>FileSecurityException</tt> (it <em>is</em> possible somebody     *     concurrently refreshed the system Policy in the interim).     *     * <li>If an end of file exection is thrown above, it is rethrown as an     *     <tt>UnexpectedEndOfFileException</tt> (we've already tested the     *     length... did someone truncate the file in the interim?).     *     * <li>If an I/O exception is thrown, it is rethrown as an     *     <tt>UnexpectedFileIOException</tt> (we've already tested for     *     existence, length and successfully opened a stream...did someone,     *     for example, force unmount or physically remove the underlying device     *     in the interim?)     *     * <li>If the timestamp read in is less than or equal to     *     {@link #HEARTBEAT_INTERVAL_PADDED} milliseconds into the past or     *     future, then a <tt>LockHeldExternallyException</tt> is thrown.     *     * <li>Otherwise, this method simply returns.     * </ol>     *     * @param withCreateNewFile if <tt>true</tt>, attempt to employ     *      <tt>File.createNewFile()</tt> as part of the check so as to     *      eliminate potential race conditions when establising a new     *      lock file     * @throws FileSecurityException if the check fails due to a Java     *      security permission check failure     * @throws LockHeldExternallyException if it is determined that the     *      file's heartbeat timestamp is less than     *      <tt>HEARTBEAT_INTERVAL_PADDED</tt> into the past (or future)     * @throws UnexpectedEndOfFileException if an <tt>EOFExceoption</tt> is     *      thrown while reading either the magic or heartbeat timestamp values     * @throws UnexpectedFileIOException if an <tt>IOException</tt> other than     *      <tt>EOFException</tt> is thrown while reading either the magic or     *      heartbeat timestamp values     * @throws UnexpectedFileNotFoundException if a     *      <tt>FileNotFoundException</tt> is thrown while attempting to open a     *      stream to read the underlying file's magic and heartbeat timestamp     *      values     * @throws WrongLengthException if it is determined that the length     *      of the file does not equal {@link #USED_REGION}     * @throws WrongMagicException if it is determined that the file's     *      content does not start with {@link #MAGIC}.     */    private final void checkHeartbeat(boolean withCreateNewFile)    throws LockFile.FileSecurityException,           LockFile.LockHeldExternallyException,           LockFile.UnexpectedEndOfFileException,           LockFile.UnexpectedFileIOException,           LockFile.UnexpectedFileNotFoundException,           LockFile.WrongLengthException, LockFile.WrongMagicException {        long now;        long lastHeartbeat;        long length = 0;//#ifdef JAVA2FULL        try {            if (withCreateNewFile) {                try {                    file.createNewFile();                    return;                } catch (IOException ioe) {}            }            if (!file.exists()) {                return;            }            length = file.length();        } catch (SecurityException se) {            throw new FileSecurityException(this, "checkHeartbeat", se);        }//#else/*        if (!file.exists()) {            return;        }        length = file.length();*///#endif JAVA2        if (length != USED_REGION) {            throw new WrongLengthException(this, "checkHeartbeat", length);        }        // Compute the current wall clock time *first* to reduce possibility        // of unwanted time dilation effects introduced, for example,        // by intervening thread or process context switches under CPU        // bursts.        //        // Example:        //        // Say currentTimeMillis is actually somewhere in (-0.5 and 0.5]        // and another LockFile concurrently writes a 0-valued heartbeat        // timestamp.        //        // Then, if readHeartbeat comes first here, happens to 'win the race        // condition' (reads the previous heartbeat: -10,000) and an intervening        // switch causes greater than ~0.5 millisecond elapsed time to        // be experienced between readHeartbeat and currentTimeMillis, then        // currentTimeMillis will be computed as n (n > 0), and (now -        // lastHearbeat) will be HEARTBEAT_INTERVAL + n, instead of        // HEARTBEAT_INTERVAL.        //        // Now, let n be greater than (HEARTBEAT_INTERVAL_PADDED -        // HEARTBEAT_INTERVAL).        //        // Then the check will succeed, although it should fail.        //        // On the other hand, if currentTimeMillis is computed first, the        // worst than can happen is a false positive indication that        // the read heartbeat timestamp value was written by a live LockFile        // instance.        //        now           = System.currentTimeMillis();        lastHeartbeat = readHeartbeat();        // Using padded interval to further reduce corner case effects,        // now that heartbeat polling is in effect.        //        // Basically, it is absolutely essential to fail when a lock really is        // still held elsewhere, so it is OK to fail on corner cases where        // the last written heartbeat is very close to HEARTBEAT_INTERVAL        // in the past and it is possible that timing jitters make it uncertain        // whether the lock really is still held.        if (Math.abs(now - lastHeartbeat) <= (HEARTBEAT_INTERVAL_PADDED)) {            throw new LockHeldExternallyException(this, "checkHeartbeat", now,                                                  lastHeartbeat);        }    }    /**     * Closes this object's {@link #raf RandomAccessFile}. <p>     *     * As a side-effect, the associated <tt>FileChannel</tt> object, if any,     * is closed as well.     *     * @throws UnexpectedFileIOException if an <tt>IOException</tt> is thrown     */    private final void closeRAF() throws LockFile.UnexpectedFileIOException {        if (raf != null) {            try {                raf.close();            } catch (IOException ex) {                throw new UnexpectedFileIOException(this, "closeRAF", ex);            } finally {                raf = null;            }        }    }    /**     * Provides any optional locking actions for the {@link #tryLock()     * tryLock()} template method. <p>     *     * Descendents are free to provide additional functionality here,     * using the following rules: <p>     *     * <b>PRE:</b><p>     *     * This method is called only from <tt>tryLock()</tt> and it is called if     * and only if <tt>tryLock()</tt> successfully invokes     * <tt>pollHeartbeat()</tt> and <tt>openRAF()</tt> first. <p>     *     * From this, it can be inferred that upon entry: <p>     *     * <ol>     * <li><tt>locked == false</tt>.     * <li><tt>raf</tt> is a non-null instance that can be used to get a     *     <tt>FileChannel</tt> instance, if desired.     * <li>the underlying file either did not exist before invoking     *     <tt>openRAF()</tt> or it was a valid but stale HSQLDB lock file     *     because it:     *     *     <ol style="list-style-type: lower-roman">     *     <li>did exist,     *     <li>was readable on <tt>USED_REGION</tt>,     *     <li>had the expected length and <tt>MAGIC</tt> value and     *     <li>had a stale heartbeat timestamp value.     *     </ol>     * </ol> <p>     *     * Further, it can be assumed that this object's heatbeat task is definitely     * cancelled and/or has never been scheduled at this point, so whatever     * timestamp is recorded in the lock file, if it did pre-exist, was written     * by a different <tt>LockFile</tt> instance or as the result of a previous,     * successful <tt>tryLock()</tt> invocation upon this <tt>LockFile</tt>     * instance. <p>     *     * Finally, it is important that this method does not rethrow any exceptions     * it encounters as unchecked exceptions to the calling context. <p>     *     * <b>POST:</b><p>     *

⌨️ 快捷键说明

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