#!/bin/bash

################################################################################
################################################################################
# Copyright 2023-2025 by NI SP Software GmbH, All rights reserved.
# Copyright 1999-2023 by Nice, srl., All rights reserved.
#
# This software includes confidential and proprietary information
# of NI SP Software GmbH ("Confidential Information").
# You shall not disclose such Confidential Information
# and shall use it only in accordance with the terms of
# the license agreement you entered into with NI SP Software.
################################################################################
################################################################################

################################################################################
# $EF_ROOT/plugins/grid/bin/common - common settings/functions for Grid Plugin
################################################################################

#-------------------------------------------------------------------------------
# Avoid recursive loops
#-------------------------------------------------------------------------------
if [ -n "$EF_GRID_DO_NOT_RECURSE" ] ; then
    exit 0
fi

EF_GRID_DO_NOT_RECURSE="true"
export EF_GRID_DO_NOT_RECURSE

EF_PLUGIN_NAME="EnginFrame Grid Plug-in"
export EF_PLUGIN_NAME

EF_PLUGIN_FILE="GRID"
export EF_PLUGIN_FILE

EF_PLUGIN_ROOT="${EF_ROOT}/plugins/grid"
export EF_PLUGIN_ROOT

#-------------------------------------------------------------------------------
# Utility functions for grid plugin
#-------------------------------------------------------------------------------

# Note: the backend name cannot contain spaces

grid_call_backend() {
    _script="$1"
    shift

    if [ -n "${GRID_USE_JOBCACHE}" -a "${GRID_USE_JOBCACHE}" = "true" -a "${EF_CURRENT_GRID_MANAGER}" != "hpc" ]; then
        _cached_script="${EF_ROOT}/plugins/grid/bin/${_script}.cached"
        if [ -e "${_cached_script}" ]; then
            "${_cached_script}" "$@" || return $?
        else
            grid_call_backend_nocache "${_script}" "$@" || return $?
        fi
    else
        grid_call_backend_nocache "${_script}" "$@" || return $?
    fi
}

grid_call_backend_nocache() {
    _script="$1"
    shift

    "${EF_ROOT}/plugins/${EF_CURRENT_GRID_MANAGER}/grid/${_script}" "$@" || return $?
}

grid_call_all_backends() {
    _callable="$1" # script or function
    shift

    OLDIFS="${IFS}"
    IFS=","

    _real_current_grid_manager="${EF_CURRENT_GRID_MANAGER}"
    _real_current_cluster="${EF_CURRENT_CLUSTER}"
    for backend in ${EF_GRID_MANAGERS}; do
        IFS="${OLDIFS}"

        export EF_CURRENT_GRID_MANAGER="`echo ${backend} | tr -d [:space:]`"
        export EF_CURRENT_CLUSTER=""

        if [ -x "${EF_ROOT}/plugins/${EF_CURRENT_GRID_MANAGER}/grid/${_callable}" ]; then
            "${EF_ROOT}/plugins/${EF_CURRENT_GRID_MANAGER}/grid/${_callable}" "$@" || return $?
        else
            type ${_callable} 2>&1 >/dev/null
            if [ $? -eq 0 ]; then
                "${_callable}" "$@" || return $?
            else
                return 1;
            fi
        fi

        IFS=","
    done

    EF_CURRENT_GRID_MANAGER="${_real_current_grid_manager}"
    EF_CURRENT_CLUSTER="${_real_current_cluster}"
    IFS="${OLDIFS}"
}

grid_call_backend_with_fallback() {
    local _callable="$1" # script or function
    local _callable_fallback="$2" # script or function
    shift
    shift

    local _backend_path="${EF_ROOT}/plugins/${EF_CURRENT_GRID_MANAGER}/grid"

    if [ -x "${_backend_path}/${_callable}" ]; then
        "${_backend_path}/${_callable}" "$@" || return $?
    elif [ -x "${_backend_path}/${_callable_fallback}" ]; then
        "${_backend_path}/${_callable_fallback}" "$@" || return $?
    else
        return 1;
    fi
}

grid_call_all_backends_with_fallback() {
    _callable="$1" # script or function
    _callable_fallback="$2" # script or function
    shift
    shift

    _real_current_grid_manager="${EF_CURRENT_GRID_MANAGER}"
    _real_current_cluster="${EF_CURRENT_CLUSTER}"

    for backend in $(echo ${EF_GRID_MANAGERS} | tr "," " "); do
        export EF_CURRENT_GRID_MANAGER="`echo ${backend} | tr -d [:space:]`"
        export EF_CURRENT_CLUSTER=""

        grid_call_backend_with_fallback $_callable $_callable_fallback "$@"
    done

    EF_CURRENT_GRID_MANAGER="${_real_current_grid_manager}"
    EF_CURRENT_CLUSTER="${_real_current_cluster}"
}

grid_call_all_backends_if_present() {
    _callable="$1"
    shift

    OLDIFS="${IFS}"
    IFS=","

    _real_current_grid_manager="${EF_CURRENT_GRID_MANAGER}"
    _real_current_cluster="${EF_CURRENT_CLUSTER}"
    for backend in ${EF_GRID_MANAGERS}; do
        IFS="${OLDIFS}"

        export EF_CURRENT_GRID_MANAGER="`echo ${backend} | tr -d [:space:]`"
        export EF_CURRENT_CLUSTER=""

        if [ -x "${EF_ROOT}/plugins/${EF_CURRENT_GRID_MANAGER}/grid/${_callable}" ]; then
            "${EF_ROOT}/plugins/${EF_CURRENT_GRID_MANAGER}/grid/${_callable}" "$@" || return $?
        fi

        IFS=","
    done

    EF_CURRENT_GRID_MANAGER="${_real_current_grid_manager}"
    EF_CURRENT_CLUSTER="${_real_current_cluster}"
    IFS="${OLDIFS}"
}

#-------------------------------------------------------------------------------
# Load common EnginFrame functions and environment
#-------------------------------------------------------------------------------
EF_UTILS="${EF_ROOT}/plugins/ef/lib/utils"

if [ ! -f "${EF_UTILS}" ]; then
    echo '<ef:error>'
    echo "  <ef:title><![CDATA[${EF_PLUGIN_NAME} Error]]></ef:title>"
    echo "  <ef:message><![CDATA[${EF_UTILS} is missing]]></ef:message>"
    echo "  <ef:command><![CDATA[${0//${EF_ROOT}/EF_ROOT}]]></ef:command>"
    echo '</ef:error>'
    exit 1
fi

. ${EF_UTILS}

EF_PLUGINS="${EF_ROOT}/plugins/ef/lib/plugins"

if [ ! -f "${EF_PLUGINS}" ]; then
    echo '<ef:error>'
    echo "  <ef:title><![CDATA[${EF_PLUGIN_NAME} Error]]></ef:title>"
    echo "  <ef:message><![CDATA[${EF_PLUGINS} is missing]]></ef:message>"
    echo "  <ef:command><![CDATA[${0//${EF_ROOT}/EF_ROOT}]]></ef:command>"
    echo '</ef:error>'
    exit 1
fi

. ${EF_PLUGINS}

#-------------------------------------------------------------------------------
# Load the configuration file for Grid Plug-in
#-------------------------------------------------------------------------------
. "${EF_ROOT}/plugins/ef/lib/utils"

# Source grid configuration file
ef_source_conf grid grid.conf

# Source job cache configuration file
ef_source_conf grid jobcache.efconf

if [ -z "${EF_GRID_MANAGERS}" ]; then
    ef_error "No grid manager specified in file grid.conf" \
             "Configuration Error" \
             "\${EF_ROOT}/plugins/grid/bin/common"
    exit 1
fi
export EF_GRID_MANAGERS

if [ -z "${EF_DEFAULT_GRID_MANAGER}" ]; then
    # If no default grid manager is specified, take the first of the list
    EF_DEFAULT_GRID_MANAGER=`echo "${EF_GRID_MANAGERS}" | cut -f1 -d"," | tr -d [:space:]`
fi
export EF_DEFAULT_GRID_MANAGER

if [ -n "${grid}" ]; then
    if [ "${grid}" != "${EF_CURRENT_GRID_MANAGER}" ]; then
        EF_CURRENT_GRID_MANAGER=`echo "${grid}" | tr -d [:space:]`
        EF_CURRENT_CLUSTER="${cluster}"
    elif [ -n "${cluster}" ]; then
        EF_CURRENT_CLUSTER="${cluster}"
    fi
elif [ -z "${EF_CURRENT_GRID_MANAGER}" ]; then
    EF_CURRENT_GRID_MANAGER=`echo "${EF_DEFAULT_GRID_MANAGER}" | tr -d [:space:]`
    EF_CURRENT_CLUSTER=
    if [ -z "${EF_CURRENT_CLUSTER}" ] && [ -x "$EF_ROOT/plugins/${EF_CURRENT_GRID_MANAGER}/grid/grid.cluster.first" ]; then
        EF_CURRENT_CLUSTER=$(eval "$EF_ROOT/plugins//${EF_CURRENT_GRID_MANAGER}/grid/grid.cluster.first")
    fi
fi

export EF_CURRENT_GRID_MANAGER
export EF_CURRENT_CLUSTER

if [ -z "${EF_CURRENT_GRID_MANAGER}" ]; then
    ef_error "The default grid manager is not specified in file grid.conf" \
             "Configuration Error" \
             "\${EF_ROOT}/plugins/grid/bin/common"
    exit 1
fi

# ex:ts=4:sw=4:et:ft=sh:
