<commit_before>% @copyright 2012-2013 Zuse Institute Berlin,

%   Licensed under the Apache License, Version 2.0 (the "License");
%   you may not use this file except in compliance with the License.
%   You may obtain a copy of the License at
%
%       http://www.apache.org/licenses/LICENSE-2.0
%
%   Unless required by applicable law or agreed to in writing, software
%   distributed under the License is distributed on an "AS IS" BASIS,
%   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%   See the License for the specific language governing permissions and
%   limitations under the License.

%% @author <NAME> <<EMAIL>>
%% @doc    Text mode top for an Erlang VM. Just call top:top() in the eshell.
%% @end
%% @version $Id$
-module(top).
-author('<EMAIL>').
-vsn('$Id:$ ').

%-define(TRACE(X,Y), io:format(X,Y)).
-define(TRACE(X,Y), ok).
-include("scalaris.hrl").

-export([start_link/1]).
-export([on/2, init/1]).

-export([top/0]).
-export([trace_fwd/2]).

-type state() :: { pdb:tableid(),
                   false | all | pid, %% sampling: no, all or a single pid
                   false | all | pid, %% output: no, all, or a single pid
                   erlang_timestamp(), %% last output
                   non_neg_integer(), %% # of measures
                   non_neg_integer(), %% sort by
                   no_exclude | pid()
                 }.

-spec start_link(list()) -> {ok, pid()}.
start_link(Group) ->
    gen_component:start_link(?MODULE, fun ?MODULE:on/2, [],
                             [{erlang_register, ?MODULE},
                              {pid_groups_join_as, Group, ?MODULE}]).

-spec init([]) -> state().
init([]) ->
    try
        Candidates = [ {X, process_info(X, [initial_call])}
                       || X <- processes()],
        Leaders = [ {Pid, process_info(Pid, [registered_name])}
                    || {Pid, [{initial_call, Call}]} <- Candidates,
                       Call =:= {group, server, 3}],
        [Leader] = [ Pid ||  {Pid, [{registered_name, []}]} <- Leaders],
        erlang:group_leader(Leader, self())
    catch _:_ -> ok
    end,
    {pdb:new(?MODULE, [set, protected]), false, false,
     os:timestamp(), 0, _SortBy = 4, self()}.

-spec top() -> ok.
top() ->
    io:format("~p~n", [io:rows(standard_io)]),
    Pid = pid_groups:find_a(?MODULE),
    comm:send_local(Pid, {enable_sampling, all}),
    comm:send_local(Pid, {sample_all}),
    comm:send_local(Pid, {enable_output, all}),
    comm:send_local(Pid, {output_all}),
    top_interactive(Pid).

top_interactive(Pid) ->
    {ok, [Char]} = io:fread("> ", "~c"),
    Quit =
        case Char of
            "q" -> quit;
            "e" ->
                comm:send_local(Pid, {output_off}),
                Expr = io:parse_erl_exprs('expr>'),
                comm:send_local(Pid, {enable_output, all}),
                comm:send_local(Pid, {output_all}),
                case element(1, Expr) of
                    ok ->
                        spawn(fun() -> erl_eval:exprs(element(2, Expr), erl_eval:new_bindings()) end),
                          ok;
                    _ -> ok
                end;
            "p" -> comm:send_local(Pid, {sort_by, pid});
            "w" -> comm:send_local(Pid, {sort_by, mqlen});
            "c" -> comm:send_local(Pid, {sort_by, cpuusage});
            "m" -> comm:send_local(Pid, {sort_by, memory});
            "t" -> comm:send_local(Pid, {toggle_exclude_self});
            "i" -> top_inspect_pid(Pid);
            "g" -> [garbage_collect(X) || X <- processes()];
            _ -> ok
    end,
    case Quit of
        quit ->
            comm:send_local(Pid, {output_off}),
            comm:send_local(Pid, {stop_sampling});
        _ -> top_interactive(Pid)
    end.

top_inspect_pid(Pid) ->
    %% Read pid and start inspect mode
    comm:send_local(Pid, {output_off}),
    comm:send_local(Pid, {stop_sampling}),
    InspectPid = pid_prompt(),
    comm:send_local(Pid, {enable_sampling, InspectPid}),
    comm:send_local(Pid, {sample_pid, InspectPid}),
    comm:send_local(Pid, {enable_output, pid}),
    comm:send_local(Pid, {output_pid, InspectPid}),
    top_inspect_pid_interactive(Pid, InspectPid),
    comm:send_local(Pid, {stop_sampling}),
    comm:send_local(Pid, {enable_sampling, all}),
    comm:send_local(Pid, {sample_all}),
    comm:send_local(Pid, {enable_output, all}),
    comm:send_local(Pid, {output_all}).

pid_prompt() ->
    {ok, [InspectPidString]} = io:fread("pid or name > ", "~s"),
    try list_to_pid(InspectPidString)
    catch _:_ ->
            try
                InspectPidAtom = list_to_atom(InspectPidString),
                case whereis(InspectPidAtom) of
                    undefined ->
                        case pid_groups:find_all(InspectPidAtom) of
                            [Pid] -> Pid;
                            [] -> throw({no_pid, no_pid});
                            Pids ->
                                SPids = lists:sort(Pids),
                                io:format("Which of the ~ps do you mean?~n",
                                          [InspectPidAtom]),
                                lists:foldl(
                                  fun(X, Acc) ->
                                          io:format(
                                            " ~p: ~p ~p~n",
                                            [Acc, X,
                                             pid_groups:group_and_name_of(X)]),
                                          1 + Acc end, 1, SPids),
                                {ok, [Nth]} = io:fread("num > ", "~d"),<commit_msg>top: don't create new atoms<commit_after>% @copyright 2012-2013 Zuse Institute Berlin,

%   Licensed under the Apache License, Version 2.0 (the "License");
%   you may not use this file except in compliance with the License.
%   You may obtain a copy of the License at
%
%       http://www.apache.org/licenses/LICENSE-2.0
%
%   Unless required by applicable law or agreed to in writing, software
%   distributed under the License is distributed on an "AS IS" BASIS,
%   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%   See the License for the specific language governing permissions and
%   limitations under the License.

%% @author <NAME> <<EMAIL>>
%% @doc    Text mode top for an Erlang VM. Just call top:top() in the eshell.
%% @end
%% @version $Id$
-module(top).
-author('<EMAIL>').
-vsn('$Id:$ ').

%-define(TRACE(X,Y), io:format(X,Y)).
-define(TRACE(X,Y), ok).
-include("scalaris.hrl").

-export([start_link/1]).
-export([on/2, init/1]).

-export([top/0]).
-export([trace_fwd/2]).

-type state() :: { pdb:tableid(),
                   false | all | pid, %% sampling: no, all or a single pid
                   false | all | pid, %% output: no, all, or a single pid
                   erlang_timestamp(), %% last output
                   non_neg_integer(), %% # of measures
                   non_neg_integer(), %% sort by
                   no_exclude | pid()
                 }.

-spec start_link(list()) -> {ok, pid()}.
start_link(Group) ->
    gen_component:start_link(?MODULE, fun ?MODULE:on/2, [],
                             [{erlang_register, ?MODULE},
                              {pid_groups_join_as, Group, ?MODULE}]).

-spec init([]) -> state().
init([]) ->
    try
        Candidates = [ {X, process_info(X, [initial_call])}
                       || X <- processes()],
        Leaders = [ {Pid, process_info(Pid, [registered_name])}
                    || {Pid, [{initial_call, Call}]} <- Candidates,
                       Call =:= {group, server, 3}],
        [Leader] = [ Pid ||  {Pid, [{registered_name, []}]} <- Leaders],
        erlang:group_leader(Leader, self())
    catch _:_ -> ok
    end,
    {pdb:new(?MODULE, [set, protected]), false, false,
     os:timestamp(), 0, _SortBy = 4, self()}.

-spec top() -> ok.
top() ->
    io:format("~p~n", [io:rows(standard_io)]),
    Pid = pid_groups:find_a(?MODULE),
    comm:send_local(Pid, {enable_sampling, all}),
    comm:send_local(Pid, {sample_all}),
    comm:send_local(Pid, {enable_output, all}),
    comm:send_local(Pid, {output_all}),
    top_interactive(Pid).

top_interactive(Pid) ->
    {ok, [Char]} = io:fread("> ", "~c"),
    Quit =
        case Char of
            "q" -> quit;
            "e" ->
                comm:send_local(Pid, {output_off}),
                Expr = io:parse_erl_exprs('expr>'),
                comm:send_local(Pid, {enable_output, all}),
                comm:send_local(Pid, {output_all}),
                case element(1, Expr) of
                    ok ->
                        spawn(fun() -> erl_eval:exprs(element(2, Expr), erl_eval:new_bindings()) end),
                          ok;
                    _ -> ok
                end;
            "p" -> comm:send_local(Pid, {sort_by, pid});
            "w" -> comm:send_local(Pid, {sort_by, mqlen});
            "c" -> comm:send_local(Pid, {sort_by, cpuusage});
            "m" -> comm:send_local(Pid, {sort_by, memory});
            "t" -> comm:send_local(Pid, {toggle_exclude_self});
            "i" -> top_inspect_pid(Pid);
            "g" -> [garbage_collect(X) || X <- processes()];
            _ -> ok
    end,
    case Quit of
        quit ->
            comm:send_local(Pid, {output_off}),
            comm:send_local(Pid, {stop_sampling});
        _ -> top_interactive(Pid)
    end.

top_inspect_pid(Pid) ->
    %% Read pid and start inspect mode
    comm:send_local(Pid, {output_off}),
    comm:send_local(Pid, {stop_sampling}),
    InspectPid = pid_prompt(),
    comm:send_local(Pid, {enable_sampling, InspectPid}),
    comm:send_local(Pid, {sample_pid, InspectPid}),
    comm:send_local(Pid, {enable_output, pid}),
    comm:send_local(Pid, {output_pid, InspectPid}),
    top_inspect_pid_interactive(Pid, InspectPid),
    comm:send_local(Pid, {stop_sampling}),
    comm:send_local(Pid, {enable_sampling, all}),
    comm:send_local(Pid, {sample_all}),
    comm:send_local(Pid, {enable_output, all}),
    comm:send_local(Pid, {output_all}).

pid_prompt() ->
    {ok, [InspectPidString]} = io:fread("pid or name > ", "~s"),
    try list_to_pid(InspectPidString)
    catch _:_ ->
            try
                InspectPidAtom = list_to_existing_atom(InspectPidString),
                case whereis(InspectPidAtom) of
                    undefined ->
                        case pid_groups:find_all(InspectPidAtom) of
                            [Pid] -> Pid;
                            [] -> throw({no_pid, no_pid});
                            Pids ->
                                SPids = lists:sort(Pids),
                                io:format("Which of the ~ps do you mean?~n",
                                          [InspectPidAtom]),
                                lists:foldl(
                                  fun(X, Acc) ->
                                          io:format(
                                            " ~p: ~p ~p~n",
                                            [Acc, X,
                                             pid_groups:group_and_name_of(X)]),
                                          1 + Acc end, 1, SPids),
                                {ok, [Nth]} = io:fread("num > ", "~d"),
{'fraction_non_alphanumeric': 0.14686248331108145, 'fraction_numerical': 0.004450378282153983, 'mean_word_length': 1.8125156445556947, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 81, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 26, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2425199', 'n_tokens_mistral': 3620, 'n_tokens_neox': 3474, 'n_words': 783}