#!/bin/sh
# fake-cluster-control
#
# Copyright (C) 2012, 2014, 2017, 2018, 2021 Thien-Thi Nguyen
#
# This file is part of Guile-PG.
#
# Guile-PG is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 3, or
# (at your option) any later version.
#
# Guile-PG is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Guile-PG.  If not, see <http://www.gnu.org/licenses/>.

LANG=C
export LANG

i=`basename $0`
fc=fake-cluster
log=$fc.log
full=`pwd`/$fc
pidfile=$fc/postmaster.pid
initdb=${INITDB-/home/ttn/bin/initdb}

drat ()
{
    echo 1>&2 ${i}: ERROR: "$@"
    exit 1
}

trycommand ()
{
    # $1 -- generic name
    # $2 -- actual command
    test -n "$2"                                \
        || drat "Undefined $1 command"
    "$2" --version 1>>$log 2>&1                         \
        || drat "Bad $1 command: '$2' (see '$log')"
}

frob ()
{
    "$PGPATH/psql" -h $full -d "$@"
}

truly_up ()
{
    test -f $pidfile \
        && ps `head -n 1 $pidfile` 1>/dev/null 2>&1 \
        && frob template1 -l 1>/dev/null 2>&1
}

truly_down ()
{
    ! truly_up
}

hopefully ()
{
    # $1 = direction
    count=15
    while [ ! 0 = $count ] ; do
        if truly_$1 ; then
            echo ${i}: daemon now $1
            return 0
        fi
        sleep 1
        count=`expr $count - 1`
    done
    drat "Could not bring $1 daemon within 15 seconds"
}

# Sanity checks.

test "$initdb" && test -x "$initdb" \
    || drat 'Could not find initdb(1).  Set env var INITDB to full filename.'

test x"$1" = x && drat 'Missing arg COMMAND'

if [ x1 = x"$DEBUG" ] ; then
    hey=:
    set -x
else
    hey="echo ${i}:"
fi

# Set PGPATH and check it.
eval `$initdb --show $fc 2>&1 | sed '/PGPATH=/!d'`
test -d "$PGPATH" || drat 'Could not determine PGPATH'

case "$1" in

    1) # up
        date +'============================================== %F %H:%M' 1>>$log
        trycommand initdb "$initdb"
        pgctl="$PGPATH/pg_ctl"
        trycommand pg_ctl "$pgctl"
        if [ ! -d $fc ] ; then
            $hey creating cluster...
            # Hmm, ‘initdb --no-locale’ seems to be undocumented.
            $initdb --locale C --encoding UTF8 $fc 1>>$log 2>&1         \
                || drat "Could not create cluster '$full' (see '$log')"
            $hey tweaking configuration...
            cfg=$fc/postgresql.conf
            # PostgreSQL 9.3 replaces ‘unix_socket_directory’ w/
            # ‘unix_socket_directories’.  Handle both w/ a regexp -- DWR!
            sed -e "/^.*\(listen_addresses\).*$/s||\1 = ''|"            \
                -e "/^.*\(unix_socket_dir[a-z]*\).*/s||\1 = '$full'|"   \
                $cfg > ${cfg}T                                          \
                && mv ${cfg}T $cfg                                      \
                || drat "Could not tweak '$cfg'"
        fi
        if truly_down ; then
            $hey kicking daemon...
            # TODO: When 7.4 support is dropped, use ‘pg_ctl --silent’.
            "$pgctl" start -D $fc -l $log 1>/dev/null
            # Unfortunately, ‘pg_ctl -w’ loses for Unix-domain sockets.
            hopefully up
        fi
        if ! frob guile_pg_test -c '' 1>/dev/null 2>&1 ; then
            $hey creating database guile_pg_test
            frob template1 -c \
                "CREATE DATABASE guile_pg_test WITH ENCODING = 'UTF8';" \
                || drat "Could not create database \"guile_pg_test\""
        fi
        ;;

    0) # down
        test -f $pidfile || exit 0
        pid=`head -n 1 $pidfile`
        if ps $pid >/dev/null 2>&1 ; then
            $hey killing daemon...
            kill $pid
            hopefully down
        else
            rm $pidfile
        fi
        ;;

    q) # query-status
        if [ -f $pidfile ] ; then
            echo ${i}: daemon running
            echo pidfile:
            sed 's/^/|/' $pidfile
            echo 'log: (tail)'
            tail $log | sed 's/^/|/'
        else
            echo ${i}: daemon not running
        fi
        ;;

    d) # drop-database
        frob template1 -c 'DROP DATABASE IF EXISTS guile_pg_test' \
            || drat "Could not drop database \"guile_pg_test\""
        ;;

    *)
        drat "Bad command: '$1'"
        ;;
esac
exit 0

# fake-cluster-control ends here
