I was writing a Ruby program today that just needed a very simple way to control multiple web requests to a Sinatra server from querying a remote server at the same time. I would think that Sinatra does have some nice way to do this(and if you know it, please send me the link
), but I didn’t have time to dig into it, so I pulled out my old trusty Lockfile class.
The concept is very simple: Open a file, put a random string into it, close it. I use the random string to make sure that my process really did create the file, rather than another process running at the same time. The verify method can be called at any time to check that we still have the lock….well, that we are suppose to have the lock
If the file already exists, then you don’t get the lock. If you can’t open the file, then someone else must have just opened it, and again no lock.
Now the source…
#
# Lockfile.rb -- Implement a simple lock file method
#
class Lockfile
attr_accessor :lockfile
@lockcode = ""
def initialize(lckf)
@lockfile = lckf
if File.exists?(@lockfile)
return false
else
lck = create
## verify that we indeed did get the lock
if self.verify
return
else
return false
end
end
end
def verify
if not File.exists?(@lockfile)
return false
end
if readlock == @lockcode
return true
else
return false
end
end
def release
if self.verify
begin
File.delete(@lockfile)
@lockcode = ""
rescue Exception => e
return false
end
return true
else
return false
end
end
def create_key(length)
alpha = [('a'..'z'),('A'..'Z')].map{|i| i.to_a}.flatten
return (0..length).map{ alpha[rand(alpha.length)] }.join
end
def finalize(id)
#
# Ensure lock file is erased when object dies before being released
#
File.delete(@lockfile)
end
##-----------------##
private
##-----------------##
def create
@lockcode = create_key(80)
begin
g = File.open(@lockfile,"w")
g.write @lockcode
g.close
rescue Exception => e
return false
end
return true
end
def readlock
code = ""
begin
g = File.open(@lockfile,"r")
code = g.read
g.close
rescue
return ""
end
return code
end
end
Using the class is pretty simple:
irb(main):085:0>p lockfile "test.lck" => nil irb(main):086:0> g = Lockfile.new(lockfile) => #<Lockfile:0x2d842ec @lockcode="eIRpefAHnAVZDtpiXXAbwblegdkFidHwkyKhJPKdGzRYOuJWRRVYtIXEWZPgyfycODxdeHfLYsPxcepVQ", @lockfile="test.lck"> irb(main):087:0> g.verify => true irb(main):088:0> h = Lockfile.new(lockfile) => #<Lockfile:0x2d7ff58 @lockfile="test.lck"> irb(main):089:0> h.verify => false irb(main):090:0> h.release => false irb(main):093:0> g.verify => true irb(main):094:0> g.release => true irb(main):095:0> File.exists?(lockfile) => false irb(main):096:0>
Good luck and have fun programming!






