#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: t; sh-basic-offset: 8; sh-indentation: 8; sh-indent-for-case-alt: + -*-

# pbench-iozone 0.01 initial version
# TODO
# 1) write results in pbench standard file names and formats
# 2) add support to run mulitple samples and get stddev
# 3) add support for multiple local or remote copies of benchmark running concurrently
# 4) add support for binding copies of benchmark to numa nodes

# script to run the iozone benchmark test

# usage ./pbench-iozone --config="string" --targets=/location/file --number_of_runs --file_sizes=1,2,3 --record_sizes=1,2,4
# file_sizes are in GB, record sizes are in MB

script_path=`dirname $0`
script_name=`basename $0`
pbench_bin="`cd ${script_path}/..; /bin/pwd`"

# source the base script
. "$pbench_bin"/base

benchmark_rpm=$script_name
benchmark="iozone"
if [[ -z "${benchmark_bin}" ]]; then
	benchmark_bin="$(resolve_benchmark_bin "${benchmark}")"
	if [[ -z "${benchmark_bin}" ]]; then
		error_log "[${script_name}] ${benchmark} executable not found on PATH=${PATH}"
		exit 1
	fi
fi
ver="$(getconf.py version ${benchmark})"
if [[ -z "${ver}" ]]; then
	error_log "${script_name}: package version is missing in config file"
	exit 1
fi

# Every bench-script follows a similar sequence:
# 1) process bench script arguments
# 2) ensure the right version of the benchmark is installed
# 3) gather pre-run state
# 4) run the benchmark and start/stop perf analysis tools
# 5) gather post-run state
# 6) postprocess benchmark data
# 7) postprocess analysis tool data

# supported test types

# 0=write/rewrite
# 1=read/re-read
# 2=random-read/write
# 3=read-backwards
# 4=re-write-record
# 5=stride-read
# 6=fwrite/re-fwrite
# 7=fread/re-fread
# 8=random_mix
# 9=pwrite/re-pwrite
# 10=pread/re-pread
# 11=pwritev/re-pwritev
# 12=preadv/re-preadv

# Check "iozone -h" for full help

supported_test_types="0,1,2,3,4,5,6,7,8,10,11,12"
config=""
targets="/tmp/iozone"
file_sizes="1,2"
record_sizes="1,2"

number_of_runs=10
iteration=1
tool_group=default
sysinfo="default"

function usage {
	printf    "\tThe following options are available:\n\n"
	printf -- "\t\t-C str --config=str name of the test config\n"
	printf -- "\t\t-d str[,str] --targets=str[,str]\n"
	printf    "\t\t\tfile to use for iozone test in format /dir/file - this is iozone : -f option\n"
	printf -- "\t\t-s str[,str] --file_sizes=str[,str]\n"
	printf    "\t\t\tone or more file_sizes sizes to use\n"
	printf -- "\t\t-r str[,str] --record_sizes=str[,str]\n"
	printf    "\t\t\tone or more record_sizes sizes to use\n"
	printf -- "\t\t-n str[,str] --number_of_runs=str[,str]\n"
	printf    "\t\t\tnumber of iozone runs - default is 10 runs\n"
	printf -- "\t\t--tool-group=str\n"
	printf -- "\t\t--sysinfo=str, str= comma separated values of sysinfo to be collected\n"
	printf -- "\t\t                    available: $(pbench-collect-sysinfo --options)\n"
}

opts=$(getopt -q -o C:d:hn:r:s: --longoptions "config:,targets:,file_sizes:,record_sizes:,number_of_runs:,tool-group:,sysinfo:,help" -n "getopt.sh" -- "$@");
if [ $? -ne 0 ]; then
	printf -- "${script_name} $*\n"
	printf -- "\n"
	printf -- "\tunrecognized option specified\n\n"
	usage
	exit 1
fi

eval set -- "$opts";
while true; do
	case "$1" in
	        -C|--config)
	        shift;
	        if [ -n "$1" ]; then
	                config="$1"
	                shift;
	        fi
	        ;;
		-d|--targets)
		shift;
		if [ -n "$1" ]; then
			targets="$1"
			shift;
		fi
		;;

		-s|--file_sizes)
		shift
		if [ -n "$1" ]; then
			file_sizes="$1"
			shift;
		fi
		;;
		-r|--record_sizes)
		shift
		if [ -n "$1" ]; then
			record_sizes="$1"
			shift;
		fi
		;;
	        --sysinfo)
		shift;
		if [ -n "$1" ]; then
			sysinfo="$1"
			shift;
		fi
		;;

		-n|--number_of_runs)
		shift
		if [ -n "$1" ]; then
			number_of_runs="$1"
			shift;
		fi
		;;

		-h|--help)
		usage
		exit 0
		;;

		--tool-group)
		shift
		if [ -n "$1" ]; then
			tool_group="$1"
			shift;
		fi
		;;

	        --)
	        shift;
	        break;
	        ;;

	        *)
	        error_log "Encountered unrecognized parameter, what happened? [$1]"
	        usage
	        exit 1;
	        ;;
	esac
done
verify_common_bench_script_options $tool_group $sysinfo

## Ensure the right version of the benchmark is installed

if check_install_rpm $benchmark_rpm $ver; then
	debug_log "[$script_name]$benchmark_rpm is installed"
else
	debug_log "[$script_name]$benchmark_rpm installation failed, exiting"
	exit 1
fi

benchmark_fullname="${benchmark}_${config}_${date_suffix}"
export benchmark_run_dir="$pbench_run/${benchmark_fullname}"
benchmark_iterations="${benchmark_run_dir}/.iterations"
benchmark_summary_file="$benchmark_run_dir/$benchmark-summary.txt"

mkdir -p $benchmark_run_dir/.running

# now that the benchmark_run_dir directory exists, we can initialize the iterations file
> ${benchmark_iterations}

export benchmark config
pbench-collect-sysinfo --group=$tool_group --dir=$benchmark_run_dir --sysinfo=$sysinfo beg
pbench-metadata-log --group=$tool_group --dir=$benchmark_run_dir beg
# on abnormal exit, make sure that the metadata log exists and is complete.
trap "pbench-metadata-log --group=$tool_group --dir=$benchmark_run_dir int" INT QUIT

benchmark_results_dir="$benchmark_run_dir/$iteration/sample1"
echo $iteration >> $benchmark_iterations
mkdir -p $benchmark_results_dir

pbench-start-tools --group=$tool_group --dir=$benchmark_results_dir

# not 100% sure what is best run logic here, either to permute record sizes or over file sizes...

for file_size in $(echo $file_sizes | sed -e s/,/" "/g); do
	for record_size in $(echo $record_sizes | sed -e s/,/" "/g); do
		for run in $(seq 1 ${number_of_runs}); do
			$benchmark_bin -i0 -i1 -i2 -i3 -i4 -i5 -i6 -i7 -i8 -i9 -i10 -i11 -i12  -c -e -f $targets -s ${file_size}g -r ${record_size}m >> $benchmark_results_dir/$(hostname)_$run.iozone
		done
	done
done

pbench-stop-tools --group=$tool_group --dir=$benchmark_results_dir
pbench-postprocess-tools --group=$tool_group --dir=$benchmark_results_dir
ln -s sample1 $benchmark_run_dir/$iteration/reference-result

pbench-metadata-log --group=$tool_group --dir=$benchmark_run_dir end
pbench-collect-sysinfo --group=$tool_group --dir=$benchmark_run_dir --sysinfo=$sysinfo end

rmdir $benchmark_run_dir/.running
