summaryrefslogtreecommitdiff
path: root/src/ht.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/ht.erl')
-rw-r--r--src/ht.erl56
1 files changed, 46 insertions, 10 deletions
diff --git a/src/ht.erl b/src/ht.erl
index 4b08e34..96a6172 100644
--- a/src/ht.erl
+++ b/src/ht.erl
@@ -39,6 +39,9 @@
-include_lib("eunit/include/eunit.hrl").
-import(lists, [foreach/2, foldl/3, reverse/1]).
+-define(MAX_READ_ENTRIES, 10000).
+-define(MAX_CALC_ENTRIES, 10000).
+
%% Data types.
-record(tree, {version :: integer(),
evaluated :: integer(),
@@ -52,9 +55,14 @@ start_link() ->
start_link(NEntries) ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [NEntries], []).
reset_tree(Arg) ->
- call(?MODULE, {reset_tree, Arg}).
+ gen_server:call(?MODULE, {reset_tree, Arg}, infinity).
load_tree(Version) ->
- call(?MODULE, {load_tree, Version}).
+ case call(?MODULE, {load_tree, Version}) of
+ eagain ->
+ load_tree(Version);
+ Result ->
+ Result
+ end.
stop() ->
call(?MODULE, stop).
size() ->
@@ -62,9 +70,19 @@ size() ->
add(Hash) ->
call(?MODULE, {add, Hash}).
root() ->
- call(?MODULE, root).
+ case call(?MODULE, root) of
+ eagain ->
+ root();
+ Result ->
+ Result
+ end.
root(Version) ->
- call(?MODULE, {root, Version}).
+ case call(?MODULE, {root, Version}) of
+ eagain ->
+ root(Version);
+ Result ->
+ Result
+ end.
path(I, V) ->
call(?MODULE, {path, I, V}).
consistency(V1, V2) ->
@@ -192,13 +210,25 @@ get_hash(Tree, {R, I}) ->
head(Tree, -1) ->
{Tree, hash(<<"">>)};
head(Tree = #tree{version = V}, Version) when Version == V ->
- NewTree = update(Tree),
- {NewTree, get_hash(NewTree, {depth(Tree) - 1, 0})};
+ EndBound = min(Version, Tree#tree.evaluated + ?MAX_CALC_ENTRIES),
+ NewTree = update(Tree, EndBound),
+ case EndBound of
+ Version ->
+ {NewTree, get_hash(NewTree, {depth(Tree) - 1, 0})};
+ _ ->
+ {NewTree, eagain}
+ end;
head(Tree = #tree{version = V}, Version) when Version > V ->
{Tree, enotimetravel};
head(Tree, Version) ->
- NewTree = update(Tree, Version),
- {NewTree, old_version_tree_head(NewTree, Version)}.
+ EndBound = min(Version, Tree#tree.evaluated + ?MAX_CALC_ENTRIES),
+ NewTree = update(Tree, EndBound),
+ case EndBound of
+ Version ->
+ {NewTree, old_version_tree_head(NewTree, Version)};
+ _ ->
+ {NewTree, eagain}
+ end.
-spec old_version_tree_head(tree(), non_neg_integer()) -> binary().
old_version_tree_head(Tree, Version) ->
@@ -262,12 +292,18 @@ add(Tree = #tree{version = V, store = Store}, Hash) ->
Tree#tree{version = V + 1, store = ts:add(Store, 0, Hash)}.
read_new_entries(State, Version) when is_integer(Version) ->
- NewEntries = db:get_by_indices(State#tree.version + 1, Version, {sorted, true}),
+ EndBound = min(Version, State#tree.version + ?MAX_READ_ENTRIES),
+ NewEntries = db:get_by_indices(State#tree.version + 1, EndBound, {sorted, true}),
NewState = foldl(fun(Hash, Tree) ->
add(Tree, Hash)
end, State, [H || {_I, H, _E} <-
NewEntries]),
- {ok, NewState}.
+ case EndBound of
+ Version ->
+ {ok, NewState};
+ _ ->
+ {eagain, NewState}
+ end.
%% @doc Return a new tree.
-spec new(list()) -> tree().