summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Majkowski <majek@lshift.net>2009-09-16 14:42:17 +0100
committerMarek Majkowski <majek@lshift.net>2009-09-16 14:42:17 +0100
commit08c140a80ca86338fbfcdc88219a1dd1507070a5 (patch)
tree6b0fb0b82825b03424e5bfa457545b16f783368d
parentead039b155010045861229aa27424d6c3d7c7197 (diff)
downloadrabbitmq-server-08c140a80ca86338fbfcdc88219a1dd1507070a5.tar.gz
new memsup code
-rw-r--r--ebin/rabbit_app.in2
-rwxr-xr-xscripts/rabbitmq-server4
-rwxr-xr-xscripts/rabbitmq-server.bat6
-rwxr-xr-xscripts/rabbitmq-service.bat6
-rw-r--r--src/rabbit.erl15
-rw-r--r--src/rabbit_alarm.erl101
-rw-r--r--src/rabbit_memguard.erl194
-rw-r--r--src/rabbit_memsup.erl142
-rw-r--r--src/rabbit_memsup_darwin.erl88
-rw-r--r--src/rabbit_memsup_linux.erl101
10 files changed, 228 insertions, 431 deletions
diff --git a/ebin/rabbit_app.in b/ebin/rabbit_app.in
index 6fc6e464..8796b425 100644
--- a/ebin/rabbit_app.in
+++ b/ebin/rabbit_app.in
@@ -22,4 +22,4 @@
{default_pass, <<"guest">>},
{default_vhost, <<"/">>},
{default_permissions, [<<".*">>, <<".*">>, <<".*">>]},
- {memory_alarms, auto}]}]}.
+ {memory_high_watermark, 0.85}]}]}.
diff --git a/scripts/rabbitmq-server b/scripts/rabbitmq-server
index 547220b4..ffd97b35 100755
--- a/scripts/rabbitmq-server
+++ b/scripts/rabbitmq-server
@@ -102,9 +102,9 @@ exec erl \
-sasl sasl_error_logger '{file,"'${RABBITMQ_SASL_LOGS}'"}' \
-os_mon start_cpu_sup true \
-os_mon start_disksup false \
- -os_mon start_memsup false \
+ -os_mon start_memsup true \
-os_mon start_os_sup false \
- -os_mon memsup_system_only true \
+ -os_mon memsup_system_only false \
-os_mon system_memory_high_watermark 0.95 \
-mnesia dir "\"${RABBITMQ_MNESIA_DIR}\"" \
${RABBITMQ_CLUSTER_CONFIG_OPTION} \
diff --git a/scripts/rabbitmq-server.bat b/scripts/rabbitmq-server.bat
index a784fee3..b83d44ca 100755
--- a/scripts/rabbitmq-server.bat
+++ b/scripts/rabbitmq-server.bat
@@ -127,10 +127,10 @@ if exist "%RABBITMQ_EBIN_ROOT%\rabbit.boot" (
-sasl sasl_error_logger {file,\""%RABBITMQ_LOG_BASE%/%RABBITMQ_NODENAME%-sasl.log"\"} ^
-os_mon start_cpu_sup true ^
-os_mon start_disksup false ^
--os_mon start_memsup false ^
+-os_mon start_memsup true ^
-os_mon start_os_sup false ^
--os_mon memsup_system_only true ^
--os_mon system_memory_high_watermark 0.95 ^
+-os_mon memsup_system_only false ^
+-os_mon system_memory_high_watermark 1.0 ^
-mnesia dir \""%RABBITMQ_MNESIA_DIR%"\" ^
%CLUSTER_CONFIG% ^
%RABBITMQ_SERVER_START_ARGS% ^
diff --git a/scripts/rabbitmq-service.bat b/scripts/rabbitmq-service.bat
index 29be1742..dcb929b1 100755
--- a/scripts/rabbitmq-service.bat
+++ b/scripts/rabbitmq-service.bat
@@ -172,10 +172,10 @@ set ERLANG_SERVICE_ARGUMENTS= ^
-sasl sasl_error_logger {file,\""%RABBITMQ_LOG_BASE%/%RABBITMQ_NODENAME%-sasl.log"\"} ^
-os_mon start_cpu_sup true ^
-os_mon start_disksup false ^
--os_mon start_memsup false ^
+-os_mon start_memsup true ^
-os_mon start_os_sup false ^
--os_mon memsup_system_only true ^
--os_mon system_memory_high_watermark 0.95 ^
+-os_mon memsup_system_only false ^
+-os_mon system_memory_high_watermark 1.0 ^
-mnesia dir \""%RABBITMQ_MNESIA_DIR%"\" ^
%CLUSTER_CONFIG% ^
%RABBITMQ_SERVER_START_ARGS% ^
diff --git a/src/rabbit.erl b/src/rabbit.erl
index ef1e0049..875021aa 100644
--- a/src/rabbit.erl
+++ b/src/rabbit.erl
@@ -136,8 +136,12 @@ start(normal, []) ->
ok = rabbit_binary_generator:
check_empty_content_body_frame_size(),
- {ok, MemoryAlarms} = application:get_env(memory_alarms),
- ok = rabbit_alarm:start(MemoryAlarms),
+ ok = rabbit_alarm:start(),
+ case application:get_env(memory_high_watermark) of
+ {ok, false} -> ok;
+ {ok, off} -> ok;
+ {ok, Float} -> start_child(rabbit_memguard, [Float])
+ end,
ok = rabbit_amqqueue:start(),
@@ -252,6 +256,13 @@ start_child(Mod) ->
transient, 100, worker, [Mod]}),
ok.
+start_child(Mod, Args) ->
+ {ok,_} = supervisor:start_child(rabbit_sup,
+ {Mod, {Mod, start_link, Args},
+ transient, 100, worker, [Mod]}),
+ ok.
+
+
ensure_working_log_handlers() ->
Handlers = gen_event:which_handlers(error_logger),
ok = ensure_working_log_handler(error_logger_file_h,
diff --git a/src/rabbit_alarm.erl b/src/rabbit_alarm.erl
index 309c9a0e..c1997554 100644
--- a/src/rabbit_alarm.erl
+++ b/src/rabbit_alarm.erl
@@ -33,24 +33,19 @@
-behaviour(gen_event).
--export([start/1, stop/0, register/2]).
+-export([start/0, stop/0, register/2]).
-export([init/1, handle_call/2, handle_event/2, handle_info/2,
terminate/2, code_change/3]).
--define(MEMSUP_CHECK_INTERVAL, 1000).
-
-%% OSes on which we know memory alarms to be trustworthy
--define(SUPPORTED_OS, [{unix, linux}, {unix, darwin}]).
-
--record(alarms, {alertees, system_memory_high_watermark = false}).
+-record(alarms, {alertees, memory_high_watermark = false}).
%%----------------------------------------------------------------------------
-ifdef(use_specs).
-type(mfa_tuple() :: {atom(), atom(), list()}).
--spec(start/1 :: (bool() | 'auto') -> 'ok').
+-spec(start/0 :: () -> 'ok').
-spec(stop/0 :: () -> 'ok').
-spec(register/2 :: (pid(), mfa_tuple()) -> 'ok').
@@ -58,20 +53,8 @@
%%----------------------------------------------------------------------------
-start(MemoryAlarms) ->
- EnableAlarms = case MemoryAlarms of
- true -> true;
- false -> false;
- auto -> lists:member(os:type(), ?SUPPORTED_OS)
- end,
- ok = alarm_handler:add_alarm_handler(?MODULE, [EnableAlarms]),
- case whereis(memsup) of
- undefined -> if EnableAlarms -> ok = start_memsup(),
- ok = adjust_memsup_interval();
- true -> ok
- end;
- _ -> ok = adjust_memsup_interval()
- end.
+start() ->
+ ok = alarm_handler:add_alarm_handler(?MODULE, []).
stop() ->
ok = alarm_handler:delete_alarm_handler(?MODULE).
@@ -83,19 +66,13 @@ register(Pid, HighMemMFA) ->
%%----------------------------------------------------------------------------
-init([MemoryAlarms]) ->
- {ok, #alarms{alertees = case MemoryAlarms of
- true -> dict:new();
- false -> undefined
- end}}.
+init([]) ->
+ {ok, #alarms{alertees = dict:new()}}.
-handle_call({register, _Pid, _HighMemMFA},
- State = #alarms{alertees = undefined}) ->
- {ok, ok, State};
handle_call({register, Pid, HighMemMFA},
State = #alarms{alertees = Alertess}) ->
_MRef = erlang:monitor(process, Pid),
- case State#alarms.system_memory_high_watermark of
+ case State#alarms.memory_high_watermark of
true -> {M, F, A} = HighMemMFA,
ok = erlang:apply(M, F, A ++ [Pid, true]);
false -> ok
@@ -106,20 +83,17 @@ handle_call({register, Pid, HighMemMFA},
handle_call(_Request, State) ->
{ok, not_understood, State}.
-handle_event({set_alarm, {system_memory_high_watermark, []}}, State) ->
+handle_event({set_alarm, {memory_high_watermark, []}}, State) ->
ok = alert(true, State#alarms.alertees),
- {ok, State#alarms{system_memory_high_watermark = true}};
+ {ok, State#alarms{memory_high_watermark = true}};
-handle_event({clear_alarm, system_memory_high_watermark}, State) ->
+handle_event({clear_alarm, memory_high_watermark}, State) ->
ok = alert(false, State#alarms.alertees),
- {ok, State#alarms{system_memory_high_watermark = false}};
+ {ok, State#alarms{memory_high_watermark = false}};
handle_event(_Event, State) ->
{ok, State}.
-handle_info({'DOWN', _MRef, process, _Pid, _Reason},
- State = #alarms{alertees = undefined}) ->
- {ok, State};
handle_info({'DOWN', _MRef, process, Pid, _Reason},
State = #alarms{alertees = Alertess}) ->
{ok, State#alarms{alertees = dict:erase(Pid, Alertess)}};
@@ -134,57 +108,6 @@ code_change(_OldVsn, State, _Extra) ->
{ok, State}.
%%----------------------------------------------------------------------------
-
-start_memsup() ->
- {Mod, Args} =
- case os:type() of
- %% memsup doesn't take account of buffers or cache when
- %% considering "free" memory - therefore on Linux we can
- %% get memory alarms very easily without any pressure
- %% existing on memory at all. Therefore we need to use
- %% our own simple memory monitor.
- %%
- {unix, linux} -> {rabbit_memsup, [rabbit_memsup_linux]};
- {unix, darwin} -> {rabbit_memsup, [rabbit_memsup_darwin]};
-
- %% Start memsup programmatically rather than via the
- %% rabbitmq-server script. This is not quite the right
- %% thing to do as os_mon checks to see if memsup is
- %% available before starting it, but as memsup is
- %% available everywhere (even on VXWorks) it should be
- %% ok.
- %%
- %% One benefit of the programmatic startup is that we
- %% can add our alarm_handler before memsup is running,
- %% thus ensuring that we notice memory alarms that go
- %% off on startup.
- %%
- _ -> {memsup, []}
- end,
- %% This is based on os_mon:childspec(memsup, true)
- {ok, _} = supervisor:start_child(
- os_mon_sup,
- {memsup, {Mod, start_link, Args},
- permanent, 2000, worker, [Mod]}),
- ok.
-
-adjust_memsup_interval() ->
- %% The default memsup check interval is 1 minute, which is way too
- %% long - rabbit can gobble up all memory in a matter of seconds.
- %% Unfortunately the memory_check_interval configuration parameter
- %% and memsup:set_check_interval/1 function only provide a
- %% granularity of minutes. So we have to peel off one layer of the
- %% API to get to the underlying layer which operates at the
- %% granularity of milliseconds.
- %%
- %% Note that the new setting will only take effect after the first
- %% check has completed, i.e. after one minute. So if rabbit eats
- %% all the memory within the first minute after startup then we
- %% are out of luck.
- ok = os_mon:call(memsup,
- {set_check_interval, ?MEMSUP_CHECK_INTERVAL},
- infinity).
-
alert(_Alert, undefined) ->
ok;
alert(Alert, Alertees) ->
diff --git a/src/rabbit_memguard.erl b/src/rabbit_memguard.erl
new file mode 100644
index 00000000..c543876d
--- /dev/null
+++ b/src/rabbit_memguard.erl
@@ -0,0 +1,194 @@
+%% The contents of this file are subject to the Mozilla Public License
+%% Version 1.1 (the "License"); you may not use this file except in
+%% compliance with the License. You may obtain a copy of the License at
+%% http://www.mozilla.org/MPL/
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+%% License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% The Original Code is RabbitMQ.
+%%
+%% The Initial Developers of the Original Code are LShift Ltd,
+%% Cohesive Financial Technologies LLC, and Rabbit Technologies Ltd.
+%%
+%% Portions created before 22-Nov-2008 00:00:00 GMT by LShift Ltd,
+%% Cohesive Financial Technologies LLC, or Rabbit Technologies Ltd
+%% are Copyright (C) 2007-2008 LShift Ltd, Cohesive Financial
+%% Technologies LLC, and Rabbit Technologies Ltd.
+%%
+%% Portions created by LShift Ltd are Copyright (C) 2007-2009 LShift
+%% Ltd. Portions created by Cohesive Financial Technologies LLC are
+%% Copyright (C) 2007-2009 Cohesive Financial Technologies
+%% LLC. Portions created by Rabbit Technologies Ltd are Copyright
+%% (C) 2007-2009 Rabbit Technologies Ltd.
+%%
+%% All Rights Reserved.
+%%
+%% Contributor(s): ______________________________________.
+%%
+
+%% In practice erlang shouldn't be allowed to grow to more than a half
+%% of available memory. The pessimistic scenario is when erlang VM has
+%% a single erlang process that's consuming all the memory.
+%% In such case during garbage collection erlang tries to allocate
+%% huge chunk of continuous memory, which can result in a crash
+%% (likely on 32-bit machine) or heavy swapping (likely on 64-bit).
+%%
+%% This module tries to warn Rabbit before such situations happen,
+%% so that it has higher chances to prevent running out of memory.
+%%
+%% This code depends on Erlang Memsup supervisor. Setting the update interval
+%% causes a side effect of setting the interval on Memsup.
+%% This should rarely be an issue.
+
+-module(rabbit_memguard).
+
+-behaviour(gen_server2).
+
+-export([start_link/1]).
+
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
+ terminate/2, code_change/3]).
+
+-export([update/0]).
+
+
+-define(SERVER, rabbit_memguard).
+-define(DEFAULT_MEMORY_CHECK_INTERVAL, 1000).
+
+-record(state, {memory_limit,
+ timeout,
+ timer,
+ alarmed
+ }).
+
+%%----------------------------------------------------------------------------
+
+start_link(Args) ->
+ gen_server2:start_link({local, ?SERVER}, ?MODULE, [Args], []).
+
+update() ->
+ gen_server2:cast(?SERVER, update).
+
+%%----------------------------------------------------------------------------
+get_system_memory_data(Key) ->
+ dict:fetch(Key,
+ dict:from_list( memsup:get_system_memory_data() )).
+
+%% On a 32-bit machine, if you're using more than 2 gigs of RAM
+%% you're in big trouble anyway.
+get_vm_limit() ->
+ case erlang:system_info(wordsize) of
+ 4 -> 2*1024*1024*1024;
+ 8 -> infinity
+ end.
+
+
+min(A,B) ->
+ case A<B of
+ true -> A;
+ false -> B
+ end.
+
+mem_fraction_to_limit(MemFraction) ->
+ get_system_memory_data(system_total_memory) * MemFraction.
+
+mem_limit_to_fraction(MemLimit) ->
+ MemLimit / get_system_memory_data(system_total_memory).
+
+
+get_mem_limit(MemFraction) ->
+ min(mem_fraction_to_limit(MemFraction), get_vm_limit()).
+
+init([MemFraction]) ->
+ MemLimit = get_mem_limit(MemFraction),
+ rabbit_log:info("Memory alarm set to ~p.~n", [MemLimit]),
+ adjust_memsup_interval(?DEFAULT_MEMORY_CHECK_INTERVAL),
+ TRef = start_timer(?DEFAULT_MEMORY_CHECK_INTERVAL),
+ State = #state { memory_limit = MemLimit,
+ timeout = ?DEFAULT_MEMORY_CHECK_INTERVAL,
+ timer = TRef,
+ alarmed = false},
+ {ok, internal_update(State)}.
+
+start_timer(Timeout) ->
+ {ok, TRef} = timer:apply_interval(Timeout, ?MODULE, update, []),
+ TRef.
+
+handle_call(get_memory_high_watermark, _From, State) ->
+ {reply, mem_limit_to_fraction(State#state.memory_limit), State};
+
+handle_call({set_memory_high_watermark, MemFraction}, _From, State) ->
+ MemLimit = get_mem_limit(MemFraction),
+ rabbit_log:info("Memory alarm set to ~p.~n", [MemLimit]),
+ {reply, ok, State#state{memory_limit = MemLimit}};
+
+handle_call(get_check_interval, _From, State) ->
+ {reply, State#state.timeout, State};
+
+handle_call({set_check_interval, Timeout}, _From, State) ->
+ {ok, cancel} = timer:cancel(State#state.timer),
+ adjust_memsup_interval(Timeout),
+ {reply, ok, State#state{timeout = Timeout, timer = start_timer(Timeout)}};
+
+handle_call(_Request, _From, State) ->
+ {noreply, State}.
+
+handle_cast(update, State) ->
+ {noreply, internal_update(State)};
+
+handle_cast(_Request, State) ->
+ {noreply, State}.
+
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+emit_update_info(State, MemUsed, MemLimit) ->
+ {_Total, _Allocated, {_WorstPid, WorstAllocated}}
+ = memsup:get_memory_data(),
+ FreeMemory = get_system_memory_data(free_memory),
+ rabbit_log:info("memory_high_watermark ~p. Memory used:~p allowed:~p "
+ "heaviest_process:~p free:~p.~n",
+ [State, MemUsed, MemLimit, WorstAllocated, FreeMemory]).
+
+internal_update(State = #state { memory_limit = MemLimit,
+ alarmed = Alarmed}) ->
+ MemUsed = erlang:memory(total),
+ NewAlarmed = MemUsed > MemLimit,
+ case {Alarmed, NewAlarmed} of
+ {false, true} ->
+ emit_update_info(set, MemUsed, MemLimit),
+ alarm_handler:set_alarm({memory_high_watermark, []});
+ {true, false} ->
+ emit_update_info(clear, MemUsed, MemLimit),
+ alarm_handler:clear_alarm(memory_high_watermark);
+ _ ->
+ ok
+ end,
+ State #state {alarmed = NewAlarmed}.
+
+adjust_memsup_interval(IntervalMs) ->
+ %% The default memsup check interval is 1 minute, which is way too
+ %% long - rabbit can gobble up all memory in a matter of seconds.
+ %% Unfortunately the memory_check_interval configuration parameter
+ %% and memsup:set_check_interval/1 function only provide a
+ %% granularity of minutes. So we have to peel off one layer of the
+ %% API to get to the underlying layer which operates at the
+ %% granularity of milliseconds.
+ %%
+ %% Note that the new setting will only take effect after the first
+ %% check has completed, i.e. after one minute. So if rabbit eats
+ %% all the memory within the first minute after startup then we
+ %% are out of luck.
+ ok = os_mon:call(memsup,
+ {set_check_interval, IntervalMs},
+ infinity).
+
diff --git a/src/rabbit_memsup.erl b/src/rabbit_memsup.erl
deleted file mode 100644
index b0d57cb2..00000000
--- a/src/rabbit_memsup.erl
+++ /dev/null
@@ -1,142 +0,0 @@
-%% The contents of this file are subject to the Mozilla Public License
-%% Version 1.1 (the "License"); you may not use this file except in
-%% compliance with the License. You may obtain a copy of the License at
-%% http://www.mozilla.org/MPL/
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-%% License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Original Code is RabbitMQ.
-%%
-%% The Initial Developers of the Original Code are LShift Ltd,
-%% Cohesive Financial Technologies LLC, and Rabbit Technologies Ltd.
-%%
-%% Portions created before 22-Nov-2008 00:00:00 GMT by LShift Ltd,
-%% Cohesive Financial Technologies LLC, or Rabbit Technologies Ltd
-%% are Copyright (C) 2007-2008 LShift Ltd, Cohesive Financial
-%% Technologies LLC, and Rabbit Technologies Ltd.
-%%
-%% Portions created by LShift Ltd are Copyright (C) 2007-2009 LShift
-%% Ltd. Portions created by Cohesive Financial Technologies LLC are
-%% Copyright (C) 2007-2009 Cohesive Financial Technologies
-%% LLC. Portions created by Rabbit Technologies Ltd are Copyright
-%% (C) 2007-2009 Rabbit Technologies Ltd.
-%%
-%% All Rights Reserved.
-%%
-%% Contributor(s): ______________________________________.
-%%
-
--module(rabbit_memsup).
-
--behaviour(gen_server).
-
--export([start_link/1]).
-
--export([init/1, handle_call/3, handle_cast/2, handle_info/2,
- terminate/2, code_change/3]).
-
--export([update/0]).
-
--record(state, {memory_fraction,
- timeout,
- timer,
- mod,
- mod_state,
- alarmed
- }).
-
--define(SERVER, memsup). %% must be the same as the standard memsup
-
--define(DEFAULT_MEMORY_CHECK_INTERVAL, 1000).
-
-%%----------------------------------------------------------------------------
-
--ifdef(use_specs).
-
--spec(start_link/1 :: (atom()) -> {'ok', pid()} | 'ignore' | {'error', any()}).
--spec(update/0 :: () -> 'ok').
-
--endif.
-
-%%----------------------------------------------------------------------------
-
-start_link(Args) ->
- gen_server:start_link({local, ?SERVER}, ?MODULE, [Args], []).
-
-update() ->
- gen_server:cast(?SERVER, update).
-
-%%----------------------------------------------------------------------------
-
-init([Mod]) ->
- Fraction = os_mon:get_env(memsup, system_memory_high_watermark),
- TRef = start_timer(?DEFAULT_MEMORY_CHECK_INTERVAL),
- InitState = Mod:init(),
- State = #state { memory_fraction = Fraction,
- timeout = ?DEFAULT_MEMORY_CHECK_INTERVAL,
- timer = TRef,
- mod = Mod,
- mod_state = InitState,
- alarmed = false },
- {ok, internal_update(State)}.
-
-start_timer(Timeout) ->
- {ok, TRef} = timer:apply_interval(Timeout, ?MODULE, update, []),
- TRef.
-
-%% Export the same API as the real memsup. Note that
-%% get_sysmem_high_watermark gives an int in the range 0 - 100, while
-%% set_sysmem_high_watermark takes a float in the range 0.0 - 1.0.
-handle_call(get_sysmem_high_watermark, _From, State) ->
- {reply, trunc(100 * State#state.memory_fraction), State};
-
-handle_call({set_sysmem_high_watermark, Float}, _From, State) ->
- {reply, ok, State#state{memory_fraction = Float}};
-
-handle_call(get_check_interval, _From, State) ->
- {reply, State#state.timeout, State};
-
-handle_call({set_check_interval, Timeout}, _From, State) ->
- {ok, cancel} = timer:cancel(State#state.timer),
- {reply, ok, State#state{timeout = Timeout, timer = start_timer(Timeout)}};
-
-handle_call(get_memory_data, _From,
- State = #state { mod = Mod, mod_state = ModState }) ->
- {reply, Mod:get_memory_data(ModState), State};
-
-handle_call(_Request, _From, State) ->
- {noreply, State}.
-
-handle_cast(update, State) ->
- {noreply, internal_update(State)};
-
-handle_cast(_Request, State) ->
- {noreply, State}.
-
-handle_info(_Info, State) ->
- {noreply, State}.
-
-terminate(_Reason, _State) ->
- ok.
-
-code_change(_OldVsn, State, _Extra) ->
- {ok, State}.
-
-internal_update(State = #state { memory_fraction = MemoryFraction,
- alarmed = Alarmed,
- mod = Mod, mod_state = ModState }) ->
- ModState1 = Mod:update(ModState),
- {MemTotal, MemUsed, _BigProc} = Mod:get_memory_data(ModState1),
- NewAlarmed = MemUsed / MemTotal > MemoryFraction,
- case {Alarmed, NewAlarmed} of
- {false, true} ->
- alarm_handler:set_alarm({system_memory_high_watermark, []});
- {true, false} ->
- alarm_handler:clear_alarm(system_memory_high_watermark);
- _ ->
- ok
- end,
- State #state { mod_state = ModState1, alarmed = NewAlarmed }.
diff --git a/src/rabbit_memsup_darwin.erl b/src/rabbit_memsup_darwin.erl
deleted file mode 100644
index 3de2d843..00000000
--- a/src/rabbit_memsup_darwin.erl
+++ /dev/null
@@ -1,88 +0,0 @@
-%% The contents of this file are subject to the Mozilla Public License
-%% Version 1.1 (the "License"); you may not use this file except in
-%% compliance with the License. You may obtain a copy of the License at
-%% http://www.mozilla.org/MPL/
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-%% License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Original Code is RabbitMQ.
-%%
-%% The Initial Developers of the Original Code are LShift Ltd,
-%% Cohesive Financial Technologies LLC, and Rabbit Technologies Ltd.
-%%
-%% Portions created before 22-Nov-2008 00:00:00 GMT by LShift Ltd,
-%% Cohesive Financial Technologies LLC, or Rabbit Technologies Ltd
-%% are Copyright (C) 2007-2008 LShift Ltd, Cohesive Financial
-%% Technologies LLC, and Rabbit Technologies Ltd.
-%%
-%% Portions created by LShift Ltd are Copyright (C) 2007-2009 LShift
-%% Ltd. Portions created by Cohesive Financial Technologies LLC are
-%% Copyright (C) 2007-2009 Cohesive Financial Technologies
-%% LLC. Portions created by Rabbit Technologies Ltd are Copyright
-%% (C) 2007-2009 Rabbit Technologies Ltd.
-%%
-%% All Rights Reserved.
-%%
-%% Contributor(s): ______________________________________.
-%%
-
--module(rabbit_memsup_darwin).
-
--export([init/0, update/1, get_memory_data/1]).
-
--record(state, {total_memory,
- allocated_memory}).
-
-%%----------------------------------------------------------------------------
-
--ifdef(use_specs).
-
--type(state() :: #state { total_memory :: ('undefined' | non_neg_integer()),
- allocated_memory :: ('undefined' | non_neg_integer())
- }).
-
--spec(init/0 :: () -> state()).
--spec(update/1 :: (state()) -> state()).
--spec(get_memory_data/1 :: (state()) -> {non_neg_integer(), non_neg_integer(),
- ('undefined' | pid())}).
-
--endif.
-
-%%----------------------------------------------------------------------------
-
-init() ->
- #state{total_memory = undefined,
- allocated_memory = undefined}.
-
-update(State) ->
- File = os:cmd("/usr/bin/vm_stat"),
- Lines = string:tokens(File, "\n"),
- Dict = dict:from_list(lists:map(fun parse_line/1, Lines)),
- [PageSize, Inactive, Active, Free, Wired] =
- [dict:fetch(Key, Dict) ||
- Key <- [page_size, 'Pages inactive', 'Pages active', 'Pages free',
- 'Pages wired down']],
- MemTotal = PageSize * (Inactive + Active + Free + Wired),
- MemUsed = PageSize * (Active + Wired),
- State#state{total_memory = MemTotal, allocated_memory = MemUsed}.
-
-get_memory_data(State) ->
- {State#state.total_memory, State#state.allocated_memory, undefined}.
-
-%%----------------------------------------------------------------------------
-
-%% A line looks like "Foo bar: 123456."
-parse_line(Line) ->
- [Name, RHS | _Rest] = string:tokens(Line, ":"),
- case Name of
- "Mach Virtual Memory Statistics" ->
- ["(page", "size", "of", PageSize, "bytes)"] =
- string:tokens(RHS, " "),
- {page_size, list_to_integer(PageSize)};
- _ ->
- [Value | _Rest1] = string:tokens(RHS, " ."),
- {list_to_atom(Name), list_to_integer(Value)}
- end.
diff --git a/src/rabbit_memsup_linux.erl b/src/rabbit_memsup_linux.erl
deleted file mode 100644
index ca942d7c..00000000
--- a/src/rabbit_memsup_linux.erl
+++ /dev/null
@@ -1,101 +0,0 @@
-%% The contents of this file are subject to the Mozilla Public License
-%% Version 1.1 (the "License"); you may not use this file except in
-%% compliance with the License. You may obtain a copy of the License at
-%% http://www.mozilla.org/MPL/
-%%
-%% Software distributed under the License is distributed on an "AS IS"
-%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
-%% License for the specific language governing rights and limitations
-%% under the License.
-%%
-%% The Original Code is RabbitMQ.
-%%
-%% The Initial Developers of the Original Code are LShift Ltd,
-%% Cohesive Financial Technologies LLC, and Rabbit Technologies Ltd.
-%%
-%% Portions created before 22-Nov-2008 00:00:00 GMT by LShift Ltd,
-%% Cohesive Financial Technologies LLC, or Rabbit Technologies Ltd
-%% are Copyright (C) 2007-2008 LShift Ltd, Cohesive Financial
-%% Technologies LLC, and Rabbit Technologies Ltd.
-%%
-%% Portions created by LShift Ltd are Copyright (C) 2007-2009 LShift
-%% Ltd. Portions created by Cohesive Financial Technologies LLC are
-%% Copyright (C) 2007-2009 Cohesive Financial Technologies
-%% LLC. Portions created by Rabbit Technologies Ltd are Copyright
-%% (C) 2007-2009 Rabbit Technologies Ltd.
-%%
-%% All Rights Reserved.
-%%
-%% Contributor(s): ______________________________________.
-%%
-
--module(rabbit_memsup_linux).
-
--export([init/0, update/1, get_memory_data/1]).
-
--record(state, {total_memory,
- allocated_memory}).
-
-%%----------------------------------------------------------------------------
-
--ifdef(use_specs).
-
--type(state() :: #state { total_memory :: ('undefined' | non_neg_integer()),
- allocated_memory :: ('undefined' | non_neg_integer())
- }).
-
--spec(init/0 :: () -> state()).
--spec(update/1 :: (state()) -> state()).
--spec(get_memory_data/1 :: (state()) -> {non_neg_integer(), non_neg_integer(),
- ('undefined' | pid())}).
-
--endif.
-
-%%----------------------------------------------------------------------------
-
-init() ->
- #state{total_memory = undefined,
- allocated_memory = undefined}.
-
-update(State) ->
- File = read_proc_file("/proc/meminfo"),
- Lines = string:tokens(File, "\n"),
- Dict = dict:from_list(lists:map(fun parse_line/1, Lines)),
- [MemTotal, MemFree, Buffers, Cached] =
- [dict:fetch(Key, Dict) ||
- Key <- ['MemTotal', 'MemFree', 'Buffers', 'Cached']],
- MemUsed = MemTotal - MemFree - Buffers - Cached,
- State#state{total_memory = MemTotal, allocated_memory = MemUsed}.
-
-get_memory_data(State) ->
- {State#state.total_memory, State#state.allocated_memory, undefined}.
-
-%%----------------------------------------------------------------------------
-
--define(BUFFER_SIZE, 1024).
-
-%% file:read_file does not work on files in /proc as it seems to get
-%% the size of the file first and then read that many bytes. But files
-%% in /proc always have length 0, we just have to read until we get
-%% eof.
-read_proc_file(File) ->
- {ok, IoDevice} = file:open(File, [read, raw]),
- Res = read_proc_file(IoDevice, []),
- file:close(IoDevice),
- lists:flatten(lists:reverse(Res)).
-
-read_proc_file(IoDevice, Acc) ->
- case file:read(IoDevice, ?BUFFER_SIZE) of
- {ok, Res} -> read_proc_file(IoDevice, [Res | Acc]);
- eof -> Acc
- end.
-
-%% A line looks like "FooBar: 123456 kB"
-parse_line(Line) ->
- [Name, RHS | _Rest] = string:tokens(Line, ":"),
- [Value | UnitsRest] = string:tokens(RHS, " "),
- Value1 = case UnitsRest of
- [] -> list_to_integer(Value); %% no units
- ["kB"] -> list_to_integer(Value) * 1024
- end,
- {list_to_atom(Name), Value1}.