#!/usr/bin/env bash

set -e

ROWS=$1
FILLFACTOR=$2
PAYLOAD=500
RUNS=3
BUILDS=/home/tomas/builds

export PGCTLTIMEOUT=3600

PATH_OLD=$PATH
DATADIR=/mnt/wd/data-prefetch

export MALLOC_TOP_PAD_=$((64*1024*1024))

TS=$(date +%Y%m%d-%H%M%S)

killall -9 postgres || true
sleep 1

rm -Rf $DATADIR

mkdir $TS

PATH=$BUILDS/master/bin:$PATH_OLD

pg_ctl -D $DATADIR init
pg_checksums --disable $DATADIR
pg_ctl -D $DATADIR start
createdb test
pg_ctl -D $DATADIR stop

# use buffered I/O for generating data
cp postgresql.conf $DATADIR/postgresql.conf

pg_ctl -D $DATADIR -l $TS/pg.log start

psql test -c "CREATE EXTENSION pg_buffercache"

psql test -c "CREATE TABLE t (id SERIAL PRIMARY KEY, val INT NOT NULL, payload TEXT NOT NULL) WITH (fillfactor=$FILLFACTOR)"
psql test -c "INSERT INTO t (val, payload) SELECT g, repeat('x', $PAYLOAD) FROM generate_series(1, $ROWS) g"
psql test -c "CREATE INDEX ON t (val)"
psql test -c "VACUUM ANALYZE t"

psql test -c "\d+"
psql test -c "\di+"

psql test -c "SELECT relpages, (relpages * 8) AS size_kB FROM pg_class WHERE relname = 't'"

pg_ctl -D $DATADIR -l $TS/pg.log stop


for io in buffered direct; do

	for iomethod in worker io_uring; do

		for sb in 128MB 8GB; do

			for branch in master patched patched-limit patched-limit-instrument; do

				for prefetch in on off; do

					for limit in 0 1 4 16 64 128; do

						# master can't do prefetch
						if [ "$branch" == "master" ] && [ "$prefetch" == "on" ]; then
							continue
						fi

						if [ "$branch" == "master" ] || [ "$branch" == "patched" ]; then
							if [ "$limit" != "0" ]; then
								continue
							fi
						fi

						if [ "$prefetch" == "off" ] && [ "$limit" != "0" ]; then
							continue
						fi

						PATH=$BUILDS/$branch/bin:$PATH_OLD

						cp postgresql.conf $DATADIR/postgresql.conf

						echo "shared_buffers = $sb" >> $DATADIR/postgresql.conf
						echo 'max_parallel_workers_per_gather = 0' >> $DATADIR/postgresql.conf
						echo 'enable_bitmapscan = off' >> $DATADIR/postgresql.conf
						echo 'enable_seqscan = off' >> $DATADIR/postgresql.conf
						echo 'enable_indexonlyscan = off' >> $DATADIR/postgresql.conf
						echo 'io_workers = 32' >> $DATADIR/postgresql.conf
						echo "io_method = $iomethod" >> $DATADIR/postgresql.conf

						if [ "$io" == "direct" ]; then
							echo "debug_io_direct = 'data'" >> $DATADIR/postgresql.conf
						fi

						if [ "$branch" != "master" ]; then
							echo "enable_indexscan_prefetch = $prefetch" >> $DATADIR/postgresql.conf
						fi

						if [ "$branch" != "master" ] && [ "$branch" != "patched" ]; then
							echo "indexscan_prefetch_distance = $limit" >> $DATADIR/postgresql.conf
						fi

						pg_ctl -D $DATADIR -l $TS/pg.log start

						for r in $(seq 1 $RUNS); do

							sudo ./drop-caches.sh

							psql test -c "select pg_buffercache_evict_all()"

							psql test > tmp.log <<EOF
EXPLAIN SELECT count(l) FROM (SELECT length(payload) AS l FROM t ORDER BY val);
\timing on
SELECT count(l) FROM (SELECT length(payload) AS l FROM t ORDER BY val);
EOF

							echo "===== io: $io  iomethod: $iomethod sb: $sb  branch: $branch  prefetch: $prefetch  limit: $limit  run: $r =====" >> $TS/debug.log
							cat tmp.log >> $TS/debug.log

							t=$(grep 'Time:' tmp.log | awk '{print $2}')

							echo sequential $ROWS $FILLFACTOR $io $iomethod $sb $branch $prefetch $limit $r $t >> $TS/results.csv

						done

						pg_ctl -D $DATADIR -l $TS/pg.log stop

					done

				done

			done

		done

	done

done
