#!/usr/bin/bash
# -*- mode: shell-script; indent-tabs-mode: t; sh-basic-offset: 4; sh-indentation: 4; tab-width: 4 -*-

script_path="$(dirname ${0})"
script_name="$(basename ${0})"
pbench_bin="$(realpath -e ${script_path}/..)"

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

# This script will post-process all tools that belong to a specific group.
# This is typically called by a benchmark script when some activity needs to
# monitored.

# Defaults
def_group="default"
group="${def_group}"
dir=""

function usage {
	printf "The following are required:\n\n"
	printf -- "\t-g str --group=str, str = a tool group used in a benchmark\n"
	printf -- "\t                          (the default group is '%s')\n\n" "${def_group}"
	printf -- "\t-d str --dir=str, str = a directory where %s\n" "${script_name}"
	printf -- "\t                        will store and process data\n"
}

# Process options and arguments

opts=$(getopt -q -o d:g: --longoptions "dir:,group:" -n "getopt.sh" -- "${@}")
if [[ ${?} -ne 0 ]]; then
	printf "\n%s: you specified an invalid option\n\n" "${script_name}"
	usage >&2
	exit 1
fi
eval set -- "${opts}"
while true; do
	case "${1}" in
	-g|--group)
		shift
		if [[ -n "${1}" ]]; then
			group="${1}"
			shift
		fi
		;;
	-d|--dir)
		shift
		if [[ -n "${1}" ]]; then
			dir="${1}"
			shift
		fi
		;;
	--)
		shift
		break
		;;
	esac
done

if [[ -z "${group}" ]]; then
	printf -- "ERROR: required tool group parameter missing.\n\n" >&2
	usage >&2
	exit 1
fi
if [[ -z "${dir}" ]]; then
	printf -- "ERROR: required directory argument missing.\n\n" >&2
	usage >&2
	exit 1
fi

# This tool group's directory which stores the list of tools and their
# options, etc.
tool_group_dir=$(verify_tool_group ${group})
if [[ ${?} -ne 0 || -z "${tool_group_dir}" ]]; then
	exit 1
fi

# The tool group's directory which stores tool output for all hosts.
tool_output_dir="${dir}/tools-${group}"
if [[ ! -d "${tool_output_dir}" ]]; then
	error_log "[${script_name}] expected tool output directory, \"${tool_output_dir}\", does not exist"
	exit 1
fi

# We run `pbench-list-tools', and parse its output
# to determine which host runs which tools with what options.
let failures=0
pbench-list-tools --group ${group} --with-option 2>/dev/null | while read hostentry ;do
	# Parse an entry from the output of `pbench-list-tools` above.
	# The format is: "group: <group>; host: <host> [, label: <label>]; tools: <tool> <options>, <tool> <options>, ...
	IFS=';' read group_spec host_spec tools_spec <<<"${hostentry}"
	IFS=',' read hostpart labelpart <<<"${host_spec}"
	IFS=':' read dummy host junk <<<"${hostpart}"
	IFS=':' read dummy label junk <<<"${labelpart}"
	IFS=':' read dummy tools_entry junk <<<"${tools_spec}"
	host=${host# *}
	label=${label# *}
	# Associative array: the keys are the tool names, and the values are the options
	declare -A tools=()
	IFS=',' read -a otools <<<"${tools_entry# *}"
	for tool in ${otools[@]} ;do
		IFS=' ' read -a atool <<<${tool}
		tools[${atool[0]}]=${atool[@]:1}
	done

	if [[ -z "${label}" ]] ;then
		host_tool_output_dir="${tool_output_dir}/${host}"
	else
		host_tool_output_dir="${tool_output_dir}/${label}:${host}"
	fi
	if [[ -d "${host_tool_output_dir}" ]]; then
		for tool_name in ${!tools[@]} ;do
			if [[ ! -x "${pbench_bin}/tool-scripts/${tool_name}" ]]; then
				# Ignore unrecognized tools
				continue
			fi
			if [[ "${tool_name}" == "node-exporter" || "${tool_name}" == "dcgm" || "${tool_name}" == "pcp" || "${tool_name}" == "pcp-transient" ]]; then
                                # To be removed when converted to python
                                continue
			fi
			tool_options="${tools[${tool_name}]}"
			${pbench_bin}/tool-scripts/${tool_name} --postprocess --dir="${host_tool_output_dir}" ${tool_options} >> ${host_tool_output_dir}/postprocess.log 2>&1
			if [[ ${?} -ne 0 ]]; then
				cat ${host_tool_output_dir}/postprocess.log >&2
				(( failures++ ))
			fi
		done
	else
		warn_log "[${script_name}] Missing tool output directory, '${host_tool_output_dir}'"
		(( failures++ ))
	fi
done

exit ${failures}
