defmodule SApp.BlockStore do
@moduledoc """
A module that implements a content-adressable storage (blocks, or pages,
identified by the hash of their contents).
Establishes full node connectivity and uses rendez-vous hashing to select
which nodes are responsible of a given hash.
TODO: WIP
"""
use GenServer
defmodule State do
defstruct [:name, :id, :manifest,
:ncopies,
:store, :peers]
end
def start_link(name) do
GenServer.start_link(__MODULE__, name)
end
def init(name) do
manifest = {:blockstore, name}
id = SData.term_hash manifest
GenServer.cast(Shard.Manager, {:register, id, self()})
GenServer.cast(self(), :init_pull)
{:ok, %State{name: name, id: id, manifest: manifest,
ncopies: 3,
store: %{}, peers: %{}}}
end
def handle_call(:manifest, _from, state) do
{:reply, state.manifest, state}
end
def handle_call({:get, key}, from, state) do
# TODO
end
def handle_call({:put, val}, state) do
# TODO
end
def handle_cast({:redundant, _}, _state) do
exit :normal
end
def handle_cast(:init_pull, state) do
GenServer.call(SNet.Manager, :get_all)
|> Enum.each(&(GenServer.cast(&1, {:send_msg, {:interested, [state.id]}})))
{:noreply, state}
end
def handle_cast({:interested, peer_id, peer_pid}, state) do
new_peers = Map.put(state.peers, peer_id, peer_pid)
new_state = %{ state | peers: new_peers }
initial_sync(new_state, peer_id, peer_pid)
{:noreply, new_state}
end
def handle_cast({:msg, peer_id, peer_pid, msg}, state) do
# TODO
{:noreply, state}
end
defp initial_sync(state, peer_id, peer_pid) do
# TODO
end
defp send(state, to, msg) do
GenServer.cast(to, {:send_msg, {state.id, msg}})
end
end