grendel.storage
Class UnixDotLock

java.lang.Object
  |
  +--grendel.storage.UnixDotLock

public class UnixDotLock
extends java.lang.Object

Implements Unix-style dot-locking (locking file "FOO" by using an atomically-created file in the same directory named "FOO.lock".)

Use it like this:

All the lock-retrying and lock-date-maintenance happens under the covers.

See also the description of movemail.

Implementation details:

The protocol for getting a lock on some file "FOO" is as follows:

  1. Create a file "FOO.1234" (random unused name.)

  2. Hard-link "FOO.1234" to "FOO.lock".
    (this is the trick, because link() happens to be one of the few atomic, synchronized operations over NFS.)

  3. Unlink "FOO.1234"
    (regardless of whether step 2 succeeded; now either we have a "FOO.lock" file or we don't.)

  4. If we obtained the lock (the link() call in step #2 succeeded), then we're done.

  5. Else if the creation-time of "FOO.lock" is more than 60 seconds in the past, then smash the lock (unlink "FOO.lock") and goto step #1.)

  6. Else, the lock is held and current. Wait a second, then goto step #1 and try again.

One thing implied by this is that if one wants to hold a lock for longer than 60 seconds (which we do in some cases) then one must maintain the lock file: its modification-date must be updated every less-than-60 seconds. We do this by having a ``heartbeat'' thread that wakes up periodically and updates all held locks.


Constructor Summary
UnixDotLock(java.io.File file)
          Lock the named file.
 
Method Summary
protected  void finalize()
          If this object becomes reclaimed without unlock() having been called, then call it (thus unlocking the underlying disk file.)
static void main(java.lang.String[] arg)
           
 void unlock()
          Unlock the file.
 
Methods inherited from class java.lang.Object
clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

UnixDotLock

public UnixDotLock(java.io.File file)
            throws java.lang.SecurityException,
                   java.io.IOException,
                   java.lang.InterruptedException
Lock the named file. Unlock it by calling the unlock() method. If you do not call unlock() before discarding the UnixDotLock object, the file will remain locked!
Throws:
java.lang.SecurityException - the lock file could not be created (file permission problems?)
java.io.IOException - a disk I/O error occurred.
java.lang.InterruptedException - this thread was killed while waiting for the lock.
Method Detail

unlock

public void unlock()
Unlock the file. This must be called before discarding the UnixDotLock object, and may be called only once. The UnixDotLock object must not be used again after calling this.
Throws:
java.lang.InterruptedException - this thread was killed while waiting for the lock.

finalize

protected void finalize()
                 throws java.lang.Throwable
If this object becomes reclaimed without unlock() having been called, then call it (thus unlocking the underlying disk file.)
Throws:
java.lang.Throwable -  
Overrides:
finalize in class java.lang.Object

main

public static final void main(java.lang.String[] arg)
                       throws java.lang.SecurityException,
                              java.io.IOException,
                              java.lang.InterruptedException