%% ``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: Ann-Marie Löf, ann-marie.lof@st.se %% Lennart Öhman, lennart.ohman@st.se %% %% Description: API module for the inviso system. %% Inviso consists of a control component and possibly one or more runtime %% components. This module is simply the API to the inviso system. All normal %% calls goes through the control component. %% ------------------------------------------------------------------------------ -module(inviso). %% ------------------------------------------------------------------------------ %% Exported API functions. %% ------------------------------------------------------------------------------ -export([start/0, start/1, add_node/1, add_node/2, add_node_if_ref/1, add_node_if_ref/2, add_nodes/2, add_nodes/3, add_nodes_if_ref/2, add_nodes_if_ref/3, change_options/1, change_options/2, init_tracing/1, init_tracing/2, stop_tracing/0, stop_tracing/1, clear/0, clear/1, clear/2, flush/0,flush/1, stop/0, stop_nodes/0, stop_nodes/1, stop_all/0, tp/1,tp/2,tp/4,tp/5,tp/6, tpl/1,tpl/2,tpl/4,tpl/5,tpl/6, tpm_localnames/0,tpm_localnames/1,tpm_globalnames/0,tpm_globalnames/1, init_tpm/4,init_tpm/5,init_tpm/7,init_tpm/8, tpm/4,tpm/5,tpm/6,tpm/8,tpm/9, tpm_tracer/4,tpm_tracer/5,tpm_tracer/6,tpm_tracer/8,tpm_tracer/9, tpm_ms/5,tpm_ms/6, tpm_ms_tracer/5,tpm_ms_tracer/6, ctpm_ms/4,ctpm_ms/5,ctpm/3,ctpm/4, ctpm_localnames/0,ctpm_localnames/1,ctpm_globalnames/0,ctpm_globalnames/1, ctp/1,ctp/2,ctp/3,ctp/4, ctpl/1,ctpl/2,ctpl/3,ctpl/4, tf/1, tf/2, tf/3, ctf/1, ctf/2, ctf/3, ctp_all/0, ctp_all/1, ctf_all/0, ctf_all/1, suspend/1, suspend/2, cancel_suspension/0, cancel_suspension/1, get_status/0, get_status/1, get_tracerdata/0, get_tracerdata/1, list_logs/0, list_logs/1, fetch_log/2, fetch_log/3, fetch_log/4, delete_log/0, delete_log/1, delete_log/2, subscribe/0, subscribe/1, unsubscribe/0, unsubscribe/1]). %% debuging inviso -export([state/0, state/1]). %% ------------------------------------------------------------------------------ %% Macros used in this module. %% ------------------------------------------------------------------------------ -define(CONTROLLER,inviso_c). %% Some function calls to runtime components may take long time, we must wait %% longer than the standard timeout for a reply from the control component. -define(CALL_TIMEOUT,60000). %% ------------------------------------------------------------------------------ %% ============================================================================= %% CONTROL COMPONENT API FUNCTIONS. %% ============================================================================= %% start()={ok,pid()}|{error,Reason} %% start(Options)={ok,pid()}|{error,Reason} %% Options=[Option,...], the options will be default options to runtime components %% later started. See add_node about available options. %% There are also options consumed by the control component: %% Option={subscribe,pid()} %% %% Starts a control component process on the local node. A control component must %% be started before runtime components can be started manually. start() -> gen_server:start({local,?CONTROLLER},?CONTROLLER,{self(),[]},[]). start(Options) -> gen_server:start({local,?CONTROLLER},?CONTROLLER,{self(),Options},[]). %% ----------------------------------------------------------------------------- %% add_node(Reference)=NodeResult|{error, Reason} %% add_node(Reference,Options)=NodeResult|{error, Reason} %% Reference=PreviousReference = term(), %% Options=[Option,...], %% Option={dependency,Dep} %% Dep=integer()|'infinity'; The timeout before the runtime component will %% terminate if abandoned by this control component. %% Option={overload,Overload}; controls how and how often overload checks shall %% be performed. Instead of specifying a tuple, the atom 'overload' can be %% specified to state no loadcheck. The result will actually be the same %% if 'infinity' is used as intervall. It is sometimes necessary to %% initialize the overlaod check. This can be done with InitMFA. The %% loadchecker must then also be removed by using a RemoveMFA. %% Overload=Iterval (int() in milliseconds) | %% {LoadMF,Interval}|{LoadMF,Interval,InitMFA,RemoveMFA} %% LoadMF={Mod,Func} %% InitMFA,RemoveMFA={Mod,Func,ArgList}|void %% If just Interval is used, it means using a default overload check. %% NodeResult={ok,NAns}|{error,Reason} %% NAns=new|{adopted,State,Status,PreviousReference}|already_added %% Status = running | {suspended, SReason} %% %% Starts or tries to connect to an existing runtime component at the local %% node, regardless if the system is distributed or not. %% Options will override any default options specified at start-up of the %% control component. add_node(Reference) -> gen_server:call(?CONTROLLER,{add_nodes,[node()],[],Reference,any_ref},?CALL_TIMEOUT). add_node(Reference,Options) when is_list(Options) -> gen_server:call(?CONTROLLER,{add_nodes,[node()],Options,Reference,any_ref},?CALL_TIMEOUT). %% ----------------------------------------------------------------------------- %% add_node(Reference)=NodeResult|{error,{wrong_reference,OtherRef}}|{error,Reason} %% add_node(Reference,Options)=NodeResult|{error,{wrong_reference,OtherRef}}| %% {error,Reason} %% %% As add_node/1,/2 but will only connect to an already existing runtime component %% if its reference is the same as the one given as argument. add_node_if_ref(Reference) -> gen_server:call(?CONTROLLER,{add_nodes,[node()],[],Reference,if_ref},?CALL_TIMEOUT). add_node_if_ref(Reference,Options) when is_list(Options) -> gen_server:call(?CONTROLLER,{add_nodes,[node()],Options,Reference,if_ref},?CALL_TIMEOUT). %% ----------------------------------------------------------------------------- %% add_nodes(Nodes,Reference)={ok,NodeResults}|{error,Reason} %% add_nodes(Nodes,Reference,Options)={ok,NodeResults}|{error,Reason} %% Nodes=[Node,...], %% NodeResults=[{Node,NodeResult},...] %% %% As add_node/1,/2 but for the nodes specified in Nodes. %% It is possible but not intended to use this function in a non-distributed %% system. By speicifying node() as the node where the runtime component shall %% be started. The return value will then follow the rules of non distributed %% returnvalues and not have a node indicator. add_nodes(Nodes,Reference) when is_list(Nodes) -> gen_server:call(?CONTROLLER,{add_nodes,Nodes,[],Reference,any_ref},?CALL_TIMEOUT). add_nodes(Nodes,Reference,Options) when is_list(Nodes),is_list(Options) -> gen_server:call(?CONTROLLER,{add_nodes,Nodes,Options,Reference,any_ref},?CALL_TIMEOUT). %% ----------------------------------------------------------------------------- %% add_nodes_if_ref(Nodes,Reference)={ok,NodeResults}|{error,Reason} %% add_nodes_if_ref(Nodes,Reference,Options)={ok,NodeResults}|{error,Reason} %% %% As add_nodes/2,/3 but will only connect to an already existing runtime component %% if its reference is the same as the one given as argument. add_nodes_if_ref(Nodes,Reference) when is_list(Nodes) -> gen_server:call(?CONTROLLER,{add_nodes,Nodes,[],Reference,if_ref},?CALL_TIMEOUT). add_nodes_if_ref(Nodes,Reference,Options) when is_list(Nodes),is_list(Options) -> gen_server:call(?CONTROLLER,{add_nodes,Nodes,Options,Reference,if_ref},?CALL_TIMEOUT). %% ----------------------------------------------------------------------------- %% change_options(Options)={ok,NodeResults}|NodeResult|{error,Reason} %% change_options(Nodes,Options)={ok,NodeResults}|{error,Reason} %% Nodes=[Node,...], %% Options= see add_node and add_nodes on available options. %% %% Change options on all or specified Nodes. This may result in for instance %% reinitialization of overloadcheck. change_options(Options) when is_list(Options) -> gen_server:call(?CONTROLLER,{change_options,all,Options},?CALL_TIMEOUT). change_options(Nodes,Options) when is_list(Nodes),is_list(Options) -> gen_server:call(?CONTROLLER,{change_options,Nodes,Options},?CALL_TIMEOUT). %% ----------------------------------------------------------------------------- %% init_tracing(TracerData)={ok,[{Node,NodeResult}]} | NodeResult | {error,Reason} %% init_tracing(TracerList)={ok,[{Node,NodeResult}]} | {error,Reason} %% init_tracing(Nodes,TracerData)={ok,[{Node,NodeResult}]}|{error,Reason} %% TracerData = [{trace,LogTD} [,{ti,TiTD}]}] | LogTD %% LogTD = {HandlerFun,Data} | collector | {relayer,pid()} | %% {relayer,CollectingNode} | {ip,IPPortParameters} | %% {file,FilePortParameters} %% TiTD = {file,FileName} | {file,FileName,TiMFA} %% TiMFA = {Module,Function,ArgumentList} initiating a private loopdata %% inside the meta-tracer. %% TracerList = [{Node,TracerData}], %% IPPortParameters = Portno | {Portno, Qsiz} %% Qsiz = %% FilePortParameters = {Filename, wrap, Tail, {time, WrapTime}, WrapCnt} | %% {FileName, wrap, Tail, WrapSize, WrapCnt} | %% {FileName, wrap, Tail, WrapSize} | %% {FileName, wrap, Tail} | FileName %% Tail =/= "" %% HandlerFun is a function taking 2 arguments. %% Nodes = [node()], %% CollectingNode = pid() | node(), %% NodeResult = {ok,LogResults} | {error, NReason} %% LogResults=[LogResult,...] %% LogResult={trace_log,LogRes} | {ti_log,LogRes} %% LogRes=ok|{error,Reason} %% %% Starts tracing on the nodes specified. If just providing a TracerData tracing %% will be initiated on all our nodes. If it is the non distributed case, that %% means only on the local non distributed node. %% %% {HandlerFun,Data} %% Will use the runtime components own process as tracer and handle all %% incomming trace message using HandlerFun. %% {relayer,CollectingNode} %% The runtime component addressed will act tracer and relay all incomming trace %% messages to Node or Pid, if CollectingNode is not a traced node connected %% to the controll component, the init_tracing call will return an error. %% Note that {relayer, Node} only is syntactical sugar for %% {relayer, rpc:call(Node,erlang,whereis,[inviso_rt])} %% collector %% The runtime component is used as tracer or collector of relayed %% trace messages using the default handler writing them to io. %% ip | file - will open a trace-port on Node using PortParameters init_tracing(TracerDataList) -> gen_server:call(?CONTROLLER,{init_tracing,TracerDataList},?CALL_TIMEOUT). init_tracing(Nodes,TracerData) when is_list(Nodes) -> gen_server:call(?CONTROLLER,{init_tracing,Nodes,TracerData},?CALL_TIMEOUT). %% ----------------------------------------------------------------------------- %% stop_tracing(Nodes)={ok,NodeResults}|{error,Reason} %% stop_tracing()={ok,NodeResults}|NodeResult %% Nodes=[Node,...], %% NodeResults=[{Node,NodeResult},...] %% NodeResult={ok,State}|{error,Reason} %% State=new|idle %% Stops tracing on all or specified Nodes. Flushes trace buffert, %% closes trace port and removes all trace flags and meta-patterns. %% The nodes are called in parallel. stop_tracing() -> gen_server:call(?CONTROLLER,{stop_tracing,all},?CALL_TIMEOUT). stop_tracing(Nodes) when is_list(Nodes) -> gen_server:call(?CONTROLLER,{stop_tracing,Nodes},?CALL_TIMEOUT). %% ----------------------------------------------------------------------------- %% clear()={ok,NodeResults}|NodeResult %% clear(Nodes,Options)={ok,NodeResults}|{error,Reason} %% clear(Options)={ok,NodeResults}|NodeResult|{error,Reason} %% Nodes=[Node,...], %% Options=[Option,...], %% Option=keep_trace_patterns|keep_log_files %% NodeResults=[{Node,NodeResult},...] %% NodeResult={ok,{new,Status}}|{error,Reason} %% Status=running|{suspended,SReason} %% %% Stops all tracing including removing meta-trace patterns. If the node is tracing %% or idle, logs belonging to the current tracerdata are removed. Hence the node %% is returned to state 'new'. Note that node can still be suspended. clear() -> gen_server:call(?CONTROLLER,{clear,all,[]},?CALL_TIMEOUT). clear(Nodes) when is_list(Nodes) -> gen_server:call(?CONTROLLER,{clear,Nodes,[]},?CALL_TIMEOUT). clear(Nodes,Options) when is_list(Nodes),is_list(Options) -> gen_server:call(?CONTROLLER,{clear,Nodes,Options},?CALL_TIMEOUT). %% ----------------------------------------------------------------------------- %% flush()={ok,NodeResults} | NodeResult %% flush(Nodes)={ok,NodeResults} %% Nodes=[Node,...] %% NodeResults=[{Node,NodeResult},...] %% NodeResult=ok | {error,Reason} %% Sends a flush request to the trace-port driver on the nodes in Nodes. %% There will be an error for nodes that are not tracing. It is not an error to %% try to flush runtime components not using a trace-port. flush() -> gen_server:call(?CONTROLLER,{flush,all},?CALL_TIMEOUT). flush(Nodes) when is_list(Nodes) -> gen_server:call(?CONTROLLER,{flush,Nodes},?CALL_TIMEOUT). %% ----------------------------------------------------------------------------- %% stop()=shutdown %% %% Stops the controll component. Runtime components are left as is. They will %% behave according to their dependency values. stop() -> case catch gen_server:call(?CONTROLLER,stop,?CALL_TIMEOUT) of shutdown -> shutdown; {'EXIT',{noproc,_}} -> shutdown; {'EXIT',Reason} -> exit(Reason) end. %% ----------------------------------------------------------------------------- %% stop_nodes()={ok,NodeResults}|NodeResult %% stop_nodes(Nodes)={ok,NodeResults}|{error,Reason} %% NodeResults=[{Node,NodeResult},...] %% NodeResult=ok|{error,Reason} %% %% Stops runtime component on Nodes. stop_nodes/0 will if the control component %% is running on a distributed node stop all runtime components. And if running %% on a non distributed node, stop the local and only runtime component. stop_nodes() -> gen_server:call(?CONTROLLER,{stop_nodes,all},?CALL_TIMEOUT). stop_nodes(Nodes) when is_list(Nodes) -> gen_server:call(?CONTROLLER,{stop_nodes,Nodes},?CALL_TIMEOUT). %% ------------------------------------------------------------------------------ %% stop_all()={ok,NodeResults}|NodeResult %% NodeResults=[{Node,NodeResult},...] %% NodeResult=ok|{error,Reason} %% %% A combination of stop/0 and stop_nodes/0. stop_all() -> gen_server:call(?CONTROLLER, stop_all,?CALL_TIMEOUT). %% ------------------------------------------------------------------------------ %% tp(Nodes,Module,Function,Arity,MatchSpec,Opts)={ok,NodeResults}|{error,Reason} %% tp(Nodes,Module,Function,Arity,MatchSpec)={ok,NodeResults}|{error,Reason} %% tp(Module,Function,Arity,MatchSpec)={ok,NodeResults}|NodeResult|{error,Reason} %% tp(Nodes,PatternList)={ok,NodeResults}|{error,Reason} %% tp(PatternList)={ok,NodeResults}|NodeResult|{error,Reason} %% Nodes=[Node,...] %% Module,Function=atom() | '_' %% Arity=integer() | '_' %% MatchSpec=true|false|[]| matchspec() %% PatternList=[Pattern,...], %% Pattern={Module,Function,Arity,MatchSpec,Opts}, %% Opts=[Opt,...] %% Opt='only_loaded'; means that the runtime component shall not try to load %% a module should it not already be present in the runtime system. %% NodeResults=[NodeResult,...] %% NodeResult={ok,[Ans]}|{error,Reason}, %% Ans=integer()|{error,Reason} %% %% Set trace pattern (global) on specified or all Nodes. The integer replied %% if the call was successfully describes the matched number of functions. %% The functions without a Nodes argument means all nodes, in a non-distributed %% environment it means the local node. %% When calling several nodes, the nodes are called in parallel. tp(Nodes,Module,Function,Arity,MatchSpec,Opts) -> trace_pattern(Nodes,[{Module,Function,Arity,MatchSpec,Opts}],[global]). tp(Nodes,Module,Function,Arity,MatchSpec) when is_list(Nodes) -> trace_pattern(Nodes,[{Module,Function,Arity,MatchSpec,[]}],[global]); tp(Module,Function,Arity,MatchSpec,Opts) when is_atom(Module) -> trace_pattern(all,[{Module,Function,Arity,MatchSpec,Opts}],[global]). tp(Module,Function,Arity,MatchSpec) -> trace_pattern(all,[{Module,Function,Arity,MatchSpec,[]}],[global]). tp(Nodes,PatternList) -> trace_pattern(Nodes,PatternList,[global]). tp(PatternList) -> trace_pattern(all,PatternList,[global]). %% ----------------------------------------------------------------------------- %% tpl(Nodes,Module,Function,Arity,MatchSpec)={ok,NodeResults}|{error,Reason} %% tpl(Module,Function,Arity,MatchSpec)={ok,NodeResults}|NodeResult|{error,Reason} %% tpl(Nodes,PatternList)={ok,NodeResults}|{error,Reason} %% tpl(PatternList)={ok,NodeResults}|NodeResult|{error,Reason} %% see tp/X for description. %% %% Set trace pattern (local) on specified or all Nodes. The integer replied %% if the command was successfully describes the matched number of functions. %% The functions without a Nodes argument means all nodes, in a non-distributed %% environment it means the local node. %% When calling several nodes, the nodes are called in parallel. tpl(Nodes,Module,Function,Arity,MatchSpec,Opts) -> trace_pattern(Nodes,[{Module,Function,Arity,MatchSpec,Opts}],[local]). tpl(Nodes,Module,Function,Arity,MatchSpec) when is_list(Nodes) -> trace_pattern(Nodes,[{Module,Function,Arity,MatchSpec,[]}],[local]); tpl(Module,Function,Arity,MatchSpec,Opts) when is_atom(Module) -> trace_pattern(all,[{Module,Function,Arity,MatchSpec,Opts}],[local]). tpl(Module,Function,Arity,MatchSpec) -> trace_pattern(all,[{Module,Function,Arity,MatchSpec,[]}],[local]). tpl(Nodes, PatternList) -> trace_pattern(Nodes,PatternList,[local]). tpl(PatternList) -> trace_pattern(all,PatternList,[local]). %% ----------------------------------------------------------------------------- %% ctp(Nodes,Module,Function,Arity)={ok,NodeResults}|{error,Reason} %% ctp(Module,Function,Arity)={ok,NodeResults}|NodeResult|{error,Reason} %% ctp(Nodes,PatternList)={ok,NodeResults}|{error,Reason} %% ctp(PatternList)={ok,NodeResults}|NodeResult|{error,Reason} %% PatternList=[{Mod,Func,Arity},...] %% see tp/X for other argument descriptions. %% %% Clear trace pattern (global) on specified or all Nodes. The integer replied %% if the call was successfully describes the matched number of functions. %% The functions without a Nodes argument means all nodes, in a non-distributed %% environment it means the local node. %% When calling several nodes, the nodes are called in parallel. ctp(Nodes,Module,Function,Arity) -> trace_pattern(Nodes,[{Module,Function,Arity,false,[only_loaded]}],[global]). ctp(Module,Function,Arity) -> trace_pattern(all,[{Module,Function,Arity,false,[only_loaded]}],[global]). ctp(Nodes,PatternList) when is_list(PatternList) -> trace_pattern(Nodes, lists:map(fun({M,F,A})->{M,F,A,false,[only_loaded]} end,PatternList), [global]). ctp(PatternList) when is_list(PatternList) -> trace_pattern(all, lists:map(fun({M,F,A})->{M,F,A,false,[only_loaded]} end,PatternList), [global]). %% ----------------------------------------------------------------------------- %% ctpl(Nodes,Module,Function,Arity)={ok,NodeResults}|{error,Reason} %% ctpl(Module,Function,Arity)={ok,NodeResults}|NodeResult|{error,Reason} %% ctpl(Nodes,PatternList)={ok,NodeResults}|{error,Reason} %% ctpl(PatternList)={ok,NodeResults}|NodeResult|{error,Reason} %% see ctp/X for argument description. %% %% Clear trace pattern (local) on specified or all Nodes. The integer replied %% if the call was successfully describes the matched number of functions. %% The functions without a Nodes argument means all nodes, in a non-distributed %% environment it means the local node. %% When calling several nodes, the nodes are called in parallel. ctpl(Nodes,Module,Function,Arity) -> trace_pattern(Nodes,[{Module,Function,Arity,false,[only_loaded]}],[local]). ctpl(Module,Function,Arity) -> trace_pattern(all,[{Module,Function,Arity,false,[only_loaded]}],[local]). ctpl(Nodes,PatternList) when is_list(PatternList) -> trace_pattern(Nodes, lists:map(fun({M,F,A})->{M,F,A,false,[only_loaded]} end,PatternList), [local]). ctpl(PatternList) when is_list(PatternList) -> trace_pattern(all, lists:map(fun({M,F,A})->{M,F,A,false,[only_loaded]} end,PatternList), [local]). %% ----------------------------------------------------------------------------- %% Help function doing the control component calling for all tp/X, tpl/X, ctp/X %% and ctpl/X functions. trace_pattern(Nodes,Patterns,FlagList) -> gen_server:call(?CONTROLLER, {trace_pattern, Nodes, Patterns, FlagList},?CALL_TIMEOUT). %% ----------------------------------------------------------------------------- %% ----------------------------------------------------------------------------- %% tf(Nodes,PidSpec,FlagList)={ok,NodeResults}|{error,Reason} %% tf(PidSpec,FlagList)={ok,NodeResults}|NodeResult|{error,Reason} %% tf(Nodes,TraceConfList)={ok,NodeResults}|{error,Reason} %% tf(NodeTraceConfList)={ok,NodeResults}|{error,Reason} %% tf(TraceConfList)={ok,NodeResults}|NodeResult|{error,Reason} %% Nodes=[Node,...], %% NodeTraceConfList=[{Node,TraceConfList}] %% TraceConfList=[{PidSpec,FlagList},...], %% FlagList=[Flags], %% PidSpec=all|new|existing|pid()|locally_registered_name() %% Flags= all process trace flags allowed. %% NodeResult={ok,[Ans]}|{error,Reason}, %% Ans=integer() | {error,Reason} %% %% Set process trace flags on processes on all or specified Nodes. The integer %% return if the call was successfully describes the matched number of processes. %% The functions without a Nodes argument means all nodes, in a non-distributed %% environment it means the local node. %% There are many combinations which does not make musch scense. For instance %% specifying a certain pid at all nodes. Or an empty TraceConfList for all %% nodes. %% When calling several nodes, the nodes are called in parallel. tf(Nodes,PidSpec,FlagList) when is_list(Nodes),is_list(FlagList) -> trace_flags(Nodes,[{PidSpec, FlagList}],true). tf(Nodes,TraceConfList) when is_list(Nodes),is_list(TraceConfList) -> trace_flags(Nodes,TraceConfList,true); tf(PidSpec,FlagList) when is_list(FlagList) -> trace_flags(all,[{PidSpec,FlagList}],true). tf(ArgList) when is_list(ArgList) -> % This one has triple functionality! case ArgList of [{_Process,Flags}|_] when is_list(Flags),is_atom(hd(Flags))-> % A call to all nodes. trace_flags(all,ArgList,true); [{_Node,TraceConfList}|_] when is_list(TraceConfList),is_tuple(hd(TraceConfList)) -> trace_flags(ArgList,true); [{_Node,_TraceConfList,_How}|_] -> trace_flags(ArgList); [] -> % Stupid but allowed. trace_flags(all,ArgList,true) % Actually doesn't matter which we choose. end. %% ----------------------------------------------------------------------------- %% ctf(Nodes,PidSpec,FlagList)={ok,NodeResults}|{error,Reason} %% ctf(PidSpec,FlagList)={ok,NodeResults}|NodeResult|{error,Reason} %% ctf(Nodes,TraceConfList)={ok,NodeResults}|{error,Reason} %% ctf(TraceConfList)={ok,NodeResults}|NodeResult|{error,Reason} %% see tf/X for arguments. %% %% Clear process trace flags on all or specified Nodes. The integer replied %% if the command was successfully describes the matched number of processes. %% The functions without a Nodes argument means all nodes, in a non-distributed %% environment it means the local node. %% When calling several nodes, the nodes are called in parallel. ctf(Nodes,PidSpec,FlagList) when is_list(Nodes),is_list(FlagList) -> trace_flags(Nodes,[{PidSpec,FlagList}],false). ctf(Nodes,TraceConfList) when is_list(Nodes),is_list(TraceConfList) -> trace_flags(Nodes,TraceConfList,false); ctf(PidSpec,FlagList) when is_list(FlagList) -> trace_flags(all,[{PidSpec,FlagList}],false). ctf(TraceConfList) when is_list(TraceConfList) -> trace_flags(all,TraceConfList,false). %% ----------------------------------------------------------------------------- %% ctf_all(Nodes)={ok,NodeResults}|{error,Reason} %% ctf_all()={ok,NodeResults}|NodeResult|{error,Reason} %% Nodes=[Node,...], %% NodeResults=[{Node,NodeResult},...] %% NodeResult=ok|{error,Reason}, %% %% Clears all trace flags on all or specified nodes. Just for convenience. ctf_all() -> gen_server:call(?CONTROLLER,{trace_flags,all,[{all,[all]}],false},?CALL_TIMEOUT). ctf_all(Nodes) -> gen_server:call(?CONTROLLER,{trace_flags,Nodes,[{all,[all]}],false},?CALL_TIMEOUT). %% ----------------------------------------------------------------------------- %% Help function to tf/X and ctf/X making the call to the control component. trace_flags(Nodes, TraceConfList, How) -> gen_server:call(?CONTROLLER, {trace_flags, Nodes, TraceConfList, How},?CALL_TIMEOUT). trace_flags(NodeTraceConfList,How) -> gen_server:call(?CONTROLLER,{trace_flags,NodeTraceConfList,How},?CALL_TIMEOUT). trace_flags(NodeTraceConfListHow) -> gen_server:call(?CONTROLLER,{trace_flags,NodeTraceConfListHow},?CALL_TIMEOUT). %% ----------------------------------------------------------------------------- %% ----------------------------------------------------------------------------- %% tpm_localnames()={ok,NodeResults}|NodeResult|{error,Reason} %% tpm_localnames(Nodes)={ok,NodeResults}|{error,Reason} %% NodeResults=[{Node,NodeResult},...] %% NodeResult={ok,N}|{error,Reason}, Note that N can only be 0 or 1. %% %% Quick version for setting meta-trace patterns on erlang:register/2. It uses %% a default CallFunc and ReturnFunc in the meta-tracer server. %% The main purpose of this function is to create ti-log entries for printing %% the aliases for process instead of their process identities. tpm_localnames() -> tpm_localnames(all). tpm_localnames(Nodes) -> gen_server:call(?CONTROLLER,{meta_pattern,Nodes,{local_register,[]}},?CALL_TIMEOUT). %% ------------------------------------------------------------------------------ %% tpm_globalnames()={ok,NodeResults}|NodeResult|{error,Reason} %% tpm_globalnames(Nodes)={ok,NodeResults}|{error,Reason} %% NodeResults=[{Node,NodeResult},...] %% NodeResult={SubResult,SubResult} %% SubResult={ok,N}|{error,Reason}, Note that N can only be 0 or 1. %% As tpm_locanames/0,/1 but for registering names with global. Note that this %% actually involves setting meta trace patterns on two functions in global. tpm_globalnames() -> tpm_globalnames(all). tpm_globalnames(Nodes) -> gen_server:call(?CONTROLLER,{meta_pattern,Nodes,{global_register,[]}},?CALL_TIMEOUT). %% ------------------------------------------------------------------------------ %% init_tpm(Mod,Func,Arity,CallFunc)={ok,NodeResults}|NodeResult|{error,Reason} %% init_tpm(Nodes,Mod,Func,Arity,CallFunc)={ok,NodeResults}|{error,Reason} %% init_tpm(Mod,Func,Arity,InitFunc,CallFunc,ReturnFunc,RemoveFunc)= %% {ok,NodeResults}|NodeResult|{error,Reason} %% init_tpm(Nodes,Mod,Func,Arity,InitFunc,CallFunc,ReturnFunc,RemoveFunc)= %% {ok,NodeResults}|{error,Reason} %% %% Mod,Func=Pointing out the function which shall be meta traced, atom(). %% Arity=As above, integer(). %% NodeResults=[{Node,NodeResult},...] %% NodeResult=ok|{error,Reason} %% %% 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. %% When calling several nodes, the nodes are called in parallel. init_tpm(Mod,Func,Arity,CallFunc) -> init_tpm(all,Mod,Func,Arity,CallFunc). init_tpm(Nodes,Mod,Func,Arity,CallFunc) -> gen_server:call(?CONTROLLER, {meta_pattern, Nodes, {init_tpm, [Mod,Func,Arity,CallFunc]}}, ?CALL_TIMEOUT). init_tpm(Mod,Func,Arity,InitFunc,CallFunc,ReturnFunc,RemoveFunc) -> init_tpm(all,Mod,Func,Arity,InitFunc,CallFunc,ReturnFunc,RemoveFunc). init_tpm(Nodes,Mod,Func,Arity,InitFunc,CallFunc,ReturnFunc,RemoveFunc) -> gen_server:call(?CONTROLLER, {meta_pattern, Nodes, {init_tpm, [Mod,Func,Arity,InitFunc,CallFunc,ReturnFunc,RemoveFunc]}}, ?CALL_TIMEOUT). %% ------------------------------------------------------------------------------ %% tpm(Mod,Func,Arity,MS)={ok,NodeResults}|NodeResult|{error,Reason} %% tpm(Nodes,Mod,Func,Arity,MS)={ok,NodeResults}|{error,Reason} %% tpm(Mod,Func,Arity,MS,CallFunc)={ok,NodeResults}|NodeResults|{error,Reason} %% tpm(Nodes,Mod,Func,Arity,MS,CallFunc)={ok,NodeResults}|{error,Reason} %% tpm(Mod,Func,Arity,MS,InitFunc,CallFunc,ReturnFunc,RemoveFunc)= %% {ok,NodeResults}|NodeResults|{error,Reason} %% tpm(Nodes,Mod,Func,Arity,MS,InitFunc,CallFunc,ReturnFunc,RemoveFunc)= %% {ok,NodeResults}|{error,Reason} %% %% Mod,Func=atom() and not '_'. %% Arity=integer() %% MS=list(), matchspecification. %% Nodes=List of nodenames. %% 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. %% %% NodeResults=[{Node,NodeResult},...] %% NodeResult={ok,N}|{error,Reason}, Note that N can only be 0 or 1. %% %% Activates meta-tracing in the inviso_rt_meta tracer. Except when using tpm/6,/8 %% and /9 the function must first have been initiated using init_tpm. If running %% a non distributed system the variants without Node shall be used. If running %% in a distributed environment, without Node means all our nodes. %% When calling several nodes, the nodes are called in parallel. tpm(Mod,Func,Arity,MS) -> tpm(all,Mod,Func,Arity,MS). tpm(Nodes,Mod,Func,Arity,MS) when is_integer(Arity) -> gen_server:call(?CONTROLLER, {meta_pattern,Nodes,{tpm,[Mod,Func,Arity,MS]}}); tpm(Mod,Func,Arity,MS,CallFunc) when is_integer(Arity) -> tpm(all,Mod,Func,Arity,MS,CallFunc). tpm(Nodes,Mod,Func,Arity,MS,CallFunc) -> gen_server:call(?CONTROLLER, {meta_pattern,Nodes,{tpm,[Mod,Func,Arity,MS,CallFunc]}}). tpm(Mod,Func,Arity,MS,InitFunc,CallFunc,ReturnFunc,RemoveFunc) -> tpm(all,Mod,Func,Arity,MS,InitFunc,CallFunc,ReturnFunc,RemoveFunc). tpm(Nodes,Mod,Func,Arity,MS,InitFunc,CallFunc,ReturnFunc,RemoveFunc) -> gen_server:call(?CONTROLLER, {meta_pattern, Nodes, {tpm, [Mod,Func,Arity,MS,InitFunc,CallFunc,ReturnFunc,RemoveFunc]}}, ?CALL_TIMEOUT). %% ------------------------------------------------------------------------------ %% Same as tpm/X but the meta tracer will append {tracer,Tracer} to any enable %% list in a trace body action term. tpm_tracer(Mod,Func,Arity,MS) -> tpm_tracer(all,Mod,Func,Arity,MS). tpm_tracer(Nodes,Mod,Func,Arity,MS) when is_integer(Arity) -> gen_server:call(?CONTROLLER, {meta_pattern,Nodes,{tpm_tracer,[Mod,Func,Arity,MS]}}, ?CALL_TIMEOUT); tpm_tracer(Mod,Func,Arity,MS,CallFunc) when is_integer(Arity) -> tpm_tracer(all,Mod,Func,Arity,MS,CallFunc). tpm_tracer(Nodes,Mod,Func,Arity,MS,CallFunc) -> gen_server:call(?CONTROLLER, {meta_pattern,Nodes,{tpm_tracer,[Mod,Func,Arity,MS,CallFunc]}}). tpm_tracer(Mod,Func,Arity,MS,InitFunc,CallFunc,ReturnFunc,RemoveFunc) -> tpm_tracer(all,Mod,Func,Arity,MS,InitFunc,CallFunc,ReturnFunc,RemoveFunc). tpm_tracer(Nodes,Mod,Func,Arity,MS,InitFunc,CallFunc,ReturnFunc,RemoveFunc) -> gen_server:call(?CONTROLLER, {meta_pattern, Nodes, {tpm_tracer, [Mod,Func,Arity,MS,InitFunc,CallFunc,ReturnFunc,RemoveFunc]}}, ?CALL_TIMEOUT). %% ------------------------------------------------------------------------------ %% tpm_ms(Mod,Func,Arity,MSname,MS)={ok,NodeResults}|NodeResult|{error,Reason} %% tpm_ms(Nodes,Mod,Func,Arity,MSname,MS)={ok,NodeResults}|{error,Reason} %% Nodes= List of all nodes where the function shall be carried out. %% 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. %% NodeResults=[{Node,NodeResult},...] %% NodeResult={ok,1}|{ok,0}|{error,Reason} where {ok,1} indicates that %% setting the matchspecification for the function succeeded. %% %% 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. %% The function must previously have been initiated in order for this function %% to add a match-spec. %% When calling several nodes, the nodes are called in parallel. tpm_ms(Mod,Func,Arity,MSname,MS) -> tpm_ms(all,Mod,Func,Arity,MSname,MS). tpm_ms(Nodes,Mod,Func,Arity,MSname,MS) -> gen_server:call(?CONTROLLER, {meta_pattern,Nodes,{tpm_ms,[Mod,Func,Arity,MSname,MS]}}, ?CALL_TIMEOUT). %% ------------------------------------------------------------------------------ %% Same as tpm_ms/5, /6 but the meta tracer will append {tracer,Tracer} to any enable %% list in a trace body action term. tpm_ms_tracer(Mod,Func,Arity,MSname,MS) -> tpm_ms_tracer(all,Mod,Func,Arity,MSname,MS). tpm_ms_tracer(Nodes,Mod,Func,Arity,MSname,MS) -> gen_server:call(?CONTROLLER, {meta_pattern,Nodes,{tpm_ms_tracer,[Mod,Func,Arity,MSname,MS]}}, ?CALL_TIMEOUT). %% ------------------------------------------------------------------------------ %% ctpm_ms(Mod,Func,Arity,MSname)={ok,NodeResults}|NodeResult|{error,Reason} %% ctpm_ms(Nodes,Mod,Func,Arity,MSname)={ok,NodeResults}|{error,Reason} %% NodeResults=[{Node,NodeResult},...] %% NodeResult=ok|{error,Reason} %% %% Removes a named match-spec from the meta traced function. Note that it never %% is a fault to remove an MS. Not even from a function which is non existant. %% When calling several nodes, the nodes are called in parallel. ctpm_ms(Mod,Func,Arity,MSname) -> ctpm_ms(all,Mod,Func,Arity,MSname). ctpm_ms(Nodes,Mod,Func,Arity,MSname) -> gen_server:call(?CONTROLLER, {meta_pattern,Nodes,{ctpm_ms,[Mod,Func,Arity,MSname]}}, ?CALL_TIMEOUT). %% ------------------------------------------------------------------------------ %% ctpm(Mod,Func,Arity)={ok,NodeResults}|NodeResult|{error,Reason} %% ctpm(Node,Mod,Func,Arity)={ok,NodeResults}|{error,Reason} %% NodeResults=[{Node,NodeResult},...] %% NodeResult=ok|{error,Reason} %% %% 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. %% When calling several nodes, the nodes are called in parallel. ctpm(Mod,Func,Arity) -> ctpm(all,Mod,Func,Arity). ctpm(Nodes,Mod,Func,Arity) -> gen_server:call(?CONTROLLER, {meta_pattern,Nodes,{ctpm,[Mod,Func,Arity]}}, ?CALL_TIMEOUT). %% ------------------------------------------------------------------------------ %% ctpm_localnames()={ok,NodeResults}|NodeResult|{error,Reason} %% ctpm_localnames(Nodes)={ok,NodeResults}|{error,Reason} %% NodeResults=[{Node,NodeResult},...] %% NodeResult=ok|{error,Reason} %% %% Removes meta-trace pattern for erlang:register/2, previously set by tpm_localnames. %% When calling several nodes, the nodes are called in parallel. ctpm_localnames() -> ctpm_localnames(all). ctpm_localnames(Nodes) -> gen_server:call(?CONTROLLER,{meta_pattern,Nodes,{remove_local_register,[]}},?CALL_TIMEOUT). %% ------------------------------------------------------------------------------ %% ctpm_localnames()={ok,NodeResults}|NodeResult|{error,Reason} %% ctpm_localnames(Nodes)={ok,NodeResults}|{error,Reason} %% NodeResults=[{Node,NodeResult},...] %% NodeResult={SubResult,Subresult} %% SubResult=ok|{error,Reason} %% %% Removes meta-trace pattern for the register functions in global. Note that there %% are two of them. %% When calling several nodes, the nodes are called in parallel. ctpm_globalnames() -> ctpm_globalnames(all). ctpm_globalnames(Nodes) -> gen_server:call(?CONTROLLER,{meta_pattern,Nodes,{remove_global_register,[]}},?CALL_TIMEOUT). %% ------------------------------------------------------------------------------ %% ctp_all(Nodes)={ok,NodeResults}|{error,Reason} %% ctp_all()={ok,NodeResults}|NodeResult|{error,Reason} %% Nodes=[Node,...], %% NodeResults=[{Node,NodeResult},...] %% NodeResult=ok|{error,Reason}, %% %% Clears all both global and local trace patterns on all or specified nodes. %% Does not effect meta patterns. ctp_all() -> gen_server:call(?CONTROLLER,{ctp_all,all},?CALL_TIMEOUT). ctp_all(Nodes) -> gen_server:call(?CONTROLLER,{ctp_all,Nodes},?CALL_TIMEOUT). %% ------------------------------------------------------------------------------ %% suspend(Nodes,Reason)={ok,NodeResults}|{error,Reason} %% suspend(Reason)={ok,NodeResults}|NodeResult|{error,Reason} %% Nodes=[Node], %% Reason=term(); supposed to describe the reason why suspended. %% NodeResults=[{Node,NodeResult},...] %% NodeResult=ok|{error,Reason}, %% %% Suspend all or specified Nodes with reason Reason. Suspend means that all %% process trace flags are removed and all meta-patterns. suspend(Nodes, Reason) -> gen_server:call(?CONTROLLER,{suspend,Reason,Nodes},?CALL_TIMEOUT). suspend(Reason) -> gen_server:call(?CONTROLLER,{suspend,Reason,all},?CALL_TIMEOUT). %% ------------------------------------------------------------------------------ %% cancel_suspension(Nodes)={ok,NodeResults}|{error,Reason} %% cancel_suspension()={ok,NodeResults}|NodeResult|{error,Reason} %% Nodes=[Node,...], %% NodeResults=[{Node,NodeResult},...] %% NodeResult=ok|{error,Reason}, %% Cancel suspension on all or specified Nodes. Note that this does not imply %% that "business" is resumed as before. You must reactivate flags and meta-patter %% your self. cancel_suspension(Nodes) -> gen_server:call(?CONTROLLER,{cancel_suspension,Nodes},?CALL_TIMEOUT). cancel_suspension() -> gen_server:call(?CONTROLLER,{cancel_suspension,all},?CALL_TIMEOUT). %% ------------------------------------------------------------------------------ %% get_status(Nodes)={ok,NodeResults}|{error,Reason} %% get_status()={ok,NodeResults}|NodeResult|{error,Reason} %% Nodes=[Node,...], %% NodeResults=[{Node,NodeResult},...] %% NodeResult={ok,{State,Status}}|{error,Reason}, %% State=new|idle|tracing %% Status=running|{suspended,SReason} %% %% Get Status form all or specified runtime components. get_status(Nodes) when is_list(Nodes) -> gen_server:call(?CONTROLLER,{get_status,Nodes},?CALL_TIMEOUT). get_status() -> gen_server:call(?CONTROLLER,{get_status,all},?CALL_TIMEOUT). %% ------------------------------------------------------------------------------ %% get_tracerdata()={ok,NodeResults}|NodeResult|{error,Reason} %% get_tracerdata(Nodes)={ok,NodeResults}|{error,Reason} %% Nodes=[Node,...], %% NodeResult={ok,NResult}|{error,Reason}, %% NResult=TracerData|no_tracerdata %% TracerData will be exactly as it was specified when doing init_tracing. %% %% Get TracerData form all or specified runtime components. get_tracerdata() -> gen_server:call(?CONTROLLER,{get_tracerdata,all},?CALL_TIMEOUT). get_tracerdata(Nodes) when is_list(Nodes) -> gen_server:call(?CONTROLLER,{get_tracerdata,Nodes},?CALL_TIMEOUT). %% ------------------------------------------------------------------------------ %% list_logs(TracerData)={ok,NodeResults}|NodeResult|{error,Reason} %% list_logs(NodeList)={ok,NodeResults}|{error,Reason} %% list_logs()={ok,NodeResults}|NodeResult|{error,Reason} %% TracerData see init_tracing/1/2 %% NodeList=[NodeSpec,...] %% NodeSpec=Node|{Node,TracerData} %% NodeResults=[{Node,NodeResult},...] %% NodeResult={ok,FileList}|{ok,no_log}|{error,Reason} %% FileList=[FileType,...], one or more of different types. %% FileType={trace_log,Dir,Files}|{ti_log,Dir,Files} %% Files=[FileNameWithOutPath,...] %% %% Ask local or specified runtime components for now existing logs given %% TracerData. If TracerData is left out, the runtime components TracerData, %% if existing, will be used instead. list_logs() -> gen_server:call(?CONTROLLER,list_logs,?CALL_TIMEOUT). list_logs(TracerDataOrNodesList) when is_list(TracerDataOrNodesList) -> gen_server:call(?CONTROLLER,{list_logs,TracerDataOrNodesList},?CALL_TIMEOUT). %% ------------------------------------------------------------------------------ %% fetch_log(LogSpecList,DestDir,Prefix)={ok,NodeResults}|{error,not_distributed}| %% {error,Reason} %% fetch_log(DestDir,Prefix)={ok,NodeResults}|{error,not_distributed}| %% {error,Reason} %% fetch_log(ToNode,DestDir,Prefix)= %% fetch_log(ToNode,LogSpecList,DestDir,Prefix)= %% DestDir=string(), to where the fetched files shall be placed. %% Prefix=string(), prefix on locally saved fetched files. %% LogSpecList=[LogSpec,...], %% LogSpec={Node,FileSpecList}|Node|{Node,TracerData} %% TracerData=see init_tracing/1/2 %% FileSpecList=[{trace_log,Dir,FileList},{ti_log,Dir,FileList}] %% where each tuple-item is optional. %% FileList=[RemoteFileName,...] %% ToNode=atom() %% NodeResult={Conclusion,ResultFileSpec}|no_log|{error,NReason} %% Conclusion=complete|incomplete %% ResultFileSpec=[{trace_log,FileResults},{ti_log,FileResults}] %% FileResults=[FileResult,...] %% FileResult={ok,FileName}|{error,FReason} %% NReason=own_node|Reason %% FReason = {file_open,{posix(),FileName}} | %% {file_open,{posix(),RemoteFileName}} %% {file_open,{posix(),[DestDir,Prefix,RemoteFileName]}} %% {file_write,{posix(),FileName}} | %% {truncated,FileName} %% {truncated,{Reason,FileName}} %% posix() - an atom which is named from the Posix error codes used in %% Unix, and in the runtime libraries of most C compilers. %% See module file in Kernel Reference manual. %% %% Copies logfiles over distributed erlang to ToNode. This %% function can only be used in a distributed system. %% The resulting transfered files will have the prefix Prefix and will be %% located in DestDir. %% Note that the client process using this function will wait until all files %% are moved. The job can be cancelled, causing any already copied files to be %% removed, by simply terminating the waiting client process. fetch_log(DestDir,Prefix) when is_list(DestDir),is_list(Prefix) -> gen_server:call(?CONTROLLER,{fetch_log,node(),all,DestDir,Prefix},infinity). fetch_log(ToNode,DestDir,Prefix) when is_atom(ToNode),is_list(DestDir),is_list(Prefix) -> gen_server:call(?CONTROLLER,{fetch_log,ToNode,all,DestDir,Prefix},infinity); fetch_log(LogSpecList,DestDir,Prefix) when is_list(LogSpecList),is_list(DestDir),is_list(Prefix) -> gen_server:call(?CONTROLLER,{fetch_log,node(),LogSpecList,DestDir,Prefix},infinity). fetch_log(ToNode,LogSpecList,DestDir,Prefix) when is_atom(ToNode),is_list(LogSpecList),is_list(DestDir),is_list(Prefix) -> gen_server:call(?CONTROLLER,{fetch_log,ToNode,LogSpecList,DestDir,Prefix},infinity). %% ------------------------------------------------------------------------------ %% delete_log(Nodes,TracerData)={ok,NodeResults}|{error,Reason} %% delete_log(NodeSpecList)={ok,NodeResults}|{error,Reason} %% delete_log(Spec)={ok,NodeResults}|NodeResult|{error,Reason} %% delete_log(TracerData)={ok,NodeResults}|NodeResult|{error,Reason} %% delete_log()={ok,NodeResults}|NodeResult|{error,Reason} %% Nodes=[Node,...], %% NodeSpecList=[{Node,Spec},...] %% Spec=[AbsPathFileName,...]|LogSpecs %% LogSpecs=[LogSpec,...] %% LogSpec={trace_log,Dir,[FileNameWithoutPath,...]}| %% {ti_log,Dir,[FileNameWithoutPath,...]} %% TracerData = see init_tracing/1/2 %% NodeResults=[{Node,NodeResult},...] %% NodeResult={ok,no_log}|{ok,LogInfos}|{ok,FileInfos} %% LogInfos=[LogInfo,...] %% LogInfo={trace_log,FileInfos}|{ti_log,FileInfos} %% FileInfos=[FileInfo,...] %% FileInfo={ok,FileName}|{error,Reason} whether FileName contains %% full path or not depends on if AbsPathFileName or LogSpec was %% used when specifying the files. %% %% Deletes listed files or files corresponding to TracerData from specified %% or all Nodes. If no TracerData or list of files is specified in the call the %% TracerData at Node will be used to identify log files to delete. delete_log() -> gen_server:call(?CONTROLLER,{delete_log,all},?CALL_TIMEOUT). delete_log(What) -> gen_server:call(?CONTROLLER,{delete_log,What},?CALL_TIMEOUT). delete_log(Nodes,Spec) -> gen_server:call(?CONTROLLER,{delete_log,Nodes,Spec},?CALL_TIMEOUT). %% ----------------------------------------------------------------------------- %% subscribe()= same as subscribe(self()) %% subscribe(Pid)=ok|{error,Reason} %% Pid=pid(), %% Reason = %% Add Pid or self() to event sending list. Note that it is possible to add a %% pid several times and that the Pid then will receive several event messages. %% All events will be sent to all subscribers in the event sending list. %% Event={inviso_event,ControllerPid,erlang:localtime(),Msg}, %% Msg= %% {connected, Node, {Tag, {State, Status}}} %% {disconnected, Node, not_applicable} %% {state_change, Node, {State, Status}} %% {port_down, Node, Reason} %% Node = node() | local_runtime (when running in a non-distributed %% environment) subscribe() -> gen_server:call(?CONTROLLER,{subscribe,self()},?CALL_TIMEOUT). subscribe(Pid) -> gen_server:call(?CONTROLLER,{subscribe,Pid},?CALL_TIMEOUT). %% ----------------------------------------------------------------------------- %% unsubscribe()= same as unsubscribe(self()) %% unsubscribe(Pid)=ok %% Pid=pid(), %% %% Remove, if present, first occurrence of Pid or self() from event sending %% list. Note that it is not an error to remove a non existing subscription. unsubscribe() -> gen_server:call(?CONTROLLER,{unsubscribe,self()},?CALL_TIMEOUT). unsubscribe(Pid) -> gen_server:call(?CONTROLLER,{unsubscribe,Pid},?CALL_TIMEOUT). %% ------------------------------------------------------------------------------ %% debuging the controller %% ---------------------------------------------------------------------------- state() -> ?CONTROLLER ! state. %% debuging the runtime component state(Node) -> ?CONTROLLER ! {state, Node}. %%% end of file