#!/bin/ksh93
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# 61haes_r714 src/43haes/lib/ksh93/hacmp/KLIB_HACMP_is_known_dependency.sh 1.3 
#  
# Licensed Materials - Property of IBM 
#  
# COPYRIGHT International Business Machines Corp. 1990,2010 
# 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 
# @(#)52	1.3  src/43haes/lib/ksh93/hacmp/KLIB_HACMP_is_known_dependency.sh, hacmp.assist, 61haes_r714 10/10/12 10:30:17

# Start of POD-formatted documentation. Viewing suggestions:
#      perldoc <FILENAME>
#      pod2text -c <FILENAME>
#      pod2text -c --code <FILENAME>
#      pod2html <FILENAME>
function devDoc {
    : <<'=cut' >/dev/null 2>&1

=head1 NAME

 KLIB_HACMP_is_known_dependency

=head1 VERSION

 Version Number:  1.3
 Last Extracted:  1/31/14 04:41:03
 Last Changed:    10/10/12 10:30:17

 Path, Component, Release(, Level):
 src/43haes/lib/ksh93/hacmp/KLIB_HACMP_is_known_dependency.sh, hacmp.assist, 61haes_r714

=head1 SYNOPSIS

KLIB_HACMP_is_known_dependency

=head1 DESCRIPTION

Determines if the specified dependency
is configured within the cluster.

=head1 ARGUMENTS

 1. dependency [REQUIRED] [string]
    The clmgr label representing the dependency to be searched for
    within the cluster.

 2. type [OPTIONAL] [string]
    An indicator of what type of dependency this is, from the set:

        PARENT_CHILD
        SAME_NODE or NODECOLLOCATION
        SAME_SITE or SITECOLLOCATION,
        DIFFERENT_NODES or ANTICOLLOCATION

=head1 RETURN

 0: no errors were detected; the operation appears to have been successful
 1: a general error has occurred
 2: a specified resource does not exist, or could not be found
 3: some required input was missing
 4: some detected input was incorrect in some way
 5: a required dependency does not exist
 6: a specified search failed to match any data

=head1 COPYRIGHT

COPYRIGHT International Business Machines Corp. 2005,2010
All Rights Reserved

=cut
} # End of POD-formatted documentation.


#================================================================
# Returns:  0: if no non-whitespace differences were found.
#           1: if SET1 contained an item that SET2 did not  
#           2: if SET2 contained an item that SET1 did not  
#================================================================
function set_differences {
    typeset SET1=${1//,/ }
    typeset SET2=" ${2//,/ } "

    [[ $SET1 == $SET2 ]] && return 0

    typeset ITEM=

    for ITEM in $SET1; do
        if [[ " $SET2 " == *\ $ITEM\ * ]]; then
            SET2="${SET2// $ITEM / }"
        else
            return 1  # SET1 contained an item that SET2 did not
        fi
    done

    [[ $SET2 != +([[:space:]]) ]] && return 2 # SET2 contained an item
                                              # that SET1 did not
    return 0
} # End of "set_differences()"


function KLIB_HACMP_is_known_dependency {
    LINENO=2 . $HALIBROOT/log_entry "$0()" "$CL"
    : version=1.3, src/43haes/lib/ksh93/hacmp/KLIB_HACMP_is_known_dependency.sh, hacmp.assist, 61haes_r714
    : INPUTS: $*

    typeset dependency=${1//\"/}  # Required
    typeset -u type=${2//\"/}     # Optional
    type=${type#\(}
    type=${type%\)}
    [[ -n $3 ]] && typeset -n DEPENDENCIES=$3
 
    [[ $CLMGR_LOGGING == 'med' ]] && set +x  # Only trace param values

    #===================================
    : Declare and initialize variables
    #===================================
    typeset line= rg= parent= child= ODMDATA= id_list=
    typeset -A list pcdeps stopafterdeps startafterdeps
    typeset RESULT=1
    typeset -i INDEX=0 I=0 rc=$RC_UNKNOWN
    typeset -i return_list=0
    [[ -n $3 ]] && return_list=1

    unset DEPTYPE

    : Remove all whitespace
    dependency=${dependency//+([[:space:]])/}

    : See if a dependency type was also provided
    if [[ $dependency == *\(*\)* ]]; then
        type=${dependency##*\(}
        type=${type%%\)*}
        dependency=${dependency/\(*\)}
    fi

    #=================
    : Validate input
    #=================
    if [[ -z $dependency ]]; then
        /usr/bin/dspmsg -s $CLVT_SET $CLVT_MSGS 100 "\nERROR: a name/label must be provided.\n\n" 1>&2
        rc=$RC_MISSING_INPUT

    else
        #================================================================
        : Load all known dependencies, avoiding the "list_dependencies"
        : function. Using that function here would result in a circular
        : reference, which will cause ksh93 to core dump!
        #================================================================

        ##
        ## ACQUIRE/RELEASE ORDER
        ##
        print -- "$0()[$LINENO]($SECONDS): $HAUTILS/clrgorder -s | /usr/bin/grep -v '#'" >>$CLMGR_TMPLOG  # Always log commands
        $HAUTILS/clrgorder -s | /usr/bin/grep -v '#' |\
        IFS=: read sel_acq par_acq ser_rel par_rel
        for rg in ${par_acq//,/ }; do
            [[ -n $dep ]] && dep="$dep,"
            dep="$dep$rg"
        done
        print "clrgorder RC: $?" >>$CLMGR_TMPLOG  # Always log command result
        if [[ $dep != *([[:space:]]) ]]; then
            list[$INDEX]="$dep (ACQUIRE_IN_PARALLEL)"
            (( INDEX++ ))
        fi
        dep=
        for rg in ${sel_acq//,/ }; do
            [[ -n $dep ]] && dep="$dep,"
            dep="$dep$rg"
        done
        if [[ $dep != *([[:space:]]) ]]; then
            list[$INDEX]="$dep (ACQUIRE_SERIALLY)"
            (( INDEX++ ))
        fi
        dep=
        for rg in ${par_rel//,/ }; do
            [[ -n $dep ]] && dep="$dep,"
            dep="$dep$rg"
        done
        if [[ $dep != *([[:space:]]) ]]; then
            list[$INDEX]="$dep (RELEASE_IN_PARALLEL)"
            (( INDEX++ ))
        fi
        dep=
        for rg in ${ser_rel//,/ }; do
            [[ -n $dep ]] && dep="$dep,"
            dep="$dep$rg"
        done
        if [[ $dep != *([[:space:]]) ]]; then
            list[$INDEX]="$dep (RELEASE_SERIALLY)"
            (( INDEX++ ))
        fi

        ##
        ## PARENT/CHILD
        ##
        if [[ -z $type || $type == "PARENT_CHILD" ]]; then
            print -- "$0()[$LINENO]($SECONDS): $HAUTILS/clrgdependency -t PARENT_CHILD -sl | /usr/bin/grep -v '#'" >>$CLMGR_TMPLOG  # Always log commands
            $HAUTILS/clrgdependency -t PARENT_CHILD -sl |/usr/bin/grep -v '#' |\
            while read parent child; do
                if [[ -n ${pcdeps[$parent]} ]]; then
                    pcdeps[$parent]="${pcdeps[$parent]},$child"
                else
                    pcdeps[$parent]=$child
                fi
            done
            print "clrgdependency RC: $?" >>$CLMGR_TMPLOG  # Always log command result
            for parent in ${!pcdeps[*]}; do
                list[$INDEX]="${parent}+${pcdeps[$parent]} (PARENT_CHILD)"
                (( INDEX++ ))
            done
        fi

        ##
        ## STOP AFTER
        ##
        if [[ -z $type || $type == "STOP_AFTER" ]]; then
            print -- "$0()[$LINENO]($SECONDS): $HAUTILS/clrgdependency -t STOP_AFTER -sl | /usr/bin/grep -v '#'" >>$CLMGR_TMPLOG  # Always log commands
            $HAUTILS/clrgdependency -t STOP_AFTER -sl 2>>$CLMGR_TMPLOG |/usr/bin/grep -v '#' |\
            while read source target; do
                if [[ -n ${stopafterdeps[$target]} ]]; then
                    stopafterdeps[$target]="${stopafterdeps[$target]},$source"
                else
                    stopafterdeps[$target]=$source
                fi
            done
            print "clrgdependency RC: $?" >>$CLMGR_TMPLOG  # Always log command result
            for target in ${!stopafterdeps[*]}; do
                list[$INDEX]="${target}+${stopafterdeps[$target]} (STOP_AFTER)"
                (( INDEX++ ))
            done
        fi

        ##
        ## START AFTER
        ##
        if [[ -z $type || $type == "START_AFTER" ]]; then
            print -- "$0()[$LINENO]($SECONDS): $HAUTILS/clrgdependency -t START_AFTER -sl | /usr/bin/grep -v '#'" >>$CLMGR_TMPLOG  # Always log commands
            $HAUTILS/clrgdependency -t START_AFTER -sl 2>>$CLMGR_TMPLOG |/usr/bin/grep -v '#' |\
            while read source target; do
                if [[ -n ${startafterdeps[$target]} ]]; then
                    startafterdeps[$target]="${startafterdeps[$target]},$source"
                else
                    startafterdeps[$target]=$source
                fi
            done
            print "clrgdependency RC: $?" >>$CLMGR_TMPLOG  # Always log command result
            for target in ${!startafterdeps[*]}; do
                list[$INDEX]="${target}+${startafterdeps[$target]} (START_AFTER)"
                (( INDEX++ ))
            done
        fi

        ##
        ## SAME SITE
        ##
        if [[ -z $type || $type == @(SAME_SITE|SITECOLLOCATION) ]]; then
            print -- "$0()[$LINENO]($SECONDS): $HAUTILS/clrgdependency -t SITECOLLOCATION -sl | /usr/bin/grep -v '#'" >>$CLMGR_TMPLOG  # Always log commands
            $HAUTILS/clrgdependency -t SITECOLLOCATION -sl | /usr/bin/grep -v '#' |\
            while read dep; do
                dep=${dep//+([[:space:]])/,}
                list[$INDEX]="$dep (SAME_SITE)"
                (( INDEX++ ))
            done
            print "clrgdependency RC: $?" >>$CLMGR_TMPLOG  # Always log command result
        fi

        ##
        ## SAME NODE
        ##
        if [[ -z $type || $type == @(SAME_NODE|NODECOLLOCATION) ]]; then
            print -- "$0()[$LINENO]($SECONDS): $HAUTILS/clrgdependency -t NODECOLLOCATION -sl | /usr/bin/grep -v '#'" >>$CLMGR_TMPLOG  # Always log commands
            $HAUTILS/clrgdependency -t NODECOLLOCATION -sl | /usr/bin/grep -v '#' |\
            while read dep; do
                dep=${dep//+([[:space:]])/,}
                list[$INDEX]="$dep (SAME_NODE)"
                (( INDEX++ ))
            done
            print "clrgdependency RC: $?" >>$CLMGR_TMPLOG  # Always log command result
        fi

        ##
        ## DIFFERENT NODES
        ##
        if [[ -z $type || $type == @(DIFFERENT_NODES|ANTICOLLOCATION) ]]; then
            print -- "$0()[$LINENO]($SECONDS): $HAUTILS/clrgdependency -t ANTICOLLOCATION -sl | /usr/bin/grep -v '#'" >>$CLMGR_TMPLOG  # Always log commands
            $HAUTILS/clrgdependency -t ANTICOLLOCATION -sl | /usr/bin/grep -v '#' |\
            while IFS=: read high int low; do
                high=${high//+([[:space:]])/,}
                int=${int//+([[:space:]])/,}
                low=${low//+([[:space:]])/,}
                list[$INDEX]="${high}+${int}+${low} (DIFFERENT_NODES)"
                (( INDEX++ ))
            done
            print "clrgdependency RC: $?" >>$CLMGR_TMPLOG  # Always log command result
        fi

        INDEX=0
        for (( I=0; I<${#list[*]}; I++ )); do
            [[ -n $type && ${list[$I]} != *\($type\)*     ]] && continue
            [[ $dependency == *\+* && ${list[$I]} != *\+* ]] && continue
            [[ $dependency == *,* && ${list[$I]} != *,*   ]] && continue

            #################################################################
            ##  TEMPORAL DEPENDENCY (order matters; location is irrelevant)
            #################################################################
            if [[ $type == @(PARENT_CHILD|STOP_AFTER|START_AFTER) || \
                  $dependency == *\+* ]]
            then
                parents=${dependency%%\+*}
                parents=${parents//,/ }
                children=${dependency##*\+}
                children=${children//,/ }

                DEPTYPE=${list[$I]}
                DEPTYPE=${DEPTYPE##*\(}
                DEPTYPE=${DEPTYPE%%\)*}

                list[$I]=${list[$I]%%*([[:space:]])\(*}
                group_parents=${list[$I]%%\+*}
                group_parents=${group_parents//,/ }

                set_differences "$parents" "$group_parents"
                if (( $? == RC_SUCCESS )); then
                    group_children=${list[$I]##*\+}
                    group_children=${group_children//,/ }
                    set_differences "$children" "$group_children"
                    if (( $? == RC_SUCCESS )); then
                        rc=$RC_SUCCESS
                        if (( return_list )); then
                            DEPENDENCIES[$INDEX]="${list[$I]} ($DEPTYPE)"
                            (( INDEX++ ))
                        fi
                        break
                    fi
                else
                    unset DEPTYPE
                fi

            ####################################################################
            ##  LOCATION DEPENDENCY (order is irrelevant; only location matters)
            ####################################################################
            else
                DEPTYPE=${list[$I]}
                DEPTYPE=${DEPTYPE##*\(}
                DEPTYPE=${DEPTYPE%%\)*}

                dependency=${dependency//,/ }
                list[$I]=${list[$I]%%*([[:space:]])\(*}

                set_differences "$dependency" "${list[$I]//,/ }"
                if (( $? == RC_SUCCESS )); then
                    rc=$RC_SUCCESS
                    if (( return_list )); then
                        DEPENDENCIES[$INDEX]="${list[$I]} ($DEPTYPE)"
                        (( INDEX++ ))
                    fi
                    break
                else
                    unset DEPTYPE
                fi
            fi
        done

        export DEPTYPE
        (( $rc != RC_SUCCESS )) && rc=$RC_ERROR
    fi

    log_return_msg "$rc" "$0()" "$LINENO"
    return $?
} # End of "KLIB_HACMP_is_known_dependency()"
