David Fetter david
Sun Jun 20 02:25:59 PDT 2004
Kind people,

I've done some work on slony_setup.pl.  Here is my proposed patch.

What do y'all think?

Cheers,
D
-- 
David Fetter david at fetter.org http://fetter.org/
phone: +1 510 893 6100   mobile: +1 415 235 3778

Remember to vote!
-------------- next part --------------
? slony_setup.patch
Index: tools/slony_setup.pl
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/tools/slony_setup.pl,v
retrieving revision 1.7
diff -2 -c -r1.7 slony_setup.pl
*** tools/slony_setup.pl	18 Jun 2004 17:41:07 -0000	1.7
--- tools/slony_setup.pl	19 Jun 2004 17:28:06 -0000
***************
*** 27,31 ****
  
  Slony setup is intended to facilitate the installation of the slony
! replication engine. Basically it asks a bunch of questions and creates
  a shell (bash) script which can then be run on the master and also
  provides the commands to be run on slaves.
--- 27,31 ----
  
  Slony setup is intended to facilitate the installation of the slony
! replication engine.  Basically it asks a bunch of questions and creates
  a shell (bash) script which can then be run on the master and also
  provides the commands to be run on slaves.
***************
*** 34,45 ****
  with:
  
! 1. A postgres master host that needs replication.
  
! 2. N slaves hosts.
  
! 3. Every postgres host allows authenticated connections from all
  participating hosts over TCP/IP.
  
! 4. A "slony" postgres superuser and a "slony" system user on every
  participating host.
  
--- 34,45 ----
  with:
  
! 1.  A postgres master host that needs replication.
  
! 2.  N slaves hosts.
  
! 3.  Every postgres host allows authenticated connections from all
  participating hosts over TCP/IP.
  
! 4.  A "slony" postgres superuser and a "slony" system user on every
  participating host.
  
***************
*** 53,58 ****
  =head1 TODO
  
- Make the version check use psql -c 'select version ()'.
- 
  Add support for running all commands to slaves over ssh.
  
--- 53,56 ----
***************
*** 74,78 ****
  
  Add support for detecting errors in piped commands in the shell script.
! Sometimes a "pg_dump | psql" will generate errors on the psql side. These
  are not always fatal, but should be looked at.
  
--- 72,76 ----
  
  Add support for detecting errors in piped commands in the shell script.
! Sometimes a "pg_dump | psql" will generate errors on the psql side.  These
  are not always fatal, but should be looked at.
  
***************
*** 84,91 ****
  =head1 CHANGELOG
  
! 06-18-2004
  
  Prompt for "working target directory" where setup script and dump scripts
! are written by slony_setup.pl. This is also where the bash script and slon
  will write.
  Detect $TMP variables and use them if they're set.
--- 82,96 ----
  =head1 CHANGELOG
  
! 2004-06-18
! 
! Aesthetic/maintainability fixes: change subroutines to take anon
! hashes, use here docs.
! 
! by David Fetter
! 
! 2004-06-18
  
  Prompt for "working target directory" where setup script and dump scripts
! are written by slony_setup.pl.  This is also where the bash script and slon
  will write.
  Detect $TMP variables and use them if they're set.
***************
*** 93,97 ****
  More cosmetic fixes.
  
! 05-28-2004
  
  Added support for replicating sequences.
--- 98,102 ----
  More cosmetic fixes.
  
! 2004-05-28
  
  Added support for replicating sequences.
***************
*** 99,103 ****
  Fixed some cosmetic issues.
  
! 05-06-2004
  
  Initial CVS import
--- 104,108 ----
  Fixed some cosmetic issues.
  
! 2004-05-06
  
  Initial CVS import
***************
*** 105,109 ****
  =head1 AUTHOR
  
! Thoughts? Send them to Daniel Ceregatti (AKA Primer in #postgresql on
  irc.freenode.net) at vi at sh dot nu.
  
--- 110,114 ----
  =head1 AUTHOR
  
! Thoughts?  Send them to Daniel Ceregatti (AKA Primer in #postgresql on
  irc.freenode.net) at vi at sh dot nu.
  
***************
*** 112,116 ****
  use strict;
  eval {
! 	require Data::Dumper;
  };
  
--- 117,121 ----
  use strict;
  eval {
!     require Data::Dumper;
  };
  
***************
*** 123,154 ****
  $SIG{KILL} = \&clean_up;
  
! #
! # Print out usage for variations of "-h" and "?"
! #
  
  if ($ARGV[0] =~ m/-h|--h|\?/) {
! 	&pager ("
  usage: perl slony_setup.pl
  
! Run this as the user you plan to run slony. This script takes no
! arguments. Just run it.
  
! If you want to know more about it, then: perldoc ./slony_setup.pl
  
! ");
! 	exit -1;
  }
  
! #
! # Create a temporary working directory and set some variables
! #
  
  my $exitcode = -1;
! my $tmpbase = $ENV{"TMPDIR"} || $ENV{"TEMP"} || $ENV{"TMP"} || "/tmp";
  my $tmpdir = "$tmpbase/slony.$$";
! my $targetdir = $ENV{"HOME"} || $tmpbase;
! mkdir $tmpdir,0700 or &death ("Can't create temporary working directory: $!");
  
! my $pgpassfile = $ENV{"HOME"} . "/.pgpass";
  my $pgpassbackup = "$tmpdir/.pgpass.backup";
  my $slony_dump = "$targetdir/slony_dump";
--- 128,165 ----
  $SIG{KILL} = \&clean_up;
  
! ##################################################
! #                                                #
! # Print out usage for variations of "-h" and "?" #
! #                                                #
! ##################################################
  
  if ($ARGV[0] =~ m/-h|--h|\?/) {
!     print <<TEXT;
  usage: perl slony_setup.pl
  
! Run this as the user you plan to run slony.  For now, this script
! takes no arguments.  Just run it.
! 
! If you want to know more about it, run the following command:
  
! perldoc ./slony_setup.pl
  
! TEXT
!     exit -1;
  }
  
! ###############################################################
! #                                                             #
! # Create a temporary working directory and set some variables #
! #                                                             #
! ###############################################################
  
  my $exitcode = -1;
! my $tmpbase = $ENV{'TMPDIR'} || $ENV{'TEMP'} || $ENV{'TMP'} || "/tmp";
  my $tmpdir = "$tmpbase/slony.$$";
! my $targetdir = $ENV{'HOME'} || $tmpbase;
! mkdir $tmpdir,0700 or death(message => "Can't create temporary working directory: $!");
  
! my $pgpassfile = $ENV{'HOME'} . "/.pgpass";
  my $pgpassbackup = "$tmpdir/.pgpass.backup";
  my $slony_dump = "$targetdir/slony_dump";
***************
*** 158,183 ****
  my $errlog = "$targetdir/slon-DATABASENAME.err";
  
! #
! # Make sure we have the correct version
! #
  
! my $psql = "";
  
! my $ret = &check_version;
  
  if ($ret == 1) {
! 	print "\nYou must have PostgreSQL version 7.3 or greater to use slony\n\n";
! 	&clean_up;
! } elsif ($ret == 2) {
! 	print "\nThe psql executable was not found. PostgreSQL must be installed\n";
! 	print "and its executables should be in your PATH\n\n";
! 	&clean_up;
! }
  
! #
! # Print the README
! #
  
! my $text = qq (
  Slony setup will guide you through the process of setting up the slony-engine
  replication system.  Some presumptions will be made in order to keep this
--- 169,207 ----
  my $errlog = "$targetdir/slon-DATABASENAME.err";
  
! #########################################
! #                                       #
! # Make sure we have the correct version #
! #                                       #
! #########################################
  
! chomp(my $psql = `which psql`);
! my $pager = $ENV{'PAGER'} || 'less' || 'more';
  
! my $ret = check_version();
  
  if ($ret == 1) {
!     print <<TEXT;
! You must have PostgreSQL version 7.3 or greater to use Slony-I
  
! TEXT
!     clean_up();
! } elsif ($ret == 2) {
!     print <<'TEXT';
! The psql executable was not found.  PostgreSQL must be installed and
! its executables should be in your $PATH
! 
! TEXT
!     clean_up();
! } else {
!     # Keep going--we're OK.
! }
! 
! ####################
! #                  #
! # Print the README #
! #                  #
! ####################
  
! my $text = <<TEXT;
  Slony setup will guide you through the process of setting up the slony-engine
  replication system.  Some presumptions will be made in order to keep this
***************
*** 185,207 ****
  ridden.  Slony requires, and the install process presumes that:
  
! 1. Your master server listens on TCP/IP.
! 2. At least one slave listens on TCP/IP.
! 3. You have a "slony" postgres superuser (createuser -a -d -P slony) as well
     as a "slony" system user on all participating hosts.
! 4. Each host participating in replication allows every other host that is
     participating in the replication to connect and authenticate to postgres
     as the slony postgres user over TCP/IP.
! 5. Slony binaries have been installed on all participating hosts.
  
  Optional, but helpful:
  
! 1. The user that will run the slony processes on all hosts has remote ssh
     access from the host slony_setup.sh runs.
  
  You will be prompted for the following information:
  
! 1. The hostname of the master server.
! 2. The hostnames of slave servers.
! 3. Authentication credentials for all hosts.
  
  Once this information is obtained, the script will then check connectivity to
--- 209,231 ----
  ridden.  Slony requires, and the install process presumes that:
  
! 1.  Your master server listens on TCP/IP.
! 2.  At least one slave listens on TCP/IP.
! 3.  You have a "slony" postgres superuser (createuser -a -d -P slony) as well
     as a "slony" system user on all participating hosts.
! 4.  Each host participating in replication allows every other host that is
     participating in the replication to connect and authenticate to postgres
     as the slony postgres user over TCP/IP.
! 5.  Slony binaries have been installed on all participating hosts.
  
  Optional, but helpful:
  
! 1.  The user that will run the slony processes on all hosts has remote ssh
     access from the host slony_setup.sh runs.
  
  You will be prompted for the following information:
  
! 1.  The hostname of the master server.
! 2.  The hostnames of slave servers.
! 3.  Authentication credentials for all hosts.
  
  Once this information is obtained, the script will then check connectivity to
***************
*** 214,270 ****
  write a perl script to a file that can then be run to create the replication
  without running slony_setup.pl again.
! );
  
! &pager ($text);
  
  print "\nAre you ready to proceed? (Y|n) ";
! &clean_up if ! &get_one_bool;
! 
! #
! # Set the working directory
! #
  
! $text = qq(
! The working target directory is where this script will store files that it
! creates.  The working target directory is currently set to '$targetdir'. If this
! directory should not be used, you should answer "no" to the follwing question
! and input a new directory. This directory should be writable by the script.
! );
! 
! &pager ($text);
! 
! print "\nThe target directory is '$targetdir'. Is this OK? (Y/n)";
! if (!&get_one_bool) {
! 	$targetdir = "";
! 	while (!$targetdir) {
! 		print "\nEnter the full path to the working target directory: ";
! 		my $temp = <>;
! 		chomp ($temp);
! 		$targetdir = $temp if $temp;
! 		if (!$targetdir) {
! 			print "No target directory specified. Select another directory.\n";
! 			$targetdir = "";
! 		} elsif (! -d $targetdir) {
! 			print "The target directory '$targetdir' is not a directory. Select another directory.\n";
! 			$targetdir = "";
! 		} elsif (! -w $targetdir) {
! 			print "The target directory '$targetdir' is not writable. Select another directory.\n";
! 			$targetdir = "";
! 		}
! 	}
! 	print "\nThe target directory is now '$targetdir'.\n";
! }
! 
! #
! # Backup the ~/.pgpass, if it exists
! #
  
  if (-f $pgpassfile) {
! 	&backup_file ($pgpassfile, $pgpassbackup);
  }
  
! #
! # Check for a previous failed run and import that data
! #
  
  my %data;
--- 238,304 ----
  write a perl script to a file that can then be run to create the replication
  without running slony_setup.pl again.
! TEXT
  
! pager(text => $text);
  
  print "\nAre you ready to proceed? (Y|n) ";
! clean_up() if ! get_one_bool();
  
! #############################
! #                           #
! # Set the working directory #
! #                           #
! #############################
! 
! $text = <<TEXT;
! The working target directory is where this script will store files
! that it creates.  The working target directory is currently set to
! '$targetdir'.  If this directory should not be used, you should answer
! "no" to the follwing question and input a new directory.  This
! directory should be writable by the script.
! TEXT
! 
! pager(text => $text);
! 
! print "\nThe target directory is '$targetdir'.  Is this OK? (Y/n)";
! if (!get_one_bool()) {
!     $targetdir = "";
!     while (!$targetdir) {
!         print "\nEnter the full path to the working target directory: ";
!         my $temp = <>;
!         chomp ($temp);
!         $targetdir = $temp if $temp;
!         if (!$targetdir) {
!             print "No target directory specified.  Select another directory.\n";
!             $targetdir = "";
!         } elsif (! -d $targetdir) {
!             print "The target directory '$targetdir' is not a directory.  Select another directory.\n";
!             $targetdir = "";
!         } elsif (! -w $targetdir) {
!             print "The target directory '$targetdir' is not writable.  Select another directory.\n";
!             $targetdir = "";
!         }
!     }
!     print "\nThe target directory is now '$targetdir'.\n";
! }
! 
! #######################################
! #                                     #
! # Back up the ~/.pgpass, if it exists #
! #                                     #
! #######################################
  
  if (-f $pgpassfile) {
!     backup_file(
!       orig => $pgpassfile
!     , backup => $pgpassbackup
!     );
  }
  
! ########################################################
! #                                                      #
! # Check for a previous failed run and import that data #
! #                                                      #
! ########################################################
  
  my %data;
***************
*** 272,291 ****
  
  if (-f $slony_dump) {
! 	print "\nA previous instance of slony_setup data was detected.\n";
! 	print "Do you want to import this data? (Y|n) ";
! 	if (&get_one_bool) {
! 		open F, $slony_dump and do {
! 			my $text = join ('', <F>);
! 			close F;
! 			my $VAR1;
! 			eval $text;
! 			%data = %{$VAR1};
! 			$cache = 1;
! 		}
! 	}
! }
! 
! #
! # Other global variables
  
  my $which = "master";
--- 306,328 ----
  
  if (-f $slony_dump) {
!     print "\nA previous instance of slony_setup data was detected.\n";
!     print "Do you want to import this data? (Y|n) ";
!     if (get_one_bool()) {
!         open F, $slony_dump and do {
!             my $text = join ('', <F>);
!             close F;
!             my $VAR1;
!             eval $text;
!             %data = %{$VAR1};
!             $cache = 1;
!         }
!     }
! }
! 
! ##########################
! #                        #
! # Other global variables #
! #                        #
! ##########################
  
  my $which = "master";
***************
*** 294,342 ****
  my $same = 0;
  
! #
! # Loop until we get good connections
! #
  
  while (1) {
! 
! 	if ($same == 0 && ($cache == 0 || !$data{$which})) {
! 		$data{$which}{"hostname"} = "none";
! 		$data{$which}{"port"} = 5432;
! 		$data{$which}{"databasename"} = "template1";
! 		$data{$which}{"username"} = "slony";
! 		$data{$which}{"password"} = "";
! 		$same=1
! 	}
! 
! 	#
! 	# Ask the user about the master database
! 	#
! 
! 	&get_info ($which);
! 
! 	#
! 	# Test the connection
! 	#
! 
! 	$ret = &test_conn ($which);
! 
! 	#
! 	# Prompt the user to retry if the connection fails
! 	#
! 
! 	if ($ret != 0) {
! 		print "\n\nConnection to $which failed. Try again? (Answering NO will abort) (Y|n) ";
! 		&clean_up if ! &get_one_bool;
! 	} else {
! 		print "\n\n$which connection successfull\n";
! 		&get_databases ($which);
! 		$slavenumber++;
! 		$which = "slave_$slavenumber";
! 		$same = 0;
! 		if ($slavenumber > 1) {
! 			print "\nAdd another slave? (Y|n) ";
! 			last if (!&get_one_bool);
! 		}
! 	}
  }
  
--- 331,386 ----
  my $same = 0;
  
! #######################################
! #                                     #
! # Loop until we get good connections. #
! #                                     #
! #######################################
  
  while (1) {
!     if ($same == 0 && ($cache == 0 || !$data{$which})) {
!         $data{$which}{'hostname'} = "none";
!         $data{$which}{'port'} = 5432;
!         $data{$which}{'databasename'} = "template1";
!         $data{$which}{'username'} = "slony";
!         $data{$which}{'password'} = "";
!         $same=1
!     }
! 
!     ##########################################
!     #                                        #
!     # Ask the user about the master database #
!     #                                        #
!     ##########################################
! 
!     get_info(which => $which);
! 
!     #######################
!     #                     #
!     # Test the connection #
!     #                     #
!     #######################
! 
!     $ret = test_conn(which => $which);
! 
!     ####################################################
!     #                                                  #
!     # Prompt the user to retry if the connection fails #
!     #                                                  #
!     ####################################################
! 
!     if ($ret != 0) {
!         print "\n\nConnection to $which failed.  Try again? (Answering NO will abort) (Y|n) ";
!         clean_up() if ! get_one_bool();
!     } else {
!         print "\n\n$which connection successfull\n";
!         get_databases(which => $which);
!         $slavenumber++;
!         $which = "slave_$slavenumber";
!         $same = 0;
!         if ($slavenumber > 1) {
!             print "\nAdd another slave? (Y|n) ";
!             last if (!get_one_bool());
!         }
!     }
  }
  
***************
*** 351,407 ****
  #
  
! if (!&get_one_bool) {
! 	print "\nAdd databases to replication:\n";
! 	foreach my $database (keys %{$data{"master"}{"databases"}}) {
! 		print " Add $database? (Y|n) ";
! 		if (!&get_one_bool) {
! 			delete $data{"master"}{"databases"}{$database};
! 		}
! 	}
  }
  
  #
  # Loop over the databases and ask the user if all tables in the database
! # should be replicated. We ask this here because the user may want to
  # replicate all databases but not all tables.
  #
  
! foreach my $database (keys %{$data{"master"}{"databases"}}) {
! 	&get_tables ("master", $database);
! 	&get_sequences ("master", $database);
! 
! 	#
! 	# Loop over the tables and prompt for addition
! 	#
! 	
! 	print "\nShould all tables in the '$database' database be replicated?
  (Note: the script cannot guarantee the schema will be properly
   installed on slaves if you choose No) (Y|n) ";
! 	
! 	if (&get_one_bool) {
! 		$data{"master"}{"databases"}{$database}{"all_tables"} = 1;
! 	} else {
! 		print "\nAdd tables in database $database to replication:\n";
! 		foreach my $table (keys %{$data{"master"}{"databases"}{$database}{"tables"}}) {
! 			print " Add $database.$table? (Y|n) ";
! 			delete $data{"master"}{"databases"}{$database}{"tables"}{$table} if ! &get_one_bool;
! 		}
! 	}
! 
! 	#
! 	# Loop over the sequences and prompt for addition
! 	#
! 	
! 	print "\nShould all sequences in the '$database' database be replicated? (Y|n) ";
! 	
! 	if (&get_one_bool) {
! 		$data{"master"}{"databases"}{$database}{"all_sequences"} = 1;
! 	} else {
! 		print "\nAdd sequences in database $database to replication:\n";
! 		foreach my $sequence (keys %{$data{"master"}{"databases"}{$database}{"sequences"}}) {
! 			print " Add $sequence? (Y|n) ";
! 			delete $data{"master"}{"databases"}{$database}{"sequences"}{$sequence} if ! &get_one_bool;
! 		}
! 	}
  }
  
--- 395,451 ----
  #
  
! if (!get_one_bool()) {
!     print "\nAdd databases to replication:\n";
!     foreach my $database (keys %{$data{'master'}{'databases'}}) {
!         print " Add $database? (Y|n) ";
!         if (!get_one_bool()) {
!             delete $data{'master'}{'databases'}{$database};
!         }
!     }
  }
  
  #
  # Loop over the databases and ask the user if all tables in the database
! # should be replicated.  We ask this here because the user may want to
  # replicate all databases but not all tables.
  #
  
! foreach my $database (keys %{$data{'master'}{'databases'}}) {
!     get_tables(which => 'master', database => $database);
!     get_sequences(which => 'master', database => $database);
! 
!     #
!     # Loop over the tables and prompt for addition
!     #
!     
!     print "\nShould all tables in the '$database' database be replicated?
  (Note: the script cannot guarantee the schema will be properly
   installed on slaves if you choose No) (Y|n) ";
!     
!     if (get_one_bool()) {
!         $data{'master'}{'databases'}{$database}{'all_tables'} = 1;
!     } else {
!         print "\nAdd tables in database $database to replication:\n";
!         foreach my $table (keys %{$data{'master'}{'databases'}{$database}{'tables'}}) {
!             print " Add $database.$table? (Y|n) ";
!             delete $data{'master'}{'databases'}{$database}{'tables'}{$table} if ! get_one_bool();
!         }
!     }
! 
!     #
!     # Loop over the sequences and prompt for addition
!     #
!     
!     print "\nShould all sequences in the '$database' database be replicated? (Y|n) ";
!     
!     if (get_one_bool()) {
!         $data{'master'}{'databases'}{$database}{'all_sequences'} = 1;
!     } else {
!         print "\nAdd sequences in database $database to replication:\n";
!         foreach my $sequence (keys %{$data{'master'}{'databases'}{$database}{'sequences'}}) {
!             print " Add $sequence? (Y|n) ";
!             delete $data{'master'}{'databases'}{$database}{'sequences'}{$sequence} if ! get_one_bool();
!         }
!     }
  }
  
***************
*** 410,415 ****
  #
  
! foreach my $database (keys %{$data{"master"}{"databases"}}) {
! 	delete $data{"master"}{"databases"}{$database} if ! keys %{$data{"master"}{"databases"}{$database}{"tables"}};
  }
  
--- 454,459 ----
  #
  
! foreach my $database (keys %{$data{'master'}{'databases'}}) {
!     delete $data{'master'}{'databases'}{$database} if ! keys %{$data{'master'}{'databases'}{$database}{'tables'}};
  }
  
***************
*** 420,447 ****
  my $summary = "\n\nSummary:";
  
! for my $datum (keys %data) {
! 	
! 	$summary .= "
! 
! $datum Hostname: " . $data{$datum}{"hostname"} . "
! $datum Port:     " . $data{$datum}{"port"} . "
! $datum Username: " . $data{$datum}{"username"} . "
! $datum Password: VALIDATED";
  
  }
  
! foreach my $database (keys %{$data{"master"}{"databases"}}) {
! 	$summary .=  "\n\nThe following tables in database $database will be replicated:\n\n";
! 	foreach my $table (keys %{$data{"master"}{"databases"}{$database}{"tables"}}) {
! 		$summary .=  "    $table\n";
! 	}
! 	$summary .=  "\n\nThe following sequences in database $database will be replicated:\n\n";
! 	foreach my $sequence (keys %{$data{"master"}{"databases"}{$database}{"sequences"}}) {
! 		$summary .=  "    $sequence\n";
! 	}
! 	$summary .=  "\n";
  }
  
! &pager ($summary);
  
  print "Save? (Y|n) ";
--- 464,492 ----
  my $summary = "\n\nSummary:";
  
! foreach my $datum (keys %data) {
!     
!     $summary .= <<TEXT;
! $datum Hostname: $data{$datum}{'hostname'}
! $datum Port:     $data{$datum}{'port'}
! $datum Username: $data{$datum}{'username'}
! $datum Password: VALIDATED
! 
! TEXT
  
  }
  
! foreach my $database (keys %{$data{'master'}{'databases'}}) {
!     $summary .=  "\n\nThe following tables in database $database will be replicated:\n\n";
!     foreach my $table (keys %{$data{'master'}{'databases'}{$database}{'tables'}}) {
!         $summary .=  "    $table\n";
!     }
!     $summary .=  "\n\nThe following sequences in database $database will be replicated:\n\n";
!     foreach my $sequence (keys %{$data{'master'}{'databases'}{$database}{'sequences'}}) {
!         $summary .=  "    $sequence\n";
!     }
!     $summary .=  "\n";
  }
  
! pager(text => $summary);
  
  print "Save? (Y|n) ";
***************
*** 451,457 ****
  #
  
! &get_users ("master");
  
! &get_groups ("master");
  
  #
--- 496,502 ----
  #
  
! get_users("master");
  
! get_groups("master");
  
  #
***************
*** 460,537 ****
  
  foreach my $slave (keys %data) {
! 	next if $slave eq "master";
! 	$slave =~ m/slave_(\d+)/;
! 	$data{"slaves"}{$1} = $data{$slave};
! }
! 
! if (&get_one_bool) {
! 
! 	#
! 	# Make this a variable!! FIXME!!
! 	#
!   open F, ">$slony_master_setup" or death ("Can't open $slony_master_setup: $!");
! 	print F "#/bin/bash\n\n";
! 	
! 	#
! 	# Start by adding the complete uninstall option
! 	#
! 
! 	$data{"master"}{"coninfo"} = "'dbname=DATABASE_NAME_HOLDER host=" . $data{"master"}{"hostname"} .
! 		" port=" . $data{"master"}{"port"} .
! 		" user=" . $data{"master"}{"username"};
! 	$data{"master"}{"coninfo"} .= " password=" . $data{"master"}{"password"} if $data{"master"}{"password"} !~ /(\s+|\*)/;
! 	$data{"master"}{"coninfo"} .= "'";
! 
! 	my $all_conn = "slonik <<_EOF_ 2>> $setup_log 1>> $setup_log\n\tcluster name = T1;
! 	node 1 admin conninfo = " . $data{"master"}{"coninfo"} . ";\n";
! 
! 	foreach my $slave (sort keys %{$data{"slaves"}}) {
! 		$data{"slaves"}{$slave}{"coninfo"} = "'dbname=DATABASE_NAME_HOLDER host=" . $data{"slaves"}{$slave}{"hostname"} .
! 			" port=" . $data{"slaves"}{$slave}{"port"} .
! 			" user=" . $data{"slaves"}{$slave}{"username"};
! 		$data{"slaves"}{$slave}{"coninfo"} .= " password=" . $data{"slaves"}{$slave}{"password"} if $data{"slaves"}{$slave}{"password"} !~ /(\s+|\*)/;
! 		$data{"slaves"}{$slave}{"coninfo"} .= "'";
! 		$all_conn .= "\tnode " . ($slave + 1) . " admin conninfo = " . $data{"slaves"}{$slave}{"coninfo"} . ";\n";
! 	}
! 	
! 	print F "if [ x\$1 = \"xuninstall\" ]\nthen\n";
! 	
! 	foreach my $database (keys %{$data{"master"}{"databases"}}) {
! 		my $conn = $all_conn;
! 		$conn =~ s/DATABASE_NAME_HOLDER/$database/g;
! 		print F $conn . "\ttry {
! 		uninstall node (id = 1);
! 	}
! 	on error {
! 		echo 'Could not uninstall slony on node 1';
! 		exit -1;
! 	}
  ";
  
! 		foreach my $slave (sort keys %{$data{"slaves"}}) {
! 			print F "\ttry {
! 		uninstall node (id = " . ($slave + 1) . ");
! 	}
! 	on error {
! 		echo 'Could not uninstall Slony on node " . ($slave + 1) . "';
! 		exit -1;
! 	}
  ";
! 		}
! 	
! 		print F "\techo 'Slony successfully uninstalled on database $database';
  _EOF_
  
  if [ \$? -ne 0 ]
  then
! 	echo Errors were detected. Please review $setup_log.  Uninstall halted.
! 	exit -1
  fi
  
  ";
! 	
! 	}
  
! 	print F "exit 0
  fi
  
--- 505,582 ----
  
  foreach my $slave (keys %data) {
!     next if $slave eq "master";
!     $slave =~ m/slave_(\d+)/;
!     $data{'slaves'}{$1} = $data{$slave};
! }
! 
! if (get_one_bool()) {
! 
!     #
!     # Make this a variable!!  FIXME!!
!     #
!   open F, ">$slony_master_setup" or death( message => "Can't open $slony_master_setup: $!");
!     print F "#/bin/bash\n\n";
!     
!     #
!     # Start by adding the complete uninstall option
!     #
! 
!     $data{'master'}{'coninfo'} = "'dbname=DATABASE_NAME_HOLDER host=" . $data{'master'}{'hostname'} .
!         " port=" . $data{'master'}{'port'} .
!         " user=" . $data{'master'}{'username'};
!     $data{'master'}{'coninfo'} .= " password=" . $data{'master'}{'password'} if $data{'master'}{'password'} !~ /(\s+|\*)/;
!     $data{'master'}{'coninfo'} .= "'";
! 
!     my $all_conn = "slonik <<_EOF_ 2>> $setup_log 1>> $setup_log\n\tcluster name = T1;
!     node 1 admin conninfo = " . $data{'master'}{'coninfo'} . ";\n";
! 
!     foreach my $slave (sort keys %{$data{'slaves'}}) {
!         $data{'slaves'}{$slave}{'coninfo'} = "'dbname=DATABASE_NAME_HOLDER host=" . $data{'slaves'}{$slave}{'hostname'} .
!             " port=" . $data{'slaves'}{$slave}{'port'} .
!             " user=" . $data{'slaves'}{$slave}{'username'};
!         $data{'slaves'}{$slave}{'coninfo'} .= " password=" . $data{'slaves'}{$slave}{'password'} if $data{'slaves'}{$slave}{'password'} !~ /(\s+|\*)/;
!         $data{'slaves'}{$slave}{'coninfo'} .= "'";
!         $all_conn .= "\tnode " . ($slave + 1) . " admin conninfo = " . $data{'slaves'}{$slave}{'coninfo'} . ";\n";
!     }
!     
!     print F "if [ x\$1 = \"xuninstall\" ]\nthen\n";
!     
!     foreach my $database (keys %{$data{'master'}{'databases'}}) {
!         my $conn = $all_conn;
!         $conn =~ s/DATABASE_NAME_HOLDER/$database/g;
!         print F $conn . "\ttry {
!         uninstall node (id = 1);
!     }
!     on error {
!         echo 'Could not uninstall slony on node 1';
!         exit -1;
!     }
  ";
  
!         foreach my $slave (sort keys %{$data{'slaves'}}) {
!             print F "\ttry {
!         uninstall node (id = " . ($slave + 1) . ");
!     }
!     on error {
!         echo 'Could not uninstall Slony on node " . ($slave + 1) . "';
!         exit -1;
!     }
  ";
!         }
!     
!         print F "\techo 'Slony successfully uninstalled on database $database';
  _EOF_
  
  if [ \$? -ne 0 ]
  then
!     echo Errors were detected.  Please review $setup_log.  Uninstall halted.
!     exit -1
  fi
  
  ";
!     
!     }
  
!     print F "exit 0
  fi
  
***************
*** 541,855 ****
  ";
  
! 	#
! 	# Create the new ~/.pgpass
! 	#
! 	open FH, $pgpassfile or death ("Can't open $pgpassfile: $!");
! 	while (<FH>) {
! 		chomp;
! 		print F "echo \"$_\" >> ~/.pgpass\n";
! 	}
! 	close FH;
! 	print F "\nchmod 600 ~/.pgpass\n\n";
! 
! 	foreach my $slave (keys %{$data{"slaves"}}) {
! 		#
! 		# Create all the users that exist on the master database on each slave, except the
! 		# postgres and slony users
! 		#
! 		foreach my $user (sort keys %{$data{"master"}{"users"}}) {
! 			print F "$psql" .
! 				" -h " . $data{"slaves"}{$slave}{"hostname"} .
! 				" -p " . $data{"slaves"}{$slave}{"port"} .
! 				" -U " . $data{"slaves"}{$slave}{"username"} .
! 				" -d template1" .
! 				" -c \\\n\"insert into pg_shadow (usename, usesysid, usecreatedb, usesuper, usecatupd, passwd, valuntil, useconfig) values (\\\n" .
! 				"'" . $data{"master"}{"users"}{$user}{"usename"} . "'," .
! #				"'" . $data{"master"}{"users"}{$user}{"usesysid"} . "'," .
! 				"(select case when max (usesysid) + 1 < 100 then 100 else max (usesysid) + 1 end from pg_shadow),\\\n" .
! 				"'" . $data{"master"}{"users"}{$user}{"usecreatedb"} . "'," .
! 				"'" . $data{"master"}{"users"}{$user}{"usesuper"} . "'," .
! 				"'" . $data{"master"}{"users"}{$user}{"usecatupd"} . "'," .
! 				"'" . $data{"master"}{"users"}{$user}{"passwd"} . "'," .
! 				(($data{"master"}{"users"}{$user}{"valuntil"}) ? "'" . $data{"master"}{"users"}{$user}{"valuntil"} . "'": "null") . "," .
! 				(($data{"master"}{"users"}{$user}{"useconfig"}) ? "'" . $data{"master"}{"users"}{$user}{"useconfig"} . "'": "null") . ")\"" .
! 				" 2>> $setup_log 1>> $setup_log\n";
! 			print F "\nif [ \$? -ne 0 ]\n";
! 			print F "then\n";
! 			print F "\techo Errors were detected. Please review $setup_log and fix the errors.\n";
! 			print F "\texit -1\n";
! 			print F "fi\n\n";
! 		}
! 		#
! 		# Create all the groups that exist on the master database on each slave
! 		#
! 		foreach my $group (sort keys %{$data{"master"}{"groups"}}) {
! 			print F "$psql" .
! 				" -h " . $data{"slaves"}{$slave}{"hostname"} .
! 				" -p " . $data{"slaves"}{$slave}{"port"} .
! 				" -U " . $data{"slaves"}{$slave}{"username"} .
! 				" -d template1" .
! 				" -c \\\n\"insert into pg_group (groname, grosysid, grolist) values (\\\n" .
! 				"'" . $data{"master"}{"groups"}{$group}{"groname"} . "'," .
! 				"'" . $data{"master"}{"groups"}{$group}{"grosysid"} . "'," .
! 				"'" . $data{"master"}{"groups"}{$group}{"grolist"} . "')\"" .
! 				" 2>> $setup_log 1>> $setup_log\n";
! 			print F "\nif [ \$? -ne 0 ]\n";
! 			print F "then\n";
! 			print F "\techo Errors were detected. Please review $setup_log and fix the errors.\n";
! 			print F "\texit -1\n";
! 			print F "fi\n\n";
! 		}
! 		#
! 		# Make sure plpgsql is created in template1 on all slaves
! 		#
! 		print F "createlang" .
! 			" -h " . $data{"slaves"}{$slave}{"hostname"} .
! 			" -p " . $data{"slaves"}{$slave}{"port"} .
! 			" -U " . $data{"slaves"}{$slave}{"username"} .
! 			" plpgsql template1" .
! 			" 2>> $setup_log 1>> $setup_log\n";
! 		print F "\nif [ \$? -ne 0 ]\n";
! 		print F "then\n";
! 		print F "\techo Errors were detected. Please review $setup_log and fix the errors.\n";
! 		print F "\texit -1\n";
! 		print F "fi\n\n";
! 		foreach my $database (keys %{$data{"master"}{"databases"}}) {
! 			#
! 			# Create the databases to be replicated on all slaves
! 			#
! 			print F "createdb" .
! 				" -h " . $data{"slaves"}{$slave}{"hostname"} .
! 				" -p " . $data{"slaves"}{$slave}{"port"} .
! 				" -U " . $data{"slaves"}{$slave}{"username"} .
! 				" -O " . $data{"master"}{"databases"}{$database}{"owner"} .
! 				" $database 2>> $setup_log 1>> $setup_log\n";
! 			print F "\nif [ \$? -ne 0 ]\n";
! 			print F "then\n";
! 			print F "\techo Errors were detected. Please review $setup_log and fix the errors.\n";
! 			print F "\texit -1\n";
! 			print F "fi\n\n";
! 			#
! 			# Use the command that copies the entire schema at once, as this assures us
! 			# that dependencies will be done in order
! 			#
! 			if ($data{"master"}{"databases"}{$database}{"all_tables"} == 1) {
! 				print F "pg_dump" .
! 					" -h " . $data{"master"}{"hostname"} .
! 					" -p " . $data{"master"}{"port"} .
! 					" -U " . $data{"master"}{"username"} .
! 					" -s " . $database .
! 					" 2>> $setup_log | \\\n" .
! 					"psql" .
! 					" -h " . $data{"slaves"}{$slave}{"hostname"} .
! 					" -p " . $data{"slaves"}{$slave}{"port"} .
! 					" -U " . $data{"slaves"}{$slave}{"username"} .
! 					" -d " . $database .
! 					" 2>> $setup_log 1>> $setup_log\n";
! 				print F "\nif [ \$? -ne 0 ]\n";
! 				print F "then\n";
! 				print F "\techo Errors were detected. Please review $setup_log and fix the errors.\n";
! 				print F "\texit -1\n";
! 				print F "fi\n\n";
! 			#
! 			# Else, do it the hard way, and hope no dependencies are broken
! 			#
! 			} else {
! 				foreach my $table (keys %{$data{"master"}{"databases"}{$database}{"tables"}}) {
! 					my ($schema, $tablename) = split (/\./, $table);
! 					print F "pg_dump" .
! 						" -h " . $data{"master"}{"hostname"} .
! 						" -p " . $data{"master"}{"port"} .
! 						" -U " . $data{"master"}{"username"} .
! 						" -n " . $schema .
! 						" -t " . $tablename .
! 						" -s " . $database .
! 						" 2>> $setup_log | \\\n" .
! 						"psql" .
! 						" -h " . $data{"slaves"}{$slave}{"hostname"} .
! 						" -p " . $data{"slaves"}{$slave}{"port"} .
! 						" -U " . $data{"slaves"}{$slave}{"username"} .
! 						" -d " . $database .
! 						" 2>> $setup_log 1>> $setup_log\n";
! 					print F "\nif [ \$? -ne 0 ]\n";
! 					print F "then\n";
! 					print F "\techo Errors were detected. Please review $setup_log and fix the errors.\n";
! 					print F "\texit -1\n";
! 					print F "fi\n\n";
! 				}
! 			}
! 		}
! 	}
! 	
! 	foreach my $database (keys %{$data{"master"}{"databases"}}) {
! 		my $conn = $all_conn;
! 
! 		$conn =~ s/DATABASE_NAME_HOLDER/$database/g;
! 		
! 		print F "$conn\ttry {
! 		echo 'Initializing the cluster';
! 		init cluster (id = 1, comment = 'Node 1');
! 	}
! 	on error {
! 		echo 'Could not initialize the cluster!';
! 		exit -1;
! 	}
! 	echo 'Database cluster initialized as Node 1';";
! 
! 		foreach my $slave (sort keys %{$data{"slaves"}}) {
! 			print F "
! 	try {
! 		echo 'Storing node " . ($slave + 1) . "';
! 		store node (id = " . ($slave + 1) . ", comment = 'Node " . ($slave + 1) . "');
! 	}
! 	on error {
! 		echo 'Could not create node " . ($slave + 1) . "!';
! 		exit -1;
! 	}
! 	echo 'Node " . ($slave + 1) . " created';";
! 		}
! 
! 		print F "
! 	try {
! 		echo 'Creating store paths';\n";
! 		foreach my $slave (keys %{$data{"slaves"}}) {
! 			my $conn = $data{"master"}{"coninfo"};
! 			$conn =~ s/DATABASE_NAME_HOLDER/$database/g;
! 			print F "\t\tstore path (server = 1, client = " . ($slave + 1) . ", conninfo = " . $conn . ");\n";
! 		}
! 		
! 		foreach my $slave (keys %{$data{"slaves"}}) {
! 			my $conn = $data{"slaves"}{$slave}{"coninfo"};
! 			$conn =~ s/DATABASE_NAME_HOLDER/$database/g;
! 			print F "\t\tstore path (server = " . ($slave + 1) . ", client = 1, conninfo = " . $conn . ");\n";
! 			foreach my $subslave (keys %{$data{"slaves"}}) {
! 				next if $slave == $subslave;
! 				print F "\t\tstore path (server = " . ($slave + 1) . ", client = " . ($subslave + 1) . ", conninfo = " . $data{"slaves"}{$slave}{"coninfo"} . ");\n";
! 			}
! 		}
! 		print F "\t}
! 	on error {
! 		echo 'Could not create store paths!';
! 		exit -1;
! 	}
! 	echo 'Store paths created';
! 	try {
! 		echo 'Storing listen network';
  ";
  
! #<JanniCash> make it as I said. As long as you don't support cascading in your script,
! #	let the master listen on all slaves for their events (origin=that_slave, provider=that_slave, receiver=master)
  #<JanniCash> and let every slave listen for (origin=all_other_nodes, provider=master, receiver=slave)
  
! 		foreach my $slave (sort keys %{$data{"slaves"}}) {
! 			print F "\t\tstore listen (origin = 1, provider = 1, receiver = " . ($slave + 1) . ");\n";
! 		}
! 
! 		foreach my $slave (sort keys %{$data{"slaves"}}) {
! 			print F "\t\tstore listen (origin = " . ($slave + 1) . ", provider = " . ($slave + 1) . ", receiver = 1);\n";
! 			foreach my $subslave (sort keys %{$data{"slaves"}}) {
! 				next if $slave == $subslave;
! 				print F "\t\tstore listen (origin = " . ($subslave + 1) . ", provider = 1, receiver = " . ($slave + 1) . ");\n";
! 			}
! 		}
! 
! 		print F "\t}
! 	on error {
! 		echo 'Could not store listen network!';
! 		exit -1;
! 	}
! 	echo 'listen network stored';
! 	try {
! 		create set (id = 1, origin = 1, comment = '$database tables');
! 	}
! 	on error {
! 		echo 'Could not create subscription set!';
! 		exit -1;
! 	}
! 	echo 'Subscription set created';
! 	try {
! 		echo 'Adding tables to the subscription set';\n";
! 
! 		my $count = 1;
! 		foreach my $table (keys %{$data{"master"}{"databases"}{$database}{"tables"}}) {
! 			print F "
! 		echo '  Adding table $table...';
! 		set add table (set id = 1, origin = 1, id = $count, full qualified name = '$table', comment = 'Table $table');
! 		echo '    done';\n";
! 			$count++;
! 		}
! 
! 		$count = 1;
! 		
! 		print F "\n\t\techo 'Adding sequences to the subscription set';\n";
! 		
! 		foreach my $sequence (keys %{$data{"master"}{"databases"}{$database}{"sequences"}}) {
! 			print F "
! 		echo '  Adding sequence $sequence...';
! 		set add sequence (set id = 1, origin = 1, id = $count, full qualified name = '$sequence', comment = 'Sequence $sequence');
! 		echo '    done';\n";
! 			$count++;
! 		}
! 
! 		print F "
! 	}
! 	on error {
! 		echo 'Could not add tables and sequences!';
! 		exit -1;
! 	}
! 	echo 'All tables added';
  _EOF_
  
  if [ \$? -ne 0 ]
  then
! 	echo Errors were detected. Please review $setup_log and fix the errors.
! 	exit -1
  else
  ";
! 		my $command = "slon T1 dbname=$database 2> $errlog 1> $outlog &\n";
  
! 		$command =~ s/DATABASENAME/$database/g;
! 		
! 		$slave_commands .= $command;
! 		
! 		$command = "\t" . $command . "\techo slon has been started on the master and placed into the background. It is
! 	echo logging STDOUT to $outlog and STDERR to $errlog.
! 	echo
! 	echo Now start slon on all slaves by running the following command on all slaves as the
! 	echo slony system user:
! 	echo
! 	echo \"slon T1 dbname=$database 2> $errlog 1> $outlog &\"
! 	echo
! 	echo Once slon is running on all slaves, hit any key to proceed with the installation
! 	read -s -n1 a
! 	echo
  fi
  
  $conn
  ";
! 		
! 		$command =~ s/DATABASENAME/$database/g;
! 		print F $command . "\ttry {\n";
! 		foreach my $slave (sort keys %{$data{"slaves"}}) {
! 			print F "\t\tsubscribe set (id = 1, provider = 1, receiver = " . ($slave + 1) . ", forward = no);\n";
! 		}
! 		print F "\t}
! 	on error {
! 		echo 'Could not subscribe the set to the slaves';
! 		exit -1;
! 	}
! 	echo 'Database $database subscribed to slaves';
  _EOF_
  
  if [ \$? -ne 0 ]
  then
! 	echo Errors were detected. Please review $setup_log and fix the errors.
! 	exit -1
  fi\n";
! 		
! 	}
  }
  
  print F "
! echo The installation has succeeded. At this time the slaves should be receiving the data
  echo from the master.";
  
--- 586,898 ----
  ";
  
!     #
!     # Create the new ~/.pgpass
!     #
!     open FH, $pgpassfile or death( message => "Can't open $pgpassfile: $!");
!     while (<FH>) {
!         chomp;
!         print F "echo \"$_\" >> ~/.pgpass\n";
!     }
!     close FH;
!     print F "\nchmod 600 ~/.pgpass\n\n";
! 
!     foreach my $slave (keys %{$data{'slaves'}}) {
!         #
!         # Create all the users that exist on the master database on each slave, except the
!         # postgres and slony users
!         #
!         foreach my $user (sort keys %{$data{'master'}{'users'}}) {
!             print F "$psql" .
!                 " -h " . $data{'slaves'}{$slave}{'hostname'} .
!                 " -p " . $data{'slaves'}{$slave}{'port'} .
!                 " -U " . $data{'slaves'}{$slave}{'username'} .
!                 " -d template1" .
!                 " -c \\\n\"insert into pg_shadow (usename, usesysid, usecreatedb, usesuper, usecatupd, passwd, valuntil, useconfig) values (\\\n" .
!                 "'" . $data{'master'}{'users'}{$user}{'usename'} . "'," .
! #                "'" . $data{'master'}{'users'}{$user}{'usesysid'} . "'," .
!                 "(select case when max (usesysid) + 1 < 100 then 100 else max (usesysid) + 1 end from pg_shadow),\\\n" .
!                 "'" . $data{'master'}{'users'}{$user}{'usecreatedb'} . "'," .
!                 "'" . $data{'master'}{'users'}{$user}{'usesuper'} . "'," .
!                 "'" . $data{'master'}{'users'}{$user}{'usecatupd'} . "'," .
!                 "'" . $data{'master'}{'users'}{$user}{'passwd'} . "'," .
!                 (($data{'master'}{'users'}{$user}{'valuntil'}) ? "'" . $data{'master'}{'users'}{$user}{'valuntil'} . "'": "null") . "," .
!                 (($data{'master'}{'users'}{$user}{'useconfig'}) ? "'" . $data{'master'}{'users'}{$user}{'useconfig'} . "'": "null") . ")\"" .
!                 " 2>> $setup_log 1>> $setup_log\n";
!             print F "\nif [ \$? -ne 0 ]\n";
!             print F "then\n";
!             print F "\techo Errors were detected.  Please review $setup_log and fix the errors.\n";
!             print F "\texit -1\n";
!             print F "fi\n\n";
!         }
!         #
!         # Create all the groups that exist on the master database on each slave
!         #
!         foreach my $group (sort keys %{$data{'master'}{'groups'}}) {
!             print F "$psql" .
!                 " -h " . $data{'slaves'}{$slave}{'hostname'} .
!                 " -p " . $data{'slaves'}{$slave}{'port'} .
!                 " -U " . $data{'slaves'}{$slave}{'username'} .
!                 " -d template1" .
!                 " -c \\\n\"insert into pg_group (groname, grosysid, grolist) values (\\\n" .
!                 "'" . $data{'master'}{'groups'}{$group}{'groname'} . "'," .
!                 "'" . $data{'master'}{'groups'}{$group}{'grosysid'} . "'," .
!                 "'" . $data{'master'}{'groups'}{$group}{'grolist'} . "')\"" .
!                 " 2>> $setup_log 1>> $setup_log\n";
!             print F "\nif [ \$? -ne 0 ]\n";
!             print F "then\n";
!             print F "\techo Errors were detected.  Please review $setup_log and fix the errors.\n";
!             print F "\texit -1\n";
!             print F "fi\n\n";
!         }
!         #
!         # Make sure plpgsql is created in template1 on all slaves
!         #
!         print F "createlang" .
!             " -h " . $data{'slaves'}{$slave}{'hostname'} .
!             " -p " . $data{'slaves'}{$slave}{'port'} .
!             " -U " . $data{'slaves'}{$slave}{'username'} .
!             " plpgsql template1" .
!             " 2>> $setup_log 1>> $setup_log\n";
!         print F "\nif [ \$? -ne 0 ]\n";
!         print F "then\n";
!         print F "\techo Errors were detected.  Please review $setup_log and fix the errors.\n";
!         print F "\texit -1\n";
!         print F "fi\n\n";
!         foreach my $database (keys %{$data{'master'}{'databases'}}) {
!             #
!             # Create the databases to be replicated on all slaves
!             #
!             print F "createdb" .
!                 " -h " . $data{'slaves'}{$slave}{'hostname'} .
!                 " -p " . $data{'slaves'}{$slave}{'port'} .
!                 " -U " . $data{'slaves'}{$slave}{'username'} .
!                 " -O " . $data{'master'}{'databases'}{$database}{'owner'} .
!                 " $database 2>> $setup_log 1>> $setup_log\n";
!             print F "\nif [ \$? -ne 0 ]\n";
!             print F "then\n";
!             print F "\techo Errors were detected.  Please review $setup_log and fix the errors.\n";
!             print F "\texit -1\n";
!             print F "fi\n\n";
!             #
!             # Use the command that copies the entire schema at once, as this assures us
!             # that dependencies will be done in order
!             #
!             if ($data{'master'}{'databases'}{$database}{'all_tables'} == 1) {
!                 print F "pg_dump" .
!                     " -h " . $data{'master'}{'hostname'} .
!                     " -p " . $data{'master'}{'port'} .
!                     " -U " . $data{'master'}{'username'} .
!                     " -s " . $database .
!                     " 2>> $setup_log | \\\n" .
!                     "psql" .
!                     " -h " . $data{'slaves'}{$slave}{'hostname'} .
!                     " -p " . $data{'slaves'}{$slave}{'port'} .
!                     " -U " . $data{'slaves'}{$slave}{'username'} .
!                     " -d " . $database .
!                     " 2>> $setup_log 1>> $setup_log\n";
!                 print F "\nif [ \$? -ne 0 ]\n";
!                 print F "then\n";
!                 print F "\techo Errors were detected.  Please review $setup_log and fix the errors.\n";
!                 print F "\texit -1\n";
!                 print F "fi\n\n";
!             #
!             # Else, do it the hard way, and hope no dependencies are broken
!             #
!             } else {
!                 foreach my $table (keys %{$data{'master'}{'databases'}{$database}{'tables'}}) {
!                     my ($schema, $tablename) = split (/\./, $table);
!                     print F "pg_dump" .
!                         " -h " . $data{'master'}{'hostname'} .
!                         " -p " . $data{'master'}{'port'} .
!                         " -U " . $data{'master'}{'username'} .
!                         " -n " . $schema .
!                         " -t " . $tablename .
!                         " -s " . $database .
!                         " 2>> $setup_log | \\\n" .
!                         "psql" .
!                         " -h " . $data{'slaves'}{$slave}{'hostname'} .
!                         " -p " . $data{'slaves'}{$slave}{'port'} .
!                         " -U " . $data{'slaves'}{$slave}{'username'} .
!                         " -d " . $database .
!                         " 2>> $setup_log 1>> $setup_log\n";
!                     print F "\nif [ \$? -ne 0 ]\n";
!                     print F "then\n";
!                     print F "\techo Errors were detected.  Please review $setup_log and fix the errors.\n";
!                     print F "\texit -1\n";
!                     print F "fi\n\n";
!                 }
!             }
!         }
!     }
!     
!     foreach my $database (keys %{$data{'master'}{'databases'}}) {
!         my $conn = $all_conn;
!         $conn =~ s/DATABASE_NAME_HOLDER/$database/g;
!         print F "$conn\ttry {
!         echo 'Initializing the cluster';
!         init cluster (id = 1, comment = 'Node 1');
!     }
!     on error {
!         echo 'Could not initialize the cluster!';
!         exit -1;
!     }
!     echo 'Database cluster initialized as Node 1';";
! 
!         foreach my $slave (sort keys %{$data{'slaves'}}) {
!             print F "
!     try {
!         echo 'Storing node " . ($slave + 1) . "';
!         store node (id = " . ($slave + 1) . ", comment = 'Node " . ($slave + 1) . "');
!     }
!     on error {
!         echo 'Could not create node " . ($slave + 1) . "!';
!         exit -1;
!     }
!     echo 'Node " . ($slave + 1) . " created';";
!         }
! 
!         print F "
!     try {
!         echo 'Creating store paths';\n";
!         foreach my $slave (keys %{$data{'slaves'}}) {
!             my $conn = $data{'master'}{'coninfo'};
!             $conn =~ s/DATABASE_NAME_HOLDER/$database/g;
!             print F "\t\tstore path (server = 1, client = " . ($slave + 1) . ", conninfo = " . $conn . ");\n";
!         }
!         
!         foreach my $slave (keys %{$data{'slaves'}}) {
!             my $conn = $data{'slaves'}{$slave}{'coninfo'};
!             $conn =~ s/DATABASE_NAME_HOLDER/$database/g;
!             print F "\t\tstore path (server = " . ($slave + 1) . ", client = 1, conninfo = " . $conn . ");\n";
!             foreach my $subslave (keys %{$data{'slaves'}}) {
!                 next if $slave == $subslave;
!                 print F "\t\tstore path (server = " . ($slave + 1) . ", client = " . ($subslave + 1) . ", conninfo = " . $data{'slaves'}{$slave}{'coninfo'} . ");\n";
!             }
!         }
!         print F "\t}
!     on error {
!         echo 'Could not create store paths!';
!         exit -1;
!     }
!     echo 'Store paths created';
!     try {
!         echo 'Storing listen network';
  ";
  
! #<JanniCash> make it as I said.  As long as you don't support cascading in your script,
! #    let the master listen on all slaves for their events (origin=that_slave, provider=that_slave, receiver=master)
  #<JanniCash> and let every slave listen for (origin=all_other_nodes, provider=master, receiver=slave)
  
!         foreach my $slave (sort keys %{$data{'slaves'}}) {
!             print F "\t\tstore listen (origin = 1, provider = 1, receiver = " . ($slave + 1) . ");\n";
!         }
! 
!         foreach my $slave (sort keys %{$data{'slaves'}}) {
!             print F "\t\tstore listen (origin = " . ($slave + 1) . ", provider = " . ($slave + 1) . ", receiver = 1);\n";
!             foreach my $subslave (sort keys %{$data{'slaves'}}) {
!                 next if $slave == $subslave;
!                 print F "\t\tstore listen (origin = " . ($subslave + 1) . ", provider = 1, receiver = " . ($slave + 1) . ");\n";
!             }
!         }
! 
!         print F "\t}
!     on error {
!         echo 'Could not store listen network!';
!         exit -1;
!     }
!     echo 'listen network stored';
!     try {
!         create set (id = 1, origin = 1, comment = '$database tables');
!     }
!     on error {
!         echo 'Could not create subscription set!';
!         exit -1;
!     }
!     echo 'Subscription set created';
!     try {
!         echo 'Adding tables to the subscription set';\n";
! 
!         my $count = 1;
!         foreach my $table (keys %{$data{'master'}{'databases'}{$database}{'tables'}}) {
!             print F "
!         echo '  Adding table $table...';
!         set add table (set id = 1, origin = 1, id = $count, full qualified name = '$table', comment = 'Table $table');
!         echo '    done';\n";
!             $count++;
!         }
! 
!         $count = 1;
!         
!         print F "\n\t\techo 'Adding sequences to the subscription set';\n";
!         
!         foreach my $sequence (keys %{$data{'master'}{'databases'}{$database}{'sequences'}}) {
!             print F "
!         echo '  Adding sequence $sequence...';
!         set add sequence (set id = 1, origin = 1, id = $count, full qualified name = '$sequence', comment = 'Sequence $sequence');
!         echo '    done';\n";
!             $count++;
!         }
! 
!         print F "
!     }
!     on error {
!         echo 'Could not add tables and sequences!';
!         exit -1;
!     }
!     echo 'All tables added';
  _EOF_
  
  if [ \$? -ne 0 ]
  then
!     echo Errors were detected.  Please review $setup_log and fix the errors.
!     exit -1
  else
  ";
!         my $command = "slon T1 dbname=$database 2> $errlog 1> $outlog &\n";
  
!         $command =~ s/DATABASENAME/$database/g;
!         
!         $slave_commands .= $command;
!         
!         $command = "\t" . $command . "\techo slon has been started on the master and placed into the background.  It is
!     echo logging STDOUT to $outlog and STDERR to $errlog.
!     echo
!     echo Now start slon on all slaves by running the following command on all slaves as the
!     echo slony system user:
!     echo
!     echo \"slon T1 dbname=$database 2> $errlog 1> $outlog &\"
!     echo
!     echo Once slon is running on all slaves, hit any key to proceed with the installation
!     read -s -n1 a
!     echo
  fi
  
  $conn
  ";
!         
!         $command =~ s/DATABASENAME/$database/g;
!         print F $command . "\ttry {\n";
!         foreach my $slave (sort keys %{$data{'slaves'}}) {
!             print F "\t\tsubscribe set (id = 1, provider = 1, receiver = " . ($slave + 1) . ", forward = no);\n";
!         }
!         print F "\t}
!     on error {
!         echo 'Could not subscribe the set to the slaves';
!         exit -1;
!     }
!     echo 'Database $database subscribed to slaves';
  _EOF_
  
  if [ \$? -ne 0 ]
  then
!     echo Errors were detected.  Please review $setup_log and fix the errors.
!     exit -1
  fi\n";
!         
!     }
  }
  
  print F "
! echo The installation has succeeded.  At this time the slaves should be receiving the data
  echo from the master.";
  
***************
*** 862,866 ****
  
  Additionally, a data dump of all data collected by this script has been stored
! in the file '$slony_dump'. You might want to save this file if you want to
  run this script again with many of the same values.  A subsequent run of
  slony_setup.pl looks for the dumpfile in the working target directory.  This dump
--- 905,909 ----
  
  Additionally, a data dump of all data collected by this script has been stored
! in the file '$slony_dump'.  You might want to save this file if you want to
  run this script again with many of the same values.  A subsequent run of
  slony_setup.pl looks for the dumpfile in the working target directory.  This dump
***************
*** 876,880 ****
  ";
  
! &pager ($end);
  
  #
--- 919,923 ----
  ";
  
! pager(text => $end);
  
  #
***************
*** 882,886 ****
  #
  
! &dump_to_file;
  
  #
--- 925,929 ----
  #
  
! dump_to_file();
  
  #
***************
*** 889,1174 ****
  
  $exitcode = 0;
! &clean_up;
! 
! #
! # Functions
! #
  
! sub pager () {
! 	my $text = shift;
! 	my $pager = $ENV{"PAGER"} || 'less' || 'more';
! 	open P, "| $pager" or &death ("Can't open pipe to $pager: $!");
! 	print P $text . "\n[This is the pager '$pager'. Press 'q' to exit]\n";
! 	close P;
! }
! 	
! sub check_version () {
! 	my $pgversion_major = 0;
! 	my $pgversion_minor = 0;
! 	$psql = `which psql`;
! 	chomp ($psql);
! 	if (-x $psql) {
! 		open P, "$psql --version |";
! 		while (<P>) {
! 			$_ =~ m/\s+(\d+)\.(\d+)((\w+)||(\.(\d+)))?\s+/;
! 			$pgversion_major = $1;
! 			$pgversion_minor = $2;
! 		}
! 		close P;
! 		if ($pgversion_major == 7 && $pgversion_minor >= 3) {
! 			return 0;
! 		} else {
! 			return 1
! 		}
! 	}
! 	return 2;
! }
! 
! sub get_info () {
! 
! 	my $which = shift;
! 	print "\n";
! 	
! 	print "Enter the hostname or IP address of the $which database (" . $data{$which}{"hostname"} . "): ";
! 	my $temp = <>;
! 	chomp ($temp);
! 	$data{$which}{"hostname"} = $temp if $temp;
! 	
! 	print "Enter the port address of the $which database (" . $data{$which}{"port"} . "): ";
! 	$temp = <>;
! 	chomp ($temp);
! 	$data{$which}{"port"} = $temp if $temp;
! 	
! 	print "Enter the username of the $which database (" . $data{$which}{"username"} . "): ";
! 	$temp = <>;
! 	chomp ($temp);
! 	$data{$which}{"username"} = $temp if $temp;
! 	
! 	system "stty -echo";
! 	if ($data{$which}{"password"}) {
! 		print "Enter the password (A password is cached. Hit enter to use it): ";
! 	} else {
! 		print "Enter the password: ";
! 	}
! 	$temp = <>;
! 	chomp ($temp);
! 	system "stty echo";
! 	$data{$which}{"password"} = $temp if $temp;
! 	
! 	my $pgpass =
! 		$data{$which}{"hostname"} . ":" .
! 		$data{$which}{"port"} . ":" .
! 		"*" . ":" .
! 		$data{$which}{"username"} . ":" .
! 		$data{$which}{"password"} . "\n";
! 	open F, ">>$pgpassfile" or &death ("Can't open file $pgpassfile: $!");
! 	print F $pgpass;
! 	close F;
! 	chmod 0600, $pgpassfile or &death ("Unable to chmod 600 $pgpassfile");
! }
! 
! sub get_databases () {
! 	my $which = shift;
! 	open P, "$psql -h " . $data{$which}{"hostname"} .
! 		" -p " . $data{$which}{"port"} .
! 		" -U " . $data{$which}{"username"} .
! 		" -d template1" .
! 		" -t -l |"
! 		|| &death ("Can't open pipe to $psql: $!");
! 	while (<P>) {
! 		$_ =~ m/\s+(\S+)\s+\|\s+(\S+)\s+\|\s+(\S+)\s+/;
! 		next if ! $3;
! 		my $name = $1;
! 		my $owner = $2;
! 		my $encoding = $3;
! 		if ($name !~ m/^template(0|1)$/) {
! 			$data{$which}{"databases"}{$name}{"owner"} = $owner;
! 		}
! 	}
! 	close P;
! }
! 
! sub get_tables () {
! 	my ($which, $database) = @_;
! 	open P, "$psql -h " . $data{$which}{"hostname"} .
! 		" -p " . $data{$which}{"port"} .
! 		" -U " . $data{$which}{"username"} .
! 		" -d $database " .
! 		" -t" .
! 		" -c " . qq("select "pg_catalog".quote_ident(schemaname), "pg_catalog".quote_ident(tablename), "pg_catalog".quote_ident(tableowner) from pg_tables where schemaname not in ('information_schema', 'pg_catalog')") . " |"
! 		|| &death ("Can't open pipe to $psql: $!");
! 	while (<P>) {
! 		$_ =~ m/\s+(\S+)\s+\|\s+(\S+)\s+\|\s+(\S+)\s+/;
! 		my $schema = $1;
! 		my $table = $2;
! 		my $owner = $3;
! 		$data{$which}{"databases"}{$database}{"tables"}{$schema . "." . $table} = 1;
! 	}
! 	close P;
! }
! 
! sub get_sequences () {
! 	my ($which, $database) = @_;
! 	open P, "$psql -h " . $data{$which}{"hostname"} .
! 		" -p " . $data{$which}{"port"} .
! 		" -U " . $data{$which}{"username"} .
! 		" -d $database " .
! 		" -t" .
! 		" -c " . qq("select "pg_catalog".quote_ident(nspname) || '.' || "pg_catalog".quote_ident(relname) from pg_class c, pg_namespace n where c.relnamespace = n.oid and c.relkind = 'S'") . " |"
! 		|| &death ("Can't open pipe to $psql: $!");
! 	while (<P>) {
! 		$_ =~ m/\s+(\S+)\s+/;
! 		my $sequence_name = $1;
! 		$data{$which}{"databases"}{$database}{"sequences"}{$sequence_name} = 1;
! 	}
! 	close P;
! }
! 
! sub get_users () {
! 	my $which = shift;
! 	open P, "$psql -h " . $data{$which}{"hostname"} .
! 		" -p " . $data{$which}{"port"} .
! 		" -U " . $data{$which}{"username"} .
! 		" -d template1 " .
! 		" -t" .
! 		" -c 'select * from pg_shadow' |"
! 		|| &death ("Can't open pipe to $psql: $!");
! 	while (<P>) {
! 		$_ =~ m/\s+(\S*)\s+\|\s+(\S*)\s+\|\s+(\S*)\s+\|\s+(\S*)\s+\|\s+(\S*)\s+\|\s+(\S*)\s+\|\s+(\S*)\s+\|\s+(\S*)$/;
! 		my $usename = $1;
! 		my $usesysid = $2;
! 		my $usecreatedb = $3;
! 		my $usesuper = $4;
! 		my $usecatupd = $5;
! 		my $passwd = $6;
! 		my $valuntil = $7;
! 		my $useconfig = $8;
! 		if ($usename && $usename !~ m/^(postgres|slony)$/) {
! 			$data{$which}{"users"}{$usesysid}{"usename"} = $usename;
! 			$data{$which}{"users"}{$usesysid}{"usesysid"} = $usesysid;
! 			$data{$which}{"users"}{$usesysid}{"usecreatedb"} = $usecreatedb;
! 			$data{$which}{"users"}{$usesysid}{"usesuper"} = $usesuper;
! 			$data{$which}{"users"}{$usesysid}{"usecatupd"} = $usecatupd;
! 			$data{$which}{"users"}{$usesysid}{"passwd"} = $passwd;
! 			$data{$which}{"users"}{$usesysid}{"valuntil"} = $valuntil;
! 			$data{$which}{"users"}{$usesysid}{"useconfig"} = $useconfig;
! 		}
! 	}
! 	close P;
! }
! 
! sub get_groups () {
! 	my $which = shift;
! 	open P, "$psql -h " . $data{$which}{"hostname"} .
! 		" -p " . $data{$which}{"port"} .
! 		" -U " . $data{$which}{"username"} .
! 		" -d template1 " .
! 		" -t" .
! 		" -c 'select * from pg_group' |"
! 		|| &death ("Can't open pipe to $psql: $!");
! 	while (<P>) {
! 		$_ =~ m/\s+(\S*)\s+\|\s+(\S*)\s+\|\s+(\S*)$/;
! 		my $groname = $1;
! 		my $grosysid = $2;
! 		my $grolist = $3;
! 		if ($groname) {
! 			$data{$which}{"groups"}{$grosysid}{"groname"} = $groname;
! 			$data{$which}{"groups"}{$grosysid}{"grosysid"} = $grosysid;
! 			$data{$which}{"groups"}{$grosysid}{"grolist"} = $grolist;
! 		}
! 	}
! 	close P;
! }
! 
! sub test_conn () {
! 	my $which = shift;
! 	my $ret = system "$psql -h " . $data{$which}{"hostname"} .
! 		" -p " . $data{$which}{"port"} .
! 		" -U " . $data{$which}{"username"} .
! 		" -d template1" .
! 		" -t" .
! 		" -c 'select current_timestamp' 1> $tmpdir/testpgconn 2> /dev/null";
! 	if ($ret != 0) {
! 		# Remove the failed attempt from ~/.pgpass
! 		open F, "$pgpassfile" || death ("Can't open $pgpassfile: $!");
! 		my @lines = <F>;
! 		close F;
! 		pop @lines;
! 		open F, ">$pgpassfile" || death ("Can't open $pgpassfile: $!");
! 		print F @lines;
! 		close F;
! 		return -1;
! 	}
    return 0;
  }
  
  sub get_one {
! 	my $temp;
! 	system "stty -echo";
! 	system "stty raw";
! 	sysread STDIN, $temp, 1;
! 	system "stty sane";
! 	system "stty echo";
! 	return $temp;
  }
  
  sub get_one_bool {
! 	my $temp = &get_one;
! 	if ($temp =~ m/n/i) {
! 		print "N\n";
! 		return 0;
! 	} else {
! 		print "Y\n";
! 		return 1;
! 	}
  }
  
  sub dump_to_file {
! 	return if ! $dumper;
! 	open F, ">$slony_dump" or &death ("Can't open $slony_dump: $!");
! 	foreach my $host (keys %data) {
! 		delete $data{$host}{"databases"};
! 		delete $data{$host}{"users"};
! 		delete $data{$host}{"groups"};
! 		delete $data{$host}{"coninfo"};
! 	}
! 	delete $data{"slaves"};
! 	print F Data::Dumper::Dumper (\%data);
! 	close F;
! 	chmod 0600, $slony_dump;
  }
  
  sub backup_file {
! 	my $orig = shift;
! 	my $backup = shift;
! 	open F, $orig or &death ("Count not open $orig: $!");
! 	open FH, ">$backup" or &death ("Count not open $backup: $!");
! 	while (<F>) {
! 		print FH $_;
! 	}
! 	close FH;
! 	close F;
! 	unlink $orig or &death ("Cannot unlink $orig: $!");
! }
! 
! sub clean_up () {
! 	print "\n\nCleaning up\n";
! 	unlink $pgpassfile;
! 	if (-f $pgpassbackup) {
! 		print "Restoring previous $pgpassfile\n";
! 		&backup_file ($pgpassbackup, $pgpassfile);
! 	}
! 	if (-d $tmpdir) {
! 		print "Removing temporary directory\n";
! 		`rm -rf $tmpdir`;
! 	}
! 	print "\n";
! 	system "stty echo";
! 	exit $exitcode;
  }
  
  sub death {
! 	my $message = shift;
! 	print "$message\n";
! 	&clean_up;
  }
--- 932,1231 ----
  
  $exitcode = 0;
! clean_up();
  
! #############
! #           #
! # Functions #
! #           #
! #############
! 
! sub pager {
!     my %params = (
!       text => undef
!     , @_
!     );
!     open P, "| $pager" or death( message => "Can't open pipe to $pager: $!");
!     print P "$params{'text'}\n[This is the pager '$pager'.  Press 'q' to exit]\n";
!     close P;
! }
!     
! sub check_version {
!     if (-x $psql) {
!         my ($major, $minor) = `$psql -t -c 'select version()' template1` =~ /postgresql\s+(\d+)\.(\d+)/i;
!         if ($major >= 7 && $minor >= 3) {
!             return 0;
!         } else {
!             return 1
!         }
!     }
!     return 2;
! }
! 
! sub get_info {
!     my %params = (
!       which => undef
!     , @_
!     );
!     print "Enter the hostname or IP address of the $params{'which'} database ($data{$params{'which'}}{'hostname'}): ";
!     my $temp = <>;
!     chomp ($temp);
!     $data{$params{'which'}}{'hostname'} = $temp if $temp;
!     
!     print "Enter the port address of the $params{'which'} database ($data{$params{'which'}}{'port'}): ";
!     $temp = <>;
!     chomp ($temp);
!     $data{$params{'which'}}{'port'} = $temp if $temp;
!     
!     print "Enter the username of the $params{'which'} database (" . $data{$params{'which'}}{'username'} . "): ";
!     $temp = <>;
!     chomp ($temp);
!     $data{$params{'which'}}{'username'} = $temp if $temp;
!     
!     system "stty -echo";
!     if ($data{$params{'which'}}{'password'}) {
!         print "Enter the password (A password is cached.  Hit enter to use it): ";
!     } else {
!         print "Enter the password: ";
!     }
!     $temp = <>;
!     chomp ($temp);
!     system "stty echo";
!     $data{$params{'which'}}{'password'} = $temp if $temp;
!     
!     my $pgpass =
!         $data{$params{'which'}}{'hostname'} . ":" .
!         $data{$params{'which'}}{'port'} . ":" .
!         "*" . ":" .
!         $data{$params{'which'}}{'username'} . ":" .
!         $data{$params{'which'}}{'password'} . "\n";
!     open F, ">>$pgpassfile" or death( message => "Can't open file $pgpassfile: $!");
!     print F $pgpass;
!     close F;
!     chmod 0600, $pgpassfile or death( message => "Unable to chmod 600 $pgpassfile");
! }
! 
! sub get_databases {
!     my %params = (
!       which => undef
!     , @_
!     );
!     open P, "$psql -h " . $data{$params{'which'}}{'hostname'} .
!         " -p " . $data{$params{'which'}}{'port'} .
!         " -U " . $data{$params{'which'}}{'username'} .
!         " -d template1" .
!         " -t -l |"
!         || death( message => "Can't open pipe to $psql: $!");
!     while (<P>) {
!         $_ =~ m/\s+(\S+)\s+\|\s+(\S+)\s+\|\s+(\S+)\s+/;
!         next if ! $3;
!         my $name = $1;
!         my $owner = $2;
!         my $encoding = $3;
!         if ($name !~ m/^template(0|1)$/) {
!             $data{$params{'which'}}{'databases'}{$name}{'owner'} = $owner;
!         }
!     }
!     close P;
! }
! 
! sub get_tables {
!     my %params = (
!       which => undef
!     , database => undef
!     , @_
!     );
!     open P, "$psql -h " . $data{$params{'which'}}{'hostname'} .
!         " -p " . $data{$params{'which'}}{'port'} .
!         " -U " . $data{$params{'which'}}{'username'} .
!         " -d $params{'database'} " .
!         " -t" .
!         " -c " . qq("select "pg_catalog".quote_ident(schemaname), "pg_catalog".quote_ident(tablename), "pg_catalog".quote_ident(tableowner) from pg_tables where schemaname not in ('information_schema', 'pg_catalog')") . " |"
!         || death( message => "Can't open pipe to $psql: $!");
!     while (<P>) {
!         my ($schema, $table, $owner) = $_ =~ m/\s+(\S+)\s+\|\s+(\S+)\s+\|\s+(\S+)\s+/;
!         $data{$params{'which'}}{'databases'}{$params{'database'}}{'tables'}{$schema . "." . $table} = 1;
!     }
!     close P;
! }
! 
! sub get_sequences {
!     my %params = (
!       which => undef
!     , database => undef
!     , @_
!     );
!     open P, "$psql -h " . $data{$params{'which'}}{'hostname'} .
!         " -p " . $data{$params{'which'}}{'port'} .
!         " -U " . $data{$params{'which'}}{'username'} .
!         " -d $params{'database'} " .
!         " -t" .
!         " -c " . qq("select "pg_catalog".quote_ident(nspname) || '.' || "pg_catalog".quote_ident(relname) from pg_class c, pg_namespace n where c.relnamespace = n.oid and c.relkind = 'S'") . " |"
!         || death( message => "Can't open pipe to $psql: $!");
!     while (<P>) {
!         $_ =~ m/\s+(\S+)\s+/;
!         my $sequence_name = $1;
!         $data{$params{'which'}}{'databases'}{$params{'database'}}{'sequences'}{$sequence_name} = 1;
!     }
!     close P;
! }
! 
! sub get_users {
!     my $which = shift;
!     open P, "$psql -h " . $data{$which}{'hostname'} .
!         " -p " . $data{$which}{'port'} .
!         " -U " . $data{$which}{'username'} .
!         " -d template1 " .
!         " -t" .
!         " -c 'select * from pg_shadow' |"
!         || death( message => "Can't open pipe to $psql: $!");
!     while (<P>) {
!         $_ =~ m/\s+(\S*)\s+\|\s+(\S*)\s+\|\s+(\S*)\s+\|\s+(\S*)\s+\|\s+(\S*)\s+\|\s+(\S*)\s+\|\s+(\S*)\s+\|\s+(\S*)$/;
!         my $usename = $1;
!         my $usesysid = $2;
!         my $usecreatedb = $3;
!         my $usesuper = $4;
!         my $usecatupd = $5;
!         my $passwd = $6;
!         my $valuntil = $7;
!         my $useconfig = $8;
!         if ($usename && $usename !~ m/^(postgres|slony)$/) {
!             $data{$which}{'users'}{$usesysid}{'usename'} = $usename;
!             $data{$which}{'users'}{$usesysid}{'usesysid'} = $usesysid;
!             $data{$which}{'users'}{$usesysid}{'usecreatedb'} = $usecreatedb;
!             $data{$which}{'users'}{$usesysid}{'usesuper'} = $usesuper;
!             $data{$which}{'users'}{$usesysid}{'usecatupd'} = $usecatupd;
!             $data{$which}{'users'}{$usesysid}{'passwd'} = $passwd;
!             $data{$which}{'users'}{$usesysid}{'valuntil'} = $valuntil;
!             $data{$which}{'users'}{$usesysid}{'useconfig'} = $useconfig;
!         }
!     }
!     close P;
! }
! 
! sub get_groups {
!     my $which = shift;
!     open P, "$psql -h " . $data{$which}{'hostname'} .
!         " -p " . $data{$which}{'port'} .
!         " -U " . $data{$which}{'username'} .
!         " -d template1 " .
!         " -t" .
!         " -c 'select * from pg_group' |"
!         || death( message => "Can't open pipe to $psql: $!");
!     while (<P>) {
!         $_ =~ m/\s+(\S*)\s+\|\s+(\S*)\s+\|\s+(\S*)$/;
!         my $groname = $1;
!         my $grosysid = $2;
!         my $grolist = $3;
!         if ($groname) {
!             $data{$which}{'groups'}{$grosysid}{'groname'} = $groname;
!             $data{$which}{'groups'}{$grosysid}{'grosysid'} = $grosysid;
!             $data{$which}{'groups'}{$grosysid}{'grolist'} = $grolist;
!         }
!     }
!     close P;
! }
! 
! sub test_conn {
!     my %params = (
!       which => undef
!     , @_
!     );
!     my $ret = system "$psql -h " . $data{$params{'which'}}{'hostname'} .
!         " -p " . $data{$params{'which'}}{'port'} .
!         " -U " . $data{$params{'which'}}{'username'} .
!         " -d template1" .
!         " -t" .
!         " -c 'select current_timestamp' 1> $tmpdir/testpgconn 2> /dev/null";
!     if ($ret != 0) {
!         # Remove the failed attempt from ~/.pgpass
!         open F, "$pgpassfile" || death( message => "Can't open $pgpassfile: $!");
!         my @lines = <F>;
!         close F;
!         pop @lines;
!         open F, ">$pgpassfile" || death( message => "Can't open $pgpassfile: $!");
!         print F @lines;
!         close F;
!         return -1;
!     }
    return 0;
  }
  
  sub get_one {
!     my $temp;
!     system "stty -echo";
!     system "stty raw";
!     sysread STDIN, $temp, 1;
!     system "stty sane";
!     system "stty echo";
!     return $temp;
  }
  
  sub get_one_bool {
!     my $temp = get_one();
!     if ($temp =~ m/n/i) {
!         print "N\n";
!         return 0;
!     } else {
!         print "Y\n";
!         return 1;
!     }
  }
  
  sub dump_to_file {
!     return if !$dumper;
!     open F, ">$slony_dump" or death( message => "Can't open $slony_dump: $!");
!     foreach my $host (keys %data) {
!         delete $data{$host}{'databases'};
!         delete $data{$host}{'users'};
!         delete $data{$host}{'groups'};
!         delete $data{$host}{'coninfo'};
!     }
!     delete $data{'slaves'};
!     print F Data::Dumper::Dumper (\%data);
!     close F;
!     chmod 0600, $slony_dump;
  }
  
  sub backup_file {
!     my %params = (
!       orig => undef
!     , backup => undef
!     , @_
!     );
!     open F, $params{'orig'} or death( message => "Count not open $params{'orig'}: $!");
!     open FH, ">$params{'backup'}" or death( message => "Count not open $params{'backup'}: $!");
!     while (<F>) {
!         print FH $_;
!     }
!     close FH;
!     close F;
!     unlink $params{'orig'} or death( message => "Cannot unlink $params{'orig'}: $!");
! }
! 
! sub clean_up {
!     print "\n\nCleaning up\n";
!     unlink $pgpassfile;
!     if (-f $pgpassbackup) {
!         print "Restoring previous $pgpassfile\n";
!         backup_file (
!           orig => $pgpassbackup
!         , backup => $pgpassfile
!         );
!     }
!     if (-d $tmpdir) {
!         print "Removing temporary directory\n";
!         system("rm -rf $tmpdir");
!     }
!     print "\n";
!     system "stty echo";
!     exit $exitcode;
  }
  
  sub death {
!     my %params = (
!       message => undef
!     , @_
!     );
!     print "$params{'message'}\n";
!     clean_up();
  }


More information about the Slony1-general mailing list