diff options
| -rwxr-xr-x | scripts/rabbitmq-plugins.bat | 2 | ||||
| -rwxr-xr-x | scripts/rabbitmq-server.bat | 2 | ||||
| -rwxr-xr-x | scripts/rabbitmqctl.bat | 2 | ||||
| -rw-r--r-- | src/mirrored_supervisor.erl | 2 | ||||
| -rw-r--r-- | src/rabbit_amqqueue_process.erl | 18 | ||||
| -rw-r--r-- | src/rabbit_backing_queue.erl | 5 | ||||
| -rw-r--r-- | src/rabbit_control_main.erl | 22 | ||||
| -rw-r--r-- | src/rabbit_log.erl | 10 | ||||
| -rw-r--r-- | src/rabbit_misc.erl | 13 | ||||
| -rw-r--r-- | src/rabbit_mnesia.erl | 12 | ||||
| -rw-r--r-- | src/rabbit_plugins.erl | 98 | ||||
| -rw-r--r-- | src/rabbit_prelaunch.erl | 7 | ||||
| -rw-r--r-- | src/rabbit_tests.erl | 18 | ||||
| -rw-r--r-- | src/vm_memory_monitor.erl | 75 |
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 %%---------------------------------------------------------------------------- |
