Current section
Files
Jump to
Current section
Files
lib/store.ex
defmodule Exkad.Store do
use GenServer
def start_link(opts) do
GenServer.start_link(__MODULE__, opts)
end
def init(_opts) do
{:ok, %{values: %{}, meta: %{}}}
end
def put(server, value) do
GenServer.call(server, {:put, value})
end
def put_meta(server, term, ptr) do
GenServer.call(server, {:put_meta, term, ptr})
end
def search(server, key) do
GenServer.call(server, {:get_meta, key})
end
def get(server, key) do
GenServer.call(server, {:get, key})
end
#Streaming hash
# def hash(s) do
# ctx = :crypto.hash_init(:md5)
# ctx = Enum.reduce(s, ctx, fn chunk, acc ->
# :crypto.hash_update(acc, chunk)
# end)
# :crypto.hash_final(ctx)
# |> :erlang.bitstring_to_list
# |> Enum.map(&(:io_lib.format("~2.16.0b", [&1])))
# |> List.flatten
# |> :erlang.list_to_bitstring
# end
def hash(bin) do
:crypto.hash(:md5, bin)
|> :erlang.bitstring_to_list
|> Enum.map(&(:io_lib.format("~2.16.0b", [&1])))
|> List.flatten
|> :erlang.list_to_bitstring
end
def handle_call({:put_meta, term, ptr}, _from, state) do
key = hash(term)
ptrs = case state.meta[key] do
nil -> [ptr]
existing -> [ptr | existing]
end
meta = Dict.put(state.meta, key, ptrs)
state = Enum.into(%{meta: meta}, state)
{:reply, {:ok, key}, state}
end
def handle_call({:get_meta, key}, _from, state) do
res = Dict.get(state.meta, key, [])
{:reply, {:ok, res}, state}
end
def handle_call({:put, value}, _from, state) do
key = hash(value)
values = Dict.put(state.values, key, value)
state = Enum.into(%{values: values}, state)
{:reply, {:ok, key}, state}
end
def handle_call({:get, key}, _from, state) do
res = case state.values[key] do
nil -> {:error, :not_found}
val -> {:ok, val}
end
{:reply, res, state}
end
end