#!/bin/sh
#------------------------------------------------------------------------------
# ========= |
# \\ / F ield | foam-extend: Open Source CFD
# \\ / O peration |
# \\ / A nd | For copyright notice see file Copyright
# \\/ M anipulation |
#------------------------------------------------------------------------------
# License
# This file is part of foam-extend.
#
# foam-extend is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# foam-extend is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with foam-extend. If not, see .
#
# Script
# foamEndJob
#
# Description
# Ends running job on current machine. Called with root,case,pid.
# - checks if pid exists
# - modifies controlDict
# - waits until
# - pid disappeared
# - controlDict modified
# to restore controlDict
#
#------------------------------------------------------------------------------
PROGNAME=`basename $0`
#------------------------------------------------------------------------------
#
# Functions
#
#------------------------------------------------------------------------------
# getNumberedLine dictionary entry
# Prints dictionary entry line + lineno
getNumberedLine() {
grep -n "^[ \t]*$2[ \t]" $1 | grep -v '^//' | head -1
}
# getLine dictionary entry
# Prints dictionary entry line (without lineno)
getLine() {
getNumberedLine $1 "$2" | sed -e 's/^[^:]*://'
}
# getRawEntry dictionary entry
# Prints value of dictionary entry
getRawEntry() {
getLine $1 "$2" | sed -e "s/^[ \t]*$2[ \t][ \t]*//"
}
# getEntry dictionary entry
# Like getRawEntry but strips " and ending ';'
getEntry() {
getRawEntry $1 "$2" | sed -e 's/^"//' -e 's/;$//' -e 's/"$//'
}
# getKey entryLine
# Prints first item on line
getKey() {
echo "$1" | sed -e 's/[ \t]*\(.*\)[ \t].*/\1/'
}
# setRawEntry dictionary entry newValue
# Replaces value of entry
setRawEntry() {
oldNumLine=`getNumberedLine $1 "$2"`
lineNo=`echo "$oldNumLine" | sed -e 's/:.*//'`
oldLine=`echo "$oldNumLine" | sed -e 's/^[^:]*://'`
oldKey=`getKey "$oldLine"`
oldVal=`getRawEntry $1 "$2"`
if [ ! "$oldKey" -o ! "$oldVal" -o ! "$oldLine" ]; then
echo "setRawStringEntry: entry $2 not found in $1"
echo "oldKey=$oldKey"
echo "lineNo=$lineNo"
echo "oldLine=$oldLine"
exit 1
fi
#echo "oldKey=$oldKey"
#echo "lineNo=$lineNo"
#echo "oldLine=$oldLine"
#echo "oldVal=$oldVal"
mv $1 ${1}_tmp
sed -e "${lineNo}s/ ${oldVal}/ $3;/" ${1}_tmp > $1
rm -f ${1}_tmp
}
# like getEntry but returns true if boolean is logical true
getBoolEntry()
{
val=`getEntry $1 $2`
case "$val" in
'yes')
return 0
;;
'no')
return 123
;;
'true')
return 0
;;
'false')
return 123
;;
1)
return 0
;;
0)
return 123
;;
*)
echo "$PROGNAME : getBoolEntry : Illegal boolean value $val in dictionary $1"
exit 1
;;
esac
}
# newerFile file1 file2
newerFile() {
latest=`ls -1 -t $1 $2 2> /dev/null | head -1`
if [ "$latest" = $1 ]; then
return 0
else
return 1
fi
}
# processExists pid
# Returns true if pid exists.
processExists() {
ps -u $LOGNAME -o 'pid' | fgrep $1 >/dev/null
}
printUsage() {
cat << USAGELABEL
Usage: $PROGNAME [-n]
or
$PROGNAME -c
Tries to end running Foam application at next write or at next time
step (-n option). It needs runTimeModifiable switched on in the
controlDict. It changes stopAt in the controlDict and waits for the job to
finish. Restores original controlDict if
- job has finished
- controlDict gets modified (by user)
- $PROGNAME gets killed.
The -c option clears any outstanding $PROGNAME for the case.
USAGELABEL
}
# Restore controlDict and clean up
restoreDict() {
trap 2 3 15
echo "$PROGNAME : Restoring controlDict from controlDict_bak."
if [ -r ${controlDict}_bak ]; then
cp ${controlDict}_bak $controlDict
fi
rm -f $pidFile
echo "$PROGNAME : Exiting."
exit 0
}
#------------------------------------------------------------------------------
#
# Main
#
#------------------------------------------------------------------------------
ARCH=`uname -s`
#-- Force standards behaving ps
# Get info on all $USER processes
case $ARCH in
HP-UX*)
UNIX95=a; export UNIX95
;;
IRIX*)
_XPG=1; export _XPG
;;
esac
#
# Initial checks
#
if [ $# -lt 3 ]; then
printUsage
exit 1
fi
STOPNOW=''
if [ $1 = '-n' ]; then
STOPNOW='yes'
shift
fi
CLEAR=''
if [ $1 = '-c' ]; then
CLEAR='yes'
shift
if [ $# -ne 2 ]; then
printUsage
exit 1
fi
ROOT=$1
CASE=$2
else
if [ $# -ne 3 ]; then
printUsage
exit 1
fi
ROOT=$1
CASE=$2
PID=$3
fi
CASE=`echo $CASE | sed -e 's!/.*!!'` #strip of processorXXX ending
#- Pid actually running
if [ ! "$CLEAR" ]; then
processExists $PID
if [ $? -ne 0 ] ;then
echo "$PROGNAME : process $PID not running."
exit 1
fi
fi
#- case directory writeable
if [ ! -w $ROOT/$CASE ]; then
echo "$PROGNAME : $ROOT/$CASE is not writeable."
exit 1
fi
#- Controldict writeable
controlDict=$ROOT/$CASE/system/controlDict
if [ ! -w $controlDict ]; then
echo "$PROGNAME : $controlDict is not writeable."
exit 1
fi
#- runTimeModifiable
getBoolEntry $controlDict 'runTimeModifiable'
if [ $? -ne 0 ]; then
echo "$PROGNAME : runTimeModifiable not true in dictionary $controlDict."
exit 1
fi
#
#- Check if another foamEndJob running
#
if [ "$CLEAR" ]; then
pidFiles=`ls $ROOT/$CASE/.foamEndJob* 2>/dev/null`
for pidFile in $pidFiles
do
pid=`cat $pidFile`
if [ "$pid" ]; then
echo "$PROGNAME : found $PROGNAME (pid $pid) for Foam process"
echo " root: $ROOT"
echo " case: $CASE"
echo "$PROGNAME : Killing $PROGNAME (pid $pid)."
kill $pid
rm -f $pidFile
fi
done
exit 0
fi
pidFile=$ROOT/$CASE/.foamEndJob${PID}
if [ -f $pidFile ]; then
pid=`cat $pidFile`
if [ "$pid" ]; then
processExists $pid
if [ $? -eq 0 ] ;then
echo "$PROGNAME : found running $PROGNAME (pid $pid) for Foam process"
echo " root: $ROOT"
echo " case: $CASE"
echo " pid : $PID"
echo " lock: $pidFile"
echo "Remove the lock if this is not the case."
exit 1
fi
fi
fi
# Mark with my pid
echo $$ > $pidFile
#
#- Get controlDict entries
#
#- startTime
startTime=`getEntry $controlDict 'startTime'`
if [ ! "$startTime" ]; then
echo "$PROGNAME : startTime not set in dictionary $controlDict."
exit 1
fi
#- Write interval
writeInterval=`getEntry $controlDict 'writeInterval'`
if [ ! "$writeInterval" ]; then
echo "$PROGNAME : writeInterval not set in dictionary $controlDict."
exit 1
fi
#- stopAt
stopAt=`getEntry $controlDict 'stopAt'`
if [ ! "$stopAt" ]; then
echo "$PROGNAME : stopAt not set in dictionary $controlDict."
exit 1
fi
#- endTime
endTime=`getEntry $controlDict 'endTime'`
if [ ! "$endTime" ]; then
echo "$PROGNAME : endTime not set in dictionary $controlDict."
exit 1
fi
echo "$PROGNAME : Read from controlDict:"
echo " controlDict : $controlDict"
echo " writeInterval : $writeInterval"
#echo " startTime : $startTime"
echo " stopAt : $stopAt"
#echo " endTime : $endTime"
echo "$PROGNAME : Making backup of controlDict to controlDict_bak"
cp $controlDict ${controlDict}_bak
#- Set up handler to restore controlDict
trap restoreDict 2 3 15
if [ "$STOPNOW" ]; then
setRawEntry $controlDict 'stopAt' 'nextWrite'
setRawEntry $controlDict 'writeInterval' '1'
echo "$PROGNAME : Changed in controlDict:"
echo " `getLine $controlDict 'stopAt'`"
echo " `getLine $controlDict 'writeInterval'`"
else
setRawEntry $controlDict 'stopAt' 'nextWrite'
echo "$PROGNAME : Changed in controlDict:"
echo " `getLine $controlDict 'stopAt'`"
fi
#- Just to make sure time has changed
touch ${controlDict}
sleep 5
#- Give bak a later date
touch ${controlDict}_bak
#- Loop a while to give NFS time to update
if newerFile ${controlDict} ${controlDict}_bak; then
echo "$PROGNAME : controlDict newer than controlDict_bak."
echo "$PROGNAME : Waiting for file dates to get updated."
iter=0
while newerFile ${controlDict} ${controlDict}_bak
do
if [ $iter -ge 120 ]; then
#- 120*5 sec = 10 mins passed. Give up
echo "$PROGNAME : File date not yet ok after 10 mins. Giving up."
break
fi
#- Give _bak a later time
touch ${controlDict}_bak
#- Give nfs some time to update time on controlDict.
sleep 5
iter=`expr $iter + 1`
done
fi
#
#- Start waiting until:
# - pid finished. Restore controlDict.
# - controlDict modified. No restore.
# - controlDict_bak removed. No restore.
echo "$PROGNAME : Waiting for Foam job $PID to finish ..."
while true
do
sleep 5
if [ ! -r ${controlDict}_bak ]; then
echo "$PROGNAME : ${controlDict}_bak dissappeared. Exiting without restore."
exit 1
fi
if newerFile ${controlDict} ${controlDict}_bak; then
echo "$PROGNAME : ${controlDict} modified externally. Exiting without restore."
exit 0
fi
processExists $PID
if [ $? -ne 0 ] ;then
#- Job finished
break
fi
#echo "Foam job $PID still running ..."
done
#- Dictionary restore
restoreDict
#------------------------------------------------------------------------------