#!/bin/sh

#
# This file is released under the terms of the Artistic License.
# Please see the file LICENSE, included in this package, for details.
#
# Copyright The DBT-2 Authors
#

usage()
{
	cat << EOF
$(basename "${0}") is the Database Test 2 (DBT-2) PostgreSQL database builder.

Usage:
  $(basename "${0}") [OPTION] [DBNAME]

Options:
  -f             perform vacuum operation in FULL mode.
  -i DIRECTORY   DIRECTORY with plpgsql stored functions
  -l PORT        PostgreSQL PORT
  --parallelism=COUNT
                 Limit datagen to COUNT processes for data loading
  -p PARAMTERS   PostgreSQL database PARAMETERS
  -r             drop existing database before building a new database
  --rows-per-commit ROWS
                 number of ROWS to load per transaction, default is to load all
                 data in a single transaction
  -s TYPE        user defined functions TYPE to install 'c' or 'plpgsql',
                 default: plpgsql
  -t             use tablespaces
  -u             run as a privileged PostgreSQL user
  -w WAREHOUSES  number of WAREHOUSES to build, default: 1
  -?, --help     show this help, then exit

DBNAME is "${DBNAME}" by default.

Database Test 2 (DBT-2) project page: https://github.com/osdldbt/dbt2
EOF
}

WAREHOUSES=1
GENERATE_DATAFILE=0
LOADARGS=""
PARALLELISM_ARG=""
PRIVILEGED=0
REBUILD_DB=0
ROWS_PER_COMMIT=0
UDF_TYPE="plpgsql"
VACUUM_FULL=0

while [ "${#}" -gt 0 ] ; do
	case "${1}" in
	(-f)
		VACUUM_FULL=1
		;;
	(-i)
		shift
		SHAREDIRARG="-i ${1}"
		;;
	(-l)
		shift
		PORT="${1}"
		;;
	(-p)
		shift
		PARAMETERS="${1}"
		;;
	(--parallelism)
		shift
		PARALLELISM_ARG="-t ${1}"
		;;
	(--parallelism=?*)
		PARALLELISM_ARG="-t ${1#*--parallelism=}"
		;;
	(--rows-per-commit)
		shift
		ROWS_PER_COMMIT="${1}"
		;;
	(--rows-per-commit=?*)
		ROWS_PER_COMMIT="${1#*--rows-per-commit=}"
		;;
	(-r)
		REBUILD_DB=1
		;;
	(-s)
		shift
		UDF_TYPE="${1}"
		;;
	(-t)
		TABLESPACES_FLAG="-t"
		;;
	(-u)
		PRIVILEGED=1
		;;
	(-w)
		shift
		WAREHOUSES=${1}
		;;
	(-w?*)
		WAREHOUSES=${1#*-w}
		;;
	(-\? | --help)
		usage
		exit 0
		;;
	(--* | -*)
		echo "$(basename "${0}"): invalid option -- '${1}'"
		echo "try \"$(basename "${0}") --help\" for more information."
		exit 1
		;;
	(*)
		break
		;;
	esac
	shift
done

shift "$(( OPTIND - 1 ))"
if [ ! "$1" = "" ]; then
	export DBT2DBNAME="$1"
fi

if [ ! "x${PORT}" = "x" ]; then
	PORTARG="-l ${PORT}"
fi

if [ "${ROWS_PER_COMMIT}" -gt 0 ]; then
	LOADARGS="--rows-per-commit=${ROWS_PER_COMMIT}"
fi

if [ $REBUILD_DB -eq 1 ] && [ -d $DBT2PGDATA ]; then
	if [ $PRIVILEGED -eq 1 ]; then
		echo "Restarting the database to reset database parameters..."
		dbt2 pgsql-stop-db
		dbt2 pgsql-start-db -p "${PARAMETERS}" || exit 1
	fi
	dbt2 pgsql-drop-db "${PORTARG}"
fi

if [ $PRIVILEGED -eq 1 ]; then
	dbt2 pgsql-init-db "${PORTARG}" || exit 1
	dbt2 pgsql-start-db -p "$PARAMETERS" || exit 1
fi
dbt2 pgsql-create-db "${PORTARG}" || exit 1
eval "dbt2 pgsql-create-tables ${PORTARG} ${TABLESPACES_FLAG}" || exit 1

SEED=$(dbt2 rand 1 18446744073709551615 0)

# FIXME: Make datagen take argument instead of setting environment variables
# for psql.
export PGPORT="${PORT}"
export PGDATABASE="${DBT2DBNAME}"

eval "dbt2 pgsql-load-db ${PORTARG} -s ${SEED} -w ${WAREHOUSES} ${LOADARGS} \
		${PARALLELISM_ARG}" || exit 1
eval "dbt2 pgsql-create-indexes ${PORTARG} ${TABLESPACES_FLAG}" || exit 1
eval "dbt2 pgsql-load-stored-procs ${SHAREDIRARG} ${PORTARG} -t ${UDF_TYPE}" \
		|| exit 1

if [ ! "x${PORT}" = "x" ]; then
	PORTARG="-p ${PORT}"
fi

SEED=$(dbt2 rand -1 1 15)
psql ${PORTARG} -e -d ${DBT2DBNAME} -c "SELECT setseed(${SEED});" || exit 1

# Set the number of vacuumdb jobs to 1 (no parallelism) and let see
# if the system can support a greater value.
VACUUM_JOBS=1
# Based on server version, enable vaccumdb parallelism if that version
# is greater than or equal to 9.5.
PG_VERSION_NUM=$(psql ${PORTARG} -At -d ${DBT2DBNAME} -c "SHOW server_version_num")
PG_VERSION_NUM=$(( $PG_VERSION_NUM + 0 ))
if [ $PG_VERSION_NUM -ge 95000 ]; then
	# Set default vacuum jobs to 9 because this is the number of tables
	# present in the database. Setting the number of job to a value
	# greater than 9 won't bring any additional benefit.
	VACUUM_JOBS=9
	# If the number of CPUs is less than 9, then we set the vacuum job
	# number to that number of CPUs.
	if [ -f "/proc/stat" ]; then
		CPUS=$(grep cpu /proc/stat | wc -l)
		CPUS=$(( $CPUS - 1 ))
		if [ $CPUS -lt $VACUUM_JOBS ]; then
			VACUUM_JOBS=$CPUS
		fi
	fi
fi

# VACUUM FULL ANALYZE: Build optimizer statistics for newly-created
# tables. The VACUUM FULL is probably unnecessary; we want to scan the
# heap and update the commit-hint bits on each new tuple, but a regular
# VACUUM ought to suffice for that.
# Note: by default, VACUUM FREEZE ANALYZE is performed. The -f option
# can be used to execute VACUUM in FULL mode.

# Perform VACUUM FREEZE ANALYZE by default
VACUUM_OPTS="ANALYZE"
if [ $VACUUM_FULL -eq 1 ]; then
	VACUUM_OPTS="${VACUUM_OPTS}, FULL"
fi

if [ $VACUUM_JOBS -gt 1 ]; then
	VACUUM_OPTS="${VACUUM_OPTS}, PARALLEL ${VACUUM_JOBS}"
fi

psql -X "${PORTARG}" -e -d "${DBT2DBNAME}" <<- EOF
	VACUUM (${VACUUM_OPTS});
EOF

exit 0
