--- /dev/null
+Description: Autotune erlang thread pool size
+ Useful for hosts with big number of CPU cores
+Origin: upstream, https://github.com/binarin/rabbitmq-server/tree/rabbitmq-server-151
+Bug: https://github.com/binarin/rabbitmq-server/tree/rabbitmq-server-151
+Applied-Upstream: 3.6.2
+---
+This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
+--- a/deps/rabbit_common/src/rabbit_misc.erl
++++ b/deps/rabbit_common/src/rabbit_misc.erl
+@@ -73,6 +73,7 @@
+ -export([get_env/3]).
+ -export([get_channel_operation_timeout/0]).
+ -export([random/1]).
++-export([report_default_thread_pool_size/0]).
+
+ %% Horrible macro to use in guards
+ -define(IS_BENIGN_EXIT(R),
+@@ -263,6 +264,7 @@
+ -spec(get_env/3 :: (atom(), atom(), term()) -> term()).
+ -spec(get_channel_operation_timeout/0 :: () -> non_neg_integer()).
+ -spec(random/1 :: (non_neg_integer()) -> non_neg_integer()).
++-spec(report_default_thread_pool_size/0 :: () -> 'ok').
+
+ -endif.
+
+@@ -1160,6 +1162,24 @@ random(N) ->
+ end,
+ random:uniform(N).
+
++guess_number_of_cpu_cores() ->
++ case erlang:system_info(logical_processors_available) of
++ unknown -> % Happens on Mac OS X.
++ erlang:system_info(schedulers);
++ N -> N
++ end.
++
++%% Discussion of choosen values is at
++%% https://github.com/rabbitmq/rabbitmq-server/issues/151
++guess_default_thread_pool_size() ->
++ PoolSize = 16 * guess_number_of_cpu_cores(),
++ min(1024, max(64, PoolSize)).
++
++report_default_thread_pool_size() ->
++ io:format("~b", [guess_default_thread_pool_size()]),
++ erlang:halt(0),
++ ok.
++
+ %% -------------------------------------------------------------------------
+ %% Begin copypasta from gen_server2.erl
+
+--- a/scripts/rabbitmq-defaults
++++ b/scripts/rabbitmq-defaults
+@@ -40,6 +40,5 @@ MNESIA_BASE=${SYS_PREFIX}/var/lib/rabbit
+ ENABLED_PLUGINS_FILE=${SYS_PREFIX}/etc/rabbitmq/enabled_plugins
+
+ PLUGINS_DIR="${RABBITMQ_HOME}/plugins"
+-IO_THREAD_POOL_SIZE=64
+
+ CONF_ENV_FILE=${SYS_PREFIX}/etc/rabbitmq/rabbitmq-env.conf
+--- a/scripts/rabbitmq-server
++++ b/scripts/rabbitmq-server
+@@ -117,7 +117,23 @@ fi
+ # there is no other way of preventing their expansion.
+ set -f
+
++# Lazy initialization of threed pool size - if it wasn't set
++# explicitly. This parameter is only needed when server is starting,
++# so it makes no sense to do this calculations in rabbitmq-env or
++# rabbitmq-defaults scripts.
++ensure_thread_pool_size() {
++ if [ -z "${RABBITMQ_IO_THREAD_POOL_SIZE}" ]; then
++ RABBITMQ_IO_THREAD_POOL_SIZE=$(
++ ${ERL_DIR}erl -pa "$RABBITMQ_EBIN_ROOT" \
++ -boot "${CLEAN_BOOT_FILE}" \
++ -noinput \
++ -s rabbit_misc report_default_thread_pool_size
++ )
++ fi
++}
++
+ start_rabbitmq_server() {
++ ensure_thread_pool_size
+ RABBITMQ_CONFIG_FILE=$RABBITMQ_CONFIG_FILE \
+ exec ${ERL_DIR}erl \
+ -pa /var/lib/rabbitmq/native-code \
--- /dev/null
+Только в rabbitmq-server-3.6.1/docs: rabbitmq-server.service.example
+--- a/scripts/rabbitmq-server
++++ b/scripts/rabbitmq-server
+@@ -47,7 +47,7 @@ case "$(uname -s)" in
+ exit $EX_CANTCREAT
+ fi
+ if ! echo $$ > ${RABBITMQ_PID_FILE}; then
+- # Bettern diagnostics - otherwise the only report in logs is about failed 'echo'
++ # Better diagnostics - otherwise the only report in logs is about failed 'echo'
+ # command, but without any other details: neither what script has failed nor what
+ # file output was redirected to.
+ echo "Failed to write pid file: ${RABBITMQ_PID_FILE}"
+@@ -58,8 +58,13 @@ esac
+
+ RABBITMQ_EBIN_ROOT="${RABBITMQ_HOME}/ebin"
+
++[ "$NOTIFY_SOCKET" ] && RUNNING_UNDER_SYSTEMD=true
++
+ set +e
+
++# NOTIFY_SOCKET is needed here to prevent epmd from impersonating the
++# success of our startup sequence to systemd.
++NOTIFY_SOCKET= \
+ RABBITMQ_CONFIG_FILE=$RABBITMQ_CONFIG_FILE \
+ RABBITMQ_DIST_PORT=$RABBITMQ_DIST_PORT \
+ ${ERL_DIR}erl -pa "$RABBITMQ_EBIN_ROOT" \
+@@ -152,7 +157,20 @@ stop_rabbitmq_server() {
+ fi
+ }
+
+-if [ 'x' = "x$RABBITMQ_ALLOW_INPUT" -a -z "$detached" ]; then
++if [ "$RABBITMQ_ALLOW_INPUT" -o "$RUNNING_UNDER_SYSTEMD" -o "$detached" ]; then
++ # Run erlang VM directly, completely replacing current shell
++ # process - so the pid file written in the code above will be
++ # valid (unless detached, which is also handled in the code
++ # above).
++ #
++ # And also this is the correct mode to run the broker under
++ # systemd - there is no need in a proxy process that converts
++ # signals to graceful shutdown command, the unit file should already
++ # contain instructions for graceful shutdown. Also by removing
++ # this additional process we could simply use value returned by
++ # `os:getpid/0` for a systemd ready notification.
++ start_rabbitmq_server "$@"
++else
+ # When RabbitMQ runs in the foreground but the Erlang shell is
+ # disabled, we setup signal handlers to stop RabbitMQ properly. This
+ # is at least useful in the case of Docker.
+@@ -161,7 +179,7 @@ if [ 'x' = "x$RABBITMQ_ALLOW_INPUT" -a -
+ RABBITMQ_SERVER_START_ARGS="${RABBITMQ_SERVER_START_ARGS} +B i"
+
+ # Signal handlers. They all stop RabbitMQ properly (using
+- # rabbitmqctl stop). Depending on the signal, this script will exwit
++ # rabbitmqctl stop). Depending on the signal, this script will exit
+ # with a non-zero error code:
+ # SIGHUP SIGTERM SIGTSTP
+ # They are considered a normal process termination, so the script
+@@ -177,6 +195,4 @@ if [ 'x' = "x$RABBITMQ_ALLOW_INPUT" -a -
+ # Block until RabbitMQ exits or a signal is caught.
+ # Waits for last command (which is start_rabbitmq_server)
+ wait $!
+-else
+- start_rabbitmq_server "$@"
+ fi
+--- a/src/rabbit.erl
++++ b/src/rabbit.erl
+@@ -284,16 +284,120 @@ broker_start() ->
+ Plugins = rabbit_plugins:setup(),
+ ToBeLoaded = Plugins ++ ?APPS,
+ start_apps(ToBeLoaded),
+- case os:type() of
+- {win32, _} -> ok;
+- _ -> case code:load_file(sd_notify) of
+- {module, sd_notify} -> SDNotify = sd_notify,
+- SDNotify:sd_notify(0, "READY=1");
+- {error, _} -> os:cmd("systemd-notify --ready")
+- end
+- end,
++ maybe_sd_notify(),
+ ok = log_broker_started(rabbit_plugins:active()).
+
++%% Try to send systemd ready notification if it makes sense in the
++%% current environment. standard_error is used intentionally in all
++%% logging statements, so all this messages will end in systemd
++%% journal.
++maybe_sd_notify() ->
++ case sd_notify_ready() of
++ false ->
++ io:format(standard_error, "systemd READY notification failed, beware of timeouts~n", []);
++ _ ->
++ ok
++ end.
++
++sd_notify_ready() ->
++ case {os:type(), os:getenv("NOTIFY_SOCKET")} of
++ {{win32, _}, _} ->
++ true;
++ {_, [_|_]} -> %% Non-empty NOTIFY_SOCKET, give it a try
++ sd_notify_legacy() orelse sd_notify_socat();
++ _ ->
++ true
++ end.
++
++sd_notify_data() ->
++ "READY=1\nSTATUS=Initialized\nMAINPID=" ++ os:getpid() ++ "\n".
++
++sd_notify_legacy() ->
++ case code:load_file(sd_notify) of
++ {module, sd_notify} ->
++ SDNotify = sd_notify,
++ SDNotify:sd_notify(0, sd_notify_data()),
++ true;
++ {error, _} ->
++ false
++ end.
++
++%% socat(1) is the most portable way the sd_notify could be
++%% implemented in erlang, without introducing some NIF. Currently the
++%% following issues prevent us from implementing it in a more
++%% reasonable way:
++%% - systemd-notify(1) is unstable for non-root users
++%% - erlang doesn't support unix domain sockets.
++%%
++%% Some details on how we ended with such a solution:
++%% https://github.com/rabbitmq/rabbitmq-server/issues/664
++sd_notify_socat() ->
++ case sd_current_unit() of
++ {ok, Unit} ->
++ io:format(standard_error, "systemd unit for activation check: \"~s\"~n", [Unit]),
++ sd_notify_socat(Unit);
++ _ ->
++ false
++ end.
++
++socat_socket_arg("@" ++ AbstractUnixSocket) ->
++ "abstract-sendto:" ++ AbstractUnixSocket;
++socat_socket_arg(UnixSocket) ->
++ "unix-sendto:" ++ UnixSocket.
++
++sd_open_port() ->
++ open_port(
++ {spawn_executable, os:find_executable("socat")},
++ [{args, [socat_socket_arg(os:getenv("NOTIFY_SOCKET")), "STDIO"]},
++ use_stdio, out]).
++
++sd_notify_socat(Unit) ->
++ case sd_open_port() of
++ {'EXIT', Exit} ->
++ io:format(standard_error, "Failed to start socat ~p~n", [Exit]),
++ false;
++ Port ->
++ Port ! {self(), {command, sd_notify_data()}},
++ Result = sd_wait_activation(Port, Unit),
++ port_close(Port),
++ Result
++ end.
++
++sd_current_unit() ->
++ case catch re:run(os:cmd("systemctl status " ++ os:getpid()), "([-.@0-9a-zA-Z]+)", [unicode, {capture, all_but_first, list}]) of
++ {'EXIT', _} ->
++ error;
++ {match, [Unit]} ->
++ {ok, Unit};
++ _ ->
++ error
++ end.
++
++sd_wait_activation(Port, Unit) ->
++ case os:find_executable("systemctl") of
++ false ->
++ io:format(standard_error, "'systemctl' unavailable, falling back to sleep~n", []),
++ timer:sleep(5000),
++ true;
++ _ ->
++ sd_wait_activation(Port, Unit, 10)
++ end.
++
++sd_wait_activation(_, _, 0) ->
++ io:format(standard_error, "Service still in 'activating' state, bailing out~n", []),
++ false;
++sd_wait_activation(Port, Unit, AttemptsLeft) ->
++ case os:cmd("systemctl show --property=ActiveState " ++ Unit) of
++ "ActiveState=activating\n" ->
++ timer:sleep(1000),
++ sd_wait_activation(Port, Unit, AttemptsLeft - 1);
++ "ActiveState=" ++ _ ->
++ true;
++ _ = Err->
++ io:format(standard_error, "Unexpected status from systemd ~p~n", [Err]),
++ false
++ end.
++
+ start_it(StartFun) ->
+ Marker = spawn_link(fun() -> receive stop -> ok end end),
+ case catch register(rabbit_boot, Marker) of
+@@ -332,6 +436,10 @@ stop_and_halt() ->
+ stop()
+ after
+ rabbit_log:info("Halting Erlang VM~n", []),
++ %% Also duplicate this information to stderr, so console where
++ %% foreground broker was running (or systemd journal) will
++ %% contain information about graceful termination.
++ io:format(standard_error, "Gracefully halting Erlang VM~n", []),
+ init:stop()
+ end,
+ ok.
+@@ -693,7 +801,8 @@ print_banner() ->
+ "~n ########## Logs: ~s"
+ "~n ###### ## ~s"
+ "~n ##########"
+- "~n Starting broker...",
++ "~n Starting broker..."
++ "~n",
+ [Product, Version, ?COPYRIGHT_MESSAGE, ?INFORMATION_MESSAGE,
+ log_location(kernel), log_location(sasl)]).
+