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

📄 lockfile.java

📁 纯Java的数据库
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
/* Copyright (c) 2001-2008, 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.EOFException;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;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.StringConverter;import org.hsqldb.lib.java.JavaSystem;/** * Base cooperative file locking implementation and <tt>LockFile</tt> * factory. <p> * * <hr> * * Provides a facility for cooperative file locking across process boundaries * and isolated in-process class loader contexts. <p> * * The need is obvious for inter-process cases, but it is no less essential for * in-process Java clients whose classes have been loaded by isolated class * loaders.  This is because static fields--the conventional<a href="#note1"> * <sup>*</sup></a> means for supporting in-process global discovery--become * distinct and inaccessible across Java class loader context boundaries when * the contexts do not share a common parent class loader or do not implement * normal parent class loader delegation semantics. <p> * * <a name="note1"><sup>*</sup></a> * The only purely in-process global discovery alternative known to the author * is to reflect upon objects found while traversing up the Java runtime thread * hierarchy.  However, this method is often subject to Java security * restrictions whose collective purpose is essentially dissimilar to that of * restrictions in effect relative to cooperative file locking requirements, * making it a generally unacceptable option in this context. <p> * * <hr> * * Here is the way this class presently operates: <p> * * <ol style="list-style-type: upper-latin"> *    <li>A file with a commonly agreed-upon path is used to implement *        cooperative locking semantics regarding another set of files with *        commonly agreed-upon paths.<p> * *    <li>In particular, a background thread periodically writes a timestamp *        value, which acts as a heartbeat that indicates to others whether a *        cooperative lock condition is currently held.<p> * *    <li>In addition, a magic value is written so that it is possible to *        distinguish with a reasonably high degree of accuracy between the *        existence of a lock file and some other type of file.<p> * *    <li>The generic rules used to aquire a cooperative lock condition are *        as follows:<p> * *    <ol> *        <li>If a lock condition is already held by this object, do nothing and *            signify that the lock attempt was successful, else...<p> * *        <li>Poll the underlying file, using a configured maximum number of *            retries and a configured interval between the end of a failed *            poll and the beginning of the next.<p> * *        <li>For each poll:<p> * *        <ol style="list-style-type: lower-roman"> * *            <li>Attempt to atomically create the underlying file if and only *                if it does not yet exist, exit the polling loop immediately *                indicating success if the attempt succeeds, else fast fail *                the current poll if a security exeption is thrown in response *                to the attempt, else...<p> * *            <li>Test if the underlying file exists, fast failing the current *                poll if it is impossible to determine (i.e. if a security *                exeption is thrown).<p> * *            <li>If the file does not exist, exit the polling loop immediately *                indicating success.<p> * *                This can occur only under pre-JDK 1.2 runtimes; or when the *                underlying platform does not correctly support {@link *                java.io.File#createNewFile()}; 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 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.<p> * *            <li>Test the file's length, fast failing the current poll if the *                length cannot be determined or it is not the expected *                value.<p> * *            <li>Open a stream to read the file's <tt>MAGIC</tt> and heartbeat *                timestamp values, fast failing the current poll if the stream *                cannot be opened.<p> * *            <li>Test the file's <tt>MAGIC</tt> value, failing the current poll *                if the value cannot be read or it is not the expected *                value.<p> * *            <li>Test the file's heartbeat timestamp value, fast failing the *                current poll if it cannot be read or it is less than a *                commonly agreed-upon value into the past (or future, to *                overcome a caveat observed by a patch contributor).<p> *        </ol> *        <li>If the polling phase exits with a failure indication, then one or *            more of the following cases must have been true at every poll *            iteration: <p> * *            <ul> *               <li>The file had the wrong length or <tt>MAGIC</tt> value (was *                   not an HSQLDB lock file). * *               <li>The file was deleted externally after a poll's initial *                   test for existence and recreated at some point before *                   the next poll's initial test for existence. * *               <li>An incompatible OS-enforced security restriction was in *                   effect. * *               <li>An incompatible Java-enforced security restriction was *                   in effect. * *               <li>The target file system media was effectively inaccessible. *               <li>A cooperative lock condition was held by some other *                   <tt>LockFile</tt>. * *               <li>A kernel-enforced manditory or advisory file lock was held. *            </ul> <p> * *            In this case, signify failure indicating the last encountered *            reason, else...<p> * *        <li>Open the file for reading and writing, write the magic value and *            an initial heartbeat timestamp, schedule a periodic heartbeat *            timestamp writer task and signify success.<p> *    </ol> *    <li>The generic rules used to release a cooperative lock condition are:<p> *    <ol> *        <li>If a lock condition is not currently held, do nothing and signify *            success, else...<p> * *        <li>A lock condition is currently held by this object, so try to *            release it. <p> * *            By default, releasing the lock condition consists of closing and *            nullifying any objects that have a file descriptor open on the *            lock file, cancelling the periodic heartbeat timestamp writer *            task and deleting the lock file. If the release occurs without *            raising an exception, signify success, else signify that the *            release attempt <em>might</em> have failed. <p> *    </ol> * </ol> <p> * * <hr> * * Additionally, {@link #doOptionalLockActions() doOptionalLockActions()} and * {@link #doOptionalReleaseActions() doOptionalReleaseActions()} are invoked * during lock and release attempts, respectively.  This enables integration of * extended lock and release strategies based on subclassing. Subclass * availability is automatically detected and exposed by the factory method * {@link #newLockFile newLockFile()}.<p> * * In particular, if {@link #USE_NIO_FILELOCK_PROPERTY} is true and the required * classes are available at static initialization, then <tt>newLockFile()</tt> * produces {@link org.hsqldb.NIOLockFile NIOLockFile} instances.<p> * * When <tt>NIOLockFile</tt> instances are produced, then it is possible that * true kernel-enforced advisory or manditory file locking is used to protect * the underlying lock file from inadvertent modification (and possibly even * from deletion, including deletion by the system superuser). * * Otherwise, <tt>newLockFile()</tt> produces vanilla <tt>LockFile</tt> * instances, which exhibit just the elementary cooperative locking behavior on * platforms that do not, by default, implement kernel-enforced manditory * locking for open files. <p> * * At this point, it must be noted that not every target platform upon which * Java can run actually provides true kernel-enforced manditory (or even * advisory) file locking. Indeed, even when a target platform <em>does</em> * provide such locking guarantees for local file systems, it may not be able * to do so for network file systems, or it may only be able to do so safely * (or at all) with certain restrictions. Further, external system configuration * may be a prerequisite to enable manditory locking on systems that support it * but employ advisory locking by default. <p> * * In recognition of these facts, the official Java NIO package specification * explicitly states basically the same information. What is unfortunate, * however, is that no capabilities API is yet provided as part of the package. * What is even more unfortunate is that without something like a capabilities * API, it is impossible for an implementation to indicate or clients to * distiguish between simple lack of platform support and cases involving * immature Java runtimes that do not fully or correctly implement all NIO * features (and hence may throw exceptions at unexpected times or in places * where the API specification indicates none can be thrown).<p> * * It is for the preceding reasons that, as of HSQLDB 1.8.0.3, * <tt>FileLock</tt>'s use of Java NIO has been made a purely optional feature. * Previous to HSQLDB 1.8.0.3, if NIO was detected available, used to create a * <tt>FileLock</tt> and failed, then the enclosing cooperative lock attempt * failed also, despite the fact that a vanilla locking approach could * succeed. <p> * * <b>Polling Configuration</b>:<p> * * Although the {@link #HEARTBEAT_INTERVAL} and default polling values may * seem quite conservative, they are the result of ongoing research into * generally reasonable concerns regarding normal timing and resource * availability fluctuations experienced frequently under most, if not all * operating systems. <p> * * Regardless, flexibility is almost always a good thing, so this class is * designed to allow polling interval and retry count values to be configured * at run-time. <p> * * At present, this can be done at any time by setting the system properties * whose names are  {@link #POLL_RETRIES_PROPERTY} and {@link * #POLL_INTERVAL_PROPERTY}. <p> * * Some consideration has also been given to modifying the polling scheme so * that run-time configuration of the HEARTBEAT_INTERVAL is possible.  For now, * however, this option has been rejected due to the relative complexity of * guaranteeing acceptably safe, deterministic behaviour.  On the other hand, * if it can be guaranteed that certain site invariants hold (in particular, * that only one version of the hsqldb jar will ever be used to open database * instances at the site) and it is desirable or required to experiment with * a lower interval, then it is recommended for now simply to recompile the * jar using a different value in the static field assignment.  Note that great * care should be taken to avoid assigning too low a value, or else it may * become possible that even very short-lived timing and resource availability * fluctuations will cause incorrect operation of this class. <p> * * <b>NIO Configuration</b>:<p> * * Starting with 1.8.0.3, NIO-enhanced file lock attempts are turned off by * default. The general reasons for this are discussed above.  Anyone interested * in the reading the detailed research notes should refer to the overview of * {@link NIOLockFile}. If, after reviewing the notes and the capabilities of * the intended target platform, one should still wish to enable NIO-enhanced * file lock attempts, it can be done by setting the system property {@link * #USE_NIO_FILELOCK_PROPERTY} true at JVM startup (for example, by using a * command-line <tt>-D&lt;property-name&gt;=true</tt> directive). Be aware that * the system property value is read only once, in the static initializer block * for this class. <p> * * <b>Design Notes</b>:<p> * * First, it should be noted that no thread synchronization occurs in * this class.  Primarily, this is because the standard entry point, * {@link #newLockFileLock(String)}, is always called from within a block * synchronized upon an HSQLDB Database instance.  If this class is to be used * elsewhere and it could be accessed concurrently, then access should be * synchronized on an appropriate monitor.  That said, certain members of this * class have been declared volatile to minimize possibility of inconsistent * views under concurrent read-only access. <p> * * Second, to the limit of the author's present understanding, the * implementation details of this class represent a good comprimse under varying * and generally uncontrollable JVM, OS and hardware platform

⌨️ 快捷键说明

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