#! /bin/sh
#
# chkconfig: - 55 45
# description:  CloudFlare Railgun server
# processname: rg-listener
# config: /etc/sysconfig/railgun
# pidfile: /var/run/railgun/railgun.pid

### BEGIN INIT INFO
# Provides:          railgun
# Required-Start:    $network
# Required-Stop:     
# Default-Start:     3 4 5
# Default-Stop:      0 1 2 6
# Short-Description: Railgun listener
# Description:       Railgun listener
### END INIT INFO

# Standard LSB functions
if [ -f /lib/lsb/init-functions ]; then
	. /lib/lsb/init-functions
fi

# Source function library.
if [ -f /etc/init.d/functions ]; then
	. /etc/init.d/functions
fi

USER="railgun"
RAILGUN="/usr/bin/rg-listener"
PORT="2408"
WAIT_TIMEOUT=30

if [ -f /etc/sysconfig/railgun ]; then
	. /etc/sysconfig/railgun
fi

[ -n "$ULIMIT" ] && ulimit $ULIMIT

if [ -f /etc/sysconfig/network ]; then
	# Check that networking is up.
	. /etc/sysconfig/network

	if [ "$NETWORKING" = "no" ]; then
		exit 0
	fi
fi

RETVAL=0
prog="railgun"

fg_exec() {
	errors=$(su --shell=/bin/sh $USER -c "sh -c \"$RAILGUN -config=/etc/railgun/railgun.conf &\" ")
	if [ -n "$errors" ]; then
		errors="${errors}"
	else
		errors="Railgun terminated abnormally. Please attempt to run manually:\nsudo -u $USER $DAEMON -config=/etc/railgun/railgun.conf\nIf problems persist, contact support (help@cloudflare.com)\nwith details on system log lines and any errors messages."
	fi

	return 0
}

start () {
	echo -n $"Starting $prog: "

	# ensure that /var/run/railgun exists and has proper permissions
	if [ ! -d /var/run/railgun ]; then
		mkdir -p /var/run/railgun
	fi

	if [ "`stat -c %U /var/run/railgun`" != "$USER" ]; then
		chown $USER /var/run/railgun
	fi

	daemon --pidfile /var/run/railgun/railgun.pid --user $USER "($RAILGUN -config /etc/railgun/railgun.conf >/dev/null 2>&1 &)&"
	RETVAL=$?
	echo

	# Attempt to start Railgun in background.
	# If PID does not exist after 5 seconds or if Railgun is not listening on a port
	# after $WAIT_TIMEOUT seconds, terminate and attempt to run in the foreground to expose errors
	sleep 5
	echo "Railgun successfully backgrounded, ensuring proper startup..."
	i=0
	pid=$(pidofproc -p /var/run/railgun/railgun.pid $(basename $RAILGUN))
	while [ -n "${pid:-}" ]; do
		port_open=$(netstat -plnt | grep "$PORT.*$pid/$(basename $RAILGUN)" 2> /dev/null)
		if [ -z "${port_open:-}" ]; then
			if [ $i = "$WAIT_TIMEOUT" ]; then
				[ -n "${pid:-}" ] && kill -9 $pid > /dev/null 2&>1 && sleep 1
				break
			else
				if [ $i = '0' ]; then
					echo -n " ... waiting "
				else
					echo -n "."
				fi
				i=$(($i+1))
				sleep 1
				# ensure rg-listener is still running
				pid=$(pidofproc -p /var/run/railgun/railgun.pid $(basename $RAILGUN))
			fi
		else
				success
				echo ""
				return 0
		fi
	done

	failure
	echo ""
	echo "Error starting Railgun as a daemon. Running in foreground..."
	fg_exec
	if [ $RETVAL -eq 0 ]; then
		echo
		echo "$errors"
		failure
		echo
	fi

	[ $RETVAL -eq 0 ] && touch /var/lock/subsys/railgun
}

stop () {
	echo -n $"Stopping $prog: "
	killproc -p /var/run/railgun/railgun.pid $RAILGUN
	RETVAL=$?
	echo
	if [ $RETVAL -eq 0 ] ; then
		rm -f /var/lock/subsys/railgun
		rm -f /var/run/railgun/railgun.pid
	fi
}
restart () {
	stop
	sleep 2
	start
}
reload() {
	echo -n $"Reloading $prog: "
	
	if [ -f "/var/run/railgun/railgun.pid" ] ; then
		pid=$(cat /var/run/railgun/railgun.pid 2>/dev/null)
		if [ -n "${pid}" ] && [ -e /proc/"${pid}" ]; then
			kill -HUP "$pid"
			RETVAL=$?
		fi
		if [ $RETVAL -ne 0 ]; then
			failure
		else
			success
		fi
	else
		failure $"Reloading $prog"
	fi
	RETVAL=$?
	echo
}
upgrade() {
	echo -n $"Upgrading $prog: "
	
	if [ -f "/var/run/railgun/railgun.pid" ] ; then
		pid=$(cat /var/run/railgun/railgun.pid 2>/dev/null)
		if [ -n "${pid}" ] && [ -e /proc/"${pid}" ]; then
			# upgrade rg-listener gracefully via SIGUSR2 and then restart
			if kill -s USR2 $pid 2>/dev/null; then
				while [ "$(/sbin/pidof /usr/bin/rg-listener 2> /dev/null | grep -o "$pid")" = "$pid" \
					-o -z "$(/sbin/pidof /usr/bin/rg-listener 2> /dev/null)" ]; do
					i=$(($i+1))
					if [ $i -gt $WAIT_TIMEOUT ]; then
						kill -s KILL $pid 2> /dev/null
						sleep 1
						rm -f /var/run/railgun/railgun.pid /var/lock/subsys/railgun
						failure $"Upgrading $prog"
						echo
						echo "Failed to upgrade rg-listener via SIGUSR2. Restarting $prog."
						start
						return $?
					fi
					sleep 1
				done
				sleep 1
				if [ -z "$(/sbin/pidof /usr/bin/rg-listener 2> /dev/null)" ]; then
					rm -f /var/run/railgun/railgun.pid /var/lock/subsys/railgun
					failure $"Upgrading $prog"
					echo
					echo "Failed to upgrade rg-listener via SIGUSR2. Restarting $prog."
					start
					return $?
				else
					success
				fi
			else
				failure $"Upgrading $prog"
				echo
				echo "Failed to upgrade rg-listener via SIGUSR2. $prog must be restarted."
			fi
		fi
	else
		failure $"Upgrading $prog"
		echo
		echo "$prog is not running"
	fi
	RETVAL=$?
	echo
}
graceful_stop() {
	echo -n $"Graceful shutdown $prog: "
	
	if [ -f "/var/run/railgun/railgun.pid" ] ; then
		pid=$(cat /var/run/railgun/railgun.pid 2>/dev/null)
		if [ -n "${pid}" ] && [ -e /proc/"${pid}" ]; then
			kill -QUIT "$pid"
			RETVAL=$?
		fi
		if [ $RETVAL -ne 0 ]; then
			failure
		else
			sleep 5
			rm -f /var/lock/subsys/railgun
			rm -f /var/run/railgun/railgun.pid
			success
		fi
	else
		failure $"Graceful shutdown $prog"
	fi
	RETVAL=$?
	echo
}

# See how we were called.
case "$1" in
	start)
		start
		;;
	stop)
		stop
		;;
	reload)
		reload
		;;
	upgrade)
		upgrade
		;;
	graceful-stop)
		graceful_stop
		;;
	status)
		status rg-listener
		;;
	restart|force-reload)
		restart
		;;
	condrestart)
		[ -f /var/lock/subsys/railgun ] && restart || :
		;;
	*)
		echo $"Usage: $0 {start|stop|status|restart|reload|force-reload|upgrade|graceful-stop|condrestart}"
		exit 1
esac

exit $?
