aboutsummaryrefslogtreecommitdiff
path: root/lib/app/blockstore.ex_
blob: 2854161bccb87abcabf945dd03514e9eaf6e5f0c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
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