Просмотр исходного кода

Merge remote-tracking branch 'TanYewWei/issue-16'

* Fix trailing whitespace
Seth Falcon 11 лет назад
Родитель
Сommit
a245271648
2 измененных файлов с 81 добавлено и 3 удалено
  1. 39 1
      src/pooler.erl
  2. 42 2
      test/pooler_tests.erl

+ 39 - 1
src/pooler.erl

@@ -39,7 +39,8 @@
          manual_start/0,
          new_pool/1,
          pool_child_spec/1,
-         rm_pool/1]).
+         rm_pool/1,
+         rm_group/1]).
 
 %% ------------------------------------------------------------------
 %% gen_server Function Exports
@@ -120,6 +121,43 @@ new_pool(PoolConfig) ->
 rm_pool(PoolName) ->
     pooler_sup:rm_pool(PoolName).
 
+%% @doc Terminates the group and all pools in that group.
+%%
+%% If termination of any member pool fails, `rm_group/1` returns
+%% `{error, {failed_delete_pools, Pools}}`, where `Pools` is a list
+%% of pools that failed to terminate.
+%%
+%% The group is NOT terminated if any member pool did not
+%% successfully terminate.
+%%
+-spec rm_group(atom()) -> ok | {error, {failed_rm_pools, [atom()]}}.
+rm_group(GroupName) ->
+    case pg2:get_local_members(GroupName) of
+        {error, {no_such_group, GroupName}} ->
+            ok;
+        Pools ->
+            case rm_group_members(Pools) of
+                [] ->
+                    pg2:delete(GroupName);
+                Failures ->
+                    {error, {failed_rm_pools, Failures}}
+            end
+    end.
+
+-spec rm_group_members([pid()]) -> [atom()].
+rm_group_members(MemberPids) ->
+    lists:foldl(
+      fun(MemberPid, Acc) ->
+              Pool = gen_server:call(MemberPid, dump_pool),
+              PoolName = Pool#pool.name,
+              case pooler_sup:rm_pool(PoolName) of
+                  ok -> Acc;
+                  _  -> [PoolName | Acc]
+              end
+      end,
+      [],
+      MemberPids).
+
 %% @doc Get child spec described by the proplist `PoolConfig'.
 %%
 %% See {@link pooler:new_pool/1} for info about `PoolConfig'.

+ 42 - 2
test/pooler_tests.erl

@@ -449,7 +449,6 @@ pooler_groups_test_() ->
        fun() ->
                ?assertEqual(ok, pooler:return_group_member(group_1, error_no_members))
        end},
-      
 
       {"exhaust pools in group",
        fun() ->
@@ -465,9 +464,50 @@ pooler_groups_test_() ->
                 error_no_members,
                 error_no_members] = [ pooler:take_group_member(group_1)
                                       || _I <- lists:seq(1, 3) ]
+       end},
+
+      {"rm_group with nonexisting group",
+       fun() ->
+               ?assertEqual(ok, pooler:rm_group(i_dont_exist))
+       end},
+
+      {"rm_group with existing empty group",
+       fun() ->
+               ?assertEqual(ok, pooler:rm_pool(test_pool_1)),
+               ?assertEqual(ok, pooler:rm_pool(test_pool_2)),
+               ?assertEqual(error_no_members, pooler:take_group_member(group_1)),
+               ?assertEqual(ok, pooler:rm_group(group_1)),
+
+               ?assertExit({noproc, _}, pooler:take_member(test_pool_1)),
+               ?assertExit({noproc, _}, pooler:take_member(test_pool_2)),
+               ?assertEqual({error_no_group, group_1},
+                            pooler:take_group_member(group_1))
+       end},
+
+      {"rm_group with existing non-empty group",
+       fun() ->
+               %% Verify that group members exist
+               MemberPid = pooler:take_group_member(group_1),
+               ?assert(is_pid(MemberPid)),
+               pooler:return_group_member(group_1, MemberPid),
+
+               Pool1Pid = pooler:take_member(test_pool_1),
+               ?assert(is_pid(Pool1Pid)),
+               pooler:return_member(test_pool_1, Pool1Pid),
+
+               Pool2Pid = pooler:take_member(test_pool_2),
+               ?assert(is_pid(Pool2Pid)),
+               pooler:return_member(test_pool_2, Pool2Pid),
+
+               %% Delete and verify that group and pools are destroyed
+               ?assertEqual(ok, pooler:rm_group(group_1)),
+
+               ?assertExit({noproc, _}, pooler:take_member(test_pool_1)),
+               ?assertExit({noproc, _}, pooler:take_member(test_pool_2)),
+               ?assertEqual({error_no_group, group_1},
+                            pooler:take_group_member(group_1))
        end}
      ]}}.
-               
 
 pooler_limit_failed_adds_test_() ->
     %% verify that pooler crashes completely if too many failures are