#!/bin/bash
#
# Wrapper to help pg_regress find the right valgrind to run.
#
# Sensitive to env vars:
#
#   VG_LOG
#   VG_ARGS
#   VG_INITDB_ARGS
#   VG_CHECK_INITDB=yes

# Invoke with PG_VALGRIND_SUPPRESSIONS set.

set -e -u

mycmd="$(basename $0)"
mydir="$(dirname $0)"

##########################################################
# Look along path for next executable with same name as us

NEXT_EXEC=$(type -pafP $mycmd |  awk '{ if (NR == 2) { print; exit; } }')

if [ "${NEXT_EXEC}" -ef "./dev-tools/valgrind/$mycmd" ]; then
    echo "ERROR: attempt to execute self"
    exit 1
fi

##########################################################
# Don't run valgrind for initdb or its children by default. It's slow and
# pointless.

if [ "${VG_CHECK_INITDB:-no}" != "yes" ]; then
    if [ "$mycmd" == "initdb" ]; then
	# You can also use this to inject extra initdb args, like here.
	exec "$NEXT_EXEC" "$@" ${VG_INITDB_ARGS:- -d -N}
    else
	# Skip single-user postgres executions done by initdb too
	for arg in "$@" ; do
	    if [ "$arg" == "--boot" ]; then
		exec "$NEXT_EXEC" "$@"
	    fi
	done
    fi
fi

# pg_ctl wants to use find_other_exec to find other commands relative to its
# argv[0]. So if we just exec'd it directly it'd look in the NEXT_EXEC
# directory for subcommands and the wrapper would not run again.
#
# Instead, lie about its location. All commands pg_ctl might run must
# have wrapper links in this directory. Postgres itself doesn't matter since
# once valgrind hooks the postmaster it'll trace all children anyway.
#
if [ "$mycmd" == "pg_ctl" ]; then
    exec -a "$0" "$NEXT_EXEC" "$@"
fi

##########################################################
# Set up the valgrind run
#
# User may set VG_LOG to preferred log path.
#
# Any configuration in ~/.valgrindrc, the env var VALGRIND_OPTS or any
# ./.valgrindrc in the CWD are read too, per the Valgrind manual.
#
# See https://valgrind.org/docs/manual/manual-core.html#opt.log-file for patterns
# supported.
#
# Valgrind doesn't give us a way to add the backend role to the filename
# without hacking the postmaster to set an environment variable before
# fork()ing so it's just a pile of files by pid. But bdr3 and pgl3 use valgrind
# macros to emit some helper info into Valgrind's logs.
#

if [ -z "${VG_LOG:-}" ]; then
    VG_LOG="./valgrind-logs-$$/%n-%p.log"
fi

if [ -n "$(dirname "${VG_LOG}")" ]; then mkdir -p "$(dirname "${VG_LOG}")" ; fi

VG_ARGS="--trace-children=yes --log-file=${VG_LOG} --time-stamp=yes ${VG_ARGS:-}"

# Don't generate stdout or we'll confuse find_other_exec's --version check
echo "Running ${NEXT_EXEC} under Valgrind with logs at ${VG_LOG}" 1>&2

exec valgrind $VG_ARGS "${NEXT_EXEC}" "$@"
