#! /bin/sh
#set -xv
#=========================================================================
# Copyright (C) GemTalk Systems 1986-2020.  All Rights Reserved.
#
# Name - postconv.sh
# Installed as - postconv
#
# Purpose - Common script for fixing sort blocks of SortedCollections 
#           and its subclasses during the 2.x to 3.x conversion.
#
# $Id$
#
#=========================================================================


if [ "a$GEMSTONE" = "a" ]; then
  echo "ERROR: GemStone scripts require a GEMSTONE environment variable."
  echo "       Please set it to the directory where GemStone resides."
  exit 1
fi

# maintenance symbols
comid="postconv"              # this script's name

# make sure of a minimum path
PATH=:/bin:/usr/bin:/usr/ucb:$PATH; export PATH

. $GEMSTONE/bin/misc.sh

defaultErrorControl

info() {
  echo $comid[INFO]: $*
}
error() {
  echo $comid[ERROR]: $*
}
warning() {
  echo $comid[WARNING]: $*
}

# Check the status of a completed topaz job.
checkStatus() {
  # tail on HPUX needs this next line
  echo >> $thisLogFile 
  tail -2 $thisLogFile | head -1 | egrep -e '^0$' >/dev/null
  status=$?
  if [ $status -ne 0 ]; then
    error "found non-zero error status in $thisLogFile"
    error "Check log files listed above."
    exit 1
  fi
}

# Wait for a list of topaz PIDs to exit.
waitForTopaz() {
  info "waiting for topaz process(es) with the following PID(s) to exit..."
  info "$pids"
  wait $pids
  info "done"
  info ""
}

# Write the common beginning of a topaz script to the file $convFile
startBuildTopazScript() {
  convFile=$upgradeLogDir/$fileNameBase.topaz
  thisLogFile=$upgradeLogDir/$fileNameBase.log
  echo set user SystemUser pass swordfish gemstone $stoneName > $convFile
  echo "display resultcheck" >> $convFile
  echo "omit oops" >> $convFile
  echo "omit bytes" >> $convFile
  echo "limit oops 50" >> $convFile
  echo "limit bytes 100" >> $convFile
  echo "iferror stack" >> $convFile
  echo login >> $convFile
  echo time >> $convFile
}

# Write the common ending of a topaz script to file $convFile
finishBuildTopazScript() {
  echo % >> $convFile
  echo time >> $convFile
  echo logout >> $convFile
  echo errorcount >> $convFile
}

usage() {
  cat <<EOF
Usage:
postconv [-c <numCacheWarmerThreads>][-h][-n <numberOfSessions>][-s <stoneName>]
         [-t <tempObjCacheSize][-u <userId>]
Environment Requirements:
    GEMSTONE          set to a 3.x GemStone/S 64 Bit product tree
    upgradeLogDir     set to a writable directory used in previous steps
Parameters:
    -c <numCacheWamerThreads> 
        Run <numCacheWamerThreads> cache warmer threads in a single gem to load the object
        table into the shared cache before starting post-conversion.
        Default: 0 (no cache warming)
    -h print this Usage and exit
    -n <numberOfSessions>
        where <numberOfSessions> is the number of parallel sessions which will
        convert the instances of SortedCollection and its subclasses.  Default: 1
    -r  Reuse an existsing version of \$upgradeLogDir/AllSortedCollections.bms if
        it exists.  This file contains the oops of all SortedCollections and its
        subclasses.  Default: delete the file if it exists and generate a new file.
    -s <stoneName>
        where <stoneName> is the name of a running 3.x stone that has already
        been through the previous conversion steps.  Default: gs64stone
    -t <tmpObjCacheSize>
        size of GEM_TEMPOBJ_CACHE_SIZE in KB.
        Default: 20000
    -u <userId>
       The UserId who has all subclasses of SortedCollection to be converted 
       in its symbol list.  Default: SystemUser
EOF
}

# defaults
stoneName=gs64stone
numberOfSessions=1
numCacheWarmers=0
userId=SystemUser
tmpObjCacheSize=20000
reuseFile=0

while getopts "hc:n:rs:t:u:" opt; do
  case $opt in
    h) usage; exit 0 ;;
    c) numCacheWarmers=$OPTARG ;;
    n) numberOfSessions=$OPTARG ;;
    r) reuseFile=1 ;;
    s) stoneName=$OPTARG ;;
    t) tmpObjCacheSize=$OPTARG ;;
    u) userId=$OPTARG ;;
   \?) error "bad arg: $opt"; usage; exit 1 ;;
  esac
done
export stoneName


  # First, range check the value given
if [ $tmpObjCacheSize -gt 1000000 ] || [ $tmpObjCacheSize -lt 1000 ]; then
  error "ERROR: Cannot set GEM_TEMPOBJ_CACHE_SIZE to $tmpObjSize."
  error "ERROR: This value must be between 1000 and 1000000."
  usage
  exit 1
fi


# make sure $upgradeLogDir has been set
info "verifying upgradeLogDir..."
if [ a$upgradeLogDir = "a" ]; then
  error "The environment variable upgradeLogDir has not been set."
  usage
  exit 1
elif [ ! -d $upgradeLogDir ]; then
  error "$upgradeLogDir is not a directory."
  usage
  exit 1
fi
info "...found upgradeLogDir..."

# make topazerrors.log go to $upgradeLogDir, not cwd.
GS_TOPAZ_ERROR_LOG_DIR=$upgradeLogDir ; export GS_TOPAZ_ERROR_LOG_DIR

# make sure $upgradeLogDir is writable
touch $upgradeLogDir/tmp$$ 2>/dev/null 
if [ "$?" != "0" ]; then
  error "$upgradeLogDir is not writable."
  usage
  exit 1
fi
rm $upgradeLogDir/tmp$$
info "...upgradeLogDir is writable."

# make sure stone is running
info "verifying $stoneName is running..."
$GEMSTONE/bin/waitstone $stoneName -1 > /dev/null 2>&1
status=$?
if [ $status -ne 0 ]; then
  error "...no stone named $stoneName found"
  usage
  exit $status
fi
info "...$stoneName is running."


# 44610 - there will now be multiple BM files, one for each sorted collection class.
#         Put them all in this subdirectory.
sortedBmDir="$upgradeLogDir/scbm"

if [ $reuseFile -eq 1 ]; then
  # User wants to reuse the files.  See if the directory is there and complain and continue if not.
  if [ ! -d $sortedBmDir ]; then
    warning "-r option specifies reusing the files in $sortedBmDir but the directory was not found."
    reuseFile=0
  else
  # Yipee, we found it!
     info "Found files in existing directory: $sortedBmDir:"
     info "The following files will be reused and listInstances step will be omitted:"
     LIST=`ls -1 $sortedBmDir`
     for each in $LIST
     do
       info "  $each"
     done
  fi
else
# Do not reuse the file.  Delete it if it's there.
  rm -fr $sortedBmDir > /dev/null 2>&1
fi

# clean up from any previous runs
rm -f $upgradeLogDir/failedSortedCollections_* \
   $upgradeLogDir/AllFailedSortedCollections.bm \
   $upgradeLogDir/topaz-*.log postconv*.* cachewarmgem*.* \
   $upgradeLogDir/postconv-find-sorted-collections.topaz \
   $upgradeLogDir/postconv-find-sorted-collections.log > /dev/null 2>&1

# put the cache warmer logs in $upgradeLogDir

# start cache warmer gems if specified
if [ $numCacheWarmers -gt 0 ]; then
  info "starting cache warmers..."
  if [ $numCacheWarmers -gt 64 ]; then
    numCacheWarmers=64
  fi
  $GEMSTONE/bin/startcachewarmer -n$numCacheWarmers -s$stoneName -L$upgradeLogDir -W
  status=$?
  if [ $status -eq 0 ]; then
    info "...successfully started cache threads."
  else
    error "...cache warming failed!"
    exit $status
  fi
  info "...cache warming completed"
fi

if [ $reuseFile -eq 0 ]; then
  info "...starting multi-threaded scan of repository for instances of SortedCollection and its subclasses..."
  info "...this might take awhile..."
  fileNameBase="postconv-find-sorted-collections"
  startBuildTopazScript
  echo expectvalue %Array >> $convFile
  echo run >> $convFile
  echo SortedCollection findAllSortedCollectionsForUser: \'$userId\' >> $convFile
  finishBuildTopazScript
  $GEMSTONE/bin/topaz -i -l -T $tmpObjCacheSize < $convFile > $thisLogFile 2>&1 &
  pids=$!
  waitForTopaz
  checkStatus
fi

# reset global counters in case this run is a retry
info "...Initializing repository for SortedCollection conversion..."
fileNameBase="postconv-init"
startBuildTopazScript
echo expectvalue true >> $convFile
echo run >> $convFile
echo "SortedCollection initializeForConversion"  >> $convFile
finishBuildTopazScript
$GEMSTONE/bin/topaz -i -l < $convFile > $thisLogFile 2>&1 &
pids=$!
waitForTopaz
checkStatus


count=1

# file numbers are 0-based.  the first input and output file is 0
# gem nums are 1-based.  the first gem is gem 1
#
pids=""
info "Starting $numberOfSessions gem(s) to convert the SortedCollections..."
while [ $count -le $numberOfSessions ]; do
  fileNameBase="convertSortedColls_$count"
  startBuildTopazScript
  echo expectvalue %String >> $convFile
  echo run >> $convFile
  echo SortedCollection convertInstancesFromFilesForGem: $count of: $numberOfSessions >> $convFile
  finishBuildTopazScript
  $GEMSTONE/bin/topaz -i -l -T $tmpObjCacheSize < $convFile > $thisLogFile 2>&1 &
  thisPid=$!
  logFiles="$thisLogFile $logFiles"
  pids="$thisPid $pids"
  info "  spawned topaz with input file $convFile, PID = $thisPid"
  count=`expr $count + 1`
done

#-------------------------------------------------
# wait for the topaz sessions to exit
waitForTopaz

#-------------------------------------------------
# grep topaz log files for error count != 0
errorFound=0
for log in $logFiles; do
  thisLogFile=$log
  checkStatus
done


info "...checking on results of conversion..."
fileNameBase="postconv-result-check"
startBuildTopazScript
echo expectvalue true >> $convFile
echo run >> $convFile
echo SortedCollection writeTotalsFiles >> $convFile
finishBuildTopazScript
$GEMSTONE/bin/topaz -i -l -T $tmpObjCacheSize < $convFile > $thisLogFile 2>&1 &
pids=$!
waitForTopaz
checkStatus

if [ ! -f $upgradeLogDir/sc_ok.txt ]; then
  error "A file is missing: $upgradeLogDir/sc_ok.txt"
  exit 1
fi
if [ ! -f $upgradeLogDir/sc_failed.txt ]; then
  error "A file is missing: $upgradeLogDir/sc_failed.txt"
  exit 1
fi
if [ ! -f $upgradeLogDir/sc_done.txt ]; then
  error "A file is missing: $upgradeLogDir/sc_done.txt"
  exit 1
fi

OK=`cat $upgradeLogDir/sc_ok.txt`
FAILED=`cat $upgradeLogDir/sc_failed.txt`
NUM_DONE=`cat $upgradeLogDir/sc_done.txt`

if [ $NUM_DONE -ne $numberOfSessions ]; then
  error "Only $NUM_DONE out of $numberOfSessions conversion sessions completed correctly."
  error "Consult the log files in $upgradeLogDir for more information"
  exit 1
fi

if [ $FAILED -ne 0 ]; then
# If we get here, all conversion gems finished but 1 or more SortedCollections could
# not be converted.  
  info "...SortedCollection conversion results: $OK sortBlocks recompiled successfully, $FAILED had errors."
  info "...consolidating unconvertable sorted collection oop files (if any)..."
  fileNameBase="postconv-combine-sorted-collections"
  startBuildTopazScript
  echo expectvalue true >> $convFile
  echo run >> $convFile
  echo SortedCollection createConversionResultFileForTotalGems: $numberOfSessions >> $convFile
  finishBuildTopazScript
  $GEMSTONE/bin/topaz -i -l -T $tmpObjCacheSize < $convFile > $thisLogFile 2>&1 &
  pids=$!
  waitForTopaz
  checkStatus
fi


# Now update DBF history...
info "...Updating Dbf History object..."
fileNameBase="postconv-updateDbfHistory"
startBuildTopazScript
echo expectvalue %String >> $convFile
echo run >> $convFile
echo SortedCollection updateDbfHistoryForConversion >> $convFile
echo % >> $convFile
echo expectvalue true >> $convFile
echo run >> $convFile
echo System commitTransaction >> $convFile
finishBuildTopazScript
$GEMSTONE/bin/topaz -i -l -T $tmpObjCacheSize < $convFile > $thisLogFile 2>&1 &
pids=$!
waitForTopaz
checkStatus

if [ $FAILED -eq 0 ]; then
 info "Congratulations!  $OK SortedCollections were successfully converted.  No errors were detected."
else
  info "Successful completion of GemStone/64 2.x to 3.x post conversion."
  info "However, $FAILED SortedCollection sortBlocks could not be converted."
  info "Note that only SortedCollection sortBlocks that are simpleBlocks can be recompiled by conversion."
  info "Object IDs for these were stored in the file $upgradeLogDir/AllFailedSortedCollections.bm"
  info "You may use the method System>>readHiddenSet: 41 fromFile: $upgradeLogDir/AllFailedSortedCollections.bm"
  info "to examine these objects and convert them manually."
fi

exit 0
