#! /bin/bash
# set -xv
#=========================================================================
# Copyright (C) GemTalk Systems 1986-2024.  All Rights Reserved.
#
# Name - gstest.sh
#
# Purpose - Script to perform various GemStone-related timing tests
#           See "help" text for details.
#
# CAUTION:  These tests should only be performed as directed by
#           GemTalk Technical Support, as some of them can overwrite
#           existing extents or tranlogs if used improperly!
#
#=========================================================================

usage() {
  cat <<EOF
===================================================================="

Purpose:

  Perform the selected GemStone systems test

CAUTION:

  These tests should only be performed as directed by
  GemTalk Technical Support, as some of them will overwrite
  existing extents or tranlogs!

Usage:
`basename $0` [-h]|[<test>] arg1 [ arg2 .. argN ]

  Make sure \$GEMSTONE is set.

Options:

  -h (or no arguments)

    print this message and exit.

  <test>

      Specifies the type of test.

      Note that for read tests this may be followed by an optional
      modifier that specifies the type of read test.

      The type of test determines the arguments that follow.
      See the list below for details:


      Testname        arguments
                      explanation
      -------------------------------------------------------------
      READING:

      read            extent-name num-iterations 
      or:
      read random     extent-name num-iterations
                      Test speed of random reads from extent

      read sorted     extent-name num-iterations
                      Test speed of sorted reads from extent

      read sequential extent-name num-iterations
                      Test speed of sequential reads from extent

      read serial     extent-name1 .. extent-nameN num-iterations
                      Test speed of serial reads across multiple extents

      read multipage  extent-name page-size num-iterations
                      Test speed of multipage random reads from extent

      -------------------------------------------------------------
      WRITING:

      write           extent-file num-iterations
                      Test speed of random writes to an extent file
                      WARNING! CHANGES EXTENT FILE!

      tranlog         tranlog-file num-iterations
                      Test speed of writes to a tranlog
                      WARNING! CHANGES TRANLOG!

      -------------------------------------------------------------
      SLEEP:

      millisleep      ms-to-sleep
                      Test millisecond sleep.

      nanosleep       ms-to-sleep (optional num-iterations)
                      Test nanosecond sleep.
                      Note first argument specifies milliseconds to sleep
                      When optional num-iterations supplied, test will
                      return the range of variation between runs.

      -------------------------------------------------------------
      OTHER:

      ffs             num-iterations
                      Test speed of FFS operation (Find First bit Set)
      memcpy          size-in-words num-iterations
                      Test speed of memcopy operation
      spinlock        num-iterations
                      Test speed of spin-lock mechanism


====================================================================

EOF
}

# check for -h or no args; print usage and exit
if [ ! $1 ] || [ $1 = "-h" ]; then
  usage
  exit 0
fi 

# initialize variables
debug="false"               # debug flag
command=""                  # pgsvr command to execute
numargs=1                   # number of arguments for pgsvr command
arg1name="num-iterations"   # help text for argument 1
arg2name=""                 # help text for argument 2
modify=""                   # warning message if modifying extent/tranlog
argorder="1"                # ordering of arguments to pass to pgsvr
                            # 1 = just pass the first argument
                            # 12 = pass arg1 and arg2 in that order
                            # 21 = reverse order of arg1 and arg2
tmpfile="/tmp/gstest$$"     # temp file holding pgsvr commands

# check for hidden -d flag to turn on debugging
if [ $1 = "-d" ]; then
  debug=true
  shift
fi

# check that $GEMSTONE is set
if [ ! $GEMSTONE ]; then
  echo "ERROR:  \$GEMSTONE not set" 1>&2
  exit 1
fi

# Check for $GEMSTONE/sys/pgsvrslow
if [ -f $GEMSTONE/sys/pgsvrslow ]; then
  pgsvrExe=$GEMSTONE/sys/pgsvrslow
else
  echo "ERROR:  \$GEMSTONE/sys/pgsvrslow not found" 1>&2
  exit 1;
fi

cmd=$1
shift
if [ $cmd = "read" ]; then
  
  #process a read command -- check for the subcommand

  if [ ! $1 ]; then
    echo "ERROR:  Missing subcommand/extent/arguments in read command"
    exit 1
  fi

  if [ $1 = "random" ]; then
    command="testreadrate"
    shift

  elif [ $1 = "sorted" ]; then
    command="testreadsorted"
    shift

  elif [ $1 = "sequential" ]; then
    command="testreadseq"
    shift

  elif [ $1 = "serial" ]; then
    command="testreadserial"
    shift

  elif [ $1 = "multipage" ]; then
    command="testbigreadrate"
    numargs=2
    argorder=12
    arg1name="page-size"
    arg2name="num-iterations"
    shift

  else
    command="testreadrate"
  fi

  # check if extent is available
  if echo $1 | grep "^[0-9]*$" >/dev/null
  then
    echo "ERROR: no extent file specified."
    exit 1
  fi


  if [ -f $1 ]; then
    echo "'$1' opendbf " >>$tmpfile
  else
    echo "ERROR:  Cant find extent file $1" 1>&2
    exit 1;
  fi
  shift

  # for testreadserial, allow opening additional extents
  if [ $command = "testreadserial" ]; then
    scanning=true
    while [ $scanning = true ]
    do
      if [ ! $1 ]; then
        echo "ERROR: Missing primary argument $arg1name"
        exit 1
      elif echo $1 | grep "^[0-9]*$" >/dev/null
      then
        scanning=false
      elif [ -f $1 ]; then
        echo "'$1' opendbf " >>$tmpfile
        shift
      else
        echo "ERROR: Cant find extent file $1" 1>&2
        exit 1
      fi
    done
  fi

elif [ $cmd = "write" ]; then
  command="testwrite"
  if [ ! $1 ]; then
    echo "ERROR: missing extent file / num-iterations."
    exit 1
  fi
  if echo $1 | grep "^[0-9]*$" >/dev/null
  then
    echo "ERROR: no extent file specified."
    exit 1
  elif [ -f $1 ]; then
    modify="WARNING:  THIS TEST WILL MODIFY EXTENT $1 !!"
    echo "'$1' opendbf " >>$tmpfile
    shift
  else
    echo "ERROR:  Cant find extent file $1" 1>&2
    exit 1
  fi

elif [ $cmd = "tranlog" ]; then
  command="testtranlogio"
  if [ ! $1 ]; then
    echo "ERROR: missing tranlog / num-iterations."
    exit 1
  fi
  if echo $1 | grep "^[0-9]*$" >/dev/null
  then
    echo "ERROR: no tranlog file specified."
    exit 1
  fi
  # check if tranlog exists..
  if [ -f $1 ]; then
    modify="WARNING:  THIS TEST WILL APPEND TO TRANLOG $1"
  else
    modify="WARNING:  THIS TEST WILL CREATE NEW TRANLOG $1"
  fi
  echo "'$1' " >>$tmpfile
  shift

elif [ $cmd = "millisleep" ]; then
  command="testmillisleep"
  arg1name="ms-to-sleep"

elif [ $cmd = "nanosleep" ]; then
  arg1name="ms-to-sleep"
  if [ ! $2 ]; then
    command="testnanosleep"
  else
    command="testnanosleeperr"
    numargs=2
    argorder=21
    arg2name="num-iterations"
  fi

elif [ $cmd = "ffs" ]; then
  command="testffs"

elif [ $cmd = "memcpy" ]; then
  command="testmemcpy"
  numargs=2
  argorder=21
  arg1name="size-in-words"
  arg2name="num-iterations"

elif [ $cmd = "spinlock" ]; then
  command="testspinlock"

else
  echo "ERROR:  Invalid test command $cmd" 1>&2
  exit 1

fi

# check that first argument is present and is a number
if [ ! $1 ]; then
  echo "ERROR: missing primary argument $arg1name"
  if [ $numargs = 2 ]; then
    echo "ERROR: missing secondary argument $arg2name"
  fi
  exit 1
fi
if echo $1 | grep "^[0-9]*$" >/dev/null
then
  : # arg OK
else
  echo "ERROR: primary argument $arg1name is not a number"
  exit 1
fi

# if second argument needed, check if present and is a number
if [ $numargs = 2 ]; then
  if [ ! $2 ]; then
    echo "ERROR:  missing secondary argument $arg2name"
    exit 1
  fi
  if echo $2 | grep "^[0-9]*$" >/dev/null
  then
    if [ $3 ]; then
      echo "Exra arguments ignored."
    fi
  else
    echo "ERROR: secondary argument $arg2name is not a number"
    exit 1
  fi
elif [ $2 ]; then
  echo "Extra arguments ignored."
fi

# check and see if this is a write command and check if OK
if [ "$modify" ]; then
  echo
  echo "$modify"
  echo 
  read -p "Do you wish to continue (y/n)? " rsp
  if [ $rsp != "y" ]; then
    echo "Test aborted!"
    exit 1
  fi
fi

# write out args and command to pgsvr execution file in proper order
if [ $argorder = 1 ]; then
  echo "$1 $command" >>$tmpfile
elif [ $argorder = 12 ]; then
  echo "$1 $2 $command" >>$tmpfile
elif [ $argorder = 21 ]; then
  echo "$2 $1 $command" >>$tmpfile
else
  echo "Script logic error: invalid arg order."
  exit 1
fi

# For debugging script problems
if [ $debug = true ]; then
  echo
  echo "DEBUG:"
  echo "   command    = $cmd"
  echo "   pgsvr test = $command"
  echo "   numargs    = $numargs"
  echo "   argorder   = $argorder"
  echo "   pgsvr      = $pgsvrExe"
  echo "   $arg1name: $1"
  if [ $numargs = 2 ]; then
    echo "   $arg2name: $2"
  fi
  echo
  echo "PGSVR SCRIPT:"
  cat $tmpfile
  echo
else
  # More concise summary for normal usage
  echo
  echo "$cmd:"
  echo "   $arg1name: $1"
  if [ $numargs = 2 ]; then
    echo "   $arg2name: $2"
  fi
  echo
fi

# now execute..
$pgsvrExe < $tmpfile
pStatus=$?
if [ $pStatus -ne 0 ]; then
  echo "pgsvr returned $pStatus";
  exit $pStatus
fi
#
# end of script
