URLS

   http://raa.ruby-lang.org/project/lockfile/
   http://www.codeforpeople.com/lib/ruby/lockfile/

SYNOPSIS

   lib/lockfile.rb : a ruby library for creating NFS safe lockfiles

   bin/rlock : ruby command line tool which uses this library to create
               lockfiles. run 'rlock -h' for more info

INSTALL

   sudo ruby install.rb


BASIC ALGORITHIM

   * create a globally uniq filename in the same filesystem as the desired
     lockfile - this can be nfs mounted

   * link(2) this file to the desired lockfile, ignore all errors

   * stat the uniq filename and desired lockfile to determine is they are the
     same, use only stat.rdev and stat.ino - ignore stat.nlink as NFS can cause
     this report incorrect values

   * iff same, you have lock.  either return or run optional code block with
     optional refresher thread keeping lockfile fresh during execution of code
     block, ensuring that the lockfile is removed..

   * iff not same try again a few times in rapid succession (poll), then, iff
     this fails, sleep using incremental backoff time.  optionally remove
     lockfile if it is older than a certain time, timeout if more than a certain
     amount of time has passed attempting to lock file.


BASIC USAGE

   1)
     lockfile = Lockfile.new 'file.lock'
     begin
       lockfile.lock
       p 42
     ensure
       lockfile.unlock
     end


   2)
     require 'pstore'           # which is NOT nfs safe on it's own

     opts = {                   # the keys can be symbols or strings

       :retries        => nil,  # we will try forever to aquire the lock

       :sleep_inc      => 2,    # we will sleep 2 seconds longer than the
                                # previous sleep after each retry, cycling from
                                # min_sleep upto max_sleep downto min_sleep upto
                                # max_sleep, etc., etc.

       :min_sleep      => 2,    # we will never sleep less than 2 seconds

       :max_sleep      => 32,   # we will never sleep longer than 32 seconds

       :max_age        => 1024, # we will blow away any files found to be older
                                # than this (lockfile.thief? #=> true)

       :suspend        => 64,   # iff we steal the lock from someone else - wait
                                # this long to give them a chance to realize it

       :refresh        => 8,    # we will spawn a bg thread that touches file
                                # every 8 sec.  this thread also causes a
                                # StolenLockError to be thrown if the lock
                                # disappears from under us - note that the
                                # 'detection' rate is limited to the refresh
                                # interval - this is a race condition

       :timeout        => nil,  # we will wait forever

       :poll_retries   => 16,   # the initial attempt to grab a lock is done in a
                                # polling fashion, this number controls how many
                                # times this is done - the total polling attempts
                                # are considered ONE actual attempt (see retries
                                # above)

       :poll_max_sleep => 0.08, # when polling a very brief sleep is issued
                                # between attempts, this is the upper limit of
                                # that sleep timeout

       :debug => true,          # trace execution step on stdout
     }

     pstore = PStore.new 'file.db'
     lockfile = Lockfile.new 'file.db.lock', opts
     lockfile.lock do
       pstore.transaction do
         pstore[:last_update_time] = Time.now
       end
     end

   3) same as 1 above - Lockfile.new takes a block and ensures unlock is called

     Lockfile.new('file.lock') do
       p 42
     end

   4) watch locking algorithim in action

       Lockfile.debug = true
       Lockfile.new('file.lock') do
         p 42
       end

     you can also set debugging via the ENV var LOCKFILE_DEBUG, eg.

     ~ > LOCKFILE_DEBUG=true rlock lockfile


SAMPLES

   * see samples/a.rb
   * see samples/nfsstore.rb
   * see bin/rlock

AUTHOR

   -a

EMAIL

   Ara.T.Howard / noaa.gov

BUGS

   > 1

   further notifications to email above

HISTORY

   1.0.0:
     - allow rertries to be nil, meaning to try forever
     - default timeout is now nil - never timeout
     - default refresh is now 8
     - fixed bug where refresher thread was not actually touching lockfile! (ouch)
     - added cycle method to timeouts
         1-2-3-2-1-2-3-1...
       pattern is constructed using min_sleep, sleep_inc, max_sleep
   0.3.0:
     - removed use of yaml in favour of hand parsing the lockfile contents, the
       file as so small it just wasn't worth and i have had one core dump when yaml
       failed to parse a (corrupt) file
   0.2.0:
     - added an initial polling style attempt to grab lock before entering normal
       sleep/retry loop.  this has really helped performance when lock is under
       heavy contention: i see almost no sleeping done by any of in the interested
       processes
   0.1.0:
     - added ability of Lockfile.new to accept a block
   0.0.0:
     - initial version