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

P=fio-bench
DEFAULT_VERSION=2.99
. $SHELLPACK_INCLUDE/common.sh
TIME_CMD=`which time`
if [ "$TIME_CMD" = "" ]; then
        TIMEFORMAT="%2Uuser %2Ssystem %Relapsed %P%%CPU"
        TIME_CMD="time"
fi
FIO_CMD_OPTIONS=

# Basic argument parser
TASKSET_SERVER=
TASKSET_CLIENT=
SERVERSIDE_COMMAND=none
SERVERSIDE_NAME=`date +%Y%m%d-%H%M-%S`

while [ "$1" != "" ]; do
	case "$1" in
	-v)
		VERSION=$2
		shift 2
		;;
	--serverside-command)
		SERVERSIDE_COMMAND=$2
		shift 2
		;;
	--serverside-name)
		SERVERSIDE_NAME=$2
		shift 2
		;;
	--install-only)
		INSTALL_ONLY=yes
		shift
		;;
	--install-force)
		INSTALL_FORCE=yes
		shift
		;;
	--cmdline)
		FIO_CMD_OPTIONS=$2
		shift 2
		;;
	--type)
		FIO_TEST_TYPE=$2
		shift 2
		;;
	--max_jobs)
		FIO_MAX_JOBS=$2
		shift 2
		;;
	--runtime)
		FIO_RUNTIME=$2
		shift 2
		;;
	--size)
		FIO_SIZE=$2
		shift 2
		;;
	--ioengine)
		FIO_IOENGINE=$2
		shift 2
		;;
	--direct)
		FIO_DIRECT=$2
		shift 2
		;;
	--iodepth)
		FIO_IODEPTH=$2
		shift 2
		;;
	--reusefiles)
		FIO_REUSE_FILES=$2
		shift 2
		;;
	*)
		echo Unrecognised option: $1
		shift
	esac
done
if [ "$TASKSET_SERVER" != "" ]; then
	echo TASKSET_SERVER: $TASKSET_SERVER
	echo TASKSET_CLIENT: $TASKSET_CLIENT
fi
if [ -z "$VERSION" ]; then
	VERSION=$DEFAULT_VERSION
fi

if [ "$INSTALL_FORCE" = "yes" ]; then
	rm -rf $SHELLPACK_SOURCES/fio-${VERSION}
fi
if [ ! -d $SHELLPACK_SOURCES/fio-${VERSION}-installed ]; then
	mmtests_activity source-install
	$SHELLPACK_INCLUDE/shellpack-install-fio -v ${VERSION}  || die fio install script returned error
	mmtests_activity source-installed
fi
cd $SHELLPACK_SOURCES/fio-${VERSION}-installed || die Failed to cd to fio install directory
if [ "$INSTALL_ONLY" = "yes" ]; then
	echo fio installed only as requested.
	exit $SHELLPACK_SUCCESS
fi

# Include monitor hooks
. $SHELLPACK_INCLUDE/include-monitor.sh

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
#### Description Flexible IO tester
#### Details fio-bench 24
