#!/bin/bash

me=$(basename $0)
mydir=$(dirname $0)

if [ $# -lt 1 ] ; then
cat <<EOF

Usage:

  $me DATADIR PORT NTABLES

Creates a postgres instance in DATADIR on port PORT with NTABLES small tables.
Note: DATADIR be on tmpfs or this will be very very slow. Once done make a tar.gz
of the DATADIR to use for later testing.

To test autovacuum, just untar the intance, set the number of workers in
postgresql.conf and start the instance, autovacuum will start analyizing all
the new tables shortly.

Example:

  $me /dev/shm/avac_40k 5440 40000
  rm /dev/shm/avac_40k/pg_logs/*
  tar czf avac_40k.tar.gz -C /dev/shm avac_40k
  rm -rf /dev/shm/avac_40k
  tar xf avac_40k.tar.gz
  # edit avac_40k/postgresl.conf to set logfile name and number of workers
  pg_ctl -D avac_40k start
  # watch the fun start

EOF
    exit 1
fi

export PGDATA=${1:?Missing data dir, should be on tmpfs or other very fast storage.}
export PGPORT=${2:?Missing port.}
ntables=${3:?Missing number of tables. Try 400000.}

export PGDATABASE=avac
export PGUSER=avac
export PGAPPNAME=$me

nrows=150
npads=1
padlen=1
scale=1
batchsize=10

inst=$(basename $PGDATA)
dbdir=$(dirname $PGDATA)

notice() {
    psql -P footer -q <<EOF
select '$*' as "Notice";
EOF
}

setup() {
    set -e
    initdb -U postgres --no-locale $PGDATA
    set +e
    cat <<CFG0 >$PGDATA/postgresql.conf
include 'postgresql_test.conf'

# instance specific settings here
port = $PGPORT
log_filename = 'default.%Y%m%d_%H%M%S.log'

max_locks_per_transaction = 10240  # required for lots of tables
autovacuum_max_workers = 4

CFG0

    cat <<CFG1 >$PGDATA/postgresql_test.conf
# postgresql_test.conf

# RESOURCE USAGE (except WAL)

shared_buffers = 1GB
work_mem = 128MB
maintenance_work_mem = 512MB
shared_preload_libraries = '\$libdir/pg_stat_statements'

# WRITE AHEAD LOG
synchronous_commit = off
wal_compression = on			# new in 9.5, remove for earlier

# QUERY TUNING
effective_cache_size = 8GB		# shared 16GB host

# ERROR REPORTING AND LOGGING
log_destination = 'csvlog'
logging_collector = on			# Enable capturing of stderr and csvlog
log_filename = 'postgresql-%Y%m%d_%H%M%S.log'
log_rotation_size = 100MB		# Automatic rotation of logfiles
log_min_duration_statement = 0
log_checkpoints = on
log_connections = on
log_disconnections = on
log_duration = off
log_hostname = on
log_line_prefix = '%m  %p  %q%c  %l  %d  %u  %a  '
log_lock_waits = on			# log lock waits >= deadlock_timeout
log_statement = none			# none, ddl, mod, all
log_temp_files = 64MB			# log temporary files equal or larger

# RUNTIME STATISTICS
track_functions = pl

# AUTOVACUUM PARAMETERS
autovacuum_naptime = '30s'
log_autovacuum_min_duration = 0		# -1 disables, 0 logs all actions and
autovacuum_analyze_scale_factor = 0.05
autovacuum_vacuum_cost_delay = -1
autovacuum_vacuum_cost_limit = -1

#autovacuum_freeze_max_age = 1000000000
#autovacuum_multixact_freeze_max_age = 1000000000
#vacuum_freeze_table_age = 1000000000
#vacuum_freeze_min_age = 200000000
#vacuum_multixact_freeze_table_age = 1000000000
#vacuum_multixact_freeze_min_age = 200000000

default_text_search_config = 'pg_catalog.english'

# CUSTOMIZED OPTIONS
pg_stat_statements.max = 1000
pg_stat_statements.track = 'top'
pg_stat_statements.save = off
CFG1

cp $PGDATA/postgresql.auto.conf $PGDATA/postgresql.auto.conf.sav
cat <<CFG2 >> $PGDATA/postgresql.auto.conf

# configure for quick loading
log_filename = 'datagen.%Y%m%d_%H%M%S.log'
fsync = 0
autovacuum = 0
full_page_writes = 0
max_wal_size = '256MB'
min_wal_size = '32MB'
CFG2
}

setup

# start instance
pg_ctl -D $PGDATA -wc start

psql -q -U postgres -d postgres <<SQL
create role $PGUSER with inherit createdb login;
create database $PGDATABASE with owner $PGUSER;
SQL

notice "AVAC SETUP start: $ntables tables, $nrows rows"
time $mydir/datagen.py $ntables $nrows $npads $padlen $scale $batchsize | psql -P footer -q
notice "AVAC SETUP done: $ntables tables, $nrows rows"

echo "Shutting down ..."
pg_ctl -D $PGDATA -m fast stop
mv $PGDATA/postgresql.auto.conf.sav $PGDATA/postgresql.auto.conf

echo Sizes:
du -hs $PGDATA/base $PGDATA/pg_stat

cat <<EOF

Setup complete.  Next steps:
- clean up the pg_log dirctory.
- make a tarball of the DATADIR for later use.
Example:

  rm $PGDATA/pg_log/*
  tar czf $inst.tar.gz -C $dbdir $inst
  rm -rf $PGDATA
EOF
