#!/bin/bash

# assume both instances are running, on port 6972 (master) and 6973 (replica)

port1=6972
port2=6973

logfile1=$HOME/pg_stuff/pg_installations/pgsql.logical_replication/logfile.logical_replication
logfile2=$HOME/pg_stuff/pg_installations/pgsql.logical_replication2/logfile.logical_replication2

# clear logs
echo > $logfile1
echo > $logfile2

scale=1;       if [[ ! "$1" == "" ]]; then scale=$1;      fi
clients=1;     if [[ ! "$2" == "" ]]; then clients=$2;    fi
INIT_WAIT=0;   if [[ ! "$3" == "" ]]; then INIT_WAIT=$3;  fi
CLEAN_ONLY=''; if [[ ! "$4" == "" ]]; then CLEAN_ONLY=$4; fi
echo    "--     scale  $scale     clients  $clients   INIT_WAIT  $INIT_WAIT    CLEAN_ONLY=$CLEAN_ONLY"

(
echo    "============================================================================"
echo    "--     "$(date +"%Y%m%d %H:%M:%S")
echo    "--     scale  $scale     clients  $clients   INIT_WAIT  $INIT_WAIT"
echo    "-- "
)

unset PGSERVICEFILE PGSERVICE   # PGPORT PGDATA PGHOST
export PGDATABASE=testdb

# (this script uses a custom pgpassfile)

function cb()
{
  #  display the 4 pgbench tables' accumulated content as md5s
  #  a,b,t,h stand for:  pgbench_accounts, -branches, -tellers, -history
  md5_total_6972='-1'
  md5_total_6973='-2'
  num_tables=$( echo "select count(*) from pg_class where relkind = 'r' and relname ~ '^pgbench_'" | psql -qtAX )
  if [[ $num_tables -ne 4 ]] 
  then
     echo "pgbench tables not 4 - exit" >> $outf
     exit
  fi
  for port in $port1 $port2
  do
    md5_a=$(echo "select * from pgbench_accounts order by aid"|psql -qtAXp$port|md5sum|cut -b 1-9)
    md5_b=$(echo "select * from pgbench_branches order by bid"|psql -qtAXp$port|md5sum|cut -b 1-9)
    md5_t=$(echo "select * from pgbench_tellers  order by tid"|psql -qtAXp$port|md5sum|cut -b 1-9)
    md5_h=$(echo "select * from pgbench_history  order by hid"|psql -qtAXp$port|md5sum|cut -b 1-9)
    cnt_a=$(echo "select count(*) from pgbench_accounts"|psql -qtAXp $port)
    cnt_b=$(echo "select count(*) from pgbench_branches"|psql -qtAXp $port)
    cnt_t=$(echo "select count(*) from pgbench_tellers" |psql -qtAXp $port)
    cnt_h=$(echo "select count(*) from pgbench_history" |psql -qtAXp $port)
    md5_total[$port]=$( echo "${md5_a} ${md5_b} ${md5_t} ${md5_h}" | md5sum )
    printf "$port a,b,t,h: %6d %6d %6d %6d" $cnt_a  $cnt_b  $cnt_t  $cnt_h
    echo -n "   $md5_a $md5_b $md5_t $md5_h"
    if   [[ $port -eq $port1 ]]; then echo    "   master"
    elif [[ $port -eq $port2 ]]; then echo -n "   replica"
    else                              echo    "             ERROR  "
    fi
  done
  if [[ "${md5_total[$port1]}" == "${md5_total[$port2]}" ]]
  then
    echo " ok"
  else
    echo " NOK"
  fi
}

sub_count=$( echo "select count(*) from pg_subscription" | psql -qtAXp $port2 )
if  [[ $sub_count -ne 0 ]]
then
  echo "sub_count -ne 0 : deleting sub1"
  echo "drop subscription if exists sub1"              | psql -qXp $port2 
  echo "drop subscription if exists sub1 nodrop slot"  | psql -qXp $port2 
fi

sub_repl_slot_count=$( echo "select count(*) from pg_replication_slots" | psql -qtAXp $port2 )
if  [[ $sub_repl_slot_count -ne 0 ]]
then
  echo "sub_repl_slot_count -ne 0 - deleting"
  echo "select pg_drop_replication_slot('sub1')" | psql -Xp $port1
fi

pub_count=$( echo "select count(*) from pg_publication" | psql -qtAXp $port1 )
if  [[ $pub_count -ne 0 ]]
then
  echo "pub_count -ne 0 - deleting pub1"
  echo "drop publication if exists pub1" | psql -qXp $port1
fi

pub_repl_slot_count=$( echo "select count(*) from pg_replication_slots" | psql -qtAXp $port1 )
if  [[ $pub_repl_slot_count -ne 0 ]]
then
  echo "pub_repl_slot_count -ne 0 - deleting (sub1)"
  echo "select pg_drop_replication_slot('sub1')" | psql -qXp $port1
fi

pub_count=$(           echo "select count(*) from pg_publication"       | psql -qtAXp $port1 )
pub_repl_slot_count=$( echo "select count(*) from pg_replication_slots" | psql -qtAXp $port1 )
sub_count=$(           echo "select count(*) from pg_subscription"      | psql -qtAXp $port2 )
sub_repl_slot_count=$( echo "select count(*) from pg_replication_slots" | psql -qtAXp $port2 )

echo "
          pub_count  $pub_count
pub_repl_slot_count  $pub_repl_slot_count
          sub_count  $sub_count
sub_repl_slot_count  $sub_repl_slot_count
"

if  [[ $pub_count           -ne 0 ]] \
 || [[ $sub_count           -ne 0 ]] \
 || [[ $pub_repl_slot_count -ne 0 ]] \
 || [[ $sub_repl_slot_count -ne 0 ]] \
;
then
    exit 1
fi

if [[ ! "$CLEAN_ONLY" == "" ]]
then
    exit 0
fi

logfile_ts=$( date +"%Y%m%d_%H%M_%s%N" )

   echo "drop table if exists pgbench_accounts;
         drop table if exists pgbench_branches;
         drop table if exists pgbench_tellers;
         drop table if exists pgbench_history;" | psql -qXp $port1 \
&& echo "drop table if exists pgbench_accounts;
         drop table if exists pgbench_branches;
         drop table if exists pgbench_tellers;
         drop table if exists pgbench_history;" | psql -qXp $port2

pgbench -p $port1 -qis $scale && echo "
        alter table pgbench_history add column hid serial primary key;
     -- alter table pgbench_history replica identity full;
     -- delete from pgbench_accounts where aid > 40;
" | psql -q1Xp $port1  \
  && pg_dump -F c --no-create-subscription-slots -p $port1 \
           -t pgbench_history  \
           -t pgbench_accounts \
           -t pgbench_branches \
           -t pgbench_tellers  \
  | pg_restore -1 -p $port2 -d testdb

# echo "-- (no diffs expected... )" 
# echo  "$(cb)"

# empty the tables on replica:
echo "
delete from pgbench_accounts; 
delete from pgbench_branches; 
delete from pgbench_tellers; 
delete from pgbench_history;
" | psql -q -X -p $port2 

# echo "-- (pre-replication,  diffs *are* expected... )" 
# echo  "$(cb)"
echo "create publication pub1 for all tables;" | psql -p $port1 -aqtAX
echo "create subscription sub1 connection 'port=${port1}' publication pub1 with (disabled);
alter subscription sub1 enable;
" | psql -p $port2 -aqtAX

if [[ $INIT_WAIT -gt 0 ]]
then
  echo "-- wait ${INIT_WAIT}s"
  sleep $INIT_WAIT
fi

RUN_PGBENCH=1

if [[ $RUN_PGBENCH -eq 1 ]]
then
  echo "-- pgbench -c $clients -T 10 -P 5 -n "
           pgbench -c $clients -T 10 -P 5 -n
else
  echo "-- not running pgbench..."
fi

waiting1=$(( $scale * 4 ))
echo "-- waiting ${waiting1}s...  (scale * 4)"
sleep $waiting1
cb_text1=$(cb)
echo "${cb_text1}"

loop_counter=0
wait_chunk=5
wait_max=60
while [[ 1 -eq 1 ]];
do
    waited_already=$(( $loop_counter * $wait_chunk ))
    if [[ $waited_already -gt $wait_max ]]
    then
       echo "-- Not good, but breaking out of wait (waited more than ${wait_max}s)"
       break
    fi

    if echo "$cb_text1" | grep -qw 'replica ok';
    then
       echo "-- All is well."
       break
    fi
    echo "-- wait another ${wait_chunk}s..."
    sleep $wait_chunk;
    cb_text1=$(cb)
    echo "${cb_text1}"
    loop_counter=$(( loop_counter + 1 ))
done

dest_dir='.'
# dest_dir='logfiles'

if  echo "${cb_text1}" | grep -qw 'replica ok'
then
  cp $logfile1 ${dest_dir}/logrep1.$logfile_ts.ok.log
  cp $logfile2 ${dest_dir}/logrep2.$logfile_ts.ok.log
else
  cp $logfile1 ${dest_dir}/logrep1.$logfile_ts.NOK.log
  cp $logfile2 ${dest_dir}/logrep2.$logfile_ts.NOK.log
fi

