summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Newson <rnewson@apache.org>2020-07-21 16:43:12 +0100
committerRobert Newson <rnewson@apache.org>2020-07-21 16:43:12 +0100
commit3602eafd0684aa6add73ccc06d4d3690ccfb585c (patch)
tree36dc1675fb6f3dc77092823e4868259ef1858725
parent6233d43b711fa83cf034f87466c8a666765f0cd6 (diff)
downloadcouchdb-prototype/fdb-layer-ebtree-fabric-style.tar.gz
switch from erlfdb to fabric2_fdbprototype/fdb-layer-ebtree-fabric-style
-rw-r--r--src/ebtree/src/ebtree.app.src3
-rw-r--r--src/ebtree/src/ebtree.erl316
2 files changed, 177 insertions, 142 deletions
diff --git a/src/ebtree/src/ebtree.app.src b/src/ebtree/src/ebtree.app.src
index d4966f6a5..10dc5142c 100644
--- a/src/ebtree/src/ebtree.app.src
+++ b/src/ebtree/src/ebtree.app.src
@@ -17,7 +17,8 @@
{applications,
[kernel,
stdlib,
- erlfdb
+ erlfdb,
+ fabric
]},
{env,[]},
{modules, []},
diff --git a/src/ebtree/src/ebtree.erl b/src/ebtree/src/ebtree.erl
index ccfd4141a..042873c51 100644
--- a/src/ebtree/src/ebtree.erl
+++ b/src/ebtree/src/ebtree.erl
@@ -80,13 +80,14 @@ open(Db, Prefix, Order, Options) when is_binary(Prefix), is_integer(Order), Orde
ReduceFun = proplists:get_value(reduce_fun, Options, fun reduce_noop/2),
CollateFun = proplists:get_value(collate_fun, Options, fun collate_raw/2),
- erlfdb:transactional(Db, fun(Tx) ->
- case get_meta(Tx, Prefix, ?META_ORDER) of
+ fabric2_fdb:transactional(Db, fun(TxDb) ->
+ #{tx := Tx} = TxDb,
+ case get_meta(TxDb, Prefix, ?META_ORDER) of
not_found ->
erlfdb:clear_range_startswith(Tx, Prefix),
- set_meta(Tx, Prefix, ?META_ORDER, Order),
- set_meta(Tx, Prefix, ?META_NEXT_ID, 1),
- set_node(Tx, init_tree(Prefix, Order), #node{id = ?NODE_ROOT_ID});
+ set_meta(TxDb, Prefix, ?META_ORDER, Order),
+ set_meta(TxDb, Prefix, ?META_NEXT_ID, 1),
+ set_node(TxDb, init_tree(Prefix, Order), #node{id = ?NODE_ROOT_ID});
Order ->
ok;
Else ->
@@ -167,8 +168,8 @@ fold(Db, #tree{} = Tree, Fun, Acc) ->
Options :: [fold_option()],
Acc1 :: term().
fold(Db, #tree{} = Tree, Fun, Acc, Options) ->
- {_, Reduce} = erlfdb:transactional(Db, fun(Tx) ->
- Root = get_node(Tx, Tree, ?NODE_ROOT_ID),
+ {_, Reduce} = fabric2_fdb:transactional(Db, fun(TxDb) ->
+ Root = get_node(TxDb, Tree, ?NODE_ROOT_ID),
fold(Db, Tree, Root, Fun, Acc, Options)
end),
Reduce.
@@ -375,26 +376,26 @@ group_reduce(Db, #tree{} = Tree, StartKey, EndKey, GroupKeyFun, UserAccFun, User
-spec range(Db :: term(), Tree :: #tree{}, StartKey :: term(), EndKey :: term(),
AccFun :: fun(), Acc0 :: term()) -> term().
range(Db, #tree{} = Tree, StartKey, EndKey, AccFun, Acc0) ->
- erlfdb:transactional(Db, fun(Tx) ->
- range(Tx, Tree, get_node(Tx, Tree, ?NODE_ROOT_ID), StartKey, EndKey, AccFun, Acc0)
+ fabric2_fdb:transactional(Db, fun(TxDb) ->
+ range(TxDb, Tree, get_node(TxDb, Tree, ?NODE_ROOT_ID), StartKey, EndKey, AccFun, Acc0)
end).
-range(Tx, #tree{} = Tree, #node{level = 0} = Node, StartKey, EndKey, AccFun, Acc0) ->
+range(TxDb, #tree{} = Tree, #node{level = 0} = Node, StartKey, EndKey, AccFun, Acc0) ->
InRange = [{K, V} || {K, V} <- Node#node.members,
less_than_or_equal(Tree, StartKey, K), less_than_or_equal(Tree, K, EndKey)],
Acc1 = AccFun(InRange, Acc0),
LastKey = last_key(Node),
case Node#node.next /= undefined andalso less_than_or_equal(Tree, LastKey, EndKey) of
true ->
- range(Tx, Tree, get_node(Tx, Tree, Node#node.next), StartKey, EndKey, AccFun, Acc1);
+ range(TxDb, Tree, get_node(TxDb, Tree, Node#node.next), StartKey, EndKey, AccFun, Acc1);
false ->
Acc1
end;
-range(Tx, #tree{} = Tree, #node{} = Node, StartKey, EndKey, AccFun, Acc) ->
+range(TxDb, #tree{} = Tree, #node{} = Node, StartKey, EndKey, AccFun, Acc) ->
ChildId = find_child_id(Tree, Node, StartKey),
- range(Tx, Tree, get_node(Tx, Tree, ChildId), StartKey, EndKey, AccFun, Acc).
+ range(TxDb, Tree, get_node(TxDb, Tree, ChildId), StartKey, EndKey, AccFun, Acc).
%% @doc Finds all key-value pairs for the specified range in reverse order.
@@ -408,26 +409,26 @@ range(Tx, #tree{} = Tree, #node{} = Node, StartKey, EndKey, AccFun, Acc) ->
-spec reverse_range(Db :: term(), Tree :: #tree{}, StartKey :: term(), EndKey :: term(),
AccFun :: fun(), Acc0 :: term()) -> term().
reverse_range(Db, #tree{} = Tree, StartKey, EndKey, AccFun, Acc0) ->
- erlfdb:transactional(Db, fun(Tx) ->
- reverse_range(Tx, Tree, get_node(Tx, Tree, ?NODE_ROOT_ID), StartKey, EndKey, AccFun, Acc0)
+ fabric2_fdb:transactional(Db, fun(TxDb) ->
+ reverse_range(TxDb, Tree, get_node(TxDb, Tree, ?NODE_ROOT_ID), StartKey, EndKey, AccFun, Acc0)
end).
-reverse_range(Tx, #tree{} = Tree, #node{level = 0} = Node, StartKey, EndKey, AccFun, Acc0) ->
+reverse_range(TxDb, #tree{} = Tree, #node{level = 0} = Node, StartKey, EndKey, AccFun, Acc0) ->
InRange = [{K, V} || {K, V} <- Node#node.members,
less_than_or_equal(Tree, StartKey, K), less_than_or_equal(Tree, K, EndKey)],
Acc1 = AccFun(lists:reverse(InRange), Acc0),
FirstKey = first_key(Node),
case Node#node.prev /= undefined andalso less_than_or_equal(Tree, StartKey, FirstKey) of
true ->
- reverse_range(Tx, Tree, get_node(Tx, Tree, Node#node.prev), StartKey, EndKey, AccFun, Acc1);
+ reverse_range(TxDb, Tree, get_node(TxDb, Tree, Node#node.prev), StartKey, EndKey, AccFun, Acc1);
false ->
Acc1
end;
-reverse_range(Tx, #tree{} = Tree, #node{} = Node, StartKey, EndKey, AccFun, Acc) ->
+reverse_range(TxDb, #tree{} = Tree, #node{} = Node, StartKey, EndKey, AccFun, Acc) ->
ChildId = find_child_id(Tree, Node, EndKey),
- reverse_range(Tx, Tree, get_node(Tx, Tree, ChildId), StartKey, EndKey, AccFun, Acc).
+ reverse_range(TxDb, Tree, get_node(TxDb, Tree, ChildId), StartKey, EndKey, AccFun, Acc).
%% @doc Inserts or updates a value in the ebtree
@@ -444,31 +445,31 @@ insert(_Db, #tree{} = _Tree, ?MAX, _Value) ->
erlang:error(max_not_allowed);
insert(Db, #tree{} = Tree, Key, Value) ->
- erlfdb:transactional(Db, fun(Tx) ->
- Root0 = get_node(Tx, Tree, ?NODE_ROOT_ID),
+ fabric2_fdb:transactional(Db, fun(TxDb) ->
+ Root0 = get_node(TxDb, Tree, ?NODE_ROOT_ID),
case ?is_full(Tree, Root0) of
true ->
- OldRoot = Root0#node{id = new_node_id(Tx, Tree)},
+ OldRoot = Root0#node{id = new_node_id(TxDb, Tree)},
FirstKey = first_key(OldRoot),
LastKey = last_key(OldRoot),
Root1 = #node{
id = ?NODE_ROOT_ID,
level = Root0#node.level + 1,
members = [{FirstKey, LastKey, OldRoot#node.id, []}]},
- {Root2, _, _} = split_child(Tx, Tree, Root1, OldRoot),
- insert_nonfull(Tx, Tree, Root2, Key, Value);
+ {Root2, _, _} = split_child(TxDb, Tree, Root1, OldRoot),
+ insert_nonfull(TxDb, Tree, Root2, Key, Value);
false ->
- insert_nonfull(Tx, Tree, Root0, Key, Value)
+ insert_nonfull(TxDb, Tree, Root0, Key, Value)
end
end),
Tree.
-split_child(Tx, #tree{} = Tree, #node{} = Parent0, #node{} = Child) ->
+split_child(TxDb, #tree{} = Tree, #node{} = Parent0, #node{} = Child) ->
{LeftMembers, RightMembers} = lists:split(Tree#tree.min, Child#node.members),
- LeftId = new_node_id(Tx, Tree),
- RightId = new_node_id(Tx, Tree),
+ LeftId = new_node_id(TxDb, Tree),
+ RightId = new_node_id(TxDb, Tree),
LeftChild = remove_pointers_if_not_leaf(#node{
id = LeftId,
@@ -486,8 +487,8 @@ split_child(Tx, #tree{} = Tree, #node{} = Parent0, #node{} = Child) ->
members = RightMembers
}),
- update_prev_neighbour(Tx, Tree, LeftChild),
- update_next_neighbour(Tx, Tree, RightChild),
+ update_prev_neighbour(TxDb, Tree, LeftChild),
+ update_next_neighbour(TxDb, Tree, RightChild),
%% adjust parent members
FirstLeftKey = first_key(LeftMembers),
@@ -505,40 +506,40 @@ split_child(Tx, #tree{} = Tree, #node{} = Parent0, #node{} = Child) ->
umerge(Tree, [{FirstRightKey, LastRightKey, RightId, RightReduction}],
lists:keydelete(Child#node.id, 3, Parent0#node.members)))
},
- clear_node(Tx, Tree, Child),
- set_nodes(Tx, Tree, [LeftChild, RightChild, Parent1]),
+ clear_node(TxDb, Tree, Child),
+ set_nodes(TxDb, Tree, [LeftChild, RightChild, Parent1]),
{Parent1, LeftChild, RightChild}.
-update_prev_neighbour(_Tx, #tree{} = _Tree, #node{prev = undefined} = _Node) ->
+update_prev_neighbour(_TxDb, #tree{} = _Tree, #node{prev = undefined} = _Node) ->
ok;
-update_prev_neighbour(Tx, #tree{} = Tree, #node{} = Node) ->
- Left = get_node(Tx, Tree, Node#node.prev),
- set_node(Tx, Tree, Left#node{next = Node#node.id}).
+update_prev_neighbour(TxDb, #tree{} = Tree, #node{} = Node) ->
+ Left = get_node(TxDb, Tree, Node#node.prev),
+ set_node(TxDb, Tree, Left#node{next = Node#node.id}).
-update_next_neighbour(_Tx, #tree{} = _Tree, #node{next = undefined} = _Node) ->
+update_next_neighbour(_TxDb, #tree{} = _Tree, #node{next = undefined} = _Node) ->
ok;
-update_next_neighbour(Tx, #tree{} = Tree, #node{} = Node) ->
- Left = get_node(Tx, Tree, Node#node.next),
- set_node(Tx, Tree, Left#node{prev = Node#node.id}).
+update_next_neighbour(TxDb, #tree{} = Tree, #node{} = Node) ->
+ Left = get_node(TxDb, Tree, Node#node.next),
+ set_node(TxDb, Tree, Left#node{prev = Node#node.id}).
-insert_nonfull(Tx, #tree{} = Tree, #node{level = 0} = Node0, Key, Value) ->
+insert_nonfull(TxDb, #tree{} = Tree, #node{level = 0} = Node0, Key, Value) ->
Node1 = Node0#node{
members = umerge(Tree, [{Key, Value}], Node0#node.members)
},
- set_node(Tx, Tree, Node1),
+ set_node(TxDb, Tree, Node1),
reduce_node(Tree, Node1);
-insert_nonfull(Tx, #tree{} = Tree, #node{} = Node0, Key, Value) ->
+insert_nonfull(TxDb, #tree{} = Tree, #node{} = Node0, Key, Value) ->
ChildId0 = find_child_id(Tree, Node0, Key),
- Child0 = get_node(Tx, Tree, ChildId0),
+ Child0 = get_node(TxDb, Tree, ChildId0),
{Node1, Child1} = case ?is_full(Tree, Child0) of
true ->
- {Parent, LeftChild, RightChild} = split_child(Tx, Tree, Node0, Child0),
+ {Parent, LeftChild, RightChild} = split_child(TxDb, Tree, Node0, Child0),
ChildId = find_child_id(Tree, Parent, Key),
Child = if
ChildId =:= LeftChild#node.id ->
@@ -551,7 +552,7 @@ insert_nonfull(Tx, #tree{} = Tree, #node{} = Node0, Key, Value) ->
{Node0, Child0}
end,
ChildId1 = Child1#node.id,
- NewReduction = insert_nonfull(Tx, Tree, Child1, Key, Value),
+ NewReduction = insert_nonfull(TxDb, Tree, Child1, Key, Value),
{CurrentFirstKey, CurrentLastKey, ChildId1, _OldReduction} = lists:keyfind(ChildId1, 3, Node1#node.members),
[NewFirstKey, _] = sort(Tree, [Key, CurrentFirstKey]),
[_, NewLastKey] = sort(Tree, [Key, CurrentLastKey]),
@@ -559,7 +560,7 @@ insert_nonfull(Tx, #tree{} = Tree, #node{} = Node0, Key, Value) ->
members = lists:keyreplace(ChildId1, 3, Node1#node.members,
{NewFirstKey, NewLastKey, ChildId1, NewReduction})
},
- set_node(Tx, Tree, Node2),
+ set_node(TxDb, Tree, Node2),
reduce_node(Tree, Node2).
@@ -570,45 +571,45 @@ insert_nonfull(Tx, #tree{} = Tree, #node{} = Node0, Key, Value) ->
%% @returns the tree.
-spec delete(Db :: term(), Tree :: #tree{}, Key :: term()) -> #tree{}.
delete(Db, #tree{} = Tree, Key) ->
- erlfdb:transactional(Db, fun(Tx) ->
- Root0 = get_node(Tx, Tree, ?NODE_ROOT_ID),
- case delete(Tx, Tree, Root0, Key) of
+ fabric2_fdb:transactional(Db, fun(TxDb) ->
+ Root0 = get_node(TxDb, Tree, ?NODE_ROOT_ID),
+ case delete(TxDb, Tree, Root0, Key) of
% if only one child, make it the new root.
#node{level = L, members = [_]} = Root1 when L > 0 ->
[{_, _, ChildId, _}] = Root1#node.members,
- Root2 = get_node(Tx, Tree, ChildId),
- clear_node(Tx, Tree, Root2),
- set_node(Tx, Tree, Root2#node{id = ?NODE_ROOT_ID});
+ Root2 = get_node(TxDb, Tree, ChildId),
+ clear_node(TxDb, Tree, Root2),
+ set_node(TxDb, Tree, Root2#node{id = ?NODE_ROOT_ID});
Root1 ->
- set_node(Tx, Tree, Root1)
+ set_node(TxDb, Tree, Root1)
end
end),
Tree.
-delete(_Tx, #tree{} = _Tree, #node{level = 0} = Node, Key) ->
+delete(_TxDb, #tree{} = _Tree, #node{level = 0} = Node, Key) ->
Node#node{
members = lists:keydelete(Key, 1, Node#node.members)
};
-delete(Tx, #tree{} = Tree, #node{} = Parent0, Key) ->
+delete(TxDb, #tree{} = Tree, #node{} = Parent0, Key) ->
ChildId0 = find_child_id(Tree, Parent0, Key),
- Child0 = get_node(Tx, Tree, ChildId0),
- Child1 = delete(Tx, Tree, Child0, Key),
+ Child0 = get_node(TxDb, Tree, ChildId0),
+ Child1 = delete(TxDb, Tree, Child0, Key),
case ?underflow(Tree, Child1) of
true ->
SiblingId = find_sibling_id(Tree, Parent0, ChildId0, Key),
- Sibling = get_node(Tx, Tree, SiblingId),
+ Sibling = get_node(TxDb, Tree, SiblingId),
NewNodes = case ?at_min(Tree, Sibling) of
true ->
- Merged = merge(Tx, Tree, Child1, Sibling),
- update_prev_neighbour(Tx, Tree, Merged),
- update_next_neighbour(Tx, Tree, Merged),
+ Merged = merge(TxDb, Tree, Child1, Sibling),
+ update_prev_neighbour(TxDb, Tree, Merged),
+ update_next_neighbour(TxDb, Tree, Merged),
[Merged];
false ->
- {Left, Right} = rebalance(Tx, Tree, Child1, Sibling),
- update_prev_neighbour(Tx, Tree, Left),
- update_next_neighbour(Tx, Tree, Right),
+ {Left, Right} = rebalance(TxDb, Tree, Child1, Sibling),
+ update_prev_neighbour(TxDb, Tree, Left),
+ update_next_neighbour(TxDb, Tree, Right),
[Left, Right]
end,
@@ -625,11 +626,11 @@ delete(Tx, #tree{} = Tree, #node{} = Parent0, Key) ->
members = Members3
},
- clear_nodes(Tx, Tree, [Child0, Sibling]),
- set_nodes(Tx, Tree, NewNodes),
+ clear_nodes(TxDb, Tree, [Child0, Sibling]),
+ set_nodes(TxDb, Tree, NewNodes),
Parent1;
false ->
- set_node(Tx, Tree, Child1),
+ set_node(TxDb, Tree, Child1),
{_OldFirstKey, _OldLastKey, ChildId0, _OldReduction} = lists:keyfind(ChildId0, 3, Parent0#node.members),
Parent0#node{
members = lists:keyreplace(ChildId0, 3, Parent0#node.members,
@@ -638,11 +639,11 @@ delete(Tx, #tree{} = Tree, #node{} = Parent0, Key) ->
end.
-merge(Tx, #tree{} = Tree, #node{level = Level} = Node1, #node{level = Level} = Node2) ->
+merge(TxDb, #tree{} = Tree, #node{level = Level} = Node1, #node{level = Level} = Node2) ->
[Left, Right] = sort(Tree, [Node1, Node2]),
#node{
- id = new_node_id(Tx, Tree),
+ id = new_node_id(TxDb, Tree),
level = Level,
prev = Left#node.prev,
next = Right#node.next,
@@ -650,14 +651,14 @@ merge(Tx, #tree{} = Tree, #node{level = Level} = Node1, #node{level = Level} = N
}.
-rebalance(Tx, #tree{} = Tree, #node{level = Level} = Node1, #node{level = Level} = Node2) ->
+rebalance(TxDb, #tree{} = Tree, #node{level = Level} = Node1, #node{level = Level} = Node2) ->
[Left0, Right0] = sort(Tree, [Node1, Node2]),
Members = lists:append(Left0#node.members, Right0#node.members),
{LeftMembers, RightMembers} = lists:split(length(Members) div 2, Members),
- Left1Id = new_node_id(Tx, Tree),
- Right1Id = new_node_id(Tx, Tree),
+ Left1Id = new_node_id(TxDb, Tree),
+ Right1Id = new_node_id(TxDb, Tree),
Left1 = remove_pointers_if_not_leaf(Left0#node{
id = Left1Id,
@@ -701,12 +702,12 @@ find_child_int(#tree{} = Tree, [{_F, L, _P, _R} = Child| Rest], Key) ->
%% metadata functions
-get_meta(Tx, #tree{} = Tree, MetaKey) ->
- get_meta(Tx, Tree#tree.prefix, MetaKey);
+get_meta(TxDb, #tree{} = Tree, MetaKey) ->
+ get_meta(TxDb, Tree#tree.prefix, MetaKey);
-get_meta(Tx, Prefix, MetaKey) when is_binary(Prefix) ->
- Future = get_meta_future(Tx, Prefix, MetaKey),
+get_meta(TxDb, Prefix, MetaKey) when is_binary(Prefix) ->
+ Future = get_meta_future(TxDb, Prefix, MetaKey),
case erlfdb:wait(Future) of
not_found ->
not_found;
@@ -715,11 +716,13 @@ get_meta(Tx, Prefix, MetaKey) when is_binary(Prefix) ->
end.
-get_meta_future(Tx, Prefix, MetaKey) ->
+get_meta_future(TxDb, Prefix, MetaKey) ->
+ #{tx := Tx} = TxDb,
erlfdb:get(Tx, meta_key(Prefix, MetaKey)).
-set_meta(Tx, Prefix, MetaKey, MetaValue) ->
+set_meta(TxDb, Prefix, MetaKey, MetaValue) ->
+ #{tx := Tx} = TxDb,
erlfdb:set(
Tx,
meta_key(Prefix, MetaKey),
@@ -731,37 +734,40 @@ meta_key(Prefix, MetaKey) when is_binary(Prefix) ->
%% node persistence functions
-get_node(Tx, #tree{} = Tree, Id) ->
- get_node_wait(Id, get_node_future(Tx, Tree, Id)).
+get_node(TxDb, #tree{} = Tree, Id) ->
+ get_node_wait(Id, get_node_future(TxDb, Tree, Id)).
get_node_wait(Id, Future) ->
decode_node(Id, erlfdb:wait(Future)).
-get_node_future(Tx, #tree{} = Tree, Id) ->
+get_node_future(TxDb, #tree{} = Tree, Id) ->
+ #{tx := Tx} = TxDb,
Key = node_key(Tree#tree.prefix, Id),
erlfdb:get(Tx, Key).
-clear_nodes(Tx, #tree{} = Tree, Nodes) ->
+clear_nodes(TxDb, #tree{} = Tree, Nodes) ->
lists:foreach(fun(Node) ->
- clear_node(Tx, Tree, Node)
+ clear_node(TxDb, Tree, Node)
end, Nodes).
-clear_node(Tx, #tree{} = Tree, #node{} = Node) ->
- Key = node_key(Tree#tree.prefix, Node#node.id),
- erlfdb:clear(Tx, Key).
+clear_node(TxDb, #tree{} = Tree, #node{} = Node) ->
+ #{tx := Tx} = TxDb,
+ Key = node_key(Tree#tree.prefix, Node#node.id),
+ erlfdb:clear(Tx, Key).
-set_nodes(Tx, #tree{} = Tree, Nodes) ->
+set_nodes(TxDb, #tree{} = Tree, Nodes) ->
lists:foreach(fun(Node) ->
- set_node(Tx, Tree, Node)
+ set_node(TxDb, Tree, Node)
end, Nodes).
-set_node(Tx, #tree{} = Tree, #node{} = Node) ->
+set_node(TxDb, #tree{} = Tree, #node{} = Node) ->
+ #{tx := Tx} = TxDb,
validate_node(Tree, Node),
Key = node_key(Tree#tree.prefix, Node#node.id),
Value = encode_node(Node),
@@ -775,28 +781,28 @@ node_key(Prefix, Id) when is_binary(Prefix), is_integer(Id) ->
%% @doc Walks the whole tree and checks it for consistency.
%% It also prints it to screen.
validate_tree(Db, #tree{} = Tree) ->
- erlfdb:transactional(Db, fun(Tx) ->
+ fabric2_fdb:transactional(Db, fun(TxDb) ->
Root = get_node(Db, Tree, ?NODE_ROOT_ID),
- validate_tree(Tx, Tree, Root)
+ validate_tree(TxDb, Tree, Root)
end).
-validate_tree(_Tx, #tree{} = Tree, #node{level = 0} = Node) ->
+validate_tree(_TxDb, #tree{} = Tree, #node{level = 0} = Node) ->
print_node(Node),
validate_node(Tree, Node);
-validate_tree(Tx, #tree{} = Tree, #node{} = Node) ->
+validate_tree(TxDb, #tree{} = Tree, #node{} = Node) ->
print_node(Node),
validate_node(Tree, Node),
- validate_tree(Tx, Tree, Node#node.members);
+ validate_tree(TxDb, Tree, Node#node.members);
-validate_tree(_Tx, #tree{} = _Tree, []) ->
+validate_tree(_TxDb, #tree{} = _Tree, []) ->
ok;
-validate_tree(Tx, #tree{} = Tree, [{_F, _L, P, _R} | Rest]) ->
- Node = get_node(Tx, Tree, P),
- validate_tree(Tx, Tree, Node),
- validate_tree(Tx, Tree, Rest).
+validate_tree(TxDb, #tree{} = Tree, [{_F, _L, P, _R} | Rest]) ->
+ Node = get_node(TxDb, Tree, P),
+ validate_tree(TxDb, Tree, Node),
+ validate_tree(TxDb, Tree, Rest).
validate_node(#tree{} = Tree, #node{} = Node) ->
@@ -980,9 +986,9 @@ last_key(Members) when is_list(Members) ->
end.
-new_node_id(Tx, Tree) ->
- NextId = get_meta(Tx, Tree, ?META_NEXT_ID),
- set_meta(Tx, Tree#tree.prefix, ?META_NEXT_ID, NextId + 1),
+new_node_id(TxDb, Tree) ->
+ NextId = get_meta(TxDb, Tree, ?META_NEXT_ID),
+ set_meta(TxDb, Tree#tree.prefix, ?META_NEXT_ID, NextId + 1),
NextId.
@@ -1002,6 +1008,8 @@ print_node(#node{} = Node) ->
%% tests
-ifdef(TEST).
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
-include_lib("eunit/include/eunit.hrl").
reduce_sum(KVs, false) ->
@@ -1058,17 +1066,58 @@ collation_fun_test_() ->
].
-lookup_test() ->
- Db = erlfdb_util:get_test_db([empty]),
+ebtree_test_() ->
+ {
+ "Test ebtree functionality",
+ {
+ foreach,
+ fun setup/0,
+ fun cleanup/1,
+ [
+ fun test_lookup/1,
+ fun test_delete/1,
+ fun test_range_after_delete/1,
+ fun test_full_reduce/1,
+ fun test_full_reduce_after_delete/1,
+ fun test_count_reduce/1,
+ fun test_sum_reduce/1,
+ fun test_stats_reduce/1,
+ fun test_group_reduce_level/1,
+ fun test_group_reduce_int/1,
+ fun test_raw_collation/1,
+ fun test_custom_collation/1,
+ fun test_intense_lookup/1,
+ fun test_range/1,
+ fun test_reverse_range/1,
+ fun test_custom_collation_range/1,
+ fun test_custom_collation_reverse_range/1
+ ]
+ }
+ }.
+
+
+setup() ->
+ Ctx = test_util:start_couch([fabric]),
+ {ok, Db} = fabric2_db:create(?tempdb(), [{user_ctx, ?ADMIN_USER}]),
+ {Db, Ctx}.
+
+
+cleanup({Db, Ctx}) ->
+ ok = fabric2_db:delete(fabric2_db:name(Db), []),
+ test_util:stop_couch(Ctx).
+
+
+test_lookup({Db, _}) ->
+ ?debugFmt("lookup 1", []),
Tree = open(Db, <<1,2,3>>, 4),
+ ?debugFmt("lookup 2: ~p", [Tree]),
Keys = [X || {_, X} <- lists:sort([ {rand:uniform(), N} || N <- lists:seq(1, 100)])],
lists:foreach(fun(Key) -> insert(Db, Tree, Key, Key + 1) end, Keys),
lists:foreach(fun(Key) -> ?assertEqual({Key, Key + 1}, lookup(Db, Tree, Key)) end, Keys),
?assertEqual(false, lookup(Db, Tree, 101)).
-delete_test() ->
- Db = erlfdb_util:get_test_db([empty]),
+test_delete({Db, _}) ->
Tree = open(Db, <<1,2,3>>, 4),
Keys = [X || {_, X} <- lists:sort([ {rand:uniform(), N} || N <- lists:seq(1, 100)])],
lists:foreach(fun(Key) -> insert(Db, Tree, Key, Key + 1) end, Keys),
@@ -1077,8 +1126,7 @@ delete_test() ->
lists:foreach(fun(Key) -> ?assertEqual(false, lookup(Db, Tree, Key)) end, Keys).
-range_after_delete_test() ->
- Db = erlfdb_util:get_test_db([empty]),
+test_range_after_delete({Db, _}) ->
Tree = open(Db, <<1,2,3>>, 4),
Keys = [X || {_, X} <- lists:sort([ {rand:uniform(), N} || N <- lists:seq(1, 100)])],
lists:foreach(fun(Key) -> insert(Db, Tree, Key, Key + 1) end, Keys),
@@ -1088,8 +1136,7 @@ range_after_delete_test() ->
?assertEqual(50, reverse_range(Db, Tree, 1, 100, fun(E, A) -> length(E) + A end, 0)).
-full_reduce_test_() ->
- Db = erlfdb_util:get_test_db([empty]),
+test_full_reduce({Db, _}) ->
Tree = open(Db, <<1,2,3>>, 4, [{reduce_fun, fun reduce_sum/2}]),
TestFun = fun(Max) ->
Keys = [X || {_, X} <- lists:sort([ {rand:uniform(), N} || N <- lists:seq(1, Max)])],
@@ -1102,8 +1149,7 @@ full_reduce_test_() ->
].
-full_reduce_after_delete_test() ->
- Db = erlfdb_util:get_test_db([empty]),
+test_full_reduce_after_delete({Db, _}) ->
Tree = open(Db, <<1,2,3>>, 4, [{reduce_fun, fun reduce_sum/2}]),
Max = 100,
Keys = [X || {_, X} <- lists:sort([ {rand:uniform(), N} || N <- lists:seq(1, Max)])],
@@ -1113,8 +1159,7 @@ full_reduce_after_delete_test() ->
?assertEqual(0, full_reduce(Db, Tree)).
-count_reduce_test_() ->
- Db = erlfdb_util:get_test_db([empty]),
+test_count_reduce({Db, _}) ->
Tree = open(Db, <<1,2,3>>, 4, [{reduce_fun, fun reduce_count/2}]),
Max = 100,
Keys = [X || {_, X} <- lists:sort([ {rand:uniform(), N} || N <- lists:seq(1, Max)])],
@@ -1129,8 +1174,7 @@ count_reduce_test_() ->
?_test(?assertEqual(Expected(5, 7), reduce(Db, Tree, 5, 7)))
].
-sum_reduce_test_() ->
- Db = erlfdb_util:get_test_db([empty]),
+test_sum_reduce({Db, _}) ->
Tree = open(Db, <<1,2,3>>, 4, [{reduce_fun, fun reduce_sum/2}]),
Max = 100,
Keys = [X || {_, X} <- lists:sort([ {rand:uniform(), N} || N <- lists:seq(1, Max)])],
@@ -1146,8 +1190,7 @@ sum_reduce_test_() ->
].
-stats_reduce_test_() ->
- Db = erlfdb_util:get_test_db([empty]),
+test_stats_reduce({Db, _}) ->
Tree = open(Db, <<1,2,3>>, 4, [{reduce_fun, fun reduce_stats/2}]),
Max = 100,
Keys = [X || {_, X} <- lists:sort([ {rand:uniform(), N} || N <- lists:seq(1, Max)])],
@@ -1162,8 +1205,7 @@ stats_reduce_test_() ->
].
-group_reduce_level_test_() ->
- Db = erlfdb_util:get_test_db([empty]),
+test_group_reduce_level({Db, _}) ->
Tree = open(Db, <<1,2,3>>, 4, [{reduce_fun, fun reduce_sum/2}]),
Max = 100,
Keys = [X || {_, X} <- lists:sort([ {rand:uniform(), N} || N <- lists:seq(1, Max)])],
@@ -1186,8 +1228,7 @@ group_reduce_level_test_() ->
].
-group_reduce_int_test_() ->
- Db = erlfdb_util:get_test_db([empty]),
+test_group_reduce_int({Db, _}) ->
Tree = open(Db, <<1,2,3>>, 4, [{reduce_fun, fun reduce_count/2}]),
Max = 100,
Keys = [X || {_, X} <- lists:sort([ {rand:uniform(), N} || N <- lists:seq(1, Max)])],
@@ -1202,16 +1243,14 @@ group_reduce_int_test_() ->
].
-raw_collation_test() ->
- Db = erlfdb_util:get_test_db([empty]),
+test_raw_collation({Db, _}) ->
Tree = open(Db, <<1,2,3>>, 4),
insert(Db, Tree, null, null),
insert(Db, Tree, 1, 1),
?assertEqual([{1, 1}, {null, null}], range(Db, Tree, 1, null, fun(E, A) -> A ++ E end, [])).
-custom_collation_test() ->
- Db = erlfdb_util:get_test_db([empty]),
+test_custom_collation({Db, _}) ->
CollateFun = fun(A, B) -> B =< A end,
Tree = open(Db, <<1,2,3>>, 4, [{collate_fun, CollateFun}]),
insert(Db, Tree, 1, 1),
@@ -1219,16 +1258,15 @@ custom_collation_test() ->
?assertEqual([{2, 2}, {1, 1}], range(Db, Tree, 3, 0, fun(E, A) -> A ++ E end, [])).
-intense_lookup_test_() ->
+test_intense_lookup({Db, _}) ->
[
- {timeout, 1000, fun() -> lookup_test_fun(1000, 20) end},
- {timeout, 1000, fun() -> lookup_test_fun(1000, 50) end},
- {timeout, 1000, fun() -> lookup_test_fun(1000, 500) end}
+ {timeout, 1000, fun() -> lookup_test_fun(Db, 1000, 20) end},
+ {timeout, 1000, fun() -> lookup_test_fun(Db, 1000, 50) end},
+ {timeout, 1000, fun() -> lookup_test_fun(Db, 1000, 500) end}
].
-lookup_test_fun(Max, Order) ->
- Db = erlfdb_util:get_test_db([empty]),
+lookup_test_fun(Db, Max, Order) ->
Keys = [X || {_, X} <- lists:sort([ {rand:uniform(), N} || N <- lists:seq(1, Max, 2)])],
T0 = erlang:monotonic_time(),
Tree = lists:foldl(fun(Key, T) -> insert(Db, T, Key, Key + 1) end, open(Db, <<1,2,3>>, Order), Keys),
@@ -1239,9 +1277,8 @@ lookup_test_fun(Max, Order) ->
[Order, Max, 1000 * (Max / msec(T1 - T0)), 1000 * (Max / msec(T2 - T1))]).
-range_test_() ->
+test_range({Db, _}) ->
{timeout, 1000, fun() ->
- Db = erlfdb_util:get_test_db([empty]),
Max = 1000,
Keys = [X || {_, X} <- lists:sort([ {rand:uniform(), N} || N <- lists:seq(1, Max)])],
Tree = lists:foldl(fun(Key, T) -> insert(Db, T, Key, Key + 1) end, open(Db, <<1,2,3>>, 10), Keys),
@@ -1255,9 +1292,8 @@ range_test_() ->
end}.
-reverse_range_test_() ->
+test_reverse_range({Db, _}) ->
{timeout, 1000, fun() ->
- Db = erlfdb_util:get_test_db([empty]),
Max = 1000,
Keys = [X || {_, X} <- lists:sort([ {rand:uniform(), N} || N <- lists:seq(1, Max)])],
Tree = lists:foldl(fun(Key, T) -> insert(Db, T, Key, Key + 1) end, open(Db, <<1,2,3>>, 10), Keys),
@@ -1271,9 +1307,8 @@ reverse_range_test_() ->
end}.
-custom_collation_range_test_() ->
+test_custom_collation_range({Db, _}) ->
{timeout, 1000, fun() ->
- Db = erlfdb_util:get_test_db([empty]),
Max = 1000,
Keys = [X || {_, X} <- lists:sort([ {rand:uniform(), N} || N <- lists:seq(1, Max)])],
CollateFun = fun(A, B) -> B =< A end,
@@ -1295,9 +1330,8 @@ custom_collation_range_test_() ->
end}.
-custom_collation_reverse_range_test_() ->
+test_custom_collation_reverse_range({Db, _}) ->
{timeout, 1000, fun() ->
- Db = erlfdb_util:get_test_db([empty]),
Max = 1000,
Keys = [X || {_, X} <- lists:sort([ {rand:uniform(), N} || N <- lists:seq(1, Max)])],
CollateFun = fun(A, B) -> B =< A end,