@@ -514,9 +514,29 @@ not_found_or_absent_dirty(Name) ->
514514 {ok , Q } -> {absent , Q , nodedown }
515515 end .
516516
517+ - spec get_rebalance_lock (pid ()) ->
518+ {true , {rebalance_queues , pid ()}} | false .
519+ get_rebalance_lock (Pid ) when is_pid (Pid ) ->
520+ Id = {rebalance_queues , Pid },
521+ Nodes = [node ()|nodes ()],
522+ % % Note that we're not re-trying. We want to immediately know
523+ % % if a re-balance is taking place and stop accordingly.
524+ case global :set_lock (Id , Nodes , 0 ) of
525+ true ->
526+ {true , Id };
527+ false ->
528+ false
529+ end .
530+
517531- spec rebalance ('all' | 'quorum' | 'classic' , binary (), binary ()) ->
518- {ok , [{node (), pos_integer ()}]}.
532+ {ok , [{node (), pos_integer ()}]} | { error , term ()} .
519533rebalance (Type , VhostSpec , QueueSpec ) ->
534+ % % We have not yet acquired the rebalance_queues global lock.
535+ maybe_rebalance (get_rebalance_lock (self ()), Type , VhostSpec , QueueSpec ).
536+
537+ maybe_rebalance ({true , Id }, Type , VhostSpec , QueueSpec ) ->
538+ rabbit_log :info (" Starting queue rebalance operation: '~s ' for vhosts matching '~s ' and queues matching '~s '" ,
539+ [Type , VhostSpec , QueueSpec ]),
520540 Running = rabbit_mnesia :cluster_nodes (running ),
521541 NumRunning = length (Running ),
522542 ToRebalance = [Q || Q <- rabbit_amqqueue :list (),
@@ -527,11 +547,17 @@ rebalance(Type, VhostSpec, QueueSpec) ->
527547 NumToRebalance = length (ToRebalance ),
528548 ByNode = group_by_node (ToRebalance ),
529549 Rem = case (NumToRebalance rem NumRunning ) of
530- 0 -> 0 ;
531- _ -> 1
532- end ,
550+ 0 -> 0 ;
551+ _ -> 1
552+ end ,
533553 MaxQueuesDesired = (NumToRebalance div NumRunning ) + Rem ,
534- iterative_rebalance (ByNode , MaxQueuesDesired ).
554+ Result = iterative_rebalance (ByNode , MaxQueuesDesired ),
555+ global :del_lock (Id ),
556+ rabbit_log :info (" Finished queue rebalance operation" ),
557+ Result ;
558+ maybe_rebalance (false , _Type , _VhostSpec , _QueueSpec ) ->
559+ rabbit_log :warning (" Queue rebalance operation is in progress, please wait." ),
560+ {error , rebalance_in_progress }.
535561
536562filter_per_type (all , _ ) ->
537563 true ;
0 commit comments