<commit_before>%%======================================================================
%%
%% Leo POD
%%
%% Copyright (c) 2012-2013 Rakuten, Inc.
%%
%% This file is provided to you 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.
%%
%%======================================================================
-module(leo_pod_manager).

-author('<NAME>').

-behaviour(gen_server).

-include_lib("eunit/include/eunit.hrl").

%% API
-export([start_link/5,
         stop/1
        ]).

-export([checkout/1,
         checkin/2,
         status/1
        ]).

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

-record(state, {num_of_children = 0 :: pos_integer(),
                max_overflow = 0    :: pos_integer(),
                worker_mod          :: atom(),
                worker_args = []    :: list(tuple()),
                worker_pids = []    :: list()
               }).


%% ===================================================================
%% API functions
%% ===================================================================
%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
%% Description: Starts the server
start_link(Id, NumOfChildren, MaxOverflow, WorkerMod, WorkerArgs) ->
    gen_server:start_link({local, Id}, ?MODULE,
                          [NumOfChildren, MaxOverflow, WorkerMod, WorkerArgs], []).

stop(Id) ->
    gen_server:call(Id, stop, 30000).

checkout(Id) ->
    gen_server:call(Id, checkout).

checkin(Id, WorkerPid) ->
    gen_server:call(Id, {checkin, WorkerPid}).

status(Id) ->
    gen_server:call(Id, status).


%% ===================================================================
%% gen_server callbacks
%% ===================================================================
%% Function: init(Args) -> {ok, State}          |
%%                         {ok, State, Timeout} |
%%                         ignore               |
%%                         {stop, Reason}
%% Description: Initiates the server
init([NumOfChildren, MaxOverflow, WorkerMod, WorkerArgs]) ->
    {ok, Children} =
        start_child(NumOfChildren, WorkerMod, WorkerArgs, []),
    {ok, #state{num_of_children = NumOfChildren,
                max_overflow    = MaxOverflow,
                worker_mod      = WorkerMod,
                worker_args     = WorkerArgs,
                worker_pids     = Children}}.

handle_call(stop,_From,State) ->
    {stop, normal, ok, State};

handle_call(checkout, _From, #state{worker_mod   = WorkerMod,
                                    worker_args  = WorkerArgs,
                                    worker_pids  = Children,
                                    max_overflow = MaxOverflow} = State) ->
    {Res, NewState} =
        case Children of
            [] ->
                case MaxOverflow > 0 of
                    true ->
                        case start_child(WorkerMod, WorkerArgs) of
                            {ok, ChildPid} ->
                                {{ok, ChildPid},
                                 State#state{max_overflow = MaxOverflow - 1}};
                            {error, _Cause} ->
                                {{error, empty}, State}
                        end;
                    false ->
                        {{error, empty}, State}
                end;
            _ ->
                [WorkerPid|NewChildren] = Children,
                {{ok, WorkerPid}, State#state{worker_pids = NewChildren}}
        end,
    {reply, Res, NewState};

handle_call({checkin, WorkerPid}, _From, #state{worker_pids = Children} = State) ->
    NewChildren = [WorkerPid|Children],
    {reply, ok, State#state{worker_pids = NewChildren}};

handle_call(status, _From, State) ->
    {reply, {ok, State#state.worker_pids}, State}.


%% Function: handle_cast(Msg, State) -> {noreply, State}          |
%%                                      {noreply, State, Timeout} |
%%                                      {stop, Reason, State}
%% Description: Handling cast messages
handle_cast(_, State) ->
    {noreply, State}.


%% Function: handle_info(Info, State) -> {noreply, State}          |
%%                                       {noreply, State, Timeout} |
%%                                       {stop, Reason, State}
%% Description: Handling all non call/cast messages
handle_info({'DOWN', MonitorRef, _Type, Pid, _Info}, #state{worker_mod  = WorkerMod,
                                                            worker_args = WorkerArgs,
                                                            worker_pids = ChildPids} = State) ->
    true = erlang:demonitor(MonitorRef),

    ChildPids1 = lists:delete(Pid, ChildPids),
    ChildPids2 = case start_child(WorkerMod, WorkerArgs) of
                     {ok, ChildPid} ->
                         [ChildPid|ChildPids1];
                     _ ->
                         ChildPids1
                 end,
    {noreply, State#state{worker_pids = ChildPids2}};

handle_info(_Info, State) -><commit_msg>Performance tuning<commit_after>%%======================================================================
%%
%% Leo POD
%%
%% Copyright (c) 2012-2013 Rakuten, Inc.
%%
%% This file is provided to you 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.
%%
%%======================================================================
-module(leo_pod_manager).

-author('<NAME>').

-behaviour(gen_server).

-include_lib("eunit/include/eunit.hrl").

%% API
-export([start_link/5,
         stop/1
        ]).

-export([checkout/1,
         checkin/2,
         status/1
        ]).

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

-record(state, {num_of_children = 0 :: pos_integer(),
                max_overflow = 0    :: pos_integer(),
                worker_mod          :: atom(),
                worker_args = []    :: list(tuple()),
                worker_pids = []    :: list()
               }).


%% ===================================================================
%% API functions
%% ===================================================================
%% Function: start_link() -> {ok,Pid} | ignore | {error,Error}
%% Description: Starts the server
start_link(Id, NumOfChildren, MaxOverflow, WorkerMod, WorkerArgs) ->
    gen_server:start_link({local, Id}, ?MODULE,
                          [NumOfChildren, MaxOverflow, WorkerMod, WorkerArgs], []).

stop(Id) ->
    gen_server:call(Id, stop, 30000).

checkout(Id) ->
    gen_server:call(Id, checkout).

checkin(Id, WorkerPid) ->
    gen_server:call(Id, {checkin, WorkerPid}).

status(Id) ->
    gen_server:call(Id, status).


%% ===================================================================
%% gen_server callbacks
%% ===================================================================
%% Function: init(Args) -> {ok, State}          |
%%                         {ok, State, Timeout} |
%%                         ignore               |
%%                         {stop, Reason}
%% Description: Initiates the server
init([NumOfChildren, MaxOverflow, WorkerMod, WorkerArgs]) ->
    {ok, Children} =
        start_child(NumOfChildren, WorkerMod, WorkerArgs, []),
    {ok, #state{num_of_children = NumOfChildren,
                max_overflow    = MaxOverflow,
                worker_mod      = WorkerMod,
                worker_args     = WorkerArgs,
                worker_pids     = Children}}.

handle_call(stop,_From,State) ->
    {stop, normal, ok, State};


%% @doc Checkout a worker
handle_call(checkout, _From, #state{worker_pids  = [],
                                    max_overflow = 0} = State) ->
    {reply, {error, empty}, State};

handle_call(checkout, _From, #state{worker_mod   = WorkerMod,
                                    worker_args  = WorkerArgs,
                                    worker_pids  = [],
                                    max_overflow = MaxOverflow} = State) ->
    {Res, NewState} =
        case start_child(WorkerMod, WorkerArgs) of
            {ok, ChildPid} ->
                {{ok, ChildPid},
                 State#state{max_overflow = MaxOverflow - 1}};
            {error, _Cause} ->
                {{error, empty}, State}
        end,
    {reply, Res, NewState};

handle_call(checkout, _From, #state{worker_pids  = Children} = State) ->
    [WorkerPid|NewChildren] = Children,
    {reply, {ok, WorkerPid}, State#state{worker_pids = NewChildren}};

%% @doc Checkin a worker
handle_call({checkin, WorkerPid}, _From, #state{worker_pids = Children} = State) ->
    NewChildren = [WorkerPid|Children],
    {reply, ok, State#state{worker_pids = NewChildren}};

%% @doc Retrieve the current status
handle_call(status, _From, State) ->
    {reply, {ok, State#state.worker_pids}, State}.


%% Function: handle_cast(Msg, State) -> {noreply, State}          |
%%                                      {noreply, State, Timeout} |
%%                                      {stop, Reason, State}
%% Description: Handling cast messages
handle_cast(_, State) ->
    {noreply, State}.


%% Function: handle_info(Info, State) -> {noreply, State}          |
%%                                       {noreply, State, Timeout} |
%%                                       {stop, Reason, State}
%% Description: Handling all non call/cast messages
handle_info({'DOWN', MonitorRef, _Type, Pid, _Info}, #state{worker_mod  = WorkerMod,
                                                            worker_args = WorkerArgs,
                                                            worker_pids = ChildPids} = State) ->
    true = erlang:demonitor(MonitorRef),

    ChildPids1 = lists:delete(Pid, ChildPids),
    ChildPids2 = case start_child(WorkerMod, WorkerArgs) of
                     {ok, ChildPid} ->
                         [ChildPid|ChildPids1];
                     _ ->
                         ChildPids1
                 end,
    {noreply, State#state{worker_pids = ChildPids2}};

handle_info(_Info, State) ->
{'fraction_non_alphanumeric': 0.1883245978673414, 'fraction_numerical': 0.00668714982830291, 'mean_word_length': 2.042056074766355, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 54, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 24, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7114657', 'n_tokens_mistral': 3110, 'n_tokens_neox': 2914, 'n_words': 697}