# File lib/pstore.rb, line 284
  def transaction(read_only=false)  # :yields:  pstore
    raise PStore::Error, "nested transaction" if @transaction
    begin
      @rdonly = read_only
      @abort = false
      @transaction = true
      value = nil
      new_file = @filename + ".new"

      content = nil
      unless read_only
        file = File.open(@filename, RDWR_ACCESS)
        file.flock(File::LOCK_EX)
        commit_new(file) if FileTest.exist?(new_file)
        content = file.read()
      else
        begin
          file = File.open(@filename, RD_ACCESS)
          file.flock(File::LOCK_SH)
          content = (File.open(new_file, RD_ACCESS) {|n| n.read} rescue file.read())
        rescue Errno::ENOENT
          content = ""
        end
      end

      if content != ""
        @table = load(content)
        if !read_only
          size = content.size
          md5 = Digest::MD5.digest(content)
        end
      else
        @table = {}
      end
      content = nil             # unreference huge data

      begin
        catch(:pstore_abort_transaction) do
          value = yield(self)
        end
      rescue Exception
        @abort = true
        raise
      ensure
        if !read_only and !@abort
          tmp_file = @filename + ".tmp"
          content = dump(@table)
          if !md5 || size != content.size || md5 != Digest::MD5.digest(content)
            File.open(tmp_file, WR_ACCESS) {|t| t.write(content)}
            File.rename(tmp_file, new_file)
            commit_new(file)
          end
          content = nil         # unreference huge data
        end
      end
    ensure
      @table = nil
      @transaction = false
      file.close if file
    end
    value
  end