aboutsummaryrefslogtreecommitdiffstats
path: root/lib/observer/src/etop_gui.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/observer/src/etop_gui.erl')
-rw-r--r--lib/observer/src/etop_gui.erl374
1 files changed, 0 insertions, 374 deletions
diff --git a/lib/observer/src/etop_gui.erl b/lib/observer/src/etop_gui.erl
deleted file mode 100644
index 3971646abc..0000000000
--- a/lib/observer/src/etop_gui.erl
+++ /dev/null
@@ -1,374 +0,0 @@
-%%
-%% %CopyrightBegin%
-%%
-%% Copyright Ericsson AB 2002-2013. 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
-%% 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 online 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.
-%%
-%% %CopyrightEnd%
-%%
--module(etop_gui).
--compile([{nowarn_deprecated_function,{gs,config,2}},
- {nowarn_deprecated_function,{gs,create,3}},
- {nowarn_deprecated_function,{gs,create,4}},
- {nowarn_deprecated_function,{gs,destroy,1}},
- {nowarn_deprecated_function,{gs,read,2}},
- {nowarn_deprecated_function,{gs,start,0}}]).
-
--author('[email protected]').
-
--export([init/1,stop/1]).
--export([formatmfa/1,to_list/1]).% For etop_txt
-
--include("etop.hrl").
--include("etop_defs.hrl").
-
--import(etop, [loadinfo/1, meminfo/2, getopt/2]).
-
-%% Heights
--define(BarH, 28). % height of menubar
--define(LabelH, 90). % height of label with system info
--define(GridLineH, 21). % height of one line in the table (grid)
-
-%% Column numbers for grid - click to sort
--define(TimeCol, 3).
--define(RedsCol, 4).
--define(MemCol, 5).
--define(MsgQCol, 6).
-
-%% Font
--define(Normal, {screen,12}).
--define(Bold, {screen,bold,12}).
-
-
-%% -----------------------------------------------------------------------------
-stop(_) -> ok.
-
-init(Config) ->
- S = gs:start(),
- Width = getopt(width, Config),
- TotLines = getopt(lines,Config)+1,
-
- %% Max number of processes shown in window at startup is 10
- %% If less than 10 lines is specified, window size fits number of lines
- WinH = if TotLines > 11 -> 11*?GridLineH + ?BarH + ?LabelH;
- true -> TotLines*?GridLineH + ?BarH + ?LabelH
- end,
- Win = gs:create(window, S,
- [{title, "Erlang Top"},
- {map, true}, %% While debugging
- {configure, true},
- {width, Width}, {height, WinH}]),
- Bar = gs:create(menubar, Win, []),
-
- FileButt = gs:create(menubutton, Bar, [{label,{text, " File "}}]),
- OptionsButt = gs:create(menubutton, Bar, [{label,{text, " Options "}}]),
- File = gs:create(menu, FileButt, []),
- Options = gs:create(menu, OptionsButt, []),
- gse:named_menuitem(refresh, File,
- [{label,{text," Refresh "}}]),
- gse:named_menuitem(dump, File,
- [{label,{text," Dump to file "}}]),
- gse:named_menuitem(exit, File,
- [{label,{text," Exit "}}]),
-
- gse:named_menuitem(accum, Options,
- [{label,{text, " Accumulate "}},
- {itemtype, check}]),
- gse:named_menuitem(intv, Options,
- [{label,{text, " Update Interval "}}]),
- gse:named_menuitem(lines, Options,
- [{label,{text, " Number of Lines "}}]),
- Sort = gse:named_menuitem(sort, Options,
- [{label,{text, " Sort "}},
- {itemtype,cascade}]),
- SortMenu = gse:create(menu, Sort, []),
- gse:named_menuitem(runtime, SortMenu,
- [{label,{text, " Time "}},
- {itemtype,radio},{group,gr1}]),
- gse:named_menuitem(memory, SortMenu,
- [{label,{text, " Memory "}},
- {itemtype,radio},{group,gr1}]),
- gse:named_menuitem(reductions, SortMenu,
- [{label,{text, " Reductions "}},
- {itemtype,radio},{group,gr1}]),
- gse:named_menuitem(msg_q, SortMenu,
- [{label,{text, " Message Queue "}},
- {itemtype,radio},{group,gr1}]),
-
- SysInfo = gs:create(label,Win,[{x, 0}, {y, ?BarH},{align,sw},
- {width, Width},{height,?LabelH}]),
-
- {GridH,VScroll} = calc_grid_h(WinH,TotLines),
- Grid = gse:grid(Win,
- [{x, 0}, {y, ?BarH+?LabelH},
- {width, Width},
- {height, GridH},
- {hscroll, false},
- {vscroll, VScroll},
- {columnwidths, calc_column_w(Width)},
- {rows, {1, TotLines}},
- {font,?Normal}]),
-
- %% Header line
- GL1 = gse:gridline(Grid, [{{text, 1}, "PID"},
- {{text, 2}, "Name or Initial Function"},
- {{text, ?TimeCol}, "Time(us)"},
- {{text, ?RedsCol}, "Reds"},
- {{text, ?MemCol}, "Memory"},
- {{text, ?MsgQCol}, "MsgQ"},
- {{text, 7}, "Current Function"},
- {bg, lightblue},
- {row, 1},
- {click, true}]),
-
- config_sort(GL1,getopt(sort,Config)),
- Info = do_update(Grid, SysInfo, Config),
-
- get_event(Info, Win, Grid, GL1, SysInfo, Config).
-
-calc_column_w(W) ->
- %% W = [2x, 3x, 1x, 1x, 1x, 1x, 3x] = 12x
- RW = W-9, % just to make nice small margins on each side of grid
- X = RW div 12,
- [2*X, 3*X, X, X, X, X, 3*X + (RW - 12*X)].
-
-config_sort(GL1,Sort) ->
- gs:config(Sort,[{select,true}]),
- lists:foreach(fun(S) ->
- gs:config(GL1,[{{font,S},?Normal}])
- end,
- [?TimeCol,?MemCol,?RedsCol,?MsgQCol]),
- case Sort of
- runtime -> gs:config(GL1,{{font,?TimeCol},?Bold});
- memory -> gs:config(GL1,{{font,?MemCol},?Bold});
- reductions -> gs:config(GL1,{{font,?RedsCol},?Bold});
- msg_q -> gs:config(GL1,{{font,?MsgQCol},?Bold})
- end.
-
-config_lines(Win,Grid,TotLines) ->
- OldGridH = gs:read(Grid,height),
- NewLinesH = TotLines*?GridLineH,
- if NewLinesH =< OldGridH ->
- gs:config(Win,[{height,NewLinesH+?BarH+?LabelH}]),
- gs:config(Grid,[{rows,{1,TotLines}},
- {height,NewLinesH},
- {vscroll,false}]);
- true ->
- gs:config(Grid,[{rows,{1,TotLines}},{vscroll,right}])
- end.
-
-calc_grid_h(WinH,TotLines) ->
- LeftInWin = WinH - ?BarH - ?LabelH,
- TotGrid = TotLines * ?GridLineH,
- if LeftInWin >= TotGrid ->
- {TotGrid,false};
- true ->
- {LeftInWin,right}
- end.
-
-set_win_h(Win,OrigH,TotLines) ->
- TotH = TotLines*?GridLineH + ?BarH + ?LabelH,
- if TotH >= OrigH -> OrigH;
- true -> gs:config(Win,[{height,TotH}]),
- TotH
- end.
-
-get_event(Info, Win, Grid, GL1, SysInfo, Config) ->
- receive
- {gs, Win, configure,[],[W,H,_,_]} ->
- TotLines = getopt(lines,Config)+1,
- %% Will not make window higher than total number of lines
- RealWinH = set_win_h(Win,H,TotLines),
- {GridH,VScroll} = calc_grid_h(RealWinH,TotLines),
- gs:config(Grid, [{width, W},
- {columnwidths, calc_column_w(W)},
- {height,GridH}, {vscroll,VScroll}]),
- get_event(Info, Win, Grid, GL1, SysInfo, Config);
- {gs, refresh, _, _, _} ->
- Info1 = do_update(Grid, SysInfo, Config),
- get_event(Info1, Win, Grid, GL1, SysInfo, Config);
- {gs, dump, _, _, _} ->
- case pop(Win,dump) of
- {ok,File} -> etop:dump(File);
- {error,cancel} -> ok
- end,
- get_event(Info, Win, Grid, GL1, SysInfo, Config);
- {gs, Win, destroy, _, _} ->
- normal;
- {gs, exit, _, _, _} ->
- ok;
- {gs, accum, _, _, _} ->
- Old = getopt(accum,Config),
- etop:config(accumulate,not Old),
- get_event(Info, Win, Grid, GL1, SysInfo, Config);
- {gs,intv,_,_,_} ->
- case pop(Win,interval) of
- {ok,Intv} -> etop:config(interval,list_to_integer(Intv));
- {error,cancel} -> ok
- end,
- get_event(Info, Win, Grid, GL1, SysInfo, Config);
- {gs,lines,_,_,_} ->
- case pop(Win,lines) of
- {ok,Lines} -> etop:config(lines,list_to_integer(Lines));
- {error,cancel} -> ok
- end,
- get_event(Info, Win, Grid, GL1, SysInfo, Config);
- {gs,Sort,_,_,_} when Sort=:=runtime;
- Sort=:=memory;
- Sort=:=reductions;
- Sort=:=msg_q ->
- etop:config(sort,Sort),
- get_event(Info, Win, Grid, GL1, SysInfo, Config);
- {gs,GL1,click,_,[Col,1,_]} ->
- case Col of
- ?TimeCol -> etop:config(sort, runtime);
- ?MemCol -> etop:config(sort, memory);
- ?RedsCol -> etop:config(sort, reductions);
- ?MsgQCol -> etop:config(sort, msg_q);
- _other -> ignore
- end,
- get_event(Info, Win, Grid, GL1, SysInfo, Config);
- {config,{Key,Value},Config1} ->
- case Key of
- lines -> config_lines(Win,Grid,Value+1);
- sort -> config_sort(GL1,Value);
- accumulate -> gs:config(accum,[{select,Value}]);
- _ -> ok
- end,
- Info1 = do_update(Grid, SysInfo, Config1),
- get_event(Info1, Win, Grid, GL1, SysInfo, Config1);
- {dump,Fd} ->
- etop_txt:do_update(Fd,Info,Config),
- get_event(Info, Win, Grid, GL1, SysInfo, Config);
- Msg ->
- io:format("~p got unexpected msg ~p~n", [?MODULE, Msg]),
- get_event(Info, Win, Grid, GL1, SysInfo, Config)
- after getopt(intv,Config) ->
- Info1 = do_update(Grid, SysInfo, Config),
- get_event(Info1, Win, Grid, GL1, SysInfo, Config)
- end.
-
-do_update(Grid, SysInfo, Config) ->
- Info = etop:update(Config),
- Lines = makegridlines(Info#etop_info.procinfo, Grid, 2),
- clear_lines(Lines, getopt(lines,Config) + 1, Grid),
- makesysinfo(getopt(node,Config),Info,SysInfo),
- Info.
-
-%clear_lines(From, To, _Grid) when From > To -> ok;
-clear_lines(From, To, Grid) ->
- case gs:read(Grid, {obj_at_row, From}) of
- undefined ->
- ok;
- GridLine ->
- gs:destroy(GridLine),
- clear_lines(From + 1, To, Grid)
- end.
-
-formatmfa({M, F, A}) ->
- io_lib:format("~w:~w/~w",[M, F, A]);
-formatmfa(Other) ->
- %% E.g. when running hipe - the current_function for some
- %% processes will be 'undefined'
- io_lib:format("~w",[Other]).
-
-
-makegridlines([#etop_proc_info{pid=Pid,
- mem=Mem,
- reds=Reds,
- name=Name,
- runtime=Time,
- cf=MFA,
- mq=MQ}
- |T], Grid, Count) ->
- update_gl(Grid, Count, [{{text, 1}, pid_to_list(Pid)},
- {{text, 2}, to_list(Name)},
- {{text, ?TimeCol},
- if is_integer(Time)->integer_to_list(Time);
- true -> Time
- end},
- {{text, ?RedsCol}, integer_to_list(Reds)},
- {{text, ?MemCol}, integer_to_list(Mem)},
- {{text, ?MsgQCol}, integer_to_list(MQ)},
- {{text, 7}, formatmfa(MFA)},
- {row, Count}, {click, false}]),
- makegridlines(T, Grid, Count + 1);
-makegridlines([],_Grid,Count) ->
- Count.
-
-update_gl(Grid, Row, GL) ->
- case gs:read(Grid, {obj_at_row, Row}) of
- undefined ->
- gse:gridline(Grid,[{row, Row}|GL]);
- GridLine ->
- gs:config(GridLine,GL)
- end.
-
-to_list(Name) when is_atom(Name) -> atom_to_list(Name);
-to_list({_M,_F,_A}=MFA) -> formatmfa(MFA).
-
-
-makesysinfo(Node,Info,SysInfo) ->
- {Cpu,NProcs,RQ,Clock} = loadinfo(Info),
- case Info#etop_info.memi of
- undefined ->
- Str = "No memory information is available.";
- Memi ->
- [Tot,Procs,Atom,Bin,Code,Ets] =
- meminfo(Memi, [total,processes,atom,binary,code,ets]),
- Str = io_lib:fwrite(?SYSFORM,
- [Node,Clock,
- Cpu,Tot,Bin,
- NProcs,Procs,Code,
- RQ,Atom,Ets])
- end,
- gs:config(SysInfo,[{label,{text,Str}},{font,?Normal}]).
-
-
-pop(Win,Key) ->
- Pop = gs:create(window,Win,[{title,"Config"},
- {width,160},{height,100}]),
- gs:create(label,Pop,[{label,{text,txt(Key)}},
- {width,160}]),
- gs:create(entry,entry,Pop,[{x,10},{y,30},{width,130},
- {keypress,true}]),
- gs:create(button,ok,Pop,[{width,45},{y,60},{x,10},
- {label,{text,"Ok"}}]),
- gs:create(button,cancel,Pop,[{width,60},{y,60},{x,80},
- {label,{text,"Cancel"}}]),
- gs:config(Pop,{map,true}),
- pop_loop(Pop).
-
-pop_loop(Pop) ->
- receive
- {gs,entry,keypress,_,['Return'|_]} ->
- Str = gs:read(entry,text),
- gs:destroy(Pop),
- {ok,Str};
- {gs,entry,keypress,_,_} -> % all other keypresses
- pop_loop(Pop);
- {gs,ok,click,_,_} ->
- Str = gs:read(entry,text),
- gs:destroy(Pop),
- {ok,Str};
- {gs,cancel,click,_,_} ->
- gs:destroy(Pop),
- {error,cancel};
- X ->
- io:format("Got X=~w~n",[X]),
- pop_loop(Pop)
- end.
-
-txt(interval) -> "Enter new interval:";
-txt(lines) -> "Enter number of lines:";
-txt(dump) -> "Enter file name:".