#!/sbin/runscript
# Copyright 1999-2006 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/dev-db/mysql-init-scripts/files/mysql.rc6,v 1.2 2007/03/04 15:47:03 vivo Exp $

# external binaries used: which, sed, tac

# int in_list(char * elem, char * list)
function in_list() {
    local elem=${1:-"none"}
    local list=${2:-","}

    [[ "${list}" == "${list/,${elem},/}" ]] \
    && return 1 \
    || return 0
}

function wdebug() {
    if [[ "${DEBUG}" -ge "${1}" ]] ; then
        shift
        echo "dbg:  ${@}"
    fi
}

depend() {
    use dns net localmount netmount nfsmount
}

do_escape() {
    # Ihatethisreallyverymuch
    #echo "$1" | sed -e "s|'| |" -e "s|=|='|" -e "s|$|'|"
    echo "$1"
}

# int get_slot_config(srv_slot=0, srv_num)
get_slot_config() {
    wdebug 4 ">>> get_slot_config()"

    local srv srv_slot srv_num
    srv_slot="${1:-"0"}"
    srv_num="${2}"
    MY_SUFFIX="-${srv_slot}"
    # srv=array(0 => [srv_slot], 1 => [srv_num] )
    srv=( ${srv_slot} ${srv_num} )

    local tmp_eval="mysql_slot_${srv_slot}${srv_num:+"_"}${srv_num}[@]"
    local conf_d_parameters="${!tmp_eval}"
    if [[ "${srv_slot}" == "0" ]] ; then
        MY_SUFFIX=''
        # try some other default for the default server
        [[ -z "${conf_d_parameters[@]}" ]] && conf_d_parameters=${mysql_slot[@]}
    fi
    [[ -z "${conf_d_parameters[@]}" ]] && conf_d_parameters=( )
    basedir="" datadir="" pidfile="" socket=""
    CHROOT="" NICE="" STARTUPTIMEOUT=5 STOPTIMEOUT=120

    wdebug 3 "srv                ${srv[@]}"
    wdebug 3 "srv_slot           ${srv_slot}"
    wdebug 3 "srv_num            ${srv_num}"
    wdebug 3 "tmp_eval           ${tmp_eval}"
    wdebug 3 "conf_d_parameters  ${conf_d_parameters[@]}"
    wdebug 3 "MY_SUFFIX          ${MY_SUFFIX}"

    local tmp_eval="mysql_slot_${srv_slot}${srv_num:+"_"}${srv_num}[@]"
    local conf_d_parameters="${!tmp_eval}"
    # collations need to be defined *after* the character sets,
    # so we will duplicate them
    local collations=""
    [[ ${conf_d_parameters[*]} == '()' ]] && conf_d_parameters=''

    MY_CNF="/etc/mysql${MY_SUFFIX}/my.cnf"
    # summa of unmanaged parameters
    # some parameters may be present multiple times
    unmanagedparams=""

    # grab the parameters from conf.d/mysql definition
    for my_default in ${conf_d_parameters[*]} ; do
        case "${my_default}" in
            nice=*)
                NICE="${my_default#nice=}"
                nice -n $NICE ls /tmp &>/dev/null || NICE=""
                ;;
            mycnf=*) MY_CNF="${my_default#mycnf=}" ;;
            startup_timeout=*)
                STARTUPTIMEOUT="${my_default#startup_timeout=}"    ;;
            basedir=*) basedir="${my_default#basedir=}" ;;
            datadir=*) datadir="${my_default#datadir=}" ;;
            pid-file=*) pidfile="${my_default#pid-file=}" ;;
            socket=*) socket="${my_default#socket=}" ;;
            user=*) user="${my_default#user=}" ;;
            *collation*=)
                collations="${collations} --$( do_escape "${my_default}" )"
                ;;
            *=*)
                # list of parameters we already have
                # prepend "--" because my_print_defaults do it
                unmanagedparams="${unmanagedparams} --$( do_escape "${my_default}" )"
                ;;
            *)
                unmanagedparams="${unmanagedparams} --${my_default}"
                ;;
        esac
    done

    if [[ ! -r "${MY_CNF}" ]] ; then
        ewarn "Cannot access ${MY_CNF} !"
        MY_CNF=""
        my_defaults=""
    else
        local my_print_defaults="$(which my_print_defaults${MY_SUFFIX} 2>/dev/null)"
        if [[ ! -x "${my_print_defaults}" ]] ; then
            eerror "my_print_defaults NOT found or not executable"
            my_defaults=""
        else
            my_defaults=$( ${my_print_defaults} \
            --loose-verbose \
            --config-file="${MY_CNF}" \
            mysqld server )
        fi
    fi

    # grab needed parameters from my.cnf, don't override the ones from
    # conf.d/mysql
    for my_default in ${my_defaults} ; do
        case "${my_default}" in
            --basedir=*)
                [[ -z "${basedir}" ]] && basedir="${my_default#--basedir=}" ;;
            --datadir=*)
                [[ -z "${datadir}" ]] && datadir="${my_default#--datadir=}" ;;
            --pid-file=*)
                [[ -z "${pidfile}" ]] && pidfile="${my_default#--pid-file=}" ;;
            --socket=*)
                [[ -z "${socket}" ]] && socket="${my_default#--socket=}" ;;
            --user=*)
                [[ -z "${user}" ]] && user="${my_default#--user=}" ;;
            --*collation*=)
                # the order is inversed because we want the conf.d ones overriden
                collations="$( do_escape "${my_default}" ) ${collations}"
                ;;
        esac
    done

    # some parameters
    basedir="${basedir:-"/usr"}"
    datadir="${datadir:-"/var/lib/mysql${MY_SUFFIX}"}"
    pidfile="${pidfile:-"/var/run/mysqld/mysqld${MY_SUFFIX}.pid"}"
    socket="${socket:-"/var/run/mysqld/mysqld${MY_SUFFIX}.sock"}"
    user="${user:-"mysql"}"
    unmanagedparams="${unmanagedparams} ${collations}"

    wdebug 3 "chroot dir => ${CHROOT}"
    wdebug 3 "niceness   => ${NICE}"
    wdebug 3 "basedir    => ${basedir}"
    wdebug 3 "datadir    => ${datadir}"
    wdebug 3 "pidfile    => ${pidfile}"
    wdebug 3 "socket     => ${socket}"
    wdebug 3 "Unmanaged  => ${unmanagedparams}"

    # extension for sleep tenth of seconds, not very portable so check it before
    if sleep 0.01 ; then
        STARTUPTIMEOUT=$(( STARTUPTIMEOUT * 10 ))
        STOPTIMEOUT=$(( STOPTIMEOUT * 10 ))
        TIMEUNIT=0.1
    else
        TIMEUNIT=1
    fi

    # push these out to the script
    export MY_SUFFIX NICE MY_CNF pidfile datadir basedir socket CHROOT
    export unmanagedparams STARTUPTIMEOUT STOPTIMEOUT TIMEUNIT
    wdebug 4 "<<< get_slot_config() ok"
    return 0
}

checkconfig() {
    wdebug 4 ">>> checkconfig(\"${1}\")"
    local datadir="${1}" pidfile="${2}" socket="${3}"

    if [[ -n "${NOCHECK}" ]] ; then
        rm -f "${pidfile}" "${socket}"
        return 0
    fi

    if [[ ! -d "${datadir}" ]] ; then
        eerror "MySQL datadir is empty or invalid"
        eerror "Please check your my.cnf : ${MY_CNF}"
        wdebug 4 "<<< checkconfig() KO"
        return 1
    fi

    if [[ ! -d "${datadir}/mysql" ]] ; then
        eerror "You don't appear to have the mysql database installed yet."
        eerror "Please run /usr/bin/mysql_install_db to have this done..."
        wdebug 4 "<<< checkconfig() KO"
        return 1
    fi

    if [[ -f "${pidfile}" ]] ; then
        kill -15 $(< ${pidfile}) 2>/dev/null
        if [[ $? -eq 0 ]] ; then
            # the process exist, we have a problem
            eerror "\"${pidfile}\" is still present and the process is running."
            eerror "Please stop it \"kill $(< ${pidfile})\" maybe ?"
            wdebug 4 "<<< checkconfig() KO"
            return 1
        else
            rm -f "${pidfile}"
        fi
    fi

    if [[ -S "${socket}" ]] ; then
        ewarn "Strange, the socket file already exist in \"${socket}\""
        ewarn "it will be removed now and re-created by the MySQL server"
        ewarn "BUT please make your checks."
        rm -f "${socket}"
    fi

    wdebug 4 "<<< checkconfig() ok"
    return 0
}

start() {
    wdebug 4 ">>> start()"

    MYSQL_GLOB_PID_FILE=${MYSQL_GLOB_PID_FILE:-"/var/run/svc-started-${SVCNAME/mysql/mysqld}"}
    # servers are defined in /etc/conf.d/mysql
    local serverlist=${!mysql_slot_*}
    # provide default for empty conf.d/mysql
    if [[ -z "${serverlist}" ]] ; then
        serverlist=0
        export mysql_slot_0=( )
    fi
    local retstatus timeout
    local globretstatus=1
    local srv_slot srv_num
    # server MUST NOT share same location for these
    local pidfilelist=',' datadirlist=',' socketlist=','
    local ssd_thing=1
    local mysqld_thing tmpnice

    ebegin "Starting ${myservice}"
    # try to start each server
    for srv in ${serverlist[*]} ; do

        srv_slot="${srv#mysql_slot_}"
        if [[ "${srv_slot}" == "${srv_slot#*_}" ]] ; then
            srv_num=''
        else
            srv_num="${srv_slot#*_}"
        fi
        srv_slot="${srv_slot%%_*}"

        retstatus=0
        get_slot_config "${srv_slot}" "${srv_num}" || retstatus=1

        # checks
        if ! checkconfig "${datadir}" "${pidfile}" "${socket}" ; then
            retstatus=2 ; continue
        fi
        if in_list "${pidfile}" "${pidfilelist}" ; then
            eerror "Sorry, won't start with same pid-file: ${pidfile}"
            retstatus=3 ; continue
        fi
        if in_list "${datadir}" "${datadirlist}" ; then
            eerror "Sorry, won't start with same datadir: ${datadir}"
            retstatus=4 ; continue
        fi
        if in_list "${socket}" "${socketlist}" ; then
            eerror "Sorry, won't start with same socket: ${socket}"
            retstatus=5 ; continue
        fi

        einfo "Starting ${myservice} (${MY_CNF})"

        mysqld_thing="${MY_CNF:+"--defaults-file="}${MY_CNF}"
        mysqld_thing="${mysqld_thing} ${unmanagedparams}"
        mysqld_thing="${mysqld_thing} --basedir=${basedir}"
        mysqld_thing="${mysqld_thing} --datadir=${datadir}"
        mysqld_thing="${mysqld_thing} --pid-file=${pidfile}"
        mysqld_thing="${mysqld_thing} --socket=${socket}"
        mysqld_thing="${mysqld_thing} --user=${user}"

        wdebug 2 "starting mysqld with: ${mysqld_thing}"

        if [[ ${ssd_thing} -eq 1 ]] ; then
            tmpnice="${NICE:+"--nicelevel "}${NICE}"
            start-stop-daemon --quiet ${DEBUG/*/"--verbose"} --start \
            --background ${tmpnice} --pidfile ${pidfile} \
            --exec ${basedir}/sbin/mysqld${MY_SUFFIX} -- ${mysqld_thing} \
            && sleep ${TIMEUNIT}
            retstatus=$?
        else
            tmpnice="${NICE:+"nice -n "}${NICE}"
            ${tmpnice} ${basedir}/sbin/mysqld${MY_SUFFIX} ${mysqld_thing} &
            retstatus=0
        fi

        # only the first run is done by start-stop-daemon
        ssd_thing=""

        # wait for socket creation
        wdebug 1
        while ! [[ -S "${socket}" || "${STARTUPTIMEOUT}" -lt 1 || "${retstatus}" -ne 0 ]] ; do
            STARTUPTIMEOUT=$(( STARTUPTIMEOUT - 1 ))
            [[ ${DEBUG} -ge 1 ]] && echo -n "${STARTUPTIMEOUT},"
            sleep ${TIMEUNIT}
        done
        wdebug 1 ""
        if [[ ! -S "${socket}" ]] ; then
            eerror "MySQL${MY_SUFFIX} NOT started (${retstatus})"
            retstatus=1
        else
            globretstatus=0
            pidfilelist="${pidfilelist}${pidfile},"
            datadirlist="${datadirlist}${datadir},"
            socketlist="${socketlist}${socket},"
            echo "${srv_slot}${srv_num:+"_"}${srv_num}=${pidfile}" >> "${MYSQL_GLOB_PID_FILE}"
        fi
    done
    # successfull if at least one mysqld started
    wdebug 4 "<<< start()"
    eend $globretstatus
}

stop() {
    get_slot_config &> /dev/null
    MYSQL_GLOB_PID_FILE=${MYSQL_GLOB_PID_FILE:-"/var/run/svc-started-${SVCNAME/mysql/mysqld}"}
    local runwhat pidfile shutdown_elem
    local PID cnt timeout=${STOPTIMEOUT:-"120"}
    local retstatus=0
    local shutdown_list="$(< "${MYSQL_GLOB_PID_FILE}" )"

    ebegin "Stopping ${myservice}"
    wdebug 5 "MYSQL_GLOB_PID_FILE: ${MYSQL_GLOB_PID_FILE}"
    wdebug 5 "shutdown_list: ${shutdown_list}"
    for shutdown_elem in ${shutdown_list} ; do
        runwhat=${shutdown_elem%%=*}
        pidfile=${shutdown_elem#*=}
        timeout=${STOPTIMEOUT:-"120"}
        PID=$(< "${pidfile}" )
        wdebug 3 "runwhat            ${runwhat}"
        wdebug 3 "pidfile            ${pidfile}"
        wdebug 3 "timeout            ${timeout}"
        wdebug 3 "PID                ${PID}"

        einfo "Stopping mysqld (${runwhat})"

        start-stop-daemon --quiet ${DEBUG/*/"--verbose"} --stop --pidfile "${pidfile}" &
        wdebug 1 ""
        while [[ -n "$PID" ]] \
            && $( ps -Ao pid | grep -q "^ *$PID$" ) \
            && [[ "${timeout}" -ge 1 ]]
        do
            timeout=$(($timeout - 1))
            [[ ${DEBUG} -ge 1 ]] && echo -n "$(( $STOPTIMEOUT - $timeout )),"
            sleep ${TIMEUNIT}
        done
        [[ "${timeout}" -lt 1 ]] && retstatus=1
    done
    sleep ${TIMEUNIT}
    [[ "$retstatus" -eq 0 ]] && rm -f "$MYSQL_GLOB_PID_FILE"
    eend ${retstatus}
}
