#! /bin/sh
#set -xv
#=========================================================================
# Copyright (C) VMware, Inc. 1986-2011.  All Rights Reserved..
#
# Name - convprep2g.sh
# Installed as - convprep2g
#
# Purpose -
#
# This script is executed as step 4 of GemStone/S 2G to GemStone/S 64 bit 2.x 
# conversion as outlined below. 
# It is run with a running 2G stone. This script does the following steps:
#   1. file in the new SmallDouble class definition and commit
#   2. System stopOtherSessions
#   3. System _reclaimAllShadowPages
#   4. Object table scan
#   5. Data page scan
#
# CUSTOMER UPGRADE PROCEDURE
#   Please refer to the GemStone/S 64 Bit 2.x Installation Guide for detailed
#   Instructions.
# STAGE 1:
# 1. maintain your 2G environment, e.g. GEMSTONE. DO NOT set GEMSTONE to
#    the 2.x product yet!
# 2. login to 2G stone, stop all other user sessions, and set SystemUser
#    password to 'swordfish'.
# 3. set environment variable upgradeLogDir to a writable directory
# 4. run the script convprep2g.  This script is found in the 2.x product tree, in
#    the upgrade directory.  This file should not be in your path, so it will need
#    to be invoked with an explicit path.
# STAGE 2:
# 5. set up your environment ($GEMSTONE) for the 2.x product tree. Maintain
#    your GS 2G extents; they will be read from during stage 2. The environment
#    variable upgradeLogDir must remain the same for stage 2 as it was for
#    stage 1.
# 6. start a 2.x gemstone with a virgin extent0.dbf and a config file specifying
#    all extents required for your 2.x system. Extent pregrow is recommended.
# 7. run the script conv2gTo2x. This script exists in the 2.x product tree
#    under the bin directory, so it needn't be called with an explicit path
# 8. wait for conv2gTo2x to exit.
# 9. restart the 2.x stone
# 10. run the script upgradeImageFrom2g. This script exists in the 2.x product
#     tree under the bin directory, so it needn't be called with an explicit
#     path.
# 11. run the script postconv. This script exists in the 2.x product tree under
#     the bin directory, so it needn't be called with an explicit path.
#
# $Id: convprep2g.sh,v 1.3 2008-01-09 22:50:52 stever Exp $
#
#=========================================================================

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="convprep2g"              # 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]: $*
}
usage() {
cat <<EOF
Usage:
convprep2g [-h] [-s <stonename>]
Prepare a GemStone/S 2G repository for conversion to GemStone/S 64 bit 2.x.
Environment requirements:
    GEMSTONE          set to a GemStone/S 2G product tree
    upgradeLogDir     set to a writable directory
Parameters:
    -h print this Usage and exit
    -s <stonename>
        where <stonename> is the name of a running 2G stone (defaults
        to gemserver12)
EOF
}

# defaults
stoneName=gemserver12

#process command line
while getopts "hs:" opt; do
  case $opt in 
    h ) usage; exit 0 ;;
    s ) stoneName=$OPTARG ;;
   \? ) error "bad arg: $opt"; usage; exit 1 ;;
  esac
done
export stoneName

# 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 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."

# clean up from previous runs, if any...
rm $upgradeLogDir/convprep2g.log $upgradeLogDir/*.bm $upgradeLogDir/*.topaz \
$upgradeLogDir/ClassesForListInstances.txt $upgradeLogDir/ListOfSegments.txt \
$upgradeLogDir/from*.out >/dev/null 2>&1

# start topaz
info "starting topaz for conversion prep. This may take a while..."

$GEMSTONE/bin/topaz -l -i << EOF >$upgradeLogDir/convprep2g.log 2>&1
output push $upgradeLogDir/convprep2g.out only
set gemstone $stoneName
set u SystemUser p swordfish
login

iferror exit 1
display resultcheck
time

! This method was added in GS 2G 1.2.3 and is required for conversion.
expectvalue %GsMethod
run
"Generates a run-time error if the method is not present."
Repository compiledMethodAt: #_writeGs64UpgradeDataToDirectory:
%

omit resultcheck
! file in the SmallDouble class
! this version only files in the class if it does not already exist
input $GEMSTONE/upgrade/smalldoub_2gto20.gs
commit

! Write out the list of segments used by this repository, in order.
expectvalue true
run
|outFile outFileName|

outFileName := String withAll: '$upgradeLogDir'.
(outFileName last == $/)
  ifFalse:[outFileName add: $/].
outFileName addAll: 'ListOfSegments.txt'.
outFile := GsFile openOnServer: outFileName mode: 'w'.
(outFile == nil)
  ifTrue:[^(String withAll: 'Cannot open output file ') addAll: outFileName; yourself].

outFile nextPutAll: SystemRepository size asString; lf.
SystemRepository do:[:eachSegment|
  outFile nextPutAll: eachSegment asOop asString; lf.
].
outFile close.
^true
%

! Read the IdentitySet containing a list of classes that the User wants us to 
! locate all instances of during conversion.
! This is strictly optional.

expectvalue %Boolean
run

|setOfClasses outFile outFileName nextLine|

setOfClasses := System myUserProfile resolveSymbol: #ConversionClassesToFind.

(setOfClasses == nil)
  ifTrue:[^false].

setOfClasses := setOfClasses value.

(setOfClasses size == 0)
  ifTrue:[^false].

(setOfClasses isKindOf: IdentitySet)
  ifFalse:[^String withAll: 'ConversionClassesToFind expected to be anIdentitySet'].

outFileName := String withAll: '$upgradeLogDir'.
(outFileName last == $/)
  ifFalse:[outFileName add: $/].
outFileName addAll: 'ClassesForListInstances.txt'.
outFile := GsFile openOnServer: outFileName mode: 'w'.
(outFile == nil)
  ifTrue:[^(String withAll: 'Cannot open output file ') addAll: outFileName; yourself].

setOfClasses do:[:eachClass|
  (eachClass isBehavior _and:[eachClass isMeta not]) ifTrue:[
  |theName theOop|
  theName := eachClass name asString.
  theOop := eachClass asOop asString.
  outFile nextPutAll: theName; nextPut: $|; nextPutAll: theOop; lf.
  ].
].
outFile close.
^true
%


display resultcheck
expectvalue true
run
|stoneStats|
stoneStats := System cacheStatistics: 1.
((stoneStats at: 50) == 0)
  ifFalse:[^'Error: Possible dead set not empty'].
((stoneStats at: 88) == 0)
  ifFalse:[^'Error: GcPossible dead set not empty'].
((stoneStats at: 51) == 0)
  ifFalse:[^'Error: DeadNotReclaimed set not empty'].
^true
%

! Stop all sessions.  Shadow page reclaim will be done by stone
expectvalue true
run
System stopOtherSessions.
[System currentSessions size == 1] whileFalse:[
  System sleep: 1.
  System stopOtherSessions.
  System sleep: 1.
].
^true
%

abort

expectvalue true
run
System _reclaimAllParallel
%

abort
! Make sure we only have 1 Commit record left.
expectvalue 1
run
(System cacheStatistics: 1) at: 35
%

! All shadow pages should be gone, make sure
expectvalue 0
run
SystemRepository _dpnsUnionSize
%

expectvalue 0
run
SystemRepository _shadowPagesCount
%


! Now, finally, write the conversion files
expectvalue %Array
run
SystemRepository _writeGs64UpgradeDataToDirectory: '$upgradeLogDir'
%

! do a clean shutdown
expecterror GemStoneError 4057
send System shutDown

exit 
EOF

status=$?
if [ $status -ne 0 ]; then
  error "...topaz exited with status $status"
else
  info "...conversion preparation complete."
  touch $upgradeLogDir/from2g_1.out
fi
exit $status
