def transaction(read_only=false)
raise PStore::Error, "nested transaction" if @transaction
begin
@transaction = true
value = nil
backup = @filename+"~"
begin
file = File::open(@filename, read_only ? "rb" : "rb+")
orig = true
rescue Errno::ENOENT
raise if read_only
file = File::open(@filename, "wb+")
end
file.flock(read_only ? File::LOCK_SH : File::LOCK_EX)
if read_only
@table = Marshal::load(file)
elsif orig and (content = file.read) != ""
@table = Marshal::load(content)
size = content.size
md5 = Digest::MD5.digest(content)
content = nil
else
@table = {}
end
begin
catch(:pstore_abort_transaction) do
value = yield(self)
end
rescue Exception
@abort = true
raise
ensure
if !read_only and !@abort
file.rewind
content = Marshal::dump(@table)
if !md5 || size != content.size || md5 != Digest::MD5.digest(content)
File::copy @filename, backup
begin
file.write(content)
file.truncate(file.pos)
content = nil
rescue
File::rename backup, @filename if File::exist?(backup)
raise
end
end
end
if @abort and !orig
File.unlink(@filename)
end
@abort = false
end
ensure
@table = nil
@transaction = false
file.close if file
end
value
end