Show More
Commit Description:
better all sub progres report
Commit Description:
better all sub progres report
File last commit:
Show/Diff file:
Action:
lib/dir_init.rb | 113 lines | 2.7 KiB | text/x-ruby | RubyLexer |
require 'fileutils'
# DirInit::Manager handles directory initialization and clean-up when
# there are many concurrent processes that wants to modify the
# directory in the same way.
#
# An example usage is when each process wants to copy some temporary
# files to the directory and delete these files after finishing its
# job. Problems may occur when the first process delete the files
# while the second process is still using the files.
#
# This library maintain a reference counter on the processes using the
# directory. It locks the dir to manage critical section when
# updating the reference counter.
module DirInit
class Manager
def initialize(dir_name, usage_filename='.usage_counter')
@dir_name = dir_name
@usage_filename = usage_filename
end
def lock_filename
return @dir_name + '/lockfile'
end
# Check if someone has initialized the dir. If not, call block.
def setup # :yields: block
dir = File.new(lock_filename,"w+")
dir.flock(File::LOCK_EX)
begin
counter_filename = get_counter_filename
if File.exist? counter_filename
# someone is here
f = File.new(counter_filename,"r+")
counter = f.read.to_i
f.seek(0)
f.write("#{counter+1}\n")
f.close
else
# i'm the first, create the counter file
counter = 0
f = File.new(counter_filename,"w")
f.write("1\n")
f.close
end
# if no one is here
if counter == 0
if block_given?
yield
end
end
rescue
raise
ensure
# make sure it unlock the directory
dir.flock(File::LOCK_UN)
dir.close
end
end
# Check if I am the last one using the dir. If true, call block.
def teardown
dir = File.new(lock_filename)
dir.flock(File::LOCK_EX)
begin
counter_filename = get_counter_filename
if File.exist? counter_filename
# someone is here
f = File.new(counter_filename,"r+")
counter = f.read.to_i
f.seek(0)
f.write("#{counter-1}\n")
f.close
if counter == 1
# i'm the last one
File.delete(counter_filename)
if block_given?
yield
end
end
else
# This is BAD
raise "Error: reference count missing"
end
rescue
raise
ensure
# make sure it unlock the directory
dir.flock(File::LOCK_UN)
dir.close
end
end
protected
def get_counter_filename
return File.join(@dir_name,@usage_filename)
end
end
end