#!/bin/bash

#Constants
[[ -n $CRASH_LOG ]] || CRASH_LOG="crash/crash.log"
[[ -n $LOGS_DIR ]] || LOGS_DIR="/db/www/logs"

#Methods
declare -i LAST_START
declare -i ISS_EXITTIME
declare -i ISS_EXITCODE
declare -A OPTS

LAST_START=0
get_rty_startuptime ()
{
	local fname="$LOGS_DIR/startup.info.$BSCONFIG_IPORT"
	[ -s "$fname" ] || return 0
	LAST_START=$(tail -1 $fname | cut -d ',' -f1)
}

CRASH_LOG_VERSION=0
find_crashlog_version ()
{
	grep -q 'section=' $1 > /dev/null && CRASH_LOG_VERSION=1
}

#Usage: get_iss_exitcode <fpath to crash.log>
ISS_EXITTIME=0
ISS_EXITCODE=500 # Unknown
get_iss_exitcode ()
{
	# Old: 2016-11-28 19:56:33,028 ws40-131:22660 -11
	# New: datetime=2016-11-27 19:44:37.856104	exit_code=-6	instance_name=man1-6412:25268	pid=339927	section=base_saas	timestamp_ms=148026507785
        # New2: coredumped=1    datetime=2017-12-14 03:38:54.805849     exit_code=-6    exit_status=    instance_name=vla1-0584:7590    pid=17  section=base_saas       term_signal=6   timestamp_ms=1513211934805
	local last_line

	find_crashlog_version $1
	if [ $CRASH_LOG_VERSION -eq 0 ]; then
		last_line="datetime=$(tac $1 | grep -m 1 $BSCONFIG_INAME)"
	else
		last_line=$(tac $1 | grep "section=$LOOP_SECTION" | grep -m 1 $BSCONFIG_INAME)
	fi

	last_line=$(echo $last_line | sed -e 's:\t: :g')

	local dt=$(echo $last_line | grep -Po '(?<=datetime=) *[0-9-]*[ T][0-9:.]*' | xargs)
	[ ! -z "$dt" ] && ISS_EXITTIME=$(date +%s -d "$dt")

	if [ $ISS_EXITTIME -lt $LAST_START ]; then
		return 1;
	fi

	if [ $CRASH_LOG_VERSION -eq 0 ]; then
		ISS_EXITCODE=$(echo $last_line | cut -d ' ' -f4)
	else
		ISS_EXITCODE=$(echo $last_line | grep -Po '(?<=exit_code=) *[0-9-]*' | xargs)
	fi
}

#Usage: update_rty_shutdown
RTY_DIAGCODE=-1
update_rty_shutdown ()
{
	local sdinfo="$LOGS_DIR/shutdown.info.$BSCONFIG_IPORT"
	if [ -f $sdinfo ]; then
		local line=$(cat $sdinfo | tail -n 1)
		local split=(${line//,/ })
		[[ $line =~ "," ]] && RTY_DIAGCODE=${split[1]}
		return 0
	fi

	local rty_diagmsg
	[ $ISS_EXITCODE -le 0 ] && RTY_DIAGCODE=$((-$ISS_EXITCODE)) && rty_diagmsg="Killed by a signal"
	[ $ISS_EXITCODE -gt 0 ] && [ $ISS_EXITCODE -lt 500 ] && RTY_DIAGCODE=$((1000 + $ISS_EXITCODE)) && rty_diagmsg="Abnormal exit"

	# Update shutdown.info from loopscript
	[[ -n ${OPTS[shutdownfile]} ]] && echo "$ISS_EXITTIME,$RTY_DIAGCODE,$rty_diagmsg" > $sdinfo
}

#Usage: update_rty_datastatus <fpath to status file>
update_rty_datastatus ()
{
	if [ -s $1 ]; then #File exists
		egrep -q "Status ?: ?OK" $1 || return 0 # Non-OK status is already set
	fi

	local rty_global_log="$LOGS_DIR/current-global-rtyserver-$BSCONFIG_IPORT"
	#local rty_global_stderr="$LOGS_DIR/current-rtyserver-stderr-$BSCONFIG_IPORT"

	INDEX_FAILED=0 #false
	if [ $RTY_DIAGCODE -eq 6 ]; then #Assertion
		#
		# TEMPORARY: handle particular asserts as index failed (let's hope that RTYServer is going to be fixed eventually...)
		#
		local assertion_info=""
		local max_depth
		if [ -f $rty_global_log ]; then # Check the log for assertions
			max_depth=$(tac $rty_global_log | grep -n -m 1 'Daemon config parsed' | cut -f1 -d:)
		        [ ! -z "$max_depth" ] || max_depth=1000000000

			assertion_info=$(tac $rty_global_log | head -n $max_depth | grep -m 1 "CRITICAL")
			if echo $assertion_info | grep -q -e protofile.h ; then
				INDEX_FAILED=1  # library/protofile
			fi
		fi
	fi

	if [ $INDEX_FAILED -eq 1 ]; then
		echo "Status : FailedIndex" > $1
		echo "Info : \"Assertion failed\"" >> $1
	fi
}

write_stderr_timestamp ()
{
	local rty_global_stderr="$LOGS_DIR/current-rtyserver-stderr-$BSCONFIG_IPORT"
	echo >> $rty_global_stderr
	echo "$(date --iso-8601=seconds) loopscript: restart_script is done" >> $rty_global_stderr
}

check_rt_fail ()
{
	[ ! -s $1 ] && return 0; #Data status does not exist
	if fgrep -q "(RT)" $1; then # do not drop, just restart
		rm -f $1 #this cancels drop_index_if_failed
	elif fgrep -q "${RTINDEX_DIRECTORY}" $1; then # do not drop, just restart
		rm -f $1 #this cancels drop_index_if_failed
	fi
}

drop_index_if_failed ()
{
	[ ! -s $1 ] && return 0; #Data status does not exist

	local status=$(head -n 1 $1 | sed --posix 's/^Status *: *//')
	if [[ $status == "FailedIndex" ]]; then
		rm -f $1
		ls -1 $INDEX_DIRECTORY/ | grep -q -e '^index_' -e '^temp_' || return
		echo "FailedIndex. REMOVING indexes in $INDEX_DIRECTORY" >&2
		rm -rf $INDEX_DIRECTORY/*
	fi
}


#
# Parse arguments && options
#
[ ! -z "$BSCONFIG_IPORT" ] && [ ! -z "$BSCONFIG_INAME" ] && [ ! -z "$LOOP_SECTION" ] && [ ! -z "$INDEX_DIRECTORY" ] && [ ! -z "$STATE_ROOT" ] && [ ! -z "${RTINDEX_DIRECTORY}" ] || exit -2

ARGS="$@"
[[ -n "$ARGS" ]] || ARGS="" # Full set: verbose,shutdownfile,allow_nonrunnable,no_stderr,no_datastatus,no_drop,restart_on_rt_fail
declare -A "OPTS=($(echo $ARGS| sed -e 's:,: :g' -e 's/[^ ][^ ]*/[&]=0/g'))"

# -------------------------------------------------------------------------------------------------------------------------------------------------------------
#  Main routine
# -------------------------------------------------------------------------------------------------------------------------------------------------------------
[[ -n ${OPTS[verbose]} ]] && echo "  Options: ${!OPTS[@]}" >&2 && set -x


get_rty_startuptime

get_iss_exitcode $CRASH_LOG

update_rty_shutdown

DATA_STATUS="$STATE_ROOT/controller-state-$(($BSCONFIG_IPORT+3))"
if [[ -z ${OPTS[no_datastatus]} ]]
then
	update_rty_datastatus $DATA_STATUS
	[[ -n ${OPTS[restart_on_rt_fail]} ]] && check_rt_fail $DATA_STATUS
	[[ -z ${OPTS[no_drop]} ]] && drop_index_if_failed $DATA_STATUS
fi

# Don't allow nonrunnables (unless the option is set)
[[ -z ${OPTS[allow_nonrunnable]} ]] && [[ -f $DATA_STATUS ]] && rm $DATA_STATUS

# Write timestamp to stderr (unless the option is set) to handle rouge asserts
[[ -z ${OPTS[no_stderr]} ]] && write_stderr_timestamp

