summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Jones <paulj@lshift.net>2009-08-10 15:13:18 +0100
committerPaul Jones <paulj@lshift.net>2009-08-10 15:13:18 +0100
commit5c553b6541e198faa6d04d7df037321e3f3617c4 (patch)
tree7a1d366b4741f64ae827ce69abdb0fe00e89f7b7
parentea67ca82ef894396adc69ee6f7bdb7fa0d6f2e92 (diff)
downloadrabbitmq-server-5c553b6541e198faa6d04d7df037321e3f3617c4.tar.gz
Implementation of hook mechanism using ETS table for storage of hooks, along with test cases to validate functionality
-rw-r--r--src/rabbit.erl1
-rw-r--r--src/rabbit_hooks.erl70
-rw-r--r--src/rabbit_tests.erl35
3 files changed, 106 insertions, 0 deletions
diff --git a/src/rabbit.erl b/src/rabbit.erl
index 088fa436..b0d62b5a 100644
--- a/src/rabbit.erl
+++ b/src/rabbit.erl
@@ -133,6 +133,7 @@ start(normal, []) ->
{"core processes",
fun () ->
ok = start_child(rabbit_log),
+ ok = rabbit_hooks:start(),
ok = rabbit_amqqueue:start(),
diff --git a/src/rabbit_hooks.erl b/src/rabbit_hooks.erl
new file mode 100644
index 00000000..454171ca
--- /dev/null
+++ b/src/rabbit_hooks.erl
@@ -0,0 +1,70 @@
+%% The contents of this file are subject to the Mozilla Public License
+%% Version 1.1 (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.mozilla.org/MPL/
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+%% License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% The Original Code is RabbitMQ.
+%%
+%% The Initial Developers of the Original Code are LShift Ltd,
+%% Cohesive Financial Technologies LLC, and Rabbit Technologies Ltd.
+%%
+%% Portions created before 22-Nov-2008 00:00:00 GMT by LShift Ltd,
+%% Cohesive Financial Technologies LLC, or Rabbit Technologies Ltd
+%% are Copyright (C) 2007-2008 LShift Ltd, Cohesive Financial
+%% Technologies LLC, and Rabbit Technologies Ltd.
+%%
+%% Portions created by LShift Ltd are Copyright (C) 2007-2009 LShift
+%% Ltd. Portions created by Cohesive Financial Technologies LLC are
+%% Copyright (C) 2007-2009 Cohesive Financial Technologies
+%% LLC. Portions created by Rabbit Technologies Ltd are Copyright
+%% (C) 2007-2009 Rabbit Technologies Ltd.
+%%
+%% All Rights Reserved.
+%%
+%% Contributor(s): ______________________________________.
+%%
+
+-module(rabbit_hooks).
+
+-export([start/0]).
+-export([subscribe/3, unsubscribe/2, trigger/2]).
+
+-define(TableName, rabbit_hooks).
+
+-ifdef(use_specs).
+
+-type(hookfun() :: fun((list()) -> 'ok')).
+
+-spec(start/0 :: () -> 'ok').
+-spec(subscribe/3 :: (atom(), atom(), hookfun()) -> 'ok').
+-spec(unsubscribe/2 :: (atom(), atom()) -> 'ok').
+-spec(trigger/2 :: (atom(), list()) -> 'ok').
+
+-endif.
+
+start() ->
+ ets:new(?TableName, [bag, public, named_table]),
+ ok.
+
+subscribe(Hook, HandlerName, Handler) ->
+ ets:insert(?TableName, {Hook, HandlerName, Handler}),
+ ok.
+
+unsubscribe(Hook, HandlerName) ->
+ ets:match_delete(?TableName, {Hook, HandlerName, '_'}),
+ ok.
+
+trigger(Hook, Args) ->
+ Hooks = ets:lookup(?TableName, Hook),
+ [case catch H(Args) of
+ {'EXIT', Reason} ->
+ rabbit_log:warning("Failed to execute handler ~p for hook ~p: ~p",
+ [Name, Hook, Reason]);
+ _ -> ok
+ end || {_, Name, H} <- Hooks],
+ ok.
diff --git a/src/rabbit_tests.erl b/src/rabbit_tests.erl
index 01757509..aef8c9d8 100644
--- a/src/rabbit_tests.erl
+++ b/src/rabbit_tests.erl
@@ -54,6 +54,7 @@ all_tests() ->
passed = test_cluster_management(),
passed = test_user_management(),
passed = test_server_status(),
+ passed = test_hooks(),
passed.
test_priority_queue() ->
@@ -601,6 +602,40 @@ test_server_status() ->
passed.
+test_hooks() ->
+ %% Firing of hooks calls all hooks in an isolated manner
+ rabbit_hooks:subscribe(test_hook, test,
+ fun(Args) ->
+ put(fired_testhook_handler, Args)
+ end),
+ rabbit_hooks:subscribe(test_hook, test2,
+ fun(Args) ->
+ put(fired_testhook_handler2, Args)
+ end),
+ rabbit_hooks:subscribe(test_hook2, test2,
+ fun(Args) ->
+ put(fired_testhook2_handler, Args)
+ end),
+ rabbit_hooks:trigger(test_hook, [arg1, arg2]),
+ [arg1, arg2] = get(fired_testhook_handler),
+ [arg1, arg2] = get(fired_testhook_handler2),
+ undefined = get(fired_testhook2_handler),
+
+ %% Hook Deletion works
+ put(fired_testhook_handler, undefined),
+ put(fired_testhook_handler2, undefined),
+ rabbit_hooks:unsubscribe(test_hook, test),
+ rabbit_hooks:trigger(test_hook, [arg3, arg4]),
+ undefined = get(fired_testhook_handler),
+ [arg3, arg4] = get(fired_testhook_handler2),
+ undefined = get(fired_testhook2_handler),
+
+ %% Catches exceptions from bad hooks
+ rabbit_hooks:subscribe(test_hook3, test, fun(Args) -> bad:bad() end),
+ ok = rabbit_hooks:trigger(test_hook3, []),
+
+ passed.
+
%---------------------------------------------------------------------
control_action(Command, Args) -> control_action(Command, node(), Args).