# -*- perl -*-
# ers_setup
# Copyright (C) 2002 Digital Distribution GFS P/L
# Derived from code Copyright (C) 2000 PostgreSQL, Inc.

eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}'
    & eval 'exec perl -S $0 $argv:q'
    if 0;

use Getopt::Long;
use DBI;

$| = 1;

$result = GetOptions("debug!", "quiet!", "help", "pgsuperuser=s", "pgsuperpass=s",
                     "masterserver=s", "masteruser=s", "masterpass=s", "masterdb=s", "masterport=s",
                     "slaveserver=s", "slaveuser=s", "slavepass=s", "slavedb=s", "slaveport=s");

$RServ::debug = $opt_debug || 0;

if( -f "@prefix@/etc/replication.cfg") {
  printf"
WARNING: @prefix@/etc/replication.cfg already exists
         which means that this server has already been
         configured\n\n";
  exit(1);
}

if (defined($opt_help)  || !defined($opt_masterdb)
			|| ( !defined($opt_slavedb) &&  !defined($opt_slaveserver) ) ) {
    print "Usage: $0 
		--masterserver=<server> [--pgsuperuser=<user>]
                --masteruser=<user>     [--pgsuperpass=<pass>]
                --masterpass=<pass>     [--slaveserver=<server>]
                --masterdb=<database>   [--slaveuser=<user>]
                --masterport=<port>     [--slavepass=<user>]
                                        [--slavedb=<database>]
                                        [--slaveport=<port>]\n";
    exit ((scalar(@ARGV) < 1)? 1:0);
}

my $quiet	 = 1 if $opt_quiet;

my $masterdb     = $opt_masterdb;
my $masterserver = $opt_masterserver || "localhost";
my $masteruser   = $opt_masteruser || "pgsql";
my $masterport   = $opt_masterport || "5432";
my $masterpass   = $opt_masterpass || "none";

my $superuser    = $opt_pgsuperuser || $masteruser;
my $superpass    = $opt_pgsuperpass || $masterpass;

my $slavedb = $opt_slavedb || $masterdb;
my $slaveserver = $opt_slaveserver || $masterserver;
my $slaveuser = $opt_slaveuser || $masteruser;
my $slaveport = $opt_slaveport || "5432";
my $slavepass = "none";
if(defined($opt_slavepass)) {
  $slavepass = $opt_slavepass;
} elsif(defined($opt_masterpass)) {
  $slavepass = $masterpass;
} 

# Display a banner to the user
if(!$quiet) {
  print "\nPostgreSQL Enterprise Replication Server 1.20\n";
  print "   Copyright (C) 2001-2002 PostgreSQL, Inc\n";
  print "*********************************************\n";
  print "\nSetting up eRServer...\n\n";
}

# Test if the parameters for connecting to the databases are valid
my $master = DBI->connect("dbi:Pg:dbname=$masterdb;host=$masterserver;port=$masterport", $masteruser, $masterpass) 
	|| die "Connection to master database failed: ", $DBI::errstr, "\n";
$master->{AutoCommit} = 0;

my $functions = DBI->connect("dbi:Pg:dbname=$masterdb;host=$masterserver;port=$masterport", $superuser, $superpass) 
	|| die "Connection to master database as superuser failed: ", $DBI::errstr, "\n";
$functions->{AutoCommit} = 0;

my $slave = DBI->connect("dbi:Pg:dbname=$slavedb;host=$slaveserver;port=$slaveport", $slaveuser, $slavepass) 
	|| die "Connection to slave database failed: ", $DBI::errstr, "\n";
$slave->{AutoCommit} = 0;

# Show Master database parameters unless quietness is requested
if(!$quiet) {
  print "Master database\n";
  print "***************\n";
  print "Server                : ", $masterserver, "\n";
  print "Port                  : ", $masterport, "\n";
  if($opt_pgsuperuser ne "") {
    print "PG Superuser          : ", $superuser, "\n";
  }
  if($opt_pgsuperpass ne "") {
    print "PG Superuser password : ", $superpass, "\n";
  }
  print "Database              : ", $masterdb, "\n";
  print "Username              : ", $masteruser, "\n";
  if($masterpass ne "") {
    print "Password              : ", $masterpass, "\n";
  }
  print "\n";
}

# eRServer Functions
$functions->do("set transaction isolation level serializable") || die $functions->errstr;

$rows = $functions->prepare("SELECT * FROM pg_proc WHERE proname = ?;");

$rows->execute("_rserv_log_");
if($rows->rows == 0) {

  $functions->do("CREATE FUNCTION _rserv_log_() RETURNS opaque AS '@prefix@/lib/erserver.so' LANGUAGE 'c'")
	|| die $functions->errstr;
  $functions->do("CREATE FUNCTION _rserv_sync_(int4) RETURNS int4 AS '@prefix@/lib/erserver.so' LANGUAGE 'c'")
	|| die $functions->errstr;
  $functions->do("CREATE FUNCTION _rserv_debug_(int4) RETURNS int4 AS '@prefix@/lib/erserver.so' LANGUAGE 'c'")
	|| die $functions->errstr;
  $functions->do("CREATE FUNCTION _rserv_lock_altid_(int4) RETURNS int4 AS '@prefix@/lib/erserver.so' LANGUAGE 'c'")
	|| die $functions->errstr;
  $functions->do("CREATE FUNCTION _rserv_unlock_altid_(int4) RETURNS int4 AS '@prefix@/lib/erserver.so' LANGUAGE 'c'")
	|| die $functions->errstr;

# PTE funcs
  $functions->do("CREATE FUNCTION _pte_get_snapshot_() RETURNS text AS '@prefix@/lib/pte.so' LANGUAGE 'c'")
	|| die $functions->errstr;
  $functions->do("CREATE FUNCTION _pte_set_snapshot_(text) RETURNS int4 AS '@prefix@/lib/pte.so' LANGUAGE 'c'")
	|| die $functions->errstr;

}
$rows->finish();

#=======
# Notify user where things are up to, unless requested
if (!$quiet) {
  print "Function creation completed\n";
}

$master->do("set transaction isolation level serializable") || die $master->errstr;

# Create Master Tables
$rows = $master->prepare("SELECT * FROM pg_class WHERE relname = ?;");

$rows->execute("_rserv_servers_");
if($rows->rows == 0) {

# List of slave servers
  $master->do("create table _RSERV_SERVERS_ (server serial, host text, post int4, dbase text)")
	|| die $master->errstr;

# List of replicated tables
  $master->do("create table _RSERV_TABLES_  (tname name, cname name, reloid oid, key int4)")
	|| die $master->errstr;

# Bookkeeping log for row replication
  $master->do("create table _RSERV_LOG_1_ (reloid oid, logid int4, logtime timestamp, deleted int4, key text)")
	|| die $master->errstr;

# This is to speedup trigger
  $master->do("create index _RSERV_LOG_1_INDX_REL_KEY_ on _RSERV_LOG_1_ (reloid, key)")
	|| die $master->errstr;

# This is to speedup lookup of updated tuples in PrepareSnapshot
  $master->do("create index _RSERV_LOG_1_INDX_REL_ID_ on _RSERV_LOG_1_ (reloid, logid)")
	|| die $master->errstr;

# Second log
  $master->do("create table _RSERV_LOG_2_ (reloid oid, logid int4, logtime timestamp, deleted int4, key text)")
	|| die $master->errstr;

# This is to speedup trigger
  $master->do("create index _RSERV_LOG_2_INDX_REL_KEY_ on _RSERV_LOG_2_ (reloid, key)")
	|| die $master->errstr;

# This is to speedup lookup of updated tuples in PrepareSnapshot
  $master->do("create index _RSERV_LOG_2_INDX_REL_ID_ on _RSERV_LOG_2_ (reloid, logid)")
	|| die $master->errstr;

# Sync point for each slave server
  $master->do("create table _RSERV_SYNC_ (server int4, syncid int4, synctime timestamp" .
                                          ", status int4, minid int4, maxid int4, active text)")
	|| die $master->errstr;

  $master->do("create index _RSERV_SYNC_INDX_SRV_ID_ on _RSERV_SYNC_ (server, syncid)")
	|| die $master->errstr;

# Sync point reference numbers
  $master->do("create sequence _rserv_sync_seq_")
	|| die $master->errstr;

# Active log id
  $master->do("create sequence _rserv_active_log_id_ MINVALUE 1 MAXVALUE 2")
	|| die $master->errstr;
  $master->do("select setval('_rserv_active_log_id_', 1)")
	|| die $master->errstr;

# Old log status
  $master->do("create sequence _rserv_old_log_status_ MINVALUE 0 MAXVALUE 2")
	|| die $master->errstr;
  $master->do("select setval('_rserv_old_log_status_', 0)")
	|| die $master->errstr;

}
$rows->finish();

# Let user know the master database setup is completed
if (!$quiet) {
  print "Master database setup completed\n\n";
}

# Display the parameters for the slave database
if(!$quiet) {
  print "Slave database\n";
  print "**************\n";
  print "Server   : ", $slaveserver, "\n";
  print "Port     : ", $slaveport, "\n";
  print "Database : ", $slavedb, "\n";
  print "Username : ", $slaveuser, "\n";
  if($slavepass ne "") {
    print "Password : ", $slavepass, "\n";
  }
  print "\n";
}

# Slave Tables
$slave->do("set transaction isolation level serializable")
	|| die $slave->errstr;

$rows = $slave->prepare("SELECT * FROM pg_class WHERE relname = ?;");

$rows->execute("_rserv_slave_tables_");
if($rows->rows == 0) {

  $slave->do("create table _RSERV_SLAVE_TABLES_ (tname name, cname name, reloid oid, key int4)")
	|| die $slave->errstr;

  $slave->do("create table _RSERV_SLAVE_SYNC_ (syncid int4, synctime timestamp)")
	|| die $slave->errstr;

}
$rows->finish();

# Commit the transactions and disconnect from the databases
$slave->commit();
$master->commit();
$functions->commit();
$slave->disconnect();
$master->disconnect();
$functions->disconnect();

# Notify user where things are up to, unless requested
if(!$quiet) {
  print "Slave database setup completed\n\n";
}

# Create the etc/replication.cfg file
system('cat @prefix@/templates/replication.cfg-template | \
        sed -e "s:_master_server_:'.$masterserver.':g" \
            -e "s:_master_port_:'.$masterport.':g" \
            -e "s:_master_user_:'.$masteruser.':g" \
            -e "s:_master_pass_:'.$masterpass.':g" \
            -e "s:_master_database_:'.$masterdb.':g" \
            -e "s:_slave_server_:'.$slaveserver.':g" \
            -e "s:_slave_port_:'.$slaveport.':g" \
            -e "s:_slave_user_:'.$slaveuser.':g" \
            -e "s:_slave_pass_:'.$slavepass.':g" \
            -e "s:_slave_database_:'.$slavedb.':g" > @prefix@/etc/replication.cfg');

# Create the bin/ers_setvars file
system('cat @prefix@/templates/ers_setvars-template | \
        sed -e "s:_master_server_:'.$masterserver.':g" \
            -e "s:_master_port_:'.$masterport.':g" \
            -e "s:_master_user_:'.$masteruser.':g" \
            -e "s:_master_pass_:'.$masterpass.':g" \
            -e "s:_master_database_:'.$masterdb.':g" \
            -e "s:_slave_server_:'.$slaveserver.':g" \
            -e "s:_slave_port_:'.$slaveport.':g" \
            -e "s:_slave_user_:'.$slaveuser.':g" \
            -e "s:_slave_pass_:'.$slavepass.':g" \
            -e "s:_slave_database_:'.$slavedb.':g" > @prefix@/bin/ers_setvars');
system('chmod 550 @prefix@/bin/ers_setvars');

# Notify user where things are up to, unless requested
if(!$quiet) {
  print "Configuration files created\n\n";
}

print "eRServer configuration complete\n\n";

exit(0);
