inviso_tool_sh.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,375 行 · 第 1/5 页
ERL
1,375 行
%%%------------------------------------------------------------------------------
%%% File : inviso_tool_sh.erl
%%% Author : Lennart 謍man <lennart.ohman@st.se>
%%% Description :
%%%
%%% Created : 24 Oct 2005 by Lennart 謍man
%%%------------------------------------------------------------------------------
-module(inviso_tool_sh).
%% Inviso Session Handler.
%% This is the code for the session handler process. Its purpose is that we have
%% one session handler process for each trace session started through the
%% start_session inviso tool API. The session handler process is responsible for:
%%
%% -Knowing the state/status of all participating runtime components.
%% -Keeping storage of all tracerdata all our participants have used. This means
%% also to find out the tracerdata of runtime components connecting by them
%% selves.
%%
%% STORAGE STRATEGY
%% ----------------
%% The local information storage can be changed by two things. Either by executing
%% commands issued through our APIs. Or by receiving trace_event from the control
%% component. When we execute commands, a corresponding event will also follow.
%% Meaning that in those situations we are informed twice.
%% A simple strategy could be to wait for the event even when doing the changes
%% to the runtime components our self (through commands). But that may result in
%% a small time frame where someone might do yet another command and failing
%% because the local information storage is not uptodate as it would have been
%% expected to be. Therefore we always update the local storage when making changes
%% to a runtime component our selves. There will eventually be a double update
%% through an incoming event. But the storage must coop with that, preventing
%% inconsitancies to happend. An example of a strategy is that the tracerdata table
%% is a bag, not allowing for double entries of the same kind. Therefore a double
%% update is harmless there.
%% ------------------------------------------------------------------------------
%% Module wide constants.
%% ------------------------------------------------------------------------------
-define(LOCAL_RUNTIME,local_runtime). % Used as node name when non-disitrbuted.
-define(TRACING,tracing). % A state defined by the control component.
-define(RUNNING,running). % A status according to control componet.
-define(COPY_LOG_FROM,copy_log_from). % Common fileystem option.
%% ------------------------------------------------------------------------------
%% ------------------------------------------------------------------------------
%% API exports.
%% ------------------------------------------------------------------------------
-export([start_link/5,start_link/8]).
-export([cancel_session/1,stop_session/3]).
-export([reactivate/1,reactivate/2]).
-export([tpl/5,tpl/6,tpl/7,
tf/2,tf/3,
tpm_localnames/2,init_tpm/6,init_tpm/9,tpm/6,tpm/7,tpm/10,
tpm_ms/7,ctpm_ms/6,ctpm/5
]).
%% ------------------------------------------------------------------------------
%% ------------------------------------------------------------------------------
%% Internal exports.
%% ------------------------------------------------------------------------------
-export([init/1,handle_call/3,handle_info/2,terminate/2]).
-export([get_loopdata/1]).
%% ------------------------------------------------------------------------------
%% ------------------------------------------------------------------------------
%% Includes.
%% ------------------------------------------------------------------------------
-include_lib("kernel/include/file.hrl"). % Necessary for file module.
%% ------------------------------------------------------------------------------
%% ==============================================================================
%% Exported API functions.
%% ==============================================================================
%% start_link(From,NodeParams,CtrlNode,CtrlPid,SafetyCatches,NodesIn,NodesNotIn) =
%% {ok,Pid} | {error,Reason}
%% From= pid(), the initial client expecting the reply.
%% NodeParams=[{Node,TracerData},{Node,TracerData,Opts}...]
%% CtrlNode=atom() | 'void', the node where the trace control component is.
%% CtrlPid=pid(), the pid of the trace control component.
%% SafetyCatches=
%% Dir=string(), where to place fetched logs and the merged log.
%% Dbg=debug structure.
%% NodesIn=[Node,...], list of nodes already in another session.
%% NodesNotIn=[Node,...], list of nodes not in another session.
%%
%% Starts a session-handler. It keeps track of the the state and status of all
%% participating runtime components. Note that there is a non-distributed case too.
%% In the non-distributed case there is no things such as CtrlNode.
start_link(From,TracerData,CtrlPid,SafetyCatches,Dbg) ->
gen_server:start_link(?MODULE,
{self(),From,TracerData,CtrlPid,SafetyCatches,Dbg},
[]).
start_link(From,NodeParams,CtrlNode,CtrlPid,SafetyCatches,Dbg,NodesIn,NodesNotIn) ->
gen_server:start_link(?MODULE,
{self(),From,NodeParams,CtrlNode,CtrlPid,
SafetyCatches,Dbg,NodesIn,NodesNotIn},
[]).
%% ------------------------------------------------------------------------------
%% Stops tracing where it is ongoing. Fetches all logfiles.
stop_session(SID,Dir,Prefix) ->
gen_server:call(SID,{stop_session,Dir,Prefix}).
%% ------------------------------------------------------------------------------
%% stop_session(SID) = ok
%%
%% Cancels the session brutaly. All runtime components are made to stop tracing,
%% all local log files are removed using the tracerdata we know for them.
cancel_session(SID) ->
gen_server:call(SID,cancel_session).
%% ------------------------------------------------------------------------------
%% reactivate(SID) = {ok,
%% reactivate(SID,Nodes) = {ok,NodeResults} | {error,Reason}.
%% SID=session id, pid().
%% Nodes=[Node,...]
%% NodeResult=[{Node,Result},...]
%% Result={Good,Bad}
%% Good,Bad=integer(), the number of redone activities.
%%
%% Function which reactivates runtime components being suspended. This is done
%% replaying all trace flags (in the correct order) to the corresponding nodes.
%% Note that this may also mean turning flags off. Like first turning them on
%% then off a split second later.
reactivate(SID) ->
gen_server:call(SID,reactivate). %% NOT IMPLEMENTED YET.
reactivate(SID,Nodes) ->
gen_server:call(SID,{reactivate,Nodes}).
%% ------------------------------------------------------------------------------
%% tpl(SessionID,Mod,Func,Arity,MS)=
%% tpl(SessionID,Mod,Func,Arity,MS,Opts)={ok,N}|{error,Reason}.
%% tpl(SessionID,Nodes,Mod,Func,Arity,MS)=
%% tpl(SessionID,Nodes,Mod,Func,Arity,MS,Opts)={ok,Result}|{error,Reason}
%% Mod='_' | ModuleName | ModRegExp | {DirRegExp,ModRegExp}
%% ModRegExp=DirRegExp= string()
%% Func='_' | FunctionName
%% Arity='_' | integer()
%% MS=[] | false | a match specification
%% Opts=[Opts,...]
%% Opt={arg,Arg}, disable_safety, {expand_regexp_at,NodeName}, only_loaded
%% Nodes=[NodeName,...]
tpl(SID,Mod,Func,Arity,MS) ->
gen_server:call(SID,{tp,tpl,Mod,Func,Arity,MS,[]}).
tpl(SID,Mod,Func,Arity,MS,Opts) when list(MS);MS==true;MS==false ->
gen_server:call(SID,{tp,tpl,Mod,Func,Arity,MS,Opts});
tpl(SID,Nodes,Mod,Func,Arity,MS) when integer(Arity);Arity=='_' ->
gen_server:call(SID,{tp,tpl,Nodes,Mod,Func,Arity,MS,[]}).
tpl(SID,Nodes,Mod,Func,Arity,MS,Opts) ->
gen_server:call(SID,{tp,tpl,Nodes,Mod,Func,Arity,MS,Opts}).
%% ------------------------------------------------------------------------------
%% ctpl(SessionID,Nodes,Mod,Func,Arity)=
%% See tpl/X for arguments.
%%
%% Removes local trace-patterns from functions.
ctpl(SID,Nodes,Mod,Func,Arity) ->
gen_server:call(SID,{ctp,ctpl,Nodes,Mod,Func,Arity}).
%% ------------------------------------------------------------------------------
tpm_localnames(SID,Nodes) ->
gen_server:call(SID,{tpm_localnames,Nodes}).
tpm_globalnames(SID,Nodes) ->
gen_server:call(SID,{tpm_globalnames,Nodes}).
init_tpm(SID,Nodes,Mod,Func,Arity,CallFunc) ->
gen_server:call(SID,{init_tpm,Nodes,Mod,Func,Arity,CallFunc}).
init_tpm(SID,Nodes,Mod,Func,Arity,InitFunc,CallFunc,ReturnFunc,RemoveFunc) ->
gen_server:call(SID,
{init_tpm,Nodes,Mod,Func,Arity,InitFunc,CallFunc,ReturnFunc,RemoveFunc}).
tpm(SID,Nodes,Mod,Func,Arity,MS) ->
gen_server:call(SID,{tpm,Nodes,Mod,Func,Arity,MS}).
tpm(SID,Nodes,Mod,Func,Arity,MS,CallFunc) ->
gen_server:call(SID,{tpm,Nodes,Mod,Func,Arity,MS,CallFunc}).
tpm(SID,Nodes,Mod,Func,Arity,MS,InitFunc,CallFunc,ReturnFunc,RemoveFunc) ->
gen_server:call(SID,{tpm,Nodes,Mod,Func,Arity,MS,InitFunc,CallFunc,ReturnFunc,RemoveFunc}).
tpm_ms(SID,Nodes,Mod,Func,Arity,MSname,MS) ->
gen_server:call(SID,{tpm_ms,Nodes,Mod,Func,Arity,MSname,MS}).
ctpm_ms(SID,Nodes,Mod,Func,Arity,MSname) ->
gen_server:call(SID,{tpm_ms,Nodes,Mod,Func,Arity,MSname}).
ctpm(SID,Nodes,Mod,Func,Arity) ->
gen_server:call(SID,{ctpm,Nodes,Mod,Func,Arity}).
%% ------------------------------------------------------------------------------
%% tf(SessionID,Nodes,TraceConfList)=
%% TraceConfList=[{PidSpec,Flags},...]
%% PidSpec=pid()|atom()|all|new|existing
%% Flags=[Flag,...]
tf(SID,TraceConfList) ->
gen_server:call(SID,{tf,TraceConfList}).
tf(SID,Nodes,TraceConfList) ->
gen_server:call(SID,{tf,Nodes,TraceConfList}).
%% ------------------------------------------------------------------------------
get_loopdata(SID) ->
gen_server:call(SID,get_loopdata).
%% ------------------------------------------------------------------------------
%% ==============================================================================
%% Genserver call-backs.
%% ==============================================================================
%% Initial function for the session handler process. The nodes participating in
%% the session must previously have been added to our control component by the tool.
%% The session handler first finds out the state/status of the specified runtime
%% components, then it tries to initiate tracing on those where it is applicable.
%% Note that a reply to the initial (tool)client is done from here instead from
%% the tool-server.
init({Parent,From,TracerData,CtrlPid,SafetyCatches,Dbg}) -> % The non-distributed case.
{ok,StateStatus}=init_rtcomponent_states([],void,CtrlPid,[?LOCAL_RUNTIME]),
case is_tool_internal_tracerdata(TracerData) of
false -> % We shall initiate local runtime.
case inviso:init_tracing(TracerData) of
ok ->
gen_server:reply(From,{ok,{self(),ok}}),
{ok,mk_ld(Parent,
void,
CtrlPid,
to_rtstates([{?LOCAL_RUNTIME,{tracing,?RUNNING},[]}]),
[{?LOCAL_RUNTIME,TracerData}],
[],
SafetyCatches,
Dbg)};
{error,Reason} -> % It might have become suspended?!
gen_server:reply(From,{error,Reason}),
{ok,mk_ld(Parent,
void,
CtrlPid,
to_rtstates([{?LOCAL_RUNTIME,StateStatus,[]}]),
[{?LOCAL_RUNTIME,TracerData}],
[],
SafetyCatches,
Dbg)}
end;
true -> % We shall not pass this one on.
gen_server:reply(From,{ok,{self(),ok}}), % Then it is ok.
{ok,mk_ld(Parent,
void,
CtrlPid,
to_rtstates([{?LOCAL_RUNTIME,StateStatus,[]}]),
[],
[?LOCAL_RUNTIME],
SafetyCatches,
Dbg)}
end;
init({Parent,From,NodeParams,CtrlNode,CtrlPid,SafetyCatches,Dbg,NodesIn,NodesNotIn}) ->
case init_rtcomponent_states(NodeParams,CtrlNode,CtrlPid,NodesNotIn) of
{ok,States} -> % A list of {Node,{State,Status},Opts}.
{NodeParams2,Nodes2}=remove_nodeparams(NodesIn,NodeParams),
case inviso_tool_lib:inviso_cmd(CtrlNode,init_tracing,[NodeParams2]) of
{ok,Result} -> % Resulted in state changes!
RTStates=set_tracing_rtstates(to_rtstates(States),Result),
ReplyValue=init_fix_resultnodes(NodesIn,Nodes2,Result),
gen_server:reply(From,{ok,{self(),ReplyValue}}),
{ok,mk_ld(Parent,CtrlNode,CtrlPid,RTStates,
NodeParams2,Nodes2,SafetyCatches,Dbg)};
{error,Reason} -> % Some general failure.
inviso_tool_lib:inviso_cmd(CtrlNode,unsubscribe,[]),
gen_server:reply(From,{error,{init_tracing,Reason}}),
{stop,{init_tracing,Reason}};
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?