inviso_tool_lib.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 357 行 · 第 1/2 页
ERL
357 行
% ``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$
%%
%% Description:
%% Support module to the inviso tool.
%%
%% Authors:
%% Lennart 謍man, lennart.ohman@st.se
%% -----------------------------------------------------------------------------
-module(inviso_tool_lib).
%% -----------------------------------------------------------------------------
%% Exported library APIs
%% -----------------------------------------------------------------------------
-export([inviso_cmd/3,expand_module_names/3,make_patterns/7,std_tdg/2]).
-export([debug/3]).
%% -----------------------------------------------------------------------------
%% Constants.
%% -----------------------------------------------------------------------------
-define(DBG_OFF,off). % No internal debug indicator.
%% =============================================================================
%% Functions for inviso_cmd
%% =============================================================================
%% Help function which executes a trace control call. The reason for having a special
%% function is that we either want to do rpc if the trace control component is
%% located on another Erlang node than this one. Or call trace_c directly if
%% it actually is on this node.
%% Returns whatever the inviso function returns. In case of badrpc it is wrapped
%% in an error-tuple.
inviso_cmd(NodeName,Func,Args) ->
case node() of
NodeName -> % Control component on this node.
apply(inviso,Func,Args);
_ -> % On other node, must do RPC.
case rpc:call(NodeName,inviso,Func,Args) of
{badrpc,Reason} ->
{error,{badrpc,Reason}};
Result ->
Result
end
end.
%% -----------------------------------------------------------------------------
%% =============================================================================
%% Functions for expand_module_names
%% =============================================================================
%% Help function which expands the module name depending on how it is expressed.
%% Setting Nodes to 'void' makes it non-distributed, expanding only here.
%% The following special cases are handled:
%% '_' =All modules, no expansion into individual module names. Instead
%% it is intended to use the '_' mechanism in the trace_pattern BIF.
%% Can therefore not be combined with a directory regexp.
%% "*" =Is translated into ".*".
%% "abc"=Means ".*abc.*". Can only be used for module or directory names
%% containing upper or lowercase, digits and a slash.
%% Returns {multinode_expansion,NodeModules},
%% {singlenode_expansion,Modules},
%% 'module', 'wildcard' or {error,Reason},
%% To limit the places where expansion is done, the option {expand_only_at,Node}
%% can be provided in the Opts list.
%% In the non-distributed case the singlenode_expansion will be returned.
expand_module_names(_Nodes,Mod={_,'_'},_) ->
{error,{faulty_regexp_combination,Mod}};
expand_module_names(Nodes,{DirStr,ModStr},Opts) when list(DirStr), list(ModStr) ->
case expand_module_names_special_regexp(DirStr) of
{ok,NewDirStr} ->
case expand_module_names_special_regexp(ModStr) of
{ok,NewModStr} ->
expand_module_names_2(Nodes,NewDirStr,NewModStr,Opts);
{error,_Reason} ->
{error,{faulty_regexp,ModStr}}
end;
{error,_Reason} ->
{error,{faulty_regexp,DirStr}}
end;
expand_module_names(_,'_',_Opts) -> % If we want to trace all modules
wildcard; % we shall not expand it.
expand_module_names(_Nodes,Mod,_Opts) when atom(Mod) ->
module; % If it is an atom, no expansion.
expand_module_names(Nodes,"*",Opts) -> % Treat this as a reg.exp.
expand_module_names(Nodes,".*",Opts);
expand_module_names(Nodes,ModStr,Opts) when list(ModStr) ->
case expand_module_names_special_regexp(ModStr) of
{ok,NewModStr} ->
expand_module_names_2(Nodes,NewModStr,Opts);
{error,_Reason} ->
{error,{faulty_regexp,ModStr}}
end.
expand_module_names_2(void,ModStr,Opts) -> % Non-distributed case.
{singlenode_expansion,inviso_rt_lib:expand_regexp(ModStr,Opts)};
expand_module_names_2(Nodes,ModStr,Opts) ->
case get_expand_regexp_at_opts(Opts) of
{ok,Node} -> % Expansion only at this node.
case inviso_rt_lib:expand_regexp([Node],ModStr,Opts) of
[{Node,Modules}] when list(Modules) ->
{singlenode_expansion,Modules};
[{Node,_}] -> % Most likely badrpc.
{error,{faulty_node,Node}}
end;
false -> % Expand on all nodes.
Result=inviso_rt_lib:expand_regexp(Nodes,ModStr,Opts),
{multinode_expansion,Result}
end.
expand_module_names_2(void,DirStr,ModStr,Opts) -> % Non-distributed case.
{singlenode_expansion,inviso_rt_lib:expand_regexp(DirStr,ModStr,Opts)};
expand_module_names_2(Nodes,DirStr,ModStr,Opts) ->
case get_expand_regexp_at_opts(Opts) of
{ok,Node} -> % Expansion only at this node.
case inviso_rt_lib:expand_regexp([Node],DirStr,ModStr,Opts) of
[{Node,Modules}] when list(Modules) ->
{singlenode_expansion,Modules};
[{Node,_}] -> % Most likely badrpc.
{error,{faulty_node,Node}}
end;
false -> % Expand on all nodes.
Result=inviso_rt_lib:expand_regexp(Nodes,DirStr,ModStr,Opts),
{multinode_expansion,Result}
end.
%% Help function which converts a special regexp into a proper one. With
%% special regexps we mean e.g:"abc" which is supposed to mean ".*abc.*".
%% Always returns a regexp or {error,Reason}.
expand_module_names_special_regexp(Str) ->
StrLen=length(Str),
case regexp:first_match(Str,"[0-9a-zA-Z_/]*") of
{match,1,StrLen} -> % Ok, it is the special case.
{ok,".*"++Str++".*"}; % Convert it to a proper regexp.
{match,_,_} ->
{ok,Str}; % Keep it and hope it is a regexp.
nomatch ->
{ok,Str}; % Keep it and hope it is a regexp.
{error,Reason} -> % Can't continue with this!
{error,Reason}
end.
%% -----------------------------------------------------------------------------
%% =============================================================================
%% Functions for make_pattern.
%% =============================================================================
-define(DEPTH,3). % Max recursive safety catch depth.
%% Help function that creates trace-patterns for each module in the list.
%% It can handle both lists of modules or lists of nodes and modules.
%% It will also in the process apply safety catches, if such are not disabled,
%% in order to prevent certain patterns to form.
%% The safety catch function is supposed to return either 'ok' or {new,NewTracePattern}.
%% Where the NewTracePattern is a list of zero or more {M,F,Arity,MS}. The
%% NewTracePatter is then the replacement for the tried trace-pattern.
%% Note that the new trace-pattern(s) are also tried against all safety catches.
%% This can possibly result in even replacements of the replacements. There is
%% a depth meter to prevent the safety catch mechanism from circularly expanding
%% trace patterns for ever.
%% Returns a list of [{Node,PatternList},...] or [Pattern,...].
%% The latter is used when the modules have been expanded on a single node.
make_patterns(Catches,Opts,Dbg,NodeModsOrMods,F,A,MS) ->
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?