#!/bin/sh -e
##  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 Developer of the Original Code is GoPivotal, Inc.
##  Copyright (c) 2007-2015 Pivotal Software, Inc.  All rights reserved.
##

# Get default settings with user overrides for (RABBITMQ_)<var_name>
# Non-empty defaults should be set in rabbitmq-env
. `dirname $0`/rabbitmq-env

RABBITMQ_START_RABBIT=
[ "x" = "x$RABBITMQ_ALLOW_INPUT" ] && RABBITMQ_START_RABBIT=" -noinput"
[ "x" = "x$RABBITMQ_NODE_ONLY" ] && RABBITMQ_START_RABBIT="$RABBITMQ_START_RABBIT -s $RABBITMQ_BOOT_MODULE boot "

case "$(uname -s)" in
  CYGWIN*) # we make no attempt to record the cygwin pid; rabbitmqctl wait
           # will not be able to make sense of it anyway
           ;;
  *)       # When -detached is passed, we don't write the pid, since it'd be the
           # wrong one
           detached=""
           for opt in "$@"; do
               if [ "$opt" = "-detached" ]; then
                   detached="true"
               fi
           done
           if [ $detached ]; then
               echo "Warning: PID file not written; -detached was passed." 1>&2
           else
               RABBITMQ_PID_DIR="$(dirname ${RABBITMQ_PID_FILE})"
               EX_CANTCREAT=73 # Standard exit code from sysexits(2)
               if ! mkdir -p "$RABBITMQ_PID_DIR"; then
                   # Better diagnostics - 'mkdir -p' reports only the first directory in chain that
                   # it fails to create
                   echo "Failed to create directory: $RABBITMQ_PID_DIR"
                   exit $EX_CANTCREAT
               fi
               if ! echo $$ > ${RABBITMQ_PID_FILE}; then
                   # Bettern 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}"
                   exit $EX_CANTCREAT
               fi
           fi
esac

RABBITMQ_EBIN_ROOT="${RABBITMQ_HOME}/ebin"

set +e

RABBITMQ_CONFIG_FILE=$RABBITMQ_CONFIG_FILE \
RABBITMQ_DIST_PORT=$RABBITMQ_DIST_PORT \
    ${ERL_DIR}erl -pa "$RABBITMQ_EBIN_ROOT" \
    -boot "${CLEAN_BOOT_FILE}" \
    -noinput \
    -hidden \
    -s rabbit_prelaunch \
    ${RABBITMQ_NAME_TYPE} rabbitmqprelaunch$$ \
    -extra "${RABBITMQ_NODENAME}"

PRELAUNCH_RESULT=$?
if [ ${PRELAUNCH_RESULT} = 2 ] ; then
    # dist port is mentioned in config, so do not set it
    true
elif [ ${PRELAUNCH_RESULT} = 0 ] ; then
    # dist port is not mentioned in the config file, we can set it
    RABBITMQ_DIST_ARG="-kernel inet_dist_listen_min ${RABBITMQ_DIST_PORT} -kernel inet_dist_listen_max ${RABBITMQ_DIST_PORT}"
else
    exit ${PRELAUNCH_RESULT}
fi

set -e

RABBITMQ_CONFIG_ARG=
[ -f "${RABBITMQ_CONFIG_FILE}.config" ] && RABBITMQ_CONFIG_ARG="-config ${RABBITMQ_CONFIG_FILE}"

RABBITMQ_LISTEN_ARG=
[ "x" != "x$RABBITMQ_NODE_PORT" ] && [ "x" != "x$RABBITMQ_NODE_IP_ADDRESS" ] && RABBITMQ_LISTEN_ARG="-rabbit tcp_listeners [{\""${RABBITMQ_NODE_IP_ADDRESS}"\","${RABBITMQ_NODE_PORT}"}]"

# If $RABBITMQ_LOGS is '-', send all log messages to stdout. Likewise
# for RABBITMQ_SASL_LOGS. This is particularily useful for Docker
# images.

if [ "$RABBITMQ_LOGS" = '-' ]; then
    RABBIT_ERROR_LOGGER='tty'
else
    RABBIT_ERROR_LOGGER='{file,"'${RABBITMQ_LOGS}'"}'
fi

if [ "$RABBITMQ_SASL_LOGS" = '-' ]; then
    SASL_ERROR_LOGGER=tty
    RABBIT_SASL_ERROR_LOGGER='tty'
else
    SASL_ERROR_LOGGER=false
    RABBIT_SASL_ERROR_LOGGER='{file,"'${RABBITMQ_SASL_LOGS}'"}'
fi

# we need to turn off path expansion because some of the vars, notably
# RABBITMQ_SERVER_ERL_ARGS, contain terms that look like globs and
# there is no other way of preventing their expansion.
set -f

start_rabbitmq_server() {
    RABBITMQ_CONFIG_FILE=$RABBITMQ_CONFIG_FILE \
    exec ${ERL_DIR}erl \
        -pa ${RABBITMQ_EBIN_ROOT} \
        ${RABBITMQ_START_RABBIT} \
        ${RABBITMQ_NAME_TYPE} ${RABBITMQ_NODENAME} \
        -boot "${SASL_BOOT_FILE}" \
        ${RABBITMQ_CONFIG_ARG} \
        +W w \
        +A ${RABBITMQ_IO_THREAD_POOL_SIZE} \
        ${RABBITMQ_SERVER_ERL_ARGS} \
        +K true \
        -kernel inet_default_connect_options "[{nodelay,true}]" \
        ${RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS} \
        ${RABBITMQ_LISTEN_ARG} \
        -sasl errlog_type error \
        -sasl sasl_error_logger "$SASL_ERROR_LOGGER" \
        -rabbit error_logger "$RABBIT_ERROR_LOGGER" \
        -rabbit sasl_error_logger "$RABBIT_SASL_ERROR_LOGGER" \
        -rabbit enabled_plugins_file "\"$RABBITMQ_ENABLED_PLUGINS_FILE\"" \
        -rabbit plugins_dir "\"$RABBITMQ_PLUGINS_DIR\"" \
        -rabbit plugins_expand_dir "\"$RABBITMQ_PLUGINS_EXPAND_DIR\"" \
        -os_mon start_cpu_sup false \
        -os_mon start_disksup false \
        -os_mon start_memsup false \
        -mnesia dir "\"${RABBITMQ_MNESIA_DIR}\"" \
        ${RABBITMQ_SERVER_START_ARGS} \
        ${RABBITMQ_DIST_ARG} \
        "$@"
}

stop_rabbitmq_server() {
    RABBITMQCTL="$(dirname "$0")/rabbitmqctl"

    if ${RABBITMQCTL} -n ${RABBITMQ_NODENAME} status >/dev/null 2>&1; then
        ${RABBITMQCTL} -n ${RABBITMQ_NODENAME} stop
    fi
}

if [ 'x' = "x$RABBITMQ_ALLOW_INPUT" -a -z "$detached" ]; then
    # 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.

    # The Erlang VM should ignore SIGINT.
    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
    # with a non-zero error code:
    #   SIGHUP SIGTERM SIGTSTP
    #     They are considered a normal process termination, so the script
    #     exits with 0.
    #   SIGINT
    #     They are considered an abnormal process termination, the script
    #     exits with the job exit code.
    trap "stop_rabbitmq_server; exit 0" HUP TERM TSTP
    trap "stop_rabbitmq_server" INT

    start_rabbitmq_server "$@" &

    # Block until RabbitMQ exits or a signal is caught.
    # Waits for last command (which is start_rabbitmq_server)
    wait $!
else
    start_rabbitmq_server "$@"
fi
