summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Radestock <matthias@rabbitmq.com>2014-04-13 19:45:06 +0100
committerMatthias Radestock <matthias@rabbitmq.com>2014-04-13 19:45:06 +0100
commitd9f1c1b064708d94e4bbcaea885cfcadf51c9b11 (patch)
tree1209dbfa8083b28b2467791085b3b7c13abdf7bb
parent56f423fcbe7c9a67a92de2a86cfdee02bb29e927 (diff)
downloadrabbitmq-server-git-d9f1c1b064708d94e4bbcaea885cfcadf51c9b11.tar.gz
ensure propagation of master death
Previously slaves were monitoring the master and sending a process_death message through gm in an attempt to get the updated gm state propagated (and thus members_changed callbacks getting invoked on slaves, which in turn trigger promotion). However, the DOWN notification for the master may well arrive and be processed, and the process_death message sent around the ring, before GM has noticed the master death, thus rendering the process_death broadcast ineffectual for its intended purpose. With the recent GM changes we can guarantee that at least one slave will be notified of the master death via GM. So we emit the process_death message then, and not on master DOWN (and ditch the master monitoring as a result). Since the new emission is triggered by a gm notification we know GM is aware of the master death, thus avoiding the aforementioned problem.
-rw-r--r--src/rabbit_mirror_queue_slave.erl16
1 files changed, 8 insertions, 8 deletions
diff --git a/src/rabbit_mirror_queue_slave.erl b/src/rabbit_mirror_queue_slave.erl
index 42680bfdd3..c18eff13d0 100644
--- a/src/rabbit_mirror_queue_slave.erl
+++ b/src/rabbit_mirror_queue_slave.erl
@@ -108,7 +108,6 @@ handle_go(Q = #amqqueue{name = QName}) ->
case rabbit_misc:execute_mnesia_transaction(
fun() -> init_it(Self, GM, Node, QName) end) of
{new, QPid, GMPids} ->
- erlang:monitor(process, QPid),
ok = file_handle_cache:register_callback(
rabbit_amqqueue, set_maximum_since_use, [Self]),
ok = rabbit_memory_monitor:register(
@@ -193,7 +192,8 @@ handle_call(go, _From, {not_started, Q} = NotStarted) ->
end;
handle_call({gm_deaths, LiveGMPids}, From,
- State = #state { q = Q = #amqqueue { name = QName, pid = MPid }}) ->
+ State = #state { gm = GM, q = Q = #amqqueue {
+ name = QName, pid = MPid }}) ->
Self = self(),
case rabbit_mirror_queue_misc:remove_from_queue(QName, Self, LiveGMPids) of
{error, not_found} ->
@@ -214,7 +214,12 @@ handle_call({gm_deaths, LiveGMPids}, From,
_ ->
%% master has changed to not us
gen_server2:reply(From, ok),
- erlang:monitor(process, Pid),
+ %% Since GM is by nature lazy we need to make sure
+ %% there is some traffic when a master dies, to
+ %% make sure all slaves get informed of the
+ %% death. That is all process_death does, create
+ %% some traffic.
+ ok = gm:broadcast(GM, process_death),
noreply(State #state { q = Q #amqqueue { pid = Pid } })
end
end;
@@ -294,11 +299,6 @@ handle_info(sync_timeout, State) ->
handle_info(timeout, State) ->
noreply(backing_queue_timeout(State));
-handle_info({'DOWN', _MonitorRef, process, MPid, _Reason},
- State = #state { gm = GM, q = #amqqueue { pid = MPid } }) ->
- ok = gm:broadcast(GM, process_death),
- noreply(State);
-
handle_info({'DOWN', _MonitorRef, process, ChPid, _Reason}, State) ->
local_sender_death(ChPid, State),
noreply(maybe_forget_sender(ChPid, down_from_ch, State));