⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 et_viewer.erl

📁 OTP是开放电信平台的简称
💻 ERL
📖 第 1 页 / 共 4 页
字号:
%% ``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$%%%%----------------------------------------------------------------------%% Purpose: Displays a sequence chart for trace events (messages/actions)%%-----------------------------------------------------------------------module(et_viewer).-behaviour(gen_server).%% External exports-export([file/1,         start/0,         start/1,	 start_link/1,	 stop/1,          get_collector_pid/1]).%% gen_server callbacks-export([init/1, terminate/2, code_change/3,         handle_call/3, handle_cast/2, handle_info/2]).-include("../include/et.hrl").-include("et_internal.hrl").-define(unknown, "UNKNOWN").-record(state,        {parent_pid,       % Pid of parent process         collector_pid,    % Pid of collector process         event_order,      % Field to be used as primary key         trace_pattern,    % Collector trace pattern         active_filter,    % Name of the active filter         filters,          % List of possible filters         selected_actor,   % Actor selected by user         first_event,      % Key of first event (regardless of visibility)         last_event,       % Key of last event (regardless of visibility)         max_events,       % Maximum number of shown events         events,           % Queue containg all event keys (regardless of visibility)         max_actors,       % Maximum number of shown actors         actors,           % List of known actors         refresh_needed,   % Refresh is needed in order to show all actors         display_mode,     % Display all or only matching actors         detail_level,     % Show only events with lesser detail level         hide_actions,     % Hide/show events where to == from actor (bool)         hide_unknown,     % Hide/show events with unknown actor (bool)         is_suspended,     % Suspend viewer updates (bool)         title,            % GUI: Window title         win,              % GUI: Window object         menubar,          % GUI: Menu bar object         packer,           % GUI: Packer object         width,            % GUI: Window width         height,           % GUI: Window height         scale,            % GUI: Scaling factor on canvas         font,             % GUI: Font to be used on text labels         canvas_width,     % GUI: Canvas width         canvas_height,    % GUI: Canvas height         canvas,           % GUI: Canvas object         y_pos}).          % GUI: Current y position on canvas-record(actor, {name, string}).-define(initial_x, 10).-define(incr_x,    60).-define(initial_y, 15).-define(incr_y,    15).-define(detail_level_min, 0).-define(detail_level_max, 100).%%%----------------------------------------------------------------------%%% Client side%%%----------------------------------------------------------------------%%----------------------------------------------------------------------%% file(FileName) -> {ok, ViewerPid} | {error, Reason}%%%% Start a new event viewer and a corresponding collector%% and load them with trace events from a trace file.%%%% FileName() = string()%% ViewerPid = pid()%% Reason = term()%%----------------------------------------------------------------------file(FileName) ->    start_link([{trace_client, {file, FileName}}]).%%----------------------------------------------------------------------%% start() -> ok%% %% Simplified start of a sequence chart viewer with%% global tracing activated.%%%% Convenient to be used from the command line%% (erl -s et_viewer) as both the viewer and collector%% processes are unlinked from the calling process.%%----------------------------------------------------------------------start() ->    start([{trace_global, true}]).%%----------------------------------------------------------------------%% start(Options) -> {ok, ViewerPid} | {error, Reason}%%----------------------------------------------------------------------start(Options) ->    start_link([{parent_pid, undefined} | Options]).%%----------------------------------------------------------------------%% start_link(Options) -> {ok, ViewerPid} | {error, Reason}%%%% Start a sequence chart viewer for trace events (messages/actions)%% %% Options = [option() | collector_option()]%%%% option() =%%   {parent_pid, extended_pid()} |%%   {title, term()} |%%   {detail_level, detail_level()} |%%   {is_suspended, boolean()} |%%   {scale, integer()} |%%   {width, integer()} |%%   {height, integer()} |%%   {collector_pid, extended_pid()} |%%   {event_order, event_order()} |%%   {active_filter, atom()} |%%   {max_events, extended_integer()} |%%   {max_actors, extended_integer()} |%%   {trace_global, et_collector_trace_global()} |%%   {trace_pattern, et_collector_trace_pattern()} |%%   {trace_port, et_collector_trace_port()} |%%   {trace_max_queue, et_collector_trace_max_queue()} |%%   {trace_client, et_collector_trace_client()} |%%   {dict_insert, {filter, filter_name()}, event_filter_fun()} |%%   {dict_insert, et_collector_dict_key(), et_collector_dict_val()} |%%   {dict_delete, {filter, filter_name()}} |%%   {dict_delete, et_collector_dict_key()} |%%   {actors, actors()} |%%   {first_event, first_key()} |%%   {hide_unknown, boolean()} |%%   {hide_actions, boolean()} |%%   {display_mode, display_mode()}%%   %% extended_pid() = pid() | undefined%% detail_level() = min | max | integer(X) when X >=0, X =< 100%% event_order() = trace_ts | event_ts%% extended_integer() = integer() | infinity%% display_mode() = all | {search_actors, direction(), first_key(), actors()}%% direction() = forward | reverse%% first_key() = event_key()%% actors() = [term()]%% %% filter_name() = atom()%% filter_fun() =  fun(Event) -> false | true | {true, NewEvent}%% Event = NewEvent = record(event)%%%% ViewerPid = pid()%% Reason = term()%%%% A filter_fun() takes an event record as sole argument%% and returns false | true | {true, NewEvent}.%%----------------------------------------------------------------------start_link(Options) ->     case parse_opt(Options, default_state(), []) of        {ok, S, CollectorOpt} ->            case S#state.collector_pid of                CollectorPid when pid(CollectorPid) ->                    case gen_server:start_link(?MODULE, [S], []) of                        {ok, Pid} when S#state.parent_pid /= self() ->                            unlink(Pid),                            {ok, Pid};                        Other ->                            Other                    end;                undefined ->                    case et_collector:start_link(CollectorOpt) of                        {ok, CollectorPid} ->                            S2 = S#state{collector_pid = CollectorPid},                            case gen_server:start_link(?MODULE, [S2], []) of                                {ok, Pid} when S#state.parent_pid /= self() ->                                    unlink(Pid),                                    {ok, Pid};                                Other ->                                    Other                            end;                        {error, Reason} ->                            {error, {et_collector, Reason}}                    end            end;        {error, Reason} ->            {error, Reason}    end.default_state() ->    #state{parent_pid     = self(),           collector_pid  = undefined,           detail_level   = max,           active_filter  = collector,           filters        = [#filter{name = collector, function = fun(E) -> E end}],           event_order    = trace_ts,           is_suspended   = false,           max_events     = 100,           first_event    = first,           last_event     = first,           events         = queue_new(),           max_actors     = 5,           actors         = [create_actor(?unknown)],           selected_actor = ?unknown,           hide_actions   = false,           hide_unknown   = false,           refresh_needed = false,           display_mode   = all,           scale          = 2,           canvas_height  = 0,           canvas_width   = 0,           width          = 800,           height         = 600}.parse_opt([], S, CollectorOpt) ->    case S#state.detail_level of        max ->            {ok, S#state{detail_level = ?detail_level_max}, CollectorOpt};        min ->            {ok, S#state{detail_level = ?detail_level_min}, CollectorOpt};        Int when integer(Int) ->            {ok, S, [{parent_pid, S#state.parent_pid} | CollectorOpt]}    end;parse_opt([H | T], S, CollectorOpt) ->    case H of        {parent_pid, Parent} when Parent == undefined ->            CollectorOpt2 = [H | CollectorOpt],            parse_opt(T, S#state{parent_pid = Parent}, CollectorOpt2);        {parent_pid, Parent} when pid(Parent) ->            CollectorOpt2 = [H | CollectorOpt],            parse_opt(T, S#state{parent_pid = Parent}, CollectorOpt2);        {title, Title} ->            parse_opt(T, S#state{title = name_to_string(Title)}, CollectorOpt);        {detail_level, Level} when integer(Level),                                   Level >= ?detail_level_min,                                   Level =< ?detail_level_max ->             parse_opt(T, S#state{detail_level = Level}, CollectorOpt);        {detail_level, max} ->            parse_opt(T, S#state{detail_level = ?detail_level_max}, CollectorOpt);        {detail_level, min} ->            parse_opt(T, S#state{detail_level = ?detail_level_min}, CollectorOpt);        {is_suspended, true} ->            parse_opt(T, S#state{is_suspended = true}, CollectorOpt);        {is_suspended, false} ->            parse_opt(T, S#state{is_suspended = false}, CollectorOpt);        {scale, Scale} when integer(Scale), Scale > 0 ->            parse_opt(T, S#state{scale = Scale}, CollectorOpt);        {width, W} when integer(W), W > 0 ->            parse_opt(T, S#state{width = W, canvas_width = W}, CollectorOpt);        {height, WH} when integer(WH), WH > 0 ->            parse_opt(T, S#state{height = WH, canvas_height = WH}, CollectorOpt);        {collector_pid, Pid} when pid(Pid) ->             parse_opt(T, S#state{collector_pid = Pid}, CollectorOpt);        {collector_pid, undefined} ->             parse_opt(T, S#state{collector_pid = undefined}, CollectorOpt);        {active_filter, Name} when atom(Name) ->            parse_opt(T, S#state{active_filter = Name}, CollectorOpt);        {event_order, trace_ts} -> %% BUGBUG: Verify event_order with collector            CollectorOpt2 = [H | CollectorOpt],            parse_opt(T, S#state{event_order = trace_ts}, CollectorOpt2);        {event_order, event_ts} -> %% BUGBUG: Verify event_order with collector            CollectorOpt2 = [H | CollectorOpt],            parse_opt(T, S#state{event_order = event_ts}, CollectorOpt2);        {trace_port, _Port} ->             CollectorOpt2 = [H | CollectorOpt],            parse_opt(T, S, CollectorOpt2);        {trace_max_queue, _Queue} ->             CollectorOpt2 = [H | CollectorOpt],            parse_opt(T, S, CollectorOpt2);        {trace_pattern, _Pattern} ->             CollectorOpt2 = [H | CollectorOpt],            parse_opt(T, S, CollectorOpt2);        {trace_global, _Boolean} ->             CollectorOpt2 = [H | CollectorOpt],            parse_opt(T, S, CollectorOpt2);        {trace_client, _Client} ->             CollectorOpt2 = [H | CollectorOpt],            parse_opt(T, S, CollectorOpt2);        {dict_insert, {filter, Name}, Fun} ->	    if		atom(Name), function(Fun) ->		    F = #filter{name = Name, function = Fun},		    Filters = lists:keydelete(Name, #filter.name, S#state.filters),		    CollectorOpt2 = [H | CollectorOpt],		    parse_opt(T, S#state{filters = Filters ++ [F]}, CollectorOpt2);		true ->	            {error, {bad_option, H}}	    end;        {dict_insert, {subscriber, Pid}, _Val} ->	    if		pid(Pid) ->		    CollectorOpt2 = [H | CollectorOpt],		    parse_opt(T, S, CollectorOpt2);		true ->	            {error, {bad_option, H}}	    end;        {dict_insert, _Key, _Val} ->            CollectorOpt2 = [H | CollectorOpt],            parse_opt(T, S, CollectorOpt2);        {dict_delete, {filter, Name}} ->            Filters = lists:keydelete(Name, #filter.name, S#state.filters),            CollectorOpt2 = [H | CollectorOpt],            parse_opt(T, S#state{filters = Filters}, CollectorOpt2);        {dict_delete, _Key} ->            CollectorOpt2 = [H | CollectorOpt],            parse_opt(T, S, CollectorOpt2);        {max_events, Max} when integer(Max), Max > 0->            parse_opt(T,  S#state{max_events = Max}, CollectorOpt);        {max_events, Max} when Max == infinity ->            parse_opt(T,  S#state{max_events = Max}, CollectorOpt);        {max_actors, Max} when integer(Max), Max >= 0->            parse_opt(T,  S#state{max_actors = Max}, CollectorOpt);        {max_actors, Max} when Max == infinity ->            parse_opt(T,  S#state{max_actors = Max}, CollectorOpt);        {actors, ActorNames} when list(ActorNames) ->            ActorNames2 =                 case lists:member(?unknown, ActorNames) of                    false -> [?unknown | ActorNames];                    true  -> ActorNames                end,            Actors = [create_actor(Name) || Name <- ActorNames2],            parse_opt(T, S#state{actors = Actors}, CollectorOpt);        {first_event, First} ->            parse_opt(T,  S#state{first_event = First}, CollectorOpt);        {hide_unknown, Bool} when Bool == false ->            parse_opt(T,  S#state{hide_unknown = Bool}, CollectorOpt);        {hide_unknown, Bool} when Bool == true ->            parse_opt(T,  S#state{hide_unknown = Bool}, CollectorOpt);        {hide_actions, Bool} when Bool == false ->            parse_opt(T,  S#state{hide_actions = Bool}, CollectorOpt);        {hide_actions, Bool} when Bool == true ->            parse_opt(T,  S#state{hide_actions = Bool}, CollectorOpt);        {display_mode, Mode = all} ->            parse_opt(T,  S#state{display_mode = Mode}, CollectorOpt);        {display_mode, Mode = {search_actors, Dir, _Key, Actors}} when list(Actors), Dir == forward ->            parse_opt(T,  S#state{display_mode = Mode}, CollectorOpt);        {display_mode, Mode = {search_actors, Dir, _Key, Actors}} when list(Actors), Dir == reverse ->            parse_opt(T,  S#state{display_mode = Mode}, CollectorOpt);        Bad ->            {error, {bad_option, Bad}}    end;parse_opt(BadList, _S, _CollectorOpt) ->    {error, {bad_option_list, BadList}}.do_dict_insert({filter, Name}, Fun, S) when atom(Name), function(Fun) ->    F = #filter{name = Name, function = Fun},    Filters = lists:keydelete(Name, #filter.name, S#state.filters),    Filters2 = lists:keysort(#filter.name, [F | Filters]),    gs:destroy(filter_menu),    create_filter_menu(S#state.active_filter, Filters2),        S#state{filters = Filters2};do_dict_insert(_Key, _Val, S) ->    %% ok = error_logger:format("~p(~p): handle_info({et, {dict_insert, ~p, ~p}})~n",    %%                          [?MODULE, self(), Key, Val]),    S.do_dict_delete({filter, Name}, S) when atom(Name), Name /= S#state.active_filter ->    Filters = lists:keydelete(Name, #filter.name, S#state.filters),    gs:destroy(filter_menu),    create_filter_menu(S#state.active_filter, Filters),        S#state{filters = Filters};do_dict_delete(_Key, S) ->    %% ok = error_logger:format("~p(~p): handle_info({et, {dict_delete, ~p}})~n",    %%                          [?MODULE, self(), Key]),    S.%%----------------------------------------------------------------------%% get_collector_pid(ViewerPid) -> CollectorPid%%%% Returns the identifier of the collector process%%%% ViewerPid = pid()%% CollectorPid = pid()%%----------------------------------------------------------------------get_collector_pid(ViewerPid) ->    call(ViewerPid, get_collector_pid).%%----------------------------------------------------------------------%% stop(ViewerPid) -> ok%% %% Stops a viewer

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -