inviso_rt_meta.erl

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

ERL
1,195
字号
	MegaS1+1<MegaS2 ->                  % More than 1 Mega sec. difference.	    true;	MegaS1==MegaS2,S1+DiffS<S2 ->	    true;	MegaS1+1==MegaS2,S1+DiffS<S2+1000000 ->	    true;	true ->	    false    end.%% -----------------------------------------------------------------------------%% This help function adds a {tracer,Tracer} to the enable-list in a 'trace'%% match spec action. The reason for this is that the author of the a meta%% match spec meant to turn tracing on for the process executing the match spec%% can not know the tracer. This since the match spec is most likely authored%% at the control component's node, and not here.%% Note the double tuple necessary to make it just precise a tuple!%% Returns a new match spec.add_tracer([MS1|Rest],Tracer) ->    [add_tracer_2(MS1,Tracer)|add_tracer(Rest,Tracer)];add_tracer([],_) ->    [];add_tracer(NotList,_Tracer) ->              % Can be 'false', but also an error.    NotList.add_tracer_2({Head,Cond,Body},Tracer) ->    {Head,Cond,add_tracer_3(Body,Tracer)};add_tracer_2(Faulty,_Tracer) ->    Faulty.add_tracer_3([{trace,Disable,Enable}|Rest],Tracer) when is_list(Enable) ->    [{trace,Disable,Enable++[{{tracer,Tracer}}]}|Rest];add_tracer_3([ActionTerm|Rest],Tracer) ->    [ActionTerm|add_tracer_3(Rest,Tracer)];add_tracer_3([],_Tracer) ->    [];add_tracer_3(FaultyBody,_Tracer) ->    FaultyBody.%% -----------------------------------------------------------------------------%% -----------------------------------------------------------------------------%% Help functions handling internal loopdata.%% ------------------------------------------------------------------------------record(ld,{init_publ_ld_mfa,               % {M,F,Args}	    remove_publ_ld_mf,              % {M,F} | void	    clean_publ_ld_mf,               % {Mod,Func}	    ms_mfarities=notable,           % ETS holding names match functions.	    call_mfarities=[],              % [{{M,F,Arity},2-TupleOrFun},...]	    return_mfarities=[],            % [{{M,F,Arity},2-TupleOrFun},...]	    remove_mfarities=[]	   }).mk_new_ld(InitPublLDmfa,RemovePublLDmf,CleanPublLDmf,TId) ->    #ld{	   init_publ_ld_mfa=InitPublLDmfa,	   remove_publ_ld_mf=RemovePublLDmf,	   clean_publ_ld_mf=CleanPublLDmf,	   ms_mfarities=TId       }.%% -----------------------------------------------------------------------------%% Function which restores the internal loop data to somekind of initial state.%% This is useful when tracing has been suspended.reset_ld(#ld{init_publ_ld_mfa=InitPublLDmfa,	     remove_publ_ld_mf=RemovePublLDmf,	     clean_publ_ld_mf=CleanPublLDmf,	     ms_mfarities=TId}) ->    ets:match_delete(TId,{'_','_'}),        % Empty the table.    #ld{init_publ_ld_mfa=InitPublLDmfa,	remove_publ_ld_mf=RemovePublLDmf,	clean_publ_ld_mf=CleanPublLDmf,        ms_mfarities=TId}.%% -----------------------------------------------------------------------------get_initpublldmfa_ld(#ld{init_publ_ld_mfa=InitPublLDmfa}) ->    InitPublLDmfa.%% -----------------------------------------------------------------------------get_removepublldmf_ld(#ld{remove_publ_ld_mf=RemovePublLDmf}) ->    RemovePublLDmf.%% -----------------------------------------------------------------------------get_cleanpublldmf_ld(#ld{clean_publ_ld_mf=CleanPublLDmf}) ->    CleanPublLDmf.%% -----------------------------------------------------------------------------%% Help function adding data associated with a meta traced function to the%% internal loopdata. Called when meta tracing is activated for M:F/Arity.init_tpm_ld(M,F,Arity,CallFunc,ReturnFunc,RemoveFunc,LD) ->    ets:insert(LD#ld.ms_mfarities,{{M,F,Arity},[]}),    CallFuncs=LD#ld.call_mfarities,    ReturnFuncs=LD#ld.return_mfarities,    RemoveFuncs=LD#ld.remove_mfarities,    LD#ld{call_mfarities=[{{M,F,Arity},CallFunc}|CallFuncs],	  return_mfarities=[{{M,F,Arity},ReturnFunc}|ReturnFuncs],	  remove_mfarities=[{{M,F,Arity},RemoveFunc}|RemoveFuncs]}.%% -----------------------------------------------------------------------------%% Help function which answers the question if we have already initiated the%% function. It is done by looking in the ETS-table with named match-functions.%% If there is an entry in the set-type table for M:F/Arity, the function is%% initiated.%% Returns 'yes' or 'no'.check_mfarity_exists(M,F,Arity) ->    case ets:lookup(?NAMED_MS_TAB,{M,F,Arity}) of	[] ->	    no;	[_] ->	    yes    end.%% -----------------------------------------------------------------------------%% Help function adding an entry with [{MSname,MSlist}|MSsNames] for M:F/Arity.%% Note that any already existing entry is removed.%% Returns nothing significant.put_ms_ld(M,F,Arity,MSname,MS,MSsNames) ->    ets:insert(?NAMED_MS_TAB,{{M,F,Arity},[{MSname,MS}|MSsNames]}).%% -----------------------------------------------------------------------------%% Help function taking a list of {MSname,MSs} and storing them in the%% internal loop data structure. The storage is actually implemented as an ETS%% table. Any previous list of {MSname,MSs} associated with this {M,F,Arity} will%% be lost. Returns nothing significant.set_ms_ld(M,F,Arity,MSsNames) ->    ets:insert(?NAMED_MS_TAB,{{M,F,Arity},MSsNames}).%% -----------------------------------------------------------------------------%% Help function fetching a list of {MSname,MatchSpecs} for a M:F/Arity. The%% match-functions are stored in an ETS table searchable on {M,F,Arity}.get_ms_ld(M,F,Arity) ->    case ets:lookup(?NAMED_MS_TAB,{M,F,Arity}) of	[{_MFArity,MSsNames}] ->	    MSsNames;	[] ->	    []    end.%% -----------------------------------------------------------------------------%% Help function removing all saved match-specs for a certain M:F/Arity.%% Returns a new loopdata structure.remove_ms_ld(M,F,Arity,LD) ->    ets:delete(LD#ld.ms_mfarities,{M,F,Arity}),    LD.%% -----------------------------------------------------------------------------%% Help function which removes all information about a meta traced function from%% the internal loopdata. Returns a new loopdata structure.ctpm_ld(M,F,Arity,LD) ->    ets:delete(LD#ld.ms_mfarities,{M,F,Arity}),    NewCallFuncs=lists:keydelete({M,F,Arity},1,LD#ld.call_mfarities),    NewReturnFuncs=lists:keydelete({M,F,Arity},1,LD#ld.return_mfarities),    NewRemoveFuncs=lists:keydelete({M,F,Arity},1,LD#ld.remove_mfarities),    LD#ld{call_mfarities=NewCallFuncs,	  return_mfarities=NewReturnFuncs,	  remove_mfarities=NewRemoveFuncs}.%% -----------------------------------------------------------------------------get_call_func_ld(M,F,Arity,#ld{call_mfarities=CallFuncs}) ->    case lists:keysearch({M,F,Arity},1,CallFuncs) of	{value,{_,MF}} ->	    MF;	false ->	    false    end.%% -----------------------------------------------------------------------------get_return_func_ld(M,F,Arity,#ld{return_mfarities=CallFuncs}) ->    case lists:keysearch({M,F,Arity},1,CallFuncs) of	{value,{_,MF}} ->	    MF;	false ->	    false    end.%% -----------------------------------------------------------------------------get_remove_func_ld(M,F,Arity,#ld{remove_mfarities=RemoveFuncs}) ->    case lists:keysearch({M,F,Arity},1,RemoveFuncs) of	{value,{_,MF}} ->	    MF;	false ->	    false    end.%% -----------------------------------------------------------------------------%% Function returning a list of all {Mod,Func,Arity} which are currently meta%% traced. It does do by listifying the call_mfarities field in the internal%% loopdata.get_all_meta_funcs_ld(#ld{call_mfarities=CallFuncs}) ->    lists:map(fun({MFArity,_})->MFArity end,CallFuncs).%% -----------------------------------------------------------------------------%% =============================================================================%% Functions for the standard PublLD structure.%%%% It is tuple {Part1,GlobalData} where Part1 is of length at least 2.%% Where each field is a list of tuples. The last item in each tuple shall be%% a now tuple, making it possible to clean it away should it be too old to be%% relevant (there was no return_from message due to a failure).%% Other fields can be used for other functions.%% The GlobalData is not cleaned but instead meant to store data must be passed%% to each CallFunc when a meta trace message arrives.%% =============================================================================		      %% Function returning our standard priv-loopdata structure.init_std_publld(Size,GlobalData) ->    {list_to_tuple(lists:duplicate(Size,[])),GlobalData}.%% -----------------------------------------------------------------------------%% Function capable of cleaning out a standard publ-ld. The last element of each%% tuple must be the now item.%% Returns a new publ-ld structure.clean_std_publld({Part1,GlobalData}) ->    {clean_std_publld_2(Part1,now(),size(Part1),[]),GlobalData}.clean_std_publld_2(_,_,0,Accum) ->    list_to_tuple(Accum);clean_std_publld_2(PublLD,Now,Index,Accum) ->    NewTupleList=clean_std_publld_3(element(Index,PublLD),Now),    clean_std_publld_2(PublLD,Now,Index-1,[NewTupleList|Accum]).clean_std_publld_3([Tuple|Rest],Now) ->    PrevNow=element(size(Tuple),Tuple),     % Last item shall be the now item.    case difference_in_now(PrevNow,Now,30) of	true ->                             % Remove it then!	    clean_std_publld_3(Rest,Now);	false ->                            % Keep it!	    [Tuple|clean_std_publld_3(Rest,Now)]    end;clean_std_publld_3([],_) ->    [].%% -----------------------------------------------------------------------------%% =============================================================================%% Functions used as handling functions (as funs) for registered process names.%% (Given that we use the standard priv-ld, otherwise you must do your own!).%% =============================================================================%% Call-back for initializing the meta traced functions there are quick functions%% for. Returns a new public loop data structure.metafunc_init(erlang,register,2,{Part1,GlobalData}) ->    {setelement(1,Part1,[]),GlobalData}.%% -----------------------------------------------------------------------------%% Call-function for erlang:register/2.%% This function adds the call to register/2 to a standard priv-ld structure.%% Note that we *must* search for previous entries from the same process. If such%% still in structure it means a failed register/2 call. It must first be removed%% so it can not be mixed up with this one. Since meta-trace message will arrive%% in order, there was no return_from message for that call if we are here now.local_register_call(CallingPid,[Alias,Pid],{Part1,GlobalData}) ->    TupleList=element(1,Part1),             % The register/2 entry in a std. priv-ld.    NewTupleList=lists:keydelete(CallingPid,1,TupleList), % If present, remove previous call.    {ok,     {setelement(1,Part1,[{CallingPid,{Alias,Pid},now()}|NewTupleList]),GlobalData},     void}.%% Return-function for the erlang:register/2 BIF.%% This function formulates the output and removes the corresponding call entry%% from the standard priv-ld structure.local_register_return(CallingPid,_Value,PublLD={Part1,GlobalData}) ->    TupleList=element(1,Part1),             % The register/2 entry in a std. priv-ld.    case lists:keysearch(CallingPid,1,TupleList) of	{value,{_,{Alias,Pid},Now}} ->	    NewTupleList=lists:keydelete(CallingPid,1,TupleList),	    {ok,	     {setelement(1,Part1,NewTupleList),GlobalData},	     term_to_binary({Pid,Alias,alias,Now})};	false ->                            % Strange, then don't know what to do.	    {ok,PublLD,void}                % Do nothing seems safe.    end.%% When unregister/1 us called we simply want a unalias entry in the ti-file.%% We can unfortunately not connect it with a certain pid.local_unregister_call(_CallingPid,[Alias],PublLD) ->    {ok,PublLD,term_to_binary({undefined,Alias,unalias,now()})}.%% -----------------------------------------------------------------------------%% Call-function for global:register_name/2,/3.%% This function is actually the call function for the handle_call/3 in the%% global server. Note that we must check that we only do this on the node%% where Pid actually resides.global_register_call(_CallingPid,[{register,Alias,P,_},_,_],PublLD) when node(P)==node()->    {ok,PublLD,term_to_binary({P,{global,Alias},alias,now()})};global_register_call(_CallingPid,_,PublLD) ->    {ok,PublLD,void}.%% Call-function for global:unregister_name. It acutally checks on the use of%% global:delete_global_name/2 which is called when ever a global name is removed.global_unregister_call(_CallingPid,[Alias,P],PublLD) when node(P)==node()->    {ok,PublLD,term_to_binary({P,{global,Alias},unalias,now()})};global_unregister_call(_CallingPid,_,PublLD) ->    {ok,PublLD,void}.%% -----------------------------------------------------------------------------%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

⌨️ 快捷键说明

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