dets_utils.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,580 行 · 第 1/4 页

ERL
1,580
字号
    none;find_next_free(_Ftab, _Addr, _Pos, _MaxBud, Next, PosN, _Base) ->    {Next, PosN}.collect_all_interval(Ftab, Addr, MaxAddr, Base) ->    MaxBud = size(Ftab),    collect_all_interval(Ftab, Addr, MaxAddr, 1, MaxBud, Base, []).collect_all_interval(Ftab, L0, U, Pos, MaxBud, Base, Acc0) when Pos =< MaxBud ->    PosTab = element(Pos, Ftab),    L = adjust_addr(L0, Pos, Base),    Acc = collect_interval(PosTab, Pos, L, U, Acc0),    collect_all_interval(Ftab, L0, U, Pos+1, MaxBud, Base, Acc);collect_all_interval(_Ftab, _L, _U, _Pos, _MaxBud, _Base, Acc) ->    lists:sort(Acc).%% It could be that Addr is inside a free area. This function adjusts%% the address so that is placed on a boundary in the Pos tree. Inlined.adjust_addr(Addr, Pos, Base) ->    Pow = ?POW(Pos - 1),    Rem = (Addr - Base) rem Pow,    if        Rem =:= 0 ->            Addr;        Addr < Pow ->            Addr;        true ->            Addr - Rem    end.%%%-----------------------------------------------------------------%%% These functions implements a B+ tree.%%% The code is originally written by lelle@erlang.ericsson.se,%%%------------------------------------------------------------------define(max_size, 16).-define(min_size, 8).%%-----------------------------------------------------------------%% Finds out the type of the node: 'l' or 'n'.%%------------------------------------------------------------------define(NODE_TYPE(Tree), element(1, Tree)).%% Finds out if a node/leaf is full or not.-define(FULL(Tree), (bplus_get_size(Tree) >= ?max_size)).%% Finds out if a node/leaf is filled up over its limit.-define(OVER_FULL(Tree), (bplus_get_size(Tree) > ?max_size)).%% Finds out if a node/leaf has less items than allowed.-define(UNDER_FILLED(Tree), (bplus_get_size(Tree) < ?min_size)).%% Finds out if a node/leaf has as few items as minimum allowed.-define(LOW_FILLED(Tree), (bplus_get_size(Tree) =< ?min_size)).%%Returns a key in a leaf at position Pos.-define(GET_LEAF_KEY(Leaf, Pos), element(Pos+1, Leaf)).%% Special for dets.collect_tree(v, _TI, Acc) -> Acc;collect_tree(T, TI, Acc) ->    Pow = ?POW(TI-1),    collect_tree2(T, Pow, Acc).collect_tree2(Tree, Pow, Acc) ->    S = bplus_get_size(Tree),    case ?NODE_TYPE(Tree) of	l ->	    collect_leaf(Tree, S, Pow, Acc);	n ->	    collect_node(Tree, S, Pow, Acc)    end.    collect_leaf(_Leaf, 0, _Pow, Acc) ->    Acc;collect_leaf(Leaf, I, Pow, Acc) ->    Key = ?GET_LEAF_KEY(Leaf, I),    V = {Key, Key+Pow},    collect_leaf(Leaf, I-1, Pow, [V | Acc]).collect_node(_Node, 0, _Pow, Acc) ->    Acc;collect_node(Node, I, Pow, Acc) ->    Acc1 = collect_tree2(bplus_get_tree(Node, I), Pow, Acc),    collect_node(Node, I-1, Pow, Acc1).%% Special for dets.tree_to_bin(v, _F, _Max, Ws, WsSz) -> {Ws, WsSz};tree_to_bin(T, F, Max, Ws, WsSz) ->    {N, L1, Ws1, WsSz1} = tree_to_bin2(T, F, Max, 0, [], Ws, WsSz),    {N1, L2, Ws2, WsSz2} = F(N, lists:reverse(L1), Ws1, WsSz1),    {0, [], NWs, NWsSz} = F(N1, L2, Ws2, WsSz2),    {NWs, NWsSz}.tree_to_bin2(Tree, F, Max, N, Acc, Ws, WsSz) when N >= Max ->    {NN, NAcc, NWs, NWsSz} = F(N, lists:reverse(Acc), Ws, WsSz),    tree_to_bin2(Tree, F, Max, NN, lists:reverse(NAcc), NWs, NWsSz);tree_to_bin2(Tree, F, Max, N, Acc, Ws, WsSz) ->    S = bplus_get_size(Tree),    case ?NODE_TYPE(Tree) of	l ->	    {N+S, leaf_to_bin(bplus_leaf_to_list(Tree), Acc), Ws, WsSz};	n ->	    node_to_bin(Tree, F, Max, N, Acc, 1, S, Ws, WsSz)    end.    node_to_bin(_Node, _F, _Max, N, Acc, I, S, Ws, WsSz) when I > S ->    {N, Acc, Ws, WsSz};node_to_bin(Node, F, Max, N, Acc, I, S, Ws, WsSz) ->    {N1,Acc1,Ws1,WsSz1} = 	tree_to_bin2(bplus_get_tree(Node, I), F, Max, N, Acc, Ws, WsSz),    node_to_bin(Node, F, Max, N1, Acc1, I+1, S, Ws1, WsSz1).leaf_to_bin([N | L], Acc) ->    leaf_to_bin(L, [<<N:32>> | Acc]);leaf_to_bin([], Acc) ->    Acc.%% Special for dets. list_to_tree(L) ->    leafs_to_nodes(L, length(L), fun bplus_mk_leaf/1, []).leafs_to_nodes([], 0, _F, [T]) ->    T;leafs_to_nodes([], 0, _F, L) ->    leafs_to_nodes(lists:reverse(L), length(L), fun mk_node/1, []);leafs_to_nodes(Ls, Sz, F, L) ->    I = if 	    Sz =< 16 -> Sz;	    Sz =< 32 -> Sz div 2;	    true -> 12	end,    {L1, R} = split_list(Ls, I, []),    N = F(L1),    Sz1 = Sz - I,     leafs_to_nodes(R, Sz1, F, [N | L]).mk_node([E | Es]) ->    NL = [E | lists:foldr(fun(X, A) -> [get_first_key(X), X | A] end, [], Es)],    bplus_mk_node(NL).    split_list(L, 0, SL) ->    {SL, L};split_list([E | Es], I, SL) ->    split_list(Es, I-1, [E | SL]).get_first_key(T) ->    case ?NODE_TYPE(T) of	l ->	    ?GET_LEAF_KEY(T, 1);	n ->	    get_first_key(bplus_get_tree(T, 1))    end.%% Special for dets.collect_interval(v, _TI, _L, _U, Acc) -> Acc;collect_interval(T, TI, L, U, Acc) ->    Pow = ?POW(TI-1),    collect_interval2(T, Pow, L, U, Acc).collect_interval2(Tree, Pow, L, U, Acc) ->    S = bplus_get_size(Tree),    case ?NODE_TYPE(Tree) of	l ->	    collect_leaf_interval(Tree, S, Pow, L, U, Acc);	n ->            {Max, _} = bplus_select_sub_tree(Tree, U),            {Min, _} = bplus_select_sub_tree_2(Tree, L, Max),	    collect_node_interval(Tree, Min, Max, Pow, L, U, Acc)    end.    collect_leaf_interval(_Leaf, 0, _Pow, _L, _U, Acc) ->    Acc;collect_leaf_interval(Leaf, I, Pow, L, U, Acc) ->    Key = ?GET_LEAF_KEY(Leaf, I),    if        Key < L ->             Acc;        Key > U ->             collect_leaf_interval(Leaf, I-1, Pow, L, U, Acc);        true ->             collect_leaf_interval(Leaf, I-1, Pow, L, U, [{Key,Key+Pow} | Acc])    end.collect_node_interval(_Node, I, UP, _Pow, _L, _U, Acc) when I > UP ->    Acc;collect_node_interval(Node, I, UP, Pow, L, U, Acc) ->    Acc1 = collect_interval2(bplus_get_tree(Node, I), Pow, L, U, Acc),    collect_node_interval(Node, I+1, UP, Pow, L, U, Acc1).%%-----------------------------------------------------------------%% Func: empty_tree/0%% Purpose: Creates a new empty tree.%% Returns: tree()%%-----------------------------------------------------------------bplus_empty_tree() -> v.%%-----------------------------------------------------------------%% Func: lookup/2%% Purpose: Looks for Key in the Tree.%% Returns: {ok, {Key, Val}} | 'undefined'.%%-----------------------------------------------------------------bplus_lookup(v, _Key) -> undefined;bplus_lookup(Tree, Key) ->    case ?NODE_TYPE(Tree) of	l ->	    bplus_lookup_leaf(Key, Tree);	n ->	    {_, SubTree} = bplus_select_sub_tree(Tree, Key),	    bplus_lookup(SubTree, Key)    end.%%-----------------------------------------------------------------%% Searches through a leaf until the Key is ok or%% when it is determined that it does not exist.%%-----------------------------------------------------------------bplus_lookup_leaf(Key, Leaf) ->     bplus_lookup_leaf_2(Key, Leaf, bplus_get_size(Leaf)).bplus_lookup_leaf_2(_, _, 0) -> undefined;bplus_lookup_leaf_2(Key, Leaf, N) ->    case ?GET_LEAF_KEY(Leaf, N) of	Key -> {ok, Key};	_ ->	    bplus_lookup_leaf_2(Key, Leaf, N-1)    end.%%-----------------------------------------------------------------%% Func: lookup_first/1%% Purpose: Finds the smallest key in the entire Tree.%% Returns: {ok, {Key, Val}} | 'undefined'.%%-----------------------------------------------------------------bplus_lookup_first(v) -> undefined;bplus_lookup_first(Tree) ->    case ?NODE_TYPE(Tree) of	l ->	    % Then it is the leftmost key here.	    {ok, ?GET_LEAF_KEY(Tree, 1)};         	n ->	    % Look in the leftmost subtree.	    bplus_lookup_first(bplus_get_tree(Tree, 1))    end.%%-----------------------------------------------------------------%% Func: lookup_next/2%% Purpose: Finds the next key nearest after Key.%% Returns: {ok, {Key, Val}} | 'undefined'. NIX!!!%%-----------------------------------------------------------------bplus_lookup_next(v, _) -> undefined;bplus_lookup_next(Tree, Key) ->    case ?NODE_TYPE(Tree) of	l ->	    lookup_next_leaf(Key, Tree);	n ->	    {Pos, SubTree} = bplus_select_sub_tree(Tree, Key),	    case bplus_lookup_next(SubTree, Key) of		undefined ->		    S = bplus_get_size(Tree),		    if			% There is a right brother.			S > Pos ->                  			    bplus_lookup_first(bplus_get_tree(Tree, Pos+1));			% No there is no right brother.			true ->			    undefined		    end;		% We ok a next item.		Result ->                         		    Result	    end    end.%%-----------------------------------------------------------------%% Returns {ok, NextKey} if there is a key in the leaf which is greater.%% If there is no such key we return 'undefined' instead.%% Key does not have to be a key in the structure, just a search value.%%-----------------------------------------------------------------lookup_next_leaf(Key, Leaf) ->     lookup_next_leaf_2(Key, Leaf, bplus_get_size(Leaf), 1).lookup_next_leaf_2(Key, Leaf, Size, Size) ->     % This is the rightmost key.    K = ?GET_LEAF_KEY(Leaf, Size),    if	K > Key ->	    {ok, ?GET_LEAF_KEY(Leaf, Size)};	true ->	    undefined    end;lookup_next_leaf_2(Key, Leaf, Size, N) ->    K = ?GET_LEAF_KEY(Leaf, N),    if	K < Key ->                         	    % K is still smaller, try next in the leaf.	    lookup_next_leaf_2(Key, Leaf, Size, N+1);	Key == K ->	    % Since this is exact Key it must be the next.	    {ok, ?GET_LEAF_KEY(Leaf, N+1)};        true ->            % Key was not an exact specification.	    % It must be K that is next greater.	    {ok, ?GET_LEAF_KEY(Leaf, N)}    end.%%-----------------------------------------------------------------%% Func: insert/3%% Purpose: Inserts a new {Key, Value} into the tree.%% Returns: tree()%%-----------------------------------------------------------------bplus_insert(v, Key) -> bplus_mk_leaf([Key]);bplus_insert(Tree, Key) ->    NewTree = bplus_insert_in(Tree, Key),    case ?OVER_FULL(NewTree) of	false ->	    NewTree;	% If the node is over-full the tree will grow.	true ->	    {LTree, DKey, RTree} = 		case ?NODE_TYPE(NewTree) of		    l ->			bplus_split_leaf(NewTree);		    n ->			bplus_split_node(NewTree)		end,	    bplus_mk_node([LTree, DKey, RTree])    end.%%-----------------------------------------------------------------%% Func: delete/2%% Purpose: Deletes a key from the tree (if present).%% Returns: tree()%%-----------------------------------------------------------------bplus_delete(v, _Key) -> v;bplus_delete(Tree, Key) ->    NewTree = bplus_delete_in(Tree, Key),    S = bplus_get_size(NewTree),    case ?NODE_TYPE(NewTree) of	l ->	    if		S =:= 0 ->		    v;		true ->		    NewTree	    end;	n ->	    if		S =:= 1 ->		    bplus_get_tree(NewTree, 1);		true ->		    NewTree	    end    end.%%% -----------------------%%% Help function to insert.%%% -----------------------bplus_insert_in(Tree, Key) ->    case ?NODE_TYPE(Tree) of	l ->	    bplus_insert_in_leaf(Tree, Key);	n ->	    {Pos, SubTree} = bplus_select_sub_tree(Tree, Key),              % Pos = "the position of the subtree".	    NewSubTree = bplus_insert_in(SubTree, Key),	    case ?OVER_FULL(NewSubTree) of		false ->		    bplus_put_subtree(Tree, [NewSubTree, Pos]);		true ->		    case bplus_reorganize_tree_ins(Tree, NewSubTree, Pos) of			{left, {LeftT, DKey, MiddleT}} ->			    bplus_put_subtree(bplus_put_lkey(Tree, DKey, Pos),					[LeftT, Pos-1, MiddleT, Pos]);			{right, {MiddleT, DKey, RightT}} ->			    bplus_put_subtree(bplus_put_rkey(Tree, DKey, Pos),					[MiddleT, Pos, RightT, Pos+1]);			{split, {LeftT, DKey, RightT}} ->			    bplus_extend_tree(Tree, {LeftT, DKey, RightT}, Pos)		    end	    end    end.%%-----------------------------------------------------------------%% Inserts a key in correct position in a leaf.%%-----------------------------------------------------------------bplus_insert_in_leaf(Leaf, Key) ->    bplus_insert_in_leaf_2(Leaf, Key, bplus_get_size(Leaf), []).bplus_insert_in_leaf_2(Leaf, Key, 0, Accum) ->    bplus_insert_in_leaf_3(Leaf, 0, [Key|Accum]);bplus_insert_in_leaf_2(Leaf, Key, N, Accum) ->    K = ?GET_LEAF_KEY(Leaf, N),    if	Key < K ->	    % Not here!	    bplus_insert_in_leaf_2(Leaf, Key, N-1, [K|Accum]);	K < Key ->	    % Insert here.	    bplus_insert_in_leaf_3(Leaf, N-1, [K, Key|Accum]);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?