Skip to content
Browse files

Rename take_pid => take_member and fix race in test code

  • Loading branch information...
1 parent 9d8b1d2 commit 456f4095959e06cf9f76eb7886dba8b43ff5a5c5 @seth seth committed Apr 3, 2011
Showing with 40 additions and 41 deletions.
  1. +3 −3 README.org
  2. +16 −16 src/pooler.erl
  3. +21 −22 test/pooler_test.erl
View
6 README.org
@@ -107,7 +107,7 @@ Here's an example session:
application:start(pooler).
P = pooler:take_member(),
% use P
-pooler:return_pid(P, ok).
+pooler:return_member(P, ok).
#+END_SRC
Once started, the main interaction you will have with pooler is through
@@ -186,9 +186,9 @@ Pool removal has two forms:
pool is removed.
#+BEGIN_SRC erlang
- -spec(take_pid() -> pid()).
+ -spec(take_member() -> pid()).
- -spec(return_pid(pid(), ok | fail) -> ignore).
+ -spec(return_member(pid(), ok | fail) -> ignore).
-spec(status() -> [term()]).
View
32 src/pooler.erl
@@ -31,8 +31,8 @@
-export([start/1,
start_link/1,
stop/0,
- take_pid/0,
- return_pid/2,
+ take_member/0,
+ return_member/2,
remove_pool/2,
add_pool/1,
pool_stats/1,
@@ -62,12 +62,12 @@ start(Config) ->
stop() ->
gen_server:call(?SERVER, stop).
-take_pid() ->
- gen_server:call(?SERVER, take_pid).
+take_member() ->
+ gen_server:call(?SERVER, take_member).
-return_pid(Pid, Status) when Status == ok; Status == fail ->
+return_member(Pid, Status) when Status == ok; Status == fail ->
CPid = self(),
- gen_server:cast(?SERVER, {return_pid, Pid, Status, CPid}),
+ gen_server:cast(?SERVER, {return_member, Pid, Status, CPid}),
ok.
remove_pool(Name, How) when How == graceful; How == immediate ->
@@ -106,10 +106,10 @@ init(Config) ->
process_flag(trap_exit, true),
{ok, State}.
-handle_call(take_pid, {CPid, _Tag}, State) ->
+handle_call(take_member, {CPid, _Tag}, State) ->
% FIXME: load-balance?
PoolName = hd(dict:fetch_keys(State#state.pools)),
- {NewPid, NewState} = take_pid(PoolName, CPid, State),
+ {NewPid, NewState} = take_member(PoolName, CPid, State),
{reply, NewPid, NewState};
handle_call(stop, _From, State) ->
% FIXME:
@@ -125,15 +125,15 @@ handle_call(_Request, _From, State) ->
{noreply, ok, State}.
-handle_cast({return_pid, Pid, Status, CPid}, State) ->
- {noreply, do_return_pid({Pid, Status}, CPid, State)};
+handle_cast({return_member, Pid, Status, CPid}, State) ->
+ {noreply, do_return_member({Pid, Status}, CPid, State)};
handle_cast(_Msg, State) ->
{noreply, State}.
handle_info({'EXIT', Pid, Reason}, State) ->
% error_logger:info_report({got_exit, Pid, Reason}),
State1 = case dict:find(Pid, State#state.in_use_pids) of
- {ok, {_PName, CPid}} -> do_return_pid({Pid, fail}, CPid, State);
+ {ok, {_PName, CPid}} -> do_return_member({Pid, fail}, CPid, State);
error ->
CPMap = State#state.consumer_to_pid,
case dict:find(Pid, CPMap) of
@@ -144,7 +144,7 @@ handle_info({'EXIT', Pid, Reason}, State) ->
_Crash -> fail
end,
lists:foldl(fun(P, S) ->
- do_return_pid({P, IsOk}, Pid, S)
+ do_return_member({P, IsOk}, Pid, S)
end, State, Pids);
error ->
State
@@ -194,7 +194,7 @@ add_pids(PoolName, N, State) ->
{max_count_reached, State}
end.
-take_pid(PoolName, From, State) ->
+take_member(PoolName, From, State) ->
#state{pools = Pools, in_use_pids = InUse, consumer_to_pid = CPMap} = State,
Pool = dict:fetch(PoolName, Pools),
#pool{max_count = Max, free_pids = Free, in_use_count = NumInUse} = Pool,
@@ -204,7 +204,7 @@ take_pid(PoolName, From, State) ->
[] when NumInUse < Max ->
case add_pids(PoolName, 1, State) of
{ok, State1} ->
- take_pid(PoolName, From, State1);
+ take_member(PoolName, From, State1);
{max_count_reached, _} ->
{error_no_pids, State}
end;
@@ -217,7 +217,7 @@ take_pid(PoolName, From, State) ->
consumer_to_pid = CPMap1}}
end.
-do_return_pid({Pid, Status}, CPid, State) ->
+do_return_member({Pid, Status}, CPid, State) ->
#state{in_use_pids = InUse, pools = Pools,
consumer_to_pid = CPMap} = State,
case dict:find(Pid, InUse) of
@@ -232,7 +232,7 @@ do_return_pid({Pid, Status}, CPid, State) ->
pools = dict:store(PoolName, Pool1, Pools),
consumer_to_pid = cpmap_remove(Pid, CPid, CPMap)};
error ->
- error_logger:warning_report({return_pid_not_found, Pid, dict:to_list(InUse)}),
+ error_logger:warning_report({return_member_not_found, Pid, dict:to_list(InUse)}),
State
end.
View
43 test/pooler_test.erl
@@ -9,10 +9,7 @@
% and take a new pid, stop cleanly, and crash.
start_user() ->
- spawn(fun() ->
- TC = pooler:take_pid(),
- user_loop(TC)
- end).
+ spawn(fun() -> user_loop(start) end).
user_id(Pid) ->
Pid ! {get_tc_id, self()},
@@ -30,6 +27,8 @@ user_stop(Pid) ->
user_crash(Pid) ->
Pid ! crash.
+user_loop(Atom) when Atom =:= error_no_pids orelse Atom =:= start ->
+ user_loop(pooler:take_member());
user_loop(MyTC) ->
receive
{get_tc_id, From} ->
@@ -42,11 +41,11 @@ user_loop(MyTC) ->
From ! pooled_gs:ping_count(MyTC),
user_loop(MyTC);
new_tc ->
- pooler:return_pid(MyTC, ok),
- MyNewTC = pooler:take_pid(),
+ pooler:return_member(MyTC, ok),
+ MyNewTC = pooler:take_member(),
user_loop(MyNewTC);
stop ->
- pooler:return_pid(MyTC, ok),
+ pooler:return_member(MyTC, ok),
stopped;
crash ->
erlang:error({user_loop, kaboom})
@@ -120,16 +119,16 @@ pooler_basics_test_() ->
[
{"take and return one",
fun() ->
- P = pooler:take_pid(),
+ P = pooler:take_member(),
?assertMatch({"type-0", _Id}, pooled_gs:get_id(P)),
- ok = pooler:return_pid(P, ok)
+ ok = pooler:return_member(P, ok)
end},
{"pids are created on demand until max",
fun() ->
- Pids = [pooler:take_pid(), pooler:take_pid(), pooler:take_pid()],
- ?assertMatch(error_no_pids, pooler:take_pid()),
- ?assertMatch(error_no_pids, pooler:take_pid()),
+ Pids = [pooler:take_member(), pooler:take_member(), pooler:take_member()],
+ ?assertMatch(error_no_pids, pooler:take_member()),
+ ?assertMatch(error_no_pids, pooler:take_member()),
PRefs = [ R || {_T, R} <- [ pooled_gs:get_id(P) || P <- Pids ] ],
% no duplicates
?assertEqual(length(PRefs), length(lists:usort(PRefs)))
@@ -138,19 +137,19 @@ pooler_basics_test_() ->
{"pids are reused most recent return first",
fun() ->
- P1 = pooler:take_pid(),
- P2 = pooler:take_pid(),
+ P1 = pooler:take_member(),
+ P2 = pooler:take_member(),
?assertNot(P1 == P2),
- ok = pooler:return_pid(P1, ok),
- ok = pooler:return_pid(P2, ok),
+ ok = pooler:return_member(P1, ok),
+ ok = pooler:return_member(P2, ok),
% pids are reused most recent first
- ?assertEqual(P2, pooler:take_pid()),
- ?assertEqual(P1, pooler:take_pid())
+ ?assertEqual(P2, pooler:take_member()),
+ ?assertEqual(P1, pooler:take_member())
end},
{"if a pid crashes it is replaced",
fun() ->
- Pids0 = [pooler:take_pid(), pooler:take_pid(), pooler:take_pid()],
+ Pids0 = [pooler:take_member(), pooler:take_member(), pooler:take_member()],
Ids0 = [ pooled_gs:get_id(P) || P <- Pids0 ],
% crash them all
[ pooled_gs:crash(P) || P <- Pids0 ],
@@ -162,10 +161,10 @@ pooler_basics_test_() ->
{"if a pid is returned with bad status it is replaced",
fun() ->
- Pids0 = [pooler:take_pid(), pooler:take_pid(), pooler:take_pid()],
+ Pids0 = [pooler:take_member(), pooler:take_member(), pooler:take_member()],
Ids0 = [ pooled_gs:get_id(P) || P <- Pids0 ],
% return them all marking as bad
- [ pooler:return_pid(P, fail) || P <- Pids0 ],
+ [ pooler:return_member(P, fail) || P <- Pids0 ],
Pids1 = get_n_pids(3, []),
Ids1 = [ pooled_gs:get_id(P) || P <- Pids1 ],
[ ?assertNot(lists:member(I, Ids0)) || I <- Ids1 ]
@@ -248,7 +247,7 @@ pooler_integration_test_() ->
get_n_pids(0, Acc) ->
Acc;
get_n_pids(N, Acc) ->
- case pooler:take_pid() of
+ case pooler:take_member() of
error_no_pids ->
get_n_pids(N, Acc);
Pid ->

0 comments on commit 456f409

Please sign in to comment.
Something went wrong with that request. Please try again.