summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xscripts/rabbitmq-plugins.bat2
-rwxr-xr-xscripts/rabbitmq-server.bat2
-rwxr-xr-xscripts/rabbitmqctl.bat2
-rw-r--r--src/mirrored_supervisor.erl2
-rw-r--r--src/rabbit_amqqueue_process.erl18
-rw-r--r--src/rabbit_backing_queue.erl5
-rw-r--r--src/rabbit_control_main.erl22
-rw-r--r--src/rabbit_log.erl10
-rw-r--r--src/rabbit_misc.erl13
-rw-r--r--src/rabbit_mnesia.erl12
-rw-r--r--src/rabbit_plugins.erl98
-rw-r--r--src/rabbit_prelaunch.erl7
-rw-r--r--src/rabbit_tests.erl18
-rw-r--r--src/vm_memory_monitor.erl75
14 files changed, 137 insertions, 149 deletions
diff --git a/scripts/rabbitmq-plugins.bat b/scripts/rabbitmq-plugins.bat
index c67a0263f6..341f871a0e 100755
--- a/scripts/rabbitmq-plugins.bat
+++ b/scripts/rabbitmq-plugins.bat
@@ -47,7 +47,7 @@ if "!RABBITMQ_PLUGINS_DIR!"=="" (
set RABBITMQ_PLUGINS_DIR=!TDP0!..\plugins
)
-"!ERLANG_HOME!\bin\erl.exe" -pa "!TDP0!..\ebin" -noinput -hidden -sname rabbitmq-plugins!RANDOM! -s rabbit_plugins_main -enabled_plugins_file "!RABBITMQ_ENABLED_PLUGINS_FILE!" -plugins_dist_dir "!RABBITMQ_PLUGINS_DIR:\=/!" -extra !STAR!
+"!ERLANG_HOME!\bin\erl.exe" -pa "!TDP0!..\ebin" -noinput -hidden -sname rabbitmq-plugins!RANDOM!!TIME:~9! -s rabbit_plugins_main -enabled_plugins_file "!RABBITMQ_ENABLED_PLUGINS_FILE!" -plugins_dist_dir "!RABBITMQ_PLUGINS_DIR:\=/!" -extra !STAR!
endlocal
endlocal
diff --git a/scripts/rabbitmq-server.bat b/scripts/rabbitmq-server.bat
index 167f272e41..3aea4c070a 100755
--- a/scripts/rabbitmq-server.bat
+++ b/scripts/rabbitmq-server.bat
@@ -96,7 +96,7 @@ set RABBITMQ_EBIN_ROOT=!TDP0!..\ebin
-pa "!RABBITMQ_EBIN_ROOT!" ^
-noinput -hidden ^
-s rabbit_prelaunch ^
- -sname rabbitmqprelaunch!RANDOM! ^
+ -sname rabbitmqprelaunch!RANDOM!!TIME:~9! ^
-extra "!RABBITMQ_NODENAME!"
if ERRORLEVEL 1 (
diff --git a/scripts/rabbitmqctl.bat b/scripts/rabbitmqctl.bat
index 9f549f1e08..d8b1eaf16e 100755
--- a/scripts/rabbitmqctl.bat
+++ b/scripts/rabbitmqctl.bat
@@ -43,7 +43,7 @@ if not exist "!ERLANG_HOME!\bin\erl.exe" (
exit /B
)
-"!ERLANG_HOME!\bin\erl.exe" -pa "!TDP0!..\ebin" -noinput -hidden !RABBITMQ_CTL_ERL_ARGS! -sname rabbitmqctl!RANDOM! -s rabbit_control_main -nodename !RABBITMQ_NODENAME! -extra !STAR!
+"!ERLANG_HOME!\bin\erl.exe" -pa "!TDP0!..\ebin" -noinput -hidden !RABBITMQ_CTL_ERL_ARGS! -sname rabbitmqctl!RANDOM!!TIME:~9! -s rabbit_control_main -nodename !RABBITMQ_NODENAME! -extra !STAR!
endlocal
endlocal
diff --git a/src/mirrored_supervisor.erl b/src/mirrored_supervisor.erl
index 4fc488b88a..24c3ebd008 100644
--- a/src/mirrored_supervisor.erl
+++ b/src/mirrored_supervisor.erl
@@ -174,7 +174,7 @@
-spec start_internal(Group, ChildSpecs) -> Result when
Group :: group_name(),
ChildSpecs :: [supervisor2:child_spec()],
- Result :: supervisor2:startlink_ret().
+ Result :: {'ok', pid()} | {'error', term()}.
-spec create_tables() -> Result when
Result :: 'ok'.
diff --git a/src/rabbit_amqqueue_process.erl b/src/rabbit_amqqueue_process.erl
index b4071627ce..6bf290de01 100644
--- a/src/rabbit_amqqueue_process.erl
+++ b/src/rabbit_amqqueue_process.erl
@@ -717,14 +717,16 @@ drop_expired_messages(State = #q{backing_queue_state = BQS,
Now = now_micros(),
DLXFun = dead_letter_fun(expired, State),
ExpirePred = fun (#message_properties{expiry = Expiry}) -> Now > Expiry end,
- case DLXFun of
- undefined -> {undefined, BQS1} = BQ:dropwhile(ExpirePred, false, BQS),
- BQS1;
- _ -> {Msgs, BQS1} = BQ:dropwhile(ExpirePred, true, BQS),
- lists:foreach(
- fun({Msg, AckTag}) -> DLXFun(Msg, AckTag) end, Msgs),
- BQS1
- end,
+ BQS1 = case DLXFun of
+ undefined -> {undefined, BQS2} =
+ BQ:dropwhile(ExpirePred, false, BQS),
+ BQS2;
+ _ -> {Msgs, BQS2} = BQ:dropwhile(ExpirePred, true, BQS),
+ lists:foreach(
+ fun({Msg, AckTag}) -> DLXFun(Msg, AckTag) end,
+ Msgs),
+ BQS2
+ end,
ensure_ttl_timer(State#q{backing_queue_state = BQS1}).
ensure_ttl_timer(State = #q{backing_queue = BQ,
diff --git a/src/rabbit_backing_queue.erl b/src/rabbit_backing_queue.erl
index dc144a0e53..95523bedb8 100644
--- a/src/rabbit_backing_queue.erl
+++ b/src/rabbit_backing_queue.erl
@@ -18,6 +18,8 @@
-ifdef(use_specs).
+-export_type([async_callback/0]).
+
%% We can't specify a per-queue ack/state with callback signatures
-type(ack() :: any()).
-type(state() :: any()).
@@ -28,7 +30,8 @@
{rabbit_types:basic_message(), boolean(), Ack, non_neg_integer()})).
-type(attempt_recovery() :: boolean()).
-type(purged_msg_count() :: non_neg_integer()).
--type(async_callback() :: fun ((atom(), fun ((atom(), state()) -> state())) -> 'ok')).
+-type(async_callback() ::
+ fun ((atom(), fun ((atom(), state()) -> state())) -> 'ok')).
-type(duration() :: ('undefined' | 'infinity' | number())).
-type(msg_fun() :: fun((rabbit_types:basic_message(), ack()) -> 'ok') |
diff --git a/src/rabbit_control_main.erl b/src/rabbit_control_main.erl
index 0b1902509d..b92493e3e6 100644
--- a/src/rabbit_control_main.erl
+++ b/src/rabbit_control_main.erl
@@ -170,8 +170,8 @@ start() ->
{error, Reason} ->
print_error("~p", [Reason]),
rabbit_misc:quit(2);
- {error_string, Reason} ->
- print_error("~s", [Reason]),
+ {parse_error, {_Line, Mod, Err}} ->
+ print_error("~s", [lists:flatten(Mod:format_error(Err))]),
rabbit_misc:quit(2);
{badrpc, {'EXIT', Reason}} ->
print_error("~p", [Reason]),
@@ -465,16 +465,15 @@ action(eval, Node, [Expr], _Opts, _Inform) ->
case erl_scan:string(Expr) of
{ok, Scanned, _} ->
case erl_parse:parse_exprs(Scanned) of
- {ok, Parsed} ->
- {value, Value, _} = unsafe_rpc(
- Node, erl_eval, exprs, [Parsed, []]),
- io:format("~p~n", [Value]),
- ok;
- {error, E} ->
- {error_string, format_parse_error(E)}
+ {ok, Parsed} -> {value, Value, _} =
+ unsafe_rpc(
+ Node, erl_eval, exprs, [Parsed, []]),
+ io:format("~p~n", [Value]),
+ ok;
+ {error, E} -> {parse_error, E}
end;
{error, E, _} ->
- {error_string, format_parse_error(E)}
+ {parse_error, E}
end.
%%----------------------------------------------------------------------------
@@ -563,9 +562,6 @@ exit_loop(Port) ->
{Port, _} -> exit_loop(Port)
end.
-format_parse_error({_Line, Mod, Err}) ->
- lists:flatten(Mod:format_error(Err)).
-
%%----------------------------------------------------------------------------
default_if_empty(List, Default) when is_list(List) ->
diff --git a/src/rabbit_log.erl b/src/rabbit_log.erl
index a6b4eeb05f..8dfa89d319 100644
--- a/src/rabbit_log.erl
+++ b/src/rabbit_log.erl
@@ -40,18 +40,20 @@
-spec(log/3 :: (category(), level(), string()) -> 'ok').
-spec(log/4 :: (category(), level(), string(), [any()]) -> 'ok').
--spec(info/1 :: (string()) -> 'ok').
--spec(info/2 :: (string(), [any()]) -> 'ok').
+
+-spec(info/1 :: (string()) -> 'ok').
+-spec(info/2 :: (string(), [any()]) -> 'ok').
-spec(warning/1 :: (string()) -> 'ok').
-spec(warning/2 :: (string(), [any()]) -> 'ok').
--spec(error/1 :: (string()) -> 'ok').
--spec(error/2 :: (string(), [any()]) -> 'ok').
+-spec(error/1 :: (string()) -> 'ok').
+-spec(error/2 :: (string(), [any()]) -> 'ok').
-endif.
%%----------------------------------------------------------------------------
start_link() ->
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
+
log(Category, Level, Fmt) -> log(Category, Level, Fmt, []).
log(Category, Level, Fmt, Args) when is_list(Args) ->
diff --git a/src/rabbit_misc.erl b/src/rabbit_misc.erl
index 6e88de8201..5c91fe532d 100644
--- a/src/rabbit_misc.erl
+++ b/src/rabbit_misc.erl
@@ -19,7 +19,7 @@
-include("rabbit_framing.hrl").
-export([method_record_type/1, polite_pause/0, polite_pause/1]).
--export([die/1, frame_error/2, amqp_error/4, quit/1, quit/2,
+-export([die/1, frame_error/2, amqp_error/4, quit/1,
protocol_error/3, protocol_error/4, protocol_error/1]).
-export([not_found/1, assert_args_equivalence/4]).
-export([dirty_read/1]).
@@ -94,7 +94,6 @@
(rabbit_framing:amqp_exception()) -> channel_or_connection_exit()).
-spec(quit/1 :: (integer()) -> no_return()).
--spec(quit/2 :: (string(), [term()]) -> no_return()).
-spec(frame_error/2 :: (rabbit_framing:amqp_method_name(), binary())
-> rabbit_types:connection_exit()).
@@ -401,19 +400,9 @@ report_coverage_percentage(File, Cov, NotCov, Mod) ->
confirm_to_sender(Pid, MsgSeqNos) ->
gen_server2:cast(Pid, {confirm, MsgSeqNos, self()}).
-%%
-%% @doc Halts the emulator after printing out an error message io-formatted with
-%% the supplied arguments. The exit status of the beam process will be set to 1.
-%%
-quit(Fmt, Args) ->
- io:format("ERROR: " ++ Fmt ++ "~n", Args),
- quit(1).
-
-%%
%% @doc Halts the emulator returning the given status code to the os.
%% On Windows this function will block indefinitely so as to give the io
%% subsystem time to flush stdout completely.
-%%
quit(Status) ->
case os:type() of
{unix, _} -> halt(Status);
diff --git a/src/rabbit_mnesia.erl b/src/rabbit_mnesia.erl
index 80acfc5d70..6aade1dae4 100644
--- a/src/rabbit_mnesia.erl
+++ b/src/rabbit_mnesia.erl
@@ -202,7 +202,7 @@ reset(Force) ->
Node = node(),
case Force of
true ->
- ok;
+ disconnect_nodes(nodes());
false ->
AllNodes = all_clustered_nodes(),
%% Reconnecting so that we will get an up to date nodes.
@@ -223,17 +223,19 @@ reset(Force) ->
leave_cluster(),
rabbit_misc:ensure_ok(mnesia:delete_schema([Node]),
cannot_delete_schema),
+ disconnect_nodes(all_clustered_nodes()),
ok
end,
- %% We need to make sure that we don't end up in a distributed Erlang system
- %% with nodes while not being in an Mnesia cluster with them. We don't
- %% handle that well.
- [erlang:disconnect_node(N) || N <- all_clustered_nodes()],
%% remove persisted messages and any other garbage we find
ok = rabbit_file:recursive_delete(filelib:wildcard(dir() ++ "/*")),
ok = rabbit_node_monitor:reset_cluster_status_file(),
ok.
+%% We need to make sure that we don't end up in a distributed Erlang system with
+%% nodes while not being in an Mnesia cluster with them. We don't handle that
+%% well.
+disconnect_nodes(Nodes) -> [erlang:disconnect_node(N) || N <- Nodes].
+
change_cluster_node_type(Type) ->
ensure_mnesia_dir(),
ensure_mnesia_not_running(),
diff --git a/src/rabbit_plugins.erl b/src/rabbit_plugins.erl
index 7cf6eea945..ecb1961126 100644
--- a/src/rabbit_plugins.erl
+++ b/src/rabbit_plugins.erl
@@ -17,8 +17,7 @@
-module(rabbit_plugins).
-include("rabbit.hrl").
--export([setup/0, active/0, read_enabled/1,
- list/1, dependencies/3]).
+-export([setup/0, active/0, read_enabled/1, list/1, dependencies/3]).
-define(VERBOSE_DEF, {?VERBOSE_OPT, flag}).
-define(MINIMAL_DEF, {?MINIMAL_OPT, flag}).
@@ -36,28 +35,25 @@
-ifdef(use_specs).
--spec(setup/0 :: () -> [atom()]).
--spec(active/0 :: () -> [atom()]).
+-type(plugin_name() :: atom()).
+
+-spec(setup/0 :: () -> [plugin_name()]).
+-spec(active/0 :: () -> [plugin_name()]).
-spec(list/1 :: (string()) -> [#plugin{}]).
--spec(read_enabled/1 :: (file:filename()) -> [atom()]).
--spec(dependencies/3 ::
- (boolean(), [atom()], [#plugin{}]) -> [atom()]).
+-spec(read_enabled/1 :: (file:filename()) -> [plugin_name()]).
+-spec(dependencies/3 :: (boolean(), [plugin_name()], [#plugin{}]) ->
+ [plugin_name()]).
-endif.
%%----------------------------------------------------------------------------
-%%
%% @doc Prepares the file system and installs all enabled plugins.
-%%
setup() ->
- {ok, PluginDir} = application:get_env(rabbit, plugins_dir),
- {ok, ExpandDir} = application:get_env(rabbit, plugins_expand_dir),
- {ok, EnabledPluginsFile} = application:get_env(rabbit,
- enabled_plugins_file),
- prepare_plugins(EnabledPluginsFile, PluginDir, ExpandDir),
- [prepare_dir_plugin(PluginName) ||
- PluginName <- filelib:wildcard(ExpandDir ++ "/*/ebin/*.app")].
+ {ok, PluginDir} = application:get_env(rabbit, plugins_dir),
+ {ok, ExpandDir} = application:get_env(rabbit, plugins_expand_dir),
+ {ok, EnabledFile} = application:get_env(rabbit, enabled_plugins_file),
+ prepare_plugins(EnabledFile, PluginDir, ExpandDir).
%% @doc Lists the plugins which are currently running.
active() ->
@@ -77,8 +73,7 @@ list(PluginsDir) ->
(Plugin = #plugin{}, {Plugins1, Problems1}) ->
{[Plugin|Plugins1], Problems1}
end, {[], []},
- [get_plugin_info(PluginsDir, Plug) ||
- Plug <- EZs ++ FreeApps]),
+ [plugin_info(PluginsDir, Plug) || Plug <- EZs ++ FreeApps]),
case Problems of
[] -> ok;
_ -> io:format("Warning: Problem reading some plugins: ~p~n",
@@ -98,11 +93,9 @@ read_enabled(PluginsFile) ->
PluginsFile, Reason}})
end.
-%%
%% @doc Calculate the dependency graph from <i>Sources</i>.
%% When Reverse =:= true the bottom/leaf level applications are returned in
%% the resulting list, otherwise they're skipped.
-%%
dependencies(Reverse, Sources, AllPlugins) ->
{ok, G} = rabbit_misc:build_acyclic_graph(
fun (App, _Deps) -> [{App, App}] end,
@@ -118,42 +111,38 @@ dependencies(Reverse, Sources, AllPlugins) ->
%%----------------------------------------------------------------------------
-prepare_plugins(EnabledPluginsFile, PluginsDistDir, DestDir) ->
+prepare_plugins(EnabledFile, PluginsDistDir, ExpandDir) ->
AllPlugins = list(PluginsDistDir),
- Enabled = read_enabled(EnabledPluginsFile),
+ Enabled = read_enabled(EnabledFile),
ToUnpack = dependencies(false, Enabled, AllPlugins),
ToUnpackPlugins = lookup_plugins(ToUnpack, AllPlugins),
- Missing = Enabled -- plugin_names(ToUnpackPlugins),
- case Missing of
- [] -> ok;
- _ -> io:format("Warning: the following enabled plugins were "
- "not found: ~p~n", [Missing])
+ case Enabled -- plugin_names(ToUnpackPlugins) of
+ [] -> ok;
+ Missing -> io:format("Warning: the following enabled plugins were "
+ "not found: ~p~n", [Missing])
end,
%% Eliminate the contents of the destination directory
- case delete_recursively(DestDir) of
- ok -> ok;
- {error, E} -> rabbit_misc:quit("Could not delete dir ~s (~p)",
- [DestDir, E])
+ case delete_recursively(ExpandDir) of
+ ok -> ok;
+ {error, E1} -> throw({error, {cannot_delete_plugins_expand_dir,
+ [ExpandDir, E1]}})
end,
- case filelib:ensure_dir(DestDir ++ "/") of
+ case filelib:ensure_dir(ExpandDir ++ "/") of
ok -> ok;
- {error, E2} -> rabbit_misc:quit("Could not create dir ~s (~p)",
- [DestDir, E2])
+ {error, E2} -> throw({error, {cannot_create_plugins_expand_dir,
+ [ExpandDir, E2]}})
end,
- [prepare_plugin(Plugin, DestDir) || Plugin <- ToUnpackPlugins].
+ [prepare_plugin(Plugin, ExpandDir) || Plugin <- ToUnpackPlugins],
-prepare_dir_plugin(PluginAppDescFn) ->
- %% Add the plugin ebin directory to the load path
- PluginEBinDirN = filename:dirname(PluginAppDescFn),
- code:add_path(PluginEBinDirN),
+ [prepare_dir_plugin(PluginAppDescPath) ||
+ PluginAppDescPath <- filelib:wildcard(ExpandDir ++ "/*/ebin/*.app")].
- %% We want the second-last token
- NameTokens = string:tokens(PluginAppDescFn,"/."),
- PluginNameString = lists:nth(length(NameTokens) - 1, NameTokens),
- list_to_atom(PluginNameString).
+prepare_dir_plugin(PluginAppDescPath) ->
+ code:add_path(filename:dirname(PluginAppDescPath)),
+ list_to_atom(filename:basename(PluginAppDescPath, ".app")).
%%----------------------------------------------------------------------------
@@ -164,22 +153,19 @@ delete_recursively(Fn) ->
Error -> Error
end.
-prepare_plugin(#plugin{type = ez, location = Location}, PluginDestDir) ->
- zip:unzip(Location, [{cwd, PluginDestDir}]);
+prepare_plugin(#plugin{type = ez, location = Location}, ExpandDir) ->
+ zip:unzip(Location, [{cwd, ExpandDir}]);
prepare_plugin(#plugin{type = dir, name = Name, location = Location},
- PluginsDestDir) ->
- rabbit_file:recursive_copy(Location,
- filename:join([PluginsDestDir, Name])).
+ ExpandDir) ->
+ rabbit_file:recursive_copy(Location, filename:join([ExpandDir, Name])).
-%% Get the #plugin{} from an .ez.
-get_plugin_info(Base, {ez, EZ0}) ->
+plugin_info(Base, {ez, EZ0}) ->
EZ = filename:join([Base, EZ0]),
case read_app_file(EZ) of
{application, Name, Props} -> mkplugin(Name, Props, ez, EZ);
{error, Reason} -> {error, EZ, Reason}
end;
-%% Get the #plugin{} from an .app.
-get_plugin_info(Base, {app, App0}) ->
+plugin_info(Base, {app, App0}) ->
App = filename:join([Base, App0]),
case rabbit_file:read_term_file(App) of
{ok, [{application, Name, Props}]} ->
@@ -198,7 +184,6 @@ mkplugin(Name, Props, Type, Location) ->
#plugin{name = Name, version = Version, description = Description,
dependencies = Dependencies, location = Location, type = Type}.
-%% Read the .app file from an ez.
read_app_file(EZ) ->
case zip:list_dir(EZ) of
{ok, [_|ZippedFiles]} ->
@@ -214,13 +199,11 @@ read_app_file(EZ) ->
{error, {invalid_ez, Reason}}
end.
-%% Return the path of the .app files in ebin/.
find_app_files(ZippedFiles) ->
{ok, RE} = re:compile("^.*/ebin/.*.app$"),
[Path || {zip_file, Path, _, _, _, _} <- ZippedFiles,
re:run(Path, RE, [{capture, none}]) =:= match].
-%% Parse a binary into a term.
parse_binary(Bin) ->
try
{ok, Ts, _} = erl_scan:string(binary_to_list(Bin)),
@@ -230,13 +213,10 @@ parse_binary(Bin) ->
Err -> {error, {invalid_app, Err}}
end.
-%% Filter out applications that can be loaded *right now*.
filter_applications(Applications) ->
[Application || Application <- Applications,
not is_available_app(Application)].
-%% Return whether is application is already available (and hence
-%% doesn't need enabling).
is_available_app(Application) ->
case application:load(Application) of
{error, {already_loaded, _}} -> true;
@@ -245,10 +225,8 @@ is_available_app(Application) ->
_ -> false
end.
-%% Return the names of the given plugins.
plugin_names(Plugins) ->
[Name || #plugin{name = Name} <- Plugins].
-%% Find plugins by name in a list of plugins.
lookup_plugins(Names, AllPlugins) ->
[P || P = #plugin{name = Name} <- AllPlugins, lists:member(Name, Names)].
diff --git a/src/rabbit_prelaunch.erl b/src/rabbit_prelaunch.erl
index b045443533..404afe3c3b 100644
--- a/src/rabbit_prelaunch.erl
+++ b/src/rabbit_prelaunch.erl
@@ -57,7 +57,7 @@ duplicate_node_check(NodeStr) ->
case rabbit_nodes:names(NodeHost) of
{ok, NamePorts} ->
case proplists:is_defined(NodeName, NamePorts) of
- true -> io:format("node with name ~p "
+ true -> io:format("ERROR: node with name ~p "
"already running on ~p~n",
[NodeName, NodeHost]),
io:format(rabbit_nodes:diagnostics([Node]) ++ "~n"),
@@ -65,7 +65,8 @@ duplicate_node_check(NodeStr) ->
false -> ok
end;
{error, EpmdReason} ->
- rabbit_misc:quit("epmd error for host ~p: ~p (~s)~n",
+ io:format("ERROR: epmd error for host ~p: ~p (~s)~n",
[NodeHost, EpmdReason,
- rabbit_misc:format_inet_error(EpmdReason)])
+ rabbit_misc:format_inet_error(EpmdReason)]),
+ rabbit_misc:quit(?ERROR_CODE)
end.
diff --git a/src/rabbit_tests.erl b/src/rabbit_tests.erl
index 1e4346e28d..7fbe6bab46 100644
--- a/src/rabbit_tests.erl
+++ b/src/rabbit_tests.erl
@@ -79,9 +79,19 @@ do_if_secondary_node(Up, Down) ->
setup_cluster() ->
do_if_secondary_node(
fun (SecondaryNode) ->
+ cover:stop(SecondaryNode),
ok = control_action(stop_app, []),
+ %% 'cover' does not cope at all well with nodes disconnecting,
+ %% which happens as part of reset. So we turn it off
+ %% temporarily. That is ok even if we're not in general using
+ %% cover, it just turns the engine on / off and doesn't log
+ %% anything. Note that this way cover won't be on when joining
+ %% the cluster, but this is OK since we're testing the clustering
+ %% interface elsewere anyway.
+ cover:stop(nodes()),
ok = control_action(join_cluster,
[atom_to_list(SecondaryNode)]),
+ cover:start(nodes()),
ok = control_action(start_app, []),
ok = control_action(start_app, SecondaryNode, [], [])
end,
@@ -1038,7 +1048,15 @@ test_server_status() ->
ok = control_action(list_consumers, []),
%% set vm memory high watermark
+ HWM = vm_memory_monitor:get_vm_memory_high_watermark(),
+ ok = control_action(set_vm_memory_high_watermark, ["1"]),
ok = control_action(set_vm_memory_high_watermark, ["1.0"]),
+ ok = control_action(set_vm_memory_high_watermark, [float_to_list(HWM)]),
+
+ %% eval
+ {parse_error, _} = control_action(eval, ["\""]),
+ {parse_error, _} = control_action(eval, ["a("]),
+ ok = control_action(eval, ["a."]),
%% cleanup
[{ok, _} = rabbit_amqqueue:delete(QR, false, false) || QR <- [Q, Q2]],
diff --git a/src/vm_memory_monitor.erl b/src/vm_memory_monitor.erl
index df5f73e749..5ce894a944 100644
--- a/src/vm_memory_monitor.erl
+++ b/src/vm_memory_monitor.erl
@@ -49,11 +49,11 @@
-record(state, {total_memory,
memory_limit,
+ memory_fraction,
timeout,
timer,
alarmed,
- alarm_set,
- alarm_clear
+ alarm_funs
}).
%%----------------------------------------------------------------------------
@@ -77,11 +77,9 @@
%% Public API
%%----------------------------------------------------------------------------
-get_total_memory() ->
- get_total_memory(os:type()).
+get_total_memory() -> get_total_memory(os:type()).
-get_vm_limit() ->
- get_vm_limit(os:type()).
+get_vm_limit() -> get_vm_limit(os:type()).
get_check_interval() ->
gen_server:call(?MODULE, get_check_interval, infinity).
@@ -109,25 +107,21 @@ start_link(MemFraction) ->
start_link(MemFraction, AlarmSet, AlarmClear) ->
gen_server:start_link({local, ?SERVER}, ?MODULE,
- [MemFraction, AlarmSet, AlarmClear], []).
+ [MemFraction, {AlarmSet, AlarmClear}], []).
-init([MemFraction, AlarmSet, AlarmClear]) ->
+init([MemFraction, AlarmFuns]) ->
TRef = start_timer(?DEFAULT_MEMORY_CHECK_INTERVAL),
- State = #state { timeout = ?DEFAULT_MEMORY_CHECK_INTERVAL,
- timer = TRef,
- alarmed = false,
- alarm_set = AlarmSet,
- alarm_clear = AlarmClear },
+ State = #state { timeout = ?DEFAULT_MEMORY_CHECK_INTERVAL,
+ timer = TRef,
+ alarmed = false,
+ alarm_funs = AlarmFuns },
{ok, set_mem_limits(State, MemFraction)}.
handle_call(get_vm_memory_high_watermark, _From, State) ->
- {reply, State#state.memory_limit / State#state.total_memory, State};
+ {reply, State#state.memory_fraction, State};
handle_call({set_vm_memory_high_watermark, MemFraction}, _From, State) ->
- State1 = set_mem_limits(State, MemFraction),
- error_logger:info_msg("Memory alarm changed to ~p, ~p bytes.~n",
- [MemFraction, State1#state.memory_limit]),
- {reply, ok, State1};
+ {reply, ok, set_mem_limits(State, MemFraction)};
handle_call(get_check_interval, _From, State) ->
{reply, State#state.timeout, State};
@@ -179,34 +173,41 @@ set_mem_limits(State, MemFraction) ->
?MEMORY_SIZE_FOR_UNKNOWN_OS;
M -> M
end,
- MemLim = get_mem_limit(MemFraction, TotalMemory),
+ UsableMemory = case get_vm_limit() of
+ Limit when Limit < TotalMemory ->
+ error_logger:warning_msg(
+ "Only ~pMB of ~pMB memory usable due to "
+ "limited address space.~n",
+ [trunc(V/?ONE_MB) || V <- [Limit, TotalMemory]]),
+ Limit;
+ _ ->
+ TotalMemory
+ end,
+ MemLim = trunc(MemFraction * UsableMemory),
error_logger:info_msg("Memory limit set to ~pMB of ~pMB total.~n",
[trunc(MemLim/?ONE_MB), trunc(TotalMemory/?ONE_MB)]),
- internal_update(State #state { total_memory = TotalMemory,
- memory_limit = MemLim }).
+ internal_update(State #state { total_memory = TotalMemory,
+ memory_limit = MemLim,
+ memory_fraction = MemFraction}).
internal_update(State = #state { memory_limit = MemLimit,
- alarmed = Alarmed,
- alarm_set = AlarmSet,
- alarm_clear = AlarmClear }) ->
+ alarmed = Alarmed,
+ alarm_funs = {AlarmSet, AlarmClear} }) ->
MemUsed = erlang:memory(total),
NewAlarmed = MemUsed > MemLimit,
case {Alarmed, NewAlarmed} of
- {false, true} ->
- emit_update_info(set, MemUsed, MemLimit),
- AlarmSet({{resource_limit, memory, node()}, []});
- {true, false} ->
- emit_update_info(clear, MemUsed, MemLimit),
- AlarmClear({resource_limit, memory, node()});
- _ ->
- ok
+ {false, true} -> emit_update_info(set, MemUsed, MemLimit),
+ AlarmSet({{resource_limit, memory, node()}, []});
+ {true, false} -> emit_update_info(clear, MemUsed, MemLimit),
+ AlarmClear({resource_limit, memory, node()});
+ _ -> ok
end,
State #state {alarmed = NewAlarmed}.
-emit_update_info(State, MemUsed, MemLimit) ->
+emit_update_info(AlarmState, MemUsed, MemLimit) ->
error_logger:info_msg(
"vm_memory_high_watermark ~p. Memory used:~p allowed:~p~n",
- [State, MemUsed, MemLimit]).
+ [AlarmState, MemUsed, MemLimit]).
start_timer(Timeout) ->
{ok, TRef} = timer:send_interval(Timeout, update),
@@ -220,7 +221,7 @@ get_vm_limit({win32,_OSname}) ->
8 -> 8*1024*1024*1024*1024 %% 8 TB for 64 bits 2^42
end;
-%% On a 32-bit machine, if you're using more than 2 gigs of RAM you're
+%% On a 32-bit machine, if you're using more than 4 gigs of RAM you're
%% in big trouble anyway.
get_vm_limit(_OsType) ->
case erlang:system_info(wordsize) of
@@ -229,10 +230,6 @@ get_vm_limit(_OsType) ->
%%http://en.wikipedia.org/wiki/X86-64#Virtual_address_space_details
end.
-get_mem_limit(MemFraction, TotalMemory) ->
- AvMem = lists:min([TotalMemory, get_vm_limit()]),
- trunc(AvMem * MemFraction).
-
%%----------------------------------------------------------------------------
%% Internal Helpers
%%----------------------------------------------------------------------------