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