inviso_rt_meta.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,195 行 · 第 1/4 页
ERL
1,195 行
%% Res1,Res2=ok|{error,Reason}remove_global_register(Pid) -> Res1=ctpm(Pid,global,handle_call,3), Res2=ctpm(Pid,global,delete_global_name,2), {Res1,Res2}.%% -----------------------------------------------------------------------------%% Exported help functions which may be used in programming CallFunc and/or%% ReturnFunc. Useful if the call is done on one node but must trigger the%% start of something at other nodes.metacast_call(Nodes,OrigPid,M,F,Args) -> multicast(Nodes,{trace_ts,OrigPid,call,{M,F,Args},void}), ok.metacast_return_from(Nodes,OrigPid,M,F,Arity,Value) -> multicast(Nodes,{trace_ts,OrigPid,return_from,{M,F,Arity},Value,void}), ok.multicast([Node|Rest],Msg) -> {?MODULE,Node} ! Msg, multicast(Rest,Msg);multicast([],_) -> true.%% -----------------------------------------------------------------------------%% get_states(Pid)={ok,LD,PubLD}.get_state(Pid) -> send_wait(Pid,get_state).%% -----------------------------------------------------------------------------send_wait(To,Msg) -> Ref=make_ref(), To ! {Msg,Ref,self()}, receive {inviso_rt_meta_reply,Ref,Reply} -> Reply end.reply(To,Ref,Reply) -> To ! {inviso_rt_meta_reply,Ref,Reply}.%% -----------------------------------------------------------------------------%% =============================================================================%% Special API.%% =============================================================================%% write_ti(OutPut)=%% OutPut=binary()%% Makes an extra entry into the trace information file (ti-file). This is useful%% if a pid-alias association is learned in another way than through a meta traced%% function call. Note that this API can only be used locally at the node in%% question.write_ti(OutPut) -> catch ?MODULE ! {write_ti,OutPut}.%% -----------------------------------------------------------------------------%% =============================================================================%% API intended to be used on CallFuncs and RemoveFuncs.%% =============================================================================%% The reason there must be a special API for CallFuncs and RemoveFuncs are is%% that those functions are executed inside *this* process context. Hence they%% can not make function calls requiering this process to receive messages.%% Returns the tracer used for regular tracing. The reason this is implemented%% in this way is that this function is intended to be used in meta trace call-%% back functions. And there we can not have message passing API:s to the meta%% trace(!).get_tracer() -> get(tracer).%% -----------------------------------------------------------------------------%% Function equivalent to inviso_rt:tpm_ms/6. This function can *only* be used%% inside a CallFunc or a RemoveFunc.tpm_ms(Mod,Func,Arity,MSname,MS) -> case check_mfarity_exists(Mod,Func,Arity) of yes -> % Ok, and args must be ok then also. {ok,h_tpm_ms(Mod,Func,Arity,MSname,MS)}; no -> {error,not_initiated} end.%% -----------------------------------------------------------------------------tpm_ms_tracer(Mod,Func,Arity,MSname,MS) -> case check_mfarity_exists(Mod,Func,Arity) of yes -> % Ok, and args must be ok then also. NewMS=add_tracer(MS,get_tracer()), {ok,h_tpm_ms(Mod,Func,Arity,MSname,NewMS)}; no -> {error,not_initiated} end.%% -----------------------------------------------------------------------------%% Function that returns all MSname in use for Mod:Func/Aritylist_tpm_ms(Mod,Func,Arity) -> {ok,h_list_tpm_ms(Mod,Func,Arity)}.%% -----------------------------------------------------------------------------%% Function equivalent to inviso_rt:ctpm_ms/5. This function can *only* be used%% inside a CallFunc or a RemoveFunc.ctpm_ms(Mod,Func,Arity,MSname) -> h_ctpm_ms(Mod,Func,Arity,MSname), ok.%% -----------------------------------------------------------------------------%% =============================================================================%% The server implemenation.%% =============================================================================init(Parent,TiData,Tracer,InitPublLDmfa,RemovePublLDmf,CleanPublLDmf) -> process_flag(priority,high), % Since we may receive from many procs. register(?MODULE,self()), % So we can act as relay receiver. case open_traceinfo_file(TiData) of {ok,TI} -> % The ti.-file. TId=ets:new(?NAMED_MS_TAB,[named_table,set,protected]), PublLD=do_init_publ_ld(InitPublLDmfa), Parent ! {self(),ok}, put(tracer,Tracer), % Uggly quick fix! loop(Parent, Tracer, TI, mk_new_ld(InitPublLDmfa,RemovePublLDmf,CleanPublLDmf,TId), PublLD, now()); {error,Reason} -> Parent ! {self(),{error,Reason}} end.%% -----------------------------------------------------------------------------loop(Parent,Tracer,TI,LD,PrevPublLD,PrevCleanTime) -> {PublLD,CleanTime}=throw_old_failed(get_cleanpublldmf_ld(LD),PrevPublLD,PrevCleanTime), receive {{init_tpm,{Mod,Func,Arity},InitFunc,CallFunc,ReturnFunc,RemoveFunc},Ref,Parent} -> case check_mfarity_exists(Mod,Func,Arity) of no -> % Good then we can add it! case check_tpm_args(Mod,Func,Arity) of true -> % Args are ok. {NewLD,NewPublLD}= h_init_tpm(Mod,Func,Arity, InitFunc,CallFunc,ReturnFunc,RemoveFunc, TI,LD,PublLD), reply(Parent,Ref,ok), loop(Parent,Tracer,TI,NewLD,NewPublLD,CleanTime); false -> % Faulty arguments, reply(Parent,Ref,{error,bad_mfa}), loop(Parent,Tracer,TI,LD,PublLD,CleanTime) end; yes -> % If it already exists, cant init again. reply(Parent,Ref,{error,already_initiated}), loop(Parent,Tracer,TI,LD,PublLD,CleanTime) end; {{tpm,{Mod,Func,Arity,MS},InitFunc,CallFunc,ReturnFunc,RemoveFunc},Ref,Parent} -> case check_mfarity_exists(Mod,Func,Arity) of no -> % Good then we can add it! case check_tpm_args(Mod,Func,Arity) of true -> % Args are ok. {NewLD,NewPublLD,N}= h_tpm(Mod,Func,Arity,MS, InitFunc,CallFunc,ReturnFunc,RemoveFunc, TI,LD,PublLD), reply(Parent,Ref,{ok,N}), loop(Parent,Tracer,TI,NewLD,NewPublLD,CleanTime); false -> reply(Parent,Ref,{error,bad_mfa}), loop(Parent,Tracer,TI,LD,PublLD,CleanTime) end; yes -> reply(Parent,Ref,{error,already_initiated}), loop(Parent,Tracer,TI,LD,PublLD,CleanTime) end; {{tpm,{Mod,Func,Arity,MS}},Ref,Parent} -> case check_mfarity_exists(Mod,Func,Arity) of yes -> % Ok, and args must be ok then also. {NewLD,N}=h_tpm(Mod,Func,Arity,MS,LD), reply(Parent,Ref,{ok,N}), loop(Parent,Tracer,TI,NewLD,PublLD,CleanTime); no -> % Must be initiated before. reply(Parent,Ref,{error,not_initiated}), loop(Parent,Tracer,TI,LD,PublLD,CleanTime) end; {{tpm_tracer,{Mod,Func,Arity,MS},InitFunc,CallFunc,ReturnFunc,RemoveFunc},Ref,Parent} -> case check_mfarity_exists(Mod,Func,Arity) of no -> % Good then we can add it! case check_tpm_args(Mod,Func,Arity) of true -> % Args are ok. NewMS=add_tracer(MS,Tracer), {NewLD,NewPublLD,N}= h_tpm(Mod,Func,Arity,NewMS, InitFunc,CallFunc,ReturnFunc,RemoveFunc, TI,LD,PublLD), reply(Parent,Ref,{ok,N}), loop(Parent,Tracer,TI,NewLD,NewPublLD,CleanTime); false -> reply(Parent,Ref,{error,bad_mfa}), loop(Parent,Tracer,TI,LD,PublLD,CleanTime) end; yes -> reply(Parent,Ref,{error,already_initiated}), loop(Parent,Tracer,TI,LD,PublLD,CleanTime) end; {{tpm_tracer,{Mod,Func,Arity,MS}},Ref,Parent} -> case check_mfarity_exists(Mod,Func,Arity) of yes -> % Ok, and args must be ok then also. NewMS=add_tracer(MS,Tracer), {NewLD,N}=h_tpm(Mod,Func,Arity,NewMS,LD), reply(Parent,Ref,{ok,N}), loop(Parent,Tracer,TI,NewLD,PublLD,CleanTime); no -> % Must be initiated before. reply(Parent,Ref,{error,not_initiated}), loop(Parent,Tracer,TI,LD,PublLD,CleanTime) end; {{tpm_ms,{Mod,Func,Arity},MSname,MS},Ref,Parent} -> case check_mfarity_exists(Mod,Func,Arity) of yes -> % Ok, and args must be ok then also. reply(Parent,Ref,{ok,h_tpm_ms(Mod,Func,Arity,MSname,MS)}), loop(Parent,Tracer,TI,LD,PublLD,CleanTime); no -> reply(Parent,Ref,{error,not_initiated}), loop(Parent,Tracer,TI,LD,PublLD,CleanTime) end; {{tpm_ms_tracer,{Mod,Func,Arity},MSname,MS},Ref,Parent} -> case check_mfarity_exists(Mod,Func,Arity) of yes -> % Ok, and args must be ok then also. NewMS=add_tracer(MS,Tracer), reply(Parent,Ref,{ok,h_tpm_ms(Mod,Func,Arity,MSname,NewMS)}), loop(Parent,Tracer,TI,LD,PublLD,CleanTime); no -> reply(Parent,Ref,{error,not_initiated}), loop(Parent,Tracer,TI,LD,PublLD,CleanTime) end; {{ctpm_ms,{Mod,Func,Arity},MSname},Ref,Parent} -> reply(Parent,Ref,ok), h_ctpm_ms(Mod,Func,Arity,MSname), loop(Parent,Tracer,TI,LD,PublLD,CleanTime); {{ctpm,{Mod,Func,Arity}},Ref,Parent} -> case get_remove_func_ld(Mod,Func,Arity,LD) of false -> % Incorrect Mod:Func/Arity! reply(Parent,Ref,{error,bad_mfa}), loop(Parent,Tracer,TI,LD,PublLD,CleanTime); % Do nothing! MF -> % {M,F}, Func or 'void'. catch erlang:trace_pattern({Mod,Func,Arity},false,[meta]), NewPublLD=do_removefunc(MF,Mod,Func,Arity,PublLD), NewLD=ctpm_ld(Mod,Func,Arity,LD), reply(Parent,Ref,ok), loop(Parent,Tracer,TI,NewLD,NewPublLD,CleanTime) end; {suspend,Parent} -> % Removes all meta trace patterns. stop_all_meta_tracing(get_all_meta_funcs_ld(LD),PublLD,LD), do_remove_publ_ld(get_removepublldmf_ld(LD),PublLD), NewPublLD=do_init_publ_ld(get_initpublldmfa_ld(LD)), loop(Parent,Tracer,TI,reset_ld(LD),NewPublLD,CleanTime); {stop,Parent} -> % Make a controlled shutdown. stop_all_meta_tracing(get_all_meta_funcs_ld(LD),PublLD,LD), do_remove_publ_ld(get_removepublldmf_ld(LD),PublLD), close_traceinfo_file(TI); % And then simply terminate. {trace_ts,Pid,call,{M,F,Args},_TS} -> case handle_meta(get_call_func_ld(M,F,length(Args),LD),Pid,Args,PublLD) of {ok,NewPublLD,Output} when is_binary(Output) -> write_output(TI,Output), loop(Parent,Tracer,TI,LD,NewPublLD,CleanTime); {ok,NewPublLD,_} -> % No output to the ti-file this time. loop(Parent,Tracer,TI,LD,NewPublLD,CleanTime); _ -> % Not handled correct, not much to do. loop(Parent,Tracer,TI,LD,PublLD,CleanTime) end; {trace_ts,Pid,return_from,{M,F,Arity},Value,_TS} -> case handle_meta(get_return_func_ld(M,F,Arity,LD),Pid,Value,PublLD) of {ok,NewPublLD,Output} when is_binary(Output) -> write_output(TI,Output), loop(Parent,Tracer,TI,LD,NewPublLD,CleanTime); {ok,NewPublLD,_} -> % No output to the ti-file this time. loop(Parent,Tracer,TI,LD,NewPublLD,CleanTime); _ -> % Not handled correct, not much to do. loop(Parent,Tracer,TI,LD,PublLD,CleanTime) end; {relayed_meta,Bin} -> write_output(TI,Bin), loop(Parent,Tracer,TI,LD,PublLD,CleanTime); {write_ti,OutPut} -> write_output(TI,OutPut), loop(Parent,Tracer,TI,LD,PublLD,CleanTime); {get_state,Ref,From} -> % Debug function. reply(From,Ref,{ok,LD,PublLD}), loop(Parent,Tracer,TI,LD,PublLD,CleanTime); _Other -> loop(Parent,Tracer,TI,LD,PublLD,CleanTime) end.%% =============================================================================%% First level help functions.%% =============================================================================%% Function which opens the trace-information file(s). It must understand%% the tidata specification which is part of the tracerdata given to the%% runtime component during init_tracing.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?