#!/bin/bash

killall postgres
sleep 1

PSQL="psql -X"
INITDB="initdb"
DATA_PRIMARY=$HOME/data/primary
DATA_STANDBY=$HOME/data/standby
PORT_PRIMARY=5432
PORT_STANDBY=5433

rm -rf $DATA_PRIMARY $DATA_STANDBY

# Initialize a primary with one standby.
$INITDB -D $DATA_PRIMARY

cat >> $DATA_PRIMARY/postgresql.conf <<EOF
wal_log_hints = off
wal_level = replica
restart_after_crash = off
max_wal_senders = 5
hot_standby = on
fsync = off
port = $PORT_PRIMARY
logging_collector = on
log_directory = 'log'
max_wal_size = 128MB
shared_buffers = 1GB
max_connections = 10
log_min_messages = debug1
log_min_error_statement = debug1
log_checkpoints = on
EOF

cat >> $DATA_PRIMARY/pg_hba.conf <<EOF
host replication ioltas 127.0.0.1/32 trust
host replication ioltas ::1/128 trust
local replication ioltas trust
EOF

pg_ctl start -w -D $DATA_PRIMARY
createdb $USER

pg_basebackup -D $DATA_STANDBY -p $PORT_PRIMARY
cat >> $DATA_STANDBY/postgresql.conf <<EOF
port = $PORT_STANDBY
checkpoint_timeout = 1h
checkpoint_completion_target = 0.9
EOF
cat >> $DATA_STANDBY/recovery.conf <<EOF
standby_mode=on
primary_conninfo = 'port=5432 user=ioltas'
EOF
pg_ctl start -w -D $DATA_STANDBY

# Dummy table for the upcoming tests.
$PSQL -p $PORT_PRIMARY -c 'create table test1 (a int);'
$PSQL -p $PORT_PRIMARY -c 'insert into test1 select generate_series(1, 10000);'
$PSQL -p $PORT_PRIMARY -c 'checkpoint;'
# The following vacuum will set visibility map bits and create
# problematic WAL records.
$PSQL -p $PORT_PRIMARY -c 'vacuum verbose test1;'

# Wait for standby to replay.
sleep 5

# Now force a checkpoint on the standby. This seems unnecessary but for "some"
# reason, the previous checkpoint on the primary does not reflect on the standby
# and without an explicit checkpoint, it may start redo recovery from a much
# older point, which includes even create table and initial page additions.
$PSQL -p $PORT_STANDBY -c 'checkpoint;'

# Now just use a dummy table and run some operations to move minRecoveryPoint
# beyond the previous vacuum.
$PSQL -p $PORT_PRIMARY -c 'create table test2 (a int, b text);'
$PSQL -p $PORT_PRIMARY -c 'insert into test2 select generate_series(1,10000), md5(random()::text)'
$PSQL -p $PORT_PRIMARY -c 'truncate test2;'

# Wait again for replay on standby side.
sleep 5

# Promote standby and wait for it to finish.
pg_ctl promote -w -D $DATA_STANDBY
sleep 5

# Truncate the table on the promoted standby, vacuum and extend it
# again to create new page references.  The first post-recovery checkpoint
# has not happened yet
$PSQL -p $PORT_STANDBY -c 'truncate test1;'
$PSQL -p $PORT_STANDBY -c 'vacuum verbose test1;'
$PSQL -p $PORT_STANDBY -c 'insert into test1 select generate_series(1,1000);'

pg_ctl -w --mode immediate -D $DATA_STANDBY stop
# Crash should happen here
pg_ctl -w -D $DATA_STANDBY start

# Wait for recovery to finish
sleep 5

$PSQL -p $PORT_STANDBY -c 'SELECT count(*) FROM test1'
