Merged default
This commit is contained in:
commit
5bf65aa0b9
|
|
@ -63,7 +63,7 @@
|
|||
-include("rabbit_framing_spec.hrl").
|
||||
|
||||
-type(maybe(T) :: T | 'none').
|
||||
-type(node() :: atom()).
|
||||
-type(erlang_node() :: atom()).
|
||||
-type(socket() :: port()).
|
||||
-type(thunk(T) :: fun(() -> T)).
|
||||
|
||||
|
|
@ -123,7 +123,7 @@
|
|||
-type(msg_id() :: non_neg_integer()).
|
||||
-type(msg() :: {queue_name(), pid(), msg_id(), bool(), message()}).
|
||||
-type(listener() ::
|
||||
#listener{node :: node(),
|
||||
#listener{node :: erlang_node(),
|
||||
protocol :: atom(),
|
||||
host :: string() | atom(),
|
||||
port :: non_neg_integer()}).
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ prepare:
|
|||
cp rabbitmq-server.logrotate SOURCES/rabbitmq-server.logrotate
|
||||
|
||||
server: prepare
|
||||
rpmbuild -ba SPECS/rabbitmq-server.spec $(DEFINES) --target noarch
|
||||
rpmbuild -ba SPECS/rabbitmq-server.spec $(DEFINES) --target i386
|
||||
rpmbuild -ba SPECS/rabbitmq-server.spec $(DEFINES) --target x86_64
|
||||
|
||||
clean:
|
||||
rm -rf SOURCES SPECS RPMS SRPMS BUILD tmp
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ BuildRequires: erlang, python-json
|
|||
%endif
|
||||
Requires: erlang, logrotate
|
||||
Packager: Hubert Plociniczak <hubert@lshift.net>
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-%{_arch}-root
|
||||
Summary: The RabbitMQ server
|
||||
Requires(post): chkconfig
|
||||
Requires(pre): chkconfig initscripts
|
||||
|
|
@ -25,11 +25,14 @@ RabbitMQ is an implementation of AMQP, the emerging standard for high
|
|||
performance enterprise messaging. The RabbitMQ server is a robust and
|
||||
scalable implementation of an AMQP broker.
|
||||
|
||||
%ifarch x86_64
|
||||
%define _erllibdir /usr/lib64/erlang/lib
|
||||
%else
|
||||
%define _erllibdir /usr/lib/erlang/lib
|
||||
%endif
|
||||
|
||||
%define _erllibdir %(erl -noshell -eval "io:format('~s~n', [code:lib_dir()]), halt().")
|
||||
%define _maindir %{buildroot}%{_erllibdir}/rabbitmq_server-%{version}
|
||||
|
||||
|
||||
%pre
|
||||
if [ $1 -gt 1 ]; then
|
||||
#Upgrade - stop and remove previous instance of rabbitmq-server init.d script
|
||||
|
|
@ -67,6 +70,8 @@ cp %{buildroot}%{_mandir}/man1/rabbitmqctl.1.gz %{buildroot}%{_mandir}/man1/rabb
|
|||
mkdir -p %{buildroot}/etc/logrotate.d
|
||||
install %SOURCE3 %{buildroot}/etc/logrotate.d/rabbitmq-server
|
||||
|
||||
rm %{_maindir}/LICENSE %{_maindir}/LICENSE-MPL-RabbitMQ %{_maindir}/INSTALL
|
||||
|
||||
%post
|
||||
# create rabbitmq group
|
||||
if ! getent group rabbitmq >/dev/null; then
|
||||
|
|
@ -110,6 +115,7 @@ fi
|
|||
/var/log/rabbitmq/
|
||||
/etc/rc.d/init.d/rabbitmq-server
|
||||
%config(noreplace) /etc/logrotate.d/rabbitmq-server
|
||||
%doc LICENSE LICENSE-MPL-RabbitMQ INSTALL
|
||||
|
||||
%clean
|
||||
rm -rf %{buildroot}
|
||||
|
|
|
|||
|
|
@ -6,16 +6,13 @@ include /usr/share/cdbs/1/class/makefile.mk
|
|||
RABBIT_LIB=$(DEB_DESTDIR)usr/lib/erlang/lib/rabbitmq_server-$(DEB_UPSTREAM_VERSION)/
|
||||
RABBIT_BIN=$(DEB_DESTDIR)usr/lib/rabbitmq/bin/
|
||||
|
||||
DEB_MAKE_INSTALL_TARGET := install TARGET_DIR=$(RABBIT_LIB) SBIN_DIR=$(RABBIT_BIN) MAN_DIR=$(DEB_DESTDIR)usr/share/man
|
||||
DEB_MAKE_INSTALL_TARGET := install TARGET_DIR=$(RABBIT_LIB) SBIN_DIR=$(RABBIT_BIN) MAN_DIR=$(DEB_DESTDIR)usr/share/man/
|
||||
|
||||
DOCDIR=$(DEB_DESTDIR)usr/share/doc/rabbitmq-server/
|
||||
|
||||
install/rabbitmq-server::
|
||||
mkdir -p $(DOCDIR)
|
||||
rm $(RABBIT_LIB)/LICENSE*
|
||||
mkdir -p $(RABBIT_BIN)
|
||||
rm $(DEB_DESTDIR)usr/share/man/man1/rabbitmq-multi.1.gz
|
||||
rm $(DEB_DESTDIR)usr/share/man/man1/rabbitmq-server.1.gz
|
||||
rm $(RABBIT_LIB)LICENSE*
|
||||
cp debian/rabbitmqctl_wrapper $(DEB_DESTDIR)usr/sbin/rabbitmqctl
|
||||
cp debian/rabbitmq-server.logrotate $(DEB_DESTDIR)etc/logrotate.d/rabbitmq-server
|
||||
chmod a+x $(DEB_DESTDIR)usr/sbin/rabbitmqctl
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ dist:
|
|||
|
||||
mkdir $(SOURCE_DIR)/sbin
|
||||
mv $(SOURCE_DIR)/scripts/rabbitmq-server.bat $(SOURCE_DIR)/sbin
|
||||
mv $(SOURCE_DIR)/scripts/rabbitmq-service.bat $(SOURCE_DIR)/sbin
|
||||
mv $(SOURCE_DIR)/scripts/rabbitmqctl.bat $(SOURCE_DIR)/sbin
|
||||
mv $(SOURCE_DIR)/scripts/rabbitmq-multi.bat $(SOURCE_DIR)/sbin
|
||||
rm -rf $(SOURCE_DIR)/scripts
|
||||
|
|
@ -18,6 +19,8 @@ dist:
|
|||
rm -rf $(SOURCE_DIR)/docs
|
||||
|
||||
mv $(SOURCE_DIR) $(TARGET_DIR)
|
||||
pod2text --loose rabbitmq-service.pod $(TARGET_DIR)/readme-service.txt
|
||||
unix2dos $(TARGET_DIR)/readme-service.txt
|
||||
zip -r $(TARGET_ZIP).zip $(TARGET_DIR)
|
||||
rm -rf $(TARGET_DIR)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,138 @@
|
|||
=head1 NAME
|
||||
|
||||
rabbitmq-service - manage RabbitMQ AMQP service
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
rabbitmq-service.bat command
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
RabbitMQ is an implementation of AMQP, the emerging standard for high
|
||||
performance enterprise messaging. The RabbitMQ server is a robust and
|
||||
scalable implementation of an AMQP broker.
|
||||
|
||||
Running B<rabbitmq-service> allows the RabbitMQ broker to be run as a
|
||||
service on NT/2000/2003/XP/Vista® environments. The RabbitMQ broker
|
||||
service can be started and stopped using the Windows® services
|
||||
applet.
|
||||
|
||||
By default the service will run in the authentication context of the
|
||||
local system account. It is therefore necessary to synchronise Erlang
|
||||
cookies between the local system account (typically
|
||||
C<C:\WINDOWS\.erlang.cookie> and the account that will be used to
|
||||
run B<rabbitmqctl>.
|
||||
|
||||
=head1 COMMANDS
|
||||
|
||||
=head2 help
|
||||
|
||||
Display usage information.
|
||||
|
||||
=head2 install
|
||||
|
||||
Install the service. The service will not be started.
|
||||
Subsequent invocations will update the service parameters if
|
||||
relevant environment variables were modified.
|
||||
|
||||
=head2 remove
|
||||
|
||||
Remove the service. If the service is running then it will
|
||||
automatically be stopped before being removed. No files will be
|
||||
deleted as a consequence and B<rabbitmq-server> will remain operable.
|
||||
|
||||
=head2 start
|
||||
|
||||
Start the service. The service must have been correctly installed
|
||||
beforehand.
|
||||
|
||||
=head2 stop
|
||||
|
||||
Stop the service. The service must be running for this command to
|
||||
have any effect.
|
||||
|
||||
=head2 disable
|
||||
|
||||
Disable the service. This is the equivalent of setting the startup
|
||||
type to B<Disabled> using the service control panel.
|
||||
|
||||
=head2 enable
|
||||
|
||||
Enable the service. This is the equivalent of setting the startup
|
||||
type to B<Automatic> using the service control panel.
|
||||
|
||||
=head1 ENVIRONMENT
|
||||
|
||||
=head2 SERVICENAME
|
||||
|
||||
Defaults to RabbitMQ.
|
||||
This is the location of log and database directories.
|
||||
|
||||
=head2 RABBITMQ_BASE
|
||||
|
||||
Defaults to the application data directory of the current user.
|
||||
This is the location of log and database directories.
|
||||
|
||||
=head2 NODENAME
|
||||
|
||||
Defaults to "rabbit". This can be useful if you want to run more
|
||||
than one node per machine - B<NODENAME> should be unique per
|
||||
erlang-node-and-machine combination. See clustering on a single
|
||||
machine guide
|
||||
at L<http://www.rabbitmq.com/clustering.html#single-machine> for
|
||||
details.
|
||||
|
||||
=head2 NODE_IP_ADDRESS
|
||||
|
||||
Defaults to "0.0.0.0". This can be changed if you only want to bind
|
||||
to one network interface.
|
||||
|
||||
=head2 NODE_PORT
|
||||
|
||||
Defaults to 5672.
|
||||
|
||||
=head2 ERLANG_SERVICE_MANAGER_PATH
|
||||
|
||||
Defaults to F<C:\Program Files\erl5.5.5\erts-5.5.5\bin>. This is
|
||||
the installation location of the Erlang service manager.
|
||||
|
||||
=head2 CLUSTER_CONFIG_FILE
|
||||
|
||||
If this file is present it is used by the server to
|
||||
auto-configure a RabbitMQ cluster. See the clustering guide
|
||||
at L<http://www.rabbitmq.com/clustering.html> for details.
|
||||
|
||||
=head2 CONSOLE_LOG
|
||||
|
||||
Set this varable to B<new> or B<reuse> to have the console
|
||||
output from the server redirected to a file named B<SERVICENAME>.debug
|
||||
in the application data directory of the user that installed the service.
|
||||
Under Vista this will be F<C:\Documents and Settings\User\AppData\username\SERVICENAME>.
|
||||
Under previous versions of Windows this will be
|
||||
F<C:\Documents and Settings\username\Application Data\SERVICENAME>.
|
||||
If B<CONSOLE_LOG> is set to B<new> then a new file will be created
|
||||
each time the service starts. If B<CONSOLE_LOG> is set to B<reuse>
|
||||
then the file will be overwritten each time the service starts.
|
||||
The default behaviour when B<CONSOLE_LOG> is not set or set to a
|
||||
value other than B<new> or B<reuse> is to discard the server output.
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
Start a previously-installed RabbitMQ AMQP service:
|
||||
|
||||
rabbitmq-service start
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Originally written by The RabbitMQ Team <info@lshift.net>
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
This package, the RabbitMQ server is licensed under the MPL.
|
||||
|
||||
If you have any questions regarding licensing, please contact us at
|
||||
info@rabbitmq.com.
|
||||
|
||||
=head1 REFERENCES
|
||||
|
||||
RabbitMQ Web Site: http://www.rabbitmq.com
|
||||
|
|
@ -66,7 +66,7 @@ exec erl \
|
|||
-sasl sasl_error_logger '{file,"'${SASL_LOGS}'"}' \
|
||||
-os_mon start_cpu_sup true \
|
||||
-os_mon start_disksup false \
|
||||
-os_mon start_memsup true \
|
||||
-os_mon start_memsup false \
|
||||
-os_mon start_os_sup false \
|
||||
-os_mon memsup_system_only true \
|
||||
-os_mon system_memory_high_watermark 0.95 \
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ set MNESIA_DIR=%MNESIA_BASE%/%NODENAME%-mnesia
|
|||
-sasl sasl_error_logger {file,\""%LOG_BASE%/%NODENAME%-sasl.log"\"} ^
|
||||
-os_mon start_cpu_sup true ^
|
||||
-os_mon start_disksup false ^
|
||||
-os_mon start_memsup true ^
|
||||
-os_mon start_memsup false ^
|
||||
-os_mon start_os_sup false ^
|
||||
-os_mon memsup_system_only true ^
|
||||
-os_mon system_memory_high_watermark 0.95 ^
|
||||
|
|
|
|||
|
|
@ -0,0 +1,189 @@
|
|||
@echo off
|
||||
REM The contents of this file are subject to the Mozilla Public License
|
||||
REM Version 1.1 (the "License"); you may not use this file except in
|
||||
REM compliance with the License. You may obtain a copy of the License at
|
||||
REM http://www.mozilla.org/MPL/
|
||||
REM
|
||||
REM Software distributed under the License is distributed on an "AS IS"
|
||||
REM basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
REM License for the specific language governing rights and limitations
|
||||
REM under the License.
|
||||
REM
|
||||
REM The Original Code is RabbitMQ.
|
||||
REM
|
||||
REM The Initial Developers of the Original Code are LShift Ltd.,
|
||||
REM Cohesive Financial Technologies LLC., and Rabbit Technologies Ltd.
|
||||
REM
|
||||
REM Portions created by LShift Ltd., Cohesive Financial Technologies
|
||||
REM LLC., and Rabbit Technologies Ltd. are Copyright (C) 2007-2008
|
||||
REM LShift Ltd., Cohesive Financial Technologies LLC., and Rabbit
|
||||
REM Technologies Ltd.;
|
||||
REM
|
||||
REM All Rights Reserved.
|
||||
REM
|
||||
REM Contributor(s): ______________________________________.
|
||||
REM
|
||||
|
||||
if "%SERVICENAME%"=="" (
|
||||
set SERVICENAME=RabbitMQ
|
||||
)
|
||||
|
||||
if "%RABBITMQ_BASE%"=="" (
|
||||
set RABBITMQ_BASE=%APPDATA%\%SERVICENAME%
|
||||
)
|
||||
|
||||
if "%NODENAME%"=="" (
|
||||
set NODENAME=rabbit
|
||||
)
|
||||
|
||||
if "%NODE_IP_ADDRESS%"=="" (
|
||||
set NODE_IP_ADDRESS=0.0.0.0
|
||||
)
|
||||
|
||||
if "%NODE_PORT%"=="" (
|
||||
set NODE_PORT=5672
|
||||
)
|
||||
|
||||
if "%ERLANG_SERVICE_MANAGER_PATH%"=="" (
|
||||
set ERLANG_SERVICE_MANAGER_PATH=C:\Program Files\erl5.5.5\erts-5.5.5\bin
|
||||
)
|
||||
|
||||
set CONSOLE_FLAG=
|
||||
set CONSOLE_LOG_VALID=
|
||||
for %%i in (new reuse) do if "%%i" == "%CONSOLE_LOG%" set CONSOLE_LOG_VALID=TRUE
|
||||
if "%CONSOLE_LOG_VALID%" == "TRUE" (
|
||||
set CONSOLE_FLAG=-debugtype %CONSOLE_LOG%
|
||||
)
|
||||
|
||||
rem *** End of configuration ***
|
||||
|
||||
if not exist "%ERLANG_SERVICE_MANAGER_PATH%\erlsrv.exe" (
|
||||
echo.
|
||||
echo **********************************************
|
||||
echo ERLANG_SERVICE_MANAGER_PATH not set correctly.
|
||||
echo **********************************************
|
||||
echo.
|
||||
echo %ERLANG_SERVICE_MANAGER_PATH%\erlsrv.exe not found!
|
||||
echo Please set ERLANG_SERVICE_MANAGER_PATH to the folder containing "erlsrv.exe".
|
||||
echo.
|
||||
exit /B 1
|
||||
)
|
||||
|
||||
rem erlang prefers forwardslash as separator in paths
|
||||
set RABBITMQ_BASE_UNIX=%RABBITMQ_BASE:\=/%
|
||||
set MNESIA_BASE=%RABBITMQ_BASE_UNIX%/db
|
||||
set LOG_BASE=%RABBITMQ_BASE_UNIX%/log
|
||||
|
||||
|
||||
rem We save the previous logs in their respective backup
|
||||
rem Log management (rotation, filtering based on size...) is left as an exercise for the user.
|
||||
|
||||
set BACKUP_EXTENSION=.1
|
||||
|
||||
set LOGS="%RABBITMQ_BASE%\log\%NODENAME%.log"
|
||||
set SASL_LOGS="%RABBITMQ_BASE%\log\%NODENAME%-sasl.log"
|
||||
|
||||
set LOGS_BACKUP="%RABBITMQ_BASE%\log\%NODENAME%.log%BACKUP_EXTENSION%"
|
||||
set SASL_LOGS_BACKUP="%RABBITMQ_BASE%\log\%NODENAME%-sasl.log%BACKUP_EXTENSION%"
|
||||
|
||||
if exist %LOGS% (
|
||||
type %LOGS% >> %LOGS_BACKUP%
|
||||
)
|
||||
if exist %SASL_LOGS% (
|
||||
type %SASL_LOGS% >> %SASL_LOGS_BACKUP%
|
||||
)
|
||||
|
||||
rem End of log management
|
||||
|
||||
|
||||
set CLUSTER_CONFIG_FILE=%RABBITMQ_BASE%\rabbitmq_cluster.config
|
||||
set CLUSTER_CONFIG=
|
||||
if not exist "%CLUSTER_CONFIG_FILE%" GOTO L1
|
||||
set CLUSTER_CONFIG=-rabbit cluster_config \""%CLUSTER_CONFIG_FILE:\=/%"\"
|
||||
:L1
|
||||
|
||||
set MNESIA_DIR=%MNESIA_BASE%/%NODENAME%-mnesia
|
||||
|
||||
|
||||
if "%1" == "install" goto INSTALL_SERVICE
|
||||
for %%i in (start stop disable enable list remove) do if "%%i" == "%1" goto MODIFY_SERVICE
|
||||
|
||||
echo.
|
||||
echo *********************
|
||||
echo Service control usage
|
||||
echo *********************
|
||||
echo.
|
||||
echo %~n0 help - Display this help
|
||||
echo %~n0 install - Install the %SERVICENAME% service
|
||||
echo %~n0 remove - Remove the %SERVICENAME% service
|
||||
echo.
|
||||
echo The following actions can also be accomplished by using
|
||||
echo Windows Services Management Console (services.msc):
|
||||
echo.
|
||||
echo %~n0 start - Start the %SERVICENAME% service
|
||||
echo %~n0 stop - Stop the %SERVICENAME% service
|
||||
echo %~n0 disable - Disable the %SERVICENAME% service
|
||||
echo %~n0 enable - Enable the %SERVICENAME% service
|
||||
echo.
|
||||
exit /B
|
||||
|
||||
|
||||
:INSTALL_SERVICE
|
||||
|
||||
if not exist "%RABBITMQ_BASE%" (
|
||||
echo Creating base directory %RABBITMQ_BASE% & md "%RABBITMQ_BASE%"
|
||||
)
|
||||
|
||||
"%ERLANG_SERVICE_MANAGER_PATH%\erlsrv" list %SERVICENAME% 2>NUL 1>NUL
|
||||
if errorlevel 1 (
|
||||
"%ERLANG_SERVICE_MANAGER_PATH%\erlsrv" add %SERVICENAME%
|
||||
) else (
|
||||
echo %SERVICENAME% service is already present - only updating service parameters
|
||||
)
|
||||
|
||||
set RABBIT_EBIN=%~dp0..\ebin
|
||||
|
||||
set ERLANG_SERVICE_ARGUMENTS= ^
|
||||
-pa "%RABBIT_EBIN%" ^
|
||||
-boot start_sasl ^
|
||||
-s rabbit ^
|
||||
+W w ^
|
||||
+A30 ^
|
||||
-kernel inet_default_listen_options "[{nodelay,true},{sndbuf,16384},{recbuf,4096}]" ^
|
||||
-kernel inet_default_connect_options "[{nodelay,true}]" ^
|
||||
-rabbit tcp_listeners "[{\"%NODE_IP_ADDRESS%\",%NODE_PORT%}]" ^
|
||||
-kernel error_logger {file,\""%LOG_BASE%/%NODENAME%.log"\"} ^
|
||||
-sasl errlog_type error ^
|
||||
-sasl sasl_error_logger {file,\""%LOG_BASE%/%NODENAME%-sasl.log"\"} ^
|
||||
-os_mon start_cpu_sup true ^
|
||||
-os_mon start_disksup 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 ^
|
||||
-mnesia dir \""%MNESIA_DIR%"\" ^
|
||||
%CLUSTER_CONFIG% ^
|
||||
%RABBIT_ARGS% ^
|
||||
%*
|
||||
|
||||
set ERLANG_SERVICE_ARGUMENTS=%ERLANG_SERVICE_ARGUMENTS:\=\\%
|
||||
set ERLANG_SERVICE_ARGUMENTS=%ERLANG_SERVICE_ARGUMENTS:"=\"%
|
||||
|
||||
"%ERLANG_SERVICE_MANAGER_PATH%\erlsrv" set %SERVICENAME% ^
|
||||
-machine "%ERLANG_SERVICE_MANAGER_PATH%\erl.exe" ^
|
||||
-env ERL_CRASH_DUMP="%RABBITMQ_BASE_UNIX%/log" ^
|
||||
-workdir "%RABBITMQ_BASE%" ^
|
||||
-stopaction "rabbit:stop_and_halt()." ^
|
||||
-sname %NODENAME% ^
|
||||
%CONSOLE_FLAG% ^
|
||||
-args "%ERLANG_SERVICE_ARGUMENTS%" > NUL
|
||||
goto END
|
||||
|
||||
|
||||
:MODIFY_SERVICE
|
||||
|
||||
"%ERLANG_SERVICE_MANAGER_PATH%\erlsrv" %1 %SERVICENAME%
|
||||
goto END
|
||||
|
||||
|
||||
:END
|
||||
|
|
@ -57,8 +57,8 @@
|
|||
-spec(rotate_logs/1 :: (file_suffix()) -> 'ok' | {'error', any()}).
|
||||
-spec(status/0 :: () ->
|
||||
[{running_applications, [{atom(), string(), string()}]} |
|
||||
{nodes, [node()]} |
|
||||
{running_nodes, [node()]}]).
|
||||
{nodes, [erlang_node()]} |
|
||||
{running_nodes, [erlang_node()]}]).
|
||||
-spec(log_location/1 :: ('sasl' | 'kernel') -> log_location()).
|
||||
|
||||
-endif.
|
||||
|
|
|
|||
|
|
@ -50,22 +50,57 @@
|
|||
%%----------------------------------------------------------------------------
|
||||
|
||||
start() ->
|
||||
ok = alarm_handler:add_alarm_handler(?MODULE),
|
||||
case whereis(memsup) of
|
||||
undefined ->
|
||||
Mod = 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_linux;
|
||||
|
||||
%% 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, []},
|
||||
permanent, 2000, worker, [Mod]}),
|
||||
ok;
|
||||
_ ->
|
||||
ok
|
||||
end,
|
||||
%% 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
|
||||
%% 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),
|
||||
|
||||
ok = alarm_handler:add_alarm_handler(?MODULE).
|
||||
ok = os_mon:call(memsup,
|
||||
{set_check_interval, ?MEMSUP_CHECK_INTERVAL},
|
||||
infinity).
|
||||
|
||||
stop() ->
|
||||
ok = alarm_handler:delete_alarm_handler(?MODULE).
|
||||
|
|
@ -77,9 +112,7 @@ register(Pid, HighMemMFA) ->
|
|||
%%----------------------------------------------------------------------------
|
||||
|
||||
init([]) ->
|
||||
HWM = system_memory_high_watermark(),
|
||||
{ok, #alarms{alertees = dict:new(),
|
||||
system_memory_high_watermark = HWM}}.
|
||||
{ok, #alarms{alertees = dict:new()}}.
|
||||
|
||||
handle_call({register, Pid, HighMemMFA},
|
||||
State = #alarms{alertees = Alertess}) ->
|
||||
|
|
@ -121,19 +154,6 @@ code_change(_OldVsn, State, _Extra) ->
|
|||
|
||||
%%----------------------------------------------------------------------------
|
||||
|
||||
system_memory_high_watermark() ->
|
||||
%% When we register our alarm_handler, the
|
||||
%% system_memory_high_watermark alarm may already have gone
|
||||
%% off. How do we find out about that? Calling
|
||||
%% alarm_handler:get_alarms() would deadlock. So instead we ask
|
||||
%% memsup. Unfortunately that doesn't expose a suitable API, so we
|
||||
%% have to reach quite deeply into its internals.
|
||||
{dictionary, D} = process_info(whereis(memsup), dictionary),
|
||||
case lists:keysearch(system_memory_high_watermark, 1, D) of
|
||||
{value, {_, set}} -> true;
|
||||
_Other -> false
|
||||
end.
|
||||
|
||||
alert(Alert, Alertees) ->
|
||||
dict:fold(fun (Pid, {M, F, A}, Acc) ->
|
||||
ok = erlang:apply(M, F, A ++ [Pid, Alert]),
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@
|
|||
-spec(basic_cancel/4 :: (amqqueue(), pid(), ctag(), any()) -> 'ok').
|
||||
-spec(notify_sent/2 :: (pid(), pid()) -> 'ok').
|
||||
-spec(internal_delete/1 :: (queue_name()) -> 'ok' | not_found()).
|
||||
-spec(on_node_down/1 :: (node()) -> 'ok').
|
||||
-spec(on_node_down/1 :: (erlang_node()) -> 'ok').
|
||||
-spec(pseudo_queue/2 :: (binary(), pid()) -> amqqueue()).
|
||||
|
||||
-endif.
|
||||
|
|
|
|||
|
|
@ -34,11 +34,11 @@
|
|||
|
||||
-ifdef(use_specs).
|
||||
|
||||
-type(node() :: atom()).
|
||||
-type(load() :: {{non_neg_integer(), float()}, node()}).
|
||||
-type(erlang_node() :: atom()).
|
||||
-type(load() :: {{non_neg_integer(), float()}, erlang_node()}).
|
||||
-spec(local_load/0 :: () -> load()).
|
||||
-spec(remote_loads/0 :: () -> [load()]).
|
||||
-spec(pick/0 :: () -> node()).
|
||||
-spec(pick/0 :: () -> erlang_node()).
|
||||
|
||||
-endif.
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||
terminate/2, code_change/3]).
|
||||
|
||||
-export([debug/1, debug/2, info/1, info/2,
|
||||
-export([debug/1, debug/2, message/4, info/1, info/2,
|
||||
warning/1, warning/2, error/1, error/2]).
|
||||
|
||||
-import(io).
|
||||
|
|
@ -67,6 +67,10 @@ debug(Fmt) ->
|
|||
debug(Fmt, Args) when is_list(Args) ->
|
||||
gen_server:cast(?SERVER, {debug, Fmt, Args}).
|
||||
|
||||
message(Direction, Channel, MethodRecord, Content) ->
|
||||
gen_server:cast(?SERVER,
|
||||
{message, Direction, Channel, MethodRecord, Content}).
|
||||
|
||||
info(Fmt) ->
|
||||
gen_server:cast(?SERVER, {info, Fmt}).
|
||||
|
||||
|
|
@ -100,6 +104,14 @@ handle_cast({debug, Fmt, Args}, State) ->
|
|||
io:format("debug:: "), io:format(Fmt, Args),
|
||||
error_logger:info_msg("debug:: " ++ Fmt, Args),
|
||||
{noreply, State};
|
||||
handle_cast({message, Direction, Channel, MethodRecord, Content}, State) ->
|
||||
io:format("~s ch~p ~p~n",
|
||||
[case Direction of
|
||||
in -> "-->";
|
||||
out -> "<--" end,
|
||||
Channel,
|
||||
{MethodRecord, Content}]),
|
||||
{noreply, State};
|
||||
handle_cast({info, Fmt}, State) ->
|
||||
error_logger:info_msg(Fmt),
|
||||
{noreply, State};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,150 @@
|
|||
%% 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 by LShift Ltd., Cohesive Financial Technologies
|
||||
%% LLC., and Rabbit Technologies Ltd. are Copyright (C) 2007-2008
|
||||
%% LShift Ltd., Cohesive Financial Technologies LLC., and Rabbit
|
||||
%% Technologies Ltd.;
|
||||
%%
|
||||
%% All Rights Reserved.
|
||||
%%
|
||||
%% Contributor(s): ______________________________________.
|
||||
%%
|
||||
|
||||
-module(rabbit_memsup_linux).
|
||||
|
||||
-behaviour(gen_server).
|
||||
|
||||
-export([start_link/0]).
|
||||
|
||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||
terminate/2, code_change/3]).
|
||||
|
||||
-export([update/0]).
|
||||
|
||||
-define(SERVER, memsup). %% must be the same as the standard memsup
|
||||
|
||||
-define(DEFAULT_MEMORY_CHECK_INTERVAL, 1000).
|
||||
|
||||
-record(state, {memory_fraction, alarmed, timeout, timer}).
|
||||
|
||||
%%----------------------------------------------------------------------------
|
||||
|
||||
-ifdef(use_specs).
|
||||
|
||||
-spec(start_link/0 :: () -> {'ok', pid()} | 'ignore' | {'error', any()}).
|
||||
-spec(update/0 :: () -> 'ok').
|
||||
|
||||
-endif.
|
||||
|
||||
%%----------------------------------------------------------------------------
|
||||
|
||||
start_link() ->
|
||||
gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
|
||||
|
||||
|
||||
update() ->
|
||||
gen_server:cast(?SERVER, update).
|
||||
|
||||
%%----------------------------------------------------------------------------
|
||||
|
||||
init(_Args) ->
|
||||
Fraction = os_mon:get_env(memsup, system_memory_high_watermark),
|
||||
TRef = start_timer(?DEFAULT_MEMORY_CHECK_INTERVAL),
|
||||
{ok, #state{alarmed = false,
|
||||
memory_fraction = Fraction,
|
||||
timeout = ?DEFAULT_MEMORY_CHECK_INTERVAL,
|
||||
timer = TRef}}.
|
||||
|
||||
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(_Request, _From, State) ->
|
||||
{noreply, State}.
|
||||
|
||||
handle_cast(update, State = #state{alarmed = Alarmed,
|
||||
memory_fraction = MemoryFraction}) ->
|
||||
File = read_proc_file("/proc/meminfo"),
|
||||
Lines = string:tokens(File, "\n"),
|
||||
Dict = dict:from_list(lists:map(fun parse_line/1, Lines)),
|
||||
MemTotal = dict:fetch('MemTotal', Dict),
|
||||
MemUsed = MemTotal
|
||||
- dict:fetch('MemFree', Dict)
|
||||
- dict:fetch('Buffers', Dict)
|
||||
- dict:fetch('Cached', Dict),
|
||||
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,
|
||||
{noreply, State#state{alarmed = NewAlarmed}};
|
||||
|
||||
handle_cast(_Request, State) ->
|
||||
{noreply, State}.
|
||||
|
||||
handle_info(_Info, State) ->
|
||||
{noreply, State}.
|
||||
|
||||
terminate(_Reason, _State) ->
|
||||
ok.
|
||||
|
||||
code_change(_OldVsn, State, _Extra) ->
|
||||
{ok, State}.
|
||||
|
||||
%%----------------------------------------------------------------------------
|
||||
|
||||
-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, Value | _] = string:tokens(Line, ": "),
|
||||
{list_to_atom(Name), list_to_integer(Value)}.
|
||||
|
|
@ -85,7 +85,7 @@
|
|||
-spec(with_user_and_vhost/3 :: (username(), vhost(), thunk(A)) -> A).
|
||||
-spec(execute_mnesia_transaction/1 :: (thunk(A)) -> A).
|
||||
-spec(ensure_ok/2 :: ('ok' | {'error', any()}, atom()) -> 'ok').
|
||||
-spec(localnode/1 :: (atom()) -> node()).
|
||||
-spec(localnode/1 :: (atom()) -> erlang_node()).
|
||||
-spec(tcp_name/3 :: (atom(), ip_address(), ip_port()) -> atom()).
|
||||
-spec(intersperse/2 :: (A, [A]) -> [A]).
|
||||
-spec(upmap/2 :: (fun ((A) -> B), [A]) -> [B]).
|
||||
|
|
|
|||
|
|
@ -43,11 +43,11 @@
|
|||
|
||||
-ifdef(use_specs).
|
||||
|
||||
-spec(status/0 :: () -> [{'nodes' | 'running_nodes', [node()]}]).
|
||||
-spec(status/0 :: () -> [{'nodes' | 'running_nodes', [erlang_node()]}]).
|
||||
-spec(ensure_mnesia_dir/0 :: () -> 'ok').
|
||||
-spec(init/0 :: () -> 'ok').
|
||||
-spec(is_db_empty/0 :: () -> bool()).
|
||||
-spec(cluster/1 :: ([node()]) -> 'ok').
|
||||
-spec(cluster/1 :: ([erlang_node()]) -> 'ok').
|
||||
-spec(reset/0 :: () -> 'ok').
|
||||
-spec(force_reset/0 :: () -> 'ok').
|
||||
-spec(create_tables/0 :: () -> 'ok').
|
||||
|
|
|
|||
|
|
@ -45,8 +45,8 @@
|
|||
-spec(start_tcp_listener/2 :: (host(), ip_port()) -> 'ok').
|
||||
-spec(stop_tcp_listener/2 :: (host(), ip_port()) -> 'ok').
|
||||
-spec(active_listeners/0 :: () -> [listener()]).
|
||||
-spec(node_listeners/1 :: (node()) -> [listener()]).
|
||||
-spec(on_node_down/1 :: (node()) -> 'ok').
|
||||
-spec(node_listeners/1 :: (erlang_node()) -> [listener()]).
|
||||
-spec(on_node_down/1 :: (erlang_node()) -> 'ok').
|
||||
-spec(check_tcp_listener_address/3 :: (atom(), host(), ip_port()) ->
|
||||
{ip_address(), atom()}).
|
||||
|
||||
|
|
|
|||
|
|
@ -71,8 +71,9 @@ handle_call(Event, State) ->
|
|||
terminate(Reason, State) ->
|
||||
sasl_report_file_h:terminate(Reason, State).
|
||||
|
||||
code_change(OldVsn, State, Extra) ->
|
||||
sasl_report_file_h:code_change(OldVsn, State, Extra).
|
||||
code_change(_OldVsn, State, _Extra) ->
|
||||
%% There is no sasl_report_file_h:code_change/3
|
||||
{ok, State}.
|
||||
|
||||
%%----------------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue