#!/bin/sh
#
# @(#) $Id: //bas/720_REL/src/krn/startscripts/startdbora#2 $
#
# NAME: startdb
#
# PURPOSE: startup an ORACLE database
#
# PARAMETER:
#       none
# Environment
#       ORACLE_HOME     must be set
#       ORACLE_SID      must be set
# Return Codes:
#       0       ok. DB may have already been running.
#       1       erroneous license check
#       2       DB not startable: inconsistency?
#       3       environment check failed
#       4       orasrv error / starting of listener error
#       5       script was killed
#
# USAGE: startdb [ORACLE_HOME] [startRemoteService]
#
#
# DESCRIPTION:
# - initialize
# - start orasrv / now: lsnrctl start
# - check database state (connect)
# - startup database, change archivelog mode
#   if this procedure is changed (e.g. Test System)
#   there is no guarantee of hotline support if the system crashes
# - check database state (connect)
# - check archive log state
# - licence check
#
# DGUX and Sequent exceptions
# R3trans is not available on the DG standalone DB server
# therefore the Oracle processes are checked

#History
#2001-03-01     rv      replace SAPSYSTEMNAME with DB_SID where appropriate, due to SDMS
#2000-11-14     rv      include begin/end messages from startsap
#1996-07-25     kgd     SQLNET*V2 and SQLNET*V1
#1996-07-11     ar      Sequent exceptions
#1996-06-11     kgd     SQLNET*V2 adaptions
#1994-12-7      mau     warning "Transport system not init." not only to
#                       logfile but also to stdout
#                       Project: 22C 241
#1995-07-25     dg      included check that caller is admuser



#====================================================================
#
# 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 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 test $? -eq 0
  then
    echo 'Database already running' >> $LOG
    returncode=0;
  else
    echo 'database not available' >> $LOG
    # now check if sgadef exists
    # if a database connect fails but sgadef exists,
    # it is possible that there is a severe database problem
    # otherwise continue with startup procedure
    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_dbnotavail
    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 $TMP_FILE
        exit $1
}
#====================================================================
#
# FUNCTION: shutdown_abort
#
#
#
shutdown_abort () 
{
        echo \
        "connect / as sysdba;
        shutdown abort;" > $SRVMGRDBA_CMD_FILE
        eval $SRVMGRDBA @$SRVMGRDBA_CMD_FILE > /dev/null 2>&1
        rm $SRVMGRDBA_CMD_FILE
}



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

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


#
# 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`"
EXEDIR="/usr/sap/$SAPSYSTEMNAME/SYS/exe/run"
CTEXEDIR="/usr/sap/$SAPSYSTEMNAME/SYS/exe/ctrun"

error_license=11
error_dbinconsistent=12
error_env=13
error_listener=14
error_kill=15
error_initora=16
error_redolog=17
error_no_r3trans=18
error_no_sqlplus=19
error_no_r3trans_str="18"
error_dbnotavail="10"

#
# Logfile, Tempfile and SQLDBA-Commandfile
#
LOG=$HOME/startdb.log
TMP_FILE=$HOME/startdb.tmp
SRVMGRDBA_CMD_FILE=$HOME/startdb.sql

#
# Initialize logfile
#
> $LOG  #clear existing log file
logstep "LOGFILE FOR STARTING ORACLE"
echo "Trying to start $DB_SID database ..." | tee -a $LOG
echo "Log file: $LOG"


#
# Oracle Tools are treated special
#
##

#
# Change ORACLE_HOME if set by startsap as parameter
#
startRemoteService="";
if [ $# -gt 2 ]; then
  usage;
fi
if [ $# -eq 1 -o $# -eq 2 ]; then
  for opt in $@; do
    if [ -z "$startRemoteService" ]; then
      if [ $opt = "startRemoteService" ]; then
        startRemoteService="$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 "$startRemoteService" ]; 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_startdb=`basename $0`
if [ "$v_startdb" = "startj2eedb" ]; then
  R3TRANS=$error_no_r3trans_str
fi

INITORA=$ORACLE_HOME/dbs/init${ORACLE_SID}.ora
# for DGUX only:
PS='ps -ef'


trap '
        logstep "do not shutdown abort database at kill command, check database status manually."
        rm -f $TMP_FILE $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 startora.
#

logstep "checking required environment variables"

if  [ -z "$SAPSYSTEMNAME" ];then
 echo "ERROR  : 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 if file init.ora is readable
#
logstep "check initora"
if test ! -r $INITORA -o ! -f $INITORA >> $LOG 2>&1; then
        # M.Schuetz
        errorexit  $error_initora
fi

#
# Check if redo log mechanism is enabled
#
logstep "check initora"
grep -i disable_logging $INITORA|grep -v \^# >> /dev/null 2>&1
if test $? -eq 0;then
        errorexit  $error_redolog
fi

#
# Check oracle server process (listener or orasrv depending if
# SQLNET Version 2 or Version 1 is used)
# (if dbs_ora_tnsname is set we assume SQLNET V2!)
#

#
# Check for SQLNETV2
#
if test $dbs_ora_tnsname; then

   #
   # Checking listener ( is now checked with "tnsping" )
   #
      logstep "checking V2 connect"

   # executable existing ?
   #
      if test ! -x $TNSPING_EXE  >> $LOG 2>&1; then
           echo $TNSPING_EXE missing. Terminating. >>$LOG
           errorexit $error_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
      else
      #
      # 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 must be started as ora<sid>
      # with startRemoteService option, listener also can be start as sidadm
         if [ "$startRemoteService" = "startRemoteService" ]; then
           for i in $LISTENER; do
             lsnrctl start $i </dev/null >/dev/null 2>&1
           done
         else
           echo
           echo V2 connect is not available. Terminating >>$LOG
           echo  No SQL*Net V2 connect to $DB_SID available.
           echo  Check that the listener is running: \"lsnrctl status\".
           echo  Start the listener as user $ORASID: \"lsnrctl start\".
           echo
           errorexit $error_listener
         fi 
      fi
#
# now the else part (SQLNET V1)
else
   #
   # Start orasrv process
   #
      logstep "starting orasrv"
      if test ! -x $ORASRV_EXE -o ! -u $ORASRV_EXE  >> $LOG 2>&1; then
            echo $ORASRV_EXE missing or without set-user-ID bit. Terminating. >>$LOG
            errorexit $error_orasrv
      fi

      if $ORASRV  >> $LOG 2>&1
      then
             :;
      else
   #  #Mau 1994-7-22: according to ORACLE orasrv returns only
        #0 (started ok) or !=0 meaning orasrv ran already or any error
        # occurred. See log entry for possible errors.
             :;
      fi
fi


#
# Check the database state.
# Try a dummy connect - exit if the database is already 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
          if [ "$TRACE" ]; then
            echo "check_db_running;"
          fi 
          check_db_running
          # save returncode  of check_db_running
          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: connect check finished with return code:' $returncode >> $LOG
        fi

        if [ "$TRACE" ]; then
          echo "returncode=$returncode"
        fi 
        case $returncode in
        0 )
               echo 'Database already running' >> $LOG
               exit 0
               ;;
        4 | 8 )
               echo 'Database already running' >> $LOG
               echo '*** WARNING: Transport system not initialized.' | tee -a $LOG
               exit 0
               ;;
        * )
               echo 'Database not available' >> $LOG
               # now check if sgadef exists
               # if a database connect fails but sgadef exists,
               # it is possible that there is a severe database problem
               # otherwise continue with startup procedure
               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
               fi
               ;;
        esac
        ;;
esac


#
# Shutdown database
# The reason for this shutdown is, that the database may be
# in the nomount or mount state
#

logstep 'Shutdown database'
echo 'First trying to shutdown the database - May be,' >> $LOG
echo 'the database is in the nomount or mount state' >> $LOG


echo "connect / as sysdba;" > $SRVMGRDBA_CMD_FILE
echo "shutdown immediate;" >> $SRVMGRDBA_CMD_FILE
echo "exit;" >> $SRVMGRDBA_CMD_FILE

eval $SRVMGRDBA @$SRVMGRDBA_CMD_FILE > /dev/null 2>&1


logstep "starting database"
#
# Startup the database without changing the ARCHIVELOG state
#

echo "connect / as sysdba;" > $SRVMGRDBA_CMD_FILE
echo "startup;" >> $SRVMGRDBA_CMD_FILE
echo "exit;" >>  $SRVMGRDBA_CMD_FILE
eval $SRVMGRDBA @$SRVMGRDBA_CMD_FILE >> $LOG 2>&1

#
# Template for the startup command with changing
# the archive log state at every database startup.
# If the normal startup procedure is substituted with
# the following commands, you can ensure, that archivelogmode
# is realy enabled.
#
# echo \
# "connect / as sysdba;
# startup mount;
# alter database archivelog;
# alter database open;
# exit;" >  $SRVMGRDBA_CMD_FILE
# $SRVMGRDBA @$SRVMGRDBA_CMD_FILE >> $LOG 2>&1
#


#
# Try a dummy connect to verify that the database is now running
#

logstep "Connect to the database to verify, that the database is now open"

case `uname` in
DYNIX*|dgux* ) check_db_running;
        ;;
* )     if test $R3TRANS = $error_no_r3trans_str
        then
          if [ "$TRACE" ]; then
            echo "check_db_running;"
          fi 
          check_db_running;
        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 )
                echo 'Database is now running' >> $LOG
                ;;
        4 | 8 )
                echo 'Database is now running' >> $LOG
                echo '*** WARNING: Transport system not initialized' | tee -a $LOG
                ;;
        * )
                echo '*** ERROR: Startup of database failed' >> $LOG
                echo '    Notify Database Administrator.' >> $LOG
                errorexit $error_dbinconsistent
                ;;
        esac
        ;;
esac


#
# Check Archive Log Mode
#
logstep "checking archive log mode"

#
# A productive system must run in ARCHIVELOG Mode.
# If this mode is changed to NOARCHIVELOG (e.g. for
# a test system) there is no guarantee of hotline support
# if the system crashes.
# If the log mode is changed during SAP upgrade, a backup
# of the whole database is necessary (see upgrade guide).
#

echo \
"connect / as sysdba;
archive log list;
exit;" > $SRVMGRDBA_CMD_FILE
eval $SRVMGRDBA @$SRVMGRDBA_CMD_FILE > $TMP_FILE 2>&1

if egrep 'NOARCHIVELOG|No Archive Mode' $TMP_FILE > /dev/null
then
  echo '*** WARNING: archive log mode is disabled.' >> $LOG
  echo '    Database log mode:  NOARCHIVELOG' >> $LOG
  echo '    SAP cannot give any hotline support if this database' >> $LOG
  echo '    crashes, e.g. due to a disk failure.' >> $LOG
else
  echo 'ARCHIVELOG enabled'  >> $LOG
fi

cat $TMP_FILE >> $LOG


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

#
# cleanup
#

rm -f $TMP_FILE
rm -f $SRVMGRDBA_CMD_FILE

exit 0