#!/bin/bash
################################################################################
# Copyright (c) 2017 VMware, Inc. All rights reserved.
################################################################################
# Sanity checks and processing before starting WAL archiving service.

ENCODING=UTF8
THIS_DIR=`dirname $0`

if [ -z $VMWARE_POSTGRES_BASE ]; then
   echo "VMWARE_POSTGRES_BASE is not set."
   echo "Check your installation."
   exit 1
fi
SANITY_FILE=$VMWARE_POSTGRES_BASE/scripts/vpostgres_sanity_checks
if [ -f $SANITY_FILE ]; then
   source $SANITY_FILE
else
   echo "Sanity check file for environment variables of VMware Postgres"
   echo "is not available. Check your installation."
   exit 1
fi

# Do not check that in vpostgres_sanity_checks as this is a vCenter-only
# configuration variable.
if [ -z $PGSERVICEFILE ]; then
   echo "PGSERVICEFILE is not set"
   exit 1
fi

# Show utility help
show_help()
{
   ERROR_NUM=$1
   echo "Usage: `basename $0` [SLOT_NAME] [MAX_TIMEOUT]"
   echo "Example: `basename $0` archiver_slot"
   exit $ERROR_NUM
}

EXPECTED_ARGS=2
if [ $# -ne $EXPECTED_ARGS ]; then
   # Leave with an error code
   show_help 1
fi

SLOT_NAME=$1
MAX_TIMEOUT=$2

# Remove any previous health status file.  This is more a sanity check
# than anything else as no other services depend on the archiver, still
# is it is better to start on safe grounds.
rm -f /dev/shm/vmware-postgres-archiver-health-status.xml

# Wait for Postgres to finish recovery and to accept connections before
# doing anything. pg_isready is able to make the difference between an
# instance rejecting connections on purpose and one that is just offline.
STATUS_CODE=1
TIMEOUT_VALUE=0
while [ $STATUS_CODE != 0 -a $TIMEOUT_VALUE != $MAX_TIMEOUT ]; do
   ${VMWARE_POSTGRES_BIN}/pg_isready -d "service=archiver"
   STATUS_CODE=$?

   # Potential status codes of PQping are listed in libpq-fe.h:
   # PQPING_OK = 0, connection accepted.
   # PQPING_REJECT = 1, connection rejected.
   # PQPING_NO_RESPONSE = 2, connection not established.
   # PQPING_NO_ATTEMPT = 3, error while processing.
   if [ $STATUS_CODE == 2 -o $STATUS_CODE == 3 ]; then
      echo "connection to server failed, sleep and retry."
      TIMEOUT_VALUE=$((TIMEOUT_VALUE + 1))
      sleep 1
   elif [ $STATUS_CODE == 1 ]; then
      echo "server rejecting connections, sleep and retry."
      TIMEOUT_VALUE=$((TIMEOUT_VALUE + 1))
      sleep 1
   elif [ $STATUS_CODE == 0 ]; then
      echo "server accepting connections, continue."
   fi
done

# Get vCenter version
VC_VER=$(grep 'NAME:VC' ${VMWARE_CFG_DIR}/.buildInfo |awk -F '-' '{print$2}')

# First create a replication slot to be used by the archiver
${VMWARE_POSTGRES_BIN}/pg_archiver --verbose -d "service=archiver" \
   --create-slot --slot $SLOT_NAME
ERR_NUM=$?
if [ $ERR_NUM != 0 ]; then
   # No new slot has been created. This can happen because the archiving
   # service failed previously and the slot has not been dropped by
   # PostgreSQL, meaning that the service can still use the same slot.
   # Collect telemetry data for pg_archiver service:
   #    -- slot exists
   #    -- old wal files will be kept
   # Push telemetry data by calling pg_trigger_telemetry.
   echo "collect telemetry data for pg_archiver service"
   ${VMWARE_POSTGRES_BASE}/bin/vmw_vpg_config/pg_trigger_telemetry.py \
    --event-type='archiver' --data1='Existing Slot' --data2='Keep WAL' \
    --data3="${VC_VER}"
   exit 0
fi

# A new slot has been created. The service will plug into it, but that
# means that any archived WAL segments that exist currently need to be
# removed to ensure that the archiver process evaluates a correct start WAL
# position for the streaming. If there are no archived WAL segments present,
# the archiver would let Postgres begin the stream at the current WAL
# location, which would be fine for a first use.
#
# XXX: we could as well rename the existing segments or move them
# elsewhere and have the automatic purging logic of the archiver take
# them into account, but that complicates the dependencies between
# this script and the archiver service, which may not be worth it.
find "${VMWARE_POSTGRES_ARCHIVE}" -name "*.gz*" -delete

# Collect telemetry data for pg_archiver service:
#    -- slot is newly created
#    -- old wal files have be deleted
echo "collect telemetry data for pg_archiver service"
${VMWARE_POSTGRES_BASE}/bin/vmw_vpg_config/pg_trigger_telemetry.py \
 --event-type='archiver' --data1='New Slot' --data2='Delete WAL' \
 --data3="${VC_VER}"
# Failures to push telemetry data shouldn't impact start up
ERR_NUM=$?
if [ "$ERR_NUM" != 0 ]; then
   # Do not return an error in the event of a failure, as telemetry data
   # loss should not result in a critical failure.
   echo "Could not generate telemetry data"
fi
exit 0
