#! /usr/bin/sh
#
# ident	"@(#)sapmon.shi	1.5	98/07/24 SMI"
#
# Copyright (c) 1997 by Sun Microsystems, Inc.
# All rights reserved.
#

VERSION=1.3
ARGV0=`basename $0`
PATH0=`dirname $0`
SYSLOG=`haget -f syslog_facility`
SAPCONF=/etc/opt/SUNWscsap/hadsconf

HA_DEBUG=1
#
# take this out before fcs
#
if [ $HA_DEBUG -ne 0 ];then
  logger -p ${SYSLOG}.info \
   "$0" "$1" "$2"
   logerr "$0" "$1" "$2"
fi


ARGV0=`basename $0`
LOGGER=logger
HA_SLOGFACILITY=`haget -f syslog_facility`
HA_SLOGTAG=hadf
prog_path=`dirname $0`
# add the ha-service specific clust_progs path since
# it will not co-reside with the framework clust_progs.
# if it's a fault monitor method, add also fault_progs.
expr "$prog_path" : '.*/clust_progs' >/dev/null 2>&1
if [ $? -eq 0 ]; then
	PATH=${prog_path}:${PATH}
else
	PATH=${prog_path}:${prog_path}/../clust_progs:${PATH}
fi

# source in ha-services common utilities
. ds_utilities.1.3

source_env_file $SAPCONF

#
# SAP variables
#
NOTAVAIL=${_INST_1_PRIV_NOT_AVAIL}
SAPSID=${_INST_1_PRIV_YOUR_SAP_SID}
CI_INSTANCE_ID=${_INST_1_PRIV_CI_INSTANCE_ID}
CI=${_INST_1_PRIV_CI_LOGICAL_HOSTNAME}
DB=${_INST_1_PRIV_DB_LOGICAL_HOSTNAME}
NFS=${_INST_1_PRIV_NFS_LOGICAL_HOSTNAME}
SAPADM=${_INST_1_PRIV_SAP_ADMIN_LOGIN_NAME}
DBADM=${_INST_1_PRIV_DB_ADMIN_LOGIN_NAME}
USRSAP=${_INST_1_PRIV_SAP_MOUNT_POINT_A}
SAPMNT=${_INST_1_PRIV_SAP_MOUNT_POINT_B}
AUTO_NFSMOUNT=${_INST_1_PRIV_AUTO_NFS_MOUNT_ON_NON_CI_HOSTS}
DS_STATE=${_INST_1_DS_STATE}

#end substitutions

check_db() 
{
	#
	# Since some <sid>adm have test for tty=/dev/console in .login
	# to launch openwin, will need to disassociate stdin for the
	# "su -" command, we will reassociate stdin after the "su - ".
	#
	exec 3<&0   # save stdin to fd 3
	exec 0<&-   # close stdin to disassociate with /dev/console

	su - ${SAPADM} -c "R3trans -d" >/dev/null 2>&1
	r3trans_rc=$?

	exec  0<&3  # restore stdin from fd 3

	case $r3trans_rc in
	0 | 4 | 8)
		return 0 ;;
	*)
		return 1 ;;
	esac
}
     

check_dia()
{
DPMON=/usr/sap/${SAPSID}/SYS/exe/run/dpmon
PF=/usr/sap/${SAPSID}/SYS/profile/${SAPSID}_DVEBMGS${CI_INSTANCE_ID}_${CI}

	[ -f /tmp/dpmon.out ] && rm -f /tmp/dpmon.out >/dev/null 2>&1

	#
	# The dpmon program reads from stdin, so we can't close it
	# Fortunately, dpmon get all its environ from the pf file, so
	# there is no need to do "su -", just "su" is sufficient.
	#
	su ${SAPADM} -c "echo q | ${DPMON} pf=${PF} > /tmp/dpmon.out"

	grep UPD /tmp/dpmon.out
	if [ $? -eq 0 ]
	then
		return 0
	else
		return 1
	fi

}


#
# This fn takes in a SAPSID and returns the dispatcher pid, if dispatcher is
# not found, a -1 is returned.
#
find_dispatcher_pid()
{
SAPSID=$1

	# Get ppid where command name matches dw.sap$SAPSID, then remove
	# all duplicates, the remaining list will contain either the
	# dispatcher process or the sapstart process

	PIDLIST=`ps -eo ppid,comm | grep dw.sap${SAPSID} | sort | uniq | cut -c1-5`

	# we then determine which one is the dispatcher by specifically 
	# checking for the command name from the list 
	for pid in $PIDLIST
	do
		ps -p $pid -o comm= | grep dw.sap${SAPSID} >/dev/null 2>&1
		[ $? -eq 0 ] && return $pid
	done

	# If for some reason we don't find it, it may be that in between
	# building the list and the loop to check, the dispatcher has exited
	# Returning 1 as error code (since pid 1 is init, it can't be the disp)
	return 1
}


#
# This fn checks for critical SAP processes. 
# Critical processes are:
#
#   1. Message server process, this is an OS level process
#        named ms.sap<SAPSID>_DVEBMGS<CI_INSTANCE_ID>
#      There is only one of these process in an SAP instance.
#
#   2. The enqueue server, this exist as one of the dialog work
#        process, there isn't a direct way of finding it by
#        using OS utilities, so we just check if there are at
#        least 1 dw.sap<SAPSID>_DVEBMGS<CI_INSTANCE_ID> out there.
#
#   3. Check if the dispatcher process exist
#
#
# Return Value:
#   0 - all process present
#   
#   bit 1 - ms.sap process not found
#   bit 2 - can't find at least 1 dw.sap process 
#   bit 3 - dispatcher dw.sap process not found
#
# If all process not present, all bits will be 1's
#
check_proc()
{

	#
	# Some SAP process names
	#
	MSPROC=ms.sap${SAPSID}_DVEBMGS${CI_INSTANCE_ID}
	DWPROC=dw.sap${SAPSID}_DVEBMGS${CI_INSTANCE_ID}


	# Check if SAP is running by making sure:
	# 1. the message server is running (1st child of sapstart)
	#      one and only one of this process is expected per instance

	msproc_cnt=`ps -ef|grep "${MSPROC}"|grep -v grep|wc -l` >/dev/null 2>&1

	# 2. at least 1 "dw" process is running (the dispatcher
	#      should be the 2st child of the sapstart process)
	dwproc_cnt=`ps -ef|grep "${DWPROC}"|grep -v grep|wc -l` >/dev/null 2>&1


	# 3. the dispatcher workprocess exist
	find_dispatcher_pid ${SAPSID}
	dpproc_pid=$?

	if [ $dpproc_pid -ne 1 ]; then
		ps -p $dpproc_pid >/dev/null 2>&1
		dpproc_stat=$?
	else
		# had problem finding dispatcher pid
		# assume dispatcher dead
		dpproc_stat=1
	fi
		

	if [ $msproc_cnt -eq 1 ] && 
	   [ $dwproc_cnt -ge 1 ] && 
	   [ $dpproc_stat -eq 0 ]; then
		return 0
	else
		rc=0

		if [ $msproc_cnt -ne 1 ]; then
			rc=`expr $rc + 1`
		fi

		if [ $dwproc_cnt -lt 1 ]; then
			rc=`expr $rc + 2`
		fi

		if [ $dpproc_stat -eq 1 ]; then
			rc=`expr $rc + 4`
		fi

		return $rc
	fi
}


usage()
{
	echo "Usage: sapmon [ db | dia | proc ]"
}



if [ $# -lt 1 ] || [ $1 = "-h" -o $1 = "help" -o $1 = "?" ]; then
	usage
	exit 2
fi


case $1 in
	db)
		check_db 
		rc=$?

		if [ $rc -eq 0 ]; then
			exit 0
		else
			exit 1
		fi 
		;;

	dia)
		check_dia
		rc=$?

		if [ $rc -eq 0 ]; then
			exit 0
		else
			exit 1
		fi 
		;;

	proc)
		check_proc
		rc=$?

		if [ $rc -eq 0 ]; then
			exit 0
		else
			exit $rc
		fi 
		;;

	*)
		usage 
		;;
esac

exit 2
