diff options
author | Matthew Sackman <matthew@rabbitmq.com> | 2013-12-04 17:22:22 +0000 |
---|---|---|
committer | Matthew Sackman <matthew@rabbitmq.com> | 2013-12-04 17:22:22 +0000 |
commit | e49c748ce7abc252fb12e7211572d21780de104e (patch) | |
tree | f56dcb228a7169a322d52699399098745aa11cbb | |
parent | ee9e3cb4ff6bc802f03f56e40234e11044f66c7a (diff) | |
download | rabbitmq-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.erl | 34 | ||||
-rw-r--r-- | src/rabbit_version.erl | 19 |
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)]. |