#!/bin/sh

# Copyright © 2009-2018 Holger Levsen (holger@layer-acht.org)
# Copyright © 2011-2012 Andreas Beckmann (anbe@debian.org)
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <https://www.gnu.org/licenses/>


. /usr/share/piuparts/lib/read_config.sh
. /usr/share/piuparts/lib/write_log.sh

get_config_value MASTER global master-directory
get_config_value SECTIONS global sections
get_config_value HTDOCS global output-directory

STARTDATE=$(date -u +%s)
OUTPUT=$(mktemp)
LOG_OUTPUT=$(mktemp)

#
# reschedule 200 oldest log files, if they are older than 180 days
# reschedule 25 oldest fail log files, if they are older than 30 days
# delete $reschedule-old-count oldest logfiles, if they are scheduled
#   for recycling and older than $expire-old-days
#   and $expire-old-days > $reschedule-old-days
#
get_config_value EXPIRE_AGE global expire-old-days 0
get_config_value AGE        global reschedule-old-days 180
get_config_value COUNT      global reschedule-old-count 200
get_config_value EXPIRE_FAIL_AGE global expire-fail-days 0
get_config_value FAIL_AGE   global reschedule-fail-days 30
get_config_value FAIL_COUNT global reschedule-fail-count 25
get_config_value AUTO_RESCHEDULE	global auto-reschedule yes


if [ -n "$*" ]; then
	SECTIONS="$*"
fi


RECENT=$(mktemp)
touch -d "2 days ago" "$RECENT"
is_recent()
{
	local stamp
	stamp="$1"
	if [ -f "$stamp" ] && [ "$stamp" -nt "$RECENT" ]; then
		return 0
	fi
	return 1
}


TMPLIST=$(mktemp)
list_logs()
{
	__AGE="$1"
	__COUNT="$2"
	shift 2
	find "$@" -name "*.log" -mtime +$__AGE \
		| tac \
		| xargs --no-run-if-empty -n99999 -s1999999 ls -dt \
		> $TMPLIST
	tail -n $__COUNT $TMPLIST
}


TOTAL=0
TOTAL_EXPIRED=0
UNSCHEDULE=0
TOTAL_QUEUED=0
LOGS=$(mktemp)
OBSOLETE=$(mktemp)
EXPIRED=$(mktemp)
UNSORTED=$(mktemp)
QUEUED=$(mktemp)
OLDPWD=$(pwd)
for SECTION in $SECTIONS ; do
	test -d $MASTER/$SECTION || continue
	cd $MASTER/$SECTION
	mkdir -p pass fail bugged affected recycle

	recycle_was_idle=
	find recycle/ -name '*.log' > $QUEUED
	if [ ! -s $QUEUED ]; then
		recycle_was_idle="empty"
	elif [ -f "recycle.stamp" ] && [ "recycle.stamp" -nt "recycle" ]; then
		recycle_was_idle="idle"
	fi

	# Clean up obsolete rescheduling requests
	for log in $(find recycle/ -name '*.log' | cut -d"/" -f2) ; do
		for dir in pass bugged affected fail ; do
			test ! -e "$dir/$log" || continue 2
		done
		echo "recycle/$log"
	done | sort > $OBSOLETE

	# Reschedule old logs
	>$LOGS
	>$EXPIRED
	get_config_value RESCHEDULE $SECTION auto-reschedule $AUTO_RESCHEDULE
	if [ "$RESCHEDULE" = "yes" ]; then
		get_config_value _EXPIRE_AGE $SECTION expire-old-days $EXPIRE_AGE
		get_config_value _AGE        $SECTION reschedule-old-days $AGE
		get_config_value _COUNT      $SECTION reschedule-old-count $COUNT
		get_config_value _EXPIRE_FAIL_AGE $SECTION expire-fail-days $EXPIRE_FAIL_AGE
		get_config_value _FAIL_AGE   $SECTION reschedule-fail-days $FAIL_AGE
		get_config_value _FAIL_COUNT $SECTION reschedule-fail-count $FAIL_COUNT
		# FIXME: we ignore bugged here - ptyhon-bts is really the way to go
		>$UNSORTED
		case $_EXPIRE_AGE in
			+*) _EXPIRE_AGE=$(($_AGE$_EXPIRE_AGE)) ;;
		esac
		if [ "$_EXPIRE_AGE" -gt "$_AGE" ]; then
		    if [ -n "$recycle_was_idle" ]; then
			list_logs $_EXPIRE_AGE      $_COUNT      pass fail affected >> $UNSORTED
		    fi
		fi
		case $_EXPIRE_FAIL_AGE in
			+*) _EXPIRE_FAIL_AGE=$(($_FAIL_AGE$_EXPIRE_FAIL_AGE)) ;;
		esac
		if [ "$_EXPIRE_FAIL_AGE" -gt "$_FAIL_AGE" ]; then
			list_logs $_EXPIRE_FAIL_AGE $_FAIL_COUNT      fail affected >> $UNSORTED
		fi
		for log in $(sort -u $UNSORTED) ; do
			# the log needs to be scheduled for recycling before it gets expired
			test -f "recycle/${log#*/}" && echo "$log"
		done > $EXPIRED
		>$UNSORTED
		if is_recent idle.stamp ; then
			list_logs $_AGE          $_COUNT                pass fail affected >> $UNSORTED
		fi
		list_logs $_FAIL_AGE $_FAIL_COUNT      fail affected >> $UNSORTED
		for log in $(sort -u $UNSORTED) ; do
			# skip if already scheduled
			test -f "recycle/${log#*/}" || echo "$log"
		done > $LOGS
	fi
	find recycle/ -name '*.log' > $QUEUED

	if [ -s $LOGS ] || [ -s $OBSOLETE ] || [ -s $EXPIRED ] || [ -s $QUEUED ] ; then
		echo "#########################################################" >> $OUTPUT
		echo >> $OUTPUT
		RCOUNT=$(wc -l $LOGS | awk '{ print $1 }')
		TOTAL=$(($TOTAL + $RCOUNT))
		ECOUNT=$(wc -l $EXPIRED | awk '{ print $1 }')
		TOTAL_EXPIRED=$(($TOTAL_EXPIRED + $ECOUNT))
		UCOUNT=$(wc -l $OBSOLETE | awk '{ print $1 }')
		UNSCHEDULE=$(($UNSCHEDULE + $UCOUNT))
		echo "$SECTION: $RCOUNT rescheduled, $ECOUNT expired, $UCOUNT obsolete${recycle_was_idle:+ (recycle-was-${recycle_was_idle})}" >> $OUTPUT
		if [ -s $LOGS ]; then
			ls -dtl $(cat $LOGS) >> $OUTPUT
			ln -f $(cat $LOGS) recycle/
		fi
		if [ -s $EXPIRED ]; then
			ls -dtl $(cat $EXPIRED) >> $OUTPUT
			rm -fv $(cat $EXPIRED) >> $OUTPUT
		fi
		if [ -s $OBSOLETE ]; then
			rm -fv $(cat $OBSOLETE) >> $OUTPUT
		fi
		find recycle/ -name '*.log' > $QUEUED
		NUM_QUEUED=$(wc -l < $QUEUED)
		TOTAL_QUEUED=$(($TOTAL_QUEUED + $NUM_QUEUED))
		echo "queued: $NUM_QUEUED$(is_recent idle.stamp || echo " not-idle")" >> $OUTPUT
		echo >> $OUTPUT
	fi
	cd $OLDPWD
done
rm $RECENT
rm $TMPLIST
rm $LOGS
rm $OBSOLETE
rm $EXPIRED
rm $UNSORTED
rm $QUEUED

FINALDATE=$(date -u +%s)
RUNTIME=$(date -u -d "0 $FINALDATE seconds - $STARTDATE seconds" +%T)
(
	echo "$(date -u)"
	echo "Runtime: $RUNTIME"
	echo
	if [ "$TOTAL" -gt "0" ]; then
		echo "Rescheduled $TOTAL logs."
	fi
	if [ "$TOTAL_EXPIRED" -gt "0" ]; then
		echo "Deleted $TOTAL_EXPIRED expired logs."
	fi
	if [ "$UNSCHEDULE" -gt "0" ]; then
		echo "Cancelled $UNSCHEDULE outdated rescheduling requests."
	fi
	if [ "$TOTAL_QUEUED" -gt "0" ]; then
		echo "Queued logs: $TOTAL_QUEUED"
	fi
	echo
	cat $OUTPUT
	echo "##################################################################################################################" >> $OUTPUT
	echo "##################################################################################################################" >> $OUTPUT
	echo
) > $LOG_OUTPUT
publish_logs $LOG_OUTPUT "" $HTDOCS reschedule_oldest_logs
rm -f $OUTPUT
