summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Sackman <matthew@rabbitmq.com>2013-12-04 17:22:22 +0000
committerMatthew Sackman <matthew@rabbitmq.com>2013-12-04 17:22:22 +0000
commite49c748ce7abc252fb12e7211572d21780de104e (patch)
treef56dcb228a7169a322d52699399098745aa11cbb
parentee9e3cb4ff6bc802f03f56e40234e11044f66c7a (diff)
downloadrabbitmq-server-e49c748ce7abc252fb12e7211572d21780de104e.tar.gz
Rather than just querying a single remote node, query them all, and accomodate remote nodes that might be running older versions than ourselves, provided we can find someone who is running the same as us.
I did try just limiting Nodes to Nodes with the rabbit process running on them. That seemed to break the tests, and trying to figure out why by looking at rabbit_mnesia made me want to slit my wrists and other body parts. Thus I wrote more code instead.
-rw-r--r--src/rabbit_mnesia.erl34
-rw-r--r--src/rabbit_version.erl19
2 files changed, 42 insertions, 11 deletions
diff --git a/src/rabbit_mnesia.erl b/src/rabbit_mnesia.erl
index 3a8fae7f..8147a91a 100644
--- a/src/rabbit_mnesia.erl
+++ b/src/rabbit_mnesia.erl
@@ -434,10 +434,9 @@ init_db(ClusterNodes, NodeType, CheckOtherNodes) ->
%% First disc node up
maybe_force_load(),
ok;
- {[AnotherNode | _], _, _} ->
+ {[_ | _], _, _} ->
%% Subsequent node in cluster, catch up
- ensure_version_ok(
- rpc:call(AnotherNode, rabbit_version, recorded, [])),
+ ok = ensure_version_ok(Nodes),
maybe_force_load(),
ok = rabbit_table:wait_for_replicated(),
ok = rabbit_table:create_local_copy(NodeType)
@@ -639,14 +638,29 @@ schema_ok_or_move() ->
ok = create_schema()
end.
-ensure_version_ok({ok, DiscVersion}) ->
- DesiredVersion = rabbit_version:desired(),
- case rabbit_version:matches(DesiredVersion, DiscVersion) of
+ensure_version_ok(OtherNodes) ->
+ Desired = rabbit_version:desired(),
+ Fun = fun (Node, FoundMatch) ->
+ case rpc:call(Node, rabbit_version, recorded, []) of
+ {error, _} ->
+ FoundMatch; %% Node probably isn't fully up.
+ {ok, NodeVersion} ->
+ case rabbit_version:compare(Desired, NodeVersion) of
+ eq ->
+ true;
+ gt ->
+ FoundMatch; %% Remote is just older than us.
+ _ ->
+ throw({error, {version_mismatch,
+ Desired, NodeVersion}})
+ end
+ end
+ end,
+ FoundMatch = lists:foldl(Fun, false, OtherNodes),
+ case FoundMatch of
true -> ok;
- false -> throw({error, {version_mismatch, DesiredVersion, DiscVersion}})
- end;
-ensure_version_ok({error, _}) ->
- ok = rabbit_version:record_desired().
+ false -> throw({error, {version_mismatch, Desired}})
+ end.
%% We only care about disc nodes since ram nodes are supposed to catch
%% up only
diff --git a/src/rabbit_version.erl b/src/rabbit_version.erl
index c629180e..047737a4 100644
--- a/src/rabbit_version.erl
+++ b/src/rabbit_version.erl
@@ -16,7 +16,7 @@
-module(rabbit_version).
--export([recorded/0, matches/2, desired/0, desired_for_scope/1,
+-export([recorded/0, matches/2, compare/2, desired/0, desired_for_scope/1,
record_desired/0, record_desired_for_scope/1,
upgrades_required/1]).
@@ -33,6 +33,7 @@
-spec(recorded/0 :: () -> rabbit_types:ok_or_error2(version(), any())).
-spec(matches/2 :: ([A], [A]) -> boolean()).
+-spec(compare/2 :: ([A], [A]) -> ('eq' | 'lt' | 'gt' | 'incomparable')).
-spec(desired/0 :: () -> version()).
-spec(desired_for_scope/1 :: (scope()) -> scope_version()).
-spec(record_desired/0 :: () -> 'ok').
@@ -82,6 +83,22 @@ record_for_scope(Scope, ScopeVersion) ->
matches(VerA, VerB) ->
lists:usort(VerA) =:= lists:usort(VerB).
+compare(VerA, VerB) ->
+ VerAS = lists:usort(VerA),
+ VerBS = lists:usort(VerB),
+ VerASPrefixVerBS = lists:prefix(VerAS, VerBS),
+ VerBSPrefixVerAS = lists:prefix(VerBS, VerAS),
+ if
+ VerAS =:= VerBS ->
+ eq;
+ VerASPrefixVerBS ->
+ lt;
+ VerBSPrefixVerAS ->
+ gt;
+ true ->
+ incomparable
+ end.
+
%% -------------------------------------------------------------------
desired() -> [Name || Scope <- ?SCOPES, Name <- desired_for_scope(Scope)].