summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon MacMullen <simon@rabbitmq.com>2014-12-01 13:57:37 +0000
committerSimon MacMullen <simon@rabbitmq.com>2014-12-01 13:57:37 +0000
commit22d9ab0a1bd2903856577177e1b7e750435844ce (patch)
tree8545c97220093ccab57ed5730b37660f6e406bc6
parent36b9eeb55f60eb8614ea3a0a258ba4c2076e5e6f (diff)
downloadrabbitmq-server-22d9ab0a1bd2903856577177e1b7e750435844ce.tar.gz
Allow argument-pairs to rename_cluster_node to go in any order (and thus allow remote-only renamings). Don't use mnesia:transform_table/3 since it's rather picky about which disk nodes are up.
-rw-r--r--src/rabbit_control_main.erl15
-rw-r--r--src/rabbit_mnesia_rename.erl54
2 files changed, 46 insertions, 23 deletions
diff --git a/src/rabbit_control_main.erl b/src/rabbit_control_main.erl
index d9bae4c4..e7e28890 100644
--- a/src/rabbit_control_main.erl
+++ b/src/rabbit_control_main.erl
@@ -235,13 +235,10 @@ action(forget_cluster_node, Node, [ClusterNodeS], Opts, Inform) ->
[ClusterNode, false])
end;
-action(rename_cluster_node, _Node, [FromNodeS, ToNodeS | OthersS], _Opts,
- Inform) ->
- Others = [list_to_atom(N) || N <- OthersS],
- FromNode = list_to_atom(FromNodeS),
- ToNode = list_to_atom(ToNodeS),
- Inform("Renaming local cluster node ~s to ~s", [FromNode, ToNode]),
- rabbit_mnesia_rename:rename(FromNode, ToNode, Others);
+action(rename_cluster_node, Node, NodesS, _Opts, Inform) ->
+ Nodes = split_list([list_to_atom(N) || N <- NodesS]),
+ Inform("Renaming cluster nodes:~n ~p~n", [Nodes]),
+ rabbit_mnesia_rename:rename(Node, Nodes);
action(force_boot, Node, [], _Opts, Inform) ->
Inform("Forcing boot for Mnesia dir ~s", [mnesia:system_info(directory)]),
@@ -729,3 +726,7 @@ prettify_typed_amqp_value(table, Value) -> prettify_amqp_table(Value);
prettify_typed_amqp_value(array, Value) -> [prettify_typed_amqp_value(T, V) ||
{T, V} <- Value];
prettify_typed_amqp_value(_Type, Value) -> Value.
+
+split_list([]) -> [];
+split_list([_]) -> exit(even_list_needed);
+split_list([A, B | T]) -> [{A, B} | split_list(T)].
diff --git a/src/rabbit_mnesia_rename.erl b/src/rabbit_mnesia_rename.erl
index a8cf2991..c505c896 100644
--- a/src/rabbit_mnesia_rename.erl
+++ b/src/rabbit_mnesia_rename.erl
@@ -17,7 +17,7 @@
-module(rabbit_mnesia_rename).
-include("rabbit.hrl").
--export([rename/3]).
+-export([rename/2]).
-export([maybe_finish/1]).
-define(CONVERT_TABLES, [schema, rabbit_durable_queue]).
@@ -26,23 +26,37 @@
-ifdef(use_specs).
--spec(rename/3 :: (node(), node(), [node()]) -> 'ok').
+-spec(rename/2 :: (node(), [{node(), node()}]) -> 'ok').
-spec(maybe_finish/1 :: ([node()]) -> 'ok').
-endif.
%%----------------------------------------------------------------------------
-rename(FromNode, ToNode, Others) ->
- NodeMap = dict:from_list(split_others([FromNode, ToNode | Others])),
+rename(Node, NodeMapList) ->
try
+ NodeMap = dict:from_list(NodeMapList),
+ {FromNodes, ToNodes} = lists:unzip(NodeMapList),
+ case length(FromNodes) - length(lists:usort(ToNodes)) of
+ 0 -> ok;
+ _ -> exit({duplicate_node, ToNodes})
+ end,
+ FromNode = case [From || {From, To} <- NodeMapList,
+ To =:= Node] of
+ [N] -> N;
+ [] -> Node
+ end,
+ ToNode = case dict:find(FromNode, NodeMap) of
+ {ok, N2} -> N2;
+ error -> FromNode
+ end,
rabbit_control_main:become(FromNode),
start_mnesia(),
Nodes = rabbit_mnesia:cluster_nodes(all),
- case {lists:member(FromNode, Nodes), lists:member(ToNode, Nodes)} of
- {true, false} -> ok;
- {false, _} -> exit({node_not_in_cluster, FromNode});
- {_, true} -> exit({node_already_in_cluster, ToNode})
+ case {FromNodes -- Nodes, ToNodes -- (ToNodes -- Nodes)} of
+ {[], []} -> ok;
+ {F, []} -> exit({nodes_not_in_cluster, F});
+ {_, T} -> exit({nodes_already_in_cluster, T})
end,
rabbit_table:force_load(),
rabbit_table:wait_for_replicated(),
@@ -59,10 +73,6 @@ rename(FromNode, ToNode, Others) ->
stop_mnesia()
end.
-split_others([]) -> [];
-split_others([_]) -> exit(even_list_needed);
-split_others([A, B | T]) -> [{A, B} | split_others(T)].
-
maybe_finish(AllNodes) ->
case rabbit_file:read_term_file(rename_config_name()) of
{ok, [{FromNode, ToNode}]} -> finish(FromNode, ToNode, AllNodes);
@@ -171,9 +181,21 @@ rename_remote_node(FromNode, ToNode) ->
{true, _} -> exit({old_node_running, FromNode});
{_, false} -> exit({new_node_not_in_cluster, ToNode})
end,
- mnesia:del_table_copy(schema, FromNode),
+ {atomic, ok} = mnesia:del_table_copy(schema, FromNode),
Map = mini_map(FromNode, ToNode),
- {atomic, ok} = mnesia:transform_table(
- rabbit_durable_queue, fun (Q) -> update_term(Map, Q) end,
- record_info(fields, amqqueue)),
+ {atomic, _} = transform_table(rabbit_durable_queue, Map),
ok.
+
+transform_table(Table, Map) ->
+ mnesia:sync_transaction(
+ fun () ->
+ mnesia:lock({table, Table}, write),
+ transform_table(Table, Map, mnesia:first(Table))
+ end).
+
+transform_table(Table, Map, '$end_of_table') ->
+ ok;
+transform_table(Table, Map, Key) ->
+ [Term] = mnesia:read(Table, Key, write),
+ ok = mnesia:write(Table, update_term(Map, Term), write),
+ transform_table(Table, Map, mnesia:next(Table, Key)).