diff options
author | Matthias Radestock <matthias@rabbitmq.com> | 2014-04-13 19:45:06 +0100 |
---|---|---|
committer | Matthias Radestock <matthias@rabbitmq.com> | 2014-04-13 19:45:06 +0100 |
commit | 3a3b67e62ad22ddb7d0eedb2a93d1bcf247d26bf (patch) | |
tree | 1209dbfa8083b28b2467791085b3b7c13abdf7bb | |
parent | 81986c4e315d9e58dad74a470b262ba7feb84b37 (diff) | |
download | rabbitmq-server-3a3b67e62ad22ddb7d0eedb2a93d1bcf247d26bf.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.erl | 16 |
1 files changed, 8 insertions, 8 deletions
diff --git a/src/rabbit_mirror_queue_slave.erl b/src/rabbit_mirror_queue_slave.erl index 42680bfd..c18eff13 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)); |