#!/usr/bin/env bash
# Buffer-header contention workload for one installed tree.  Set BUILD to the
# prefix (directory that contains bin/postgres).
set -euo pipefail

BUILD="${BUILD:?set BUILD to the install prefix, e.g. .../builds/half-state/patched}"
CLIENTS="${CLIENTS:-1 8}"
DURATION="${DURATION:-15}"
ROUNDS="${ROUNDS:-3}"
PROBES="${PROBES:-1000}"
PORT="${PORT:-55440}"
DATA="${DATA:-$(dirname "$BUILD")/data}"
SQL="${SQL:-$(dirname "$BUILD")/index.sql}"
LOG="${LOG:-$(dirname "$BUILD")/$(basename "$BUILD").log}"
RESULTS="${RESULTS:-$(dirname "$BUILD")/results-$(basename "$BUILD")-$(date +%Y%m%d-%H%M%S).csv}"

[[ -x $BUILD/bin/postgres ]] || { echo "no $BUILD/bin/postgres" >&2; exit 1; }

start() {
  "$BUILD/bin/pg_ctl" -D "$DATA" -l "$LOG" -w -o \
    "-p $PORT -k /tmp -c listen_addresses= -c shared_buffers=128MB -c fsync=off \
     -c autovacuum=off -c jit=off -c max_parallel_workers_per_gather=0" start >/dev/null
}

stop() {
  "$BUILD/bin/pg_ctl" -D "$DATA" -m fast stop >/dev/null 2>&1 || true
}

trap stop EXIT

export PGOPTIONS="-c enable_seqscan=off -c enable_bitmapscan=off -c enable_memoize=off -c enable_material=off"

cat >"$SQL" <<EOF
SELECT sum(s.v) FROM generate_series(1, $PROBES) g(i),
  LATERAL (SELECT v FROM hot WHERE id = g.i % 10 + 1 OFFSET 0) s;
EOF

if [[ ! -d $DATA ]]; then
  "$BUILD/bin/initdb" -D "$DATA" -A trust >/dev/null
  start
  "$BUILD/bin/createdb" -h /tmp -p "$PORT" bench
  "$BUILD/bin/psql" -qX -h /tmp -p "$PORT" -d bench -v ON_ERROR_STOP=1 -c \
    "CREATE TABLE hot(id int PRIMARY KEY, v int);
     INSERT INTO hot SELECT g, g FROM generate_series(1, 10) g;
     VACUUM ANALYZE hot;"
  stop
fi

echo "build=$(basename "$BUILD") sql=$SQL"
echo "round,clients,tps" >"$RESULTS"
for ((r = 1; r <= ROUNDS; r++)); do
  start
  for c in $CLIENTS; do
    tps=$("$BUILD/bin/pgbench" -n -M prepared -c "$c" -j "$c" -T "$DURATION" \
      -h /tmp -p "$PORT" -f "$SQL" bench 2>&1 |
      sed -n 's/^tps = \([0-9.]*\).*/\1/p')
    echo "$r,$c,$tps" | tee -a "$RESULTS"
  done
  stop
done
