diff options
author | Simon MacMullen <simon@rabbitmq.com> | 2013-03-26 17:54:00 +0000 |
---|---|---|
committer | Simon MacMullen <simon@rabbitmq.com> | 2013-03-26 17:54:00 +0000 |
commit | 46eb23b9f4b1c693c37abfdf9e55203e688f50e8 (patch) | |
tree | 70ce8d111169cc7818cf276f23ca0cb1d145e924 | |
parent | 81ef7e1ba1ad331d29d697dd1fadde6dc7fc6f01 (diff) | |
download | rabbitmq-server-46eb23b9f4b1c693c37abfdf9e55203e688f50e8.tar.gz |
Simplistic way of selecting a winner: order by the number of connections, then the size of the partition.
-rw-r--r-- | src/rabbit_node_monitor.erl | 47 |
1 files changed, 28 insertions, 19 deletions
diff --git a/src/rabbit_node_monitor.erl b/src/rabbit_node_monitor.erl index c2c81545..957a9025 100644 --- a/src/rabbit_node_monitor.erl +++ b/src/rabbit_node_monitor.erl @@ -283,9 +283,7 @@ handle_info({mnesia_system_event, handle_info({autoheal_request_winner, Node}, State = #state{autoheal = {wait_for_winner_reqs,[Node], Notify}, partitions = Partitions}) -> - %% TODO actually do something sensible to figure out who the winner is - AllPartitions = all_partitions(Partitions), - Winner = self(), + Winner = autoheal_select_winner(all_partitions(Partitions)), rabbit_log:info("Autoheal: winner is ~p~n", [Winner]), [{?MODULE, N} ! {autoheal_winner, Winner} || N <- Notify], {noreply, State#state{autoheal = wait_for_winner}}; @@ -298,18 +296,17 @@ handle_info({autoheal_request_winner, Node}, handle_info({autoheal_winner, Winner}, State = #state{autoheal = wait_for_winner, partitions = Partitions}) -> - Node = node(Winner), - case lists:member(Node, Partitions) of + case lists:member(Winner, Partitions) of false -> case node() of - Node -> rabbit_log:info( - "Autoheal: waiting for nodes to stop: ~p~n", - [Partitions]), - {noreply, - State#state{autoheal = {wait_for, Partitions, - Partitions}}}; - _ -> rabbit_log:info( - "Autoheal: nothing to do~n", []), - {noreply, State#state{autoheal = not_healing}} + Winner -> rabbit_log:info( + "Autoheal: waiting for nodes to stop: ~p~n", + [Partitions]), + {noreply, + State#state{autoheal = {wait_for, Partitions, + Partitions}}}; + _ -> rabbit_log:info( + "Autoheal: nothing to do~n", []), + {noreply, State#state{autoheal = not_healing}} end; true -> autoheal_restart(Winner), {noreply, State} @@ -439,17 +436,29 @@ autoheal(State) -> _ -> wait_for_winner end}. +autoheal_select_winner(AllPartitions) -> + {_, [Winner | _]} = hd(lists:sort( + [{autoheal_value(P), P} || P <- AllPartitions])), + Winner. + +autoheal_value(Partition) -> + Connections = [Res || Node <- Partition, + Res <- [rpc:call(Node, rabbit_networking, + connections_local, [])], + is_list(Res)], + {length(lists:append(Connections)), length(Partition)}. + autoheal_restart(Winner) -> rabbit_log:warning( - "Autoheal: we were selected to restart; winner is ~p~n", [node(Winner)]), + "Autoheal: we were selected to restart; winner is ~p~n", [Winner]), run_outside_applications( fun () -> - MRef = erlang:monitor(process, Winner), + MRef = erlang:monitor(process, {?MODULE, Winner}), rabbit:stop(), - Winner ! {autoheal_node_stopped, node()}, + {?MODULE, Winner} ! {autoheal_node_stopped, node()}, receive - {'DOWN', MRef, process, Winner, _Reason} -> ok; - autoheal_safe_to_start -> ok + {'DOWN', MRef, process, {?MODULE, Winner}, _Reason} -> ok; + autoheal_safe_to_start -> ok end, erlang:demonitor(MRef, [flush]), rabbit:start() |