#! /bin/sh
# PCP QA Test No. 412
# Test out wrapping on libpcp/interp
#
#  Test the creation and reading of an archive created using pmlogger(1) and
#  and pmval(1).
#
# Copyright (c) 1995-2002 Silicon Graphics, Inc.  All Rights Reserved.
#

seq=`basename $0`
echo "QA output created by $seq"

# get standard environment, filters and checks
. ./common.product
. ./common.filter
. ./common.check

signal=$PCP_BINADM_DIR/pmsignal
status=1	# failure is the default!
trap "rm -f $tmp.*; exit \$status" 0 1 2 3 15

_wrap_off()
{
    dowrap=0
    unset PCP_COUNTER_WRAP
    echo "--- Wrapping OFF ---"
}

_wrap_on()
{
    dowrap=1
    PCP_COUNTER_WRAP=
    export PCP_COUNTER_WRAP
    echo "--- Wrapping ON ---"
}

_setTimeZone () {
    MONTH=`date +%m`
    
    if [ $MONTH -lt 7 ]
    then
    	#  Daylight savings on from Sunday 1st January to
    	#  Sunday 5th March
        TZ="EST-10EDT-11,1/0,64/3"
    else
    	#  Daylight savings on from Sunday 29th October to Wednesday
    	#  "32nd" December (including the end of the extra day for
    	#  leap years)
    	TZ="EST-10EDT-11,302/2,367/0"
    fi
    
    #  This is what the specification should be normally, but
    #  it won't work because the start date of daylight savings
    #  is AFTER the end date.  libc.so hates this, so I hate
    #  libc.so.
    #TZ="EST-10EDT-11,302/2,64/3"
    
    echo $TZ
}

#
# Reset the sample agent so that we start from a known
# point for the wrap metrics
#
_reset()
{
    pmstore sample.control -1 >/dev/null
    $sudo $signal -a -s HUP pmcd
    _wait_for_pmcd
}

#
# Simulate interpolated fetching with/without wrapping
# Assumes doing it for sample.wrap.ulong
#
_process_log()
{
    rm -f $tmp.dbg
    # t is reporting time in seconds
    #
    t=`echo $starttime | sed -e 's/.*://'`
    sed <$tmp.dump \
	-e '/^[0-9]/{
s/[0-9][0-9]* metrics*//
N
s/\n/ /
}' \
    | $PCP_AWK_PROG -v dowrap=$dowrap -v half_delta=$half_delta -v t=$t '
      BEGIN {
	    maxuint = 4294967295
	    debug = 0
	    # get to same starting time as -O $half_time used for pmval
	    #
	    t += half_delta
      }
      $2 == "29.0.58" { 
	    next_time = $1
	    next_value = $5
	    gsub(/^.*:/, "", next_time)
	    if (prev_time != 0) {
		if (next_time < prev_time) next_time += 60
		delta = next_time - prev_time
		if (debug) {
		    printf("time t=%s;delta=%s;next=%s;prev=%s\n", t, delta, next_time, prev_time) >"'$tmp.dbg'"
		    printf("value next=%s;prev=%d\n", next_value, prev_value) >"'$tmp.dbg'"
		}

		# note ... cannot do arithmetic here bacause of precision
		#	issues on some platforms (especialy *BSD) where
		#	integer arithmetic in awk tops out at 32-bits,
		#	so defer to bc(1)
		#
		if (next_value < prev_value && dowrap) { # then wrap
		    system("echo \"(" prev_value "+(" next_value "+" maxuint "-" prev_value ")*(" t "-" prev_time ")/" delta ") % " maxuint "\" | bc")
		    if (debug)
			printf("dowrap\n") >"'$tmp.dbg'"
		}
		else {
		    system("echo \"" prev_value "+(" next_value "-" prev_value ")*(" t "-" prev_time ")/" delta "\" | bc")
		}

		# increment the same as -t $delta for pmval
		#
		t += half_delta + half_delta
	    }
	    prev_time = next_time
	    prev_value = next_value
      }
    '
    if [ -f $tmp.dbg ]
    then
	cat $tmp.dbg >>$seq.full
	rm -f $tmp.dbg
    fi
}

#
# Note the time of the first sample.wrap value
#
_set_starttime()
{
    $PCP_AWK_PROG <$tmp.dump '
BEGIN		{ stamp = 0 }
/^[0-9]/	{ stamp = $1; next }
$1 == "29.0.58" { printf("%s\n", stamp); exit 0; }'
}

#
# Get out the interp values using pmval
#
_pmval_log()
{
    echo >>$seq.full
    echo "--- pmval -S@$starttime -O $half_delta ---" >>$seq.full
    #debug debug=-Dinterp,fetch
    pmval $debug -w 15 -f 0 -r -a $tmp.archive -S "@$starttime" -O $half_delta -t $delta 2>$tmp.err \
      sample.wrap.ulong \
    | tee -a $seq.full \
    | sed \
	-e '/metric/,/interval/d' \
	-e '/^[ 	]*$/d' \
	-e 's/^[^ ][^ ]*  *//'
    cat $tmp.err >>$seq.full
}

#
# Compare values allowing for an error
#
_compare_results()
{
    echo >>$seq.full
    echo "--- paste ---" >>$seq.full
    # imprecision is in floating point arithmetic where the time
    # stamp precision from pmdumplog is much less than then precision
    # used in interp.c within libpcp
    # the values are O(10) digits, and expect the first 5 of these to
    # be correct, so error should be less than 100,000
    #
    error=100000
    paste $tmp.1 $tmp.2 \
    | tee -a $seq.full \
    | $PCP_AWK_PROG -v error=$error ' {
	    diff = $1-$2; 
	    if (diff < 0) diff *= -1; 
	    if (diff > error) 
		printf("mismatch: %f, %f (diff=%f)\n", $1, $2, diff);
	    else
		printf("match\n");
    }'
}

rm -f $seq.full

# real QA test starts here

delta=2
half_delta=1

_reset
cat <<EOF >$tmp.config
log advisory on $delta second {
    sample.wrap.ulong
} 
EOF
pmlogger -c $tmp.config -s5 -l$tmp.log $tmp.archive
if [ $? -ne 0 ]
then
    echo "Archive failed to be created !"
    cat $tmp.log
    exit 1
    fi
pmdumplog $tmp.archive >$tmp.dump
echo >>$seq.full
echo "--- pmdumplog ---" >>$seq.full
cat $tmp.dump >>$seq.full
starttime=`_set_starttime`

_wrap_off
_process_log >$tmp.1
echo >>$seq.full
echo "--- process_log wrap_off ---" >>$seq.full
cat $tmp.1 >>$seq.full
_pmval_log >$tmp.2
echo >>$seq.full
echo "--- process pmval ---" >>$seq.full
cat $tmp.2 >>$seq.full
_compare_results

_wrap_on
_process_log >$tmp.1
echo >>$seq.full
echo "--- process_log wrap_on ---" >>$seq.full
cat $tmp.1 >>$seq.full
_pmval_log >$tmp.2
echo >>$seq.full
echo "--- process pmval ---" >>$seq.full
cat $tmp.2 >>$seq.full
_compare_results

# success, all done
status=0
exit
