tv_db.erl

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

ERL
1,268
字号
    case ExitInfo of        {MasterPid, _Reason} ->               % When from master, just quit!            exit(normal);        _Other ->            done    end.update_db(NewList, ListOfKeys, ProcVars) ->    DbData = ProcVars#process_variables.db_data,    #db_data{db            = OldDbList,	     max_elem_size = MaxElemSize,	     deleted       = DelList,	     ets_type      = EtsType,	     sorting       = Sorting,	     rev_sorting   = RevSorting,	     sort_key_no   = SortKeyNo,	     key_no        = KeyNo} = DbData,        DbList   = update_colors(OldDbList -- DelList),    OldList  = dblist2list(DbList),    InsOrUpd = (NewList -- OldList),    DelOrUpd = (OldList -- NewList),        {Inserted, Deleted, Updated} = group_difflists(basetype(EtsType), KeyNo, 						   InsOrUpd, 						   DelOrUpd),    DelMarked = mark_deleted(KeyNo, Deleted, DbList),    Replaced  = replace_elements(KeyNo, Updated, DelMarked),    NewDbList = add_elements(KeyNo, Inserted, Replaced, Sorting, RevSorting, 			     SortKeyNo),    NewMaxSize = ?COMM_FUNC_FILE:max(MaxElemSize, 				     ?COMM_FUNC_FILE:max(max_size(Replaced), 							 max_size(Inserted))),    NewDbData = DbData#db_data{db            = NewDbList,			       db_size       = length(NewDbList),			       max_elem_size = NewMaxSize,			       deleted       = list2dblist(Deleted, ?BLACK)			      },    ProcVars#process_variables{db_data = NewDbData,			       list_of_keys = ListOfKeys			      }.    update_object(Obj, OldObj, OldColor, ObjNo, ProcVars) ->    #process_variables{db_data     = DbData,		       etsread_pid = EtsreadPid}  = ProcVars,        #db_data{key_no        = KeyNo} = DbData,       %% Don't update if there are no changes!    case OldObj of	Obj when OldColor =/= ?BLACK ->   %% Allow deleted objects to be inserted!	    gs:window(dbwin, gs:start(), []),	    case get(error_msg_mode) of		normal ->		    tv_utils:notify(dbwin, "TV Notification", ["The object is unchanged!"]);		haiku ->		    tv_utils:notify(dbwin, "TV Notification", 				    ["Stay the patient course,",				     "Of little worth is your ire:",				     "The object's unchanged." ])	    end,	    gs:destroy(dbwin),	    {false, ProcVars};	_Other ->	       %% Before we try to update the internal database, we have to check to see	       %% whether the ETS/Mnesia update is allowed!	    Result = 		case OldColor of		    ?BLACK ->			EtsreadPid ! #etsread_new_object{sender     = self(),							 object     = Obj}, 			receive 			    #etsread_new_object_cfm{success = Success} ->				Success			after 			    60000 ->				exit(etsread_not_responding)			end;		    _OtherColor ->			EtsreadPid ! #etsread_update_object{sender     = self(),							    key_no     = KeyNo,							    object     = Obj,							    old_object = OldObj}, 			receive 			    #etsread_update_object_cfm{success = Success} ->				Success			after 			    60000 ->				exit(etsread_not_responding)			end		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 ->		    {true, update_object2(Obj, OldObj, OldColor, ObjNo, ProcVars)}	    end    end.update_object2(Obj, OldObj, OldColor, ObjNo, ProcVars) ->    #process_variables{db_data = DbData}  = ProcVars,        #db_data{db            = DbList,	     ets_type      = EtsType,     %% 'bag', 'set', 'ordered_set' or 					  %% 'duplicate_bag'	     max_elem_size = MaxElemSize,	     sorting       = Sorting,	     rev_sorting   = RevSorting,	     sort_key_no   = SortKeyNo,	     key_no        = KeyNo} = DbData,       %% Replace the old element...    Key    = element(KeyNo, Obj),    OldKey = element(KeyNo, OldObj),       %% If Key == OldKey, the old object shall only be replaced!       %% Otherwise the updated object shall be treated as a new        %% object when inserting it in the list!       %% In that latter case, we also have to check for duplicates!    Fun = 	case basetype(EtsType) of	    set ->		case Key of		    OldKey ->			fun({Data,Color}, {Replaced,AccDb}) when element(KeyNo,Data) =/= Key ->				{Replaced, [{Data,Color} | AccDb]};			   ({_Data,Color}, {Replaced,AccDb}) when not Replaced,								 OldColor =:= ?BLACK,								 Color =:= ?BLACK ->				{true, [{Obj,?RED1} | AccDb]};			   ({_Data,Color}, {Replaced,AccDb}) when not Replaced,								 OldColor =/= ?BLACK,								 Color =/= ?BLACK ->				{true, [{Obj,?GREEN1} | AccDb]};			   ({_Data,_Color}, {Replaced,AccDb}) ->				{Replaced, AccDb}			end;		    _NewKey ->			fun({Data,Color}, {Replaced,AccDb}) ->				ElemKey = element(KeyNo,Data),				case ElemKey of				    OldKey when not Replaced,						OldColor =:= ?BLACK,						Color    =:= ?BLACK ->					{true, [{Obj,?RED1} | AccDb]};				    OldKey when not Replaced,						OldColor =/= ?BLACK,						Color =/= ?BLACK ->					{true, [{Obj,?GREEN1} | AccDb]};				    OldKey ->					{Replaced, AccDb};				    Key ->					{Replaced, AccDb};				    _OtherKey ->					{Replaced, [{Data,Color} | AccDb]}				end			end		end;	    bag ->		case Key of		    OldKey ->			fun({Data,_Color}, {Replaced,AccDb}) when Data =:= Obj ->				{Replaced, AccDb};			   ({Data,Color}, {Replaced,AccDb}) when Data =/= OldObj ->				{Replaced, [{Data,Color} | AccDb]};			      %% Clauses when Data =:= OldObj.			   ({_Data,Color}, {Replaced,AccDb}) when not Replaced,								 OldColor =:= ?BLACK,								 Color =:= ?BLACK ->				{true, [{Obj,?RED1} | AccDb]};			   ({_Data,Color}, {Replaced,AccDb}) when not Replaced,								 OldColor =/= ?BLACK,								 Color =/= ?BLACK ->				{true, [{Obj,Color} | AccDb]};			   ({_Data,_Color}, {Replaced,AccDb}) ->				{Replaced, AccDb}			end;		    _NewKey ->			fun({Data,Color}, {Replaced,AccDb}) when Data =:= OldObj,								 not Replaced,								 OldColor =:= ?BLACK,								 Color =:= ?BLACK ->				{true, [{Obj,?RED1} | AccDb]};			   ({Data,Color}, {Replaced,AccDb}) when Data =:= OldObj,								 not Replaced,								 OldColor =/= ?BLACK,								 Color =/= ?BLACK ->				{true, [{Obj,?GREEN1} | AccDb]};			   ({Data,_Color}, {Replaced,AccDb}) when Data =:= OldObj ->				{Replaced, AccDb};			   ({Data,_Color}, {Replaced,AccDb}) when Data =:= Obj ->				{Replaced, AccDb};			   ({Data,Color}, {Replaced,AccDb}) ->				{Replaced, [{Data,Color} | AccDb]}			end		end;	    duplicate_bag ->		   %% Multiple identical objects allowed, meaning that we shall not		   %% remove anything, just replace one element.		case Key of		    OldKey ->			fun({Data,Color}, {Replaced,AccDb}) when Data =:= Obj ->				{Replaced, [{Data,Color} | AccDb]};			   ({Data,Color}, {Replaced,AccDb}) when Data =/= OldObj ->				{Replaced, [{Data,Color} | AccDb]};			   ({_Data,Color}, {Replaced,AccDb}) when not Replaced,								 OldColor =:= ?BLACK,								 Color =:= ?BLACK ->				{true, [{Obj,?RED1} | AccDb]};			   ({_Data,Color}, {Replaced,AccDb}) when not Replaced,								 OldColor =/= ?BLACK,								 Color =/= ?BLACK ->				{true, [{Obj,Color} | AccDb]};			   ({Data,Color}, {Replaced,AccDb}) ->				{Replaced, [{Data,Color} | AccDb]}			end;		    _NewKey ->			fun({Data,Color}, {Replaced,AccDb}) when Data =:= OldObj,								 not Replaced,								 OldColor =:= ?BLACK,								 Color =:= ?BLACK ->				{true, [{Obj,?RED1} | AccDb]};			   ({Data,Color}, {Replaced,AccDb}) when Data =:= OldObj,								 not Replaced,								 OldColor =/= ?BLACK,								 Color =/= ?BLACK ->				{true, [{Obj,?GREEN1} | AccDb]};			   ({Data,Color}, {Replaced,AccDb}) when Data =:= OldObj ->				{Replaced, [{Data,Color} | AccDb]};			   ({Data,Color}, {Replaced,AccDb}) when Data =:= Obj ->				{Replaced, [{Data,Color} | AccDb]};			   ({Data,Color}, {Replaced,AccDb}) ->				{Replaced, [{Data,Color} | AccDb]}			end		end	end,        FilterFun = fun(Acc0, L) ->			lists:foldl(Fun, Acc0, L)		end,            {Repl, TmpList} =	case split(ObjNo, DbList) of	    {L1, [{OldObj,OldColor} | T]} when OldColor =/= ?BLACK ->		{true, 		 lists:reverse(element(2, FilterFun({true,[]}, L1))) ++ 		 [{Obj,?GREEN1} | lists:reverse(element(2, FilterFun({true,[]},T)))]};	    {L1, [{OldObj,OldColor} | T]} ->		{true, 		 lists:reverse(element(2, FilterFun({true,[]}, L1))) ++ 		 [{Obj,?RED1} | lists:reverse(element(2, FilterFun({true,[]}, T)))]};	    {L1, L2} ->		{R1, NewL1} = FilterFun({false,[]}, L1),		{R2, NewL2} = FilterFun({false,[]}, L2),		{R1 or R2, lists:reverse(NewL1) ++ lists:reverse(NewL2)}	end,    NewDbList = 	case Repl of	    true when not Sorting ->		TmpList;	    true ->		tv_db_sort:mergesort(SortKeyNo, TmpList, RevSorting);	    false ->		TmpList2 = 		    case Key of			OldKey ->			    lists:reverse(element(2, FilterFun({false,[]}, TmpList)));			_OtherKey ->			    lists:reverse(element(2, FilterFun({true,[]}, TmpList))) ++ 				[{Obj,?RED1}]		    end,		case Sorting of		    false ->			TmpList2;		    true ->			tv_db_sort:mergesort(SortKeyNo, TmpList2, RevSorting)		end	end,    NewMaxSize = ?COMM_FUNC_FILE:max(MaxElemSize, max_size([Obj])),    NewDbData = DbData#db_data{db            = NewDbList,			       db_size       = length(NewDbList),			       max_elem_size = NewMaxSize			      },    ProcVars#process_variables{db_data = NewDbData}.delete_object(_Obj, ?BLACK, _ObjNo, ProcVars) ->       %% Don't delete already deleted objects!!!    {false, ProcVars};delete_object(undefined, undefined, _ObjNo, ProcVars) ->    {false, ProcVars};delete_object(Obj, _ObjColor, ObjNo, ProcVars) ->    #process_variables{db_data     = DbData,		       etsread_pid = EtsreadPid}  = ProcVars,        #db_data{db            = DbList,	     deleted       = OldDeleted} = DbData,           %% Before we try to update the internal database, we have to check to see       %% whether the ETS/Mnesia update is allowed!    EtsreadPid ! #etsread_delete_object{sender     = self(),					object     = Obj},     Result = 	receive 	    #etsread_delete_object_cfm{success = Success} ->		Success	after	    60000 ->		exit(etsread_not_responding)	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 ->	       %% Replace the old element...	       %% Have to beware of duplicate_bag tables,	       %% i.e., the same object may occur more than	       %% once, but we only want to remove it once!	    {Repl, TmpList} =		case split(ObjNo, DbList) of		    {L1, [{Obj,_Color} | T]} ->			{true, L1 ++ [{Obj,?BLACK} | T]};		    {L1, L2} ->			{false, L1 ++ L2}		end,	    NewDbList = 		case Repl of		    true ->			TmpList;		    false ->			Fun = fun({Data,TmpColor}, 				  {Removed,AccDb}) when Data =/= Obj ->				      {Removed, [{Data,TmpColor} | AccDb]};				 ({_Data,TmpColor}, 				  {Removed,AccDb}) when not Removed, TmpColor =/= ?BLACK ->				      {true, [{Obj,?BLACK} | AccDb]};				 ({Data,TmpColor}, 				  {Removed,AccDb}) ->				      {Removed, [{Data,TmpColor} | AccDb]}			      end,			lists:reverse(element(2, lists:foldl(Fun, {false,[]}, DbList)))		end,	    NewDbData = DbData#db_data{db      = NewDbList,				       db_size = length(NewDbList),				       deleted = [{Obj,?BLACK} | OldDeleted]},	    {true, ProcVars#process_variables{db_data = NewDbData}}    end.new_object(Obj, ProcVars) ->    #process_variables{db_data     = DbData,		       etsread_pid = EtsreadPid}  = ProcVars,        #db_data{db            = DbList,	     max_elem_size = MaxElemSize,	     ets_type      = EtsType,     %% 'bag', 'set' or 'duplicate_bag'	     sorting       = Sorting,	     rev_sorting   = RevSorting,	     sort_key_no   = SortKeyNo,	     key_no        = KeyNo} = DbData,       %% Before we try to update the internal database, we have to check to see       %% whether the ETS/Mnesia update is allowed!    EtsreadPid ! #etsread_new_object{sender     = self(),				     object     = Obj},     Result = 	receive 	    #etsread_new_object_cfm{success = Success} ->		Success	after	    60000 ->		exit(etsread_not_responding)

⌨️ 快捷键说明

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