#!/usr/bin/ksh
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# perf720 src/perf/perfagent/usr/lib/libSpmi/spmiclean.sh 1.6 
#  
# Licensed Materials - Property of IBM 
#  
# Restricted Materials of IBM 
#  
# COPYRIGHT International Business Machines Corp. 2011,2012 
# 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 

DUMP_FILE=/var/perf/spmi.dump
LOG_FILE=/var/perf/spmiclean.log
DBX_FILE=/usr/bin/dbx
INETD_FILE=/etc/inetd.conf
OPT=$1
PID=$2
GREP="grep"
commented="no"

print_usage() {
    print "Usage: "
    print "    spmiclean -d        => To dump the stack of the processes that uses SPMI."
    print "    spmiclean -c        => To clean the shared memory used by SPMI."
    print "    spmiclean -dc       => To dump the stack of the processes that uses SPMI and clean the shared memory."
    print "    spmiclean -p <pid>  => To dump the stack of the process of the given pid."
    print "    [NOTE: Dump file location: $DUMP_FILE]"
}

print_error() {
	print "Error occurred.. See $LOG_FILE for more details.\n"
	exit
}
	
check_dump_file_size() {
	echo "Dump file size check.. " >> $LOG_FILE
	if [ ! -f $DUMP_FILE ]; then
		touch $DUMP_FILE 
	fi

    # Check for the dump file size. 
    # If it is greater than 7000, then clear the file.
	size=`ls -la $DUMP_FILE | awk '{ print $5 }'`
	if [[ $size -gt 7000 ]]; then
		echo "$DUMP_FILE size huge. Clearing the file." >> $LOG_FILE
		: > $DUMP_FILE 
	fi

    # Have this header info to ease the life of us when we get confused on 
    # date of this log
    echo "================================================================" >> $DUMP_FILE
	echo "SPMI Dump log for $(date +%d/%m/%Y-%H:%M:%S)" >> $DUMP_FILE
    echo "================================================================" >> $DUMP_FILE
	echo "[OK]\n" >> $LOG_FILE
}

find_spmi_processes() {

	pids1=`/usr/bin/genld -l | grep -p Spmi | grep Proc | awk '{ print $2 }'` ;
	echo "Find SPMI processes: " >> $LOG_FILE
	echo "No process using SPMI. " >> $LOG_FILE

	if [[ $pids1 == '' ]]; then
		echo "[NOT OK]\n" >> $LOG_FILE
	else
		set -A pids $(echo "$pids1")
	fi
	echo "[OK] \n" >> $LOG_FILE
}

check_valid_pid() {
	tpids=`/usr/bin/ps -eaf | grep $PID | grep -v $GREP | awk '{ print $2 }'`
	echo "       PID validity check: " >> $LOG_FILE
	if [[ $tpids == '' ]]; then
		echo "$PID does not exist. " >> $LOG_FILE
		echo "[NOT OK]\n" >> $LOG_FILE
		print_error
	else
		set -A tpid $(echo "$tpids")
		tp=0
		while (( tp <= ${#tpid[*]}-1 ))
			do
			if [[ ${tpid[tp]} == $PID ]]; then 
				echo "$PID exists. " >> $LOG_FILE
				echo "[OK]\n" >> $LOG_FILE
				return
			fi
			((tp=tp+1))
			done
	
		echo "$PID does not exist. " >> $LOG_FILE
		echo "[NOT OK]\n" >> $LOG_FILE
		print_error
	fi
}

print_process_dump_header() {
	echo "--------------------------------" >> $DUMP_FILE
	echo "Dump of $pname : " >> $DUMP_FILE
	echo "--------------------------------" >> $DUMP_FILE
}

dump_stack() {
	# Check if the binary is debug binary or not.
	# If it is not a debug binary, then do not dump the variable list
	# as it wont be of much help for debugging purpose
	check_debug_binary
	print_process_dump_header

	echo "      Dumping $PID stack to $DUMP_FILE.. Wait!.. " >> $LOG_FILE
	echo "where \n $DUMP_CMD \n detach" | $DBX_FILE -a  $PID >> $DUMP_FILE 2>&1
   	echo "[OK]\n" >> $LOG_FILE
}

check_debug_binary() {
	pname=`ps -eaf | grep $PID | grep -v $GREP | awk '{print $2,"\t",$8}' | grep $PID | awk '{print $2}'`
	pnamepath=`/usr/bin/type $pname | awk '{ print $3 }'`
	dbg=`/usr/bin/file $pnamepath | grep "not stripped"` 
	if [[ $dbg == '' ]]; then
		echo "      $pnamepath is not a debug binary.." >> $LOG_FILE
		DUMP_CMD=""
	else
		echo "      $pnamepath is a debug binary.." >> $LOG_FILE
		DUMP_CMD=" dump . "
	fi
}

dump_stacks() {
	echo "Stack Dumping status: " >> $LOG_FILE

	if [[ $OPT == "-p" ]]; then
		check_valid_pid ;
        dump_stack

	else
		curpid=0;

		while (( curpid <= ${#pids[*]}-1 )) 
		do
  	        PID=${pids[curpid]} ;
            dump_stack ;
			((curpid=curpid+1));
		done
	fi
}

add_inetd_entry() {
	if [[ $commented == "yes" ]]; then
		return
	fi
	echo "      Adding back xmtopas entry in inetd.conf file .." >> $LOG_FILE
	sed "s/.*xmquery/xmquery/g" $INETD_FILE > temp; mv temp $INETD_FILE;

	echo "      Refreshing inetd.." >> $LOG_FILE
	refresh -s inetd > /dev/null
}

remove_inetd_entry() {
	if [[ $commented == yes ]]; then
		return
	fi
	echo "      Removing xmtopas entry from inetd.conf file.." >> $LOG_FILE
	sed "s/xmquery/#xmquery/g" $INETD_FILE > temp; mv temp $INETD_FILE;

	echo "      Refreshing inetd.." >> $LOG_FILE
	refresh -s inetd > /dev/null
}

clean_memory() {
	echo "      Cleaning shared memory.." >> $LOG_FILE
	for id in `/usr/bin/ipcs -a | grep 0x78 | awk '{ print \$2 }' `
	do
    	 /usr/bin/ipcrm -m $id
	done
}

kill_pids() {
	if [[ ${#pids[*]} -gt 0 ]]; then
		echo "      Killing existing SPMI consumer processes.." >> $LOG_FILE
		kill  ${pids[*]}
		slibclean
	else
		echo "      No process to kill.." >> $LOG_FILE
	fi
}

check_inetd_entry() {
	echo "      Check if the inetd entry is already removed.." >> $LOG_FILE
	entry=`cat $INETD_FILE | grep "#xmquery"`
	if [[ $entry == "" ]]; then
		echo "      Entry not commented.. so comment it and proceed.." >> $LOG_FILE
		commented="no" 
	else
		echo "      Entry already commented.. so dont touch it.." >> $LOG_FILE
        # Refresh inetd just in case user forgot to issue refresh after commenting the entry
        # in inetd.conf file
	    echo "      Refreshing inetd.." >> $LOG_FILE
        refresh -s inetd > /dev/null
		commented="yes" 
	fi
}

clean_shared_memory() {
	echo "Shared memory cleanup: " >> $LOG_FILE
	
	check_inetd_entry

	remove_inetd_entry

	kill_pids

	clean_memory

	add_inetd_entry

	echo "[OK]\n" >> $LOG_FILE
}

check_dbx() {
	echo "DBX Fileset Check: " >> $LOG_FILE
	if [ ! -f $DBX_FILE ]; then
		echo "      Please install bos.adt.debug fileset and try again." >> $LOG_FILE
		echo "[NOT OK]\n" >> $LOG_FILE
		exit
	else	
		echo "      DBX fileset bos.adt.debug installed." >> $LOG_FILE
		echo "[OK]\n" >> $LOG_FILE
	fi	
}
	
dispatch() {

    # Print header info
    print_log_header

    # Check if DBX is installed
    check_dbx

    # Find SPMI processes that uses SPMI
    find_spmi_processes

	if [[ $OPT != -c ]]; then
		check_dump_file_size
		dump_stacks
	fi

	if [[ $OPT == *c ]]; then 
		clean_shared_memory
	fi
}

print_log_header() {
	if [ ! -f $LOG_FILE ]; then
		/usr/bin/touch $LOG_FILE
	fi
	: > $LOG_FILE
    echo "================================================================" > $LOG_FILE
	echo "SPMI Clean log for $(date +%d/%m/%Y-%H:%M:%S)" >> $LOG_FILE 
    echo "================================================================" >> $LOG_FILE
}

# Check for the correct usage of this script
if [[ $# -lt 1 ||  $# -gt 2 || ( $OPT != -c && $OPT != -d && $OPT != -dc && $OPT != -p ) ]]; then
	print_usage
	exit
fi

if [[ $# -eq 1 && $OPT == -p ]]; then
	print_usage
	exit
fi


# Dispatch the queries. The script's main().
dispatch 

#if [[ $tty_id != - ]]; then
	echo "\nSUCCESS!!..."
#fi

exit;