<commit_before>%% @author Northscale <<EMAIL>>
%% @copyright 2010 NorthScale, Inc.
%% All rights reserved.

%% This module exists to slow down supervisors to prevent fast spins
%% on crashes.

-module(supervisor_cushion).

-behaviour(gen_server).
-behavior(ns_log_categorizing).

-define(FAST_CRASH, 1).

%% API
-export([start_link/5]).
-export([ns_log_cat/1, ns_log_code_string/1, child_pid/1]).

%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
         terminate/2, code_change/3]).

-record(state, {name, delay, started, child_pid}).

start_link(Name, Delay, M, F, A) ->
    gen_server:start_link(?MODULE, [Name, Delay, M, F, A], []).

init([Name, Delay, M, F, A]) ->
    process_flag(trap_exit, true),
    error_logger:info_msg("starting ~p with delay of ~p~n", [M, Delay]),
    {ok, Pid} = apply(M, F, A),
    {ok, #state{name=Name, delay=Delay, started=now(), child_pid=Pid}}.

handle_call(child_pid, _From, State) ->
    {reply, State#state.child_pid, State};
handle_call(_Request, _From, State) ->
    Reply = ok,
    {reply, Reply, State}.

handle_cast(_Msg, State) ->
    {noreply, State}.

handle_info({'EXIT', _Pid, Reason}, State) ->
    error_logger:info_msg("Cushion managed supervisor for ~p failed:  ~p~n",
                          [State#state.name, Reason]),
    State1 = die_slowly({error, cushioned_supervisor, Reason}, State),
    {noreply, State1};
handle_info({die, Reason}, State) ->
    {stop, Reason, State};
handle_info(Info, State) ->
    error_logger:info_msg("Cushion got unexpected info supervising ~p: ~p~n",
                          [State#state.name, Info]),
    State1 = die_slowly({error, cushioned_supervisor, Info}, State),
    {noreply, State1}.

die_slowly(Reason, State) ->
    %% How long (in microseconds) has this service been running?
    Lifetime = timer:now_diff(now(), State#state.started),
    %% now_diff returns microseconds, so let's do the same.
    MinDelay = State#state.delay * 1000,
    %% If the restart was too soon, slow down a bit.
    case Lifetime < MinDelay of
        true ->
            ns_log:log(?MODULE, ?FAST_CRASH,
                       "Service ~p crashed in ~.2fs~n",
                       [State#state.name, Lifetime / 1000000]),
            timer:send_after(State#state.delay, {die, Reason});
        _ -> self() ! {die, Reason}
    end,
    State#state{child_pid=undefined}.

terminate(_Reason, _State) ->
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.

ns_log_cat(?FAST_CRASH) -> warn.

ns_log_code_string(?FAST_CRASH) -> "port crashed too soon after restart".

%% API
child_pid(Pid) ->
    gen_server:call(Pid, child_pid).
<commit_msg>Supervisor cushion fix to handle instacrash. bug 852<commit_after>%% @author Northscale <<EMAIL>>
%% @copyright 2010 NorthScale, Inc.
%% All rights reserved.

%% This module exists to slow down supervisors to prevent fast spins
%% on crashes.

-module(supervisor_cushion).

-behaviour(gen_server).
-behavior(ns_log_categorizing).

-define(FAST_CRASH, 1).

%% API
-export([start_link/5]).
-export([ns_log_cat/1, ns_log_code_string/1, child_pid/1]).

%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
         terminate/2, code_change/3]).

-record(state, {name, delay, started, child_pid}).

start_link(Name, Delay, M, F, A) ->
    gen_server:start_link(?MODULE, [Name, Delay, M, F, A], []).

init([Name, Delay, M, F, A]) ->
    process_flag(trap_exit, true),
    error_logger:info_msg("starting ~p with delay of ~p~n", [M, Delay]),
    case apply(M, F, A) of
        {ok, Pid} ->
            {ok, #state{name=Name, delay=Delay, started=now(), child_pid=Pid}};
        X ->
            {ok, die_slowly(X, #state{name=Name, delay=Delay, started=now()})}
    end.

handle_call(child_pid, _From, State) ->
    {reply, State#state.child_pid, State};
handle_call(_Request, _From, State) ->
    Reply = ok,
    {reply, Reply, State}.

handle_cast(_Msg, State) ->
    {noreply, State}.

handle_info({'EXIT', _Pid, Reason}, State) ->
    error_logger:info_msg("Cushion managed supervisor for ~p failed:  ~p~n",
                          [State#state.name, Reason]),
    State1 = die_slowly({error, cushioned_supervisor, Reason}, State),
    {noreply, State1};
handle_info({die, Reason}, State) ->
    {stop, Reason, State};
handle_info(Info, State) ->
    error_logger:info_msg("Cushion got unexpected info supervising ~p: ~p~n",
                          [State#state.name, Info]),
    State1 = die_slowly({error, cushioned_supervisor, Info}, State),
    {noreply, State1}.

die_slowly(Reason, State) ->
    %% How long (in microseconds) has this service been running?
    Lifetime = timer:now_diff(now(), State#state.started),
    %% now_diff returns microseconds, so let's do the same.
    MinDelay = State#state.delay * 1000,
    %% If the restart was too soon, slow down a bit.
    case Lifetime < MinDelay of
        true ->
            ns_log:log(?MODULE, ?FAST_CRASH,
                       "Service ~p crashed in ~.2fs~n",
                       [State#state.name, Lifetime / 1000000]),
            timer:send_after(State#state.delay, {die, Reason});
        _ -> self() ! {die, Reason}
    end,
    State#state{child_pid=undefined}.

terminate(_Reason, _State) ->
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.

ns_log_cat(?FAST_CRASH) -> warn.

ns_log_code_string(?FAST_CRASH) -> "port crashed too soon after restart".

%% API
child_pid(Pid) ->
    gen_server:call(Pid, child_pid).

{'fraction_non_alphanumeric': 0.15203193033381712, 'fraction_numerical': 0.01179245283018868, 'mean_word_length': 3.351223362273086, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7218586', 'n_tokens_mistral': 2012, 'n_tokens_neox': 1896, 'n_words': 464}