#!/bin/bash
# This script installs fio and runs a fio job

###SHELLPACK preamble fio-bench 2.99
FIO_CMD_OPTIONS=

###SHELLPACK parseargBegin
###SHELLPACK parseargInstall
###SHELLPACK parseargParam --cmdline                FIO_CMD_OPTIONS
###SHELLPACK parseargParam --type		    FIO_TEST_TYPE
###SHELLPACK parseargParam --max_jobs		    FIO_MAX_JOBS
###SHELLPACK parseargParam --runtime		    FIO_RUNTIME
###SHELLPACK parseargParam --size		    FIO_SIZE
###SHELLPACK parseargParam --ioengine		    FIO_IOENGINE
###SHELLPACK parseargParam --direct		    FIO_DIRECT
###SHELLPACK parseargParam --iodepth		    FIO_IODEPTH
###SHELLPACK parseargParam --reusefiles		    FIO_REUSE_FILES
###SHELLPACK parseargEnd
###SHELLPACK monitor_hooks

###SHELLPACK check_install_required fio-${VERSION}
###SHELLPACK init_complete

FIO_IO_PATTERNS="write read rw randread randwrite randrw"

if [ "$FIO_CMD_OPTIONS" != "" ]; then
	monitor_pre_hook $LOGDIR_RESULTS $SIZE

	./fio --directory="$SHELLPACK_DATA" --minimal \
		--write_lat_log $LOGDIR_RESULTS/fio $FIO_CMD_OPTIONS 2>&1 |
		tee $LOGDIR_RESULTS/fio.log || \
		die "Failed to have fun with fio"

	rm -rf $SHELLPACK_DATA/*
	monitor_post_hook $LOGDIR_RESULTS $SIZE
	gzip $LOGDIR_RESULTS/fio*.log
	exit $SHELLPACK_SUCCESS
fi

# default values for scaling test
FIO_MAX_JOBS=${FIO_MAX_JOBS:-64}
FIO_RUNTIME=${FIO_RUNTIME:-15}
FIO_SIZE=${FIO_SIZE:-1G}
FIO_IOENGINE=${FIO_IOENGINE:-libaio}
FIO_DIRECT=${FIO_DIRECT:-1}
FIO_IODEPTH=${FIO_IODEPTH:-1}
FIO_REUSE_FILES=${FIO_REUSE_FILES:-no}

function remove_fio_files() {
	local logfile=$1 name=$2
	local d files

	for d in ${SHELLPACK_DATA_DIRS[*]}; do
		files=$(ls ${d}/${name}.*[0-9].[0-9]* 2>/dev/null)
		if [ $? -eq 0 ]; then
			files=$(ls ${d}/${name}.*[0-9].[0-9]*)
			rm ${files}
		fi
	done
}

function one_pass() {
	local logfile=$1 rw=$2 size=$3 qd=$4 rt=$5 njobs=$6 bs=$7 name=$8

	if [ "${FIO_REUSE_FILES}" != "yes" ]; then
		remove_fio_files ${logfile} ${name}
	fi
	echo "fio --directory=${DIRS} --rw=${rw} --name=${name} \
	    --size=${size} --group_reporting \
	    --output-format=terse --terse-version=5 \
	    --ioengine=${FIO_IOENGINE} --direct=${FIO_DIRECT} \
	    --iodepth=${qd} --runtime=${rt} --numjobs=${njobs} \
	    --blocksize=${bs}" | tee -a ${logfile}
	./fio --directory=${DIRS} --rw=${rw} --name=${name} \
	    --size=${size} --group_reporting \
	    --output-format=terse --terse-version=5 \
	    --ioengine=${FIO_IOENGINE} --direct=${FIO_DIRECT} \
	    --iodepth=${qd} --runtime=${rt} --numjobs=${njobs} \
	    --blocksize=${bs} | tee -a ${logfile} \
	    || die Failed to have fun with fio
}

function rand_read_write() {
	local rw size qd=$1 rt=30 njobs=$2 bs=4k name=fio-ssd
	local logfile=${LOGDIR_RESULTS}/fio-ssd-rand-jobs_${njobs}-qd_${qd}-bs_${bs}
	for rw in randread randwrite; do
		for size in 1G 2G 4G 8G 16G; do
			one_pass ${logfile} ${rw} ${size} ${qd} ${rt} ${njobs} ${bs} ${name}
		done
	done
}

function seq_write_read() {
	local rw size qd=$1 rt=10 njobs=1 bs=128k name=fio-ssd
	local logfile=${LOGDIR_RESULTS}/fio-ssd-seq-jobs_${njobs}-qd_${qd}-bs_${bs}
	for rw in write read; do
		for size in 8G 16G 32G; do
			one_pass ${logfile} ${rw} ${size} ${qd} ${rt} ${njobs} ${bs} ${name}
		done
	done
}

function scaling_test() {
	local rw size=${FIO_SIZE} qd=${FIO_IODEPTH} rt=${FIO_RUNTIME} bs=4k name=fio-scaling
	local logfile i njobs=0 p_njobs=0
	for rw in ${FIO_IO_PATTERNS}; do
		logfile=${LOGDIR_RESULTS}/fio-scaling-${rw}
		for i in $(seq 0 ${NUMCPUS}); do
			njobs=$[2**${i}*${DIR_NR}]
			if [ ${njobs} -gt ${FIO_MAX_JOBS} ]; then
				break
			fi
			if [ ${njobs} -gt ${NUMCPUS} ]; then
				njobs=${NUMCPUS}
			fi
			if [ ${njobs} -eq ${p_njobs} ]; then
				break
			fi
			p_njobs=${njobs}
			one_pass ${logfile} ${rw} ${size} ${qd} ${rt} ${njobs} ${bs} ${name}
		done
	done
}

case $FIO_TEST_TYPE in
scaling)
	DIR_NR=${#SHELLPACK_DATA_DIRS[*]}
	DIRS=`echo ${SHELLPACK_DATA_DIRS[*]} | tr " " ":"`
	monitor_pre_hook $LOGDIR_RESULTS $FIO_READWRITE
	scaling_test
	monitor_post_hook $LOGDIR_RESULTS $FIO_READWRITE
	;;
ssd)
	DIR_NR=${#SHELLPACK_DATA_DIRS[*]}
	DIRS=$(echo ${SHELLPACK_DATA_DIRS[*]} | tr " " ":")
	monitor_pre_hook ${LOGDIR_RESULTS}
	# 4k, QD  1, jobs 1 (randread, randwrite)
	rand_read_write 1 1
	# 4k, QD 32, jobs 4 (randread, randwrite)
	rand_read_write 32 4
	# 128k, QD 2, jobs 1
	seq_write_read 2
	# 128k, QD 4, jobs 1
	seq_write_read 4
	monitor_post_hook ${LOGDIR_RESULTS}
	;;
*)
	die Unrecognised test type $FIO_TEST_TYPE
	;;
esac

gzip $LOGDIR_RESULTS/fio*.log
exit $SHELLPACK_SUCCESS
