#!/bin/sh
#
# @(#) $Id: //bas/720_REL/src/krn/startscripts/stopdbora#1 $ 
#
# NAME: stopdb 
#
# PURPOSE: stop an ORACLE database
#
# Environment
#       ORACLE_HOME     must be set
#       ORACLE_SID      must be set
# PARAMETER: 
#       none
# USAGE: stopdb [ORACLE_HOME] [stopRemoteService]
#
# Return Codes:
#       0       ok
#       1       DB not available
#       2       Environment error.
#       3       DB was running, could not be stopped.
#       4       script was killed
#       5       DB inconsistency?
#
# orasrv will not be stopped for this service could be used
# from different databases 
#
# DGUX and Sequent exceptions
# R3trans is not available on the DG standalone DB server
# therefore the Oracle processes are checked

#====================================================================
#
# FUNCTION: check_db_running
#
# PURPOSE:  check wheather db is runnig without R3trans 
# set returncode = 0  db available
#     returncode != 0 db error
#
check_db_running()
{
  # in order to find out if the database is not available
  # check whether the Oracle processes are running or not
  echo "
  ------------------------------------------------------------- " >> $LOG
  echo `date` >> $LOG
  echo "check if Oracle processes are running" >> $LOG
  $PS | grep ora_[a-z][a-z][a-z][a-z]_${ORACLE_SID} > /dev/null 2>&1
  if [ $? -eq 0 ]; then
    echo 'Database is running' >> $LOG
    echo 'Continue with stop procedure' >> $LOG
    returncode=0
  else
    if test -f $ORACLE_HOME/dbs/sgadef${ORACLE_SID}.dbf  -o \
            -f $ORACLE_HOME/dbs/sgadef${ORACLE_SID}.ora
    then
      echo "*** ERROR:Database possibly left running when system" >> $LOG
      echo "    went down(system crash?)." >> $LOG
      echo "    Notify Database Administrator." >> $LOG
      returncode=$error_dbinconsistent
    else
      echo 'There are no Oracle processes running - ' >> $LOG
      echo 'Database is probably already stopped.' >> $LOG
      returncode=$error_dbnotavail
    fi
  fi

}

#====================================================================
#
# FUNCTION: logstep
#
#
logstep () {
        (
        echo
        echo "------------------------------" `date`
        echo $1
        echo 
        ) >> $LOG;
}
#====================================================================
#
# FUNCTION: errorexit
#
#
errorexit () {
        echo "$0: Terminating with error code $1" | tee -a $LOG
        rm -f $SRVMGRDBA_CMD_FILE
        exit $1
}


#====================================================================
#
# FUNCTION: usage
#
# PURPOSE:  
# 
#

usage()
{
  echo "Usage: `basename $0` [ORACLE_HOME] [stopRemoteService]"
  exit 1;
}

#====================================================================
#
# FUNCTION: stop_listener
#
# PURPOSE:  
#
# Check for SQLNETV2 and stop the listener
#
stop_listener()
{
  if test $dbs_ora_tnsname; then
    #
    # Checking listener ( is now checked with "tnsping" )
    #
    logstep "checking V2 connect"

    if [ "$stopRemoteService" = "stopRemoteService" ]; then
      # executable existing ?
      #
      if test ! -x $TNSPING_EXE  >> $LOG 2>&1; then
        echo $TNSPING_EXE missing. Terminating. >>$LOG
        errorexit $error_listener
      fi

      # search for listener.ora
      _LISTENERFILE1="$ORACLE_HOME"/network/admin/listener.ora
      _LISTENERFILE2=/etc/listener.ora
      _LISTENERFILE3="$TNS_ADMIN"/listener.ora
      if [ -f "$_LISTENERFILE1" ];then
        LISTENERFILE="$_LISTENERFILE1"
      elif [ -f "$_LISTENERFILE2" ];then
        LISTENERFILE="$_LISTENERFILE2"
      elif [ -f "$_LISTENERFILE3" ];then
        LISTENERFILE="$_LISTENERFILE3"
      else
        echo " Can not find listener.ora "
      fi

      # search for the listener name in listener.ora
      
      #LISTENER=`grep SID_LIST_ "$LISTENERFILE" | awk '{print $1}' | awk -FLIST_ '{print $2}'` 
      # -F only allows 1 character on some unix platforms
      LISTENER=`awk '/^SID_LIST_/ { listener=substr($1, length("SID_LIST_") + 1); print listener }' "$LISTENERFILE"`
      if [ $? -ne 0 -o -z $LISTENER ]; then
        LISTENER=LISTENER;
      fi

      # listener already running ? / connect possible
      #$LSNRCTL stat >> $LOG 2>&1
      eval $TNSPING $DB_SID 1 >> $LOG 2>&1
      if test $? -eq 0; then
        echo tnsping: V2 connect to $DB_SID >>$LOG
        for i in $LISTENER; do
          lsnrctl stop $i </dev/null >/dev/null 2>&1
        done
      fi
    fi
  fi
}

#====================================================================
#
#
#  MAIN routine
#
#====================================================================
#
#
# Set Variables
#
USER="`id | awk -F\( '{print $2}' | awk -F\) '{print $1}'`"

if  [ -z "$DB_SID" ];then
   DB_SID="$ORACLE_SID"
fi

TRUL='tr "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"'
SIDADM="`echo $SAPSYSTEMNAME | $TRUL`adm"
ORASID="ora`echo $DB_SID | $TRUL`"

#
# Logfile, Tempfile and SQLDBA-Commandfile
#

LOG=$HOME/stopdb.log
SRVMGRDBA_CMD_FILE=$HOME/stopdb.sql
EXEDIR="/usr/sap/$SAPSYSTEMNAME/SYS/exe/run"
CTEXEDIR="/usr/sap/$SAPSYSTEMNAME/SYS/exe/ctrun"

error_dbnotavail=10
error_dbavail=11
error_env=12
error_dbnostop=13
error_kill=14
error_dbinconsistent=15
error_listener=16
error_no_r3trans=18
error_no_sqlplus=19
error_no_r3trans_str="18"

#
# Initialize logfile 
#
> $LOG
logstep "LOGFILE FOR STOPPING ORACLE"
echo "Trying to stop $DB_SID database ..." | tee -a $LOG
echo "Log file: $LOG"


#
# Oracle Tools are treated special
#
##

#
# Change ORACLE_HOME (if set by stopsap as parameter)
#
stopRemoteService="";
if [ $# -gt 2 ]; then
  usage;
fi
if [ $# -eq 1 -o $# -eq 2 ]; then
  for opt in $@; do
    if [ -z "$stopRemoteService" ]; then
      if [ $opt = "stopRemoteService" ]; then
        stopRemoteService="$opt";
        continue;:1

      fi
    fi
    echo " Changing ORACLE_HOME from $ORACLE_HOME to $opt " | tee -a $LOG
    ORACLE_HOME="$opt"; export ORACLE_HOME;
  done  
fi
if [ $# -eq 2 -a -z "$stopRemoteService" ]; then
  usage;
fi

#
# shall sqlplus be used
#
if test -x "${ORACLE_HOME}/bin/sqlplus"
then
    SRVMGRDBA_EXE="${ORACLE_HOME}/bin/sqlplus"
else
   echo   " Can not find executable sqlplus " | tee -a $LOG
   exit $error_no_sqlplus
fi

#
# And the others
#
ORASRV_EXE="${ORACLE_HOME}/bin/orasrv"
LSNRCTL_EXE="${ORACLE_HOME}/bin/lsnrctl"
TNSPING_EXE="${ORACLE_HOME}/bin/tnsping"

SRVMGRDBA_P()
{
  ORA_NLS33="${ORACLE_HOME}/ocommon/nls/admin/data" "${SRVMGRDBA_EXE}" /nolog "$@"
}
SRVMGRDBA=SRVMGRDBA_P
export SRVMGRDBA

for tool in ORASRV    \
            LSNRCTL   \
            TNSPING
do
  proc_name="${tool}_P"
  exe_name="${tool}_EXE"
  funcdef="${proc_name}()"'
    {
      ORA_NLS33="${ORACLE_HOME}/ocommon/nls/admin/data" "${'"${exe_name}"'}" "$@"
    }'
  eval "$funcdef"
  eval "${tool}=${proc_name}; export ${tool}"
done
##


#
# which R3trans
#
if [ -x $EXEDIR/R3trans ]; then
   R3TRANS=$EXEDIR/R3trans
elif [ -x $CTEXEDIR/R3trans ]; then
   R3TRANS=$CTEXEDIR/R3trans
else
   echo   "Info: Can not find executable R3trans " >> $LOG
   R3TRANS=$error_no_r3trans_str
fi

v_stopdb=`basename $0`
if [ "$v_stopdb" = "stopj2eedb" ]; then
  R3TRANS=$error_no_r3trans_str
fi

# for DGUX only: 
PS="ps -ef"


trap '
        rm -f $SRVMGRDBA_CMD_FILE
        logstep "$0 was killed or interrupted. Terminating."
        exit $error_kill
' 1 2 15

#
#  Check environment. Make sure that required variables are set.
#  If they are not, prompt user to set them and restart stopora.
#

logstep "checking required environment variables"

if  [ -z "$SAPSYSTEMNAME" ];then
 echo "\nERROR  : SAPSYSTEMNAME not set " | tee -a $LOG
 echo   "         Please check environment and restart " | tee -a $LOG
 errorexit  $error_env
fi

if [ "$USER" != "$SIDADM" ]; then
 if test $R3TRANS = $error_no_r3trans_str
 then
   if [ "$USER" != "$ORASID" ]; then
     echo "ERROR  : You are user $USER, but you have to be $SIDADM to start this script" | tee -a $LOG
     errorexit  $error_env
   fi
 fi
fi

if test $ORACLE_HOME; then
        echo "ORACLE_HOME  is >$ORACLE_HOME<" >> $LOG
else
        echo "*** ERROR occured: ORACLE_HOME not set ! " >> $LOG
        echo "Set and export ORACLE_HOME, then restart script." >> $LOG
        errorexit $error_env
fi

if test $ORACLE_SID; then
        echo "ORACLE_SID   is >$ORACLE_SID<" >> $LOG
else
        echo "*** ERROR occured: ORACLE_SID not set ! " >> $LOG
        echo "Set and export ORACLE_SID, then restart script." >> $LOG
        errorexit  $error_env
fi


#
# Check the database state.
# Try a dummy connect - exit if the database is not available 
#
logstep "Connect to the database to check the database state:"
 
case `uname` in
DYNIX*|dgux* ) check_db_running;
               ;;
* )     if [ "$R3TRANS" = $error_no_r3trans_str ]; then
          if [ "$TRACE" ]; then
            echo "check_db_running;"
          fi 
          check_db_running;
          # check_db_running also set retruncode
          echo 'check_db_running finished with return code:' $returncode >> $LOG
        else  
          eval $R3TRANS -d -w /dev/null > /dev/null 2>&1
          returncode=$?
          # save returncode  of R3trans
          echo 'R3trans check finished with return code:' $returncode >> $LOG
        fi


        if [ "$TRACE" ]; then
          echo "returncode=$returncode"
        fi 
        case $returncode in
        0 )
                echo 'Database is running' >> $LOG
                echo 'Continue with stop procedure' >> $LOG
                ;;
        4 | 8 )
                echo 'Database is running' >> $LOG
                echo 'Continue with stop procedure' >> $LOG
                echo '*** WARNING: Transport system not initialized' >> $LOG
                ;;
        * )
                if test  -f $ORACLE_HOME/dbs/sgadef${ORACLE_SID}.dbf  -o \
                         -f $ORACLE_HOME/dbs/sgadef${ORACLE_SID}.ora
                then
                    echo "*** ERROR:Database possibly left running when system" >> $LOG
                    echo "    went down(system crash?)." >> $LOG
                    echo "    Notify Database Administrator." >> $LOG
                    errorexit $error_dbinconsistent
                else
                    echo 'There is no database connect possible - ' >> $LOG
                    echo 'Database is probably already stopped.' >> $LOG
                    stop_listener;
                    exit 0
                fi  
                ;;
        esac ;
        ;;
esac



#
# Force a log switch and then stop the database
#
logstep "Forceing a log switch and then stop the database"

echo \
"connect / as sysdba;
alter system switch logfile;
connect / as sysdba;
shutdown immediate;
exit;" >  $SRVMGRDBA_CMD_FILE
eval $SRVMGRDBA @$SRVMGRDBA_CMD_FILE >> $LOG 2>&1
 


#
# Check the database state.
# Try a dummy connect to verify that the database is no longer
# running
#
logstep "Connect to the database to check the database state:"
 
 
case `uname` in
DYNIX*|dgux* ) check_db_running;
               ;;
* )     if test $R3TRANS = $error_no_r3trans_str
        then
          check_db_running;
          # check_db_running also set returncode
          echo 'check_db_running check finished with return code:' $returncode >> $LOG
        else  
          eval $R3TRANS -d -w /dev/null > /dev/null 2>&1
          # save returncode  of R3trans
          returncode=$?
          echo 'R3trans check finished with return code:' $returncode >> $LOG
        fi 
   
        if [ "$TRACE" ]; then
          echo "returncode=$returncode"
        fi 
        case $returncode in
        0 | 4 | 8 )
                echo 'Database is still running' >> $LOG
                echo '*** ERROR: shutdown failed' >> $LOG
                errorexit $error_dbnostop
                ;;
        * )
                echo 'Database not available' >> $LOG
                echo 'Shutdown successfull' >> $LOG
                ;;
        esac ;
        ;;
esac

echo "$DB_SID database stopped" | tee -a $LOG

#
# cleanup
#
 
rm -f $SRVMGRDBA_CMD_FILE

stop_listener;


exit 0