#!/usr/bin/bash
#
# pgpool-II backend node configuration driver.
#
# Copyright EnterpriseDB Corporation, 2014-2025. All Rights Reserved.
#

# version name
EFM=efm-5.1

PCP_USER='' # PCP user name
PCP_PORT='' # PCP port number as in pgpool.conf
PCP_HOST='' # hostname of Pgpool-II
PCP_PASS_FILE='' # file containing credentials fort pcp user
PGPOOL_PATH='' # Pgpool-II installed path

#
# look for the last occurrence of a non-commented line. Leading and trailing
# white spaces trimmed.
#
# shell functions can't return string, so rely on clunky outvar
#
# Params
#   $1 outvar - this is the name of the variable to store the result in
#   $2 property name to look for
#   $3 property file to grep in
get_prop() {
    local OUTVAR=$1
    local PROP_NAME=$2
    local PROP_FILE=$3
    local RESULT=$(grep "${PROP_NAME}" "${PROP_FILE}" | grep -v \# | tail -1 | cut -d'=' -f2 | awk '{$1=$1};1')
    eval ${OUTVAR}=\$RESULT
}

# function returns the Pgpool-II backend node-id for the given hostname
# and port number, And if the node-id is not found 255 is returned
# Arguments:
# 1- Hostname
#
function get_pgpool_nodeid_from_host {
    if [ -z "$1" ]; then
        echo "hostname not provided"
        return 255
    fi

    # Now get the total number of nodes configured in Pgpool-II
    node_count=$("$PGPOOL_PATH"/pcp_node_count -U "$PCP_USER" -h "$PCP_HOST" -p "$PCP_PORT" -w)

    i=0
    while [ $i -lt "$node_count" ];
    do
        nodeinfo=$("$PGPOOL_PATH"/pcp_node_info -U "$PCP_USER" -h "$PCP_HOST" -p "$PCP_PORT" -w $i)
        hostname=$(echo "$nodeinfo" | awk -v N=1 '{print $N}')

        if [ "$hostname" == "$1" ];
        then
            return $i
        fi

        let i=i+1
    done
    return 255
}

# Function attach the node-id to the Pgpool-II
# Arguments
# 1- node-id: Pgpool-II backend node-id to be attached
#
function attach_node_id {
    if [ -z "$1" ]; then
        echo "node-id not provided"
        return 255
    fi

    "$PGPOOL_PATH"/pcp_attach_node -w -U "$PCP_USER" -h "$PCP_HOST" -p "$PCP_PORT" "$1"
    return $?
}

# Function detach the node-id from the Pgpool-II
# Arguments
# 1- node-id: Pgpool-II backend node-id to be detached
#
function detach_node_id {
    if [ -z "$1" ]; then
        echo "node-id not provided"
        return 255
    fi

    "$PGPOOL_PATH"/pcp_detach_node -w -U "$PCP_USER" -h "$PCP_HOST" -p "$PCP_PORT" "$1"
    return $?
}

# function attaches the backend node identified by hostname:port
# to Pgpool-II
# Arguments:
# 1- Hostname
#
function attach_node {
    get_pgpool_nodeid_from_host "$1"
    node_id=$?

    if [ $node_id -eq 255 ]; then
        echo "unable to find Pgpool-II backend node id for $1"
        return 255
    else
        attach_node_id $node_id
        return $?
    fi
}

# function detaches the backend node identified by hostname:port
# from Pgpool-II
# Arguments:
# 1- Hostname
#
function detach_node {
    get_pgpool_nodeid_from_host "$1"
    node_id=$?

    if [ $node_id -eq 255 ]; then
        return 255
    else
        detach_node_id $node_id
        return $?
    fi
}

function watchdog_info {
    "$PGPOOL_PATH"/pcp_watchdog_info -w -U "$PCP_USER" -h "$PCP_HOST" -p "$PCP_PORT" -v
}

function print_usage {
    echo $"Usage: $0 attach      <cluster name|props file location> <host>"
    echo $"       $0 detach      <cluster name|props file location> <host>"
    echo $"       $0 watchdog    <cluster name|props file location>"
}

# script entry point
if [ -z "$1" ] || [ -z "$2" ]; then
    echo "ERROR: operation not provided"
    print_usage
    exit 1
fi

if [[ "$2" == *\.properties ]]; then
    # If the given value ends with ".properties" consider it as a properties file path
    PROPS="$2";
elif [ -f "$HOME/${EFM}/$2.properties" ]; then
    # If props file path not given then check if the properties file with given cluster
    #  name exists in user's home directory. If present, consider that as properties file.
    PROPS="$HOME/${EFM}/$2.properties"
else
    # If not found in user's home dir too then use the default props file location
    PROPS="/etc/edb/${EFM}/$2.properties"
fi

get_prop PCP_USER pcp.user "${PROPS}"
get_prop PCP_HOST pcp.host "${PROPS}"
get_prop PCP_PORT pcp.port "${PROPS}"
get_prop PCP_PASS_FILE pcp.pass.file "${PROPS}"
get_prop PGPOOL_PATH pgpool.bin "${PROPS}"

# export this env variable for pgpool scripts to access
export PCPPASSFILE="$PCP_PASS_FILE"

shopt -s nocasematch
case "$1" in
    "attach" )
        attach_node "$3"
        ;;
    "detach" )
        detach_node "$3"
        ;;
    "watchdog" )
        watchdog_info
        ;;
    *)
        echo "invalid operation $1".
        print_usage;;
    esac
exit $?
