#!/usr/local/bin/cbsd
#v10.0.6
MYARG=""
MYOPTARG=""
MYDESC="Execute first new task from taskd table, waits for complete and update errcode"
CBSDMODULE="taskd"
EXTHELP="wf_taskd"

. ${subrdir}/nc.subr
. ${cbsdinit}
. ${system}

mail_notify()
{
	[ -z "${platform}" ] && return 0
	[ -z "${MAIL_CMD}" ] && MAIL_CMD=$( which mail )
	[ -z "${MAIL_CMD}" ] && return 0

	local _msg=$( ${MKTEMP_CMD} )
	local _result

	trap "${RM_CMD} -f ${_msg}" HUP KILL INT ABRT BUS TERM EXIT

	[ -z "${lastoutput_num}" ] && lastoutput_num=0

	${CAT_CMD} > ${_msg} <<EOF
cmd: ${cmd}
runtime: ${runtime} minutes
errcode: ${_err}
EOF

	if [ ${lastoutput_num} -gt 0 -a -f "${logfile}" ]; then
		${CAT_CMD} >> ${_msg} <<EOF

last ${lastoutput_num} lines of task log (${logfile}):

$( ${TAIL_CMD} -n${lastoutput_num} ${logfile} )
EOF
	fi

	if [ ${_err} -eq 0 ]; then
		_result="completed"
	else
		_result="failed"
	fi

	${MAIL_CMD} -s "CBSD $nodename: task $id is ${_result}" ${CBSDRCPT} <<EOF
$( ${CAT_CMD} ${_msg} )
EOF

	${RM_CMD} -f ${_msg}
	trap "" HUP KILL INT ABRT BUS TERM EXIT
}


trynext_with_exclude()
{
	[ -z "${EXCLUDE}" ] && return 1

	A=$( cbsdsqlro cbsdtaskd "SELECT id,user,cmd,logfile,logtype,notify,owner,after,autoflush FROM taskd WHERE status='0' ${EXCLUDE} LIMIT 1" )

	# code 2 - no jobs anymore
	[ -z "${A}" ] && exit 2

	unset id user cmd logfile logtype notify owner after autoflush

	IFS="|"
	sqllist "${A}" id user cmd logfile logtype notify owner after autoflush
	IFS=" "
}


# return 0 on success
# return 2 when we have next job as dependency, and re-run searching for next job with excluding depended-job-id in this session
check_for_depend()
{
	[ ${after} -eq 0 ] && return 0

	dep_status=$( cbsdsqlro cbsdtaskd "SELECT status,errcode FROM taskd WHERE id='${after}'" )
	IFS="|"
	sqllist "${dep_status}" depstatus deperrcode
	IFS=" "

	if [ ${depstatus} -eq 0 -o ${depstatus} -eq 1 ]; then
		EXCLUDE="${EXCLUDE} AND id!=\"${id}\""
		return 2
	fi

	# only status=2 remain here, but check it anyway
	[ ${depstatus} -ne 2 ] && exit 2

	if [ ${deperrcode} -ne 0 ]; then
		# dependend job in incompleted, so mask current job is incompleted too
		_end_time=$( ${DATE_CMD} "+%Y%m%d%H%M%S" )
		_st_time=${_end_time}
		cbsdsqlrw cbsdtaskd "UPDATE taskd SET status=\"2\",errcode=\"${deperrcode}\",end_time=\"${_end_time}\" WHERE id=\"${id}\""
		runtime=$(( ( _end_time - _st_time ) / 60 ))
		readconf task.conf
		[ -n "${CBSDRCPT}" -a ${notify} -eq 1 ] && mail_notify
		exit 0
	fi
}

export workdir="${workdir}"
### MAIN ###
A=$( cbsdsqlro cbsdtaskd "SELECT id,user,cmd,logfile,logtype,notify,owner,after,autoflush FROM taskd WHERE status='0' LIMIT 1" )
# code 2 - no jobs anymore
[ -z "${A}" ] && exit 2

unset id user cmd logfile logtype notify owner after autoflush EXCLUDE

IFS="|"
sqllist "${A}" id user cmd logfile logtype notify owner after autoflush
IFS=" "

# check_for_depend return not 0 if next job is waiting for other job,
# so move to next before the end (errcode=0)
check_for_depend

if [ $? -eq 2 ]; then
	while [ 1 ]; do
		trynext_with_exclude
		check_for_depend
		[ $? -eq 0 ] && break
	done
fi

[ "${logtype}" = "auto" ] && logfile="/tmp/taskd.${id}.log"

_st_time=$( ${DATE_CMD} "+%Y%m%d%H%M%S" )
cbsdsqlrw cbsdtaskd "UPDATE taskd SET status=\"1\",st_time=\"${_st_time}\",logfile=\"${logfile}\" WHERE id=\"${id}\""
echo "spawntask ${id} ${logfile} ${cmd}"
spawntask ${id} ${logfile} ${cmd} > /dev/null 2>&1
_err=$?
_end_time=$( ${DATE_CMD} "+%Y%m%d%H%M%S" )

# SQLite3 locking? try to restry
for i in $( ${SEQ_CMD} 5 ); do
	cbsdsqlrw cbsdtaskd "UPDATE taskd SET status=\"2\",errcode=\"${_err}\",end_time=\"${_end_time}\" WHERE id=\"${id}\""
	sleep 0.5
	A=$( cbsdsqlro cbsdtaskd SELECT status FROM taskd WHERE id=\"${id}\" LIMIT 1 | ${AWK_CMD} '{printf $1}' )
	[ "${A}" = "2" ] && break
done

runtime=$(( ( _end_time - _st_time ) / 60 ))

readconf task.conf

#determine email for this owner
eval CBSDRCPT=\${${owner}_rcpt}
[ -n "${CBSDRCPT}" -a ${notify} -eq 1 ] && mail_notify

case "${autoflush}" in
	0)
		;;
	1)
		if [ ${_err} -eq 0 ]; then
			cbsdsqlrw cbsdtaskd "DELETE FROM taskd WHERE id=\"${id}\""
			[ -r "${logfile}" ] && ${RM_CMD} -f ${logfile}
		fi
		;;
	2)
		echo "Remove $id"
		cbsdsqlrw cbsdtaskd "DELETE FROM taskd WHERE id=\"${id}\""
		[ -r "${logfile}" ] && ${RM_CMD} -f ${logfile}
		;;
esac

exit 0
