Skip to content

Commit

Permalink
implement deletion of guarded handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
argv0 committed Apr 1, 2011
1 parent 9aced05 commit dc64975
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 22 deletions.
21 changes: 20 additions & 1 deletion src/riak_core.erl
Expand Up @@ -23,7 +23,7 @@
-export([stop/0, stop/1]).
-export([register_vnode_module/1, vnode_modules/0]).
-export([add_guarded_event_handler/3, add_guarded_event_handler/4]).

-export([delete_guarded_event_handler/3]).

%% @spec stop() -> ok
%% @doc Stop the riak application and the calling process.
Expand Down Expand Up @@ -76,6 +76,25 @@ add_guarded_event_handler(HandlerMod, Handler, Args) ->
add_guarded_event_handler(HandlerMod, Handler, Args, ExitFun) ->
riak_core_eventhandler_sup:start_guarded_handler(HandlerMod, Handler, Args, ExitFun).

%% @spec delete_guarded_event_handler(HandlerMod, Handler, Args) -> Result
%% HandlerMod = module()
%% Handler = module() | {module(), term()}
%% Args = term()
%% Result = term() | {error, module_not_found} | {'EXIT', Reason}
%% Reason = term()
%%
%% @doc Delete a guarded event handler from a gen_event instance.
%%
%% Args is an arbitrary term which is passed as one of the arguments to
%% Module:terminate/2.
%%
%% The return value is the return value of Module:terminate/2. If the
%% specified event handler is not installed, the function returns
%% {error,module_not_found}. If the callback function fails with Reason,
%% the function returns {'EXIT',Reason}.
delete_guarded_event_handler(HandlerMod, Handler, Args) ->
riak_core_eventhandler_sup:stop_guarded_handler(HandlerMod, Handler, Args).

app_for_module(Mod) ->
app_for_module(application:which_applications(), Mod).

Expand Down
12 changes: 4 additions & 8 deletions src/riak_core_eventhandler_guard.erl
Expand Up @@ -42,14 +42,14 @@ handle_cast(_Msg, State) -> {noreply, State}.


handle_info({gen_event_EXIT, _Handler, shutdown}, State) ->
{stop, shutdown, State};
handle_info({gen_event_EXIT, _Handler, normal}, State) ->
{stop, normal, State};
handle_info({gen_event_EXIT, _Handler, _Reason}, State=#state{exitfun=undefined}) ->
handle_info({gen_event_EXIT, _Handler, normal}, State) ->
{stop, normal, State};
handle_info({gen_event_EXIT, Handler, _Reason}, State=#state{exitfun=undefined}) ->
{stop, {gen_event_EXIT, Handler}, State};
handle_info({gen_event_EXIT, Handler, Reason}, State=#state{exitfun=ExitFun}) ->
ExitFun(Handler, Reason),
{stop, normal, State};
{stop, {gen_event_EXIT, Handler}, State};
handle_info(_Info, State) ->
{noreply, State}.

Expand All @@ -58,7 +58,3 @@ terminate(_Reason, #state{}) ->

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

%default_exitfun(Handler, _Reason) ->
% error_logger:error_msg(" ~s: handler ~w exited",
% [?MODULE, Handler]).

20 changes: 18 additions & 2 deletions src/riak_core_eventhandler_sup.erl
Expand Up @@ -24,7 +24,7 @@
-module(riak_core_eventhandler_sup).
-behaviour(supervisor).
-export([start_link/0, init/1]).
-export([start_guarded_handler/3, start_guarded_handler/4]).
-export([start_guarded_handler/3, start_guarded_handler/4, stop_guarded_handler/3]).

start_guarded_handler(HandlerMod, Handler, Args) ->
start_guarded_handler(HandlerMod, Handler, Args, undefined).
Expand All @@ -35,10 +35,26 @@ start_guarded_handler(HandlerMod, Handler, Args, ExitFun) ->
Other -> Other
end.

stop_guarded_handler(HandlerMod, Handler, Args) ->
case lists:member(Handler, gen_event:which_handlers(HandlerMod)) of
true ->
case gen_event:delete_handler(HandlerMod, Handler, Args) of
{error, module_not_found} ->
{error, module_not_found};
O ->
Id = {HandlerMod, Handler},
ok = supervisor:terminate_child(?MODULE, Id),
ok = supervisor:delete_child(?MODULE, Id),
O
end;
false ->
{error, module_not_found}
end.

handler_spec(HandlerMod, Handler, Args, ExitFun) ->
{{HandlerMod, Handler},
{riak_core_eventhandler_guard, start_link, [HandlerMod, Handler, Args, ExitFun]},
permanent, 5000, worker, [riak_core_eventhandler_guard]}.
transient, 5000, worker, [riak_core_eventhandler_guard]}.

start_link() ->
supervisor:start_link({local, ?MODULE}, ?MODULE, []).
Expand Down
26 changes: 15 additions & 11 deletions test/test_guarded_event_handler.erl
Expand Up @@ -50,8 +50,8 @@ handle_call(get_events, State) ->
handle_info(_Info, State) ->
{ok, State}.

terminate(_Reason, _State) ->
ok.
terminate(Reason, _State) ->
Reason.

code_change(_OldVsn, State, _Extra) ->
{ok, State}.
Expand All @@ -76,6 +76,14 @@ cleanup(_Pid) ->
process_flag(trap_exit, true),
gen_event:stop(?MODULE).

wait_for_exitfun() ->
receive
{?MODULE, {'EXIT', crash}} ->
ok
after 5000 ->
fail
end.

guarded_handler_test_case() ->
Self = self(),
F = fun(Handler, Reason) ->
Expand All @@ -85,17 +93,13 @@ guarded_handler_test_case() ->
gen_event:notify(?MODULE, {event, foo}),
?assertEqual(?MODULE:get_events(), [foo]),
gen_event:notify(?MODULE, crash),
Res = receive
{?MODULE, {'EXIT', crash}} ->
ok
after 5000 ->
fail
end,
?assertEqual(Res, ok),
?assertEqual(wait_for_exitfun(), ok),
wait_for_handler(?MODULE, 1000, 100),
gen_event:notify(?MODULE, {event, baz}),
Events2 = ?MODULE:get_events(),
?assertEqual(Events2, [baz]).
?assertEqual(?MODULE:get_events(), [baz]),
?assertEqual(riak_core:delete_guarded_event_handler(?MODULE,?MODULE,quux), quux),
?assertNot(lists:member(?MODULE, gen_event:which_handlers(?MODULE))),
?assertEqual([], supervisor:which_children(riak_core_eventhandler_sup)).

wait_for_handler(_, 0, _) ->
fail;
Expand Down

0 comments on commit dc64975

Please sign in to comment.