inviso_rt_meta.erl

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

ERL
1,195
字号
%% It must return an internal notation of the time of file open and a%% useful descriptor the write_output function can use.%% Returns {ok,TiDescriptor} or {error,Reason}.open_traceinfo_file({file,FileName}) ->     % A plain raw binary file.    case file:open(FileName,[write,raw,binary]) of	{ok,FD} ->	    {ok,{file,FD}};	{error,Reason} ->	    {error,{open,[FileName,Reason]}}    end;open_traceinfo_file({relay,ToNode}) ->      % Use distributed Erlang.    {ok,{relay,ToNode}};open_traceinfo_file(IncorrectTI) ->    {error,{badarg,IncorrectTI}}.%% -----------------------------------------------------------------------------close_traceinfo_file({file,FD}) ->    file:close(FD);close_traceinfo_file(_) ->    ok.%% -----------------------------------------------------------------------------%% Help function handling initializing meta tracing of a function.%% Returns {NewLD,NewPublLD}.h_init_tpm(Mod,Func,Arity,InitFunc,CallFunc,ReturnFunc,RemoveFunc,TI,LD,PublLD) ->    case do_initfunc(InitFunc,Mod,Func,Arity,PublLD) of	{NewPublLD,Output} ->	    write_output(TI,Output),	    NewLD=init_tpm_ld(Mod,Func,Arity,CallFunc,ReturnFunc,RemoveFunc,LD),	    {NewLD,NewPublLD};	false ->                            % The initfunc did not do anything.	    NewLD=init_tpm_ld(Mod,Func,Arity,CallFunc,ReturnFunc,RemoveFunc,LD),	    {NewLD,PublLD}    end.%% -----------------------------------------------------------------------------%% Help function handling initializing meta tracing of a function and also%% set the meta trace pattern as specified.%% Returns {NewLD,NewPublLD,N}.h_tpm(Mod,Func,Arity,MS,InitFunc,CallFunc,ReturnFunc,RemoveFunc,TI,LD,PublLD) ->    {NewLD,NewPublLD}=	h_init_tpm(Mod,Func,Arity,InitFunc,CallFunc,ReturnFunc,RemoveFunc,TI,LD,PublLD),    case set_meta_tracing(Mod,Func,Arity,MS) of	true ->                              % Ok, set one pattern.	    {NewLD,NewPublLD,1};	false ->	    {NewLD,NewPublLD,0}    end.%% -----------------------------------------------------------------------------%% Help function handling setting meta trace patter for a function which has%% already been intialized. Note that we must remove all potentially stored%% match-specs, if this function has been given match-specs before with%% tpm_ms.%% Returns a {NewLD,N}.h_tpm(Mod,Func,Arity,MS,LD) ->    case set_meta_tracing(Mod,Func,Arity,MS) of	true ->	    {remove_ms_ld(Mod,Func,Arity,LD),1};	false ->	    {LD,0}    end.%% -----------------------------------------------------------------------------%% Help function that adds a match-spec to Mod:Func/Arity. It is not defined%% in which order the match-specs will be given to the BIF.%% Note that if an MS with the same name as an exiting is inserted, the previous%% match-spec will be removed.%% Very important to realise is that the empty meta match spec [] imposes no%% restrictions what so ever on the generating of meta trace call messages.%% Uncontrolled sending of such messages may quickly drain power from the system.%% Since an empty match-spec will "disappear" when added to other match specs,%% the empty match is transformed to what it actually is: [{'_',[],[]}].%% Returns 0 or 1 indicating failure or success.h_tpm_ms(Mod,Func,Arity,MSname,MS) ->    MSsNames=get_ms_ld(Mod,Func,Arity),     % Fetch all previous match-specs.    TransformedMS=h_tpm_ms_convert_null_ms(MS),    MSsNames1=lists:keydelete(MSname,1,MSsNames), % If it already existed, it is gone!    NewMSs=lists:flatten([TransformedMS,lists:map(fun({_Name,MSx})->MSx end,MSsNames1)]),    case set_meta_tracing(Mod,Func,Arity,NewMSs) of	true ->                             % We only save the MS if it was good.	    put_ms_ld(Mod,Func,Arity,MSname,TransformedMS,MSsNames1),	    1;	false ->	    0    end.%% Help function converting the null match spec into, still a null match spec,%% on a proper match spec format. This because it will otherwise be difficult%% to see the difference between no active tpm_ms and all a set of null ms.h_tpm_ms_convert_null_ms([]) ->    [{'_',[],[]}];h_tpm_ms_convert_null_ms(MS) ->    MS.%% -----------------------------------------------------------------------------%% Help function returning a list of all names used for match-functions for%% the Mod:Func/Arity in question.h_list_tpm_ms(Mod,Func,Arity) ->    MSsNames=get_ms_ld(Mod,Func,Arity),     % A list of {MSname,MS}.    lists:map(fun({MSname,_})->MSname end,MSsNames).%% -----------------------------------------------------------------------------%% Function that removes a named match-spec. Returns nothing significant.%% Note that if we end up with no match-specs, we must remove the meta trace%% patten all together. That is bringing the function back to just initiated.h_ctpm_ms(Mod,Func,Arity,MSname) ->    case get_ms_ld(Mod,Func,Arity) of	[] ->                               % The name does certainly not exist!	    true;                           % We don't have to do anything.	MSsNames ->	    case lists:keysearch(MSname,1,MSsNames) of		{value,{_,_MS}} ->          % Ok, we must do something!		    NewMSsNames=lists:keydelete(MSname,1,MSsNames),		    case lists:flatten(lists:map(fun({_Name,MS})->MS end,NewMSsNames)) of			[] ->               % This means stop meta tracing.			    set_meta_tracing(Mod,Func,Arity,false);			NewMSs ->			    set_meta_tracing(Mod,Func,Arity,NewMSs)		    end,		    set_ms_ld(Mod,Func,Arity,NewMSsNames);		false ->                    % But this name does not exist.		    true                    % So we do not have to do anything.	    end    end.%% -----------------------------------------------------------------------------%% Function that checks the arguments to the meta trace pattern. The reason we%% must do this is that we can only allow meta tracing on specific functions and%% not using wildpatterns. Otherwise the meta trace server will not understand%% which callfunc for instance to call when a meta-trace message is generated%% for a function.%% Returns 'true' or 'false'.check_tpm_args(Mod,Func,Arity)  when is_atom(Mod),is_atom(Func),is_integer(Arity),Mod/='_',Func/='_' ->    true;check_tpm_args(_,_,_) ->    false.%% -----------------------------------------------------------------------------%% Help function which calls the actual BIF setting meta-trace-patterns.%% Returns 'true' or 'false'.set_meta_tracing(Mod,Func,Arity,MS) when is_atom(Mod) ->    case erlang:module_loaded(Mod) of	true ->	    set_meta_tracing_2(Mod,Func,Arity,MS);	false ->                            % The module is not loaded.	    case code:ensure_loaded(Mod) of		{module,_Mod} ->		    set_meta_tracing_2(Mod,Func,Arity,MS);		{error,_Reason} ->          % Could not load the module.		    false                   % No use try to trace.	    end    end;set_meta_tracing(_,_,_,_) ->    false.set_meta_tracing_2(Mod,Func,Arity,MS) ->    case catch erlang:trace_pattern({Mod,Func,Arity},MS,[meta]) of	0 ->                                % Hmm, nothing happend :-)	    false;	N when is_integer(N) ->                % The normal case, some functions were hit.	    true;	{'EXIT',_Reason} ->	    false    end.%% -----------------------------------------------------------------------------%% Help function which removes all meta trace pattern for the functions mentioned%% in the list being first argument. It also executes the remove funcs for each%% and every no longer meta traced function. This done since some of the remove%% functions may do side-effects (like deleteing ETS tables).%% Returns nothing significant.stop_all_meta_tracing([{M,F,Arity}|Rest],PublLD,LD) ->    catch erlang:trace_pattern({M,F,Arity},false,[meta]),    NewPublLD=do_removefunc(get_remove_func_ld(M,F,Arity,LD),M,F,Arity,PublLD),    stop_all_meta_tracing(Rest,NewPublLD,LD);stop_all_meta_tracing([],_,_) ->    true.%% -----------------------------------------------------------------------------%% This function calls the function registered to be handler for a certain%% meta-traced function. Such a function or fun must take three arguments%% and return {ok,NewPrivLD,OutPutBinary} or 'false'. OutPutBinary may be%% something else, and is then ignored.handle_meta({M,F},Pid,Arg1,PrivLD) ->    (catch M:F(Pid,Arg1,PrivLD));handle_meta(Fun,Pid,Arg1,PrivLD) when is_function(Fun) ->    (catch Fun(Pid,Arg1,PrivLD));handle_meta(_,_,_,_) ->                     % Don't know how to do this.    false.%% -----------------------------------------------------------------------------%% Help function writing output from a callback function to the ti-file.%% Output can be a binary or a list of binaries.write_output(TI,[OutPut|Rest]) ->    write_output(TI,OutPut),    write_output(TI,Rest);write_output({file,FD},Bin) when is_binary(Bin) -> % Plain direct-binary file    Size=size(Bin),    file:write(FD,list_to_binary([<<0,Size:32>>,Bin]));write_output({relay,ToNode},Bin) when is_atom(ToNode),is_binary(Bin) ->    {inviso_rt_meta,ToNode} ! {relayed_meta,Bin};write_output(_,_) ->                        % Don't understand, just skip.    true.%% -----------------------------------------------------------------------------%% =============================================================================%% Various help functions.%% =============================================================================%% Help function initializing the public loopdata structure. Note that if the%% supplied InitPublLDmfa is faulty we let the structure become the error.%% The error will most likely turn up in an error report somewhere, eventually.do_init_publ_ld({M,F,Args}) when is_atom(M),is_atom(F),is_list(Args) ->    case catch apply(M,F,Args) of	{'EXIT',_Reason} ->	    {error,init_publ_ld_func};      % Let the struct be this error!	InitialPublLD ->	    InitialPublLD    end;do_init_publ_ld(_) ->    {error,init_publ_ld_func}.%% -----------------------------------------------------------------------------%% Help function which removes the public loopdata structure. The function does%% not necessarily have to exist. Returns nothing significant.do_remove_publ_ld({M,F},PublLD) when is_atom(M),is_atom(F) ->    catch M:F(PublLD);do_remove_publ_ld(_,_) ->    true.%% -----------------------------------------------------------------------------	%% Hlp function initializing a particular meta traced function into the public%% loopdata. Note that the function is not mandatory.%% Returns {NewPublLD,Output} or 'false'.do_initfunc({M,F},Mod,Func,Arity,PublLD) when is_atom(M),is_atom(F) ->    case catch M:F(Mod,Func,Arity,PublLD) of	{ok,NewPublLD,Output} ->	    {NewPublLD,Output};	_ ->                                % Everything else is an error.	    false                           % Act as no initialization function.    end;do_initfunc(Fun,Mod,Func,Arity,PublLD) when is_function(Fun) ->    case catch Fun(Mod,Func,Arity,PublLD) of	{ok,NewPublLD,Output} ->	    {NewPublLD,Output};	_ ->                                % Everything else is an error.	    false                           % Act as no initialization function.    end;do_initfunc(_,_,_,_,_) ->                   % Perhaps too generous, should be 'void' only.    false.%% -----------------------------------------------------------------------------%% Help function removing a particular meta traced function from the public%% loopdata. Note that we do not make much noice should the call back function%% be faulty.do_removefunc({M,F},Mod,Func,Arity,PublLD) when is_atom(M),is_atom(F) ->    case catch M:F(Mod,Func,Arity,PublLD) of	{ok,NewPublLD} ->	    NewPublLD;	_ ->                                % Everything else is an error.	    PublLD                          % Act as no initialization function.    end;do_removefunc(Fun,Mod,Func,Arity,PublLD) when is_function(Fun) ->    case catch Fun(Mod,Func,Arity,PublLD) of	{ok,NewPublLD} ->	    NewPublLD;	_ ->                                % Everything else is an error.	    PublLD                          % Act as no initialization function.    end;do_removefunc(_,_,_,_,PublLD) ->    PublLD.%% -----------------------------------------------------------------------------%% Function that, if the time has come, goes through the priv-ld structure and%% cleans away entryn left behind. The usual cause is that the function call%% caused an exception and there were therefore no matching return_from.%% Returns {NewPrivLD,now()}.throw_old_failed({M,F},PrivLD,PrevClean) ->    case difference_in_now(PrevClean,now(),60) of % We clean once every minute.	true ->	    case catch apply(M,F,[PrivLD]) of		{'EXIT',_Reason} ->         % Something went wrong, ignore it.		    {PrivLD,now()};         % Just keep the old priv-ld.		NewPrivLD ->                % The function must return a priv-ld.		    {NewPrivLD,now()}	    end;	false ->                            % Not time yet!	    {PrivLD,PrevClean}    end.%% -----------------------------------------------------------------------------%% Help function comparing two now timestamps. Returns true or false depending%% on if S2 is more than DiffS seconds after S1. Only works for differences%% less than 1 million seconds.difference_in_now({MegaS1,S1,_},{MegaS2,S2,_},DiffS) ->    if

⌨️ 快捷键说明

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