1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2013-2018. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19-module(cdv_proc_cb).
20
21-export([col_to_elem/1,
22	 col_spec/0,
23	 get_info/1,
24	 get_detail_cols/1,
25	 get_details/2,
26	 detail_pages/0]).
27
28-include_lib("wx/include/wx.hrl").
29-include("crashdump_viewer.hrl").
30
31%% Columns
32-define(COL_ID,  0).
33-define(COL_NAME, ?COL_ID+1).
34-define(COL_STATE,?COL_NAME+1).
35-define(COL_REDS, ?COL_STATE+1).
36-define(COL_MEM,  ?COL_REDS+1).
37-define(COL_MSG,  ?COL_MEM+1).
38
39%% Callbacks for cdv_virtual_list_wx
40col_to_elem(id) -> col_to_elem(?COL_ID);
41col_to_elem(?COL_ID)  -> #proc.pid;
42col_to_elem(?COL_NAME) -> #proc.name;
43col_to_elem(?COL_STATE) -> #proc.state;
44col_to_elem(?COL_MEM)  -> #proc.memory;
45col_to_elem(?COL_REDS) -> #proc.reds;
46col_to_elem(?COL_MSG)  -> #proc.msg_q_len.
47
48col_spec() ->
49    [{"Pid", ?wxLIST_FORMAT_CENTRE,  120},
50     {"Name or Initial Func", ?wxLIST_FORMAT_LEFT, 250},
51     {"State", ?wxLIST_FORMAT_LEFT, 100},
52     {"Reds", ?wxLIST_FORMAT_RIGHT, 80},
53     {"Memory", ?wxLIST_FORMAT_RIGHT, 80},
54     {"MsgQ",  ?wxLIST_FORMAT_RIGHT, 50}].
55
56get_info(_) ->
57    {ok,Info,TW} = crashdump_viewer:processes(),
58    {Info,TW}.
59
60get_detail_cols(_) ->
61    {[{process, ?COL_ID}],true}.
62
63%% Callbacks for cdv_detail_wx
64get_details(Id, _) ->
65    case crashdump_viewer:proc_details(Id) of
66	{ok,Info,TW} ->
67	    %% The following table is used by observer_html_lib
68	    %% for storing expanded terms and it is read by
69	    %% cdv_html_wx when a link to an expandable term is clicked.
70	    Tab = ets:new(cdv_expand,[set,public]),
71	    Proplist0 =
72		crashdump_viewer:to_proplist(record_info(fields,proc),Info),
73	    Proplist = [{expand_table,Tab}|Proplist0],
74	    Title = io_lib:format("~ts (~s)",[Info#proc.name, Id]),
75	    {ok,{Title,Proplist,TW}};
76	{error,{other_node,NodeId}} ->
77	    Info = "The process you are searching for was residing on "
78		"a remote node. No process information is available. "
79		"Show information about the remote node?",
80	    Fun = fun() -> cdv_virtual_list_wx:start_detail_win(NodeId, port) end,
81	    {yes_no, Info, Fun};
82	{error,not_found} ->
83	    Info = "The process you are searching for could not be found.",
84	    {info,Info}
85    end.
86
87detail_pages() ->
88    [{"General Information",   fun init_gen_page/2},
89     {"Messages",   fun init_message_page/2},
90     {"Dictionary", fun init_dict_page/2},
91     {"Stack Dump", fun init_stack_page/2},
92     {"ETS tables", fun init_ets_page/2},
93     {"Timers",     fun init_timer_page/2}].
94
95init_gen_page(Parent, Info) ->
96    Fields = info_fields(),
97    cdv_info_wx:start_link(Parent,{Fields,Info,[]}).
98
99init_message_page(Parent, Info) ->
100    init_memory_page(Parent, Info, msg_q, "MsgQueue").
101
102init_dict_page(Parent, Info) ->
103    init_memory_page(Parent, Info, dict, "Dictionary").
104
105init_stack_page(Parent, Info) ->
106    init_memory_page(Parent, Info, stack_dump, "StackDump").
107
108init_memory_page(Parent, Info0, Tag, Heading) ->
109    Info = proplists:get_value(Tag,Info0),
110    Tab = proplists:get_value(expand_table,Info0),
111    Html = observer_html_lib:expandable_term(Heading,Info,Tab, observer_lib:colors(Parent)),
112    cdv_html_wx:start_link(Parent,{expand,Html,Tab}).
113
114init_ets_page(Parent, Info) ->
115    Pid = proplists:get_value(pid,Info),
116    cdv_virtual_list_wx:start_link(Parent, cdv_ets_cb, Pid).
117
118init_timer_page(Parent, Info) ->
119    Pid = proplists:get_value(pid,Info),
120    cdv_virtual_list_wx:start_link(Parent, cdv_timer_cb, Pid).
121
122%%%-----------------------------------------------------------------
123%%% Internal
124info_fields() ->
125    [{"Overview",
126      [{"Initial Call",     init_func},
127       {dynamic,            current_func},
128       {"Registered Name",  name},
129       {"Status",           state},
130       {"Internal State",   int_state},
131       {"Started",          start_time},
132       {"Parent",           {click,parent}},
133       {"Message Queue Len",msg_q_len},
134       {"Run queue",        run_queue},
135       {"Reductions",       reds},
136
137       {"Program counter",  prog_count},
138       {"Continuation pointer",cp},
139       {"Arity",arity}]},
140     {scroll_boxes,
141      [{"Last Calls",1,{plain,last_calls}}]},
142     {scroll_boxes,
143      [{"Links",1,{click,links}},
144       {"Monitors",2,{click,monitors}},
145       {"Monitored By",2,{click,mon_by}}]},
146     {"Memory and Garbage Collection",
147      [{"Memory",           memory},
148       {"Stack and Heap",   stack_heap},
149       {"Old Heap",         old_heap},
150       {"Heap Unused",      heap_unused},
151       {"Old Heap Unused",  old_heap_unused},
152       {"Binary vheap",     bin_vheap},
153       {"Old Binary vheap", old_bin_vheap},
154       {"Binary vheap unused",  bin_vheap_unused},
155       {"Old Binary vheap unused", old_bin_vheap_unused},
156       {"Number of Heap Fragements", num_heap_frag},
157       {"Heap Fragment Data",heap_frag_data},
158       {"New Heap Start",   new_heap_start},
159       {"New Heap Top",     new_heap_top},
160       {"Stack Top",        stack_top},
161       {"Stack End",        stack_end},
162       {"Old Heap Start",   old_heap_start},
163       {"Old Heap Top",     old_heap_top},
164       {"Old Heap End",     old_heap_end}]}].
165