#! /bin/sh
#set -xv
#=========================================================================
# Copyright (C) GemTalk Systems 1986-2014.  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: postconv.sh 34196 2014-09-11 22:35:06Z normg $
#
#=========================================================================


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 converted OK, $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 SortedCollections could not be converted."
  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
