class Bootsnap::LoadPathCache::Store

def commit_transaction

def commit_transaction
  if @dirty
    dump_data
    @dirty = false
  end
end

def dump_data

def dump_data
  # Change contents atomically so other processes can't get invalid
  # caches if they read at an inopportune time.
  tmp = "#{@store_path}.#{(rand * 100000).to_i}.tmp"
  FileUtils.mkpath(File.dirname(tmp))
  File.binwrite(tmp, MessagePack.dump(@data))
  FileUtils.mv(tmp, @store_path)
end

def fetch(key)

def fetch(key)
  raise SetOutsideTransactionNotAllowed unless @in_txn
  v = get(key)
  unless v
    @dirty = true
    v = yield
    @data[key] = v
  end
  v
end

def get(key)

def get(key)
  @data[key]
end

def initialize(store_path)

def initialize(store_path)
  @store_path = store_path
  @in_txn = false
  @dirty = false
  load_data
end

def load_data

def load_data
  @data = begin
    MessagePack.load(File.binread(@store_path))
  # handle malformed data due to upgrade incompatability
  rescue Errno::ENOENT, MessagePack::MalformedFormatError, MessagePack::UnknownExtTypeError, EOFError
    {}
  end
end

def set(key, value)

def set(key, value)
  raise SetOutsideTransactionNotAllowed unless @in_txn
  if value != @data[key]
    @dirty = true
    @data[key] = value
  end
end

def transaction

def transaction
  raise NestedTransactionError if @in_txn
  @in_txn = true
  yield
ensure
  commit_transaction
  @in_txn = false
end