summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon MacMullen <simon@rabbitmq.com>2011-07-29 16:29:10 +0100
committerSimon MacMullen <simon@rabbitmq.com>2011-07-29 16:29:10 +0100
commite2c57c78fcc0281eeb78dd1914287e539265244c (patch)
treebb22eb45526d05760d39412fd47bb03367cead54
parent6bb7d212f9f352832167c2c1995f67a1e2143bdb (diff)
parent930b42314f4124491abd97c45849d208b11a7085 (diff)
downloadrabbitmq-server-e2c57c78fcc0281eeb78dd1914287e539265244c.tar.gz
Merge bug24284
-rw-r--r--packaging/windows-exe/rabbitmq_nsi.in18
-rw-r--r--src/priority_queue.erl3
-rw-r--r--src/rabbit_amqqueue_process.erl17
-rw-r--r--src/rabbit_channel.erl4
-rw-r--r--src/rabbit_misc.erl23
-rw-r--r--src/rabbit_mnesia.erl160
-rw-r--r--src/rabbit_msg_store.erl5
-rw-r--r--src/rabbit_tests.erl45
-rw-r--r--src/rabbit_upgrade.erl18
9 files changed, 217 insertions, 76 deletions
diff --git a/packaging/windows-exe/rabbitmq_nsi.in b/packaging/windows-exe/rabbitmq_nsi.in
index 1ed4064e..27e4e1dc 100644
--- a/packaging/windows-exe/rabbitmq_nsi.in
+++ b/packaging/windows-exe/rabbitmq_nsi.in
@@ -113,17 +113,17 @@ Section "Start Menu" RabbitStartMenu
CreateDirectory "$APPDATA\RabbitMQ\db"
CreateDirectory "$SMPROGRAMS\RabbitMQ Server"
- CreateShortCut "$SMPROGRAMS\RabbitMQ Server\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0
- CreateShortCut "$SMPROGRAMS\RabbitMQ Server\Plugins Directory.lnk" "$INSTDIR\rabbitmq_server-%%VERSION%%\plugins"
- CreateShortCut "$SMPROGRAMS\RabbitMQ Server\Log Directory.lnk" "$APPDATA\RabbitMQ\log"
- CreateShortCut "$SMPROGRAMS\RabbitMQ Server\Database Directory.lnk" "$APPDATA\RabbitMQ\db"
- CreateShortCut "$SMPROGRAMS\RabbitMQ Server\(Re)Install Service.lnk" "$INSTDIR\rabbitmq_server-%%VERSION%%\sbin\rabbitmq-service.bat" "install" "$INSTDIR\rabbitmq.ico"
- CreateShortCut "$SMPROGRAMS\RabbitMQ Server\Remove Service.lnk" "$INSTDIR\rabbitmq_server-%%VERSION%%\sbin\rabbitmq-service.bat" "remove" "$INSTDIR\rabbitmq.ico"
- CreateShortCut "$SMPROGRAMS\RabbitMQ Server\Start Service.lnk" "$INSTDIR\rabbitmq_server-%%VERSION%%\sbin\rabbitmq-service.bat" "start" "$INSTDIR\rabbitmq.ico"
- CreateShortCut "$SMPROGRAMS\RabbitMQ Server\Stop Service.lnk" "$INSTDIR\rabbitmq_server-%%VERSION%%\sbin\rabbitmq-service.bat" "stop" "$INSTDIR\rabbitmq.ico"
+ CreateShortCut "$SMPROGRAMS\RabbitMQ Server\Uninstall RabbitMQ.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0
+ CreateShortCut "$SMPROGRAMS\RabbitMQ Server\RabbitMQ Plugins.lnk" "$INSTDIR\rabbitmq_server-%%VERSION%%\plugins"
+ CreateShortCut "$SMPROGRAMS\RabbitMQ Server\RabbitMQ Logs.lnk" "$APPDATA\RabbitMQ\log"
+ CreateShortCut "$SMPROGRAMS\RabbitMQ Server\RabbitMQ Database Directory.lnk" "$APPDATA\RabbitMQ\db"
+ CreateShortCut "$SMPROGRAMS\RabbitMQ Server\RabbitMQ Service - (re)install.lnk" "$INSTDIR\rabbitmq_server-%%VERSION%%\sbin\rabbitmq-service.bat" "install" "$INSTDIR\rabbitmq.ico"
+ CreateShortCut "$SMPROGRAMS\RabbitMQ Server\RabbitMQ Service - remove.lnk" "$INSTDIR\rabbitmq_server-%%VERSION%%\sbin\rabbitmq-service.bat" "remove" "$INSTDIR\rabbitmq.ico"
+ CreateShortCut "$SMPROGRAMS\RabbitMQ Server\RabbitMQ Service - start.lnk" "$INSTDIR\rabbitmq_server-%%VERSION%%\sbin\rabbitmq-service.bat" "start" "$INSTDIR\rabbitmq.ico"
+ CreateShortCut "$SMPROGRAMS\RabbitMQ Server\RabbitMQ Service - stop.lnk" "$INSTDIR\rabbitmq_server-%%VERSION%%\sbin\rabbitmq-service.bat" "stop" "$INSTDIR\rabbitmq.ico"
SetOutPath "$INSTDIR\rabbitmq_server-%%VERSION%%\sbin"
- CreateShortCut "$SMPROGRAMS\RabbitMQ Server\Command Prompt (sbin dir).lnk" "$WINDIR\system32\cmd.exe" "" "$WINDIR\system32\cmd.exe"
+ CreateShortCut "$SMPROGRAMS\RabbitMQ Server\RabbitMQ Command Prompt (sbin dir).lnk" "$WINDIR\system32\cmd.exe" "" "$WINDIR\system32\cmd.exe"
SetOutPath $INSTDIR
SectionEnd
diff --git a/src/priority_queue.erl b/src/priority_queue.erl
index 34787903..4fc8b469 100644
--- a/src/priority_queue.erl
+++ b/src/priority_queue.erl
@@ -47,6 +47,9 @@
-ifdef(use_specs).
+-export_type([q/0]).
+
+-type(q() :: pqueue()).
-type(priority() :: integer() | 'infinity').
-type(squeue() :: {queue, [any()], [any()]}).
-type(pqueue() :: squeue() | {pqueue, [{priority(), squeue()}]}).
diff --git a/src/rabbit_amqqueue_process.erl b/src/rabbit_amqqueue_process.erl
index 4492bbd8..c6019413 100644
--- a/src/rabbit_amqqueue_process.erl
+++ b/src/rabbit_amqqueue_process.erl
@@ -31,12 +31,10 @@
-export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2,
handle_info/2, handle_pre_hibernate/1, prioritise_call/3,
- prioritise_cast/2, prioritise_info/2]).
+ prioritise_cast/2, prioritise_info/2, format_message_queue/2]).
-export([init_with_backing_queue_state/7]).
--export([format_message_queue/2]).
-
%% Queue's state
-record(q, {q,
exclusive_consumer,
@@ -1165,15 +1163,4 @@ handle_pre_hibernate(State = #q{backing_queue = BQ,
backing_queue_state = BQS3},
{hibernate, stop_rate_timer(State1)}.
-format_message_queue(_Opt, Mailbox) ->
- Len = priority_queue:len(Mailbox),
- {Len,
- case Len > 100 of
- false -> priority_queue:to_list(Mailbox);
- true -> {summary,
- orddict:to_list(
- lists:foldl(
- fun ({P, _V}, Counts) ->
- orddict:update_counter(P, 1, Counts)
- end, orddict:new(), priority_queue:to_list(Mailbox)))}
- end}.
+format_message_queue(Opt, MQ) -> rabbit_misc:format_message_queue(Opt, MQ).
diff --git a/src/rabbit_channel.erl b/src/rabbit_channel.erl
index f398fcc5..13fb7ce1 100644
--- a/src/rabbit_channel.erl
+++ b/src/rabbit_channel.erl
@@ -27,7 +27,7 @@
-export([init/1, terminate/2, code_change/3, handle_call/3, handle_cast/2,
handle_info/2, handle_pre_hibernate/1, prioritise_call/3,
- prioritise_cast/2]).
+ prioritise_cast/2, format_message_queue/2]).
-record(ch, {state, protocol, channel, reader_pid, writer_pid, conn_pid,
limiter_pid, start_limiter_fun, tx_status, next_tag,
@@ -344,6 +344,8 @@ terminate(Reason, State) ->
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
+format_message_queue(Opt, MQ) -> rabbit_misc:format_message_queue(Opt, MQ).
+
%%---------------------------------------------------------------------------
reply(Reply, NewState) -> reply(Reply, [], NewState).
diff --git a/src/rabbit_misc.erl b/src/rabbit_misc.erl
index b6b97f6d..3bbfb1d7 100644
--- a/src/rabbit_misc.erl
+++ b/src/rabbit_misc.erl
@@ -57,6 +57,7 @@
-export([ntoa/1, ntoab/1]).
-export([is_process_alive/1]).
-export([pget/2, pget/3, pget_or_die/2]).
+-export([format_message_queue/2]).
%%----------------------------------------------------------------------------
@@ -205,6 +206,7 @@
-spec(pget/2 :: (term(), [term()]) -> term()).
-spec(pget/3 :: (term(), [term()], term()) -> term()).
-spec(pget_or_die/2 :: (term(), [term()]) -> term() | no_return()).
+-spec(format_message_queue/2 :: (any(), priority_queue:q()) -> term()).
-endif.
@@ -919,3 +921,24 @@ pget_or_die(K, P) ->
undefined -> exit({error, key_missing, K});
V -> V
end.
+
+format_message_queue(_Opt, MQ) ->
+ Len = priority_queue:len(MQ),
+ {Len,
+ case Len > 100 of
+ false -> priority_queue:to_list(MQ);
+ true -> {summary,
+ orddict:to_list(
+ lists:foldl(
+ fun ({P, V}, Counts) ->
+ orddict:update_counter(
+ {P, format_message_queue_entry(V)}, 1, Counts)
+ end, orddict:new(), priority_queue:to_list(MQ)))}
+ end}.
+
+format_message_queue_entry(V) when is_atom(V) ->
+ V;
+format_message_queue_entry(V) when is_tuple(V) ->
+ list_to_tuple([format_message_queue_entry(E) || E <- tuple_to_list(V)]);
+format_message_queue_entry(_V) ->
+ '_'.
diff --git a/src/rabbit_mnesia.erl b/src/rabbit_mnesia.erl
index 8d5c8646..ab553a8b 100644
--- a/src/rabbit_mnesia.erl
+++ b/src/rabbit_mnesia.erl
@@ -23,7 +23,8 @@
empty_ram_only_tables/0, copy_db/1, wait_for_tables/1,
create_cluster_nodes_config/1, read_cluster_nodes_config/0,
record_running_nodes/0, read_previously_running_nodes/0,
- delete_previously_running_nodes/0, running_nodes_filename/0]).
+ delete_previously_running_nodes/0, running_nodes_filename/0,
+ is_disc_node/0]).
-export([table_names/0]).
@@ -65,6 +66,7 @@
-spec(read_previously_running_nodes/0 :: () -> [node()]).
-spec(delete_previously_running_nodes/0 :: () -> 'ok').
-spec(running_nodes_filename/0 :: () -> file:filename()).
+-spec(is_disc_node/0 :: () -> boolean()).
-endif.
@@ -115,13 +117,47 @@ force_cluster(ClusterNodes) ->
cluster(ClusterNodes, Force) ->
ensure_mnesia_not_running(),
ensure_mnesia_dir(),
- rabbit_misc:ensure_ok(mnesia:start(), cannot_start_mnesia),
+
+ %% Wipe mnesia if we're changing type from disc to ram
+ case {is_disc_node(), should_be_disc_node(ClusterNodes)} of
+ {true, false} -> error_logger:warning_msg(
+ "changing node type; wiping mnesia...~n~n"),
+ rabbit_misc:ensure_ok(mnesia:delete_schema([node()]),
+ cannot_delete_schema);
+ _ -> ok
+ end,
+
+ %% Pre-emptively leave the cluster
+ %%
+ %% We're trying to handle the following two cases:
+ %% 1. We have a two-node cluster, where both nodes are disc nodes.
+ %% One node is re-clustered as a ram node. When it tries to
+ %% re-join the cluster, but before it has time to update its
+ %% tables definitions, the other node will order it to re-create
+ %% its disc tables. So, we need to leave the cluster before we
+ %% can join it again.
+ %% 2. We have a two-node cluster, where both nodes are disc nodes.
+ %% One node is forcefully reset (so, the other node thinks its
+ %% still a part of the cluster). The reset node is re-clustered
+ %% as a ram node. Same as above, we need to leave the cluster
+ %% before we can join it. But, since we don't know if we're in a
+ %% cluster or not, we just pre-emptively leave it before joining.
+ ProperClusterNodes = ClusterNodes -- [node()],
+ try
+ ok = leave_cluster(ProperClusterNodes, ProperClusterNodes)
+ catch
+ {error, {no_running_cluster_nodes, _, _}} when Force ->
+ ok
+ end,
+
+ %% Join the cluster
+ start_mnesia(),
try
ok = init_db(ClusterNodes, Force,
fun maybe_upgrade_local_or_record_desired/0),
ok = create_cluster_nodes_config(ClusterNodes)
after
- mnesia:stop()
+ stop_mnesia()
end,
ok.
@@ -158,10 +194,13 @@ nodes_of_type(Type) ->
%% This function should return the nodes of a certain type (ram,
%% disc or disc_only) in the current cluster. The type of nodes
%% is determined when the cluster is initially configured.
- %% Specifically, we check whether a certain table, which we know
- %% will be written to disk on a disc node, is stored on disk or in
- %% RAM.
- mnesia:table_info(rabbit_durable_exchange, Type).
+ mnesia:table_info(schema, Type).
+
+%% The tables aren't supposed to be on disk on a ram node
+table_definitions(disc) ->
+ table_definitions();
+table_definitions(ram) ->
+ [{Tab, copy_type_to_ram(TabDef)} || {Tab, TabDef} <- table_definitions()].
table_definitions() ->
[{rabbit_user,
@@ -218,8 +257,6 @@ table_definitions() ->
{type, ordered_set},
{match, #topic_trie_binding{trie_binding = trie_binding_match(),
_='_'}}]},
- %% Consider the implications to nodes_of_type/1 before altering
- %% the next entry.
{rabbit_durable_exchange,
[{record_name, exchange},
{attributes, record_info(fields, exchange)},
@@ -341,7 +378,11 @@ check_table_content(Tab, TabDef) ->
end.
check_tables(Fun) ->
- case [Error || {Tab, TabDef} <- table_definitions(),
+ case [Error || {Tab, TabDef} <- table_definitions(
+ case is_disc_node() of
+ true -> disc;
+ false -> ram
+ end),
case Fun(Tab, TabDef) of
ok -> Error = none, false;
{error, Error} -> true
@@ -442,30 +483,47 @@ init_db(ClusterNodes, Force, SecondaryPostMnesiaFun) ->
end;
true -> ok
end,
- case {Nodes, mnesia:system_info(use_dir)} of
- {[], false} ->
+ WantDiscNode = should_be_disc_node(ClusterNodes),
+ WasDiscNode = is_disc_node(),
+ %% We create a new db (on disk, or in ram) in the first
+ %% two cases and attempt to upgrade the in the other two
+ case {Nodes, WasDiscNode, WantDiscNode} of
+ {[], _, false} ->
+ %% New ram node; start from scratch
+ ok = create_schema(ram);
+ {[], false, true} ->
%% Nothing there at all, start from scratch
- ok = create_schema();
- {[], true} ->
+ ok = create_schema(disc);
+ {[], true, true} ->
%% We're the first node up
case rabbit_upgrade:maybe_upgrade_local() of
ok -> ensure_schema_integrity();
version_not_available -> ok = schema_ok_or_move()
- end,
- ok;
- {[AnotherNode|_], _} ->
+ end;
+ {[AnotherNode|_], _, _} ->
%% Subsequent node in cluster, catch up
ensure_version_ok(
rpc:call(AnotherNode, rabbit_version, recorded, [])),
- IsDiskNode = ClusterNodes == [] orelse
- lists:member(node(), ClusterNodes),
+ {CopyType, CopyTypeAlt} =
+ case WantDiscNode of
+ true -> {disc, disc_copies};
+ false -> {ram, ram_copies}
+ end,
ok = wait_for_replicated_tables(),
- ok = create_local_table_copy(schema, disc_copies),
- ok = create_local_table_copies(case IsDiskNode of
- true -> disc;
- false -> ram
- end),
+ ok = create_local_table_copy(schema, CopyTypeAlt),
+ ok = create_local_table_copies(CopyType),
+
ok = SecondaryPostMnesiaFun(),
+ %% We've taken down mnesia, so ram nodes will need
+ %% to re-sync
+ case is_disc_node() of
+ false -> start_mnesia(),
+ mnesia:change_config(extra_db_nodes,
+ ProperClusterNodes),
+ wait_for_replicated_tables();
+ true -> ok
+ end,
+
ensure_schema_integrity(),
ok
end;
@@ -496,7 +554,7 @@ schema_ok_or_move() ->
"and recreating schema from scratch~n",
[Reason]),
ok = move_db(),
- ok = create_schema()
+ ok = create_schema(disc)
end.
ensure_version_ok({ok, DiscVersion}) ->
@@ -508,18 +566,27 @@ ensure_version_ok({ok, DiscVersion}) ->
ensure_version_ok({error, _}) ->
ok = rabbit_version:record_desired().
-create_schema() ->
- mnesia:stop(),
- rabbit_misc:ensure_ok(mnesia:create_schema([node()]),
- cannot_create_schema),
- rabbit_misc:ensure_ok(mnesia:start(),
- cannot_start_mnesia),
- ok = create_tables(),
+create_schema(Type) ->
+ stop_mnesia(),
+ case Type of
+ disc -> rabbit_misc:ensure_ok(mnesia:create_schema([node()]),
+ cannot_create_schema);
+ ram -> %% remove the disc schema since this is a ram node
+ rabbit_misc:ensure_ok(mnesia:delete_schema([node()]),
+ cannot_delete_schema)
+ end,
+ start_mnesia(),
+ ok = create_tables(Type),
ensure_schema_integrity(),
ok = rabbit_version:record_desired().
+is_disc_node() -> mnesia:system_info(use_dir).
+
+should_be_disc_node(ClusterNodes) ->
+ ClusterNodes == [] orelse lists:member(node(), ClusterNodes).
+
move_db() ->
- mnesia:stop(),
+ stop_mnesia(),
MnesiaDir = filename:dirname(dir() ++ "/"),
{{Year, Month, Day}, {Hour, Minute, Second}} = erlang:universaltime(),
BackupDir = lists:flatten(
@@ -537,14 +604,16 @@ move_db() ->
MnesiaDir, BackupDir, Reason}})
end,
ensure_mnesia_dir(),
- rabbit_misc:ensure_ok(mnesia:start(), cannot_start_mnesia),
+ start_mnesia(),
ok.
copy_db(Destination) ->
ok = ensure_mnesia_not_running(),
rabbit_misc:recursive_copy(dir(), Destination).
-create_tables() ->
+create_tables() -> create_tables(disc).
+
+create_tables(Type) ->
lists:foreach(fun ({Tab, TabDef}) ->
TabDef1 = proplists:delete(match, TabDef),
case mnesia:create_table(Tab, TabDef1) of
@@ -554,9 +623,13 @@ create_tables() ->
Tab, TabDef1, Reason}})
end
end,
- table_definitions()),
+ table_definitions(Type)),
ok.
+copy_type_to_ram(TabDef) ->
+ [{disc_copies, []}, {ram_copies, [node()]}
+ | proplists:delete(ram_copies, proplists:delete(disc_copies, TabDef))].
+
table_has_copy_type(TabDef, DiscType) ->
lists:member(node(), proplists:get_value(DiscType, TabDef, [])).
@@ -586,7 +659,7 @@ create_local_table_copies(Type) ->
end,
ok = create_local_table_copy(Tab, StorageType)
end,
- table_definitions()),
+ table_definitions(Type)),
ok.
create_local_table_copy(Tab, Type) ->
@@ -622,14 +695,14 @@ reset(Force) ->
true -> ok;
false ->
ensure_mnesia_dir(),
- rabbit_misc:ensure_ok(mnesia:start(), cannot_start_mnesia),
+ start_mnesia(),
{Nodes, RunningNodes} =
try
ok = init(),
{all_clustered_nodes() -- [Node],
running_clustered_nodes() -- [Node]}
after
- mnesia:stop()
+ stop_mnesia()
end,
leave_cluster(Nodes, RunningNodes),
rabbit_misc:ensure_ok(mnesia:delete_schema([Node]),
@@ -652,6 +725,7 @@ leave_cluster(Nodes, RunningNodes) ->
[schema, node()]) of
{atomic, ok} -> true;
{badrpc, nodedown} -> false;
+ {aborted, {node_not_running, _}} -> false;
{aborted, Reason} ->
throw({error, {failed_to_leave_cluster,
Nodes, RunningNodes, Reason}})
@@ -662,3 +736,11 @@ leave_cluster(Nodes, RunningNodes) ->
false -> throw({error, {no_running_cluster_nodes,
Nodes, RunningNodes}})
end.
+
+start_mnesia() ->
+ rabbit_misc:ensure_ok(mnesia:start(), cannot_start_mnesia),
+ ensure_mnesia_running().
+
+stop_mnesia() ->
+ stopped = mnesia:stop(),
+ ensure_mnesia_not_running().
diff --git a/src/rabbit_msg_store.erl b/src/rabbit_msg_store.erl
index 3f4162cd..27de1f77 100644
--- a/src/rabbit_msg_store.erl
+++ b/src/rabbit_msg_store.erl
@@ -29,7 +29,8 @@
-export([transform_dir/3, force_recovery/2]). %% upgrade
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
- terminate/2, code_change/3, prioritise_call/3, prioritise_cast/2]).
+ terminate/2, code_change/3, prioritise_call/3, prioritise_cast/2,
+ format_message_queue/2]).
%%----------------------------------------------------------------------------
@@ -836,6 +837,8 @@ terminate(_Reason, State = #msstate { index_state = IndexState,
code_change(_OldVsn, State, _Extra) ->
{ok, State}.
+format_message_queue(Opt, MQ) -> rabbit_misc:format_message_queue(Opt, MQ).
+
%%----------------------------------------------------------------------------
%% general helper functions
%%----------------------------------------------------------------------------
diff --git a/src/rabbit_tests.erl b/src/rabbit_tests.erl
index 283a5c4a..2a3ced92 100644
--- a/src/rabbit_tests.erl
+++ b/src/rabbit_tests.erl
@@ -940,7 +940,6 @@ test_option_parser() ->
passed.
test_cluster_management() ->
-
%% 'cluster' and 'reset' should only work if the app is stopped
{error, _} = control_action(cluster, []),
{error, _} = control_action(reset, []),
@@ -988,13 +987,16 @@ test_cluster_management() ->
ok = control_action(reset, []),
ok = control_action(start_app, []),
ok = control_action(stop_app, []),
+ ok = assert_disc_node(),
ok = control_action(force_cluster, ["invalid1@invalid",
"invalid2@invalid"]),
+ ok = assert_ram_node(),
%% join a non-existing cluster as a ram node
ok = control_action(reset, []),
ok = control_action(force_cluster, ["invalid1@invalid",
"invalid2@invalid"]),
+ ok = assert_ram_node(),
SecondaryNode = rabbit_misc:makenode("hare"),
case net_adm:ping(SecondaryNode) of
@@ -1013,15 +1015,18 @@ test_cluster_management2(SecondaryNode) ->
%% make a disk node
ok = control_action(reset, []),
ok = control_action(cluster, [NodeS]),
+ ok = assert_disc_node(),
%% make a ram node
ok = control_action(reset, []),
ok = control_action(cluster, [SecondaryNodeS]),
+ ok = assert_ram_node(),
%% join cluster as a ram node
ok = control_action(reset, []),
ok = control_action(force_cluster, [SecondaryNodeS, "invalid1@invalid"]),
ok = control_action(start_app, []),
ok = control_action(stop_app, []),
+ ok = assert_ram_node(),
%% change cluster config while remaining in same cluster
ok = control_action(force_cluster, ["invalid2@invalid", SecondaryNodeS]),
@@ -1033,27 +1038,45 @@ test_cluster_management2(SecondaryNode) ->
"invalid2@invalid"]),
ok = control_action(start_app, []),
ok = control_action(stop_app, []),
+ ok = assert_ram_node(),
- %% join empty cluster as a ram node
+ %% join empty cluster as a ram node (converts to disc)
ok = control_action(cluster, []),
ok = control_action(start_app, []),
ok = control_action(stop_app, []),
+ ok = assert_disc_node(),
- %% turn ram node into disk node
+ %% make a new ram node
ok = control_action(reset, []),
+ ok = control_action(force_cluster, [SecondaryNodeS]),
+ ok = control_action(start_app, []),
+ ok = control_action(stop_app, []),
+ ok = assert_ram_node(),
+
+ %% turn ram node into disk node
ok = control_action(cluster, [SecondaryNodeS, NodeS]),
ok = control_action(start_app, []),
ok = control_action(stop_app, []),
+ ok = assert_disc_node(),
%% convert a disk node into a ram node
+ ok = assert_disc_node(),
ok = control_action(force_cluster, ["invalid1@invalid",
"invalid2@invalid"]),
+ ok = assert_ram_node(),
+
+ %% make a new disk node
+ ok = control_action(force_reset, []),
+ ok = control_action(start_app, []),
+ ok = control_action(stop_app, []),
+ ok = assert_disc_node(),
%% turn a disk node into a ram node
ok = control_action(reset, []),
ok = control_action(cluster, [SecondaryNodeS]),
ok = control_action(start_app, []),
ok = control_action(stop_app, []),
+ ok = assert_ram_node(),
%% NB: this will log an inconsistent_database error, which is harmless
%% Turning cover on / off is OK even if we're not in general using cover,
@@ -1079,6 +1102,10 @@ test_cluster_management2(SecondaryNode) ->
{error, {no_running_cluster_nodes, _, _}} =
control_action(reset, []),
+ %% attempt to change type when no other node is alive
+ {error, {no_running_cluster_nodes, _, _}} =
+ control_action(cluster, [SecondaryNodeS]),
+
%% leave system clustered, with the secondary node as a ram node
ok = control_action(force_reset, []),
ok = control_action(start_app, []),
@@ -1617,6 +1644,18 @@ clean_logs(Files, Suffix) ->
end || File <- Files],
ok.
+assert_ram_node() ->
+ case rabbit_mnesia:is_disc_node() of
+ true -> exit('not_ram_node');
+ false -> ok
+ end.
+
+assert_disc_node() ->
+ case rabbit_mnesia:is_disc_node() of
+ true -> ok;
+ false -> exit('not_disc_node')
+ end.
+
delete_file(File) ->
case file:delete(File) of
ok -> ok;
diff --git a/src/rabbit_upgrade.erl b/src/rabbit_upgrade.erl
index a2abb1e5..9739f6b7 100644
--- a/src/rabbit_upgrade.erl
+++ b/src/rabbit_upgrade.erl
@@ -144,7 +144,7 @@ upgrade_mode(AllNodes) ->
case nodes_running(AllNodes) of
[] ->
AfterUs = rabbit_mnesia:read_previously_running_nodes(),
- case {is_disc_node(), AfterUs} of
+ case {is_disc_node_legacy(), AfterUs} of
{true, []} ->
primary;
{true, _} ->
@@ -182,12 +182,6 @@ upgrade_mode(AllNodes) ->
end
end.
-is_disc_node() ->
- %% This is pretty ugly but we can't start Mnesia and ask it (will hang),
- %% we can't look at the config file (may not include us even if we're a
- %% disc node).
- filelib:is_regular(filename:join(dir(), "rabbit_durable_exchange.DCD")).
-
die(Msg, Args) ->
%% We don't throw or exit here since that gets thrown
%% straight out into do_boot, generating an erl_crash.dump
@@ -218,7 +212,7 @@ force_tables() ->
secondary_upgrade(AllNodes) ->
%% must do this before we wipe out schema
- IsDiscNode = is_disc_node(),
+ IsDiscNode = is_disc_node_legacy(),
rabbit_misc:ensure_ok(mnesia:delete_schema([node()]),
cannot_delete_schema),
%% Note that we cluster with all nodes, rather than all disc nodes
@@ -282,6 +276,14 @@ lock_filename() -> lock_filename(dir()).
lock_filename(Dir) -> filename:join(Dir, ?LOCK_FILENAME).
backup_dir() -> dir() ++ "-upgrade-backup".
+is_disc_node_legacy() ->
+ %% This is pretty ugly but we can't start Mnesia and ask it (will
+ %% hang), we can't look at the config file (may not include us
+ %% even if we're a disc node). We also can't use
+ %% rabbit_mnesia:is_disc_node/0 because that will give false
+ %% postivies on Rabbit up to 2.5.1.
+ filelib:is_regular(filename:join(dir(), "rabbit_durable_exchange.DCD")).
+
%% NB: we cannot use rabbit_log here since it may not have been
%% started yet
info(Msg, Args) -> error_logger:info_msg(Msg, Args).