#!/bin/sh
#
#	Copyright 06/16/97 Sun Microsystems, Inc.  All Rights Reserved.
#
#ident	"@(#)callmethod.sh	1.15	97/06/16 SMI"
#
# Usage:  callmethod servicename methodname
#
#	Calls the methodname of the servicename, using the
#	appropriate timeout for that method.  Checks service_is_on
#	to compute the proper parameters and even to decide whether
#	to call the method at all-- we don't call certain 
#	fault monitoring methods when the service is off.


# Non-standard boilerplate, for speed.  We simply assume that
# the env variable files $HA_ENV and hafmconfig have already
# been read in by the caller.

LOGGER=logger
PROG=callmethod
if [ -z "$HA_ENV_DEFINED" ]; then
    $LOGGER -p local7.err -t "hadf" "${PROG}:  Cannot determine correct HA environment"
    exit 1
fi

# include HA utilities library
. utilities
if [ $? -ne 0 ]; then
	$LOGGER -p $HA_SLOGLEV -t "$HA_SLOGTAG" "${PROG}:  Cannot find HA utilities library!"
	exit 1
fi

# [end of boilerplate]


cleanup()
{
    rm -f $CLMT_TMPERR >/dev/null 2>&1
}

#
# Main program
#

CLMT_TMPERR=$HA_TMP/callmethod.err.$$

establish_cleanup_handler

if [ $# -ne 2 ]; then
    abort "callmethod: Wrong number of arguments (should be 2): $*"
fi
CLMT_SN="$1"
CLMT_MN="$2"

# Check that the method name is one of the constant strings.  
# Categorize the method as published API vs. fault monitoring.
if [ "$CLMT_MN" = "START" -o "$CLMT_MN" = "START_NET" -o \
     "$CLMT_MN" = "STOP" -o "$CLMT_MN" = "STOP_NET" -o \
     "$CLMT_MN" = "ABORT" -o "$CLMT_MN" = "ABORT_NET" ]
then
    CLMT_FM=0
elif [ "$CLMT_MN" = "FM_INIT" -o "$CLMT_MN" = "FM_START" -o \
       "$CLMT_MN" = "FM_STOP" -o "$CLMT_MN" = "FM_CHECK_THIS_HOST_OK" ]
then
    CLMT_FM=1
else
    abort "callmethod: Unrecognized method name: $CLMT_MN"
fi

# Fetch the method program.
CLMT_PROG="`hareg -q $CLMT_SN -M $CLMT_MN 2>$CLMT_TMPERR`"
if [ $? -ne 0 ]; then
    logerr "hareg -q $CLMT_SN -M $CLMT_MN failed"
    log_err_file $CLMT_TMPERR
    cleanup
    exit 1
fi
if [ -z "$CLMT_PROG" -o "$CLMT_PROG" = "NULL" ]; then
    logdeb "For data service $CLMT_SN the $CLMT_MN method is null (ok)"
    exit 0
fi

# Fetch the time-out.  Only the four starting/stopping methods
# have a user-specifiable time-out.
# Impose a short time-out on the abort methods.
# Impose a long time-out on the fault monitoring methods.
if [ -z "$HA_METHOD_DEFAULT_TIMEOUT_SECS" ]; then
    HA_METHOD_DEFAULT_TIMEOUT_SECS=3600
    export HA_METHOD_DEFAULT_TIMEOUT_SECS
fi
if [ "$CLMT_MN" = "START" -o "$CLMT_MN" = "START_NET" -o \
     "$CLMT_MN" = "STOP" -o "$CLMT_MN" = "STOP_NET" ]
then
    CLMT_TIMEOUT="`hareg -q $CLMT_SN -T $CLMT_MN 2>$CLMT_TMPERR`"
    if [ $? -ne 0 ]; then
	logerr "hareg -q $CLMT_SN -T $CLMT_MN failed"
	log_err_file $CLMT_TMPERR
	cleanup
	exit 1
    fi
    if [ -n "$CLMT_TIMEOUT" ] && [ $CLMT_TIMEOUT -eq 0 ]; then
        CLMT_TIMEOUT=""
    fi
    if [ -z "$CLMT_TIMEOUT" ]; then
	CLMT_TIMEOUT="$HA_METHOD_DEFAULT_TIMEOUT_SECS"
    fi
    logdeb "For data service $CLMT_SN the $CLMT_MN method timeout is: $CLMT_TIMEOUT"
elif [ "$CLMT_MN" = "ABORT" -o "$CLMT_MN" = "ABORT_NET" ]; then
    if [ -n "$HA_ABORT_TIMEOUT_SECS" ]; then
	CLMT_TIMEOUT=$HA_ABORT_TIMEOUT_SECS
    else
	CLMT_TIMEOUT=120
    fi
else 
    CLMT_TIMEOUT=$HA_METHOD_DEFAULT_TIMEOUT_SECS
fi    

# Check if the data service is on, and if not, depending on the
# method, return immediately.  Even though our caller may
# have already filtered out off data services, we need to
# know the on/off state in order to pass the proper parameter list
# to the methods.  It simplifies the interface with our caller
# to just look up the on/off state again right here.
is_member $CLMT_SN "$HA_SERVICES_ON"
if [ $? -eq 0 ]; then
    CLMT_DSISON=1
else
    CLMT_DSISON=0
fi
logdeb "For data service $CLMT_SN service_is_on = $CLMT_DSISON"
if [ $CLMT_DSISON -eq 0 ]; then
    if [ "$CLMT_MN" = "FM_INIT" -o "$CLMT_MN" = "FM_START" -o \
	 "$CLMT_MN" = "FM_CHECK_THIS_HOST_OK" -o \
	 "$CLMT_MN" = "START" -o "$CLMT_MN" = "START_NET" ]
    then
	lognotice "Not calling $CLMT_MN method for data service $CLMT_SN because the data service is off"
	cleanup
	exit 0
    fi
fi

# Error if method program is not executable file.
if [ ! -x $CLMT_PROG  -o  ! -f $CLMT_PROG ]; then
    logerr "$CLMT_MN method of data service $CLMT_SN is not an executable file or does not exist: $CLMT_PROG"
    cleanup
    exit 1
fi

# Data service on/off affects the parameter lists to methods.
# If the data service is off, or if the method is an aborting method,
# then the set to serve (arg1) is empty, and the set to not serve (arg2)
# is the universe.

if [ $CLMT_DSISON -eq 1 ]; then
    CLMT_ARG1="$HA_METASETSERVE_COMMA"
    CLMT_ARG2="$HA_NO_METASETSERVE_COMMA"
else
    CLMT_ARG1=""
    CLMT_ARG2="$HA_ALL_METASETS_COMMA"

    # For backward compatibility, hack up the HA_ env variables 
    # to reflect the fact that the Data Service is off.  We do
    # that by pretending that all of the logical hosts are
    # not being served by any host, while calling just this data service.

    HA_NFSERVE=""
    export HA_NFSERVE

    HA_METASETSERVE=""
    export HA_METASETSERVE

    HA_METASETSERVE_COMMA=""
    export HA_METASETSERVE_COMMA

    HA_NO_NFSERVE="$HA_ALLNATIVEHOSTS $HA_ALLFOREIGNHOSTS"
    HA_NO_NFSERVE="`echo $HA_NO_NFSERVE`"
    export HA_NO_NFSERVE

    HA_NO_METASETSERVE="$HA_ALL_METASETS"
    export HA_NO_METASETSERVE

    HA_NO_METASETSERVE_COMMA="$HA_ALL_METASETS_COMMA"
    export HA_NO_METASETSERVE_COMMA

    HA_SIBLING_METASETSERVE=""
    export HA_SIBLING_METASETSERVE
fi


lognotice "Calling $CLMT_MN method of data service ${CLMT_SN}: $CLMT_PROG"
logdeb "Arg1 is: $CLMT_ARG1"
logdeb "Arg2 is: $CLMT_ARG2"

# 12-Jun-1997  cmm calls processor_bind() only on 'sun4d' arch, 
# subsequently all its childs inherit the same cpu affinity, this 
# behavior negatively impacts any program started from cluster transition.
# Add the following code to unbind this process (thus all its babies) 
# on the 'sun4d' architecture. 
PBIND=/usr/sbin/pbind

ARCH="`/bin/uname -m`"
if [ "$ARCH" = "sun4d" ]
then
	$PBIND -u $$ >/dev/null 2>&1
fi

# 6-Nov-1996 Change the scheduler class to TS (TimeSharing) as
# we invoke the method.  The motivation for this change is that
# the cluster membership monitor runs in RT (RealTime) class
# and thus so do its descendents.  Before, the methods ran in
# RT class also, which tended to mean that the Data Service
# itself would run in RT.  Alas, having everything on the system
# run in RT meant that some crucial Solaris OS housekeeping 
# processes, e.g., fsflush, were getting starved.
# We still run the cluster transition scripts in RT class though
# because (i) they are short-lived, and (ii) there is a time-out
# associated with the step, such that the system will abort if
# the time-out expires.
CLMT_TPROG="priocntl -e -c TS fdl_timedrun -k TERM $CLMT_TIMEOUT $CLMT_PROG"

# In order to pass an empty string argument to the method,
# we need to use exactly the string '' on the shell command
# line.  Variable substitution will not work.  We end up
# with four different command lines, depending on which of
# arg1 and arg2 are empty.
if [ -n "$CLMT_ARG1" -a -n "$CLMT_ARG2" ]; then
    $CLMT_TPROG $CLMT_ARG1 $CLMT_ARG2 $CLMT_TIMEOUT
    CLMT_RC=$?
elif [ -z "$CLMT_ARG1" -a -z "$CLMT_ARG2" ]; then
    $CLMT_TPROG '' '' $CLMT_TIMEOUT
    CLMT_RC=$?
elif [ -z "$CLMT_ARG1" ]; then
    $CLMT_TPROG '' $CLMT_ARG2 $CLMT_TIMEOUT
    CLMT_RC=$?
else
    $CLMT_TPROG $CLMT_ARG1 '' $CLMT_TIMEOUT
    CLMT_RC=$?
fi

if [ $CLMT_RC -eq 99 ]; then
    logerr "Call to $CLMT_MN method of data service $CLMT_SN timed-out, time-out was: $CLMT_TIMEOUT"
else
    lognotice "Call to $CLMT_MN method of data service $CLMT_SN returned, exit code was $CLMT_RC"
fi

cleanup
exit $CLMT_RC
