#!/usr/bin/env bash
#
# Thomas Dreibholz's PlanetLab Script Collection
# Copyright (C) 2005-2022 by Thomas Dreibholz, dreibh@iem.uni-due.de
#
# $Id$
#
# 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, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Contact: dreibh@iem.uni-due.de
#

if [ $# -lt 12 ] ; then
   echo "Usage: perftest [Test Name] [Prefix] [PRs] [PEs] [PUs] [PEs' Primary PR] [PUs' Primary PR] [Policy] [ReregInterval] [InterHResTime] [MaxHResItems] [Duration]" >&2
   exit 1
fi


TESTNAME="$1"
PREFIX="$TESTNAME/$2"
PRs="$3"
PEs="$4"
PUs="$5"
PRIMARY_PE_PR="$6"
PRIMARY_PU_PR="$7"
POLICY="$8"
REREGINTERVAL="$9"
shift ; INTERHRESTIME="$9"   # $10 funktioniert nicht!!!
shift ; MAXHRESITEMS="$9"    # $10 funktioniert nicht!!!
shift ; DURATION="$9"        # $12 funktioniert nicht!!!

LAUNCH_DELAY=""   # sleep 0.1"
SHUTDOWN_DELAY="sleep 60"
POOLHANDLE="EchoPool"


# HOST_PR_LIST="132.252.151.178 132.252.151.157"   # 2. Host wird primärer PR!
# HOST_PE_LIST="132.252.152.70 132.252.152.71 132.252.152.72 132.252.152.73 132.252.152.74 132.252.152.75 132.252.152.76 132.252.152.77 132.252.152.78 132.252.152.79"
# HOST_PU_LIST="$HOST_PE_LIST"
# OPT_CSP="-cspserver=132.252.151.157:2960 -cspinterval=333"

# HOST_PR_LIST="localhost"
# HOST_PE_LIST="127.0.0.1"
# HOST_PU_LIST="lupo"
# OPT_CSP="-cspserver=127.0.0.1:2960 -cspinterval=333"

HOST_PR_LIST=`cat $TESTNAME/PR.hosts | xargs`
HOST_PE_LIST=`cat $TESTNAME/PE.hosts | xargs`
HOST_PU_LIST=`cat $TESTNAME/PU.hosts | xargs`
OPT_CSP="-cspserver=132.252.151.157:2960 -cspinterval=333"



# ====== Choose host from HOST_LIST in round robin order ====================
CHOOSE_HOST=""
CHOOSE_HOST_LAST=0
choose_host ()
{
   oldGetHostLast=$CHOOSE_HOST_LAST
   CHOOSE_HOST_LAST=0
   for myHost in $CHOOSE_HOST_LIST ; do
      if [ $CHOOSE_HOST_LAST -gt $oldGetHostLast ] ; then
         CHOOSE_HOST=$myHost
         return
      fi 
      let CHOOSE_HOST_LAST=$CHOOSE_HOST_LAST+1
   done

   for myHost in $CHOOSE_HOST_LIST ; do
      CHOOSE_HOST=$myHost
      CHOOSE_HOST_LAST=0
      return
   done
}


# ====== Get file via scp ===================================================
fetchfile ()
{
   SERVER=$1
   INFILE=$2
   OUTFILE=$3
   scp -q -C $CC_SSHOPT -i $CC_REMOTEKEY $CC_REMOTEUSER@$SERVER:"~/src/rsplib2/rsplib/$INFILE" $OUTFILE
}


# ====== Get uptime =========================================================
get_uptime ()
{
   cat /proc/uptime | (
      read up idle
      echo $up
   )
}


# ====== Start scenario =====================================================
if [ ! -e "$TESTNAME" ] ; then
   mkdir "$TESTNAME"
fi
if [ -e "$PREFIX/runtimes.data" ] ; then
   echo "##################################################"
   echo "$PREFIX is already there -> skipping!"
   echo "##################################################"
   exit 0
fi
rm -rf "$PREFIX"
mkdir "$PREFIX"


# ====== Prepare ASAP/ENRP addresses ========================================
. ./Lab-User.config
. ./ComponentControl.config PR

ALL_HOSTS="`( for HOST in $HOST_PR_LIST $HOST_PE_LIST $HOST_PU_LIST ; do
                 echo $HOST
              done ) | sort -u | xargs echo`"
OPT_PEERS=""
OPT_PE_REGISTRAR=""
OPT_PU_REGISTRAR=""
OPT_PR_ASAP_PORT=4000
OPT_PR_ENRP_PORT=5000
CHOOSE_HOST_LIST="$HOST_PR_LIST"
CHOOSE_HOST_LAST=0
i=1 ; while [ $i -le $PRs ] ; do
   let asapPort=$OPT_PR_ASAP_PORT+i
   let enrpPort=$OPT_PR_ENRP_PORT+i
   choose_host
   OPT_PEERS="$OPT_PEERS -peer=$CHOOSE_HOST:$enrpPort"
   if [ $i -eq $PRIMARY_PE_PR ] ; then
      OPT_PE_REGISTRAR="-registrar=$CHOOSE_HOST:$asapPort"
   fi
   if [ $i -eq $PRIMARY_PU_PR ] ; then
      OPT_PU_REGISTRAR="-registrar=$CHOOSE_HOST:$asapPort"
   fi
   let i=$i+1
done
if [ "x$OPT_PE_REGISTRAR" = "x" ] ; then
   echo "ERROR: Invalid number of PEs' primary PR given!"
   exit 1
fi
if [ "x$OPT_PU_REGISTRAR" = "x" ] ; then
   echo "ERROR: Invalid number of PUs' primary PR given!"
   exit 1
fi


# ====== Print information ==================================================
echo "   + Preparing test for the following parameters:"
echo "      - All:              $ALL_HOSTS"
echo "      - PRs:              $HOST_PR_LIST"
echo "      - PEs:              $HOST_PE_LIST"
echo "      - PUs:              $HOST_PU_LIST"
echo "      - Elements:         $PRs PRs, $PEs PEs, $PUs PUs"
echo "      - PEs' Primary PR:  $PRIMARY_PE_PR"
echo "      - PUs' Primary PR:  $PRIMARY_PU_PR"
echo "      - Peer Opts:       $OPT_PEERS"
echo "      - PE Registrar Opt: $OPT_PE_REGISTRAR"
echo "      - PU Registrar Opt: $OPT_PU_REGISTRAR"
echo "      - ReregInterval:    $REREGINTERVAL [ms]"
echo "      - InterHResTime:    $INTERHRESTIME [ms]"
echo "      - MaxHResItems:     $MAXHRESITEMS"
echo "      - Duration:         $DURATION [s]"


# ====== Start components ===================================================
# ------ Stop all -----------------------------------------------------------
echo "   + `date`: Stopping all old stuff ..."
KILL_PROCS="registrar server hrestest"
KILL_CMDS=""
for p in $KILL_PROCS ; do
   KILL_CMDS="$KILL_CMDS ; killall -KILL $p 2>/dev/null ; killall -q -KILL lt-$p 2>/dev/null"
   KILL_CMDS="$KILL_CMDS ; killall -KILL $p 2>/dev/null ; killall -q -KILL .libs/lt-$p 2>/dev/null"
   KILL_CMDS="$KILL_CMDS ; ./rootshell /usr/bin/killall -KILL $p 2>/dev/null ; ./rootshell /usr/bin/killall -q -KILL lt-$p 2>/dev/null"
done
for HOST in $ALL_HOSTS ; do
   ssh -q -C $CC_SSHOPT -i $CC_REMOTEKEY $CC_REMOTEUSER@$HOST "\
      cd ~/src/rsplib2/rsplib $KILL_CMDS ; echo \"      - \`hostname\` (\`uname -a\`)\"" &
done
wait
rm -f TestP?-*.pid
echo "   + `date`: Ready. Waiting 5 seconds ..."
sleep 5


# ------ Remember current time ----------------------------------------------
UPTIME_STARTUP=$(get_uptime)


# ------ Start PR -----------------------------------------------------------
CHOOSE_HOST_LIST="$HOST_PR_LIST"
CHOOSE_HOST_LAST=0
echo "   + `date`: Starting $PRs PRs ..."
for HOST in $ALL_HOSTS ; do
   rm -f $PREFIX/PR-start-$HOST.sh
done
i=1 ; while [ $i -le $PRs ] ; do
   let enrpPort=$OPT_PR_ENRP_PORT+i
   let asapPort=$OPT_PR_ASAP_PORT+i
   choose_host
   ./RemoteComponentControl WriteCmdOnly $PREFIX/PR-start-$CHOOSE_HOST.sh ./Lab-User.config $CHOOSE_HOST ./ComponentControl.config PR TestPR-$i start \
      -disable-ipv6 \
      $OPT_PEERS -enrp=[0.0.0.0]:$enrpPort -asap=[0.0.0.0]:$asapPort \
      -maxhresitems=$MAXHRESITEMS -loglevel=3 -statsfile=TestPR-$i.data -statsinterval=250 $OPT_CSP
   echo $LAUNCH_DELAY >>$PREFIX/PR-start-$CHOOSE_HOST.sh
   let i=$i+1
done
for HOST in $HOST_PR_LIST ; do
   if [ -e $PREFIX/PR-start-$HOST.sh ] ; then
      echo "Contacting $CC_REMOTEUSER@$HOST ..."
      echo "wait" >>$PREFIX/PR-start-$HOST.sh
      cat $PREFIX/PR-start-$HOST.sh | ssh -i $CC_REMOTEKEY $CC_SSHOPT $CC_REMOTEUSER@$HOST &
   fi
done
wait
sleep 10


# ------ Start PEs ----------------------------------------------------------
CHOOSE_HOST_LIST="$HOST_PE_LIST"
CHOOSE_HOST_LAST=0
echo "   + `date`: Starting $PEs PEs ..."
for HOST in $ALL_HOSTS ; do
   rm -f $PREFIX/PE-start-$HOST.sh
done
i=1 ; while [ $i -le $PEs ] ; do
   choose_host
   ./RemoteComponentControl WriteCmdOnly $PREFIX/PE-start-$CHOOSE_HOST.sh ./Lab-User.config $CHOOSE_HOST ./ComponentControl.config PE TestPE-$i start \
      $OPT_PE_REGISTRAR -loglevel=3 \
      -poolhandle=$POOLHANDLE -rereginterval=$REREGINTERVAL -echo -policy=$POLICY
   echo $LAUNCH_DELAY >>$PREFIX/PE-start-$CHOOSE_HOST.sh
   let i=$i+1
done
for HOST in $HOST_PE_LIST ; do
   if [ -e $PREFIX/PE-start-$HOST.sh ] ; then
      echo "Contacting $CC_REMOTEUSER@$HOST ..."
      echo "wait" >>$PREFIX/PE-start-$HOST.sh
      cat $PREFIX/PE-start-$HOST.sh | ssh -i $CC_REMOTEKEY $CC_SSHOPT $CC_REMOTEUSER@$HOST &
   fi
done
wait
sleep 10


# ------ Start PUs ----------------------------------------------------------
CHOOSE_HOST_LIST="$HOST_PU_LIST"
CHOOSE_HOST_LAST=0
echo "   + `date`: Starting $PUs PUs ..."
for HOST in $ALL_HOSTS ; do
   rm -f $PREFIX/PU-start-$HOST.sh
done
i=1 ; while [ $i -le $PUs ] ; do
   choose_host
   ./RemoteComponentControl WriteCmdOnly $PREFIX/PU-start-$CHOOSE_HOST.sh ./Lab-User.config $CHOOSE_HOST ./ComponentControl.config PU TestPU-$i start \
      $OPT_PU_REGISTRAR -loglevel=3 \
      -poolhandle=$POOLHANDLE -pause=$INTERHRESTIME -quiet -statsfile=TestPU-$i.data -statsinterval=250
   echo $LAUNCH_DELAY >>$PREFIX/PU-start-$CHOOSE_HOST.sh
   let i=$i+1
done
for HOST in $HOST_PU_LIST ; do
   if [ -e $PREFIX/PU-start-$HOST.sh ] ; then
      echo "Contacting $CC_REMOTEUSER@$HOST ..."
      echo "wait" >>$PREFIX/PU-start-$HOST.sh
      cat $PREFIX/PU-start-$HOST.sh | ssh -i $CC_REMOTEKEY $CC_SSHOPT $CC_REMOTEUSER@$HOST &
   fi
done
wait


# ====== Run tests ==========================================================
echo "   + `date`: Running test for $DURATION seconds ..."
UPTIME_MSTART=$(get_uptime)
sleep $DURATION
UPTIME_MEND=$(get_uptime)


# ====== Stop scenario ======================================================

# ------ Stop PUs -----------------------------------------------------------
CHOOSE_HOST_LIST="$HOST_PU_LIST"
CHOOSE_HOST_LAST=0
echo "   + `date`: Stopping PUs ..."
for HOST in $ALL_HOSTS ; do
   rm -f $PREFIX/PU-stop-$HOST.sh
done
i=1 ; while [ $i -le $PUs ] ; do
   choose_host
   ./RemoteComponentControl WriteCmdOnly $PREFIX/PU-stop-$CHOOSE_HOST.sh ./Lab-User.config $CHOOSE_HOST ./ComponentControl.config PU TestPU-$i stop
   let i=$i+1
   # echo $LAUNCH_DELAY >>$PREFIX/PU-stop-$CHOOSE_HOST.sh
done
for HOST in $HOST_PU_LIST ; do
   if [ -e $PREFIX/PU-stop-$HOST.sh ] ; then
      echo "Contacting $CC_REMOTEUSER@$HOST ..."
      echo "wait" >>$PREFIX/PU-stop-$HOST.sh
      cat $PREFIX/PU-stop-$HOST.sh | ssh -i $CC_REMOTEKEY $CC_SSHOPT $CC_REMOTEUSER@$HOST &
   fi
done
wait

# ------ Stop PEs -----------------------------------------------------------
CHOOSE_HOST_LIST="$HOST_PE_LIST"
CHOOSE_HOST_LAST=0
echo "   + `date`: Stopping PEs ..."
for HOST in $ALL_HOSTS ; do
   rm -f $PREFIX/PE-stop-$HOST.sh
done
i=1 ; while [ $i -le $PEs ] ; do
   choose_host
   ./RemoteComponentControl WriteCmdOnly $PREFIX/PE-stop-$CHOOSE_HOST.sh ./Lab-User.config $CHOOSE_HOST ./ComponentControl.config PE TestPE-$i stop
   let i=$i+1
   # echo $LAUNCH_DELAY >>$PREFIX/PE-stop-$CHOOSE_HOST.sh
done
for HOST in $HOST_PE_LIST ; do
   if [ -e $PREFIX/PE-stop-$HOST.sh ] ; then
      echo "Contacting $CC_REMOTEUSER@$HOST ..."
      echo "wait" >>$PREFIX/PE-stop-$HOST.sh
      cat $PREFIX/PE-stop-$HOST.sh | ssh -i $CC_REMOTEKEY $CC_SSHOPT $CC_REMOTEUSER@$HOST &
   fi
done
wait

# ------ Stop PR ------------------------------------------------------------
CHOOSE_HOST_LIST="$HOST_PR_LIST"
CHOOSE_HOST_LAST=0
echo "   + `date`: Stopping PRs ..."
for HOST in $ALL_HOSTS ; do
   rm -f $PREFIX/PR-stop-$HOST.sh
done
i=1 ; while [ $i -le $PRs ] ; do
   choose_host
   ./RemoteComponentControl WriteCmdOnly $PREFIX/PR-stop-$CHOOSE_HOST.sh ./Lab-User.config $CHOOSE_HOST ./ComponentControl.config PR TestPR-$i stop
   let i=$i+1
   # echo $LAUNCH_DELAY >>$PREFIX/PR-stop-$CHOOSE_HOST.sh
done
for HOST in $HOST_PR_LIST ; do
   if [ -e $PREFIX/PR-stop-$HOST.sh ] ; then
      echo "Contacting $CC_REMOTEUSER@$HOST ..."
      echo "wait" >>$PREFIX/PR-stop-$HOST.sh
      cat $PREFIX/PR-stop-$HOST.sh | ssh -i $CC_REMOTEKEY $CC_SSHOPT $CC_REMOTEUSER@$HOST &
   fi
done
wait
UPTIME_SHUTDOWN=$(get_uptime)


# ====== Get results ========================================================
CHOOSE_HOST_LIST="$HOST_PR_LIST"
CHOOSE_HOST_LAST=0
echo "   + `date`: Fetching PR results ..."
i=1 ; while [ $i -le $PRs ] ; do
   choose_host
   fetchfile $CHOOSE_HOST "TestPR-$i.data" "$PREFIX/" &
   let i=$i+1
done
wait


echo "Startup MeasurementStart MeasurementEnd Shutdown" >$PREFIX/runtimes.data
echo "1 $UPTIME_STARTUP $UPTIME_MSTART $UPTIME_MEND $UPTIME_SHUTDOWN" >>$PREFIX/runtimes.data


$SHUTDOWN_DELAY
echo "   + `date`: Done!"
