#!/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=}" ;;
			*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=}" ;;
			--*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"}"
	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 "Unamanged  => ${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=mysql"

		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}
}