📄 lockfile.java
字号:
* of <code>f</code>. That is, two <code>LockFile</code> * objects have the same <code>hashCode</code> value if they have the * same lock file. <p> * * @return a hash code value for this object. * @see #equals(java.lang.Object) */ public int hashCode() { return f == null ? 0 : f.hashCode(); } /** * Retrieves whether this object has successfully obtained and is * still currently holding (has not yet released) a cooperative * lock condition on its lock file. <p> * * <b>Note:</b> Due to the retrictions placed on the JVM by * platform-independence, it is very possible to successfully * obtain and hold a cooperative lock on a lock file and yet for * the lock to become invalid while held. <p> * * For instance, under JVMs with no <code>java.nio</code> package or * operating systems that cannot live up to the contracts set forth for * {@link java.nio.channels.FileLock FileLock}, it is quite possible * for another process or even an uncooperative bit of code running * in the same JVM to delete or overwrite the lock file while * this object holds a lock on it. <p> * * Because of this, the isValid() method is provided in the public * interface in order to allow clients to detect such situations. <p> * * @return true iff this object has successfully obtained * and is currently holding (has not yet released) * a lock on its lock file * @see #isValid */ public boolean isLocked() { return locked; } /** * Retrieves whether there is potentially already a cooperative lock, * operating system lock or some other situation preventing * a cooperative lock condition from being aquired, relative to the * specified path. * * @param path the path to test */ public static boolean isLocked(String path) { FileInputStream fis = null; try { LockFile lf = LockFile.newLockFile(path); lf.checkHeartbeat(); if (lf.f.exists() && lf.f.isFile()) { fis = new FileInputStream(lf.f); fis.read(); } return false; } catch (Exception e) {} finally { if (fis != null) { try { fis.close(); } catch (java.io.IOException ioe) {} } } return true; } /** * Retrieves whether this object holds a valid lock on its lock file. <p> * * More formally, this method retrieves true iff: <p> * * <pre> * isLocked() && * f != null && * f.exists() && * raf != null * </pre> * * @return true iff this object holds a valid lock on its * lock file. */ public boolean isValid() { return isLocked() && f != null && f.exists() && raf != null; } /** * For internal use only. <p> * * This Runnable class provides the implementation for the timed task * that periodically writes out a heartbeat timestamp to the lock file.<p> */ protected class HeartbeatRunner implements Runnable { public void run() { try { trace("HeartbeatRunner.run(): writeHeartbeat()"); writeHeartbeat(); } catch (Throwable t) { trace("HeartbeatRunner.run(): caught Throwable: " + t); } } } /** * Retrieves a String representation of this object. <p> * * The String is of the form: <p> * * <pre> * super.toString() + * "[file=" + getAbsolutePath() + * ", exists=" + f.exists() + * ", locked=" + isLocked() + * ", valid=" + isValid() + * ", " + toStringImpl() + * "]"; * </pre> * @return a String representation of this object. * @see #toStringImpl */ public String toString() { return super.toString() + "[file =" + cpath + ", exists=" + f.exists() + ", locked=" + isLocked() + ", valid=" + isValid() + ", " + toStringImpl() + "]"; } /** * Retrieves an implementation-specific tail value for the * toString() method. <p> * * The default implementation returns the empty string. * @return an implementation-specific tail value for the toString() method * @see #toString */ protected String toStringImpl() { return ""; } /** * Attempts, if not already held, to obtain a cooperative lock condition * on this object's lock file. <p> * * @throws Exception if an error occurs that absolutely prevents the lock * status of the lock condition from being determined * (e.g. an unhandled file I/O error). * @return <code>true</code> if this object already holds a lock or * the lock was obtained successfully, else * <code>false</code> */ public boolean tryLock() throws Exception { String mn = "tryLock(): "; trace(mn + "entered."); if (locked) { trace(mn + " lock already held. Returning true immediately."); return true; } checkHeartbeat();// Alternatively, we could give ourselves a second try,// raising our chances of success in the rare case that the// last locker terminiated abruptly just less than// HEARTBEAT_INTERVAL ago.//// try {// checkHeartbeat();// } catch (Exception e) {// try {// Thread.sleep(HEARTBEAT_INTERVAL);// } catch (Exception e2) {}// checkHeartbeat();// } openRAF(); locked = lockImpl(); if (locked) { writeMagic(); startHeartbeat(); try { // attempt to ensure that tryRelease() gets called if/when // the VM shuts down, just in case this object has not yet // been garbage-collected or explicitly released. JavaSystem.runFinalizers(); trace(mn + "success for System.runFinalizersOnExit(true)"); } catch (Exception e) { trace(mn + e.toString()); } } else { try { releaseImpl(); closeRAF(); } catch (Exception e) { trace(mn + e.toString()); } } trace(mn + "ran to completion. Returning " + locked); return locked; } /** * Attempts to release any cooperative lock condition this object * may have on its lock file. <p> * * @throws Exception if an error occurs that absolutely prevents * the status of the lock condition from * being determined (e.g. an unhandled file * I/O exception). * @return <code>true</code> if this object does not hold a * lock or the lock is released successfully, * else <code>false</code>. */ public boolean tryRelease() throws Exception { String mn = "tryRelease(): "; String path; trace(mn + "entered."); boolean released = !locked; if (released) { trace(mn + "No lock held. Returning true immediately"); return true; } try { released = releaseImpl(); } catch (Exception e) { trace(mn + e); } if (!released) { trace(mn + "releaseImpl() failed. Returning false immediately."); return false; } trace(mn + "releaseImpl() succeeded."); stopHeartbeat(); closeRAF(); // without a small delay, the following delete may occasionally fail // and return false on some systems, when really it should succeed // and return true. trace(mn + "Starting Thread.sleep(100)."); try { Thread.sleep(100); } catch (Exception e) { trace(mn + e.toString()); } trace(mn + "Finished Thread.sleep(100)."); path = "[" + cpath + "]"; if (f.exists()) { trace(mn + path + " exists."); released = f.delete(); trace(mn + path + (released ? "" : "not") + " deleted."); if (f.exists()) { trace(mn + " WARNING!: " + path + "still exists."); } } locked = !released; trace(mn + "ran to completion. Returning " + released); return released; } /** * Prints tracing information and the value of the specified object * * @param o the value to print */ protected void trace(Object o) { if (Trace.TRACE) { Trace.printSystemOut("[" + super.toString() + "]: " + o); } } /** * Attempts to release any lock condition this object may have on its * lock file. <p> * * @throws Throwable if this object encounters an unhandled exception * trying to release the lock condition, * if any, that it has on its lock file. */ protected void finalize() throws Throwable { trace("finalize(): calling tryRelease()"); tryRelease(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -