#!/usr/bin/bash

if [ "$SERVICE" != "mds" ]; then
	echo "$SERVICE is not supported by service helper"
	exit 255
fi

CONFIG_DIR="/etc/vstorage"
CLUSTERS_DIR="$CONFIG_DIR/clusters"
CLUSTER_DIR="$CLUSTERS_DIR/$CLUSTER_NAME"
CONFIG_FILE="$SERVICE.config"
CLUSTER_ROOT="/mnt/vstorage"
CLUSTER_LOGS_PATH=".logs"
DEF_FILENUM=50
CLUSTER_LOGS_FILENUM=$DEF_FILENUM
LOGROTATE_WAIT_DELAY=60

# load cluster config
[ -f "$CONFIG_DIR/$CONFIG_FILE" ] && source "$CONFIG_DIR/$CONFIG_FILE"
[ -f "$CONFIG_DIR/service.config" ] && source "$CONFIG_DIR/service.config"
[ -f "$CLUSTER_DIR/$CONFIG_FILE" ] && source "$CLUSTER_DIR/$CONFIG_FILE"
[ -f "$CONTROL_DIR/$CONFIG_FILE" ] && source "$CONTROL_DIR/$CONFIG_FILE"

CLUSTER_LOGS_ROOT=$CLUSTER_ROOT/$CLUSTER_LOGS_PATH
LOGS_DST=$CLUSTER_LOGS_ROOT/$SERVICE/$SERVICEID
LOGS_SRC=$DAEMON_DIR/logs
LOGS_HEAD_LINK=$LOGS_SRC/$SERVICE.log.head
LOGS_HEAD_FILE=""
START_DELAY=10
WAIT_DELAY=$LOGROTATE_WAIT_DELAY
BASE_IDX=100

README=$(cat << END
This is the folder for storing storage logs rotated out from the local filesystem.
The rotation is performed by /usr/libexec/vstorage/vstorage-service-helper script
launched by /usr/libexec/vstorage/vstorage-service on service start. One can completely
disable rotation by removing (renaming) vstorage-service-helper script. Other options:
 * To temporary disable rotation one can create .disable file in this folder
 * To set the number of files to keep one can write it to .filenum file in this folder.
   The default is $DEF_FILENUM.

The following variables may be set in service configuration files to change defaults:
 SVC_HELPER           - the path to the service helper script (now $0),
                        set it to empty string to disable service helper execution
 CLUSTER_ROOT         - the cluster mount point used (now $CLUSTER_ROOT)
 CLUSTER_LOGS_PATH    - the logs root folder relative to the CLUSTER_ROOT (now $CLUSTER_LOGS_PATH)
 CLUSTER_LOGS_FILENUM - the number of logs to keep (now $CLUSTER_LOGS_FILENUM)
 LOGROTATE_WAIT_DELAY - number of seconds to wait between rotation checks (now $LOGROTATE_WAIT_DELAY)

The logs root folder ($CLUSTER_LOGS_ROOT) is not created automatically. The script will wait
in case it does not exist. The lower level directories are created by the script automatically.
For troubleshooting use systemctl status command for the storage service. It will show running
vstorage-service-helper script and the log of its operation.
END
)

function check_prerequisites()
{
	if ! mountpoint -q "$CLUSTER_ROOT"; then
		echo "cluster $CLUSTER_NAME is not mounted at $CLUSTER_ROOT"
		while ! mountpoint -q "$CLUSTER_ROOT"; do sleep $WAIT_DELAY; done
		echo "cluster $CLUSTER_NAME is mounted at $CLUSTER_ROOT"
		sleep $START_DELAY
	fi
	if [ ! -d "$CLUSTER_LOGS_ROOT" ]; then
		echo "cluster logs root folder $CLUSTER_LOGS_ROOT does not exist"
		while [ ! -d "$CLUSTER_LOGS_ROOT" ]; do sleep $WAIT_DELAY; done
		echo "cluster logs root folder $CLUSTER_LOGS_ROOT is found"
	fi
	if [ ! -d "$LOGS_DST" ]; then
		echo "cluster logs folder $LOGS_DST does not exist, creating"
		mkdir -p "$LOGS_DST"
		if [ ! -d "$LOGS_DST" ]; then
			echo "failed to create cluster logs folder $LOGS_DST, aborting"
			exit 255
		fi
		echo "cluster logs folder $LOGS_DST created"
	fi
	if [ -f "$CLUSTER_LOGS_ROOT/.disabled" ] || [ -f "$CLUSTER_LOGS_ROOT/$SERVICE/.disabled" ]; then
		echo "logs rotation to the cluster is temporary disabled"
		while [ -f "$CLUSTER_LOGS_ROOT/.disabled" ] || [ -f "$CLUSTER_LOGS_ROOT/$SERVICE/.disabled" ]; do sleep $WAIT_DELAY; done
		echo "logs rotation to the cluster is enabled"
	fi
	if [ ! -L "$LOGS_HEAD_LINK" ]; then
		echo "$LOGS_HEAD_LINK does not exist"
		while [ ! -L "$LOGS_HEAD_LINK" ]; do sleep $WAIT_DELAY; done
		echo "$LOGS_HEAD_LINK is found"
	fi
	LOGS_HEAD_FILE=$(readlink ${LOGS_HEAD_LINK})
	if [ ! -f "$LOGS_HEAD_FILE" ]; then
		echo "log head file $LOGS_HEAD_FILE does not exist"
		while [ ! -f "$LOGS_HEAD_FILE" ]; do sleep $WAIT_DELAY; done
		echo "log head file $LOGS_HEAD_FILE is found"
	fi
}

function idle_wait()
{
	sleep $WAIT_DELAY
	check_prerequisites
}

function copy_head()
{
	local TAG=$1
	local DSL_LINK=$2
	local DST_FILE="$LOGS_DST/$SERVICE.log.tail.$TAG"
	echo "copy $LOGS_HEAD_FILE to $DST_FILE"
	cp -f "$LOGS_HEAD_FILE" "$DST_FILE"
	ln -f -s "$DST_FILE" "$DSL_LINK"
}

function dst_cleanup()
{
	local FILENUM=$1
	local EXT=$2
	local TAIL_FILE=$3
	local PREFIX="$LOGS_DST/$SERVICE.log."
	local SUFFIX=".$EXT"
	local PREFIX_SZ=${#PREFIX}
	local SUFFIX_SZ=${#SUFFIX}
	local TOP_IDX=$(($BASE_IDX+$FILENUM-1))
	for f in $PREFIX*$SUFFIX ; do
		local IDX=${f::-$SUFFIX_SZ}
		IDX=${IDX:$PREFIX_SZ}
		if [ $IDX -ge $TOP_IDX ]; then
			echo "removing $f"
			rm -f "$f"
		fi
	done
	for f in $LOGS_DST/$SERVICE.log.tail.* ; do
		if [ "$f" != "$TAIL_FILE" ]; then
			echo "removing $f"
			rm -f "$f"
		fi
	done
}

function rotate_logs()
{
	local FILENUM=$1
	local EXT=$2
	local TAIL_FILE=$3
	local IDX=$(($BASE_IDX+1))
	local TOP_IDX=$(($BASE_IDX+$FILENUM-1))
	while [ $IDX -le $TOP_IDX ]; do
		if [ ! -f "$LOGS_DST/$SERVICE.log.$IDX.$EXT" ]; then
			break
		fi
		IDX=$(($IDX+1))
	done
	if [ $IDX -gt $TOP_IDX ]; then
		dst_cleanup $FILENUM $EXT $TAIL_FILE
		IDX=$TOP_IDX
	fi
	while [ $IDX -gt $BASE_IDX ]; do
		local OLD_IDX=$(($IDX-1))
		if [ $OLD_IDX -ne $BASE_IDX ]; then
			mv "$LOGS_DST/$SERVICE.log.$OLD_IDX.$EXT" "$LOGS_DST/$SERVICE.log.$IDX.$EXT"
		else
			mv "$TAIL_FILE" "$LOGS_DST/$SERVICE.log.$IDX.$EXT"
		fi
		IDX=$OLD_IDX
	done
}

sleep $START_DELAY

check_prerequisites

echo "$README" > $CLUSTER_LOGS_ROOT/.readme
echo "$README" > $CLUSTER_LOGS_ROOT/$SERVICE/.readme

echo "$SERVICE$SERVICEID helper started $LOGS_SRC -> $LOGS_DST"

for (( ; ; ))
do
	LOGS_EXT="${LOGS_HEAD_FILE##*.}"
	LOGS_HEAD_TAG=$(stat -c '%i-%Y' "$LOGS_HEAD_FILE")
	DST_TAIL_LINK=${LOGS_DST}/${SERVICE}.log.${BASE_IDX}.${LOGS_EXT}
	FILENUM=$CLUSTER_LOGS_FILENUM

	[ -f "$CLUSTER_LOGS_ROOT/.filenum" ] && FILENUM=$(cat "$CLUSTER_LOGS_ROOT/.filenum" | tr -d '[:space:]')
	[ -f "$CLUSTER_LOGS_ROOT/$SERVICE/.filenum" ] && FILENUM=$(cat "$CLUSTER_LOGS_ROOT/$SERVICE/.filenum" | tr -d '[:space:]')
	[ $FILENUM -lt 2 ] && FILENUM=2

	if [ ! -L "$DST_TAIL_LINK" ]; then
		echo "$DST_TAIL_LINK not found"
		copy_head $LOGS_HEAD_TAG $DST_TAIL_LINK
		idle_wait
		continue
	fi

	DST_TAIL_FILE=$(readlink ${DST_TAIL_LINK})
	if [ ! -f "$DST_TAIL_FILE" ]; then
		echo "$DST_TAIL_FILE not found"
		copy_head $LOGS_HEAD_TAG $DST_TAIL_LINK
		idle_wait
		continue
	fi

	DST_TAIL_TAG="${DST_TAIL_FILE##*.}"

	if [ "$LOGS_HEAD_TAG" != "$DST_TAIL_TAG" ]; then
		rotate_logs $FILENUM $LOGS_EXT $DST_TAIL_FILE
		copy_head $LOGS_HEAD_TAG $DST_TAIL_LINK
		echo "logs rotated successfully"
	fi

	idle_wait
done
