tv_db.erl

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

ERL
1,268
字号
	end,        case Result of	false ->	    gs:window(dbwin, gs:start(), [beep]),	    case get(error_msg_mode) of		normal ->		    tv_utils:notify(dbwin, "TV Notification", 				    ["Couldn't update table!"]);		haiku ->		    tv_utils:notify(dbwin, "TV Notification", 				    ["Three things are certain:",				     "Death, taxes, and lost updates.",				     "Guess which has occurred."])	    end,	    gs:destroy(dbwin),	    {false, ProcVars};	true ->	    Key = element(KeyNo, Obj),	    NewDbList = insert_new_object(EtsType, Key, KeyNo, Obj, DbList, Sorting, 					  RevSorting, SortKeyNo),	    NewMaxSize = ?COMM_FUNC_FILE:max(MaxElemSize, max_size([Obj])),	    NewDbData = DbData#db_data{db            = NewDbList,				       db_size       = length(NewDbList),				       max_elem_size = NewMaxSize				      },	    {true, ProcVars#process_variables{db_data = NewDbData}}    end.insert_new_object(EtsType,Key,KeyNo,Obj,DbList,Sorting,RevSorting,SortKeyNo) ->       %% Remove elements from the list that ought not to be there,       %% according to the table type!    Fun = 	case basetype(EtsType) of	    set ->		fun({Data,Color}, {Replaced,AccDb}) when element(KeyNo,Data) =/= Key ->			{Replaced, [{Data,Color} | AccDb]};		   ({Data,Color}, {Replaced,AccDb}) when not Replaced, 							 Color =/= ?BLACK,							 Data =/= Obj->			{true, [{Obj,?GREEN1} | AccDb]};		   ({_Data,Color}, {Replaced,AccDb}) when not Replaced, 							 Color =/= ?BLACK ->			{true, [{Obj,Color} | AccDb]};		   ({_Data,Color}, {Replaced,AccDb}) when not Replaced, 							 Color =:= ?BLACK ->			{true, [{Obj, ?RED1} | AccDb]};		   ({_Data,Color}, {Replaced,AccDb}) when Replaced, 							 Color =:= ?BLACK ->			{false, AccDb};		   ({_Data,_Color}, {Replaced,AccDb}) ->			{Replaced, AccDb}		end;	    bag ->		fun({Data,Color}, {Replaced,AccDb}) when Data =/= Obj ->			{Replaced, [{Data,Color} | AccDb]};		   ({_Data,Color}, {Replaced,AccDb}) when not Replaced, 							 Color =/= ?BLACK ->			{true, [{Obj,Color} | AccDb]};		   ({_Data,Color}, {Replaced,AccDb}) when Replaced, 							 Color =/= ?BLACK ->			{true, AccDb};		   ({_Data,Color}, {Replaced,AccDb}) when Replaced, 							 Color =:= ?BLACK ->			{true, AccDb};		   ({_Data,Color}, {Replaced,AccDb}) when not Replaced, 							 Color =:= ?BLACK ->			{true, [{Obj, ?RED1} | AccDb]};		   ({_Data,_Color}, {Replaced,AccDb}) ->			{Replaced, AccDb}		end;	    duplicate_bag ->		   %% The fun is never called if the type is duplicate_bag,		   %% because all we have to do with new elements is to insert 		   %% them (multiple identical objects allowed). 		not_used	end,        FilterFun = fun(Acc0, L) ->			lists:foldl(Fun, Acc0, L)		end,        {_Replaced, TmpDbList} = 	case EtsType of	    duplicate_bag ->		{false, DbList};	    _OtherType ->		{R,L} = FilterFun({false,[]}, DbList),		{R, lists:reverse(L)}	end,    case Sorting of	false ->	    TmpDbList ++ [{Obj,?RED1}];	true ->	       %% The original list is already sorted!	       %% Just merge the two lists together!	    tv_db_sort:merge(SortKeyNo, TmpDbList, [{Obj,?RED1}], RevSorting)    end.    max_size([]) ->        0;max_size(L) ->    max_size(L, 0).max_size([], CurrMax) ->    CurrMax;max_size([H | T], CurrMax) when is_tuple(H) ->    Size = size(H),    if	Size >= CurrMax ->	    max_size(T, Size);	true ->	    max_size(T, CurrMax)    end;max_size([_H | T], CurrMax) ->    Size = 1,    if	Size >= CurrMax ->	    max_size(T, Size);	true ->	    max_size(T, CurrMax)    end.add_elements(_KeyNo, Inserted, List, false, _RevSorting, _SortKeyNo) ->       % Remember that the order of the original list has to be preserved!    List ++ list2dblist(Inserted, ?RED1);add_elements(_KeyNo, Inserted, List, _Sorting, RevSorting, SortKeyNo) ->       % The original list is already sorted - sort the new elements, and       % just merge the two lists together!    SortedInsertedList = tv_db_sort:mergesort(SortKeyNo, 					       list2dblist(Inserted, ?RED1), 					       RevSorting),    tv_db_sort:merge(SortKeyNo, List, SortedInsertedList, RevSorting).       %% We assume the list already has been sorted, i.e., since the order won't    %% be changed by marking an element deleted, we DON'T have to sort the list   %% once again!mark_deleted(_KeyNo, [], List) ->    List;mark_deleted(KeyNo, [Data | T], List) ->    KeyValue = tv_db_sort:get_compare_value(KeyNo, Data),    NewList  = mark_one_element_deleted(KeyNo, KeyValue, Data, List, []),    mark_deleted(KeyNo, T, NewList).    mark_one_element_deleted(_KeyNo, _KeyValue, _Data, [], Acc) ->    Acc;mark_one_element_deleted(KeyNo, {tuple, KeyValue}, 			 Data, [{DataTuple, Color} | Tail], Acc) ->    OldKeyValue = tv_db_sort:get_compare_value(KeyNo, DataTuple),       % Remember that the order of the original list has to be preserved!    if	OldKeyValue =:= {tuple, KeyValue} ->	    Acc ++ [{Data, ?BLACK}] ++ Tail;	true ->	    mark_one_element_deleted(KeyNo, {tuple, KeyValue}, Data, Tail, 				     Acc ++ [{DataTuple, Color}])    end;mark_one_element_deleted(KeyNo, _KeyValue, Data, [{DataTuple, Color} | Tail], Acc) ->    if	Data =:= DataTuple ->	    Acc ++ [{Data, ?BLACK}] ++ Tail;	true ->	    mark_one_element_deleted(KeyNo, _KeyValue, Data, Tail, 				     Acc ++ [{DataTuple, Color}])    end.           %% We assume the list already has been sorted, i.e., since the order won't    %% be changed by marking an element updated, we DON'T have to sort the list   %% once again!replace_elements(_KeyNo, [], List) ->    List;replace_elements(KeyNo, [Data | T], List) ->    KeyValue = tv_db_sort:get_compare_value(KeyNo, Data),    NewList  = replace_one_element(KeyNo, KeyValue, Data, List, []),    replace_elements(KeyNo, T, NewList).        replace_one_element(_KeyNo, _Key, _Data, [], Acc) ->    Acc;replace_one_element(KeyNo, {tuple, Key1}, Data, [{DataTuple, Color} | Tail], Acc) ->    Key2 = tv_db_sort:get_compare_value(KeyNo, DataTuple),    % Remember that the order of the original list has to be preserved!    if	Key2 =:= {tuple, Key1} ->	    Acc ++ [{Data, ?GREEN1}] ++ Tail;	true ->	    replace_one_element(KeyNo, {tuple, Key1}, Data, Tail, 				Acc ++ [{DataTuple, Color}])    end;replace_one_element(_KeyNo, _KeyValue, _Data, [{DataTuple, Color} | Tail], Acc) ->       % Can't replace an element with no key!    Acc ++ [{DataTuple, Color} | Tail].    group_difflists(bag, _KeyNo, Inserted, Deleted) ->	            %% Since the ETS table is of bag type, no element can be updated, i.e.,       %% it can only be deleted and re-inserted, otherwise a new element will be added.    {Inserted, Deleted, []};group_difflists(duplicate_bag, _KeyNo, Inserted, Deleted) ->	            %% Since the ETS table is of duplicate_bag type, no element can be updated, i.e.,       %% it can only be deleted and re-inserted, otherwise a new element will be added.    {Inserted, Deleted, []};group_difflists(set, _KeyNo, [], Deleted) ->       %% Updated elements have to be present in both lists, i.e., if one list is empty,       %% the other contains no updated elements - they are either inserted or deleted!    {[], Deleted, []};group_difflists(set, _KeyNo, Inserted, []) ->    {Inserted, [], []};group_difflists(set, KeyNo, InsOrUpd, DelOrUpd) ->    match_difflists(KeyNo, InsOrUpd, DelOrUpd, [], []).    match_difflists(_KeyNo, [], Deleted, Inserted, Updated) ->    {Inserted, Deleted, Updated};match_difflists(KeyNo, [Data | T], DelOrUpd, InsAcc, UpdAcc) ->    % This function is only called in case of a 'set' ETS table.    % 'Set' type of ETS table means there are unique keys. If two elements in     % InsOrUpd and DelOrUpd have the same key, that element has been updated,     % and is added to the Updated list, and removed from the original two lists.    % After the two lists have been traversed in this way, the remaining elements    % in DelOrUpd forms the new Deleted list (analogous for InsOrUpd).    % If we want to improve the performance, we could check which list is the     % shortest, since the traversing time depends on this.     Key = element(KeyNo, Data),    case searchdelete(Key, KeyNo, DelOrUpd) of	{true, NewDelOrUpd} ->	    match_difflists(KeyNo, T, NewDelOrUpd, InsAcc, [Data | UpdAcc]);	{false, SameDelOrUpd} ->	    match_difflists(KeyNo, T, SameDelOrUpd, [Data | InsAcc], UpdAcc)    end.searchdelete(_Key, _ElemNo, []) ->    {false, []};searchdelete(Key, ElemNo, List) ->    searchdelete(Key, ElemNo, List, []).searchdelete(_Key, _ElemNo, [], Acc) ->    {false, Acc};searchdelete(Key, ElemNo, [Tuple | Tail], Acc) ->    % We don't use standard libraries, 'cause we want to make an 'atomic'    % operation, i.e., we will not search the list two times...    case (element(ElemNo, Tuple) =:= Key) of	true ->	    {true, Acc ++ Tail};   % Return the list without the matching element	_Other ->	    searchdelete(Key, ElemNo, Tail, [Tuple | Acc])    end.	    dblist2list([]) ->    [];dblist2list([{Data, _Color} | T]) ->    [Data | dblist2list(T)].            list2dblist([], _Color) ->        [];list2dblist([Data | T], Color) ->    [{Data, Color} | list2dblist(T, Color)].update_colors([]) ->    [];update_colors([{Data, Color} | T]) ->    [{Data, new_color(Color)} | update_colors(T)].    new_color(?GREEN1) ->    ?GREEN2;new_color(?GREEN2) ->    ?GREEN3;new_color(?GREEN3) ->    ?GREEN4;new_color(?GREEN4) ->    ?GREEN5;new_color(?GREEN5) ->    ?DEFAULT_BTN_COLOR;new_color(?RED1) ->    ?RED2;new_color(?RED2) ->    ?RED3;new_color(?RED3) ->    ?RED4;new_color(?RED4) ->    ?RED5;new_color(?RED5) ->    ?DEFAULT_BTN_COLOR;new_color(_Other) ->    ?DEFAULT_BTN_COLOR.                  % Default shall be gray.compute_elapsed_seconds({H1, M1, S1}, {H2, M2, S2}) ->    ElapsedHours   = get_time_diff(hours, H1, H2),    ElapsedMinutes = get_time_diff(minutes, M1, M2),    ElapsedSeconds = get_time_diff(seconds, S1, S2),    (ElapsedHours * 3600) + (ElapsedMinutes * 60) + ElapsedSeconds + 1.get_time_diff(_Type, T1, T2) when T1 =< T2 ->    T2 - T1;get_time_diff(hours, T1, T2) ->    T2 + 24 - T1;get_time_diff(minutes, T1, T2) ->    T2 + 60 - T1;get_time_diff(seconds, T1, T2) ->    T2 + 60 - T1.split(_N, []) ->    {[], []};split(0, List) ->    {[], List};split(N, List) ->    split2(0, N - 1, [], List).split2(Ctr, N, Acc, [H | T]) when Ctr < N ->    split2(Ctr + 1, N, [H | Acc], T);split2(_Ctr, _N, Acc, []) ->    {lists:reverse(Acc), []};split2(_Ctr, _N, Acc, List) ->    {lists:reverse(Acc), List}.basetype(ordered_set) ->	        set;basetype(Any) ->    Any.

⌨️ 快捷键说明

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