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.1: - fixed bugette in sleep cycle where repeated locks with same lockfile would not reset the cycle at the start of each lock 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