#!/usr/bin/bash

set -e
set -x

MACHINE=$1
PATH_OLD=$PATH
BUILDS=/home/tomas/builds
DATADIR=/mnt/wd/data-parallel-vacuum

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

mkdir $LOGDIR

rm -f workers.list
for w in 0 1 2 3 4 6 8; do
	echo $w >> workers.list
done

killall -9 postgres || true
rm -Rf $DATADIR

PATH=$BUILDS/master/bin:$PATH_OLD

pg_ctl -D $DATADIR init

echo "shared_buffers = '4GB'" >> $DATADIR/postgresql.conf
echo "min_wal_size = '32GB'"  >> $DATADIR/postgresql.conf
echo "max_wal_size = '128GB'" >> $DATADIR/postgresql.conf
echo "maintenance_work_mem = '512MB'" >> $DATADIR/postgresql.conf
echo "work_mem = '128MB'" >> $DATADIR/postgresql.conf
echo "max_worker_processes = 32" >> $DATADIR/postgresql.conf
echo "max_parallel_workers_per_gather = 16" >> $DATADIR/postgresql.conf
echo "max_parallel_maintenance_workers = 16" >> $DATADIR/postgresql.conf
echo "max_parallel_workers = 32" >> $DATADIR/postgresql.conf
echo "log_statement = 'all'" >> $DATADIR/postgresql.conf

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

for size in 100000000; do
#for size in 10000000 100000000 1000000000; do

	echo `date` "== size: $size"

	for logged in logged unlogged; do

		echo `date` "==== logged: $logged"

		dropdb --if-exists test-template
		createdb test-template

		log=""
		if [ "$logged" == "unlogged" ]; then
			log="unlogged"
		fi

		sed "s/ROWS/$size/" create.sql | sed "s/LOG/$log/" | psql test-template

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

		# what fraction of table to delete, each page has ~200 rows
		for m in 100 500 1000 5000; do

			echo `date` "====== m: $m"

			for run in 1 2 3; do

				echo `date` "======== run: $run"

				for indexes in 0 1 2 3 4 5; do

					echo `date` "========== indexes: $indexes"

					for build in master patched-0001 patched-0002 patched-0003 patched-0004 patched-0005; do

						echo `date` "============ build: $build"

						# create copy of the database
						dropdb --if-exists test
						createdb test -T test-template -S file_copy

						r=0

						for idx in $(seq $((indexes+1)) 5); do
							psql test -c "drop index idx_${idx}"
						done

						for workers in $(shuf workers.list); do

							echo `date` "============== workers: $workers"

							# master does not support parallel vacuum
							#if [ "$build" == "master" ] && [ "$workers" != "0" ]; then
							#	continue
							#fi

							ts=$(date +%s)
							echo `date` "=========== ts: $ts run: $r size: $size build: $build workers: $workers indexes: $indexes logged: $logged m: $m r: $r =========="

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

							# stop/start, to use correct build
							pg_ctl -D $DATADIR -l $LOGDIR/pg.log stop
							pg_ctl -D $DATADIR -l $LOGDIR/pg.log start

							# clean page cache
							echo `date` "drop page cache"
							sudo ./drop-caches.sh

							ps ax | grep postgres

							datoid=$(psql -t -A test -c "select oid from pg_database where datname = current_database()")
							relfilenodes=$(psql -t -A test -c "select pg_relation_filenode(oid) from pg_class where relname like 'idx_%' order by relname")

							for f in $relfilenodes; do
								echo `date` "page cache warmup index relfilenode $datoid/$f"
								cat $DATADIR/base/$datoid/$f* > /dev/null
							done

							relfilenode=$(psql -t -A test -c "select pg_relation_filenode(oid) from pg_class where relname like 'test_vacuum'")

							echo `date` "page cache warmup table relfilenode $datoid/$relfilenode"
							cat $DATADIR/base/$datoid/$relfilenode* > /dev/null

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

							psql test -c "\d+ test_vacuum"

							psql test -c "vacuum analyze test_vacuum"
							psql test -c "checkpoint"

							sync

							psql test > $LOGDIR/$ts.delete.log 2>&1 <<EOF
-- deletes two rows on each page
delete from test_vacuum where mod(a,$m) = $r;
checkpoint;
EOF

							cat $LOGDIR/$ts.delete.log

							s=$(psql -t -A test -c "select extract(epoch from now())")
							start_time=$(psql -t -A test -c "select now()")

							echo `date` "vacuum (parallel $workers, verbose) test_vacuum";

							psql test > $LOGDIR/$ts.vacuum.log 2>&1 <<EOF
vacuum (parallel $workers, verbose) test_vacuum;
EOF
							d=$(psql -t -A test -c "select extract(epoch from now()) - $s")
							e=$(psql -t -A test -c "select extract(epoch from now())")
							end_time=$(psql -t -A test -c "select now()")

							is=$(grep 'index scans:' $LOGDIR/$ts.vacuum.log | awk '{print $7}')

							pages_removed=$(grep '^pages:' $LOGDIR/$ts.vacuum.log | awk '{print $2}')
							pages_remain=$(grep '^pages:' $LOGDIR/$ts.vacuum.log | awk '{print $4}')
							pages_scanned=$(grep '^pages:' $LOGDIR/$ts.vacuum.log | awk '{print $6}')
							pages_frozen=$(grep '^frozen:' $LOGDIR/$ts.vacuum.log | awk '{print $2}')

							tuples_removed=$(grep '^tuples:' $LOGDIR/$ts.vacuum.log | awk '{print $2}')
							tuples_remain=$(grep '^tuples:' $LOGDIR/$ts.vacuum.log | awk '{print $4}')

							avg_read=$(grep '^avg read' $LOGDIR/$ts.vacuum.log | awk '{print $4}')
							avg_write=$(grep '^avg read' $LOGDIR/$ts.vacuum.log | awk '{print $9}')

							cat $LOGDIR/$ts.vacuum.log

							echo `date` "START TIME: $start_time ($s)"
							echo `date` "END TIME: $end_time ($e)"
							echo `date` "DELTA: $d"

							echo $MACHINE $ts $run $size $m $r $build $workers $indexes $logged $d $is $pages_removed $pages_remain $pages_scanned $pages_frozen $tuples_removed $tuples_remain $avg_read $avg_write >> $LOGDIR/results.csv

							r=$((r+1))

						done

					done

				done

			done

		done

	done

done

pg_ctl -D $DATADIR stop
