aboutsummaryrefslogtreecommitdiff
path: root/server/_build/default/lib/poolboy
diff options
context:
space:
mode:
Diffstat (limited to 'server/_build/default/lib/poolboy')
-rw-r--r--server/_build/default/lib/poolboy/LICENSE15
-rw-r--r--server/_build/default/lib/poolboy/README.md171
-rw-r--r--server/_build/default/lib/poolboy/ebin/poolboy.app9
-rw-r--r--server/_build/default/lib/poolboy/ebin/poolboy.beambin0 -> 17524 bytes
-rw-r--r--server/_build/default/lib/poolboy/ebin/poolboy_sup.beambin0 -> 1804 bytes
-rw-r--r--server/_build/default/lib/poolboy/ebin/poolboy_worker.beambin0 -> 1560 bytes
-rw-r--r--server/_build/default/lib/poolboy/hex_metadata.config15
-rw-r--r--server/_build/default/lib/poolboy/rebar.config15
-rw-r--r--server/_build/default/lib/poolboy/rebar.lock1
-rw-r--r--server/_build/default/lib/poolboy/src/poolboy.app.src8
-rw-r--r--server/_build/default/lib/poolboy/src/poolboy.erl357
-rw-r--r--server/_build/default/lib/poolboy/src/poolboy_sup.erl14
-rw-r--r--server/_build/default/lib/poolboy/src/poolboy_worker.erl10
13 files changed, 615 insertions, 0 deletions
diff --git a/server/_build/default/lib/poolboy/LICENSE b/server/_build/default/lib/poolboy/LICENSE
new file mode 100644
index 0000000..ce34eab
--- /dev/null
+++ b/server/_build/default/lib/poolboy/LICENSE
@@ -0,0 +1,15 @@
+ISC License
+
+Copyright (c) 2014, Devin Alexander Torres <devin@devintorr.es>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/server/_build/default/lib/poolboy/README.md b/server/_build/default/lib/poolboy/README.md
new file mode 100644
index 0000000..495d812
--- /dev/null
+++ b/server/_build/default/lib/poolboy/README.md
@@ -0,0 +1,171 @@
+# Poolboy - A hunky Erlang worker pool factory
+
+[![Build Status](https://api.travis-ci.org/devinus/poolboy.svg?branch=master)](https://travis-ci.org/devinus/poolboy)
+
+[![Support via Gratipay](https://cdn.rawgit.com/gratipay/gratipay-badge/2.3.0/dist/gratipay.png)](https://gratipay.com/devinus/)
+
+Poolboy is a **lightweight**, **generic** pooling library for Erlang with a
+focus on **simplicity**, **performance**, and **rock-solid** disaster recovery.
+
+## Usage
+
+```erl-sh
+1> Worker = poolboy:checkout(PoolName).
+<0.9001.0>
+2> gen_server:call(Worker, Request).
+ok
+3> poolboy:checkin(PoolName, Worker).
+ok
+```
+
+## Example
+
+This is an example application showcasing database connection pools using
+Poolboy and [epgsql](https://github.com/epgsql/epgsql).
+
+### example.app
+
+```erlang
+{application, example, [
+ {description, "An example application"},
+ {vsn, "0.1"},
+ {applications, [kernel, stdlib, sasl, crypto, ssl]},
+ {modules, [example, example_worker]},
+ {registered, [example]},
+ {mod, {example, []}},
+ {env, [
+ {pools, [
+ {pool1, [
+ {size, 10},
+ {max_overflow, 20}
+ ], [
+ {hostname, "127.0.0.1"},
+ {database, "db1"},
+ {username, "db1"},
+ {password, "abc123"}
+ ]},
+ {pool2, [
+ {size, 5},
+ {max_overflow, 10}
+ ], [
+ {hostname, "127.0.0.1"},
+ {database, "db2"},
+ {username, "db2"},
+ {password, "abc123"}
+ ]}
+ ]}
+ ]}
+]}.
+```
+
+### example.erl
+
+```erlang
+-module(example).
+-behaviour(application).
+-behaviour(supervisor).
+
+-export([start/0, stop/0, squery/2, equery/3]).
+-export([start/2, stop/1]).
+-export([init/1]).
+
+start() ->
+ application:start(?MODULE).
+
+stop() ->
+ application:stop(?MODULE).
+
+start(_Type, _Args) ->
+ supervisor:start_link({local, example_sup}, ?MODULE, []).
+
+stop(_State) ->
+ ok.
+
+init([]) ->
+ {ok, Pools} = application:get_env(example, pools),
+ PoolSpecs = lists:map(fun({Name, SizeArgs, WorkerArgs}) ->
+ PoolArgs = [{name, {local, Name}},
+ {worker_module, example_worker}] ++ SizeArgs,
+ poolboy:child_spec(Name, PoolArgs, WorkerArgs)
+ end, Pools),
+ {ok, {{one_for_one, 10, 10}, PoolSpecs}}.
+
+squery(PoolName, Sql) ->
+ poolboy:transaction(PoolName, fun(Worker) ->
+ gen_server:call(Worker, {squery, Sql})
+ end).
+
+equery(PoolName, Stmt, Params) ->
+ poolboy:transaction(PoolName, fun(Worker) ->
+ gen_server:call(Worker, {equery, Stmt, Params})
+ end).
+```
+
+### example_worker.erl
+
+```erlang
+-module(example_worker).
+-behaviour(gen_server).
+-behaviour(poolboy_worker).
+
+-export([start_link/1]).
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
+ code_change/3]).
+
+-record(state, {conn}).
+
+start_link(Args) ->
+ gen_server:start_link(?MODULE, Args, []).
+
+init(Args) ->
+ process_flag(trap_exit, true),
+ Hostname = proplists:get_value(hostname, Args),
+ Database = proplists:get_value(database, Args),
+ Username = proplists:get_value(username, Args),
+ Password = proplists:get_value(password, Args),
+ {ok, Conn} = epgsql:connect(Hostname, Username, Password, [
+ {database, Database}
+ ]),
+ {ok, #state{conn=Conn}}.
+
+handle_call({squery, Sql}, _From, #state{conn=Conn}=State) ->
+ {reply, epgsql:squery(Conn, Sql), State};
+handle_call({equery, Stmt, Params}, _From, #state{conn=Conn}=State) ->
+ {reply, epgsql:equery(Conn, Stmt, Params), State};
+handle_call(_Request, _From, State) ->
+ {reply, ok, State}.
+
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+terminate(_Reason, #state{conn=Conn}) ->
+ ok = epgsql:close(Conn),
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+```
+
+## Options
+
+- `name`: the pool name
+- `worker_module`: the module that represents the workers
+- `size`: maximum pool size
+- `max_overflow`: maximum number of workers created if pool is empty
+- `strategy`: `lifo` or `fifo`, determines whether checked in workers should be
+ placed first or last in the line of available workers. So, `lifo` operates like a traditional stack; `fifo` like a queue. Default is `lifo`.
+
+## Authors
+
+- Devin Torres (devinus) <devin@devintorres.com>
+- Andrew Thompson (Vagabond) <andrew@hijacked.us>
+- Kurt Williams (onkel-dirtus) <kurt.r.williams@gmail.com>
+
+## License
+
+Poolboy is available in the public domain (see `UNLICENSE`).
+Poolboy is also optionally available under the ISC license (see `LICENSE`),
+meant especially for jurisdictions that do not recognize public domain works.
diff --git a/server/_build/default/lib/poolboy/ebin/poolboy.app b/server/_build/default/lib/poolboy/ebin/poolboy.app
new file mode 100644
index 0000000..228edc3
--- /dev/null
+++ b/server/_build/default/lib/poolboy/ebin/poolboy.app
@@ -0,0 +1,9 @@
+{application,poolboy,
+ [{description,"A hunky Erlang worker pool factory"},
+ {vsn,"1.5.2"},
+ {applications,[kernel,stdlib]},
+ {registered,[poolboy]},
+ {maintainers,["Devin Torres","Andrew Thompson","Kurt Williams"]},
+ {licenses,["Unlicense","Apache 2.0"]},
+ {links,[{"GitHub","https://github.com/devinus/poolboy"}]},
+ {modules,[poolboy,poolboy_sup,poolboy_worker]}]}.
diff --git a/server/_build/default/lib/poolboy/ebin/poolboy.beam b/server/_build/default/lib/poolboy/ebin/poolboy.beam
new file mode 100644
index 0000000..c6a0e49
--- /dev/null
+++ b/server/_build/default/lib/poolboy/ebin/poolboy.beam
Binary files differ
diff --git a/server/_build/default/lib/poolboy/ebin/poolboy_sup.beam b/server/_build/default/lib/poolboy/ebin/poolboy_sup.beam
new file mode 100644
index 0000000..76226d6
--- /dev/null
+++ b/server/_build/default/lib/poolboy/ebin/poolboy_sup.beam
Binary files differ
diff --git a/server/_build/default/lib/poolboy/ebin/poolboy_worker.beam b/server/_build/default/lib/poolboy/ebin/poolboy_worker.beam
new file mode 100644
index 0000000..c4f0656
--- /dev/null
+++ b/server/_build/default/lib/poolboy/ebin/poolboy_worker.beam
Binary files differ
diff --git a/server/_build/default/lib/poolboy/hex_metadata.config b/server/_build/default/lib/poolboy/hex_metadata.config
new file mode 100644
index 0000000..4b24846
--- /dev/null
+++ b/server/_build/default/lib/poolboy/hex_metadata.config
@@ -0,0 +1,15 @@
+{<<"name">>,<<"poolboy">>}.
+{<<"version">>,<<"1.5.2">>}.
+{<<"requirements">>,#{}}.
+{<<"app">>,<<"poolboy">>}.
+{<<"maintainers">>,
+ [<<"Devin Torres">>,<<"Andrew Thompson">>,<<"Kurt Williams">>]}.
+{<<"precompiled">>,false}.
+{<<"description">>,<<"A hunky Erlang worker pool factory">>}.
+{<<"files">>,
+ [<<"src/poolboy.app.src">>,<<"LICENSE">>,<<"README.md">>,<<"rebar.config">>,
+ <<"rebar.lock">>,<<"src/poolboy.erl">>,<<"src/poolboy_sup.erl">>,
+ <<"src/poolboy_worker.erl">>]}.
+{<<"licenses">>,[<<"Unlicense">>,<<"Apache 2.0">>]}.
+{<<"links">>,[{<<"GitHub">>,<<"https://github.com/devinus/poolboy">>}]}.
+{<<"build_tools">>,[<<"rebar3">>]}.
diff --git a/server/_build/default/lib/poolboy/rebar.config b/server/_build/default/lib/poolboy/rebar.config
new file mode 100644
index 0000000..1d494ca
--- /dev/null
+++ b/server/_build/default/lib/poolboy/rebar.config
@@ -0,0 +1,15 @@
+{erl_opts, [
+ debug_info,
+ {platform_define, "^R", pre17}
+]}.
+
+{eunit_opts, [verbose]}.
+{cover_enabled, true}.
+
+{profiles, [
+ {test, [
+ {plugins, [
+ {rebar3_eqc, ".*", {git, "https://github.com/kellymclaughlin/rebar3-eqc-plugin.git", {tag, "0.1.0"}}}
+ ]}
+ ]
+}]}.
diff --git a/server/_build/default/lib/poolboy/rebar.lock b/server/_build/default/lib/poolboy/rebar.lock
new file mode 100644
index 0000000..57afcca
--- /dev/null
+++ b/server/_build/default/lib/poolboy/rebar.lock
@@ -0,0 +1 @@
+[].
diff --git a/server/_build/default/lib/poolboy/src/poolboy.app.src b/server/_build/default/lib/poolboy/src/poolboy.app.src
new file mode 100644
index 0000000..5119212
--- /dev/null
+++ b/server/_build/default/lib/poolboy/src/poolboy.app.src
@@ -0,0 +1,8 @@
+{application,poolboy,
+ [{description,"A hunky Erlang worker pool factory"},
+ {vsn,"1.5.2"},
+ {applications,[kernel,stdlib]},
+ {registered,[poolboy]},
+ {maintainers,["Devin Torres","Andrew Thompson","Kurt Williams"]},
+ {licenses,["Unlicense","Apache 2.0"]},
+ {links,[{"GitHub","https://github.com/devinus/poolboy"}]}]}.
diff --git a/server/_build/default/lib/poolboy/src/poolboy.erl b/server/_build/default/lib/poolboy/src/poolboy.erl
new file mode 100644
index 0000000..0023412
--- /dev/null
+++ b/server/_build/default/lib/poolboy/src/poolboy.erl
@@ -0,0 +1,357 @@
+%% Poolboy - A hunky Erlang worker pool factory
+
+-module(poolboy).
+-behaviour(gen_server).
+
+-export([checkout/1, checkout/2, checkout/3, checkin/2, transaction/2,
+ transaction/3, child_spec/2, child_spec/3, start/1, start/2,
+ start_link/1, start_link/2, stop/1, status/1]).
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
+ code_change/3]).
+-export_type([pool/0]).
+
+-define(TIMEOUT, 5000).
+
+-ifdef(pre17).
+-type pid_queue() :: queue().
+-else.
+-type pid_queue() :: queue:queue().
+-endif.
+
+-ifdef(OTP_RELEASE). %% this implies 21 or higher
+-define(EXCEPTION(Class, Reason, Stacktrace), Class:Reason:Stacktrace).
+-define(GET_STACK(Stacktrace), Stacktrace).
+-else.
+-define(EXCEPTION(Class, Reason, _), Class:Reason).
+-define(GET_STACK(_), erlang:get_stacktrace()).
+-endif.
+
+-type pool() ::
+ Name :: (atom() | pid()) |
+ {Name :: atom(), node()} |
+ {local, Name :: atom()} |
+ {global, GlobalName :: any()} |
+ {via, Module :: atom(), ViaName :: any()}.
+
+% Copied from gen:start_ret/0
+-type start_ret() :: {'ok', pid()} | 'ignore' | {'error', term()}.
+
+-record(state, {
+ supervisor :: undefined | pid(),
+ workers = [] :: [pid()],
+ waiting :: pid_queue(),
+ monitors :: ets:tid(),
+ size = 5 :: non_neg_integer(),
+ overflow = 0 :: non_neg_integer(),
+ max_overflow = 10 :: non_neg_integer(),
+ strategy = lifo :: lifo | fifo
+}).
+
+-spec checkout(Pool :: pool()) -> pid().
+checkout(Pool) ->
+ checkout(Pool, true).
+
+-spec checkout(Pool :: pool(), Block :: boolean()) -> pid() | full.
+checkout(Pool, Block) ->
+ checkout(Pool, Block, ?TIMEOUT).
+
+-spec checkout(Pool :: pool(), Block :: boolean(), Timeout :: timeout())
+ -> pid() | full.
+checkout(Pool, Block, Timeout) ->
+ CRef = make_ref(),
+ try
+ gen_server:call(Pool, {checkout, CRef, Block}, Timeout)
+ catch
+ ?EXCEPTION(Class, Reason, Stacktrace) ->
+ gen_server:cast(Pool, {cancel_waiting, CRef}),
+ erlang:raise(Class, Reason, ?GET_STACK(Stacktrace))
+ end.
+
+-spec checkin(Pool :: pool(), Worker :: pid()) -> ok.
+checkin(Pool, Worker) when is_pid(Worker) ->
+ gen_server:cast(Pool, {checkin, Worker}).
+
+-spec transaction(Pool :: pool(), Fun :: fun((Worker :: pid()) -> any()))
+ -> any().
+transaction(Pool, Fun) ->
+ transaction(Pool, Fun, ?TIMEOUT).
+
+-spec transaction(Pool :: pool(), Fun :: fun((Worker :: pid()) -> any()),
+ Timeout :: timeout()) -> any().
+transaction(Pool, Fun, Timeout) ->
+ Worker = poolboy:checkout(Pool, true, Timeout),
+ try
+ Fun(Worker)
+ after
+ ok = poolboy:checkin(Pool, Worker)
+ end.
+
+-spec child_spec(PoolId :: term(), PoolArgs :: proplists:proplist())
+ -> supervisor:child_spec().
+child_spec(PoolId, PoolArgs) ->
+ child_spec(PoolId, PoolArgs, []).
+
+-spec child_spec(PoolId :: term(),
+ PoolArgs :: proplists:proplist(),
+ WorkerArgs :: proplists:proplist())
+ -> supervisor:child_spec().
+child_spec(PoolId, PoolArgs, WorkerArgs) ->
+ {PoolId, {poolboy, start_link, [PoolArgs, WorkerArgs]},
+ permanent, 5000, worker, [poolboy]}.
+
+-spec start(PoolArgs :: proplists:proplist())
+ -> start_ret().
+start(PoolArgs) ->
+ start(PoolArgs, PoolArgs).
+
+-spec start(PoolArgs :: proplists:proplist(),
+ WorkerArgs:: proplists:proplist())
+ -> start_ret().
+start(PoolArgs, WorkerArgs) ->
+ start_pool(start, PoolArgs, WorkerArgs).
+
+-spec start_link(PoolArgs :: proplists:proplist())
+ -> start_ret().
+start_link(PoolArgs) ->
+ %% for backwards compatability, pass the pool args as the worker args as well
+ start_link(PoolArgs, PoolArgs).
+
+-spec start_link(PoolArgs :: proplists:proplist(),
+ WorkerArgs:: proplists:proplist())
+ -> start_ret().
+start_link(PoolArgs, WorkerArgs) ->
+ start_pool(start_link, PoolArgs, WorkerArgs).
+
+-spec stop(Pool :: pool()) -> ok.
+stop(Pool) ->
+ gen_server:call(Pool, stop).
+
+-spec status(Pool :: pool()) -> {atom(), integer(), integer(), integer()}.
+status(Pool) ->
+ gen_server:call(Pool, status).
+
+init({PoolArgs, WorkerArgs}) ->
+ process_flag(trap_exit, true),
+ Waiting = queue:new(),
+ Monitors = ets:new(monitors, [private]),
+ init(PoolArgs, WorkerArgs, #state{waiting = Waiting, monitors = Monitors}).
+
+init([{worker_module, Mod} | Rest], WorkerArgs, State) when is_atom(Mod) ->
+ {ok, Sup} = poolboy_sup:start_link(Mod, WorkerArgs),
+ init(Rest, WorkerArgs, State#state{supervisor = Sup});
+init([{size, Size} | Rest], WorkerArgs, State) when is_integer(Size) ->
+ init(Rest, WorkerArgs, State#state{size = Size});
+init([{max_overflow, MaxOverflow} | Rest], WorkerArgs, State) when is_integer(MaxOverflow) ->
+ init(Rest, WorkerArgs, State#state{max_overflow = MaxOverflow});
+init([{strategy, lifo} | Rest], WorkerArgs, State) ->
+ init(Rest, WorkerArgs, State#state{strategy = lifo});
+init([{strategy, fifo} | Rest], WorkerArgs, State) ->
+ init(Rest, WorkerArgs, State#state{strategy = fifo});
+init([_ | Rest], WorkerArgs, State) ->
+ init(Rest, WorkerArgs, State);
+init([], _WorkerArgs, #state{size = Size, supervisor = Sup} = State) ->
+ Workers = prepopulate(Size, Sup),
+ {ok, State#state{workers = Workers}}.
+
+handle_cast({checkin, Pid}, State = #state{monitors = Monitors}) ->
+ case ets:lookup(Monitors, Pid) of
+ [{Pid, _, MRef}] ->
+ true = erlang:demonitor(MRef),
+ true = ets:delete(Monitors, Pid),
+ NewState = handle_checkin(Pid, State),
+ {noreply, NewState};
+ [] ->
+ {noreply, State}
+ end;
+
+handle_cast({cancel_waiting, CRef}, State) ->
+ case ets:match(State#state.monitors, {'$1', CRef, '$2'}) of
+ [[Pid, MRef]] ->
+ demonitor(MRef, [flush]),
+ true = ets:delete(State#state.monitors, Pid),
+ NewState = handle_checkin(Pid, State),
+ {noreply, NewState};
+ [] ->
+ Cancel = fun({_, Ref, MRef}) when Ref =:= CRef ->
+ demonitor(MRef, [flush]),
+ false;
+ (_) ->
+ true
+ end,
+ Waiting = queue:filter(Cancel, State#state.waiting),
+ {noreply, State#state{waiting = Waiting}}
+ end;
+
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+handle_call({checkout, CRef, Block}, {FromPid, _} = From, State) ->
+ #state{supervisor = Sup,
+ workers = Workers,
+ monitors = Monitors,
+ overflow = Overflow,
+ max_overflow = MaxOverflow} = State,
+ case Workers of
+ [Pid | Left] ->
+ MRef = erlang:monitor(process, FromPid),
+ true = ets:insert(Monitors, {Pid, CRef, MRef}),
+ {reply, Pid, State#state{workers = Left}};
+ [] when MaxOverflow > 0, Overflow < MaxOverflow ->
+ {Pid, MRef} = new_worker(Sup, FromPid),
+ true = ets:insert(Monitors, {Pid, CRef, MRef}),
+ {reply, Pid, State#state{overflow = Overflow + 1}};
+ [] when Block =:= false ->
+ {reply, full, State};
+ [] ->
+ MRef = erlang:monitor(process, FromPid),
+ Waiting = queue:in({From, CRef, MRef}, State#state.waiting),
+ {noreply, State#state{waiting = Waiting}}
+ end;
+
+handle_call(status, _From, State) ->
+ #state{workers = Workers,
+ monitors = Monitors,
+ overflow = Overflow} = State,
+ StateName = state_name(State),
+ {reply, {StateName, length(Workers), Overflow, ets:info(Monitors, size)}, State};
+handle_call(get_avail_workers, _From, State) ->
+ Workers = State#state.workers,
+ {reply, Workers, State};
+handle_call(get_all_workers, _From, State) ->
+ Sup = State#state.supervisor,
+ WorkerList = supervisor:which_children(Sup),
+ {reply, WorkerList, State};
+handle_call(get_all_monitors, _From, State) ->
+ Monitors = ets:select(State#state.monitors,
+ [{{'$1', '_', '$2'}, [], [{{'$1', '$2'}}]}]),
+ {reply, Monitors, State};
+handle_call(stop, _From, State) ->
+ {stop, normal, ok, State};
+handle_call(_Msg, _From, State) ->
+ Reply = {error, invalid_message},
+ {reply, Reply, State}.
+
+handle_info({'DOWN', MRef, _, _, _}, State) ->
+ case ets:match(State#state.monitors, {'$1', '_', MRef}) of
+ [[Pid]] ->
+ true = ets:delete(State#state.monitors, Pid),
+ NewState = handle_checkin(Pid, State),
+ {noreply, NewState};
+ [] ->
+ Waiting = queue:filter(fun ({_, _, R}) -> R =/= MRef end, State#state.waiting),
+ {noreply, State#state{waiting = Waiting}}
+ end;
+handle_info({'EXIT', Pid, _Reason}, State) ->
+ #state{supervisor = Sup,
+ monitors = Monitors} = State,
+ case ets:lookup(Monitors, Pid) of
+ [{Pid, _, MRef}] ->
+ true = erlang:demonitor(MRef),
+ true = ets:delete(Monitors, Pid),
+ NewState = handle_worker_exit(Pid, State),
+ {noreply, NewState};
+ [] ->
+ case lists:member(Pid, State#state.workers) of
+ true ->
+ W = lists:filter(fun (P) -> P =/= Pid end, State#state.workers),
+ {noreply, State#state{workers = [new_worker(Sup) | W]}};
+ false ->
+ {noreply, State}
+ end
+ end;
+
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+terminate(_Reason, State) ->
+ ok = lists:foreach(fun (W) -> unlink(W) end, State#state.workers),
+ true = exit(State#state.supervisor, shutdown),
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+start_pool(StartFun, PoolArgs, WorkerArgs) ->
+ case proplists:get_value(name, PoolArgs) of
+ undefined ->
+ gen_server:StartFun(?MODULE, {PoolArgs, WorkerArgs}, []);
+ Name ->
+ gen_server:StartFun(Name, ?MODULE, {PoolArgs, WorkerArgs}, [])
+ end.
+
+new_worker(Sup) ->
+ {ok, Pid} = supervisor:start_child(Sup, []),
+ true = link(Pid),
+ Pid.
+
+new_worker(Sup, FromPid) ->
+ Pid = new_worker(Sup),
+ Ref = erlang:monitor(process, FromPid),
+ {Pid, Ref}.
+
+dismiss_worker(Sup, Pid) ->
+ true = unlink(Pid),
+ supervisor:terminate_child(Sup, Pid).
+
+prepopulate(N, _Sup) when N < 1 ->
+ [];
+prepopulate(N, Sup) ->
+ prepopulate(N, Sup, []).
+
+prepopulate(0, _Sup, Workers) ->
+ Workers;
+prepopulate(N, Sup, Workers) ->
+ prepopulate(N-1, Sup, [new_worker(Sup) | Workers]).
+
+handle_checkin(Pid, State) ->
+ #state{supervisor = Sup,
+ waiting = Waiting,
+ monitors = Monitors,
+ overflow = Overflow,
+ strategy = Strategy} = State,
+ case queue:out(Waiting) of
+ {{value, {From, CRef, MRef}}, Left} ->
+ true = ets:insert(Monitors, {Pid, CRef, MRef}),
+ gen_server:reply(From, Pid),
+ State#state{waiting = Left};
+ {empty, Empty} when Overflow > 0 ->
+ ok = dismiss_worker(Sup, Pid),
+ State#state{waiting = Empty, overflow = Overflow - 1};
+ {empty, Empty} ->
+ Workers = case Strategy of
+ lifo -> [Pid | State#state.workers];
+ fifo -> State#state.workers ++ [Pid]
+ end,
+ State#state{workers = Workers, waiting = Empty, overflow = 0}
+ end.
+
+handle_worker_exit(Pid, State) ->
+ #state{supervisor = Sup,
+ monitors = Monitors,
+ overflow = Overflow} = State,
+ case queue:out(State#state.waiting) of
+ {{value, {From, CRef, MRef}}, LeftWaiting} ->
+ NewWorker = new_worker(State#state.supervisor),
+ true = ets:insert(Monitors, {NewWorker, CRef, MRef}),
+ gen_server:reply(From, NewWorker),
+ State#state{waiting = LeftWaiting};
+ {empty, Empty} when Overflow > 0 ->
+ State#state{overflow = Overflow - 1, waiting = Empty};
+ {empty, Empty} ->
+ Workers =
+ [new_worker(Sup)
+ | lists:filter(fun (P) -> P =/= Pid end, State#state.workers)],
+ State#state{workers = Workers, waiting = Empty}
+ end.
+
+state_name(State = #state{overflow = Overflow}) when Overflow < 1 ->
+ #state{max_overflow = MaxOverflow, workers = Workers} = State,
+ case length(Workers) == 0 of
+ true when MaxOverflow < 1 -> full;
+ true -> overflow;
+ false -> ready
+ end;
+state_name(#state{overflow = MaxOverflow, max_overflow = MaxOverflow}) ->
+ full;
+state_name(_State) ->
+ overflow.
diff --git a/server/_build/default/lib/poolboy/src/poolboy_sup.erl b/server/_build/default/lib/poolboy/src/poolboy_sup.erl
new file mode 100644
index 0000000..e6485a6
--- /dev/null
+++ b/server/_build/default/lib/poolboy/src/poolboy_sup.erl
@@ -0,0 +1,14 @@
+%% Poolboy - A hunky Erlang worker pool factory
+
+-module(poolboy_sup).
+-behaviour(supervisor).
+
+-export([start_link/2, init/1]).
+
+start_link(Mod, Args) ->
+ supervisor:start_link(?MODULE, {Mod, Args}).
+
+init({Mod, Args}) ->
+ {ok, {{simple_one_for_one, 0, 1},
+ [{Mod, {Mod, start_link, [Args]},
+ temporary, 5000, worker, [Mod]}]}}.
diff --git a/server/_build/default/lib/poolboy/src/poolboy_worker.erl b/server/_build/default/lib/poolboy/src/poolboy_worker.erl
new file mode 100644
index 0000000..4a5bfae
--- /dev/null
+++ b/server/_build/default/lib/poolboy/src/poolboy_worker.erl
@@ -0,0 +1,10 @@
+%% Poolboy - A hunky Erlang worker pool factory
+
+-module(poolboy_worker).
+
+-callback start_link(WorkerArgs) -> {ok, Pid} |
+ {error, {already_started, Pid}} |
+ {error, Reason} when
+ WorkerArgs :: proplists:proplist(),
+ Pid :: pid(),
+ Reason :: term().