#!/bin/bash
#==============================================================================
# Copyright and license info is available in the LICENSE file included with
# the Server Deployment Package (SDP), and also available online:
# https://swarm.workshop.perforce.com/projects/perforce-software-sdp/view/main/LICENSE
#------------------------------------------------------------------------------

# Helix Server base init script

# Do nothing unless $SDP_INSTANCE is defined.
export SDP_INSTANCE=${1:-Unset}

if [[ $SDP_INSTANCE == Unset ]]; then
   echo -e "\nError: The SDP_INSTANCE is not defined.\n."
   exit 1
fi

# Load SDP controlled shell environment.
source /p4/common/bin/p4_vars "$SDP_INSTANCE"
if [[ $? -ne 0 ]]; then
   echo -e "\nError: Failed to load SDP environment for instance $SDP_INSTANCE.\n"
   exit 1
fi

source $P4CBIN/backup_functions.sh
if [[ $? -ne 0 ]]; then
   echo -e "\nError: Failed to load SDP lib $P4CBIN/backup_functions.sh.\n"
   exit 1
fi

LOGFILE=$LOGS/p4d_init.log
THISSCRIPT=${0##*/}
CMDLINE="$0 $*"
set_vars

if [[ $(id -u) -eq 0 ]]; then
   exec su - $OSUSER -c "$0 $*"
elif [[ $(id -u -n) != $OSUSER ]]; then
   echo "$0 can only be run by root or $OSUSER"
   exit 1
fi

if [[ ! -x $P4DBIN ]]; then
   echo -e "\nError: $P4DBIN is not executable."
   exit 2;
fi

# Ensure that the '--pid-file' argument is provided, and add it if it is not.
# This is intended to prevent problems upgrading the SDP in case the
# /p4/common/config/p4_N.vars file isn't updated to use the new template.
if [[ "$P4D_FLAGS" != *"--pid-file"* ]]; then
   export P4D_FLAGS="$P4D_FLAGS --pid-file"
fi

# For P4D 2017.1+, automatically replace '-d' with '--daemonsafe'.
if [[ "$P4D_VERSION" > "2017.1" ]]; then
   export P4D_FLAGS=${P4D_FLAGS/ -d / --daemonsafe }
fi

log "\nCalled $THISSCRIPT called with command line:\n$CMDLINE"

# See how we were called.
case "${2:-usage}" in
   force_start)
      echo "Starting $P4DBIN $P4D_FLAGS" | tee -a $LOGFILE
      $P4DBIN $P4D_FLAGS >> $LOGFILE 2>&1
   ;;
   start)
      if [[ -r $P4ROOT/db.domain ]]; then
         echo Preflight check: $P4DBIN -r $P4ROOT -xvU | tee -a $LOGFILE
         $P4DBIN -r $P4ROOT -xvU >> $LOGFILE 2>&1
         ExitCode=$?
         echo EXIT_CODE=$ExitCode >> $LOGFILE

         if [[ $ExitCode -ne 0 ]]; then
            echo -e "\nError: DB check with 'p4d -xvU' failed.  Database integrity is in question.  Please Contact Perforce Support (support@perforce.com).  The force_start option is availble, but not recommended.  Review this file:\n$LOGFILE\n" | tee -a $LOGFILE
         fi
      fi

      # Rotate the journal when starting so that any corruption is at the end of the rotated journal.
      if [[ "$P4REPLICA" == "FALSE" ]] && [[ $EDGESERVER -eq 0 ]]; then
         echo "Setting P4JOURNAL in the database to $P4JOURNAL." | tee -a $LOGFILE
         echo $P4DBIN -r $P4ROOT -cset P4JOURNAL=$P4JOURNAL | tee -a $LOGFILE
         $P4DBIN -r $P4ROOT "-cset P4JOURNAL=$P4JOURNAL" 2>&1 | tee -a $LOGFILE
         get_journalnum
         p4d_truncate_journal
      fi
      echo "Starting $P4DBIN $P4D_FLAGS" | tee -a $LOGFILE
      $P4DBIN $P4D_FLAGS >> $LOGFILE 2>&1
   ;;
   status)
      if [[ -r $P4ROOT/server.pid ]]; then
         pid=$(cat $P4ROOT/server.pid)
         echo -e "\nThe $P4ROOT/server.pid file contains pid $pid.  Pid info:" | tee -a $LOGFILE
         $PS -f -p $pid 2>&1 | tee -a $LOGFILE
         echo

         if [[ $? -ne 0 ]]; then
            echo -e "\nError: A server.pid file exists, but that process id is not running.  This could indicate abnormal process termination.\n" | tee -a $LOGFILE
         fi
      fi

      $P4BIN -p $P4PORT -u $P4USER info -s 2>&1 | tee -a $LOGFILE
   ;;
   admin_stop)
      # If there is no server.pid file, shut down the old fashioned way.
      echo -n "Shutting down $P4DBIN: " | tee -a $LOGFILE
      if [[ "${P4REPLICA}" == "FALSE" ]]; then
         $P4CBIN/p4login
      fi
      echo $P4BIN -p $P4PORT -u $P4USER admin stop | tee -a $LOGFILE
      $P4BIN -p $P4PORT -u $P4USER admin stop 2>&1 | tee -a $LOGFILE
      sleep 5
      $P4BIN -p $P4PORT info > /dev/null 2>&1
      ExitCode=$?
      if [[ $ExitCode -eq 0 ]]; then
         echo -e "\nError: Server shutdown failed." | tee -a $LOGFILE
         exit 1
      else
         exit 0
      fi
   ;;
   stop)
      if [[ -r $P4ROOT/server.pid ]]; then
         pid=$(cat $P4ROOT/server.pid)

         $PS -p $pid > /dev/null 2>&1
         status=$?

         if [[ $status -eq 0 ]]; then
            echo -e "\nSending SIGTERM signal to pid $pid in $P4ROOT/server.pid." | tee -a $LOGFILE
            kill $pid 2>&1 | tee -a $LOGFILE
            sleep 1

            $PS -p $pid > /dev/null 2>&1
            status=$?

            if [[ $status -eq 0 ]]; then
               echo -n "Waiting for p4d to shutdown ..." | tee -a $LOGFILE

               while [[ $status -eq 0 ]]; do
                  echo -n "."
                  sleep 5
                  $PS -p $pid > /dev/null 2>&1
                  status=$?
               done
            fi
            echo -e "\nConfirmed shutdown of $P4DBIN." | tee -a $LOGFILE
         else
            echo -e "\nError: A server.pid file exists, but that process id is not running.  This could indicate abnormal process termination.\n" | tee -a $LOGFILE
            exit 1
         fi
      else
         echo -e "\nWarning: Missing $P4ROOT/server.pid. Attempting shutdown with 'p4 admin stop'.\n" | tee -a $LOGFILE
         echo $0 $SDP_INSTANCE admin_stop | tee -a $LOGFILE
         $0 $SDP_INSTANCE admin_stop 2>&1 | tee -a $LOGFILE
      fi
   ;;
   restart)
      $0 $SDP_INSTANCE stop
      $0 $SDP_INSTANCE start
   ;;
   *)
      echo -e "\nUsage: $0 SDP_INSTANCE {start|stop|admin_stop|status|restart|force_start}\n"
      exit 1
   ;;
esac

exit 0