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
79
80
81
82
83
84
85
86
87
88
89
90
91
|
defprotocol SData.Page do
@moduledoc"""
Protocol to be implemented by objects that are used as data pages
in a pagestore and that may reference other data pages by their hash.
"""
@fallback_to_any true
@doc"""
Get hashes of all pages referenced by this page.
"""
def refs(page)
end
defimpl SData.Page, for: Any do
def refs(_page), do: []
end
defprotocol SData.PageStore do
@moduledoc"""
Protocol to be implemented for page stores to allow their
manipulation.
This protocol may also be implemented by store proxies that track
operations and implement different synchronization or caching mechanisms.
"""
@doc"""
Put a page. Argument is the content of the page, returns the
hash that the store has associated to it.
Returns {hash, store}
"""
def put(store, page)
@doc"""
Get a page referenced by its hash.
Returns page
"""
def get(store, hash)
@doc"""
Copy to the store a page and all its references from the other store.
In the case of pages on the network in a distributed store, this may
be lazy.
Returns store
"""
def copy(store, other_store, hash)
@doc"""
Free a page referenced by its hash, marking it as no longer needed.
Returns store
"""
def free(store, hash)
end
defmodule SData.LocalStore do
defstruct [:pages]
def new() do
%SData.LocalStore{ pages: %{} }
end
end
defimpl SData.PageStore, for: SData.LocalStore do
def put(store, page) do
hash = SData.term_hash page
store = %{ store | pages: Map.put(store.pages, hash, page) }
{ hash, store }
end
def get(store, hash) do
store.pages[hash]
end
def copy(store, other_store, hash) do
page = SData.PageStore.get(other_store, hash)
refs = SData.Page.refs(page)
store = Enum.reduce(refs, store, fn x, acc -> copy(acc, other_store, x) end)
%{ store | pages: Map.put(store.pages, hash, page) }
end
def free(store, hash) do
%{ store | pages: Map.delete(store.pages, hash) }
end
end
|