--- /dev/null
+#!/usr/bin/env bash
+#
+# Copyright (c) 2013-2020 PgPool Global Development Group
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose and without fee is hereby
+# granted, provided that the above copyright notice appear in all
+# copies and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of the
+# author not be used in advertising or publicity pertaining to
+# distribution of the software without specific, written prior
+# permission. The author makes no representations about the
+# suitability of this software for any purpose. It is provided "as
+# is" without express or implied warranty.
+#-------------------------------------------------------------------
+# Set up pgpool-II and PostgreSQL temporary installation in current
+# directory for *testing* purpose.
+# Do not use this tool for production environment!
+#
+# usage: pgpool_setup [-m r|s|n|l][-n num_clusters][-p base_port][-pg pg_base_port][--no-stop][-d][-s][-r]
+# -m s: create an installation as streaming replication mode.
+# (the default)
+# -m r: create an installation as native replication mode.
+# -m n: create an installation as raw mode.
+# -m l: create an installation as logical replication mode.
+# -m y: create an installation as slony mode.
+# -m i: create an installation as snapshot isolation mode.
+# -n num_clusters: create num_clusters PostgreSQL database cluster nodes
+# -p base_port: specify base port. pgpool port is base_port.
+# pcp port is base_port + 1. The first PostgreSQL node's port is
+# base_port + 2, second PostgreSQL node's port is base_port + 3
+# and so on.
+# if -pg option is specified, the first PostgreSQL node's port is
+# assigned to pg_pase_port, the second PostgreSQL node's port is
+# pg_base_port + 1 and so on.
+# --no-stop: do not stop pgpool and PostgreSQL after the work
+# -d: start pgpool with debug mode
+# -s: use replication slot, rather than wal archive.
+# -r: use pg_rewind for base backup if possible.
+#
+# The user run this script will become the PostgreSQL super user as
+# well. Current directory must be empty. Assume that appropreate
+# pgpool and PostgreSQL binaries are in the command search path.
+# The user must have passwordless access to localhost over SSH.
+#
+# Rayout after executing this script:
+# data[0-]: PostgreSQL database clusters
+# log: pgpool.log and pgpool_status resides here
+# run: pgpool-II pid file resides here(generated by pgpool-II)
+# etc/pgpool.conf: pgpool-II configuration file
+# etc/pool_passwd: generated by pgpool-II
+# ./startall: a script to start pgpool-II and all PostgreSQL servers
+# ./shutdownall: a script to shutdown pgpool-II and all PostgreSQL servers
+#
+# test database "test" is created.
+# pcp username and password is set to the person who executed this script.
+#
+#-------------------------------------------
+# Configuration section
+#-------------------------------------------
+# Starting port number to be used. Each PostgreSQL is assigned
+# $BASEPORT + 2, $BASEPORT + 3 and so on.
+# pgpool port and pcp_port will be assigned to $BASEPORT and $BASEPORT +1 .
+BASEPORT=${BASEBOPRT:-"11000"}
+ORIGBASEPORT=$BASEPORT
+# PostgreSQL startig port number.
+PGBASEPORT=`expr $BASEPORT + 2`
+# Default number of PostgreSQL database clusters
+NUMCLUSTERS=${NUMCLUSTERS:-"2"}
+# Where to look for pgpool.conf.sample*
+PGPOOL_INSTALL_DIR=${PGPOOL_INSTALL_DIR:-"@@PGPOOL_INSTALL_DIR@@"}
+PGPOOLDIR=${PGPOOLDIR:-"@@PGPOOL_CONFIG_DIR@@"}
+# PostgreSQL commands(initdb, pg_ctl, psql) install dir
+PGBIN=${PGBIN:-"@@PGSQL_BIN_DIR@@"}
+# LD_LIBRARY_PATH
+LPATH=${PGLIB:-"@@PGSQL_LIB_DIR@@"}
+# unix socket directory
+PGSOCKET_DIR=${PGSOCKET_DIR:-"/tmp"}
+# initdb args
+INITDBARG="--no-locale -E UTF_8"
+# Use replication slot
+USE_REPLICATION_SLOT=${USE_REPLICATION_SLOT:-"false"}
+# Use pg_rewind
+USE_PG_REWIND=${USE_PG_REWIND:-"false"}
+# Check TIME_WAIT in shutdownall script
+CHECK_TIME_WAIT=${CHECK_TIME_WAIT:-"false"}
+#-------------------------------------------
+# End of configuration section
+#-------------------------------------------
+#
+# user name
+WHOAMI=`whoami`
+
+# our root directory
+BASEDIR=`pwd`
+
+# PostgreSQL bin directory
+INITDB=$PGBIN/initdb
+PG_CTL=$PGBIN/pg_ctl
+PSQL=$PGBIN/psql
+
+# get PostgreSQL major version
+vstr=`$INITDB -V|awk '{print $3}'|sed 's/\./ /g'`
+#vstr="12beta1"
+#vstr="9.1.24"
+#vstr="11.1"
+
+# check if alpha or beta
+echo $vstr|egrep "[a-z]" > /dev/null
+if [ $? = 0 ];then
+ vstr=`echo $vstr|sed 's/\([0-9]*\).*/\1/'`
+ major1=`echo $vstr|awk '{print $1}'`
+ major2=`echo $vstr|awk '{print $2}'`
+ if [ -z $major2 ];then
+ major2=0
+ fi
+else
+ vstr=`echo $vstr|sed 's/\./ /g'`
+ major1=`echo $vstr|awk '{print $1}'`
+ major2=`echo $vstr|awk '{print $2}'`
+fi
+major1=`expr $major1 \* 10`
+PGVERSION=`expr $major1 + $major2`
+echo PostgreSQL major version: $PGVERSION
+
+if [ $PGVERSION -gt 91 ];then
+ INITDBARG="$INITDBARG --data-checksums"
+fi
+
+# pgpool-II configuration file localtion.
+CONF=$BASEDIR/etc/pgpool.conf
+# failover script
+FAILOVER_SCRIPT=$BASEDIR/etc/failover.sh
+# follow master script
+FOLLOW_MASTER_SCRIPT=$BASEDIR/etc/follow_master.sh
+# pgpool_remote_start
+PGPOOL_REMOTE_START_SCRIPT=pgpool_remote_start
+# Start script name. This will be generated in this script.
+STARTALL=$BASEDIR/startall
+# Shutdown script name. This will be generated in this script.
+SHUTDOWNALL=$BASEDIR/shutdownall
+PCP_PASS_FILE=$BASEDIR/pcppass
+# pgpool reload script name. This will be generated in this script.
+PGPOOL_RELOAD=$BASEDIR/pgpool_reload
+
+export PGHOST=$PGSOCKET_DIR
+
+#-------------------------------------------
+# create failover script
+#-------------------------------------------
+function create_failover_script()
+{
+cat >> $FAILOVER_SCRIPT <<'EOF'
+#! /bin/sh
+# Execute command by failover.
+# special values: %d = node id
+# %h = host name
+# %p = port number
+# %D = database cluster path
+# %m = new master node id
+# %M = old master node id
+# %H = new master node host name
+# %P = old primary node id
+# %R = new master database cluster path
+# %r = new master port number
+# %% = '%' character
+failed_node_id=$1
+failed_host_name=$2
+failed_port=$3
+failed_db_cluster=$4
+new_master_id=$5
+old_master_id=$6
+new_master_host_name=$7
+old_primary_node_id=$8
+new_master_port_number=$9
+new_master_db_cluster=${10}
+mydir=__MYDIR__
+log=$mydir/log/failover.log
+pg_ctl=__PGBIN__/pg_ctl
+cluster0=$mydir/data0
+cluster1=$mydir/data1
+
+date >> $log
+echo "failed_node_id $failed_node_id failed_host_name $failed_host_name failed_port $failed_port failed_db_cluster $failed_db_cluster new_master_id $new_master_id old_master_id $old_master_id new_master_host_name $new_master_host_name old_primary_node_id $old_primary_node_id new_master_port_number $new_master_port_number new_master_db_cluster $new_master_db_cluster" >> $log
+
+if [ a"$failed_node_id" = a"$old_primary_node_id" ];then # master failed
+! new_primary_db_cluster=${mydir}/data"$new_master_id"
+ echo $pg_ctl -D $new_primary_db_cluster promote >>$log # let standby take over
+ $pg_ctl -D $new_primary_db_cluster promote >>$log # let standby take over
+ sleep 2
+fi
+EOF
+
+#-------------------------------------------
+# replace some variables in the script
+#-------------------------------------------
+/bin/sed -i \
+ -e "/__MYDIR__/s@__MYDIR__@$BASEDIR@" \
+ -e "/__PGBIN__/s@__PGBIN__@$PGBIN@" \
+ $FAILOVER_SCRIPT
+
+chmod 755 $FAILOVER_SCRIPT
+}
+
+#-------------------------------------------
+# create follow master script
+#-------------------------------------------
+function create_follow_master_script()
+{
+cat >> $FOLLOW_MASTER_SCRIPT <<'EOF'
+#! /bin/sh
+# Execute command by failover.
+# special values: %d = node id
+# %h = host name
+# %p = port number
+# %D = database cluster path
+# %m = new master node id
+# %M = old master node id
+# %H = new master node host name
+# %P = old primary node id
+# %R = new master database cluster path
+# %r = new master port number
+# %% = '%' character
+failed_node_id=$1
+failed_host_name=$2
+failed_port=$3
+failed_db_cluster=$4
+new_master_id=$5
+old_master_id=$6
+new_master_host_name=$7
+old_primary_node_id=$8
+new_master_port_number=$9
+new_master_db_cluster=${10}
+mydir=__MYDIR__
+log=$mydir/log/failover.log
+pg_ctl=__PGBIN__/pg_ctl
+cluster0=$mydir/data0
+cluster1=$mydir/data1
+cluster2=$mydir/data2
+PCP_PORT=__PCPPORT__
+export PCPPASSFILE=__PCPPASSFILE__
+
+date >> $log
+echo "failed_node_id $failed_node_id failed_host_name $failed_host_name failed_port $failed_port failed_db_cluster $failed_db_cluster new_master_id $new_master_id old_master_id $old_master_id new_master_host_name $new_master_host_name old_primary_node_id $old_primary_node_id new_master_port_number $new_master_port_number new_master_db_cluster $new_master_db_cluster" >> $log
+
+# Stop standby node if it's running
+$pg_ctl -D $failed_db_cluster status >/dev/null 2>&1
+if [ $? = 0 ]
+then
+ $pg_ctl -w -m f -D $failed_db_cluster stop >> $log 2>&1
+ sleep 10
+ # recovery the node
+ pcp_recovery_node -w -h localhost -p $PCP_PORT -n $failed_node_id >> $log 2>&1
+else
+ echo "$failed_db_cluster is not running. skipping follow master command." >> $log
+fi
+EOF
+
+#-------------------------------------------
+# replace some variables in the script
+#-------------------------------------------
+
+/bin/sed -i \
+ -e "/__MYDIR__/s@__MYDIR__@$BASEDIR@" \
+ -e "/__PGBIN__/s@__PGBIN__@$PGBIN@" \
+ -e "/__PCPPASSFILE__/s@__PCPPASSFILE__@$PCP_PASS_FILE@" \
+ -e "/__PCPPORT__/s/__PCPPORT__/$PCP_PORT/" \
+ $FOLLOW_MASTER_SCRIPT
+
+chmod 755 $FOLLOW_MASTER_SCRIPT
+}
+
+#-------------------------------------------
+# create pgpool_remote_start script
+# argument: PostgreSQL database cluster directory
+#-------------------------------------------
+function create_pgpool_remote_start_script()
+{
+cat >> $1/$PGPOOL_REMOTE_START_SCRIPT <<'EOF'
+#! /bin/sh
+#
+# start postmaster on the recoveried node
+#
+if [ $# -ne 2 ]
+then
+ echo "pgpool_remote_start remote_host remote_datadir"
+ exit 1
+fi
+
+DEST=$1
+DESTDIR=$2
+PGCTL=__PGBIN__/pg_ctl
+
+ssh -T $DEST $PGCTL -w -D $DESTDIR start 2>/dev/null 1>/dev/null < /dev/null &
+EOF
+
+#-------------------------------------------
+# replace some variables in the script
+#-------------------------------------------
+/bin/sed -i \
+ -e "/__PGBIN__/s@__PGBIN__@$PGBIN@" \
+ $1/$PGPOOL_REMOTE_START_SCRIPT
+
+chmod 755 $1/$PGPOOL_REMOTE_START_SCRIPT
+}
+
+#-------------------------------------------
+# set postgresql.conf
+# argument: PostgreSQL database cluster directory
+#-------------------------------------------
+function set_postgresql_conf
+{
+ PGCONF=$1/postgresql.conf
+ PGHBACONF=$1/pg_hba.conf
+
+ echo "listen_addresses = '*'" >> $PGCONF
+ echo "port = $PORT" >> $PGCONF
+ echo "logging_collector = on" >> $PGCONF
+ echo "log_filename = '%A.log'" >> $PGCONF
+ echo "log_line_prefix = '%p %t '" >> $PGCONF
+ echo "log_truncate_on_rotation = on" >> $PGCONF
+ echo "log_statement = 'all'" >> $PGCONF
+ echo "max_prepared_transactions = 10" >> $PGCONF
+ echo "unix_socket_directories = '$PGSOCKET_DIR'" >> $PGCONF
+
+ if [ $PGVERSION -ge 120 ];then
+ echo "include_if_exists = 'myrecovery.conf'" >> $PGCONF
+ fi
+
+ if [ $MODE = "s" ];then
+ echo "hot_standby = on" >> $PGCONF
+ echo "wal_level = hot_standby" >> $PGCONF
+ echo "max_wal_senders = $NUMCLUSTERS" >> $PGCONF
+
+ if [ $USE_REPLICATION_SLOT = "false" ];then
+ echo "archive_mode = on" >> $PGCONF
+ echo "archive_command = 'cp %p $BASEDIR/archivedir/%f </dev/null'" >> $PGCONF
+ else
+ num_slots=`expr $NUMCLUSTERS + 10`
+ echo "max_replication_slots = $num_slots" >> $PGCONF
+ fi
+
+ elif [ $MODE = 'r' -o $MODE = 'l' -o $MODE = 'y' -o $MODE = 'i' ];then
+ echo "wal_level = archive" >> $PGCONF
+ echo "archive_mode = on" >> $PGCONF
+ echo "archive_command = 'cp %p $BASEDIR/archivedir/%f </dev/null'" >> $PGCONF
+ if [ $MODE = 'l' ];then
+ echo "wal_level = logical" >> $PGCONF
+ fi
+ fi
+
+ # Snapshot isolation mode requires REPEATABLE READ transaction isolation mode.
+ if [ $MODE = 'i' ];then
+ echo "default_transaction_isolation = 'repeatable read'" >> $PGCONF
+ fi
+
+ sed -i '/host.*all.*all.*trust$/s/^/#/g' $PGHBACONF
+ sed -i '/local.*all.*all.*trust$/s/^/#/g' $PGHBACONF
+
+ if [ $PGVERSION -ge 100 ];
+ then
+ echo "host all scram_user 0/0 scram-sha-256" >> $PGHBACONF
+ echo "host all md5_user 0/0 md5" >> $PGHBACONF
+ fi
+
+ echo "host all all 0/0 trust" >> $PGHBACONF
+
+ if [ $PGVERSION -ge 100 ];
+ then
+ echo "local all scram_user scram-sha-256" >> $PGHBACONF
+ echo "local all md5_user md5" >> $PGHBACONF
+ fi
+
+ echo "local all all trust" >> $PGHBACONF
+
+ ed $1/pg_hba.conf <<EOF
+/^#local *replication/s/^#//p
+/^#host *replication/s/^#//p
+/^#host *replication/s/^#//p
+w
+q
+EOF
+}
+
+#-------------------------------------------
+# create basebackup.sh for streaming replication mode
+# argument1: PostgreSQL database cluster
+# argument2: cluster node number
+#-------------------------------------------
+function create_basebackup_stream {
+SCRIPT=basebackup.sh
+cat >> $1/$SCRIPT <<'EOF'
+#! /bin/sh
+psql=__PGBIN__/psql
+pg_rewind=__PGBIN__/pg_rewind
+DATADIR_BASE=__DATADIR_BASE__
+PGSUPERUSER=__PGSUPERUSER__
+
+master_db_cluster=$1
+recovery_node_host_name=$2
+DEST_CLUSTER=$3
+PORT=$4
+recovery_node=$5
+
+pg_rewind_failed="true"
+
+log=$DATADIR_BASE/log/recovery.log
+echo >> $log
+date >> $log
+EOF
+
+echo "export PGHOST=$PGSOCKET_DIR" >> $1/$SCRIPT
+
+pg_rewind_failed="true"
+
+if [ $USE_PG_REWIND = "true" ];then
+cat >> $1/$SCRIPT <<'EOF'
+
+# First try pg_rewind
+
+# Make backup copy of postgresql.conf since pg_rewind blindly copies
+# $master_db_cluster/postgresql.conf.
+cp $DEST_CLUSTER/postgresql.conf /tmp/
+echo "pg_rewind starts" >> $log
+$pg_rewind -P -D $DEST_CLUSTER --source-server="port=$PORT user=$PGSUPERUSER dbname=postgres" >> $log 2>&1
+if [ $? != 0 ];then
+ # pg_rewind failed. Fallback to rsync.
+ echo "pg_rewind failed. Fall back to rsync" >> $log
+ pg_rewind_failed="true"
+else
+ pg_rewind_failed="false"
+fi
+EOF
+fi
+
+cat >> $1/$SCRIPT <<'EOF'
+if [ $pg_rewind_failed = "true" ];then
+
+$psql -p $PORT -c "SELECT pg_start_backup('Streaming Replication', true)" postgres
+
+echo "source: $master_db_cluster dest: $DEST_CLUSTER" >> $log
+
+rsync -C -a -c --delete --exclude postgresql.conf --exclude postmaster.pid \
+--exclude postmaster.opts --exclude pg_log \
+--exclude recovery.conf --exclude recovery.done \
+--exclude pg_xlog pg_wal \
+$master_db_cluster/ $DEST_CLUSTER/
+
+rm -fr $DEST_CLUSTER/pg_xlog
+mkdir $DEST_CLUSTER/pg_xlog
+chmod 700 $DEST_CLUSTER/pg_xlog
+
+rm -fr $DEST_CLUSTER/pg_wal
+mkdir $DEST_CLUSTER/pg_wal
+chmod 700 $DEST_CLUSTER/pg_wal
+
+rm $DEST_CLUSTER/recovery.done
+fi
+EOF
+
+if [ $USE_REPLICATION_SLOT = "true" ];then
+ cat >> $1/$SCRIPT <<'EOF'
+$psql -p $PORT -c "SELECT * FROM pg_create_physical_replication_slot('pgpool_setup_slot$recovery_node')" postgres
+EOF
+fi
+
+if [ $PGVERSION -ge 120 ];then
+ cat >> $1/$SCRIPT <<'EOF'
+cat > $DEST_CLUSTER/myrecovery.conf <<REOF
+primary_conninfo = 'host=localhost port=$PORT user=$PGSUPERUSER application_name=''server$recovery_node'''
+recovery_target_timeline='latest'
+EOF
+
+else
+
+ cat >> $1/$SCRIPT <<'EOF'
+cat > $DEST_CLUSTER/recovery.conf <<REOF
+standby_mode = 'on'
+primary_conninfo = 'host=localhost port=$PORT user=$PGSUPERUSER application_name=''server$recovery_node'''
+recovery_target_timeline='latest'
+EOF
+fi
+
+if [ $USE_REPLICATION_SLOT = "false" ];then
+ cat >> $1/$SCRIPT <<'EOF'
+restore_command = 'cp $DATADIR_BASE/archivedir/%f "%p" 2> /dev/null'
+REOF
+EOF
+else
+ cat >> $1/$SCRIPT << 'EOF'
+primary_slot_name = 'pgpool_setup_slot$recovery_node'
+REOF
+EOF
+fi
+
+cat >> $1/$SCRIPT <<'EOF'
+if [ $pg_rewind_failed = "true" ];then
+$psql -p $PORT -c "SELECT pg_stop_backup()" postgres
+fi
+
+if [ $pg_rewind_failed = "false" ];then
+ cp /tmp/postgresql.conf $DEST_CLUSTER/
+fi
+touch $DEST_CLUSTER/standby.signal
+EOF
+
+#-------------------------------------------
+# replace some variables in the script
+#-------------------------------------------
+/bin/sed -i \
+ -e "/__PGBIN__/s@__PGBIN__@$PGBIN@" \
+ -e "/__DATADIR_BASE__/s@__DATADIR_BASE__@$BASEDIR@" \
+ -e "/__PGSUPERUSER__/s/__PGSUPERUSER__/$WHOAMI/" \
+$1/$SCRIPT
+
+chmod 755 $1/$SCRIPT
+}
+
+#-------------------------------------------
+# create basebackup.sh for native replication mode
+# argument: PostgreSQL database cluster directory
+#-------------------------------------------
+function create_basebackup_replication {
+SCRIPT=basebackup.sh
+cat >> $1/$SCRIPT <<'EOF'
+#! /bin/sh
+psql=__PGBIN__/psql
+DATADIR_BASE=__DATADIR_BASE__
+PGSUPERUSER=__PGSUPERUSER__
+EOF
+
+echo "export PGHOST=$PGSOCKET_DIR" >> $1/$SCRIPT
+
+cat >> $1/$SCRIPT <<'EOF'
+master_db_cluster=$1
+recovery_node_host_name=$2
+DEST_CLUSTER=$3
+PORT=$4
+
+log=$DATADIR_BASE/log/recovery.log
+
+$psql -p $PORT -c "SELECT pg_start_backup('Native Replication', true)" postgres
+
+echo "source: $master_db_cluster dest: $DEST_CLUSTER" > $log
+EOF
+
+if [ $PGVERSION -ge 120 ];then
+ cat >> $1/$SCRIPT <<'EOF'
+cat > $master_db_cluster/myrecovery.conf <<REOF
+restore_command = 'cp __ARCHDIR__/%f %p'
+REOF
+EOF
+
+else
+
+ cat >> $1/$SCRIPT <<'EOF'
+cat > $master_db_cluster/recovery.conf <<REOF
+restore_command = 'cp __ARCHDIR__/%f %p'
+REOF
+EOF
+fi
+
+cat >> $1/$SCRIPT <<'EOF'
+rsync -C -a -c --delete --exclude postgresql.conf --exclude postmaster.pid \
+--exclude postmaster.opts --exclude pg_log \
+--exclude recovery.done \
+--exclude pg_xlog pg_wal \
+$master_db_cluster/ $DEST_CLUSTER/
+
+rm -fr $DEST_CLUSTER/pg_xlog
+mkdir $DEST_CLUSTER/pg_xlog
+chmod 700 $DEST_CLUSTER/pg_xlog
+
+rm -fr $DEST_CLUSTER/pg_wal
+mkdir $DEST_CLUSTER/pg_wal
+chmod 700 $DEST_CLUSTER/pg_wal
+EOF
+
+cat >> $1/$SCRIPT <<'EOF'
+$psql -p $PORT -c "SELECT pg_stop_backup()" postgres
+EOF
+
+if [ $PGVERSION -ge 120 ];then
+ cat >> $1/$SCRIPT <<'EOF'
+touch $DEST_CLUSTER/recovery.signal
+EOF
+fi
+
+#-------------------------------------------
+# replace some variables in the script
+#-------------------------------------------
+/bin/sed -i \
+ -e "/__PGBIN__/s@__PGBIN__@$PGBIN@" \
+ -e "/__DATADIR_BASE__/s@__DATADIR_BASE__@$BASEDIR@" \
+ -e "/__PGSUPERUSER__/s/__PGSUPERUSER__/$WHOAMI/" \
+ -e "/__ARCHDIR__/s@__ARCHDIR__@$BASEDIR/archivedir@" \
+ $1/$SCRIPT
+
+chmod 755 $1/$SCRIPT
+}
+
+#-------------------------------------------
+# create pgpool_recovery_pitr (2nd stage script)for native replication mode
+# argument: PostgreSQL database cluster directory
+#-------------------------------------------
+function create_pgpool_recovery_pitr {
+SCRIPT=pgpool_recovery_pitr
+cat >> $1/$SCRIPT <<'EOF'
+#! /bin/sh
+psql=__PGBIN__/psql
+DATADIR_BASE=__DATADIR_BASE__
+PGSUPERUSER=__PGSUPERUSER__
+
+master_db_cluster=$1
+recovery_node_host_name=$2
+DEST_CLUSTER=$3
+PORT=$4
+
+log=$DATADIR_BASE/log/recovery.log
+EOF
+
+echo "export PGHOST=$PGSOCKET_DIR" >> $1/$SCRIPT
+
+cat >> $1/$SCRIPT <<'EOF'
+# Force to flush current value of sequences to xlog
+$psql -q -p $PORT -t -c 'SELECT datname FROM pg_database WHERE NOT datistemplate AND datallowconn' template1|
+while read i
+do
+ if [ "$i" != "" ];then
+ $psql -p $PORT -c "SELECT setval(oid, nextval(oid)) FROM pg_class WHERE relkind = 'S'" $i
+ fi
+done
+
+$psql -p $PORT -c "SELECT pgpool_switch_xlog('__ARCHDIR__')" template1
+EOF
+#-------------------------------------------
+# replace some variables in the script
+#-------------------------------------------
+/bin/sed -i \
+ -e "/__PGBIN__/s@__PGBIN__@$PGBIN@p" \
+ -e "/__DATADIR_BASE__/s@__DATADIR_BASE__@$BASEDIR@" \
+ -e "/__PGSUPERUSER__/s/__PGSUPERUSER__/$WHOAMI/" \
+ -e "/__ARCHDIR__/s@__ARCHDIR__@$BASEDIR/archivedir@" \
+ $1/$SCRIPT
+
+chmod 755 $1/$SCRIPT
+}
+
+#-------------------------------------------
+# create initial recovery.conf
+# argument1: PostgreSQL database cluster directory
+# argument2: cluster No. We assume that data0 is primary
+#-------------------------------------------
+function create_recovery_conf {
+ if [ $PGVERSION -ge 120 ];then
+ fname=myrecovery.conf
+ elif [ $2 = "0" ];then
+ fname=recovery.done
+ else
+ fname=recovery.conf
+ fi
+
+ if [ $PGVERSION -lt 120 ];then
+ cat > $1/$fname <<EOF
+standby_mode = 'on'
+EOF
+ fi
+
+ cat > $1/$fname <<EOF
+primary_conninfo = 'host=localhost port=$BASEPORT user=$WHOAMI application_name=''server$2'''
+recovery_target_timeline='latest'
+EOF
+ if [ $USE_REPLICATION_SLOT = true ];then
+ echo "primary_slot_name = 'pgpool_setup_slot$2'" >> $1/$fname
+ else
+ cat >> $1/$fname <<EOF
+restore_command = 'cp $BASEDIR/archivedir/%f "%p" 2> /dev/null'
+EOF
+ fi
+}
+
+function set_pool_hba_conf {
+ POOL_HBACONF=$1
+ sed -i '/host.*all.*all.*trust$/s/^/#/g' $POOL_HBACONF
+ sed -i '/local.*all.*all.*trust$/s/^/#/g' $POOL_HBACONF
+
+ if [ $PGVERSION -ge 100 ];
+ then
+ echo "host all scram_user 0/0 scram-sha-256" >> $POOL_HBACONF
+ echo "host all md5_user 0/0 md5" >> $POOL_HBACONF
+
+ echo "local all scram_user scram-sha-256" >> $POOL_HBACONF
+ echo "local all md5_user md5" >> $POOL_HBACONF
+ fi
+
+ echo "local all all trust" >> $POOL_HBACONF
+
+ echo "host all all 127.0.0.1/32 trust" >> $POOL_HBACONF
+ echo "host all all ::1/128 trust" >> $POOL_HBACONF
+}
+
+#-------------------------------------------
+# set pgpool.conf
+# argument: absolute path to pgpool.conf
+#-------------------------------------------
+function set_pgpool_conf {
+ echo "sr_check_user = '$WHOAMI'" >> $CONF
+ echo "recovery_user = '$WHOAMI'" >> $CONF
+ echo "recovery_password = ''" >> $CONF
+ echo "recovery_1st_stage_command = 'basebackup.sh'" >> $CONF
+
+ if [ $MODE = "r" -o $MODE = "i" ];then
+ echo "recovery_2nd_stage_command = 'pgpool_recovery_pitr'" >> $CONF
+ fi
+
+ n=0
+ while [ $n -lt $NUMCLUSTERS ]
+ do
+ echo "health_check_period$n = 10" >> $CONF
+ echo "health_check_timeout$n = 20" >> $CONF
+ echo "health_check_user$n = '$WHOAMI'" >> $CONF
+ echo "health_check_password$n = ''" >> $CONF
+ echo "health_check_database$n = 'postgres'" >> $CONF
+ echo "health_check_max_retries$n = 3" >> $CONF
+ echo "health_check_retry_delay$n = 1" >> $CONF
+ echo "connect_timeout$n = 1000" >> $CONF
+ n=`expr $n + 1`
+ done
+ OIDDIR=$BASEDIR/log/pgpool/oiddir
+ mkdir -p $OIDDIR
+ echo "memqcache_oiddir = '$OIDDIR'" >> $CONF
+ echo "log_per_node_statement = on" >> $CONF
+
+ if [ $MODE = "s" ];then
+ echo "failover_command = '$FAILOVER_SCRIPT %d %h %p %D %m %M %H %P %r %R'" >> $CONF
+ fi
+
+ echo "socket_dir = '$PGSOCKET_DIR'" >> $CONF
+ echo "pcp_socket_dir = '$PGSOCKET_DIR'" >> $CONF
+ echo "log_line_prefix = '%t: %a pid %p: '" >> $CONF
+}
+
+#-------------------------------------------
+# wait for pgpool comes up
+#-------------------------------------------
+function wait_for_pgpool_startup {
+ timeout=20
+
+ while [ $timeout -gt 0 ]
+ do
+ $PSQL -p $PGPOOL_PORT -c "show pool_nodes" postgres >/dev/null 2>&1
+ if [ $? = 0 ];then
+# echo "pgpool-II comes up after `expr 20 - $timeout` seconds"
+ break;
+ fi
+ timeout=`expr $timeout - 1`
+ sleep 1
+ done
+}
+
+#-------------------------------------------
+# wait for pgpool reload finished
+#-------------------------------------------
+function wait_for_pgpool_reload {
+ timeout=20
+ num_node=$1
+
+ while [ $timeout -gt 0 ]
+ do
+ N=`$PSQL -p $PGPOOL_PORT -c "show pool_status" test | grep backend_data | wc -l`
+ if [ $N = $num_node ];then
+ break;
+ fi
+ timeout=`expr $timeout - 1`
+ sleep 1
+ done
+}
+
+#################################################################################
+#
+# main script
+#
+################################################################################
+function usage()
+{
+ echo "usage: $0 [-m r|s|n|l|y|i] [-n num_clusters] [-p base_port] [-pg pg_base_port][--no-stop] [-d] [-s] [-r]";exit 1
+}
+
+#-------------------------------------------
+# Argument check
+# usage: $0 [-m r|s|n][-n num_clusters][-p base_port][-pg pg_base_port][--no-stop][-d][-s][-r]
+#-------------------------------------------
+#
+# default mode is streaming replication mode
+MODE="s"
+NO_STOP="false"
+
+while [ $# -gt 0 ]
+do
+ if [ $1 = "-m" ];then
+ shift
+ case $1 in
+ r ) MODE="r";;
+ s ) MODE="s";;
+ n ) MODE="n";;
+ l ) MODE="l";;
+ y ) MODE="y";;
+ i ) MODE="i";;
+ * ) usage;;
+ esac
+ elif [ $1 = "-n" ];then
+ shift
+ NUMCLUSTERS=$1
+ elif [ $1 = "-p" ];then
+ shift
+ BASEPORT=$1
+ ORIGBASEPORT=$1
+ elif [ $1 = "-pg" ];then
+ shift
+ PGBASEPORT=$1
+ elif [ $1 = "--no-stop" ];then
+ shift
+ NO_STOP="true"
+ elif [ $1 = "-d" ];then
+ PGPOOLDEBUG="true"
+ elif [ $1 = "-s" ];then
+ USE_REPLICATION_SLOT="true"
+ elif [ $1 = "-r" ];then
+ USE_PG_REWIND="true"
+ elif [ $1 = "--help" -o $1 = "-o" ];then
+ usage
+ exit
+ else
+ usage
+ exit
+ fi
+ shift
+done
+
+case $MODE in
+ r) MODENAME="native replication mode"
+ SAMPLE_CONF=$PGPOOLDIR/pgpool.conf.sample-replication
+ ;;
+ s ) MODENAME="streaming replication mode"
+ SAMPLE_CONF=$PGPOOLDIR/pgpool.conf.sample-stream
+ ;;
+ n ) MODENAME="raw mode"
+ SAMPLE_CONF=$PGPOOLDIR/pgpool.conf.sample-raw
+ ;;
+ l ) MODENAME="logical replication mode"
+ SAMPLE_CONF=$PGPOOLDIR/pgpool.conf.sample-logical
+ ;;
+ y ) MODENAME="slony mode"
+ SAMPLE_CONF=$PGPOOLDIR/pgpool.conf.sample-slony
+ ;;
+ i ) MODENAME="snapshot isolation mode"
+ SAMPLE_CONF=$PGPOOLDIR/pgpool.conf.sample-snapshot
+ ;;
+esac
+
+# If USE_REPLICATION_SLOT is provided as an environment variable, turn on -s
+if [ a$USE_REPLICATION_SLOT = a"true" ];then
+ USE_REPLICATION_SLOT="true"
+fi
+
+# If USE_PG_REWIND is provided as an environment variable, turn on -r
+if [ a$USE_PG_REWIND = a"true" ];then
+ USE_PG_REWIND="true"
+fi
+
+#-------------------------------------------
+# Make sure that current directory is empty
+#-------------------------------------------
+if [ "`/bin/ls`" != "" ]
+then
+ echo "$0: Current directory is not empty. Please remove files and directories then try again."
+ exit 1
+fi
+
+exec 5> $BASEDIR/pgpool_setup.log
+
+#-------------------------------------------
+# everything looks good. starting setup...
+#-------------------------------------------
+echo "Starting set up in $MODENAME"
+
+#-------------------------------------------
+# assign base port for PostgreSQL
+#-------------------------------------------
+ORIG_BASEPORT=$BASEPORT
+BASEPORT=$PGBASEPORT
+
+#-------------------------------------------
+# install pgpool.conf
+#-------------------------------------------
+test ! -d etc && mkdir etc
+cp $SAMPLE_CONF $CONF
+cp $PGPOOLDIR/pool_hba.conf.sample $BASEDIR/etc/pool_hba.conf
+
+#-------------------------------------------
+# create startall, shutdownall and pgpool_reload
+#-------------------------------------------
+echo "creating startall and shutdownall"
+echo "LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$LPATH" > $STARTALL
+echo 'dir=`pwd`' >> $STARTALL
+echo "PGPOOL_INSTALL_DIR=$PGPOOL_INSTALL_DIR" >> $STARTALL
+chmod 755 $STARTALL
+echo 'dir=`pwd`' > $SHUTDOWNALL
+echo "PGPOOL_INSTALL_DIR=$PGPOOL_INSTALL_DIR" >> $SHUTDOWNALL
+echo '$PGPOOL_INSTALL_DIR/bin/pgpool -f $dir/etc/pgpool.conf -m f stop' >> $SHUTDOWNALL
+echo 'while [ -f $dir/run/pgpool.pid ];do sleep 1;done' >> $SHUTDOWNALL
+if [ $CHECK_TIME_WAIT != "false" ];then
+ echo "while netstat -a|grep $ORIGBASEPORT ;do sleep 1;done" >> $SHUTDOWNALL
+fi
+chmod 755 $SHUTDOWNALL
+echo 'dir=`pwd`' > $PGPOOL_RELOAD
+echo "PGPOOL_INSTALL_DIR=$PGPOOL_INSTALL_DIR" >> $PGPOOL_RELOAD
+echo '$PGPOOL_INSTALL_DIR/bin/pgpool -f $dir/etc/pgpool.conf reload' >> $PGPOOL_RELOAD
+chmod 755 $PGPOOL_RELOAD
+
+#-------------------------------------------
+# create failover script
+#-------------------------------------------
+echo "creating failover script"
+create_failover_script >&5 2>&1
+
+#-------------------------------------------
+# create each PostgreSQL cluster
+#-------------------------------------------
+n=0
+while [ $n -lt $NUMCLUSTERS ]
+do
+ CLUSTER="data"`expr $n`
+ CLUSTERDIR=$BASEDIR/$CLUSTER
+ PORT=`expr $BASEPORT + $n`
+
+ echo -n "creating database cluster $CLUSTERDIR..."
+ $INITDB -D $CLUSTERDIR $INITDBARG >&5 2>&1
+ echo "done."
+
+ # set postgresql.conf
+ echo "update postgresql.conf"
+ set_postgresql_conf $CLUSTERDIR >&5 2>&1
+
+ # create pgpool_remote_start script under cluster directory
+ echo "creating pgpool_remote_start"
+ create_pgpool_remote_start_script $CLUSTERDIR >&5 2>&1
+
+ echo "creating basebackup.sh"
+ # create basebackup.sh
+ if [ $MODE = 's' ];then
+ create_basebackup_stream $CLUSTERDIR $n >&5 2>&1
+ elif [ $MODE = 'r' -o $MODE = 'i' ];then
+ create_basebackup_replication $CLUSTERDIR >&5 2>&1
+ create_pgpool_recovery_pitr $CLUSTERDIR >&5 2>&1
+ fi
+
+ # create recovery.conf or recovery.done if streaming replication
+ # mode
+ if [ $MODE = "s" ];then
+ echo "creating recovery.conf"
+ create_recovery_conf $CLUSTERDIR $n >&5 2>&1
+ fi
+
+ echo "$PG_CTL -D $CLUSTERDIR -m f stop" >> $SHUTDOWNALL
+ echo "$PG_CTL -w -D $CLUSTERDIR start" >> $STARTALL
+
+ n=`expr $n + 1`
+
+ echo "#$n port is $PORT" >> README.port
+
+done
+
+set_pgpool_conf $CONF
+set_pool_hba_conf $BASEDIR/etc/pool_hba.conf
+
+PGPOOL_PORT=$ORIG_BASEPORT
+echo "port = $PGPOOL_PORT" >> $CONF
+PCP_PORT=`expr $PGPOOL_PORT + 1`
+echo "pcp_port = $PCP_PORT" >> $CONF
+
+#-------------------------------------------
+# create password file for pcp
+#-------------------------------------------
+echo "localhost:${PCP_PORT}:${WHOAMI}:${WHOAMI}" >> $PCP_PASS_FILE
+chmod 0600 $PCP_PASS_FILE
+
+test ! -d run && mkdir run
+echo "pid_file_name = '$BASEDIR/run/pgpool.pid'" >> $CONF
+test ! -d log && mkdir log
+echo "logdir = '$BASEDIR/log'" >> $CONF
+
+if [ "$PGPOOLDEBUG" = "true" ];then
+ echo '$PGPOOL_INSTALL_DIR/bin/pgpool -d -D -n -f $dir/etc/pgpool.conf -F $dir/etc/pcp.conf -a $dir/etc/pool_hba.conf 2>&1 | cat > $dir/log/pgpool.log &' >> $STARTALL
+else
+ echo '$PGPOOL_INSTALL_DIR/bin/pgpool -D -n -f $dir/etc/pgpool.conf -F $dir/etc/pcp.conf -a $dir/etc/pool_hba.conf 2>&1 | cat > $dir/log/pgpool.log &' >> $STARTALL
+fi
+
+# create pcp.conf
+
+if [ -f $PGPOOLDIR/pcp.conf.sample ];then
+ cp $PGPOOLDIR/pcp.conf.sample etc/pcp.conf
+fi
+echo -n "${WHOAMI}:" >> etc/pcp.conf
+$PGPOOL_INSTALL_DIR/bin/pg_md5 $WHOAMI >> etc/pcp.conf
+
+# create pool_passwd
+$PGPOOL_INSTALL_DIR/bin/pg_md5 -m -f etc/pgpool.conf -u $WHOAMI $WHOAMI
+
+if [ $USE_REPLICATION_SLOT = "false" ];then
+ # create archive directory
+ mkdir archivedir
+fi
+
+#-------------------------------------------
+# if streaming replication mode, we need to create data1 and so on, by
+# using on line recovery.
+#-------------------------------------------
+
+if [ $MODE = 's' ];then
+# temporarily start data0 cluster to create extensions
+ echo "temporarily start data0 cluster to create extensions"
+ $PG_CTL -w -D data0 start >&5 2>&1
+ $PSQL -p $BASEPORT template1 >&5 2>&1 <<EOF
+CREATE EXTENSION pgpool_regclass;
+CREATE EXTENSION pgpool_recovery;
+CREATE DATABASE test;
+EOF
+ if [ $USE_REPLICATION_SLOT = "true" ];then
+ n=0
+ while [ $n -lt $NUMCLUSTERS ]
+ do
+ $PSQL -p $BASEPORT template1 -c "SELECT * FROM pg_create_physical_replication_slot('pgpool_setup_slot$n')" >&5 2>&1
+ n=`expr $n + 1`
+ done
+ fi
+
+ n=0
+ PORT=$BASEPORT
+ CLUSTER="data"`expr $n`
+ CLUSTERDIR=$BASEDIR/$CLUSTER
+ echo "backend_hostname$n = '$PGSOCKET_DIR'" >> $CONF
+ echo "backend_port$n = $PORT" >> $CONF
+ echo "backend_weight$n = 1" >> $CONF
+ echo "backend_data_directory$n = '$CLUSTERDIR'" >> $CONF
+ echo "backend_application_name$n = 'server$n'" >> $CONF
+
+# temporarily start pgpool
+ echo "temporarily start pgpool-II to create standby nodes"
+ $PGPOOL_INSTALL_DIR/bin/pgpool -D -n -f $BASEDIR/etc/pgpool.conf -F $BASEDIR/etc/pcp.conf -a $BASEDIR/etc/pool_hba.conf > $BASEDIR/log/pgpool.log 2>&1 &
+
+ wait_for_pgpool_startup
+
+ if [ $NUMCLUSTERS -gt 1 ];then
+ n=1
+ while [ $n -lt $NUMCLUSTERS ]
+ do
+ # set up pgpool.conf
+ PORT=`expr $PORT + 1`
+ echo "backend_hostname$n = '$PGSOCKET_DIR'" >> $CONF
+ echo "backend_port$n = $PORT" >> $CONF
+ echo "backend_weight$n = 1" >> $CONF
+ CLUSTER="data"`expr $n`
+ CLUSTERDIR=$BASEDIR/$CLUSTER
+ echo "backend_data_directory$n = '$CLUSTERDIR'" >> $CONF
+ echo "backend_application_name$n = 'server$n'" >> $CONF
+ n=`expr $n + 1`
+ done
+ $PGPOOL_INSTALL_DIR/bin/pgpool -f $BASEDIR/etc/pgpool.conf reload
+ fi
+
+ wait_for_pgpool_reload $NUMCLUSTERS
+$PSQL -p $PGPOOL_PORT -c "show pool_nodes" test
+export PCPPASSFILE=$PCP_PASS_FILE
+# recovery data1 and so on
+ n=1
+ while [ $n -lt $NUMCLUSTERS ]
+ do
+ echo -n "recovery node $n..."
+ $PGPOOL_INSTALL_DIR/bin/pcp_recovery_node -w -h localhost -p $PCP_PORT -n $n
+ echo "done."
+ n=`expr $n + 1`
+ if [ $n -lt $NUMCLUSTERS ];then
+ wait_for_pgpool_startup
+# sleep 10
+ fi
+ done
+
+#
+# replication mode
+#
+else
+ n=0
+ PORT=$BASEPORT
+ CLUSTER="data"`expr $n`
+ CLUSTERDIR=$BASEDIR/$CLUSTER
+
+ while [ $n -lt $NUMCLUSTERS ]
+ do
+ if [ $MODE = 'l' -o $MODE = 'y' ]
+ then
+ # temporarily start data$n cluster to create extensions
+ echo "temporarily start data${n} cluster to create extensions"
+ $PG_CTL -w -D data${n} start >&5 2>&1
+ $PSQL -p `expr $BASEPORT + $n` template1 >&5 2>&1 <<EOF
+CREATE EXTENSION pgpool_regclass;
+CREATE EXTENSION pgpool_recovery;
+CREATE DATABASE test;
+EOF
+ $PG_CTL -m f -D data${n} stop >&5 2>&1
+ fi
+
+ # set up pgpool.conf
+ echo "backend_hostname$n = '$PGSOCKET_DIR'" >> $CONF
+ echo "backend_port$n = $PORT" >> $CONF
+ echo "backend_weight$n = 1" >> $CONF
+
+ if [ $n -eq 0 -a $MODE = "l" ]
+ then
+ echo "backend_flag$n = ALWAYS_MASTER" >> $CONF
+ fi
+
+ CLUSTER="data"`expr $n`
+ CLUSTERDIR=$BASEDIR/$CLUSTER
+ echo "backend_data_directory$n = '$CLUSTERDIR'" >> $CONF
+ PORT=`expr $PORT + 1`
+ n=`expr $n + 1`
+ done
+
+ echo "start all"
+ $STARTALL >&5 2>&1
+ echo -n "waiting for pgpool-II coming up..."
+ wait_for_pgpool_startup
+# sleep 20
+ echo "done."
+fi
+
+if [ $MODE = "r" -o $MODE = "n" -o $MODE = "i" ];then
+ echo "create extensions"
+ $PSQL -p $PGPOOL_PORT template1 >&5 2>&1 <<EOF
+CREATE EXTENSION pgpool_regclass;
+CREATE EXTENSION pgpool_recovery;
+CREATE DATABASE test;
+EOF
+fi
+
+#-------------------------------------------
+# create follow_masterfailover script
+#-------------------------------------------
+if [ $MODE = "s" ];then
+ echo "creating follow master script"
+ create_follow_master_script >&5 2>&1
+ echo "follow_master_command = '$FOLLOW_MASTER_SCRIPT %d %h %p %D %m %M %H %P %r %R'" >> $CONF
+fi
+
+$PSQL -p $PGPOOL_PORT test <<EOF
+show pool_nodes;
+EOF
+
+echo "pgpool port is $PGPOOL_PORT" >> README.port
+echo "pcp port is $PCP_PORT" >> README.port
+
+if [ $NO_STOP = "false" ];then
+ echo "shutdown all"
+ $SHUTDOWNALL >&5 2>&1
+fi
+
+echo "export PGPOOL_PORT=$PGPOOL_PORT" > bashrc.ports
+echo "export PCP_PORT=$PCP_PORT" >> bashrc.ports
+echo "export PCPPASSFILE=$PCP_PASS_FILE" >> bashrc.ports
+chmod 755 bashrc.ports
+
+echo
+echo "pgpool-II setting for $MODENAME is done."
+echo "To start the whole system, use ${STARTALL}."
+echo "To shutdown the whole system, use ${SHUTDOWNALL}."
+echo "pcp command user name is \"$WHOAMI\", password is \"$WHOAMI\"."
+echo "Each PostgreSQL, pgpool-II and pcp port is as follows:"
+cat README.port
+echo "The info above is in README.port."
+
+if [ $NO_STOP = "true" ];then
+ echo "CAUTION: whole system is still running."
+fi
--- /dev/null
+#!/usr/bin/env bash
+#
+# Copyright (c) 2013-2019 PgPool Global Development Group
+#
+# Permission to use, copy, modify, and distribute this software and
+# its documentation for any purpose and without fee is hereby
+# granted, provided that the above copyright notice appear in all
+# copies and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of the
+# author not be used in advertising or publicity pertaining to
+# distribution of the software without specific, written prior
+# permission. The author makes no representations about the
+# suitability of this software for any purpose. It is provided "as
+# is" without express or implied warranty.
+#-------------------------------------------------------------------
+# Set up watchdog enabled pgpool-II and PostgreSQL temporary
+# installation in current directory for *testing* purpose. Do not use
+# this tool for production environment!
+# Note that this script uses pgpool_setup as a work horse.
+#
+# usage: watchdog_setup [-wn num_pgpool][-wp watchdog_base_port][-m r|s|n][-n num_clusters][-p base_port][--no-stop][-d]
+# -wn num_pgpool: create num_pgpool pgpool nodes. The default is 3. Must be greater than 1.
+# -wp watchdog_base_port: starting port number. The default is
+# 50000.
+#-------------------------------------------
+# Configuration section
+#-------------------------------------------
+# Number of Pgpool-II installations.
+W_NUM_PGPOOL=${W_NUM_PGPOOL:-"3"}
+
+# Starting port number.
+W_BASE_PORT=${W_BASE_PORT:-"50000"}
+
+# PostgreSQL startig port number.
+export PGBASEPORT=`expr $W_BASE_PORT + 1000`
+
+# number of ports used in a single pgpool-II installation.
+# (port, pcp_port, wd_port, wd_heartbeat_port)
+num_ports_per_node=4
+
+#-------------------------------------------
+# End of configuration section
+#-------------------------------------------
+#
+# user name
+WHOAMI=`whoami`
+
+# our root directory
+BASEDIR=`pwd`
+
+# location of pgpool_setup
+PGPOOL_SETUP=${PGPOOL_SETUP:-"$(dirname $0)/pgpool_setup"}
+
+# PostgreSQL bin directory
+PGBIN=${PGBIN:-"@@PGSQL_BIN_DIR@@"}
+INITDB=$PGBIN/initdb
+PG_CTL=$PGBIN/pg_ctl
+PSQL=$PGBIN/psql
+
+#-------------------------------------------
+# set postgresql.conf
+# argument: PostgreSQL database cluster directory
+#-------------------------------------------
+function set_postgresql_conf
+{
+ PGCONF=$1/postgresql.conf
+
+ echo "listen_addresses = '*'" >> $PGCONF
+ echo "port = $PORT" >> $PGCONF
+ echo "logging_collector = on" >> $PGCONF
+ echo "log_filename = '%A.log'" >> $PGCONF
+ echo "log_line_prefix = '%p %t '" >> $PGCONF
+ echo "log_truncate_on_rotation = on" >> $PGCONF
+ echo "log_statement = 'all'" >> $PGCONF
+ echo "max_prepared_transactions = 10" >> $PGCONF
+ echo "unix_socket_directories = '$PGSOCKET_DIR'" >> $PGCONF
+
+ if [ $MODE = "s" ];then
+ echo "hot_standby = on" >> $PGCONF
+ echo "wal_level = hot_standby" >> $PGCONF
+ echo "max_wal_senders = $NUMCLUSTERS" >> $PGCONF
+ echo "archive_mode = on" >> $PGCONF
+ echo "archive_command = 'cp %p $BASEDIR/archivedir/%f </dev/null'" >> $PGCONF
+ elif [ $MODE = 'r' ];then
+ echo "wal_level = archive" >> $PGCONF
+ echo "archive_mode = on" >> $PGCONF
+ echo "archive_command = 'cp %p $BASEDIR/archivedir/%f </dev/null'" >> $PGCONF
+ fi
+
+ ed $1/pg_hba.conf <<EOF
+/^#local *replication/s/^#//p
+/^#host *replication/s/^#//p
+/^#host *replication/s/^#//p
+w
+q
+EOF
+
+}
+
+#-------------------------------------------
+# set pgpool.conf
+# argument: absolute path to pgpool.conf
+#-------------------------------------------
+function set_pgpool_conf {
+ echo "sr_check_user = '$WHOAMI'" >> $CONF
+ echo "recovery_user = '$WHOAMI'" >> $CONF
+ echo "recovery_password = ''" >> $CONF
+ echo "recovery_1st_stage_command = 'basebackup.sh'" >> $CONF
+
+ if [ $MODE = "r" ];then
+ echo "recovery_2nd_stage_command = 'pgpool_recovery_pitr'" >> $CONF
+ fi
+
+ echo "health_check_period = 10" >> $CONF
+ echo "health_check_user = '$WHOAMI'" >> $CONF
+ OIDDIR=$BASEDIR/log/pgpool/oiddir
+ mkdir -p $OIDDIR
+ echo "memqcache_oiddir = '$OIDDIR'" >> $CONF
+ echo "log_per_node_statement = on" >> $CONF
+
+ if [ $MODE = "s" ];then
+ echo "failover_command = '$FAILOVER_SCRIPT %d %h %p %D %m %M %H %P %r %R'" >> $CONF
+ fi
+
+ echo "socket_dir = '$PGSOCKET_DIR'" >> $CONF
+ echo "pcp_socket_dir = '$PGSOCKET_DIR'" >> $CONF
+}
+
+#-------------------------------------------
+# wait for pgpool comes up
+#-------------------------------------------
+function wait_for_pgpool_startup {
+ timeout=20
+
+ while [ $timeout -gt 0 ]
+ do
+ $PSQL -p $PGPOOL_PORT -c "show pool_nodes" postgres >/dev/null 2>&1
+ if [ $? = 0 ];then
+ # echo "pgpool-II comes up after `expr 20 - $timeout` seconds"
+ break;
+ fi
+ timeout=`expr $timeout - 1`
+ sleep 1
+ done
+}
+
+#-------------------------------------------
+# wait for pgpool reload finished
+#-------------------------------------------
+function wait_for_pgpool_reload {
+ timeout=20
+ num_node=$1
+
+ while [ $timeout -gt 0 ]
+ do
+ N=`$PSQL -p $PGPOOL_PORT -c "show pool_status" test | grep backend_data | wc -l`
+ if [ $N = $num_node ];then
+ break;
+ fi
+ timeout=`expr $timeout - 1`
+ sleep 1
+ done
+}
+
+#-------------------------------------------
+# Set watchdog params to pgpool.conf
+#-------------------------------------------
+function set_watchdog_params {
+ id=$1
+ num_pgpool=$2
+ base_port=$3
+ priority=`expr $num_pgpool - $id`
+ n=0
+ conf=etc/pgpool.conf
+ node_id_file=etc/pgpool_node_id
+
+ cat >> $conf <<EOF
+use_watchdog = on
+wd_interval = 1
+wd_priority = $priority
+EOF
+
+ while [ $n -lt $num_pgpool ]
+ do
+ pgpool_port=`expr $base_port + \( $n \* $num_ports_per_node \)`
+ pcp_port=`expr $pgpool_port + 1`
+ wd_port=`expr $pcp_port + 1`
+
+ wd_heartbeat_port=`expr $wd_port + 1`
+ echo "hostname$n = 'localhost'" >> $conf
+ echo "pgpool_port$n = $pgpool_port" >> $conf
+ echo "wd_port$n = $wd_port" >> $conf
+ echo "heartbeat_hostname$n = 'localhost'" >> $conf
+ echo "heartbeat_port$n = $wd_heartbeat_port" >> $conf
+ n=`expr $n + 1`
+ done
+
+ echo "$id" >> $node_id_file
+}
+
+#################################################################################
+#
+# main script
+#
+################################################################################
+function usage()
+{
+ echo "usage: $0 [-wn num_pgpool][-wp watchdog_base_port][-m r|s|n] [-n num_clusters] [-p base_port] [-pg pg_base_port][--no-stop] [-d]";exit 1
+}
+
+#-------------------------------------------
+# Argument check
+# usage: $0 [-wn num_pgpool][-wp watchdog_base_port][-m r|s|n][-n num_clusters][-p base_port][-pg pg_base_port][--no-stop][-d]
+#-------------------------------------------
+#
+# default mode is streaming replication mode
+MODE="s"
+NO_STOP="false"
+
+while [ $# -gt 0 ]
+do
+ if [ $1 = "-wn" ];then
+ shift
+ W_NUM_PGPOOL=$1
+ if [ "$W_NUM_PGPOOL" -le 1 ];then
+ echo "number of Pgpool-II nodes must be greater than 1"
+ exit 1
+ fi
+ elif [ $1 = "-wp" ];then
+ shift
+ W_BASE_PORT=$1
+ PGBASEPORT=`expr $W_BASE_PORT + 1000`
+
+ # rest are pgpool_setup args
+
+ elif [ $1 = "-m" ];then
+ shift
+ case $1 in
+ r ) MODE="r";;
+ s ) MODE="s";;
+ n ) MODE="n";;
+ * ) usage;;
+ esac
+ elif [ $1 = "-n" ];then
+ shift
+ export NUMCLUSTERS=$1
+ elif [ $1 = "-p" ];then
+ shift
+ export BASEPORT=$1
+ elif [ $1 = "-pg" ];then
+ shift
+ export PGBASEPORT=$1
+ elif [ $1 = "--no-stop" ];then
+ shift
+ NO_STOP="true"
+ elif [ $1 = "-d" ];then
+ export PGPOOLDEBUG="true"
+ shift;
+ elif [ $1 = "--help" -o $1 = "-o" ];then
+ usage
+ exit
+ else
+ usage
+ exit
+ fi
+ shift
+done
+
+#-------------------------------------------
+# Make sure that current directory is empty
+#-------------------------------------------
+if [ "`/bin/ls`" != "" ]
+then
+ echo "$0: Current directory is not empty. Please remove files and directories then try again."
+ exit 1
+fi
+
+#-------------------------------------------
+# everything looks good. starting setup...
+#-------------------------------------------
+echo "Starting set up "
+
+#-------------------------------------------
+# Run pgpool_setup
+#-------------------------------------------
+
+STARTALL=$BASEDIR/startall
+SHUTDOWNALL=$BASEDIR/shutdownall
+
+cnt=0
+
+while [ $cnt -lt $W_NUM_PGPOOL ]
+do
+ echo "============= setting up pgpool $cnt ============="
+ mkdir pgpool$cnt
+ cd pgpool$cnt
+ port=`expr $W_BASE_PORT + \( $cnt \* $num_ports_per_node \)`
+ $PGPOOL_SETUP -m $MODE -p $port -pg $PGBASEPORT
+ set_watchdog_params $cnt $W_NUM_PGPOOL $W_BASE_PORT
+
+ # remove "pg_ctl start" line from startall/shutdownall script in other than pgpool0
+ if [ $cnt != 0 ]
+ then
+ sed -i '/.*data.*/d' startall
+ sed -i '/.*data.*/d' shutdownall
+ fi
+
+ echo "cd pgpool$cnt" >> $STARTALL
+ echo "./startall" >> $STARTALL
+ echo "cd .." >> $STARTALL
+ echo "cd pgpool$cnt" >> $SHUTDOWNALL
+ echo "./shutdownall" >> $SHUTDOWNALL
+ echo "cd .." >> $SHUTDOWNALL
+
+ cd ..
+ cnt=`expr $cnt + 1`
+done
+
+chmod 755 $STARTALL
+chmod 755 $SHUTDOWNALL