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

PROG="$(basename ${0})"

tool_output_dir="${1}"
if [[ ! -d "${tool_output_dir}" ]]; then
    printf -- "%s: invalid tool output directory, '%s'\n" "${PROG}" "${tool_output_dir}" >&2
    exit 1
fi

interval="${2}"
if [[ -z "${interval}" ]]; then
    printf -- "%s: missing required 'interval' argument\n" "${PROG}" >&2
    exit 1
fi

pid_to_jstack="${3}"
if [[ -z "${pid_to_jstack}" ]]; then
    printf -- "%s: missing PID to jstack\n" "${PROG}" >&2
    exit 1
fi

command -v jstack > /dev/null
if [[ ${?} -ne 0 ]]; then
    printf -- "%s: missing 'jstack' command\n" "${PROG}" >&2
    exit 1
fi

jstack_log="${tool_output_dir}/jstack-threads.log"

if [[ "${pid_to_jstack}" == "0" ]]; then
    pid_to_jstack=""
fi
pattern="${4}"
if [[ -z "${pattern}" ]]; then
    pattern="java"
fi

rc=0
while [[ ${rc} -eq 0 ]]; do
    # get java pids running on host.
    jvm_pids="$(pgrep "${pattern}") ${pid_to_jstack}"

    for jvm_pid in ${jvm_pids}; do
	# map pid to process name for jstack output.
	ls -A /proc/${jvm_pid}/cmdline > /dev/null 2>&1
	if [[ ${?} -eq 0 ]]; then
	    pname="$(echo "${jvm_pid}-$(cat /proc/${jvm_pid}/cmdline)")"
	else
	    pname="${jvm_pid}"
	fi
	jstack_stdout_file=${tool_output_dir}/jstack-${pname}-stdout.txt

	# check if containerized.
	cnt=$(grep -cF 'user.slice' /proc/${jvm_pid}/cgroup 2> /dev/null)
	if [[ ${?} -eq 0 && ${cnt} -eq 0 ]]; then
	    jpid=$(grep hsperfdata /proc/${jvm_pid}/task/${jvm_pid}/maps | awk -F "hsperfdata" '{print $2}' | sed "s/[^0-9]//g")
	    nsenter --target ${jvm_pid} --mount --uts --ipc --net --pid jstack ${jpid} > ${jstack_log}
	else
	    jstack ${jvm_pid} > ${jstack_log}
	fi

	ru=$(grep -c RUNN ${jstack_log} 2> /dev/null)
	b=$(grep -c BLOCK ${jstack_log} 2> /dev/null)
	w=$(grep -c WAITING ${jstack_log} 2> /dev/null)

	echo "$(date "+%s.%N"),${ru},${b},${w}" >> "${jstack_stdout_file}"

        rm ${jstack_log}
    done

    sleep ${interval}
    rc=${?}
done
