summaryrefslogtreecommitdiff
path: root/src/db.erl
diff options
context:
space:
mode:
authorLinus Nordberg <linus@nordberg.se>2014-10-08 16:18:23 +0200
committerLinus Nordberg <linus@nordberg.se>2014-10-08 16:18:23 +0200
commit9d2ef27d1427ef1c61c497c272a74506d651771a (patch)
tree48847b4dd27646a186b52b2040e2597fb179b3d8 /src/db.erl
parent6bceff8e5d10eff9ca59571e80a017afae347ced (diff)
parent409ea0e5857acffe36ebc977bdce843f994a00aa (diff)
Merge remote-tracking branch 'refs/remotes/map/fsync4' into origin-master
Conflicts: src/db.erl src/plop.erl
Diffstat (limited to 'src/db.erl')
-rw-r--r--src/db.erl184
1 files changed, 70 insertions, 114 deletions
diff --git a/src/db.erl b/src/db.erl
index ddebbeb..04c9bd7 100644
--- a/src/db.erl
+++ b/src/db.erl
@@ -6,11 +6,8 @@
%% API.
-export([start_link/0, stop/0]).
--export([init_db/0, init_db/1, init_tables/0, init_tables/1]).
-export([add/4, size/0]).
-export([get_by_index/1, get_by_indices/3, get_by_leaf_hash/1, get_by_entry_hash/1]).
-%% API for testing.
--export([dump/1, destroy_tables/0, info_tables/0, dump_to_file/1]).
%% gen_server callbacks.
-export([init/1, handle_call/3, terminate/2, handle_cast/2, handle_info/2,
code_change/3]).
@@ -19,50 +16,11 @@
-include("db.hrl").
-include("$CTROOT/plop/include/plop.hrl").
-%% @doc Set up a database schema on all nodes that are to be included
-%% in the "database cluster". Has to be run _before_ mnesia has been
-%% started.
-init_db() ->
- init_db([node()]).
-init_db(Nodes) ->
- ok = mnesia:create_schema(Nodes),
- rpc:multicall(Nodes, application, start, [mnesia]),
- init_tables(Nodes),
- rpc:multicall(Nodes, application, stop, [mnesia]).
-
-%% @doc Run once, or rather every time you start on a new database.
-%% If run more than once, we'll get {aborted, {already_exists, TABLE}}.
-init_tables() ->
- init_tables([node()]).
-init_tables(Nodes) ->
- %% We've once upon a time invoked mnesia:create_schema/1 with the
- %% nodes that will be part of the database.
- RamCopies = [],
- DiscCopies = [],
- DiscOnlyCopies = Nodes,
- mnesia:start(),
- {atomic, ok} =
- mnesia:create_table(plop,
- [{type, set},
- {ram_copies, RamCopies},
- {disc_copies, DiscCopies},
- {disc_only_copies, DiscOnlyCopies},
- {attributes, record_info(fields, plop)},
- {majority, true}]),
- {atomic, ok} = mnesia:add_table_index(plop, entryhash),
- {atomic, ok} = mnesia:add_table_index(plop, mtlhash).
-
-destroy_tables() ->
- mnesia:delete_table(plop).
-info_tables() ->
- mnesia:table_info(plop, all).
-dump_to_file(Filename) ->
- mnesia:dump_to_textfile(Filename).
size() ->
- mnesia:table_info(plop, size).
+ binary_to_integer(atomic:readfile(treesize_path())).
init(_Args) ->
- {mnesia:wait_for_tables([plop], 5000), []}.
+ {ok, []}.
start_link() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
@@ -99,10 +57,6 @@ get_by_leaf_hash(LeafHash) ->
get_by_entry_hash(EntryHash) ->
gen_server:call(?MODULE, {get_by_entry_hash, EntryHash}).
-%% Testing and debugging.
-dump(Table) ->
- gen_server:call(?MODULE, {dump, Table}).
-
%%%%%%%%%%%%%%%%%%%%
%% gen_server callbacks.
@@ -122,81 +76,83 @@ terminate(_Reason, _State) ->
%%%%%%%%%%%%%%%%%%%%
%% The meat.
+% Table for Leaf hash -> Entry
+entry_root_path() ->
+ {ok, Value} = application:get_env(plop, entry_root_path),
+ Value.
+
+% Table for Leaf hash -> Entry
+indexforhash_root_path() ->
+ {ok, Value} = application:get_env(plop, indexforhash_root_path),
+ Value.
+
+% Table for Index -> Leaf hash
+index_path() ->
+ {ok, Value} = application:get_env(plop, index_path),
+ Value.
+
+% Table for Entry hash -> Leaf hash
+entryhash_root_path() ->
+ {ok, Value} = application:get_env(plop, entryhash_root_path),
+ Value.
+
+% File that stores tree size
+treesize_path() ->
+ {ok, Value} = application:get_env(plop, treesize_path),
+ Value.
+
+
+entry_for_leafhash(LeafHash) ->
+ perm:readfile(entry_root_path(), LeafHash).
+
+index_for_leafhash(LeafHash) ->
+ binary_to_integer(perm:readfile(indexforhash_root_path(), LeafHash)).
+
+leafhash_for_index(Index) ->
+ index:get(index_path(), Index).
+
+leafhash_for_entryhash(EntryHash) ->
+ perm:readfile(entryhash_root_path(), EntryHash).
+
handle_call(stop, _From, State) ->
{stop, normal, stopped, State};
handle_call({add, {LeafHash, EntryHash, Data, Index}}, _From, State) ->
- R = mnesia:transaction(
- fun() ->
- mnesia:write(
- #plop{
- index = Index,
- mtlhash = LeafHash,
- entryhash = EntryHash,
- logentry = Data})
- end),
- {reply, R, State};
-
-handle_call({get_by_indices, {Start, End, Sorted}}, _From, State) ->
- R = case Sorted of
- false ->
- select_index(Start, End);
- true ->
- %% FIXME: RAM hog -- how bad is it?
- lists:sort(select_index(Start, End))
- end,
+ ok = perm:ensurefile(entry_root_path(), LeafHash, Data),
+ ok = perm:ensurefile(entryhash_root_path(), EntryHash, LeafHash),
+ ok = perm:ensurefile(indexforhash_root_path(),
+ LeafHash, integer_to_binary(Index)),
+ ok = index:add(index_path(), Index, LeafHash),
+ ok = atomic:replacefile(treesize_path(), integer_to_list(Index+1)),
+ {reply, ok, State};
+
+handle_call({get_by_indices, {Start, End, _Sorted}}, _From, State) ->
+ R = lists:map(fun (Index) ->
+ LeafHash = leafhash_for_index(Index),
+ Entry = entry_for_leafhash(LeafHash),
+ {Index, LeafHash, Entry}
+ end, lists:seq(Start, End)),
{reply, R, State};
handle_call({get_by_index, Index}, _From, State) ->
- {reply,
- find_entry(fun() -> mnesia:read(plop, Index) end),
- State};
+ LeafHash = leafhash_for_index(Index),
+ Entry = entry_for_leafhash(LeafHash),
+ R = {Index, LeafHash, Entry},
+ {reply, R, State};
handle_call({get_by_leaf_hash, LeafHash}, _From, State) ->
- {reply,
- find_entry(fun() ->
- mnesia:index_read(plop, LeafHash, #plop.mtlhash)
- end),
- State};
+ Entry = entry_for_leafhash(LeafHash),
+ Index = index_for_leafhash(LeafHash),
+ R = {Index, LeafHash, Entry},
+ {reply, R, State};
handle_call({get_by_entry_hash, EntryHash}, _From, State) ->
- {reply,
- find_entry(fun() ->
- mnesia:index_read(plop, EntryHash, #plop.entryhash)
- end),
- State};
-
-handle_call({dump, Table}, _From, State) ->
- R = mnesia:transaction(
- fun() ->
- Q = qlc:q([E || E <- mnesia:table(Table)]),
- qlc:e(Q)
- end),
- {reply, R, State}.
-
-%%%%%%%%%%%%%%%%%%%%
-%% Helper functions.
-
--spec select_index(non_neg_integer(), non_neg_integer()) ->
- [{non_neg_integer(), binary(), binary()}].
-select_index(Start, End) ->
- F = fun() ->
- %% Get index, mtlhash and logentry.
- MatchHead = {plop, '$1', '$2', '_', '$3'},
- Guard = [{'>=', '$1', Start}, {'=<', '$1', End}],
- Result = ['$$'],
- mnesia:select(plop, [{MatchHead, Guard, Result}])
+ R = case leafhash_for_entryhash(EntryHash) of
+ noentry ->
+ notfound;
+ LeafHash ->
+ Entry = entry_for_leafhash(LeafHash),
+ Index = index_for_leafhash(LeafHash),
+ {Index, LeafHash, Entry}
end,
- {atomic, Res} = mnesia:transaction(F),
- Res.
-
--spec find_entry(fun()) -> notfound |
- {non_neg_integer(), binary(), binary()} |
- duplicate.
-find_entry(Fun) ->
- {atomic, Result} = mnesia:transaction(Fun),
- case Result of
- [] -> notfound;
- [#plop{index = I, mtlhash = H, logentry = E}] -> {I, H, E};
- _ -> duplicate
- end.
+ {reply, R, State}.