#!/bin/sh
pgm="${0##*/}"		# Program basename
progdir="${0%/*}"	# Program directory

alt_path=
env_file=
run_test=

while getopts "d:e:p:t:" opt; do
	case "${opt}" in
		d) debug="${OPTARG}" ;;
		e) env_file="${OPTARG}" ;;
		p) alt_path="${OPTARG}" ;;
		t) run_test="${OPTARG}" ;;
	esac
	shift $(($OPTIND - 1))
done

set -e
. /usr/local/etc/spacevm-perf-fio.conf
. /usr/local/share/spacevm/fio-subr/SpaceVM.subr
. /usr/local/share/spacevm/fio-subr/color.subr
. /usr/local/share/spacevm/fio-subr/system.subr
. /usr/local/share/spacevm/fio-subr/network.subr
set +e

print_stats()
{
	${ECHO} "${H2_COLOR}Read: ${R_MB}${N1_COLOR} MB/s ( ${H2_COLOR}${R_KB}${N1_COLOR} KB/s )${N0_COLOR}"
	${ECHO} "${H2_COLOR}Write: ${W_MB}${N1_COLOR} MB/s ( ${H2_COLOR}${W_KB}${N1_COLOR} KB/s )${N0_COLOR}"
}


## MAIN
init_color

## FIO_ MACROS/PARAMS
FIO_PARAMS="
DIRECTORY
RUNTIME
BS
IOENGINE
DIRECT
NUMJOBS
SIZE
IODEPTH
RWMIXREAD
"

# AUTO_XXX vars ?
[ -n "${env_file}" -a -r "${env_file}" ] && . ${env_file}

if [ -z "${run_test}" ]; then
	# try to get vars from image boot
	_AUTO_PROFILE=$( kenv mfsbsd.fio_auto_profile 2>/dev/null )
	ret=$?

	if [ ${ret} -eq 0 -a -n "${_AUTO_PROFILE}" ]; then
		case "${_AUTO_PROFILE}" in
			all|manual)
				AUTO_PROFILE=
				;;
			*)
				AUTO_PROFILE="${_AUTO_PROFILE}"
				;;
		esac
	fi
else
	AUTO_PROFILE="${run_test}"
fi

if [ -z "${AUTO_PROFILE}" -o "${AUTO_PROFILE}" = "manual" ]; then
	# SYNC
	echo "${CURL_CMD} -o /tmp/index.conf ${BENCH_INDEX_URL}"
	${CURL_CMD} -s -o /tmp/index.conf ${BENCH_INDEX_URL} > /tmp/curl.$$ 2>&1
	ret=$?

	trap "${RM_CMD} -f /tmp/curl.$$" HUP INT ABRT BUS TERM EXIT

	if [ ${ret} -ne 0 ]; then
		echo "curl error: ${ret}"
		${CAT_CMD} /tmp/curl.$$
		exit 1
	else
		echo "fetched config:"
		cat /tmp/index.conf
		echo
	fi

	_tmpdir=$( ${MKTEMP_CMD} -d )
	_tmpfile=$( ${MKTEMP_CMD} )

	index=1

	_def_method=$( ${CAT_CMD} /tmp/index.conf | ${SORT_CMD} -n | while read a; do
		p1=${a%%:*}
		p2=${a##*:}
		[ -z "${p1}" ] && continue
		[ ${index} -eq 1 ] && printf "${p1}"

		echo "0:${p1}:" >> ${_tmpdir}/${p1}.item
		${ECHO} "${H3_COLOR}Description: ${p2}${N0_COLOR}" > ${_tmpdir}/${p1}.descr
		index=$(( index + 1 ))
	done )

	subject="Select test profile (${_def_method}):"
	${ECHO} "${N1_COLOR}${subject}${N0_COLOR}"
	#/usr/local/bin/spacevm-select-item ${_tmpdir} ${_tmpfile} item ${_def_method}
	/usr/local/bin/spacevm-select-item ${_tmpdir} ${_tmpfile} item ${_def_method} 2>/dev/null
	_ret=$?
	${RM_CMD} -rf ${_tmpdir}

	if [ ${_ret} -ne 0 ]; then
		# break or cancel
		choose="0"
	fi

	PROFILE=$( ${CAT_CMD} ${_tmpfile} )
	${RM_CMD} ${_tmpfile} /tmp/index.conf
else
	# autotests
	PROFILE="${AUTO_PROFILE}"
fi
TYPE="fio"

#unset TYPE PROFILE
#. /tmp/test.conf

#if [ -z "${TYPE}" ]; then
#	echo "no such benchmark TYPE specified: ${BENCH_CONF_URL}"
#	exit 1
#fi
if [ -z "${PROFILE}" ]; then
	echo "no such benchmark PROFILE specified: ${PROFILE}"
	exit 1
fi

# inherit PROFILE for test chains
export AUTO_PROFILE="${PROFILE}"

if [ -n "${env_file}" ]; then
	if [ -r "${env_file}" ]; then
		${MV_CMD} ${env_file} ${env_file}.tmp
		${GREP_CMD} -v ^AUTO_PROFILE ${env_file}.tmp > ${env_file}
		${RM_CMD} -f ${env_file}.tmp
	fi
	echo "AUTO_PROFILE=\"${PROFILE}\"" >> ${env_file}
fi

if [ -r /etc/os-release ]; then
	NAME=
	PRETTY_NAME=
	. /etc/os-release
	if [ -n "${PRETTY_NAME}" ]; then
		OPSYS="${PRETTY_NAME}"
	elif [ -n "${NAME}" ]; then
		OPSYS="${NAME}"
	else
		OPSYS="${OS}"
	fi
fi

BENCH_TPL="${checkin_server}/${TYPE}/${PROFILE}.fio"
BENCH_CONFIG="${checkin_server}/${TYPE}/${PROFILE}.config"
BENCH_DEFAULTS_CONFIG="${checkin_server}/${TYPE}/defaults.config"

echo "TPL: ${BENCH_TPL}, CFG: ${BENCH_CONFIG}"

${CURL_CMD} -s -o /tmp/defaults.config ${BENCH_DEFAULTS_CONFIG} 2>&1 | ${TEE_CMD} -a /tmp/curl.$$
ret=$?
if [ ${ret} -ne 0 ]; then
	echo "curl error: ${ret}"
	${CAT_CMD} /tmp/curl.$$
	exit 1
fi
${RM_CMD} /tmp/curl.$$
[ -r /tmp/defaults.config ] && . /tmp/defaults.config

# per-template extra/custom
${CURL_CMD} -s -o /tmp/${PROFILE}.config ${BENCH_CONFIG} 2>&1 | ${TEE_CMD} -a /tmp/curl.$$
ret=$?
if [ ${ret} -eq 0 ]; then
	${RM_CMD} /tmp/curl.$$
fi

[ -r /tmp/${PROFILE}.config ] && . /tmp/defaults.config
[ -r /tmp/profile.conf.tpl ] && ${RM_CMD} -f /tmp/profile.conf.tpl
${CURL_CMD} -s -o /tmp/profile.conf.tpl ${BENCH_TPL} 2>&1 | ${TEE_CMD} -a /tmp/curl.$$
ret=$?
if [ ${ret} -ne 0 ]; then
	echo "curl error: ${ret}"
	${CAT_CMD} /tmp/curl.$$
	exit 1
fi

${RM_CMD} /tmp/curl.$$
${GREP_CMD} -q "^rw=" /tmp/profile.conf.tpl
ret=$?
if [ ${ret} -ne 0 ]; then
	echo "broken/wrong profile: ${BENCH_TPL}, no rw= ?"
	exit 1
fi

# get from env first
if [ -z "${FIO_AUTO_RWMIXREAD}" ]; then
	if [ -n "${FIO_AUTO_PROFILE}" ]; then
		# unattended
		FIO_RWMIXREAD="${FIO_AUTO_RWMIXREAD}"
	else
		# read from per-profile/custom?
		_FIO_AUTO_RWMIXREAD=$( kenv mfsbsd.fio_auto_rwmixread 2>/dev/null )
		ret=$?

		if [ ${ret} -eq 0 -a -n "${_FIO_AUTO_RWMIXREAD}" ]; then
			FIO_RWMIXREAD="${_FIO_AUTO_RWMIXREAD}"
			FIO_AUTO_RWMIXREAD="${_FIO_AUTO_RWMIXREAD}"
		fi
	fi
else
	FIO_RWMIXREAD="${FIO_AUTO_RWMIXREAD}"
fi

[ -z "${FIO_RWMIXREAD}" ] && FIO_RWMIXREAD="50"

# interactive
if [ -z "${FIO_AUTO_PROFILE}" ]; then
	if [ -z "${FIO_AUTO_RWMIXREAD}" ]; then
		case "${PROFILE}" in
			rw|randrw)
				for i in 1 2 3; do
					${ECHO} "${N1_COLOR}mixed workload is specified: ${N2_COLOR}${PROFILE}${N1_COLOR}"
					${ECHO} "${N1_COLOR}Please adjust/confirm RWMIXREAD values (Default: ${N2_COLOR}${FIO_RWMIXREAD}${N1_COLOR})${N0_COLOR}"
					${ECHO} "${N1_COLOR} (For example, --rwmixread=${N2_COLOR}30${N1_COLOR} would mean that ${N2_COLOR}30%${N1_COLOR} of the I/O will be reads and ${N2_COLOR}70%${N1_COLOR} will be writes${N0_COLOR}"
					read _RWMIXREAD
					if [ -z "${_RWMIXREAD}" ]; then
						${ECHO} "${N1_COLOR}Confirmed: ${N2_COLOR}${FIO_RWMIXREAD}${N0_COLOR}"
						break
					fi
					case "${_RWMIXREAD}" in
						''|*[!0-9]*)
							${ECHO} "${N1_COLOR}Wrong valued, please use 0-100 values${N0_COLOR}"
							continue
							;;
						*)
							if [ ${_RWMIXREAD} -gt 100 ]; then
								${ECHO} "${N1_COLOR}Wrong valued, please use 0-100 values${N0_COLOR}"
								continue
							fi
							${ECHO} "${N1_COLOR}Adjusted: ${N2_COLOR}${_RWMIXREAD}${N0_COLOR}"
							FIO_RWMIXREAD="${_RWMIXREAD}"
							break
							;;
					esac
				done
				;;
		esac
	else
		FIO_RWMIXREAD="${FIO_AUTO_RWMIXREAD}"
	fi
else
	FIO_RWMIXREAD="${FIO_AUTO_RWMIXREAD}"
fi

[ -z "${FIO_RWMIXREAD}" ] && FIO_RWMIXREAD="50"

TYPE_UPPER=$( echo "${TYPE}" | ${TR_CMD} '[:lower:]' '[:upper:]' )

eval MY_PARAMS="\$${TYPE_UPPER}_PARAMS"

# overrides
#FIO_DIRECTORY="/storages/local${FIO_DIRECTORY}"
#FIO_DIRECTORY="/storages/zfs/z150_12${FIO_DIRECTORY}"
#FIO_IOENGINE="libaio"

echo $MY_PARAMS

# overrides
if [ -n "${alt_path}" ]; then
	echo "ALTPOOL: ${alt_path}"
	FIO_DIRECTORY="${alt_path}"
fi

if [ -n "${MY_PARAMS}" ]; then
	for i in ${MY_PARAMS}; do
		eval VAL="\$${TYPE_UPPER}_${i}"
#		echo "X $VAL"
		if [ -z "${VAL}" ]; then
			${ECHO} "${W1_COLOR}fioloop: params empty: ${N2_COLOR}${i}${N0_COLOR}"
			exit 1
		fi
#		${SED_CMD} -i'' "s#%%i%%#${VAL}#g" /tmp/profile.conf.tpl
		${SED_CMD} -i${sed_delimer}'' -Ees:"%%${i}%%":"${VAL}":g /tmp/profile.conf.tpl
	done
else
	${ECHO} "${W1_COLOR}No PARAMS vars${N0_COLOR}"
	exit 1
fi

${MV_CMD} /tmp/profile.conf.tpl /tmp/profile.fio
echo "FIO_DIR: ${FIO_DIRECTORY}"
[ -d /tmp/spacevm-perf-fio/tests ] && ${RM_CMD} -rf /tmp/spacevm-perf-fio/tests
${MKDIR_CMD} -p /tmp/spacevm-perf-fio/tests/${FIO_BS}

# VEIL
#IN_USE=$( df -h /storages/local/tmp/test/job.0.0 | ${GREP_CMD} -v Filesystem | ${AWK_CMD} '{printf $5}' )
#echo "pool:${FIO_DIRECTORY},inuse:${IN_USE}" > /tmp/spacevm-perf-fio/tests/extra_info.txt

echo "CHECK for: ${FIO_DIRECTORY}/job.0.0"
if [ -n "${FIO_DIRECTORY}" -a "${FIO_DIRECTORY}" != "/" ]; then
	if [ -d "${FIO_DIRECTORY}" ]; then
		if [ -r "${FIO_DIRECTORY}/job.0.0" ]; then
			echo "Clean dir: ${FIO_DIRECTORY}"
			${RM_CMD} -rf "${FIO_DIRECTORY}"
		else
			echo "no such dir for clean?: ${FIO_DIRECTORY}"
		fi
	fi
fi
${MKDIR_CMD} -p "${FIO_DIRECTORY}"

CBSD_PERF_DISTRO=
[ -r /etc/rc.conf ] && . /etc/rc.conf
if [ "${CBSD_PERF_DISTRO}" = "1" ]; then
	${CP_CMD} -a /tmp/profile.fio /tmp/profile.bak
	${GREP_CMD} -v directory /tmp/profile.bak > /tmp/profile.fio
	if [ -z "${FIO_SELECTED_DISK}" ]; then
		echo "No such FIO_SELECTED_DISK"
		exit 1
	fi
	echo "filename=${FIO_SELECTED_DISK}" >> /tmp/profile.fio

	i=$( echo ${FIO_SELECTED_DISK} | ${SED_CMD} s#/dev/##g )
	dsk_info ${i}
	conv2human ${BSIZE}
	SIZE="${human_val}"
	echo "raw disk: ${FIO_SELECTED_DISK},size: ${SIZE}, model: ${DSK_INFO}" > /tmp/spacevm-perf-fio/tests/extra_info.txt
fi

# VEIL
#IN_USE=$( df -h /storages/local/tmp/test/job.0.0 | ${GREP_CMD} -v Filesystem | ${AWK_CMD} '{printf $5}' )
#echo "pool:${FIO_DIRECTORY},inuse:${IN_USE}" > /tmp/spacevm-perf-fio/tests/extra_info.txt


if [ -r ${FIO_DIRECTORY}.extra_info.txt ]; then
	${CP_CMD} ${FIO_DIRECTORY}.extra_info.txt /tmp/spacevm-perf-fio/tests/extra_info.txt
fi


echo "${FIO_CMD} --output-format=json --output=/tmp/spacevm-perf-fio/tests/${FIO_BS}/${PROFILE}-iodepth-${FIO_IODEPTH}-numjobs-${FIO_NUMJOBS}.json /tmp/profile.fio"

# randread-iodepth-1-numjobs-2
${FIO_CMD} --output-format=json --output=/tmp/spacevm-perf-fio/tests/${FIO_BS}/${PROFILE}-iodepth-${FIO_IODEPTH}-numjobs-${FIO_NUMJOBS}.json /tmp/profile.fio
_ret=$?

#echo "/tmp/spacevm-perf-fio/tests/profile.txt

echo "profile=\"${PROFILE}\"" > /tmp/spacevm-perf-fio/tests/fio.conf

${GREP_CMD} "^[a-z]*=" /tmp/profile.fio | while read a; do
	p1=${a%%=*}
	p2=${a##*=}
	case "${p1}" in
		runtime|bs|ioengine|numjobs|size|iodepth|rwmixread)
			echo "${a}" >> /tmp/spacevm-perf-fio/tests/fio.conf
			;;
		*)
			;;
	esac
done

# print result
_json_data="/tmp/spacevm-perf-fio/tests/${FIO_BS}/${PROFILE}-iodepth-${FIO_IODEPTH}-numjobs-${FIO_NUMJOBS}.json"

READ_BW_BYTES=$( ${CAT_CMD} ${_json_data} | ${JQ_CMD} '.jobs[0].read.bw_bytes' | ${TR_CMD} -d '"' )
WRITE_BW_BYTES=$( ${CAT_CMD} ${_json_data} | ${JQ_CMD} '.jobs[0].write.bw_bytes' | ${TR_CMD} -d '"' )
RUNTIME=$( ${CAT_CMD} ${_json_data} | ${JQ_CMD} '.jobs[0]."job options".runtime' | ${TR_CMD} -d '"' )

R_KB=$(( READ_BW_BYTES / 1024 ))
R_MB=$(( READ_BW_BYTES / 1024 / 1024 ))
W_KB=$(( WRITE_BW_BYTES / 1024 ))
W_MB=$(( WRITE_BW_BYTES / 1024 / 1024 ))

echo
echo
${ECHO} "${H1_COLOR}======== [${PROFILE}] [bs:${FIO_BS},depth:${FIO_DEPTH},jobs:${FIO_NUMJOBS},rwmixread:${FIO_RWMIXREAD}] result ========:${N0_COLOR}"
print_stats | ${COLUMN_CMD} -t

#printf "${N1_COLOR}Read: ${H2_COLOR}%-10s${N1_COLOR} MB/s ( ${H2_COLOR}%-16s${N1_COLOR} KB/s )${N0_COLOR}\n" ${R_MB} ${R_KB}
# ${H2_COLOR}${R_MB}${N1_COLOR} MB/s ( ${H2_COLOR}${R_KB}${N1_COLOR} KB/s )${N0_COLOR}"
#printf "${N1_COLOR}Write: ${H2_COLOR}{${W_MB}${N1_COLOR} MB/s ( ${H2_COLOR{${W_KB}${N1_COLOR} KB/s )${N0_COLOR}"
echo

# Clean
if [ -n "${FIO_DIRECTORY}" -a "${FIO_DIRECTORY}" != "/" ]; then
	if [ -d "${FIO_DIRECTORY}" ]; then
		if [ -r "${FIO_DIRECTORY}/job.0.0" ]; then
			echo "Clean dir: ${FIO_DIRECTORY}"
			${RM_CMD} -rf "${FIO_DIRECTORY}"
		else
			echo "no such dir for clean?: ${FIO_DIRECTORY}"
		fi
	fi
fi

exit ${_ret}
