-
-
Save hansonkd/a0a974704a8483216dca2a1e79c00e62 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule CubDB.Store.MerkleStore do | |
@moduledoc false | |
# `CubDB.Store.MerkleStore` is an implementation of the `Store` protocol | |
# intended for test purposes only. It is backed by a map, but supports all the | |
# operations of a `CubDB.Store`. It allows some tests to be simpler and faster | |
# by avoid using the file system. | |
defstruct agent: nil | |
alias CubDB.Store.MerkleStore | |
@type t :: %MerkleStore{agent: pid} | |
@spec create() :: {:ok, t} | {:error, term} | |
def create do | |
with {:ok, pid} <- Agent.start_link(fn -> {%{}, nil} end) do | |
{:ok, %MerkleStore{agent: pid}} | |
end | |
end | |
end | |
defimpl CubDB.Store, for: CubDB.Store.MerkleStore do | |
alias CubDB.Store.MerkleStore | |
def clean_up(_store, cpid, btree) do | |
:ok | |
end | |
def clean_up_old_compaction_files(store, pid) do | |
:ok | |
end | |
def start_cleanup(%MerkleStore{}) do | |
{:ok, nil} | |
end | |
def next_compaction_store(%MerkleStore{}) do | |
Store.MerkleStore.create() | |
end | |
def put_node(%MerkleStore{agent: agent}, node) do | |
Agent.get_and_update( | |
agent, | |
fn {map, latest_header_loc} -> | |
loc = :crypto.hash(:blake2b, :erlang.term_to_binary(node)) | |
{loc, {Map.put(map, loc, node), latest_header_loc}} | |
end, | |
:infinity | |
) | |
end | |
def put_header(%MerkleStore{agent: agent}, header) do | |
Agent.get_and_update( | |
agent, | |
fn {map, _} -> | |
loc = :crypto.hash(:blake2b, :erlang.term_to_binary(header)) | |
{loc, {Map.put(map, loc, header), loc}} | |
end, | |
:infinity | |
) | |
end | |
def sync(%MerkleStore{}), do: :ok | |
def get_node(%MerkleStore{agent: agent}, location) do | |
case Agent.get( | |
agent, | |
fn {map, _} -> | |
Map.fetch(map, location) | |
end, | |
:infinity | |
) do | |
{:ok, value} -> value | |
:error -> raise(ArgumentError, message: "End of file") | |
end | |
end | |
def get_latest_header(%MerkleStore{agent: agent}) do | |
Agent.get( | |
agent, | |
fn | |
{_, nil} -> nil | |
{map, header_loc} -> {header_loc, Map.get(map, header_loc)} | |
end, | |
:infinity | |
) | |
end | |
def close(%MerkleStore{agent: agent}) do | |
Agent.stop(agent, :normal, :infinity) | |
end | |
def blank?(%MerkleStore{agent: agent}) do | |
Agent.get( | |
agent, | |
fn | |
{_, nil} -> true | |
_ -> false | |
end, | |
:infinity | |
) | |
end | |
def open?(%MerkleStore{agent: agent}) do | |
Process.alive?(agent) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment