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