#!/bin/bash

if [ -s $GEMSTONE/seaside/etc/gemstone.secret ]; then
    . $GEMSTONE/seaside/etc/gemstone.secret
else
    echo 'Missing password file $GEMSTONE/seaside/etc/gemstone.secret'
    exit 1
fi

cat << EOF | nohup $GEMSTONE/bin/topaz -l -T200000 2>&1 > $GEMSTONE_LOGDIR/maintenance_gem.log &

set user DataCurator pass $GEMSTONE_CURATOR_PASS gems $GEMSTONE_NAME

display oops
iferror where

login

run
"record gems pid in the pid file"
| file |
(GsFile isServerDirectory: '$GEMSTONE_DATADIR') ifFalse: [ ^nil ].
file := GsFile openWriteOnServer: '$GEMSTONE_DATADIR/maintenance_gem.pid'.
file nextPutAll: (System gemVersionReport at: 'processId') printString.
file cr.
file close.
(ObjectLogEntry
  info: 'MTCE: startup'
  object: 'pid: ', (System gemVersionReport at: 'processId') printString) addToLog.
System commitTransaction.
%

run
| count expirations |
true "enable for remote breakpoints and profiling"
  ifTrue: [
    GemToGemAnnouncement installStaticHandler.
    Exception
      installStaticException:
        [:ex :cat :num :args | 
          BreakpointNotification signal.
          "needed to avoid infinite loop when resuming from a breakpoint"
          ex _incrementBreakpointsToIgnore. ]
      category: GemStoneError
      number: 6005 "#rtErrCodeBreakpoint"
      subtype: nil.
   System commitTransaction ifFalse: [ nil error: 'Could not commit for GemToGemSignaling' ]].

System transactionMode: #manualBegin.
Exception 
  installStaticException: 
    [:ex :cat :num :args |
      "Run the abort in a lowPriority process, since we must acquire the
       transactionMutex."
      [
        SeasidePlatformSupport transactionMutex 
          critical: [ 
            SeasidePlatformSupport doAbortTransaction ].
        System enableSignaledAbortError.
      ] forkAt: Processor lowestPriority.
    ]
  category: GemStoneError
  number: 6009 "#rtErrSignalAbort"
  subtype: nil.
System enableSignaledAbortError.
"This thread is needed to handle the SigAbort exception, when the primary
 thread is blocked. Assuming default 60 second STN_GEM_ABORT_TIMEOUT, wake 
 up at 30 second intervals."
[ 
  [ true ] whileTrue: [ (Delay forSeconds: 30) wait ].
] forkAt: Processor lowestPriority.

expirations := count := 0.
[true] whileTrue: [ [ | expired dps |
  expired := 0.
  GsFile gciLogServer: DateAndTime now printString.
  GsFile gciLogServer: 'Unregistering...'.
  "Auto transaction mode while expiring sessions"
  System transactionMode: #autoBegin.
  GsFile gciLogServer: 'Begin AutoTransaction: ', System inTransaction printString.
  expirations := expirations + 1.
  System _sessionCacheStatAt: 5 put: expirations.
  System _sessionCacheStatAt: 6 put: 0.
  dps := OrderedCollection with: WADispatcher default.
  [dps isEmpty] whileFalse: [ | dp |
    dp := dps removeFirst.
    dp entryPoints do: [:ep |
        ep isApplication 
            ifTrue: [expired := expired + (ep unregisterExpiredHandlers)]
            ifFalse: [ep isDispatcher ifTrue: [dps add: ep]].
    ].
  ].
  GsFile gciLogServer: 'Finish expiration loop: ', System inTransaction printString.
  expirations := expirations + 1.
  System _sessionCacheStatAt: 5 put: expirations.
  System _sessionCacheStatAt: 6 put: expired.
  expired > 0 ifTrue: [ (ObjectLogEntry trace: 'MTCE: expired sessions' object: expired) addToLog ].
  GsFile gciLogServer: '...Expired: ', expired printString, ' sessions.'.
  GsFile gciLogServer: 'Before commit: ', System inTransaction printString.
  System commitTransaction.
  System transactionMode: #manualBegin.
  ((count \\\\ 60) = 0) 
    ifTrue: [ 
      GsFile gciLogServer: DateAndTime now printString.
      GsFile gciLogServer: 'Starting markForCollect.'.
      [
        SystemRepository markForCollection
      ] on: Error 
        do: [:ex | 
          ((ex gsNumber == 3020) _or: [ex gsNumber == 3006])
            ifTrue: [ | fileSize freeSpace used fileUnit freeUnit usedUnit |
              fileSize := SystemRepository fileSize / 1024.0.
              freeSpace := SystemRepository freeSpace / 1024.0.
              used := fileSize - freeSpace.
              fileUnit := fileSize > (1024)
                ifTrue: [
                  fileSize := fileSize / 1024.
                  'M']
                ifFalse: ['K'].
              freeUnit := freeSpace > (1024)
                ifTrue: [
                  freeSpace := freeSpace / 1024.
                  'M']
                ifFalse: ['K'].
              usedUnit := used > (1024)
                ifTrue: [
                  used := used / 1024.
                  'M']
                ifFalse: ['K'].
              System beginTransaction.
              (ObjectLogEntry 
                trace: 'MTCE: Repository Size' 
                object: 'Repository: ', fileSize displayString, fileUnit, 
                        ', Free: ', freeSpace displayString, freeUnit,
                        ', Used: ', used displayString, usedUnit) addToLog.
              (ObjectLogEntry trace: 'MTCE: MFC' object: ex) addToLog.
              System commitTransaction.
              GsFile gciLogServer: ex description]
            ifFalse: [ex pass ]
        ].
      GsFile gciLogServer: DateAndTime now printString.
      GsFile gciLogServer: '...finished markForCollect.'.
    ].
  "Sleep for a minute"
  (Delay forSeconds: 60) wait.
  count := count + 1] 
    on: Error, Halt, BreakpointNotification
    do: [:ex | 
	  System inTransaction
		ifTrue: [ 
          DebuggerLogEntry createContinuationLabeled: 'MTCE continuation'.
          System commitTransaction.
          System beginTransaction ]
        ifFalse: [
          System beginTransaction.
          DebuggerLogEntry createContinuationLabeled: 'MTCE continuation'.
          System commitTransaction].
      ex isResumable ifTrue: [ex resume]]].
%
run
GemToGemAnnouncement uninstallStaticHandler.
System beginTransaction.
(ObjectLogEntry
  fatal: 'MTCE: topaz exit'
  object:
    'pid: ', (System gemVersionReport at: 'processId') printString) addToLog.
System commitTransaction.
%
EOF
