#!/bin/bash

SYNO_FILE_STATS_PATH="/proc/fs/nfsd/syno_file_stats"
SYNO_FILE_STATS_FREQ=900
SYNO_FILE_STATS_OPT=1
SYNO_UDC_SUB_COLLECTOR="/usr/syno/sbin/synonfs_udc_sub_collector.py"

declare -A VIRTUAL_KEYS
VIRTUAL_KEYS["vmware"]=".vmdk .lck"
VIRTUAL_KEYS["microsoft"]=".vhd .vhdx"
VIRTUAL_KEYS["oracle"]=".vdi"
VIRTUAL_KEYS["parallels"]=".hdd"

declare -A VIRTUAL_VENDOR_STATS
for v in "${!VIRTUAL_KEYS[@]}"; do
	VIRTUAL_VENDOR_STATS[${v}]=0
done

function get_key_int()
{
	local File="$1"
	local Key="$2"
	local Value
	local ret=0
	Value=$(/usr/syno/bin/synogetkeyvalue "$File" "$Key")
	if [ "x$Value" = "x" ]; then
		Value=0
		ret=1
	fi
	echo -n "$Value"
	return $ret
}

function get_key()
{
	local File="$1"
	local Key="$2"
	local Value
	local ret=0
	Value=$(/usr/syno/bin/synogetkeyvalue "$File" "$Key")
	if [ "x$Value" = "x" ]; then
		Value=""
		ret=1
	fi
	echo -n "$Value"
	return $ret
}

function get_virtual_vendor_by_key()
{
	local SEARCH_KEY="${1}"

	VENDOR=""
	for v in "${!VIRTUAL_KEYS[@]}"; do
		for k in ${VIRTUAL_KEYS[$v]}; do
			if [ "${k}" = "${SEARCH_KEY}" ]; then
				VENDOR="${v}"
				break
			fi
		done
	done
}

function nfs_get_virtul_vendor_stats()
{
	[ ! -f ${SYNO_FILE_STATS_PATH} ] && return

	SYNO_FILE_STATS=$(cat ${SYNO_FILE_STATS_PATH} | tail -n +2)

	for line in ${SYNO_FILE_STATS}; do
		KEY=$(echo ${line} | cut -d : -f 1)
		CNT=$(echo ${line} | cut -d : -f 2)
		get_virtual_vendor_by_key ${KEY}
		[ "${VENDOR}" = "" ] && continue
		VIRTUAL_VENDOR_STATS[${VENDOR}]=$[${VIRTUAL_VENDOR_STATS[${VENDOR}]}+${CNT}]
	done
}

function nfs_is_using_virtualization()
{
	NFS_IS_USING_VIRTUALIZATION=false
	for v in "${!VIRTUAL_VENDOR_STATS[@]}"; do
		if [ ${VIRTUAL_VENDOR_STATS[${v}]} -gt 0 ]; then
			NFS_IS_USING_VIRTUALIZATION=true
			break
		fi
	done
}

function nfs_virtual_vendor_in_use_json()
{
	JSON_STR="{"
	COMMA=""
	for v in "${!VIRTUAL_VENDOR_STATS[@]}"; do
		if [ ${VIRTUAL_VENDOR_STATS[${v}]} -gt 0 ]; then
			JSON_STR=${JSON_STR}"${COMMA}\"${v}\":\"yes\""
		else
			JSON_STR=${JSON_STR}"${COMMA}\"${v}\":\"no\""
		fi
		[ "${COMMA}" = "" ] && COMMA=","
	done
	JSON_STR=${JSON_STR}"}"
	NFS_VIRTUAL_VENDOR_IN_USE_JSON=${JSON_STR}
}

function nfs_get_virtualization_info()
{
	nfs_get_virtul_vendor_stats
	nfs_is_using_virtualization
	nfs_virtual_vendor_in_use_json
}

function nfs_get_udc_stat()
{
	$SYNO_UDC_SUB_COLLECTOR --save
	NFS_CONNECTION_STAT_JSON=$($SYNO_UDC_SUB_COLLECTOR --dump_conn)
	NFS_ERRORS_STAT_JSON=$($SYNO_UDC_SUB_COLLECTOR --dump_err)
	NFS_LATENCY_HISTOGRAM_JSON=$($SYNO_UDC_SUB_COLLECTOR --dump_lat)
	$SYNO_UDC_SUB_COLLECTOR --reset
}

function nfs_gen_udc_json_str()
{
	# collect NFS settings
	if [ "enabled" = "$(synosystemctl get-enable-status nfs-server)" ]; then
		NFS_ENABLE="yes";
	else
		NFS_ENABLE="no";
	fi
	NFS_READ_SIZE=$(get_key_int /etc/nfs/syno_nfs_conf udp_read_size)
	NFS_WRITE_SIZE=$(get_key_int /etc/nfs/syno_nfs_conf udp_write_size)
	NFS_V4="$(get_key /etc/nfs/syno_nfs_conf nfsv4_enable)"
	NFS_MINOR_VER=$(get_key_int /etc/nfs/syno_nfs_conf nfs_minor_ver_enable)
	NFS_KERBEROS="$(get_key /etc/nfs/syno_nfs_conf kerberos_principal)"
	NFS_UMASK_ENABLE="$(get_key /etc/nfs/syno_nfs_conf nfs_unix_pri_enable)"
	if [ "${NFS_ENABLE}" = "yes" ] ; then
		NFS_CONN_NUM=$(cat /run/nfs_mount_list 2>/dev/null | /usr/bin/wc -l)
	else
		NFS_CONN_NUM=0
	fi
	nfs_get_virtualization_info
	nfs_get_udc_stat

	# generate json-format string for UDC
	UDC_RESULT="{"
	UDC_RESULT=${UDC_RESULT}"\"is_enable\":\"${NFS_ENABLE}\""
	UDC_RESULT=${UDC_RESULT}",\"udp_read_size\":${NFS_READ_SIZE}"
	UDC_RESULT=${UDC_RESULT}",\"udp_write_size\":${NFS_WRITE_SIZE}"
	UDC_RESULT=${UDC_RESULT}",\"nfsv4_enable\":\"${NFS_V4}\""
	UDC_RESULT=${UDC_RESULT}",\"nfs_minor_version\":${NFS_MINOR_VER}"
	if [ "x${NFS_KERBEROS}" = "x" ]; then
		UDC_RESULT=${UDC_RESULT}",\"nfs_kerberos_enable\":\"no\""
	else
		UDC_RESULT=${UDC_RESULT}",\"nfs_kerberos_enable\":\"yes\""
	fi
	if [ "${NFS_UMASK_ENABLE}" == "1" ]; then
		UDC_RESULT=${UDC_RESULT}",\"nfs_umask_enable\":\"yes\""
	else
		UDC_RESULT=${UDC_RESULT}",\"nfs_umask_enable\":\"no\""
	fi
	UDC_RESULT=${UDC_RESULT}",\"connection_num\":${NFS_CONN_NUM}"
	if [ "${NFS_IS_USING_VIRTUALIZATION}" = true ]; then
		UDC_RESULT=${UDC_RESULT}",\"is_using_virtualization\":\"yes\""
	else
		UDC_RESULT=${UDC_RESULT}",\"is_using_virtualization\":\"no\""
	fi
	UDC_RESULT=${UDC_RESULT}",\"virtualization_vendor_in_use\":${NFS_VIRTUAL_VENDOR_IN_USE_JSON}"
	UDC_RESULT=${UDC_RESULT}",\"connection\":${NFS_CONNECTION_STAT_JSON}"
	UDC_RESULT=${UDC_RESULT}",\"errors\":${NFS_ERRORS_STAT_JSON}"
	UDC_RESULT=${UDC_RESULT}",\"lat_hist\":${NFS_LATENCY_HISTOGRAM_JSON}"
	UDC_RESULT=${UDC_RESULT}"}"
	echo -n "${UDC_RESULT}"
}

function nfs_set_syno_file_stats()
{
	[ ! -f ${SYNO_FILE_STATS_PATH} ] && return

	SPACE=""
	NR_KEYS=0
	ALL_KEYS=""
	for v in "${!VIRTUAL_VENDOR_STATS[@]}"; do
		for k in ${VIRTUAL_KEYS[$v]}; do
			ALL_KEYS=${ALL_KEYS}"${SPACE}${k}"
			NR_KEYS=$[${NR_KEYS} + 1]
			[ "${SPACE}" == "" ] && SPACE=" "
		done
	done

	[ ${NR_KEYS} -eq 0 ] && return

	echo "${SYNO_FILE_STATS_FREQ} ${SYNO_FILE_STATS_OPT} ${NR_KEYS} ${ALL_KEYS}" > ${SYNO_FILE_STATS_PATH}
}

function nfs_clean_syno_file_stats()
{
	[ ! -f ${SYNO_FILE_STATS_PATH} ] && return
	echo 0 > ${SYNO_FILE_STATS_PATH}
}

case $1 in
	--json-str)
		nfs_gen_udc_json_str
		ret=$?
	;;
	--set-syno-file-stats)
		nfs_set_syno_file_stats
		ret=$?
	;;
	--clean-syno-file-stats)
		nfs_clean_syno_file_stats
		ret=$?
	;;
	--dump-syno-file-stats)
		cat ${SYNO_FILE_STATS_PATH}
		ret=$?
	;;
	*)
		echo "Usage: $0"
		echo "  --json-str"
		echo "  --set-syno-file-stats"
		echo "  --clean-syno-file-stats"
		echo "  --dump-syno-file-stats"
	;;
esac
exit $ret
