# -*- perl -*-
# ers_addslave
# 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;
use lib "@prefix@/lib";
use eRServer;

$| = 1;

$result = GetOptions("debug!", "quiet!", "help", "table=s",
                     "slaveserver=s", "slaveuser=s", "slavepass=s", "slavedb=s", "slaveport=s");

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

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

if( ! -f "@prefix@/etc/replication.cfg") {
  printf"
WARNING: @prefix@/etc/replication.cfg doesn't exist,
         which means that this server has not yet been
         configured\n\n";
  exit(1);
}

$replic		= &eRServer::ReadConfig();

my $quiet	= 1 if $opt_quiet;

my $slaves	= $replic->{'replic.master.ConnectionPoolSize'};
my $no_slaves	= $slaves + 1;
my $max_slaves	= $slaves + 2;

$masterserver	= (split(/:/, (split(/\//, $replic->{'replic.master.JDBCConnectionURL'}))[2]))[0];
$masterport	= (split(/:/, (split(/\//, $replic->{'replic.master.JDBCConnectionURL'}))[2]))[1];
$masterdb	= (split(/\//, $replic->{'replic.master.JDBCConnectionURL'}))[3];
$masteruser	= $replic->{'replic.master.user'};
$masterpass	= $replic->{'replic.master.password'};

my $slavedb     = $opt_slavedb     || (split(/\//, (split(/,/, $replic->{'replic.slave.JDBCConnectionURL'}))[0]))[3];  
my $slaveserver = $opt_slaveserver || (split(/:/, (split(/\//, (split(/,/, $replic->{'replic.slave.JDBCConnectionURL'}))[0]))[2]))[0];
my $slaveport   = $opt_slaveport   || (split(/:/, (split(/\//, (split(/,/, $replic->{'replic.slave.JDBCConnectionURL'}))[0]))[2]))[1];
my $slaveuser   = $opt_slaveuser   || (split(/,/, $replic->{'replic.slave.user'}))[0];                          
my $slavepass   = $opt_slavepass   || (split(/,/, $replic->{'replic.slave.password'}))[0];                           
chomp($slavedb);
chomp($slaveserver);
chomp($slaveuser);
chomp($slavepass);
chomp($slaveport);

# 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 "\nAdding new slave database...\n\n";
}

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;

# 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;

  open(IN, "@prefix@/etc/replication.cfg");
  open(OUT, ">@prefix@/etc/replication.cfg.n");
  while(<IN>) {
    chomp();
    if(/^replic.master.ConnectionPoolSize/) {
      print OUT "replic.master.ConnectionPoolSize=${no_slaves}\n";
    } elsif(/^replic.master.ConnectionPoolMax/) {
      print OUT "replic.master.ConnectionPoolMax=${max_slaves}\n";
    } elsif(/^replic.server.ReplicInterval/) {
      print OUT "$_,".(split(/,/, $replic->{'replic.server.ReplicInterval'}))[0]."\n";
    } elsif(/^replic.slave.JDBCDriver/) {
      print OUT "$_,".(split(/,/, $replic->{'replic.slave.JDBCDriver'}))[0]."\n";
    } elsif(/^replic.slave.ConnectionPoolSize/) {
      print OUT "$_,".(split(/,/, $replic->{'replic.slave.ConnectionPoolSize'}))[0]."\n";
    } elsif(/^replic.slave.ConnectionPoolMax/) {
      print OUT "$_,".(split(/,/, $replic->{'replic.slave.ConnectionPoolMax'}))[0]."\n";
    } elsif(/^replic.slave.ConnectionUseCount/) {
      print OUT "$_,".(split(/,/, $replic->{'replic.slave.ConnectionUseCount'}))[0]."\n";
    } elsif(/^replic.slave.ConnectionTimeout/) {
      print OUT "$_,".(split(/,/, $replic->{'replic.slave.ConnectionTimeout'}))[0]."\n";
    } elsif(/^replic.slave.JDBCConnectionURL/) {
      print OUT "$_,jdbc:postgresql://${slaveserver}:${slaveport}/${slavedb}\n";
    } elsif(/^replic.slave.user/) {
      print OUT "$_,${slaveuser}\n";
    } elsif(/^replic.slave.password/) {
      print OUT "$_,${slavepass}\n";
    } else {
      print OUT "$_\n";
    }
  }
  close(IN);
  close(OUT);

  system("mv @prefix@/etc/replication.cfg.n @prefix@/etc/replication.cfg");
}

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;

# Find out what tables need to be replicated
$rows = $master->prepare("SELECT tname FROM _rserv_tables_;");
$rows->execute();
if($rows->rows == 0) {
  $rows->finish();
  $slave->disconnect();
  $master->disconnect();

  # Let the user know where things are up to
  if(!$quiet) {
    print "The master database currently has no tables requiring replication\n\n";
    print "Slave database ${slavedb} not added\n\n";
  }
  exit(1);

} else {

  # Let the user know where things are up to
  if(!$quiet) {
    print "\nCopying all tables definitions from the master database to the new slave...\n\n";
  }

  $tbl_list = $rows->fetchall_arrayref({});
  $rows->finish();

  $tbl_exists = $slave->prepare("SELECT tname FROM _rserv_slave_tables_ WHERE tname = ?");
  foreach my $table (@$tbl_list) {
    if(!$quiet) {
      print "\tAdding ".${table}->{'tname'}." ...\n";
    }
    $tbl_exists->execute($table->{'tname'});
    if($tbl_exists->rows == 0) {
      &eRServer::CopyTbl($masteruser, $masterdb, $master, $slave, $table->{'tname'});
      $slave->commit;
    }
  }
}

# Close the connection to the slave database

$tbl_exists->finish();
$slave->disconnect();
$master->disconnect();

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

exit(0);
