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

. ${subrdir}/nc.subr
. ${tools}
cixinit
. ${system}

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

	local _msg=
	capture _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

	cbsdsqlro_vars 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 "${id}" ] && exit 2
}

# 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

	cbsdsqlro_vars cbsdtaskd "SELECT status,errcode FROM taskd WHERE id='${after}'" depstatus deperrcode

	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
		capture _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 ###
cbsdsqlro_vars cbsdtaskd "SELECT id,user,cmd,logfile,logtype,notify,owner,after,autoflush FROM taskd WHERE status='0' LIMIT 1"
[ -z "${id}" ] && exit 2
EXCLUDE=

# 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"

capture _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=$?
capture _end_time ${DATE_CMD} "+%Y%m%d%H%M%S"

# SQLite3 locking? try to restry
for ((i=1; i<=5; i++)); do
	cbsdsqlrw cbsdtaskd "UPDATE taskd SET status='2',errcode='${_err}',end_time='${_end_time}' WHERE id='${id}'"
	sleep 0.5
	cbsdsqlro_vars cbsdtaskd "SELECT status FROM taskd WHERE id='${id}' LIMIT 1"
	[ "${status}" = "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)
		true
		;;
	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
