#!/bin/bash
# ---------------------------------------------------------------------------
#  Intel Concurrent Collections for Haskell
#  Copyright (c) 2010, Intel Corporation.
# 
#  This program is free software; you can redistribute it and/or modify it
#  under the terms and conditions of the GNU Lesser General Public License,
#  version 2.1, as published by the Free Software Foundation.
# 
#  This program is distributed in the hope it will be useful, but WITHOUT
#  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
#  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for
#  more details.
# 
#  You should have received a copy of the GNU Lesser General Public License along with
#  this program; if not, write to the Free Software Foundation, Inc., 
#  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
# ---------------------------------------------------------------------------


# Usage: ntimes <N> cmd args ...

# Takes the best time out of N.
# Returns that best time in seconds to stdout.

# This script writes a bunch of stuff to stderr, but only one thing to
# stdout.  The one thing, the "return value" of this process is the
# best time in seconds.

# Responds to the environment variable HIDEOUTPUT, which, if non-empty
# suppresses echoing of the child command's output.

# Also responds to NOTIME which turns off the timing.


# Time out processes after three minutes.
TIMEOUT=1000

# Unfortunately 'tempfile' is not a standard command:
function mytempfile {
  date=`date +"%Y.%m.%d"`
  secs=`date +"%s"`
  #index=$(($index+1))
  index=$1
  file=./runs/"$date"_"$base"_"$CNC_VARIANT"_"$CNC_SCHEDULER"_"$NUMTHREADS"_"$secs"_"$index".log
  touch $file
  echo $file
}

N=$1
shift
CMD=$*

if [ "$CMD" == "" ];
then echo Usage: "ntimes <trials> <cmd> <cmdargs> ..."
     exit 1
fi
base=`basename $1`

if [ ! -d "./runs" ]; then mkdir ./runs; fi 

CAT=/bin/cat

  # This serves as the log
  TMP1=`mytempfile 1`
  echo "Execution log file: " >> /dev/stderr
  echo "   $TMP1" >> /dev/stderr

  #echo "=================== ASYNCHRONOUS TEST OUTPUT TO FOLLOW ======================" > $TMP1

  # if [ "$HIDEOUTPUT" == "" ];
  # then  (tail -f $TMP1 >> /dev/stderr) &
  # fi

EXITCODE=0

 for ((i=1; i <= $N; i++)); do
    # Stores just this one executable's output:
    TMP2=`mytempfile 2`

# [2009.12.17] I need to get a good cross-platform process time-out system:
     # HACK: Sometimes I run this on systems WITHOUT a working GHC:
    if [ -e ./timeout.sh ];
    then TIMEOUTRUN="./timeout.sh -t $TIMEOUT"
    elif [ -e ./timeout ];
    # [2010.06.03] --RTS is a hack for working around a problem with +RTS flags:
    then TIMEOUTRUN="./timeout $TIMEOUT --RTS "
    else TIMEOUTRUN=
    fi

    if [ "$HIDEOUTPUT" == "" ];
    then MYOUT=/dev/stderr
    else MYOUT=/dev/null
    fi

    echo                           | tee -a $TMP2 >> $MYOUT
    echo "Running trial $i of $N:" | tee -a $TMP2 >> $MYOUT
    echo "------------------------------------------------------------" | tee -a $TMP2 >> $MYOUT

    # This is hackish, it depends on the program output not containing
    # the string "real".  (Aside from the timing results.)

    if [ "$NOTIME" != "" ];
    then                                  ($TIMEOUTRUN $CMD) &> /dev/stdout | tee -a $TMP2 >> $MYOUT; CODE=${PIPESTATUS[0]}
    elif [ `uname` == "Linux" ];
    then (/usr/bin/time --format="%e real" $TIMEOUTRUN $CMD) &> /dev/stdout | tee -a $TMP2 >> $MYOUT; CODE=${PIPESTATUS[0]}
    else (/usr/bin/time                    $TIMEOUTRUN $CMD) &> /dev/stdout | tee -a $TMP2 >> $MYOUT; CODE=${PIPESTATUS[0]}
    fi

    # If there was an error, we don't commit the output to $TMP1:
    if [ "$CODE" == "0" ];
    then echo "   Run $i of command succeeded" >> /dev/stderr

	# SUPERHACK terrain... Here's a special symbol that the script can
	# use to override the external timing and use internal timing
	# mechinasms.
	selftime=`grep SELFTIME $TMP2`
	if [ "$selftime" != "" ]; then 
	  echo "  +++ Executable appears self-timed!!:"  >> $MYOUT
	  echo "$selftime"                               >> $MYOUT
	  cat $TMP2 | grep -v "real" | sed 's/SELFTIMED/real/' >> $TMP1
	else
          cat $TMP2 >> $TMP1
	fi


    # [2010.05.11] I used to just give warnings when not ALL of the trials failed:
    # This was for timing the nondeterministic hashtable hack:
    #else echo "Warning: run $i of command failed with code $CODE: $CMD" >> /dev/stderr
    else echo "ERROR run $i of command failed with code $CODE: $CMD" >> /dev/stderr
         #exit $CODE
	 EXITCODE=$CODE
    fi

    rm -f $TMP2
done;

  # Stores the times:
  TMP3=`mytempfile 3`

  # HACK HACK: this assumes the string "real" doesn't occur in the test output.
  grep real $TMP1 | awk '{ print $1" "$2 }' | sort -n > $TMP3

  # Echo the final output to stdout:

  echo "Final Timings: " > /dev/stderr

  cat $TMP3 | sed 's/real //' | sed 's/ real//' 

  # Leave behind only $TMP1
  rm -f $TMP3

exit $EXITCODE
