#!/bin/ksh
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
#  
#  
# Licensed Materials - Property of IBM 
#  
# (C) COPYRIGHT International Business Machines Corp. 2000,2006 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
# @(#)19 1.32 src/avs/fs/mmfs/ts/admin/runmmfs.sh, mmfs, avs_rgpfs24, rgpfs240610b 10/26/05 19:20:55 
#######################################################################
#
# runmmfs is used to start up the GPFS daemon.
#
#  Usage:  
#    runmmfs [options]
#
#  where   
#    options    if specified, passed through to the mmfsenv script.
#
#######################################################################


#------------------------------------------------------------------------
# Collect options, if any, to be passed on to mmfsenv.
#------------------------------------------------------------------------
mmfsenvOpt=$@

#------------------------------------------------------------------------
# Decide where to look for the commands.  The normal install directory
# is /usr/lpp/mmfs/bin.  This can be changed by setting the MMFSDIR 
# environment variable to something other than /usr/lpp/mmfs.
# If MMFSDIR is not used, before assuming the default install directory,
# we will check if the mmfs binaries are in the same place where this
# script resides.  This is a development aid for running out of a build tree.
#------------------------------------------------------------------------
if [[ -n $MMFSDIR ]]
then
  mmcmdDir="${MMFSDIR}/bin"
else
  if [[ -z ${0%%/*} ]]
  then
    fullname="$0"
  else
    fullname="${PWD%/}/$0"
  fi
  progDir=${fullname%/*}

  if [[ -f ${progDir}/mmfs ]]
  then
    mmcmdDir="$progDir"
  else
    mmcmdDir="/usr/lpp/mmfs/bin"
  fi
fi

# Determine the values of mmcmdSubdir and mmcmdSuffix.
set -f ; set -- $(/bin/uname -a) ; set +f
osName=$1
osVersion=$4
set --
if [[ -f ${mmcmdDir}/mmfs || $osName != AIX || $osVersion < 5 ]]
then
  mmcmdSubdir=""
  mmcmdSuffix=""

else
  # Must be running on top of AIX 5.
  # Determine whether the current kernel is 64-bit.
  kernelMode=$(${mmcmdDir}/mmkerninfo)
  if [[ $kernelMode = 64 ]]
  then
    mmcmdSubdir="aix64"
    mmcmdSuffix="64"
  else
    mmcmdSubdir="aix32"
    mmcmdSuffix=""
  fi
fi 

# Include global declarations and service routines.
. ${mmcmdDir}/mmglobfuncs
. ${mmcmdDir}/mmsdrfsdef
. ${mmcmdDir}/mmfsfuncs

commandPath=set

sourceFile="runmmfs.sh"
[[ -n $DEBUG || -n $DEBUGrunmmfs ]] && set -x
$mmTRACE_ENTER "$*"


#------------------------------------------------------------------------
# Function to catch stop signals issued while we are in this script.
# The daemon, once started, is responsible for signal handling.
#------------------------------------------------------------------------
function sigcatch
{
  print "$(date) ${mmcmd}: Received a stop request; exiting"
  $mmTRACE_EXIT "rc=1  stop request"
  exit 1
}

#------------------------------------------------------------------------
# Set the default sleep backoff to 7 seconds.  This ensures that the
# first three attempts to start will not occur within 20 seconds.
#------------------------------------------------------------------------
(( backoff = 7 ))

#------------------------------------------------------------------------
# If running under the control of the startup daemon (daemonize command),
# set up the console output (standout and standerr) files.
#------------------------------------------------------------------------
foreground=true
waittime=20

# DAEMONIZE is set by daemonize command when it execs us
if [[ -n $DAEMONIZE ]]; then

  #--------------------------------------------------------------
  # If we were started by daemonize then we are responsible for
  # restarting mmfsd.  The rerunmmfs file enables that function
  #--------------------------------------------------------------
  $touch $rerunmmfsFile

  foreground=false

  #------------------------------------------------------
  # Find the setting of the logDir mmfs.cfg parameter.
  # It can be used to override the default log location.
  #------------------------------------------------------
  if [[ -f $mmfscfg ]]
  then
    logDir=$($awk '$1 == "logDir" {value = $2} END {print value}' $mmfscfg)
    [[ -n $logDir ]] && rasDir="${logDir}/"
  fi

  standin="/dev/console"
  standout="${rasDir}mmfs.log"
  standerr="${rasDir}mmfs.log"
  signorm=31
  sigforce=15
fi
    
#---------------------------------------------------------------------
# Set the stop request signal handlers.
# Use the "waittime" value to set the respawn backoff.
#---------------------------------------------------------------------
trap sigcatch $signorm $sigforce
(( backoff = (waittime / 3) + 1 ))
  
#------------------------------------------------------------------
# If we were started by daemonize, then this script may be responsible 
# for respawning mmfsd after a death ($rerunmmfsFile is present). 
#------------------------------------------------------------------
while true
do
   # Move the respawnlog file, if any.
   $mv "$respawnlog" "$respawnlog2" 2>/dev/null

   if [[ -n $DAEMONIZE ]]; then
      exec 0<$standin
      exec 1>$standout
      exec 2>$standerr

      cd ${mmcmdDir}
   fi

   print -- "$(date) $mmcmd starting"

   if [[ $foreground = false ]]
   then 
      #---------------------------------------------------------------------
      # Clean out console log files not accessed in the last 11 days.
      #---------------------------------------------------------------------
      savepwd="$PWD"
      if [[ -f "$standout" ]]; then
         dir="${standout%/*}"
         base="${standout##*/}"
         print "Removing old $standout.* files:"
         if cd "$dir"; then
            $find . -type f -name "${base}"'.*' -atime +10 -mtime +10 -exec $rm {} \; -print
         fi
      fi

      if [[ "$standout" != "$standerr" && -f "$standerr" ]]; then
         dir="${standerr%/*}"
         base="${standerr##*/}"
         print "Removing old $standerr.* files:"
         if cd "$dir"; then
            $find . -type f -name "${base}"'.*' -atime +10 -mtime +10 -exec $rm {} \; -print
         fi
      fi
      cd "$savepwd"

      #---------------------------------------------------------------------
      # Standard out and standard error are opened in non-append mode.  If
      # standard out and standard error are directed at files, rename the
      # files, so that on the next restart these files are not overwritten.
      # Also, re-open the files in append mode.
      #---------------------------------------------------------------------
      suffix="$($date +%Y.%m.%d.%H.%M.%S).$($hostname -s)"
      changeprevious=1
      if [[ -f "$respawnlog2" ]]; then
         # When respawning, use previous log file to prevent the directory
         # from filling up with lots of nearly identical files.
         if [[ -L "${standout}.latest" ]]; then
            latest=$($ls -l "${standout}.latest")
            latest=${latest##*-\> }
            prefix=$(basename ${standout})
            latest=${latest#${prefix}.}
            [[ -n "$latest" ]] && suffix="$latest"
            changeprevious=0
         fi
      fi

      if [[ -f "$standout" ]]; then
         $cat "$standout" >> "${standout}.${suffix}"
         $chmod 644 "${standout}.${suffix}"
         exec 1>>"${standout}.${suffix}"
         [[ "$standout" = "$standerr" ]] && exec 2>&1
         $rm "$standout"

         # Create a symbolic link with suffix "latest" to the current log
         # and suffix "previous" to the previous log.
         if [[ $changeprevious = 1 ]]; then
            if [[ -L "${standout}.previous" ]]; then
               $rm -f "${standout}.previous"
            else
               $mv -f "${standout}.previous" "${standout}.previous.save"
            fi
            [[ ! -r  "${standout}.previous" ]] && [[ -L "${standout}.latest" ]] && \
              $mv -f "${standout}.latest" "${standout}.previous"
         fi

         [[ ! -r  "${standout}.latest" ]] && \
           $ln -sf $(basename "${standout}.${suffix}") "${standout}.latest"
         [[ ! -f "${mmsdrfsDir}mmfslog" ]] && \
           $ln -sf "${standout}.latest" "${mmsdrfsDir}mmfslog"
      fi

      if [[ "$standout" != "$standerr" && -f "$standerr" ]]; then
         $cat "$standerr" >> "${standerr}.${suffix}"
         $chmod 644 "${standerr}.${suffix}"
         exec 2>>"${standerr}.${suffix}"
         $rm "$standerr"
      fi
   fi  # end of if [[ $foreground = false ]]

   #-------------------------------------------------------------------------
   # To prevent start/crash loops, this script creates/modifies a file
   # that keeps a record of how often the MMFS daemon has been respawned
   # and the daemon has not come up completely due to external influences.
   # This file is removed by the daemon.
   #
   # If the file does not exist, create it with values "0 ${backoff}"; where
   # the backoff is the initial sleep (default 7 seconds), designed so that
   # the first three respawns will not occur within 20 seconds.
   #
   # If the file already exists, and the sleep we're about to take is less
   # than 56 seconds, double the time for the next sleep.  If the upcoming
   # sleep is greater than or equal to 56 seconds but less than 336 seconds,
   # add another 56 seconds to the next sleep.  If the upcoming sleep is
   # 336 seconds or more, the next sleep will be the same.  The count of the
   # number of times we've slept waiting to respawn is always incremented
   # by one.
   #
   # Note: file respawnlog isn't restored until just before an "exit" or
   # "exec"; until then file respawnlog2 is used.  This helps to prevent
   # the persistence of the respawn log between stop and start commands.
   #-------------------------------------------------------------------------
   if [[ -s "$respawnlog2" ]]; then
      read count waitPeriod < "$respawnlog2"
      if [[ $count != +([0-9]) || $waitPeriod != +([0-9]) ]]; then
        (( count = 1 ))
        (( waitPeriod = backoff ))
      else
        (( count += 1 ))
      fi
      if (( waitPeriod < 56 )); then
         (( newWaitPeriod = waitPeriod * 2 ))
      elif (( waitPeriod < 336 )); then
         (( newWaitPeriod = waitPeriod + 56 ))
      else
         (( newWaitPeriod = waitPeriod ))
      fi
      print ${count} ${newWaitPeriod} > "$respawnlog2"
      print "$(date) ${mmcmd}: respawn ${count} waiting ${waitPeriod} seconds before restarting mmfsd"

      #---------------------------------------------------------------------
      # Run the sleep in the background and then wait for it.  This lets
      # the parent script get signals exactly when they're delivered.
      # A side effect is that the sleep itself is protected from the signals,
      # and will continue to run, but a "sleep" process consumes almost no
      # resources, and will eventually wakeup and exit.
      #---------------------------------------------------------------------
      $sleep ${waitPeriod} &
      wait

   else
      # file does not exist yet, create it.
      (( newWaitPeriod = backoff ))
      print 0 ${newWaitPeriod} > "$respawnlog2"

   fi  # end of if [[ -s "$respawnlog2" ]]

   #------------------------------------------------------
   # Perform standard initialization.
   # If something goes wrong, do not bring the daemon up.
   #------------------------------------------------------
   $mmfsenv $mmfsenvOpt
   mmfsenvrc=$?
   sourceFile="runmmfs.sh"  # restore value after in-line call to mmfsenv

   #---------------------------------------------------------------------------
   # Now check the return status from "mmfsenv"; if it's bad, restore the
   # respawnlog file just before the exit and delete any old respawnlog2 files.
   # If the error is in setting up the kernel extension, give up all together.
   #---------------------------------------------------------------------------
   if [[ $mmfsenvrc -eq $MM_KExtFailure ]]; then
      print "$(date) ${mmcmd}: error in loading or unloading the mmfs kernel extension"
      print "$(date) ${mmcmd}: stopping GPFS"

      $rm -f "${respawnlog}"* $rerunmmfsFile
      $mmTRACE_EXIT "rc=$mmfsenvrc  mmfsenv error"
      exit $mmfsenvrc

   elif [[ $mmfsenvrc != 0 ]]; then
      print "$(date) ${mmcmd}: error preparing environment for mmfsd"
      print "$(date) ${mmcmd}: will try again in ${newWaitPeriod} seconds"
      $mv -f "$respawnlog2" "$respawnlog"
      $rm -f "${respawnlog}".*
      $mmTRACE_EXIT "rc=$mmfsenvrc  mmfsenv error"

      # If the rerunmmfsFile is present, go back to the top
      # of the loop for another iteration.  Otherwise we exit.
      [[ -n $DAEMONIZE && -f "$rerunmmfsFile" ]] && continue

      $rm -f $rerunmmfsFile
      exit $mmfsenvrc
   fi

   #-----------------------------------------------------
   # Start the MMFS daemon.
   # Restore the respawnlog file just before the "exec".
   #-----------------------------------------------------
   ulimit -d unlimited
   ulimit -m unlimited
   ulimit -f unlimited
   ulimit -t unlimited
   ulimit -n 1000000   # virtually unlimited while still an acceptable value
   ulimit -c 1024      # keep core files small

   # Start tracing if the environment variable is set.
   [[ -n "$MMTRACE" ]] && $mmtrace

   if [[ -n "$MMFSCONFIG" ]]; then
      MMARGS="-d $MMFSCONFIG"
   else
      MMARGS=""
   fi
   $mmTRACE "---> Starting GPFS daemon from runmmfs."
   $mv -f "$respawnlog2" "$respawnlog"
   $rm -f "${respawnlog}".*

   # If we are spawned by daemonize and $rerunmmfsFile exists,
   # then we'll be responsible for restarting GPFS.
   if [[ -n $DAEMONIZE ]]; then
     $mmfsd $MMARGS
     rc=$?

     # If rc is 101 (i.e., this daemon discovered a previously-running
     # incarnation of mmfsd), just get out and do not erase $rerunmmfsFile,
     # since it belongs to the other instance.
     [[ $rc = 101 ]] && exit $rc

     # Continue to the beginning of the loop for restart of mmfsd.
     [[ -f "$rerunmmfsFile" ]] && continue
     exit
   fi
    
   exec $mmfsd $MMARGS

done

