inviso_rt_meta.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,195 行 · 第 1/4 页
ERL
1,195 行
%% ``The contents of this file are subject to the Erlang Public License,%% Version 1.1, (the "License"); you may not use this file except in%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %% $Id$%%%% Author: Lennart 謍man, lennart.ohman@st.se%%%% This module implements the meta tracer process belonging to the%% runtime component. Its main purpose is to write the ti-file (traceinformation).%% The ti-file contains translations between process id:s and what ever "you"%% want to read in the merged and formatted logfile.%% This process interacts with the runtime component process.%%%% Currently it handles the following types of ti-files:%% Plain raw, binary log.%% Relay to other inviso_rt_meta process on another node.%%%% The TI file will be on binary format and each entry is:%% <<LengthIndicator:32, {Pid,Alias,Op,NowStamp} >>%% Pid=pid(), or if OP==unalias pid()|any_other_than_pid()%% Op=alias|unalias%% ------------------------------------------------------------------------------module(inviso_rt_meta).%% -----------------------------------------------------------------------------%% API exports.%% ------------------------------------------------------------------------------export([start/2,start/5]).-export([stop/1,suspend/1]).-export([init_tpm/5,init_tpm/8]).-export([tpm/5,tpm/6,tpm/9,tpm_tracer/5,tpm_tracer/6,tpm_tracer/9]).-export([tpm_ms/6,tpm_ms_tracer/6,ctpm_ms/5,ctpm/4]).-export([local_register/1,global_register/1]).-export([remove_local_register/1,remove_global_register/1]).-export([write_ti/1]).-export([get_tracer/0,tpm_ms/5,tpm_ms_tracer/5,list_tpm_ms/3,ctpm_ms/4]).-export([metacast_call/5,metacast_return_from/6]).-export([get_state/1]).%% -----------------------------------------------------------------------------%% -----------------------------------------------------------------------------%% Internal exports.%% ------------------------------------------------------------------------------export([init/6]).-export([init_std_publld/2,clean_std_publld/1]).%% -----------------------------------------------------------------------------%% -----------------------------------------------------------------------------%% Constants.%% ------------------------------------------------------------------------------define(NAMED_MS_TAB,inviso_rt_meta_named_ms).%% -----------------------------------------------------------------------------%% =============================================================================%% Exported API (Meant to be used by a runtime component).%% =============================================================================%% start(TiData,Tracer)={ok,Pid} | {error,Reason}%% start(TiData,Tracer,InitPublLDmfa,RemovePublLDmfa,CleanPublLDmf)=%% {ok,Pid} | {error,Reason}%% TiData={file,FileName}|{relay,Node}%% Tracer=pid()|port()%% FileName=string()%% InitPublLDmfa={Mod,Func,ArgList}%% RemovePublLDmf={Mod,Func} | void%% RemovePublLDmf(PublLD)->nothing significant.%% These functions are called to create and destroy the public loopdata%% structure available to the meta-trace CallFunc and ReturnFunc.%% CleanPublLDmf={Mod,Func}%% This function will periodically be called to clean the public LD from%% pending meta-trace messages waiting for a corresponding return_from%% message.%%%% Starts a meta-tracer process, opening the ti-file specified in TiData. PublLD%% is used to communicate data, typically between a call and return_from.%% If no special initialization function is specified a standard one is used.%% Note that the meta tracer function must know "who" is the regular tracer%% (process or port). This because it must be possible to append {tracer,Tracer}%% in meta match specs.start(TiData,Tracer) -> Pid=spawn_link(?MODULE, init, [self(), TiData, Tracer, {?MODULE,init_std_publld,[2,[]]}, void, {?MODULE,clean_std_publld}]), wait_for_reply(Pid).start(TiData,Tracer,InitPublLDmfa,RemovePublLDmf,CleanPublLDmf) -> Pid=spawn_link(?MODULE, init, [self(),TiData,Tracer,InitPublLDmfa,RemovePublLDmf,CleanPublLDmf]), wait_for_reply(Pid).wait_for_reply(Pid) -> receive {Pid,ok} -> {ok,Pid}; {Pid,{error,Reason}} -> {error,Reason} after 10000 -> % After very long time. exit(Pid,kill), % It must be hanging. {error,time_out} end.%% -----------------------------------------------------------------------------%% stop(Pid)=ok%% Pid=Adders to the meta tracer, pid().%% Shutsdown the metatracer.stop(Pid) -> Pid ! {stop,self()}, ok.%% -----------------------------------------------------------------------------%% suspend(Pid)=ok%% Pid=Adders to the meta tracer, pid().%% Suspends the meta tracer by removing all meta trace patterns.suspend(Pid) -> Pid ! {suspend,self()}, ok.%% -----------------------------------------------------------------------------%% init_tpm(Pid,Mod,Func,Arity,CallFunc)=%% init_tpm(Pid,Mod,Func,Arity,InitFunc,CallFunc,ReturnFunc,RemoveFunc)=ok|{error,Reason}.%% Pid=Address to meta tracer process, pid().%% Mod,Func=Pointing out the function which shall be meta traced, atom().%% Arity=As above, integer().%% InitFunc,RemoveFunc={Module,Function}|fun(), functions being called when%% to initialize the public loopdata structure, and to reset it.%% InitFunc(Mod,Func,Arity,PublLD)->{ok,NewPublLD,Output}%% Supposed to initialize whatever needs to be done before%% handling any incoming meta-trace message for the Mod:Func/Arity.%% RemoveFunc(Mod,Func,Arity,PublLD)->{ok,NewPublLD}%% Called when meta tracing of Mod:Func/Arity is stopped. It is supposed%% to clear datastructures away from the PublLD.%% Initializes the public loopdata for this function. Note that we can not use wildcards%% here (even if it is perfectly legal in Erlang). It also sets the CallFunc and%% ReturnFunc for the meta traced function. The function is hence ready to be%% meta traced with either tpm/5 or tpm_ms/5.%% This function is synchronous, waiting for a reply from the meta server.init_tpm(Pid,Mod,Func,Arity,CallFunc) -> init_tpm(Pid,Mod,Func,Arity,void,CallFunc,void,void).init_tpm(Pid,Mod,Func,Arity,InitFunc,CallFunc,ReturnFunc,RemoveFunc) -> send_wait(Pid, {init_tpm,{Mod,Func,Arity},InitFunc,CallFunc,ReturnFunc,RemoveFunc}).%% -----------------------------------------------------------------------------%% tpm(Pid,Mod,Func,Arity,MatchSpec)={ok,N}|{error,Reason}%% tpm(Pid,Mod,Func,Arity,MatchSpec,CallFunc)={ok,N}|{error,Reason}%% tpm(Pid,Mod,Func,Arity,MatchSpec,InitFunc,CallFunc,ReturnFunc,RemoveFunc)=%% Pid=Address to meta tracer process, pid().%% Mod,Func=Pointing out the function which shall be meta traced, atom().%% Arity=As above, integer().%% MatchSpec=List of match specification, possibly empty. Remember {return_trace}%% if expecting return_from messages.%% InitFunc,CallFunc,ReturnFunc,RemoveFunc={Module,Function}|fun(),%% functions being called when these functions are called by the meta trace%% server at certain events.%% CallFunc(CallingPid,ActualArgList,PublLD)->{ok,NewPrivLD,Output}%% ReturnFunc(CallingPid,ReturnValue,PublLD)->{ok,NewPrivLD,Output}%% When a call respectively return_from trace message arrives for the meta%% traced function, the corresponding function is called.%% The ReturnFunc must handle the fact that a return_from message arrives%% for a call which was never noticed. This because the message queue of the%% meta tracer may have been emptied.%% Reason=badarg | %% Output=Characters to be written to the ti-file, bin() | 'void'%% The tpm/5 function simply starts meta tracing for the function. It must%% previously have been initialized.%% tpm/6 & /9 initializes the function and starts meta tracing.tpm(Pid,Mod,Func,Arity,MatchSpec) when is_atom(Mod),is_atom(Func),is_integer(Arity),is_list(MatchSpec),Mod/='_',Func/='_'-> send_wait(Pid,{tpm,{Mod,Func,Arity,MatchSpec}});tpm(_,_,_,_,_) -> {error,badarg}.tpm(Pid,Mod,Func,Arity,MatchSpec,CallFunc) -> tpm(Pid,Mod,Func,Arity,MatchSpec,void,CallFunc,void,void).tpm(Pid,Mod,Func,Arity,MatchSpec,InitFunc,CallFunc,ReturnFunc,RemoveFunc) when is_atom(Mod),is_atom(Func),is_integer(Arity),is_list(MatchSpec),Mod/='_',Func/='_' -> send_wait(Pid,{tpm,{Mod,Func,Arity,MatchSpec},InitFunc,CallFunc,ReturnFunc,RemoveFunc});tpm(_,_,_,_,_,_,_,_,_) -> {error,badarg}.%% -----------------------------------------------------------------------------%% Same as tpm/X but the meta tracer will automatically append {tracer,Tracer}%% to the enable list in a {trace,Disable,Enable} match spec action term.tpm_tracer(Pid,Mod,Func,Arity,MatchSpec) when is_atom(Mod),is_atom(Func),is_integer(Arity),is_list(MatchSpec),Mod/='_',Func/='_'-> send_wait(Pid,{tpm_tracer,{Mod,Func,Arity,MatchSpec}});tpm_tracer(_,_,_,_,_) -> {error,badarg}.tpm_tracer(Pid,Mod,Func,Arity,MatchSpec,CallFunc) -> tpm_tracer(Pid,Mod,Func,Arity,MatchSpec,void,CallFunc,void,void).tpm_tracer(Pid,Mod,Func,Arity,MatchSpec,InitFunc,CallFunc,ReturnFunc,RemoveFunc) when is_atom(Mod),is_atom(Func),is_integer(Arity),is_list(MatchSpec),Mod/='_',Func/='_' -> send_wait(Pid,{tpm_tracer, {Mod,Func,Arity,MatchSpec}, InitFunc,CallFunc,ReturnFunc,RemoveFunc});tpm_tracer(_,_,_,_,_,_,_,_,_) -> {error,badarg}.%% -----------------------------------------------------------------------------%% tpm_ms(Pid,Mod,Func,Arity,MSname,MS)={ok,N}|{error,Reason}%% Pid=Address to meta tracer process, pid().%% Mod,Func=Pointing out the function to which we shall add a match-spec., atom().%% Arity=As above, integer().%% MSname=A name to be used if this MS shall be removed later. term().%% MatchSpec=List of match specification, Remember {return_trace}%% if expecting return_from messages.%% This function adds a list of match-specs to the already existing ones. It%% uses an internal database to keep track of existing match-specs. If the%% match-spec does not result in any meta traced functions (for whatever reason),%% the MS is not saved in the database. The previously known match-specs are%% not removed.tpm_ms(Pid,Mod,Func,Arity,MSname,MS) -> send_wait(Pid,{tpm_ms,{Mod,Func,Arity},MSname,MS}).%% -----------------------------------------------------------------------------%% Same as tpm_ms/6 but the meta tracer will automatically append {tracer,Tracer}%% to the enable list in a {trace,Disable,Enable} match spec action term.tpm_ms_tracer(Pid,Mod,Func,Arity,MSname,MS) -> send_wait(Pid,{tpm_ms_tracer,{Mod,Func,Arity},MSname,MS}).%% -----------------------------------------------------------------------------%% ctpm_ms(Pid,Mod,Func,Arity)=ok%%%% Removes a names match-spec from the meta traced function. Note that is never%% a fault to remove an MS. Not even from a function which is non existant.ctpm_ms(Pid,Mod,Func,Arity,MSname) -> send_wait(Pid,{ctpm_ms,{Mod,Func,Arity},MSname}).%% -----------------------------------------------------------------------------%% Quick versions for erlang:register/2 which also uses a default CallFunc%% and a default ReturnFunc.local_register(Pid) -> Res1=tpm(Pid, erlang,register,2,[{'_',[],[{return_trace}]}], fun metafunc_init/4,fun local_register_call/3, fun local_register_return/3,void), Res2=tpm(Pid, erlang,unregister,1,[], void,fun local_unregister_call/3,void,void), {Res1,Res2}.%% -----------------------------------------------------------------------------%% Quick version for global:register_name/2, /3.global_register(Pid) -> Res1=tpm(Pid,global,handle_call,3,[{[{register,'_','_','_'},'_','_'],[],[]}], void,fun global_register_call/3,void,void), Res2=tpm(Pid,global,delete_global_name,2,[], void,fun global_unregister_call/3,void,void), {Res1,Res2}.%% -----------------------------------------------------------------------------%% ctpm(Pid,Mod,Func,Arity)=ok|{error,bad_mfa}%%%% Removes the meta trace pattern for the function, means stops generating output%% for this function. The public LD may be cleared by the previously entered%% RemoveFunc.ctpm(Pid,Mod,Func,Arity) -> send_wait(Pid,{ctpm,{Mod,Func,Arity}}).%% -----------------------------------------------------------------------------%% remove_local_register(Pid)={Res1,Res2}%% Res1,Res2=ok|{error,Reason}remove_local_register(Pid) -> Res1=ctpm(Pid,erlang,register,2), Res2=ctpm(Pid,erlang,unregister,1), {Res1,Res2}.%% -----------------------------------------------------------------------------%% remove_global_register(Pid)={Res1,Res2}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?