#!/bin/bash

### BEGIN INIT INFO
# Provides:          nebd-daemon
# Required-Start:    $local_fs $remote_fs $network
# Required-Stop:     $local_fs $remote_fs $network
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: nebd-daemon service
# Description:       Start the nebd-daemon service and associated helpers
### END INIT INFO

NEBD_SERVER_BIN=/usr/bin/nebd-server
STARTED_AS_ROOT=false
USERS_FILE=/etc/nebd/users
USERS=()

if [[ $(id -u) -eq 0 ]]; then
    STARTED_AS_ROOT=true
fi

function get_nebd_server_pid() {
    local tmp=$(pgrep -u ${1} nebd-server)
    echo $tmp
}

function list_users() {
    if [ -f ${USERS_FILE} ]; then
        IFS=$'\n' read -d '' -r -a TMP_USERS <${USERS_FILE}
        USERS=("${TMP_USERS[@]}")
    fi

    # always add root user for compatible
    if [[ ! "${USERS[@]}" =~ "root" ]]; then
        USERS=("root" "${USERS[@]}")
    fi
}

function create_dir_if_not_exists() {
    if [ ! -d ${1} ]; then
        mkdir -p ${1} >/dev/null 2>&1
        chown ${2} ${1} >/dev/null 2>&1
        chmod 777 ${1} >/dev/null 2>&1
    fi
}

function prepare_env() {
    PREPARE_RES=

    cat /etc/passwd | awk -F':' '{ print $1 }' | grep $1 >/dev/null 2>&1
    if [ $? -ne 0 ]; then
        PREPARE_RES="user ${1} not found in '/etc/passwd'"
        # echo "user '${1}' not found in '/etc/passwd'"
        return
    fi

    if [ "${1}" == "root" ]; then
        DAEMON_NAME=nebd-server
        META_DATA_PATH=/data/nebd
        DATA_LOCK_PATH=${META_DATA_PATH}/lock
        BASE_LOG_PATH=/data/log/nebd
        CONF_PATH=/etc/nebd/nebd-server.conf
    else
        DAEMON_NAME=nebd-server-${1}
        META_DATA_PATH=/data/nebd/nebd-${1}
        DATA_LOCK_PATH=${META_DATA_PATH}/lock
        BASE_LOG_PATH=/data/log/nebd/nebd-${1}
        CONF_PATH=/etc/nebd/nebd-server-${1}.conf
    fi

    PID_FILE=${BASE_LOG_PATH}/nebd-server.pid
    DAEMON_LOG=${BASE_LOG_PATH}/nebd-server-daemon.log
    CONSOLE_LOG=${BASE_LOG_PATH}/nebd-server-console.log
    LOG_PATH=${BASE_LOG_PATH}/server
    NEBD_CLIENT_LOG_PATH=${BASE_LOG_PATH}/client

    # check config file
    if [ ! -f ${CONF_PATH} ]; then
        PREPARE_RES="not found config file '${CONF_PATH}'"
        # echo "not found config file '${CONF_PATH}'"
        return
    fi

    create_dir_if_not_exists ${META_DATA_PATH} ${1}
    create_dir_if_not_exists ${DATA_LOCK_PATH} ${1}
    create_dir_if_not_exists ${LOG_PATH} ${1}
    create_dir_if_not_exists ${NEBD_CLIENT_LOG_PATH} ${1}
}

function start_one() {
    prepare_env $1

    if [ "${PREPARE_RES}" != "" ]; then
        echo "$1: prepare env failed, ${PREPARE_RES}"
        return
    fi

    # check whether already started by daemon
    daemon --name ${DAEMON_NAME} --pidfile ${PID_FILE} --running
    if [ $? -eq 0 ]; then
        echo "$1: already started nebd-server by daemon"
        return
    fi

    # record number of line before start
    line1=$(cat ${DAEMON_LOG} | wc -l)

    USEROPTS=
    if $STARTED_AS_ROOT; then
        USEROPTS="--user ${1}"
    fi

    LD_PRELOAD=${jemallocpath} daemon --name ${DAEMON_NAME} --core --inherit \
        --respawn --attempts 10 --delay 10 --acceptable 10 --pidfile ${PID_FILE} \
        --errlog ${DAEMON_LOG} \
        --output ${CONSOLE_LOG} ${USEROPTS} \
        -- ${NEBD_SERVER_BIN} -confPath=${CONF_PATH} -log_dir=${LOG_PATH} -graceful_quit_on_sigterm=true -stderrthreshold=3

    # sleep a while, check whether start successful
    sleep 1
    line2=$(cat ${DAEMON_LOG} | wc -l)
    if [ $line1 != $line2 ]; then
        echo "$1: start nebd-server met error!"
        stop_one $1
    fi
}

function stop_one() {
    prepare_env $1

    if [ "${PREPARE_RES}" != "" ]; then
        echo "$1: prepare env failed, ${PREPARE_RES}"
        return
    fi

    # 判断是否已经通过daemon启动了nebd-server
    daemon --name ${DAEMON_NAME} --pidfile ${PID_FILE} --running
    if [ $? -ne 0 ]; then
        echo "$1: didn't start nebd-server by daemon"
        return
    fi

    daemon --name ${DAEMON_NAME} --pidfile ${PID_FILE} --stop
    if [ $? -ne 0 ]; then
        echo "$1: stop may not success!"
    else
        # wait 3s
        retry_times=0
        while [ $retry_times -le 3 ]; do
            ((retry_times = $retry_times + 1))
            pgrep -u $1 nebd-server >/dev/null 2>&1
            if [ $? -eq 0 ]; then
                sleep 1
            else
                break
            fi
        done

        pgrep -u $1 nebd-server >/dev/null 2>&1
        if [ $? -eq 0 ]; then
            echo "$1: nebd-server still exists after 3s, now kill it with SIGKILL"
            kill -9 $(pgrep -u $1 nebd-server)
        fi

        echo "$1: nebd-server exit success, daemon exit success!"
    fi
}

function restart_one() {
    prepare_env $1

    if [ "${PREPARE_RES}" != "" ]; then
        echo "$1: prepare env failed, ${PREPARE_RES}"
        return
    fi

    # 判断是否已经通过daemon启动了nebd-server
    daemon --name ${DAEMON_NAME} --pidfile ${PID_FILE} --running
    if [ $? -ne 0 ]; then
        echo "$1: didn't start nebd-server by daemon"
        return
    fi

    old_pid=$(get_nebd_server_pid $1)

    daemon --name ${DAEMON_NAME} --pidfile ${PID_FILE} --restart

    sleep 1
    new_pid=$(get_nebd_server_pid $1)

    if [ $old_pid == $new_pid ]; then
        echo "$1: restart nebd-server may failed, now kill it with SIGKILL"
        kill -9 $old_pid
    fi
}

function status_one() {
    prepare_env $1

    if [ "${PREPARE_RES}" != "" ]; then
        echo "$1: prepare env failed, ${PREPARE_RES}"
        return
    fi

    daemon --name ${DAEMON_NAME} --pidfile ${PID_FILE} --running
    if [ $? -ne 0 ]; then
        echo "$1: didn't start nebd-server by daemon"
    else
        echo "$1: nebd-server is running by daemon"
    fi
}

# start nebd-server
function start() {
    if ! $STARTED_AS_ROOT; then
        echo "nebd-daemon start should run as root"
        exit 1
    fi

    list_users
    for u in "${USERS[@]}"; do
        start_one $u
    done
}

# stop daemon and nebd-server
function stop() {
    if ! $STARTED_AS_ROOT; then
        echo "nebd-daemon stop should run as root"
        exit 1
    fi

    list_users
    for u in "${USERS[@]}"; do
        stop_one $u
    done
}

# restart
function restart() {
    if ! $STARTED_AS_ROOT; then
        echo "nebd-daemon restart should run as root"
        exit 1
    fi

    list_users
    for u in "${USERS[@]}"; do
        restart_one $u
    done
}

# status
function status() {
    if ! $STARTED_AS_ROOT; then
        echo "nebd-daemon status should run as root"
        exit 1
    fi

    list_users
    for u in "${USERS[@]}"; do
        status_one $u
    done
}

# 使用方式
function usage() {
    echo "Usage:"
    echo "  nebd-daemon start -- start deamon process and watch on nebd-server process for all instance"
    echo "  nebd-daemon start-one -- start deamon process and watch on nebd-server process for current user's instance"

    echo "  nebd-daemon stop  -- stop daemon process and nebd-server for all instance"
    echo "  nebd-daemon stop-one  -- stop daemon process and nebd-server for current user's instance"

    echo "  nebd-daemon restart -- restart nebd-server for all instance"
    echo "  nebd-daemon restart-one -- restart nebd-server for current user's instance"

    echo "  nebd-daemon status -- show if the nebd-server is running by daemon for all instance"
    echo "  nebd-daemon status-one -- show if the nebd-server is running by daemon for current user's instance"
}

# 检查参数启动参数，最少1个
if [ $# -lt 1 ]; then
    usage
    exit
fi

case $1 in
"start")
    start
    ;;
"start-one")
    start_one ${USER}
    ;;
"stop")
    stop
    ;;
"stop-one")
    stop_one ${USER}
    ;;
"restart")
    restart
    ;;
"restart-one")
    restart_one ${USER}
    ;;
"status")
    status
    ;;
"status-one")
    status_one ${USER}
    ;;
*)
    usage
    ;;
esac
