aboutsummaryrefslogtreecommitdiffstats
path: root/lib/observer/src/ttb.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/observer/src/ttb.erl')
-rw-r--r--lib/observer/src/ttb.erl75
1 files changed, 55 insertions, 20 deletions
diff --git a/lib/observer/src/ttb.erl b/lib/observer/src/ttb.erl
index 072aa165e7..61fd6d1787 100644
--- a/lib/observer/src/ttb.erl
+++ b/lib/observer/src/ttb.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2002-2009. All Rights Reserved.
+%% Copyright Ericsson AB 2002-2011. All Rights Reserved.
%%
%% 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
@@ -75,29 +75,41 @@ do_tracer(Nodes0,PI,Client,Traci) ->
do_tracer(Clients,PI,Traci).
do_tracer(Clients,PI,Traci) ->
- ShellOutput = proplists:get_value(shell, Traci, false),
- {ClientSucc,Succ} =
+ Shell = proplists:get_value(shell, Traci, false),
+ DefShell = fun(Trace) -> dbg:dhandler(Trace, standard_io) end,
+ {ClientSucc,Succ} =
lists:foldl(
- fun({N,{local,File},TF},{CS,S}) ->
- TF2 = case ShellOutput of
- only -> none;
- _ -> TF
- end,
- [_Sname,Host] = string:tokens(atom_to_list(N),"@"),
+ fun({N,{local,File},TF},{CS,S}) ->
+ {TF2, FileInfo, ShellOutput} =
+ case Shell of
+ only -> {none, shell_only, DefShell};
+ true -> {TF, {file,File}, DefShell};
+ {only,Fun} -> {none, shell_only, Fun};
+ Fun when is_function(Fun) -> {TF, {file,File}, Fun};
+ _ -> {TF, {file,File}, false}
+ end,
+ Host = case N of
+ nonode@nohost ->
+ {ok, H} = inet:gethostname(),
+ H;
+ _ ->
+ [_,H] = string:tokens(atom_to_list(N),"@"),
+ H
+ end,
case catch dbg:tracer(N,port,dbg:trace_port(ip,0)) of
{ok,N} ->
{ok,Port} = dbg:trace_port_control(N,get_listen_port),
{ok,T} = dbg:get_tracer(N),
rpc:call(N,seq_trace,set_system_tracer,[T]),
dbg:trace_client(ip,{Host,Port},
- {fun ip_to_file/2,{{file,File}, ShellOutput}}),
+ {fun ip_to_file/2,{FileInfo, ShellOutput}}),
{[{N,{local,File,Port},TF2}|CS], [N|S]};
Other ->
display_warning(N,{cannot_open_ip_trace_port,
Host,
Other}),
{CS, S}
- end;
+ end;
({N,C,_}=Client,{CS,S}) ->
case catch dbg:tracer(N,port,dbg:trace_port(file,C)) of
{ok,N} ->
@@ -519,7 +531,7 @@ ensure_no_overloaded_nodes() ->
[];
_ ->
?MODULE ! {get_overloaded, self()},
- receive O -> O end
+ receive {overloaded,O} -> O end
end,
case Overloaded of
[] -> ok;
@@ -620,7 +632,7 @@ stop_opts(Opts) ->
case {FormatData, lists:member(return_fetch_dir, Opts)} of
{false, true} ->
{fetch, FetchDir}; % if we specify return_fetch_dir, the data should be fetched
- {false, false} ->
+ {false, false} ->
case lists:member(nofetch,Opts) of
false -> {fetch, FetchDir};
true -> nofetch
@@ -687,6 +699,11 @@ loop(NodeInfo, SessionInfo) ->
{MetaFile,undefined}
end,
loop(dict:store(Node,{AbsoluteMetaFile,MetaPid},NodeInfo), SessionInfo);
+ {ip_to_file_trace_port,Port,Sender} ->
+ Ports = proplists:get_value(ip_to_file_trace_ports, SessionInfo, []),
+ NewSessionInfo = [{ip_to_file_trace_ports,[Port|Ports]}|SessionInfo],
+ Sender ! {?MODULE,ok},
+ loop(NodeInfo, NewSessionInfo);
{get_nodes,Sender} ->
Sender ! {?MODULE,dict:fetch_keys(NodeInfo)},
loop(NodeInfo, SessionInfo);
@@ -715,7 +732,7 @@ loop(NodeInfo, SessionInfo) ->
lists:keydelete(overloaded, 1, SessionInfo)},
loop(NodeInfo, [{overloaded, [Node|Overloaded]} | SI]);
{get_overloaded, Pid} ->
- Pid ! proplists:get_value(overloaded, SessionInfo, []),
+ Pid ! {overloaded,proplists:get_value(overloaded, SessionInfo, [])},
loop(NodeInfo, SessionInfo);
trace_started ->
case proplists:get_value(timer, SessionInfo) of
@@ -736,7 +753,7 @@ loop(NodeInfo, SessionInfo) ->
end
end.
-do_stop(nofetch, Sender, NodeInfo, _) ->
+do_stop(nofetch, Sender, NodeInfo, SessionInfo) ->
write_config(?last_config, all),
dict:fold(
fun(Node,{_,MetaPid},_) ->
@@ -744,6 +761,7 @@ do_stop(nofetch, Sender, NodeInfo, _) ->
end,
ok,
NodeInfo),
+ stop_ip_to_file_trace_ports(SessionInfo),
dbg:stop_clear(),
ets:delete(?history_table),
Sender ! {?MODULE, stopped};
@@ -766,6 +784,7 @@ do_stop({FetchOrFormat, UserDir}, Sender, NodeInfo, SessionInfo) ->
end,
[],
NodeInfo),
+ stop_ip_to_file_trace_ports(SessionInfo),
dbg:stop_clear(),
AllNodes =
lists:map(
@@ -784,6 +803,19 @@ do_stop({FetchOrFormat, UserDir}, Sender, NodeInfo, SessionInfo) ->
end,
Sender ! {?MODULE,{stopped,Absname}}.
+stop_ip_to_file_trace_ports(SessionInfo) ->
+ lists:foreach(fun(Port) ->
+ case lists:member(Port,erlang:ports()) of
+ true ->
+ dbg:deliver_and_flush(Port),
+ erlang:port_close(Port);
+ false ->
+ ok
+ end
+ end,
+ proplists:get_value(ip_to_file_trace_ports,SessionInfo,[])).
+
+
make_node_dead(Node, NodeInfo, SessionInfo) ->
{MetaFile,_} = dict:fetch(Node, NodeInfo),
NewDeadNodes = [{Node, MetaFile} | proplists:get_value(dead_nodes, SessionInfo)],
@@ -1255,14 +1287,17 @@ display_warning(Item,Warning) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% Trace client which reads an IP port and puts data directly to a file.
%%% This is used when tracing remote nodes with no file system.
-ip_to_file({metadata,_,_},{_, only} = State) ->
+ip_to_file({metadata,_,_},{shell_only, _} = State) ->
State;
-ip_to_file(Trace, {_, only} = State) ->
- dbg:dhandler(Trace, standard_io),
+ip_to_file(Trace, {shell_only, Fun} = State) ->
+ Fun(Trace),
State;
ip_to_file(Trace,{{file,File}, ShellOutput}) ->
Fun = dbg:trace_port(file,File), %File can be a filename or a wrap spec
Port = Fun(),
+ %% Store the port so it can be properly closed
+ ?MODULE ! {ip_to_file_trace_port, Port, self()},
+ receive {?MODULE,ok} -> ok end,
case Trace of
{metadata, _, _} -> ok;
Trace -> show_trace(Trace, ShellOutput)
@@ -1279,8 +1314,8 @@ ip_to_file(Trace,{Port, ShellOutput}) ->
erlang:port_command(Port,B),
{Port, ShellOutput}.
-show_trace(Trace, true) ->
- dbg:dhandler(Trace, standard_io);
+show_trace(Trace, Fun) when is_function(Fun) ->
+ Fun(Trace);
show_trace(_, _) ->
ok.