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 + -
显示快捷键?