#! /bin/sh
# set -xv
#=========================================================================
# Copyright (C) GemTalk Systems 2019-2024.  All Rights Reserved.
#
# Name - upgradeSeasideImage
# Installed as - upgradeSeasideImage
#
# Purpose - 
#
# This script reloads GLASS (extent0.seaside.dbf), GLASS1 or tODE after a 
#		GemStone upgradeImage has been performed.
# Currently upgrades from GemStone/S 64 Bit 3.2.0 or later are supported.
#
#	If the upgrade is from GemStone/S 64 Bit 3.2.x, all methods must be recompiled
#		and this script removes all of the methods from the classes from the symbol
#		dictionary into which GLASS, GLASS1 or tODE has been installed.
# For GemStone versions 3.3.0 and beyond, the GLASS, GLASS1 or tODE application
#		is reloaded into the image.
# Following completion of this script, you should reload your own application code.
#
# See the GsDevKit/GsDevKit_upgrade project 
#		(https://github.com/GsDevKit/GsDevKit_upgrade/blob/master/README.md) for
#		latest details and instructions
#
#=========================================================================

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

upgradeDir=$GEMSTONE/upgrade
export upgradeDir

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

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

. $GEMSTONE/bin/misc.sh

usage() {
  cat <<EOF
Usage:
$comid [-c <tempObjCacheSize>][-s <stoneName>][-W]
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:
		-s <stoneName>
				where <stoneName> is the name of a running 3.x stone.
				Default: gs64stone
		-c <tempObjCacheSize>
				size of temp obj cache to use in KB.
				Default: 100000
		-u <Gemstone User>
				if other than DataCurator has seaside installed.
				Default: DataCurator
		-p <password>
				Default: swordfish.
		-P <path>
				path to customized to GsDevKit_upgrade instance creation script
				Default: $upgradeDir/createGsDevKit_upgrade.topaz
		-E
				enable isNil optimization (leave enabled). upgradeImage enables isNil 
				optimization by default but, there are potential problems with isNil 
        optimization in some Seaside projects, upgradeSeasideImage disables 
				isNil optimiazation unless this options is specified. See 
				https://github.com/GsDevKit/GsDevKit_upgrade/issues/30 for more information
		-W
				enable TOPAZWAITFORDEBUG, to allow remote debugging via DEBUGGEM
EOF
}


defaultErrorControl

# default GEM_TEMPOBJ_CACHE_SIZE -- default to 100000
tmpObjSize=100000
stoneName=gs64stone
username=DataCurator
password=swordfish
createpath="$upgradeDir/createGsDevKit_upgrade.topaz"
topazWaitForDebug="ex pass"
deoptimizeIsNil="true"
# process command line
while getopts "c:s:u:p:EP:W" opt; do
  case $opt in 
    c ) tmpObjSize=$OPTARG ;;
    s ) stoneName=$OPTARG ;;
    u ) username=$OPTARG ;;
    p ) password=$OPTARG ;;
		E ) deoptimizeIsNil="false" ;;
    P ) createpath=$OPTARG ;;
		W ) topazWaitForDebug="System waitForDebug" ;;
   \? ) usage; exit 1 ;;   
  esac
done
export stoneName

# make sure tmpObjSize is within legal limits
if [ $tmpObjSize -gt 1000000 ] || [ $tmpObjSize -lt 1000 ]; then
  echo "ERROR: Cannot set GEM_TEMPOBJ_CACHE_SIZE to $tmpObjSize."
  echo "ERROR: This value must be between 1000 and 1000000."
  usage
  exit 1
fi

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

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

# create a gem config file to use

cat <<EOF >$upgradeLogDir/conversion.conf
GEM_TEMPOBJ_CACHE_SIZE = $tmpObjSize;
EOF

cat <<EOF

Starting GemStone/S 64 3.x Seaside upgrade.

Note:	This script should be run AFTER upgradeImage has been run.
			SessionMethods will be enabled and all code included in the 
			GLASS, GLASS1 or tODE project will be reloaded.
		
			There are 4 phases performed by this script and each script is 
			performed in its own topaz session:

			1. As SystemUser, install GsDevKit_upgrade code and 
					GsuAbstractGsDevKitUpgrade>>prepareImage. 
			2. As $username, GsuAbstractGsDevKitUpgrade>>prepareImage_pragma_user 
			3. As SystemUser, GsuAbstractGsDevKitUpgrade>>prepareImage_pragma_systemuser
			4. As $username, GsuAbstractGsDevKitUpgrade>>prepareImage_user and 
					GsuAbstractGsDevKitUpgrade>>prepareGsDevKitImage

			For additional details about the work performed during each phase see
			https://github.com/GsDevKit/GsDevKit_upgrade .
	
Stone name is $stoneName.

Press the return key to continue...
EOF
read prompt

$GEMSTONE/bin/waitstone "$stoneName" -1 > /dev/null
waitstone_stat="$?"
if [ $waitstone_stat -ne 0 ]; then
  echo "ERROR: no stone named $stoneName running on this machine."
  usage
  exit 1
fi

echo `date`
echo "Starting GLASS/GLASS1/GsDevKit/TODE upgrade for ${stoneName}..."

echo "############################################################################"
echo "1. As SystemUser, conditionally disable isNil optimization. install GsDevKit_upgrade code and GsuAbstractGsDevKitUpgrade>>prepareImage." 
cat <<EOF >$upgradeLogDir/createGsDevKit_upgrade.topaz
output append $upgradeLogDir/upgradeSeasideImage.out only
! from  seaside/bin/upgradeSeasideImage createGsDevKit_upgrade step
input $createpath
output pop
EOF

cat <<EOF >$upgradeLogDir/installGsDevKit_upgrade.topaz
output append $upgradeLogDir/upgradeSeasideImage.out
! from  seaside/bin/upgradeSeasideImage installGsDevKit_upgrade.topaz step 
fileformat UTF8
display resultcheck
limit bytes 2000
limit lev1bytes 2000
level 0
display oops
iferr 1 where
iferr 2 stack
iferr 4 input pop

set user SystemUser password swordfish
set gemstone $stoneName
login
EOF

## conditionally undo isNil optimization -- append to installGsDevKit_upgrade.topaz
if [ "$deoptimizeIsNil" = "true" ] ; then
cat <<EOF >>$upgradeLogDir/installGsDevKit_upgrade.topaz
output append $upgradeLogDir/upgradeSeasideImage.out
! from  seaside/bin/upgradeSeasideImage installGsDevKit_upgrade.topaz step (conditional undo isNil optimization) 

# --BEGIN----- undo isNil optimization
category: 'Private'
classmethod: GsNMethod
_adjustOptimizedSelectors
  OptimizedSelectors := #( notNil yourself ).
%
run
| x |
GsNMethod _adjustOptimizedSelectors .
(x := GsNMethod configurableOptimizedSelectors) = #( notNil yourself) 
ifFalse:[ Error signal: 'wrong value ', x printString ].
true
%
commit
logout
login

expectvalue /Integer
run
 | cnt | 
 cnt := 0 .
 ((ClassOrganizer new substringSearch: 'isNil') at: 1) do:[:meth |
   meth recompileFromSource .
   GsFile gciLogServer:'recompiled  ' , meth printString .
   cnt := cnt + 1 .
 ].
 ^ cnt
%
commit
# --END----- undo isNil optimization
logout

EOF
fi

cat <<EOF >>$upgradeLogDir/installGsDevKit_upgrade.topaz
output append $upgradeLogDir/upgradeSeasideImage.out
! from  seaside/bin/upgradeSeasideImage installGsDevKit_upgrade.topaz step (install $upgradeDir/installGsDevKit_upgrade.topaz)
login
run
	"Used in GsDevKit_upgrade instance creation script (option -P), during installGsDevKit_upgrade.topaz"
	[ UserGlobals at: #SeasideUpgradeUser put: '$username' ]
		on: Error
		do: [:ex | $topazWaitForDebug ].
	System commitTransaction.
%

run
GsFile gciLogServer: '---'.
GsFile gciLogServer: 'installing $upgradeDir/installGsDevKit_upgrade.topaz'.
GsFile gciLogServer: '---'.
true
%

input $upgradeDir/installGsDevKit_upgrade.topaz

run
	GsDevKit_Image_Upgrade prepareImage.
	UserGlobals removeKey: #SeasideUpgradeUser.
	System commitTransaction.
%

logout
expectvalue 0
errorcount
output pop
exit
EOF

$GEMSTONE/bin/topaz -i -l -e $upgradeLogDir/conversion.conf -C 'GEM_LISTEN_FOR_DEBUG=TRUE' < $upgradeLogDir/installGsDevKit_upgrade.topaz > $upgradeLogDir/installGsDevKit_upgrade_topaz.log 2>&1

topaz_stat=$?
if [ $topaz_stat -ne 0 ]; then
  echo "ERROR: topaz exited with status $topaz_stat in installGsDevKit_upgrade and prepareImage."
  echo "Please check the file upgradeSeasideImage.out in "
  echo "$upgradeLogDir for errors."
  exit $topaz_stat
fi

echo "############################################################################"
echo "2. As $username, GsuAbstractGsDevKitUpgrade>>prepareImage_pragma_user"

cat <<EOF >$upgradeLogDir/prepareGsDevKitImage_pragma_user.topaz
output append $upgradeLogDir/upgradeSeasideImage.out
! from  seaside/bin/upgradeSeasideImage prepareGsDevKitImage_pragma_user.topaz  step 
fileformat UTF8
display resultcheck
limit bytes 2000
limit lev1bytes 2000
level 0
display oops
iferr 1 where
iferr 2 stack
iferr 4 input pop
set user $username password $password
set gemstone $stoneName
login

run
	[ (((AllUsers userWithId: 'SystemUser') 
		objectNamed: #UserGlobals) 
			at: #'GsDevKit_Image_Upgrade')
				prepareImage_pragma_user ]
		on: Error
		do: [:ex | $topazWaitForDebug ].
	System commitTransaction.
%

expectvalue 0
errorcount
output pop
exit
EOF

$GEMSTONE/bin/topaz -i -l -e $upgradeLogDir/conversion.conf -I $upgradeLogDir/seasideini -C 'GEM_LISTEN_FOR_DEBUG=TRUE' < $upgradeLogDir/prepareGsDevKitImage_pragma_user.topaz > $upgradeLogDir/prepareGsDevKitImage_pragma_user.log 2>&1

topaz_stat=$?
if [ $topaz_stat -ne 0 ]; then
  echo "ERROR: topaz exited with status $topaz_stat in prepareGsDevKitImage_pragma_user."
  echo "Please check the file upgradeSeasideImage.out in "
  echo "$upgradeLogDir for errors."
  exit $topaz_stat
fi

echo "############################################################################"
echo "3. As SystemUser, GsuAbstractGsDevKitUpgrade>>prepareImage_pragma_systemuser"

cat <<EOF >$upgradeLogDir/prepareImage_pragma_systemuser.topaz
output append $upgradeLogDir/upgradeSeasideImage.out
! from  seaside/bin/upgradeSeasideImage prepareImage_pragma_systemuser.topaz step
fileformat UTF8
display resultcheck
level 0
limit bytes 2000
limit lev1bytes 2000
display oops
iferr 1 where
iferr 2 stack
iferr 4 input pop

set user SystemUser password swordfish
set gemstone $stoneName
login

run
	[ GsDevKit_Image_Upgrade prepareImage_pragma_systemuser ]
		on: Error
		do: [:ex | $topazWaitForDebug ].
	System commitTransaction.
%

logout
expectvalue 0
errorcount
output pop
exit
EOF

$GEMSTONE/bin/topaz -i -l -e $upgradeLogDir/conversion.conf -C 'GEM_LISTEN_FOR_DEBUG=TRUE' < $upgradeLogDir/prepareImage_pragma_systemuser.topaz > $upgradeLogDir/prepareImage_pragma_systemuser_topaz.log 2>&1

topaz_stat=$?
if [ $topaz_stat -ne 0 ]; then
  echo "ERROR: topaz exited with status $topaz_stat in prepareImage_pragma_systemuser."
  echo "Please check the file upgradeSeasideImage.out in "
  echo "$upgradeLogDir for errors."
  exit $topaz_stat
fi

echo "############################################################################"
echo "4. As $username, GsuAbstractGsDevKitUpgrade>>prepareImage_user and GsuAbstractGsDevKitUpgrade>>prepareGsDevKitImage"

cat <<EOF >$upgradeLogDir/prepareGsDevKitImage.topaz
output append $upgradeLogDir/upgradeSeasideImage.out
! from  seaside/bin/upgradeSeasideImage prepareGsDevKitImage.topaz step 
fileformat UTF8
display resultcheck
level 0
limit bytes 2000
limit lev1bytes 2000
display oops
iferr 1 where
iferr 2 stack
iferr 4 input pop

set user $username password $password
set gemstone $stoneName
login

run
	[ (((AllUsers userWithId: 'SystemUser') 
		objectNamed: #UserGlobals) 
			at: #'GsDevKit_Image_Upgrade')
				prepareImage_user;
				prepareGsDevKitImage ]
		on: Error
		do: [:ex | $topazWaitForDebug ].
System commitTransaction.
%

expectvalue 0
errorcount
output pop
exit
EOF

$GEMSTONE/bin/topaz -i -l -e $upgradeLogDir/conversion.conf -I $upgradeLogDir/seasideini -C 'GEM_LISTEN_FOR_DEBUG=TRUE' < $upgradeLogDir/prepareGsDevKitImage.topaz > $upgradeLogDir/prepareGsDevKitImage.log 2>&1

topaz_stat=$?
if [ $topaz_stat -ne 0 ]; then
  echo "ERROR: topaz exited with status $topaz_stat in prepareGsDevKitImage."
  echo "Please check the file upgradeSeasideImage.out in "
  echo "$upgradeLogDir for errors."
  exit $topaz_stat
fi

echo "############################################################################"
echo "5. As SystemUser, Remove  globals created during upgrade."

cat <<EOF >$upgradeLogDir/cleanupGsDevKitImage.topaz
output append $upgradeLogDir/upgradeSeasideImage.out
! from  seaside/bin/upgradeSeasideImage cleanupGsDevKitImage.topaz step
fileformat UTF8
display resultcheck
level 0
limit bytes 2000
limit lev1bytes 2000
display oops
iferr 1 where
iferr 2 stack
iferr 4 input pop
set user SystemUser password swordfish
set gemstone $stoneName
login

run
	[ UserGlobals removeKey: #'GsDevKit_Image_Upgrade' ifAbsent: [].
	UserGlobals removeKey: #'GsDevKit_Upgrade_Cache' ifAbsent: [] ]
		on: Error
		do: [:ex | $topazWaitForDebug ].
System commitTransaction.
%

expectvalue 0
errorcount
output pop
exit
EOF

$GEMSTONE/bin/topaz -i -l -e $upgradeLogDir/conversion.conf -I $upgradeLogDir/seasideini -C 'GEM_LISTEN_FOR_DEBUG=TRUE' < $upgradeLogDir/cleanupGsDevKitImage.topaz > $upgradeLogDir/cleanupGsDevKitImage.log 2>&1

topaz_stat=$?
if [ $topaz_stat -ne 0 ]; then
  echo "ERROR: topaz exited with status $topaz_stat in cleanupGsDevKitImage."
  echo "Please check the file upgradeSeasideImage.out in "
  echo "$upgradeLogDir for errors."
  exit $topaz_stat
fi

echo "GsDevKit Upgrade completed (GLASS/GLASS1/GsDevKit/tODE). No errors detected."
exit 0
