A delete will now cause the proper collapse of cnodes into snodes up the tree to the root node.
This commit is contained in:
parent
e7ec1105eb
commit
c5fa370609
1 changed files with 32 additions and 21 deletions
53
src/hamt.erl
53
src/hamt.erl
|
@ -235,26 +235,43 @@ delete(Key, {hamt, Node}=T)
|
||||||
when is_binary(Key) ->
|
when is_binary(Key) ->
|
||||||
case delete_1(hash(Key), Key, Node, 0) of
|
case delete_1(hash(Key), Key, Node, 0) of
|
||||||
not_found -> T;
|
not_found -> T;
|
||||||
delete -> {hamt, nil};
|
{snode, Key, _} -> {hamt, nil};
|
||||||
N -> {hamt, N}
|
{snode, _, _}=N -> {hamt, N};
|
||||||
|
{cnode, _, _}=N -> {hamt, N}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
delete_1(H, Key, {cnode, Bitmap, Nodes}=CNode, L)
|
delete_1(H, Key, {cnode, Bitmap, Nodes}, L)
|
||||||
when is_integer(L), L =< 30 ->
|
when is_integer(L), L =< 30 ->
|
||||||
Bit = bitpos(H, L),
|
Bit = bitpos(H, L),
|
||||||
Idx = index(Bit, Bitmap),
|
Idx = index(Bit, Bitmap),
|
||||||
case exists(Bit, Bitmap) of
|
case exists(Bit, Bitmap) of
|
||||||
true ->
|
true ->
|
||||||
case delete_1(H, Key, ba_get(Idx, Nodes), L + 5) of
|
case delete_1(H, Key, ba_get(Idx, Nodes), L + 5) of
|
||||||
not_found -> not_found;
|
{cnode, _, _}=CN ->
|
||||||
delete -> delete_2(Key, Bit, CNode);
|
{cnode, Bitmap, ba_set(Idx, CN, Nodes)};
|
||||||
N -> {cnode, Bitmap, ba_set(Idx, N, Nodes)}
|
{snode, Key, _} ->
|
||||||
|
case length(Nodes) of
|
||||||
|
2 ->
|
||||||
|
[{snode, _, _}=SN] = ba_del(Key, Nodes),
|
||||||
|
SN;
|
||||||
|
false ->
|
||||||
|
{cnode, (Bitmap bxor Bit), ba_del(Key, Nodes)}
|
||||||
|
end;
|
||||||
|
{snode, _, _}=SN ->
|
||||||
|
case length(Nodes) > 1 of
|
||||||
|
true ->
|
||||||
|
{cnode, Bitmap, ba_set(Idx, SN, Nodes)};
|
||||||
|
false ->
|
||||||
|
SN
|
||||||
|
end;
|
||||||
|
not_found ->
|
||||||
|
not_found
|
||||||
end;
|
end;
|
||||||
false ->
|
false ->
|
||||||
not_found
|
not_found
|
||||||
end;
|
end;
|
||||||
delete_1(_H, Key, {snode, Key, _}, _L) ->
|
delete_1(_H, Key, {snode, Key, _}=SN, _L) ->
|
||||||
delete;
|
SN;
|
||||||
delete_1(_H, _Key, {snode, _, _}, _L) ->
|
delete_1(_H, _Key, {snode, _, _}, _L) ->
|
||||||
not_found;
|
not_found;
|
||||||
delete_1(_H, Key, {lnode, List}, _L) ->
|
delete_1(_H, Key, {lnode, List}, _L) ->
|
||||||
|
@ -267,16 +284,6 @@ delete_1(_H, Key, {lnode, List}, _L) ->
|
||||||
{snode, Key, lists:keyfind(Key, 2, List)}
|
{snode, Key, lists:keyfind(Key, 2, List)}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
%% @doc This CNode only has 2 elements in it and one is about to be
|
|
||||||
%% be deleted, time to collapse this CNode into an SNode.
|
|
||||||
delete_2(Key, _Bit, {cnode, _Bitmap, Nodes})
|
|
||||||
when length(Nodes) =:= 2 ->
|
|
||||||
[{snode, _, _}=SN] = ba_del(Key, Nodes),
|
|
||||||
SN;
|
|
||||||
%% @doc Remove the right key and update the bitmap
|
|
||||||
delete_2(Key, Bit, {cnode, Bitmap, Nodes}) ->
|
|
||||||
{cnode, (Bitmap bxor Bit), ba_del(Key, Nodes)}.
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
-spec map(Function, Hamt1) -> Hamt2 when
|
-spec map(Function, Hamt1) -> Hamt2 when
|
||||||
|
@ -409,9 +416,13 @@ del_one_of_many_keys_test() ->
|
||||||
{hamt,{snode,<<"k2">>,<<"v2">>}}).
|
{hamt,{snode,<<"k2">>,<<"v2">>}}).
|
||||||
|
|
||||||
del_causes_cascading_cnode_collapse_test() ->
|
del_causes_cascading_cnode_collapse_test() ->
|
||||||
H = hamt:put([{<<X>>, <<X>>} || X <- lists:seq(1,5)], hamt:new()),
|
?assertEqual(hamt:delete(<<5>>, hamt:put([{<<X>>, <<X>>} || X <- lists:seq(1,6)], hamt:new())),
|
||||||
?assertEqual(hamt:delete(<<5>>, H),
|
{hamt,{cnode,17629440,
|
||||||
hamt:put([{<<X>>, <<X>>} || X <- lists:seq(1,4)], hamt:new())).
|
[{snode,<<3>>,<<3>>},
|
||||||
|
{snode,<<6>>,<<6>>},
|
||||||
|
{snode,<<1>>,<<1>>},
|
||||||
|
{snode,<<2>>,<<2>>},
|
||||||
|
{snode,<<4>>,<<4>>}]}}).
|
||||||
|
|
||||||
put_lots_test() ->
|
put_lots_test() ->
|
||||||
KVPs = [{<<X>>, <<X>>} || X <- lists:seq(1,10000)],
|
KVPs = [{<<X>>, <<X>>} || X <- lists:seq(1,10000)],
|
||||||
|
|
Loading…
Reference in a new issue