CVS User Account cvsuser
Tue May 31 17:11:11 PDT 2005
Log Message:
-----------
As per discussion on list, rename scripts to a "Hungarian style" notation
where the scripts that generate slonik are prefixed with "slonik_".

Modified Files:
--------------
    slony1-engine/tools/altperl:
        README (r1.12 -> r1.13)
        ToDo (r1.3 -> r1.4)

Added Files:
-----------
    slony1-engine/tools/altperl:
        slonik_build_env.pl (r1.1)
        slonik_create_set.pl (r1.1)
        slonik_drop_node.pl (r1.1)
        slonik_drop_set.pl (r1.1)
        slonik_execute_script.pl (r1.1)
        slonik_failover.pl (r1.1)
        slonik_init_cluster.pl (r1.1)
        slonik_merge_sets.pl (r1.1)
        slonik_move_set.pl (r1.1)
        slonik_restart_node.pl (r1.1)
        slonik_store_node.pl (r1.1)
        slonik_subscribe_set.pl (r1.1)
        slonik_uninstall_nodes.pl (r1.1)
        slonik_unsubscribe_set.pl (r1.1)
        slonik_update_nodes.pl (r1.1)
        slony_show_configuration.pl (r1.1)

Removed Files:
-------------
    slony1-engine/tools/altperl:
        build_env.pl
        create_set.pl
        drop_node.pl
        drop_set.pl
        execute_script.pl
        failover.pl
        init_cluster.pl
        merge_sets.pl
        move_set.pl
        restart_node.pl
        store_node.pl
        subscribe_set.pl
        uninstall_nodes.pl
        unsubscribe_set.pl
        update_nodes.pl

-------------- next part --------------
--- /dev/null
+++ tools/altperl/slonik_update_nodes.pl
@@ -0,0 +1,37 @@
+#!@@PERL@@
+# $Id: slonik_update_nodes.pl,v 1.1 2005/05/31 16:11:05 cbbrowne Exp $
+# Author: Christopher Browne
+# Copyright 2004 Afilias Canada
+
+use Getopt::Long;
+
+# Defaults
+$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
+$SHOW_USAGE  = 0;
+
+# Read command-line options
+GetOptions("config=s" => \$CONFIG_FILE,
+	   "help"     => \$SHOW_USAGE);
+
+my $USAGE =
+"Usage: update_nodes [--config file]
+
+    Updates the functions on all nodes.
+
+";
+
+if ($SHOW_USAGE) {
+  print $USAGE;
+  exit 0;
+}
+
+require '@@PGLIBDIR@@/slon-tools.pm';
+require $CONFIG_FILE;
+
+open(SLONIK, ">", "/tmp/update_nodes.$$");
+print SLONIK genheader();
+foreach my $node (@NODES) {
+  print SLONIK "  update functions (id = $node);\n";
+};
+close SLONIK;
+run_slonik_script("/tmp/update_nodes.$$");
--- /dev/null
+++ tools/altperl/slonik_subscribe_set.pl
@@ -0,0 +1,75 @@
+#!@@PERL@@
+# $Id: slonik_subscribe_set.pl,v 1.1 2005/05/31 16:11:05 cbbrowne Exp $
+# Author: Christopher Browne
+# Copyright 2004 Afilias Canada
+
+use Getopt::Long;
+
+# Defaults
+$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
+$SHOW_USAGE  = 0;
+
+# Read command-line options
+GetOptions("config=s"  => \$CONFIG_FILE,
+	   "help"      => \$SHOW_USAGE);
+
+my $USAGE =
+"Usage: subscribe_set [--config file] set# node#
+
+    Begins replicating a set to the specified node.
+
+";
+
+if ($SHOW_USAGE) {
+  print $USAGE;
+  exit 0;
+}
+
+require '@@PGLIBDIR@@/slon-tools.pm';
+require $CONFIG_FILE;
+
+my ($set, $node) = @ARGV;
+if ($node =~ /^(?:node)?(\d+)$/) {
+  $node = $1;
+} else {
+  print "Need to specify node!\n";
+  die $USAGE;
+}
+
+if ($set =~ /^(?:set)?(\d+)$/) {
+  $set = $1;
+} else {
+  print "Need to specify set!\n";
+  die $USAGE;
+}
+
+get_set($set) or die "Non-existent set specified.\n";
+
+$FILE="/tmp/slonik-subscribe.$$";
+open(SLONIK, ">$FILE");
+print SLONIK genheader();
+print SLONIK "  try {\n";
+
+if ($DSN[$node]) {
+  my $provider = $SET_ORIGIN;
+  my $forward;
+  if ($PARENT[$node]) {
+    $provider = $PARENT[$node];
+  }
+  if ($NOFORWARD[$node] eq "yes") {
+    $forward = "no";
+  } else {
+    $forward = "yes";
+  }
+  print SLONIK "    subscribe set (id = $set, provider = $provider, receiver = $node, forward = $forward);\n";
+} else {
+  die "Node $node not found\n";
+}
+
+print SLONIK "  }\n";
+print SLONIK "  on error {\n";
+print SLONIK "    exit 1;\n";
+print SLONIK "  }\n";
+print SLONIK "  echo 'Subscribed nodes to set $set';\n";
+close SLONIK;
+run_slonik_script($FILE);
--- tools/altperl/create_set.pl
+++ /dev/null
@@ -1,126 +0,0 @@
-#!@@PERL@@
-# $Id: create_set.pl,v 1.15 2005/02/23 20:30:51 smsimms Exp $
-# Author: Christopher Browne
-# Copyright 2004 Afilias Canada
-
-use Getopt::Long;
-
-$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
-$SHOW_USAGE  = 0;
-
-# Read command-line options
-GetOptions("config=s" => \$CONFIG_FILE,
-	   "help"     => \$SHOW_USAGE);
-
-my $USAGE =
-"Usage: create_set [--config file] set
-
-    set  The name or ID of the set to be created
-
-";
-
-if ($SHOW_USAGE) {
-    print $USAGE;
-    exit 0;
-}
-
-require '@@PGLIBDIR@@/slon-tools.pm';
-require $CONFIG_FILE;
-
-my ($set) = @ARGV;
-$SET_ID = get_set($set);
-unless ($SET_ID) {
-    die $USAGE;
-}
-
-$FILE="/tmp/add_tables.$$";
-open (SLONIK, ">", $FILE);
-print SLONIK genheader();
-
-# Tables without primary keys
-print SLONIK "\n";
-print SLONIK "# TABLE ADD KEY\n";
-foreach my $table (@SERIALTABLES) {
-    $table = ensure_namespace($table);
-    print SLONIK "  echo '  Adding unique key to table $table...';\n";
-    print SLONIK "  table add key (\n";
-    print SLONIK "    node id = $SET_ORIGIN,\n";
-    print SLONIK "    full qualified name='$table'\n";
-    print SLONIK "  );\n";
-}
-
-# CREATE SET
-print SLONIK "\n";
-print SLONIK "# CREATE SET\n";
-print SLONIK "  try {\n";
-print SLONIK "    create set (id = $SET_ID, origin = $SET_ORIGIN, comment = 'Set $SET_ID for $CLUSTER_NAME');\n";
-print SLONIK "  } on error {\n";
-print SLONIK "    echo 'Could not create subscription set $SET_ID for $CLUSTER_NAME!';\n";
-print SLONIK "    exit -1;\n";
-print SLONIK "  }\n";
-
-# SET ADD TABLE
-print SLONIK "\n";
-print SLONIK "# SET ADD TABLE\n";
-print SLONIK "  echo 'Subscription set $SET_ID created';\n";
-print SLONIK "  echo 'Adding tables to the subscription set';\n";
-
-$TABLE_ID = 1 if $TABLE_ID < 1;
-
-foreach my $table (@SERIALTABLES) {
-    $table = ensure_namespace($table);
-    print SLONIK "  set add table (set id = $SET_ID, origin = $SET_ORIGIN, id = $TABLE_ID,\n";
-    print SLONIK "                 full qualified name = '$table', key=serial,\n";
-    print SLONIK "                 comment = 'Table $table without primary key');\n";
-    print SLONIK "  echo 'Add unkeyed table $table';\n";
-    $TABLE_ID++;
-}
-
-foreach my $table (@PKEYEDTABLES) {
-    $table = ensure_namespace($table);
-    print SLONIK "  set add table (set id = $SET_ID, origin = $SET_ORIGIN, id = $TABLE_ID,\n";
-    print SLONIK "                 full qualified name = '$table',\n";
-    print SLONIK "                 comment = 'Table $table with primary key');\n";
-    print SLONIK "  echo 'Add primary keyed table $table';\n";
-    $TABLE_ID++;
-}
-
-foreach my $table (keys %KEYEDTABLES) {
-    my $key = $KEYEDTABLES{$table};
-    $table = ensure_namespace($table);
-    print SLONIK "  set add table (set id = $SET_ID, origin = $SET_ORIGIN, id = $TABLE_ID,\n";
-    print SLONIK "                 full qualified name = '$table', key='$key'\n";
-    print SLONIK "                 comment = 'Table $table with candidate primary key $key');\n";
-    print SLONIK "  echo 'Add candidate primary keyed table $table';\n";
-    $TABLE_ID++;
-}
-
-# SET ADD SEQUENCE
-print SLONIK "\n";
-print SLONIK "# SET ADD SEQUENCE\n";
-print SLONIK "  echo 'Adding sequences to the subscription set';\n";
-
-$SEQUENCE_ID = 1 if $SEQUENCE_ID < 1;
-foreach my $seq (@SEQUENCES) {
-    $seq = ensure_namespace($seq);
-    print SLONIK "  set add sequence (set id = $SET_ID, origin = $SET_ORIGIN, id = $SEQUENCE_ID,\n";
-    print SLONIK "                    full qualified name = '$seq',\n";
-    print SLONIK "                    comment = 'Sequence $seq');\n";
-    print SLONIK "  echo 'Add sequence $seq';\n";
-    $SEQUENCE_ID++;
-}
-print SLONIK "  echo 'All tables added';\n";
-
-close SLONIK;
-run_slonik_script($FILE);
-
-### If object hasn't a namespace specified, assume it's in "public", and make it so...
-sub ensure_namespace {
-    my ($object) = @_;
-    if ($object =~ /^(.*\..*)$/) {
-	# Table has a namespace specified
-    } else {
-	$object = "public.$object";
-    }
-    return $object;
-}
--- tools/altperl/subscribe_set.pl
+++ /dev/null
@@ -1,75 +0,0 @@
-#!@@PERL@@
-# $Id: subscribe_set.pl,v 1.10 2005/02/23 20:30:51 smsimms Exp $
-# Author: Christopher Browne
-# Copyright 2004 Afilias Canada
-
-use Getopt::Long;
-
-# Defaults
-$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
-$SHOW_USAGE  = 0;
-
-# Read command-line options
-GetOptions("config=s"  => \$CONFIG_FILE,
-	   "help"      => \$SHOW_USAGE);
-
-my $USAGE =
-"Usage: subscribe_set [--config file] set# node#
-
-    Begins replicating a set to the specified node.
-
-";
-
-if ($SHOW_USAGE) {
-  print $USAGE;
-  exit 0;
-}
-
-require '@@PGLIBDIR@@/slon-tools.pm';
-require $CONFIG_FILE;
-
-my ($set, $node) = @ARGV;
-if ($node =~ /^(?:node)?(\d+)$/) {
-  $node = $1;
-} else {
-  print "Need to specify node!\n";
-  die $USAGE;
-}
-
-if ($set =~ /^(?:set)?(\d+)$/) {
-  $set = $1;
-} else {
-  print "Need to specify set!\n";
-  die $USAGE;
-}
-
-get_set($set) or die "Non-existent set specified.\n";
-
-$FILE="/tmp/slonik-subscribe.$$";
-open(SLONIK, ">$FILE");
-print SLONIK genheader();
-print SLONIK "  try {\n";
-
-if ($DSN[$node]) {
-  my $provider = $SET_ORIGIN;
-  my $forward;
-  if ($PARENT[$node]) {
-    $provider = $PARENT[$node];
-  }
-  if ($NOFORWARD[$node] eq "yes") {
-    $forward = "no";
-  } else {
-    $forward = "yes";
-  }
-  print SLONIK "    subscribe set (id = $set, provider = $provider, receiver = $node, forward = $forward);\n";
-} else {
-  die "Node $node not found\n";
-}
-
-print SLONIK "  }\n";
-print SLONIK "  on error {\n";
-print SLONIK "    exit 1;\n";
-print SLONIK "  }\n";
-print SLONIK "  echo 'Subscribed nodes to set $set';\n";
-close SLONIK;
-run_slonik_script($FILE);
--- tools/altperl/init_cluster.pl
+++ /dev/null
@@ -1,228 +0,0 @@
-#!@@PERL@@
-# $Id: init_cluster.pl,v 1.12 2005/02/23 20:30:51 smsimms Exp $
-# Author: Christopher Browne
-# Copyright 2004 Afilias Canada
-
-use Getopt::Long;
-
-# Defaults
-my $CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
-my $SHOW_USAGE  = 0;
-
-# Read command-line options
-GetOptions("config=s" => \$CONFIG_FILE,
-	   "help"     => \$SHOW_USAGE);
-
-my $USAGE =
-"Usage: init_cluster [--config file]
-
-    Generates the slonik commands necessary to create a cluster and
-    prepare the nodes for use.  Also displays a report showing the
-    relationships between the various nodes.
-
-";
-
-if ($SHOW_USAGE) {
-  print $USAGE;
-  exit 0;
-}
-
-require '@@PGLIBDIR@@/slon-tools.pm';
-require $CONFIG_FILE;
-
-my $FILE="/tmp/init-cluster.$$";
-
-# INIT CLUSTER
-open(SLONIK, ">", $FILE);
-print SLONIK "\n# INIT CLUSTER\n";
-print SLONIK genheader();
-my ($dbname, $dbhost) = ($DBNAME[$MASTERNODE], $HOST[$MASTERNODE]);
-print SLONIK "  init cluster (id = $MASTERNODE, comment = 'Node $MASTERNODE - $dbname\@$dbhost');\n";
-
-# STORE NODE
-print SLONIK "\n# STORE NODE\n";
-foreach my $node (@NODES) {
-  if ($node != $MASTERNODE) {		# skip the master node; it's already initialized!
-    my ($dbname, $dbhost) = ($DBNAME[$node], $HOST[$node]);
-    print SLONIK "  store node (id = $node, event node = $MASTERNODE, comment = 'Node $node - $dbname\@$dbhost');\n";
-  }
-}
-print SLONIK "  echo 'Set up replication nodes';\n";
-
-# STORE PATH
-print SLONIK "\n# STORE PATH\n";
-
-my @COST;
-my @VIA;
-my @PATH;
-generate_listen_paths();
-
-print SLONIK "  echo 'Next: configure paths for each node/origin';\n";
-foreach my $nodea (@NODES) {
-  my $dsna = $DSN[$nodea];
-  foreach my $nodeb (@NODES) {
-    if ($nodea != $nodeb) {
-      my $dsnb = $DSN[$nodeb];
-      my $providerba = $VIA[$nodea][$nodeb];
-      my $providerab = $VIA[$nodeb][$nodea];
-      if (!$printed[$nodea][$nodeb] and $providerab == $nodea) {
-	print SLONIK "  store path (server = $nodea, client = $nodeb, conninfo = '$dsna');\n";
-	$printed[$nodea][$nodeb] = "done";
-      }
-      if (!$printed[$nodeb][$nodea] and $providerba == $nodea) {
-	print SLONIK "  store path (server = $nodeb, client = $nodea, conninfo = '$dsnb');\n";
-	$printed[$nodeb][$nodea] = "done";
-      }
-    }
-  }
-}
-
-# STORE LISTEN
-print SLONIK "\n# STORE LISTEN\n";
-foreach my $origin (@NODES) {
-  my $dsna = $DSN[$origin];
-  foreach my $receiver (@NODES) {
-    if ($origin != $receiver) {
-      my $provider = $VIA[$origin][$receiver];
-      print SLONIK "  store listen (origin = $origin, receiver = $receiver, provider = $provider);\n";
-    }
-  }
-}
-print SLONIK "  echo 'Replication nodes prepared';\n";
-print SLONIK "  echo 'Please start a slon replication daemon for each node';\n";
-close SLONIK;
-run_slonik_script($FILE);
-report_on_paths();
-
-sub generate_listen_paths {
-  my $infinity = 10000000;	# Initial costs are all infinite
-  foreach my $node1 (@NODES) {
-    foreach my $node2 (@NODES) {
-      $COST[$node1][$node2] = $infinity;
-    }
-  }
-
-  # Initialize paths between parents and children, and based on them,
-  # generate initial seeding of listener paths, @VIA
-
-  foreach my $node1 (@NODES) {
-    $COST[$node1][$node1] = 0;
-    $VIA[$node1][$node1] = 0;
-    foreach my $node2 (@NODES) {
-      if ($node2 != $node1) {
-	if ((not ($PARENT[$node1] or $PARENT[$node2])) or
-	    ($PARENT[$node1] and $PARENT[$node1] == $node2) or
-	    ($PARENT[$node2] and $PARENT[$node2] == $node1)) {
-	  $PATH[$node1][$node2] = 1;
-	  $PATH[$node2][$node1] = 1;
-	  # Set up a cost 1 path between them
-	  # Parent to child
-	  $COST[$node1][$node2] = 1;
-	  $VIA[$node1][$node2] = $node1;
-
-	  # Child to parent
-	  $COST[$node2][$node1] = 1;
-	  $VIA[$node2][$node1] = $node2;
-	}
-      }
-    }
-  }
-
-  # Now, update the listener paths...
-  # 4 level nested iteration:
-  # 1 while not done, do
-  #   2 for each node, node1
-  #     3 for each node, node2, where node2 <> node1, where we don't
-  #           yet have a listener path
-  #       4 for each node node3 (<> node1 or node2),
-  #          consider introducing the listener path:
-  #                 node1 to node2 then node2 to node3
-  # In concept, it's an O(n^4) algorithm; since the number of nodes, n,
-  # is not likely to get particularly large, it's not worth tuning
-  # further.
-  $didwork = "yes";
-  while ($didwork eq "yes") {
-    $didwork = "no";
-    foreach my $node1 (@NODES) {
-      foreach my $node3 (@NODES) {
-	if (($VIA[$node3][$node1] == 0) && ($node3 != $node1)) {
-	  foreach my $node2 (@NODES) {
-	    if ($PATH[$node1][$node2] && ($VIA[$node2][$node3] != 0) && ($node2 != $node3) && ($node2 != $node1)) {
-	      # Consider introducing a path from n1 to n2 then n2 to n3
-	      # as a cheaper alternative to going direct from n1 to n3
-	      my $oldcost = $COST[$node3][$node1];
-	      my $newcost = $COST[$node1][$node2] + $COST[$node2][$node3];
-	      if ($newcost < $oldcost) {
-		$didwork = "yes";
-				# So we go via node 2
-		$VIA[$node3][$node1] = $node2;
-		$COST[$node3][$node1] = $newcost;
-
-		$VIA[$node1][$node3] = $node2;
-		$COST[$node1][$node3] = $newcost;
-	      }
-	    }
-	  }
-	}
-      }
-    }
-  }
-}
-
-sub report_on_paths {
-  print "# Configuration Summary:\n";
-  print "#\n";
-  print "# COST\n";
-  print "#      ";
-  foreach my $node2 (@NODES) {
-    printf "| %3d ", $node2;
-  }
-  print "|\n# ";
-  print ("-----+" x (scalar(@NODES) + 1));
-  print "\n";
-  foreach my $node1 (@NODES) {
-    printf "#  %3d ", $node1;
-    foreach my $node2 (@NODES) {
-      if ($COST[$node2][$node1] == $infinity) {
-	printf "| inf ";
-      } else {
-	printf "|%4d ", $COST[$node2][$node1];
-      }
-    }
-    print "|\n";
-  }
-  print "# \n";
-  print "# VIA\n";
-  print "#      ";
-  foreach my $node2 (@NODES) {
-    printf "| %3d ", $node2;
-  }
-  print "|\n# ";
-  print ("-----+" x (scalar(@NODES) + 1));
-  print "\n";
-  foreach my $node1 (@NODES) {
-    printf "#  %3d ", $node1;
-    foreach my $node2 (@NODES) {
-      printf "|%4d ", $VIA[$node2][$node1];
-    }
-    print "|\n";
-  }
-
-  print "# \n";
-  print "# PATHS\n";
-  print "#      ";
-  foreach my $node2 (@NODES) {
-    printf "| %3d ", $node2;
-  }
-  print "|\n# ";
-  print ("-----+" x (scalar(@NODES) + 1));
-  print "\n";
-  foreach my $node1 (@NODES) {
-    printf "#  %3d ", $node1;
-    foreach my $node2 (@NODES) {
-      printf "|%4d ", $PATH[$node2][$node1];
-    }
-    print "|\n";
-  }
-  print "\n";
-}
--- /dev/null
+++ tools/altperl/slonik_create_set.pl
@@ -0,0 +1,126 @@
+#!@@PERL@@
+# $Id: slonik_create_set.pl,v 1.1 2005/05/31 16:11:05 cbbrowne Exp $
+# Author: Christopher Browne
+# Copyright 2004 Afilias Canada
+
+use Getopt::Long;
+
+$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
+$SHOW_USAGE  = 0;
+
+# Read command-line options
+GetOptions("config=s" => \$CONFIG_FILE,
+	   "help"     => \$SHOW_USAGE);
+
+my $USAGE =
+"Usage: create_set [--config file] set
+
+    set  The name or ID of the set to be created
+
+";
+
+if ($SHOW_USAGE) {
+    print $USAGE;
+    exit 0;
+}
+
+require '@@PGLIBDIR@@/slon-tools.pm';
+require $CONFIG_FILE;
+
+my ($set) = @ARGV;
+$SET_ID = get_set($set);
+unless ($SET_ID) {
+    die $USAGE;
+}
+
+$FILE="/tmp/add_tables.$$";
+open (SLONIK, ">", $FILE);
+print SLONIK genheader();
+
+# Tables without primary keys
+print SLONIK "\n";
+print SLONIK "# TABLE ADD KEY\n";
+foreach my $table (@SERIALTABLES) {
+    $table = ensure_namespace($table);
+    print SLONIK "  echo '  Adding unique key to table $table...';\n";
+    print SLONIK "  table add key (\n";
+    print SLONIK "    node id = $SET_ORIGIN,\n";
+    print SLONIK "    full qualified name='$table'\n";
+    print SLONIK "  );\n";
+}
+
+# CREATE SET
+print SLONIK "\n";
+print SLONIK "# CREATE SET\n";
+print SLONIK "  try {\n";
+print SLONIK "    create set (id = $SET_ID, origin = $SET_ORIGIN, comment = 'Set $SET_ID for $CLUSTER_NAME');\n";
+print SLONIK "  } on error {\n";
+print SLONIK "    echo 'Could not create subscription set $SET_ID for $CLUSTER_NAME!';\n";
+print SLONIK "    exit -1;\n";
+print SLONIK "  }\n";
+
+# SET ADD TABLE
+print SLONIK "\n";
+print SLONIK "# SET ADD TABLE\n";
+print SLONIK "  echo 'Subscription set $SET_ID created';\n";
+print SLONIK "  echo 'Adding tables to the subscription set';\n";
+
+$TABLE_ID = 1 if $TABLE_ID < 1;
+
+foreach my $table (@SERIALTABLES) {
+    $table = ensure_namespace($table);
+    print SLONIK "  set add table (set id = $SET_ID, origin = $SET_ORIGIN, id = $TABLE_ID,\n";
+    print SLONIK "                 full qualified name = '$table', key=serial,\n";
+    print SLONIK "                 comment = 'Table $table without primary key');\n";
+    print SLONIK "  echo 'Add unkeyed table $table';\n";
+    $TABLE_ID++;
+}
+
+foreach my $table (@PKEYEDTABLES) {
+    $table = ensure_namespace($table);
+    print SLONIK "  set add table (set id = $SET_ID, origin = $SET_ORIGIN, id = $TABLE_ID,\n";
+    print SLONIK "                 full qualified name = '$table',\n";
+    print SLONIK "                 comment = 'Table $table with primary key');\n";
+    print SLONIK "  echo 'Add primary keyed table $table';\n";
+    $TABLE_ID++;
+}
+
+foreach my $table (keys %KEYEDTABLES) {
+    my $key = $KEYEDTABLES{$table};
+    $table = ensure_namespace($table);
+    print SLONIK "  set add table (set id = $SET_ID, origin = $SET_ORIGIN, id = $TABLE_ID,\n";
+    print SLONIK "                 full qualified name = '$table', key='$key'\n";
+    print SLONIK "                 comment = 'Table $table with candidate primary key $key');\n";
+    print SLONIK "  echo 'Add candidate primary keyed table $table';\n";
+    $TABLE_ID++;
+}
+
+# SET ADD SEQUENCE
+print SLONIK "\n";
+print SLONIK "# SET ADD SEQUENCE\n";
+print SLONIK "  echo 'Adding sequences to the subscription set';\n";
+
+$SEQUENCE_ID = 1 if $SEQUENCE_ID < 1;
+foreach my $seq (@SEQUENCES) {
+    $seq = ensure_namespace($seq);
+    print SLONIK "  set add sequence (set id = $SET_ID, origin = $SET_ORIGIN, id = $SEQUENCE_ID,\n";
+    print SLONIK "                    full qualified name = '$seq',\n";
+    print SLONIK "                    comment = 'Sequence $seq');\n";
+    print SLONIK "  echo 'Add sequence $seq';\n";
+    $SEQUENCE_ID++;
+}
+print SLONIK "  echo 'All tables added';\n";
+
+close SLONIK;
+run_slonik_script($FILE);
+
+### If object hasn't a namespace specified, assume it's in "public", and make it so...
+sub ensure_namespace {
+    my ($object) = @_;
+    if ($object =~ /^(.*\..*)$/) {
+	# Table has a namespace specified
+    } else {
+	$object = "public.$object";
+    }
+    return $object;
+}
--- /dev/null
+++ tools/altperl/slonik_drop_node.pl
@@ -0,0 +1,49 @@
+#!@@PERL@@
+# $Id: slonik_drop_node.pl,v 1.1 2005/05/31 16:11:05 cbbrowne Exp $
+# Author: Christopher Browne
+# Copyright 2004 Afilias Canada
+
+use Getopt::Long;
+
+# Defaults
+$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
+$SHOW_USAGE  = 0;
+
+# Read command-line options
+GetOptions("config=s" => \$CONFIG_FILE,
+	   "help"     => \$SHOW_USAGE);
+
+my $USAGE =
+"Usage: drop_node [--config file] node#
+
+    Drops a node.
+
+";
+
+if ($SHOW_USAGE) {
+  print $USAGE;
+  exit 0;
+}
+
+require '@@PGLIBDIR@@/slon-tools.pm';
+require $CONFIG_FILE;
+
+my ($node) = @ARGV;
+if ($node =~ /^(?:node)?(\d+)$/) {
+  $node = $1;
+} else {
+  die $USAGE;
+}
+
+my $FILE="/tmp/slonik-drop.$$";
+open(SLONIK, ">", $FILE);
+print SLONIK genheader();
+print SLONIK "  try {\n";
+print SLONIK "      drop node (id = $node, event node = $MASTERNODE);\n";
+print SLONIK "  } on error {\n";
+print SLONIK "      echo 'Failed to drop node $node from cluster';\n";
+print SLONIK "      exit 1;\n";
+print SLONIK "  }\n";
+print SLONIK "  echo 'dropped node $node cluster';\n";
+close SLONIK;
+run_slonik_script($FILE);
--- tools/altperl/store_node.pl
+++ /dev/null
@@ -1,233 +0,0 @@
-#!@@PERL@@
-# $Id: store_node.pl,v 1.1 2005/03/10 18:03:10 smsimms Exp $
-# Author: Steve Simms
-# Copyright 2005 PostgreSQL Global Development Group
-
-use Getopt::Long;
-
-# Defaults
-my $CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
-my $SHOW_USAGE  = 0;
-
-# Read command-line options
-GetOptions("config=s" => \$CONFIG_FILE,
-	   "help"     => \$SHOW_USAGE);
-
-my $USAGE =
-"Usage: store_node [--config file] node#
-
-    Generates the slonik commands necessary to add a node to a
-    cluster.  Also displays a report showing the relationships between
-    the various nodes.
-
-";
-
-if ($SHOW_USAGE) {
-  print $USAGE;
-  exit 0;
-}
-
-require '@@PGLIBDIR@@/slon-tools.pm';
-require $CONFIG_FILE;
-
-$node = $ARGV[0];
-
-# Node can be passed either as "node1" or just "1"
-if ($node =~ /^(?:node)?(\d+)$/) {
-  $node = $1;
-} else {
-  die $USAGE;
-}
-
-my $FILE="/tmp/store_node.$$";
-
-open(SLONIK, ">", $FILE);
-print SLONIK genheader();
-
-# STORE NODE
-print SLONIK "\n# STORE NODE\n";
-my ($dbname, $dbhost) = ($DBNAME[$node], $HOST[$node]);
-print SLONIK "  store node (id = $node, event node = $MASTERNODE, comment = 'Node $node - $dbname\@$dbhost');\n";
-print SLONIK "  echo 'Set up replication nodes';\n";
-
-# STORE PATH
-print SLONIK "\n# STORE PATH\n";
-
-my @COST;
-my @VIA;
-my @PATH;
-generate_listen_paths();
-
-print SLONIK "  echo 'Next: configure paths for each node/origin';\n";
-foreach my $nodea (@NODES) {
-    my $dsna = $DSN[$nodea];
-    foreach my $nodeb (@NODES) {
-	if ($nodea != $nodeb) {
-	    next unless ($node == $nodea or $node == $nodeb);
-	    my $dsnb = $DSN[$nodeb];
-	    my $providerba = $VIA[$nodea][$nodeb];
-	    my $providerab = $VIA[$nodeb][$nodea];
-	    if (!$printed[$nodea][$nodeb] and $providerab == $nodea) {
-		print SLONIK "  store path (server = $nodea, client = $nodeb, conninfo = '$dsna');\n";
-		$printed[$nodea][$nodeb] = "done";
-	    }
-	    if (!$printed[$nodeb][$nodea] and $providerba == $nodea) {
-		print SLONIK "  store path (server = $nodeb, client = $nodea, conninfo = '$dsnb');\n";
-		$printed[$nodeb][$nodea] = "done";
-	    }
-	}
-    }
-}
-
-# STORE LISTEN
-print SLONIK "\n# STORE LISTEN\n";
-foreach my $origin (@NODES) {
-    my $dsna = $DSN[$origin];
-    foreach my $receiver (@NODES) {
-	if ($origin != $receiver) {
-	    my $provider = $VIA[$origin][$receiver];
-	    next unless ($node == $origin   or
-			 $node == $receiver or
-			 $node == $provider);
-	    print SLONIK "  store listen (origin = $origin, receiver = $receiver, provider = $provider);\n";
-	}
-    }
-}
-print SLONIK "  echo 'Replication nodes prepared';\n";
-print SLONIK "  echo 'Please start a slon replication daemon for each node';\n";
-close SLONIK;
-run_slonik_script($FILE);
-report_on_paths();
-
-sub generate_listen_paths {
-  my $infinity = 10000000;	# Initial costs are all infinite
-  foreach my $node1 (@NODES) {
-    foreach my $node2 (@NODES) {
-      $COST[$node1][$node2] = $infinity;
-    }
-  }
-
-  # Initialize paths between parents and children, and based on them,
-  # generate initial seeding of listener paths, @VIA
-
-  foreach my $node1 (@NODES) {
-    $COST[$node1][$node1] = 0;
-    $VIA[$node1][$node1] = 0;
-    foreach my $node2 (@NODES) {
-      if ($node2 != $node1) {
-	if ((not ($PARENT[$node1] or $PARENT[$node2])) or
-	    ($PARENT[$node1] and $PARENT[$node1] == $node2) or
-	    ($PARENT[$node2] and $PARENT[$node2] == $node1)) {
-	  $PATH[$node1][$node2] = 1;
-	  $PATH[$node2][$node1] = 1;
-	  # Set up a cost 1 path between them
-	  # Parent to child
-	  $COST[$node1][$node2] = 1;
-	  $VIA[$node1][$node2] = $node1;
-
-	  # Child to parent
-	  $COST[$node2][$node1] = 1;
-	  $VIA[$node2][$node1] = $node2;
-	}
-      }
-    }
-  }
-
-  # Now, update the listener paths...
-  # 4 level nested iteration:
-  # 1 while not done, do
-  #   2 for each node, node1
-  #     3 for each node, node2, where node2 <> node1, where we don't
-  #           yet have a listener path
-  #       4 for each node node3 (<> node1 or node2),
-  #          consider introducing the listener path:
-  #                 node1 to node2 then node2 to node3
-  # In concept, it's an O(n^4) algorithm; since the number of nodes, n,
-  # is not likely to get particularly large, it's not worth tuning
-  # further.
-  $didwork = "yes";
-  while ($didwork eq "yes") {
-    $didwork = "no";
-    foreach my $node1 (@NODES) {
-      foreach my $node3 (@NODES) {
-	if (($VIA[$node3][$node1] == 0) && ($node3 != $node1)) {
-	  foreach my $node2 (@NODES) {
-	    if ($PATH[$node1][$node2] && ($VIA[$node2][$node3] != 0) && ($node2 != $node3) && ($node2 != $node1)) {
-	      # Consider introducing a path from n1 to n2 then n2 to n3
-	      # as a cheaper alternative to going direct from n1 to n3
-	      my $oldcost = $COST[$node3][$node1];
-	      my $newcost = $COST[$node1][$node2] + $COST[$node2][$node3];
-	      if ($newcost < $oldcost) {
-		$didwork = "yes";
-				# So we go via node 2
-		$VIA[$node3][$node1] = $node2;
-		$COST[$node3][$node1] = $newcost;
-
-		$VIA[$node1][$node3] = $node2;
-		$COST[$node1][$node3] = $newcost;
-	      }
-	    }
-	  }
-	}
-      }
-    }
-  }
-}
-
-sub report_on_paths {
-  print "# Configuration Summary:\n";
-  print "#\n";
-  print "# COST\n";
-  print "#      ";
-  foreach my $node2 (@NODES) {
-    printf "| %3d ", $node2;
-  }
-  print "|\n# ";
-  print ("-----+" x (scalar(@NODES) + 1));
-  print "\n";
-  foreach my $node1 (@NODES) {
-    printf "#  %3d ", $node1;
-    foreach my $node2 (@NODES) {
-      if ($COST[$node2][$node1] == $infinity) {
-	printf "| inf ";
-      } else {
-	printf "|%4d ", $COST[$node2][$node1];
-      }
-    }
-    print "|\n";
-  }
-  print "# \n";
-  print "# VIA\n";
-  print "#      ";
-  foreach my $node2 (@NODES) {
-    printf "| %3d ", $node2;
-  }
-  print "|\n# ";
-  print ("-----+" x (scalar(@NODES) + 1));
-  print "\n";
-  foreach my $node1 (@NODES) {
-    printf "#  %3d ", $node1;
-    foreach my $node2 (@NODES) {
-      printf "|%4d ", $VIA[$node2][$node1];
-    }
-    print "|\n";
-  }
-
-  print "# \n";
-  print "# PATHS\n";
-  print "#      ";
-  foreach my $node2 (@NODES) {
-    printf "| %3d ", $node2;
-  }
-  print "|\n# ";
-  print ("-----+" x (scalar(@NODES) + 1));
-  print "\n";
-  foreach my $node1 (@NODES) {
-    printf "#  %3d ", $node1;
-    foreach my $node2 (@NODES) {
-      printf "|%4d ", $PATH[$node2][$node1];
-    }
-    print "|\n";
-  }
-  print "\n";
-}
--- tools/altperl/drop_node.pl
+++ /dev/null
@@ -1,49 +0,0 @@
-#!@@PERL@@
-# $Id: drop_node.pl,v 1.9 2005/02/22 16:51:09 smsimms Exp $
-# Author: Christopher Browne
-# Copyright 2004 Afilias Canada
-
-use Getopt::Long;
-
-# Defaults
-$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
-$SHOW_USAGE  = 0;
-
-# Read command-line options
-GetOptions("config=s" => \$CONFIG_FILE,
-	   "help"     => \$SHOW_USAGE);
-
-my $USAGE =
-"Usage: drop_node [--config file] node#
-
-    Drops a node.
-
-";
-
-if ($SHOW_USAGE) {
-  print $USAGE;
-  exit 0;
-}
-
-require '@@PGLIBDIR@@/slon-tools.pm';
-require $CONFIG_FILE;
-
-my ($node) = @ARGV;
-if ($node =~ /^(?:node)?(\d+)$/) {
-  $node = $1;
-} else {
-  die $USAGE;
-}
-
-my $FILE="/tmp/slonik-drop.$$";
-open(SLONIK, ">", $FILE);
-print SLONIK genheader();
-print SLONIK "  try {\n";
-print SLONIK "      drop node (id = $node, event node = $MASTERNODE);\n";
-print SLONIK "  } on error {\n";
-print SLONIK "      echo 'Failed to drop node $node from cluster';\n";
-print SLONIK "      exit 1;\n";
-print SLONIK "  }\n";
-print SLONIK "  echo 'dropped node $node cluster';\n";
-close SLONIK;
-run_slonik_script($FILE);
--- tools/altperl/move_set.pl
+++ /dev/null
@@ -1,64 +0,0 @@
-#!@@PERL@@
-# $Id: move_set.pl,v 1.10 2005/05/19 18:14:45 cbbrowne Exp $
-# Author: Christopher Browne
-# Copyright 2004 Afilias Canada
-
-use Getopt::Long;
-
-# Defaults
-$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
-$SHOW_USAGE  = 0;
-
-# Read command-line options
-GetOptions("config=s" => \$CONFIG_FILE,
-	   "help"     => \$SHOW_USAGE);
-
-my $USAGE =
-"Usage: move_set [--config file] set# from_node# to_node#
-
-    Change a set's origin.
-
-";
-
-if ($SHOW_USAGE) {
-  print $USAGE;
-  exit 0;
-}
-
-require '@@PGLIBDIR@@/slon-tools.pm';
-require $CONFIG_FILE;
-
-my ($set, $node1, $node2) = @ARGV;
-if ($set =~ /^(?:set)?(\d+)$/) {
-  # Node name is in proper form
-  $set = $1;
-} else {
-  print "Valid set names are set1, set2, ...\n\n";
-  die $USAGE;
-}
-
-if ($node1 =~ /^(?:node)?(\d+)$/) {
-  $node1 = $1;
-} else {
-  print "Valid node names are node1, node2, ...\n\n";
-  die $USAGE;
-}
-
-if ($node2 =~ /^(?:node)?(\d+)$/) {
-  $node2 = $1;
-} else {
-  print "Valid node names are node1, node2, ...\n\n";
-  die $USAGE;
-}
-
-open(SLONIK, ">", "/tmp/slonik.$$");
-print SLONIK genheader();
-print SLONIK "  echo 'Locking down set $set on node $node1';\n";
-print SLONIK "  lock set (id = $set, origin = $node1);\n";
-print SLONIK "  echo 'Locked down - moving it';\n";
-print SLONIK "  move set (id = $set, old origin = $node1, new origin = $node2);\n";
-print SLONIK "  echo 'Replication set $set moved from node $node1 to $node2.  Remember to';\n";
-print SLONIK "  echo 'update your configuration file, if necessary, to note the new location';\n";
-print SLONIK "  echo 'for the set.';\n";
-close SLONIK;
-run_slonik_script("/tmp/slonik.$$");
--- /dev/null
+++ tools/altperl/slonik_build_env.pl
@@ -0,0 +1,108 @@
+#!@@PERL@@
+# $Id: slonik_build_env.pl,v 1.1 2005/05/31 16:11:05 cbbrowne Exp $
+# Contributed by:
+# Joe Kalash
+# kalash at savicom.net
+
+# This script, given parameters concerning the database nodes,
+# generates output for "slon_tools.conf" consisting of:
+# - A set of add_node() calls to configure the cluster
+# - The arrays @KEYEDTABLES, @SERIALTABLES, and @SEQUENCES
+
+use DBI;
+use Getopt::Long;
+use strict;
+
+my $dataBase;
+my $host;
+my $dataBaseUser;
+my $dataBasePassword;
+my $dataBasePort;
+my @nodes;
+my $usage = "$0 -node host:database:user[:password:port] [-node ...]
+First node is assumed to be the master.\n";
+
+&usage if(!GetOptions('node=s@'=>\@nodes));
+
+die "At least one node is required" if ( scalar(@nodes) < 1 );
+
+my $nodeNumber = 1;
+my $parentString;
+foreach my $node (@nodes)
+{
+  my($tmpHost,$tmpDataBase,$tmpDataBaseUser,$tmpDataBasePassword,$tmpPort) =
+    split(/:/,$node);
+  die "Host is required" if ( !$tmpHost );
+  die "database is required" if ( !$tmpDataBase );
+  die "user is required" if ( !$tmpDataBaseUser );
+  $tmpPort = 5432 if ( !$tmpPort );
+  $host = $tmpHost if ( !$host );
+  $dataBase = $tmpDataBase if ( !$dataBase );
+  if ( !$dataBaseUser ) {
+    $dataBaseUser = $tmpDataBaseUser;
+    $dataBasePassword = $tmpDataBasePassword if ( $tmpDataBasePassword );
+    $dataBasePort = $tmpPort if ( $tmpPort );
+  }
+  print "&add_node(host => '$tmpHost', dbname => '$tmpDataBase', port =>$tmpPort,
+        user=>'$tmpDataBaseUser', password=>'$tmpDataBasePassword', node=>$nodeNumber $parentString);\n";
+  $parentString = ', parent=>1';
+  $nodeNumber++;
+
+}
+my $connectString = "dbi:Pg:dbname=$dataBase;host=$host;port=$dataBasePort";
+my $dbh = DBI->connect($connectString,$dataBaseUser,$dataBasePassword,
+		       {RaiseError => 0, PrintError => 0, AutoCommit => 1});
+die "connect: $DBI::errstr" if ( !defined($dbh) || $DBI::err );
+# Read in all the user 'normal' tables in public.
+my $tableQuery = $dbh->prepare("
+SELECT pg_namespace.nspname || '.' || pg_class.relname,pg_class.relkind,pg_class.relhaspkey 
+FROM pg_namespace,pg_class
+WHERE pg_class.reltype > 0
+AND pg_class.relnamespace = pg_catalog.pg_namespace.oid
+AND (pg_class.relkind = 'r' OR pg_class.relkind = 'S')
+AND pg_namespace.nspname = 'public' AND pg_namespace.oid = pg_class.relnamespace");
+
+die "prepare(tableQuery): $DBI::errstr" if ( !defined($tableQuery) || $DBI::err );
+die "execute(tableQuery): $DBI::errstr" if ( !$tableQuery->execute() );
+
+my @tablesWithIndexes;
+my @tablesWithoutIndexes;
+my @sequences;
+while ( my $row = $tableQuery->fetchrow_arrayref() ) {
+  my $relname = @$row[0];
+  my $relkind = @$row[1];
+  my $relhaspkey = @$row[2];
+  push(@sequences,$relname) if ( $relkind eq 'S' );
+  push(@tablesWithIndexes,$relname) if ( $relkind eq 'r' && $relhaspkey == 1 );
+  push(@tablesWithoutIndexes,$relname) if ( $relkind eq 'r' && $relhaspkey == 0 );
+}
+$tableQuery->finish();
+$dbh->disconnect();
+
+if ( scalar(@tablesWithIndexes) > 1 ) {
+  print '@KEYEDTABLES=(' . "\n";
+  foreach my $table (sort @tablesWithIndexes) {
+    print "\t\"$table\",\n";
+  }
+  print ");\n";
+}
+if ( scalar(@tablesWithoutIndexes) > 1 ) {
+  print '@SERIALTABLES=(' . "\n";
+  foreach my $table (sort @tablesWithoutIndexes) {
+    print "\t\"$table\",\n";
+  }
+  print ");\n";
+}
+if ( scalar(@sequences) > 1 ) {
+  print '@SEQUENCES=(' . "\n";
+  foreach my $table (sort @sequences) {
+    print "\t\"$table\",\n";
+  }
+  print ");\n";
+}
+exit 0;
+
+sub usage {
+  print "$usage";
+  exit 0;
+}
--- /dev/null
+++ tools/altperl/slonik_uninstall_nodes.pl
@@ -0,0 +1,40 @@
+#!@@PERL@@
+# $Id: slonik_uninstall_nodes.pl,v 1.1 2005/05/31 16:11:05 cbbrowne Exp $
+# Author: Christopher Browne
+# Copyright 2004 Afilias Canada
+
+use Getopt::Long;
+
+# Defaults
+$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
+$SHOW_USAGE  = 0;
+
+# Read command-line options
+GetOptions("config=s" => \$CONFIG_FILE,
+	   "help"     => \$SHOW_USAGE);
+
+my $USAGE =
+"Usage: uninstall_nodes [--config file]
+
+    Removes Slony configuration from all nodes in a cluster.
+
+";
+
+if ($SHOW_USAGE) {
+  print $USAGE;
+  exit 0;
+}
+
+require '@@PGLIBDIR@@/slon-tools.pm';
+require $CONFIG_FILE;
+
+$FILE="/tmp/slonik.$$";
+open(SLONIK, ">$FILE");
+print SLONIK genheader();
+foreach my $node (@NODES) {
+    next if $node == $MASTERNODE; # Do this one last
+    print SLONIK "  uninstall node (id=$node);\n";
+}
+print SLONIK "  uninstall node (id=$MASTERNODE);\n";
+close SLONIK;
+run_slonik_script($FILE);
--- tools/altperl/build_env.pl
+++ /dev/null
@@ -1,108 +0,0 @@
-#!@@PERL@@
-# $Id: build_env.pl,v 1.8 2005/02/10 06:22:41 smsimms Exp $
-# Contributed by:
-# Joe Kalash
-# kalash at savicom.net
-
-# This script, given parameters concerning the database nodes,
-# generates output for "slon_tools.conf" consisting of:
-# - A set of add_node() calls to configure the cluster
-# - The arrays @KEYEDTABLES, @SERIALTABLES, and @SEQUENCES
-
-use DBI;
-use Getopt::Long;
-use strict;
-
-my $dataBase;
-my $host;
-my $dataBaseUser;
-my $dataBasePassword;
-my $dataBasePort;
-my @nodes;
-my $usage = "$0 -node host:database:user[:password:port] [-node ...]
-First node is assumed to be the master.\n";
-
-&usage if(!GetOptions('node=s@'=>\@nodes));
-
-die "At least one node is required" if ( scalar(@nodes) < 1 );
-
-my $nodeNumber = 1;
-my $parentString;
-foreach my $node (@nodes)
-{
-  my($tmpHost,$tmpDataBase,$tmpDataBaseUser,$tmpDataBasePassword,$tmpPort) =
-    split(/:/,$node);
-  die "Host is required" if ( !$tmpHost );
-  die "database is required" if ( !$tmpDataBase );
-  die "user is required" if ( !$tmpDataBaseUser );
-  $tmpPort = 5432 if ( !$tmpPort );
-  $host = $tmpHost if ( !$host );
-  $dataBase = $tmpDataBase if ( !$dataBase );
-  if ( !$dataBaseUser ) {
-    $dataBaseUser = $tmpDataBaseUser;
-    $dataBasePassword = $tmpDataBasePassword if ( $tmpDataBasePassword );
-    $dataBasePort = $tmpPort if ( $tmpPort );
-  }
-  print "&add_node(host => '$tmpHost', dbname => '$tmpDataBase', port =>$tmpPort,
-        user=>'$tmpDataBaseUser', password=>'$tmpDataBasePassword', node=>$nodeNumber $parentString);\n";
-  $parentString = ', parent=>1';
-  $nodeNumber++;
-
-}
-my $connectString = "dbi:Pg:dbname=$dataBase;host=$host;port=$dataBasePort";
-my $dbh = DBI->connect($connectString,$dataBaseUser,$dataBasePassword,
-		       {RaiseError => 0, PrintError => 0, AutoCommit => 1});
-die "connect: $DBI::errstr" if ( !defined($dbh) || $DBI::err );
-# Read in all the user 'normal' tables in public.
-my $tableQuery = $dbh->prepare("
-SELECT pg_namespace.nspname || '.' || pg_class.relname,pg_class.relkind,pg_class.relhaspkey 
-FROM pg_namespace,pg_class
-WHERE pg_class.reltype > 0
-AND pg_class.relnamespace = pg_catalog.pg_namespace.oid
-AND (pg_class.relkind = 'r' OR pg_class.relkind = 'S')
-AND pg_namespace.nspname = 'public' AND pg_namespace.oid = pg_class.relnamespace");
-
-die "prepare(tableQuery): $DBI::errstr" if ( !defined($tableQuery) || $DBI::err );
-die "execute(tableQuery): $DBI::errstr" if ( !$tableQuery->execute() );
-
-my @tablesWithIndexes;
-my @tablesWithoutIndexes;
-my @sequences;
-while ( my $row = $tableQuery->fetchrow_arrayref() ) {
-  my $relname = @$row[0];
-  my $relkind = @$row[1];
-  my $relhaspkey = @$row[2];
-  push(@sequences,$relname) if ( $relkind eq 'S' );
-  push(@tablesWithIndexes,$relname) if ( $relkind eq 'r' && $relhaspkey == 1 );
-  push(@tablesWithoutIndexes,$relname) if ( $relkind eq 'r' && $relhaspkey == 0 );
-}
-$tableQuery->finish();
-$dbh->disconnect();
-
-if ( scalar(@tablesWithIndexes) > 1 ) {
-  print '@KEYEDTABLES=(' . "\n";
-  foreach my $table (sort @tablesWithIndexes) {
-    print "\t\"$table\",\n";
-  }
-  print ");\n";
-}
-if ( scalar(@tablesWithoutIndexes) > 1 ) {
-  print '@SERIALTABLES=(' . "\n";
-  foreach my $table (sort @tablesWithoutIndexes) {
-    print "\t\"$table\",\n";
-  }
-  print ");\n";
-}
-if ( scalar(@sequences) > 1 ) {
-  print '@SEQUENCES=(' . "\n";
-  foreach my $table (sort @sequences) {
-    print "\t\"$table\",\n";
-  }
-  print ");\n";
-}
-exit 0;
-
-sub usage {
-  print "$usage";
-  exit 0;
-}
--- tools/altperl/update_nodes.pl
+++ /dev/null
@@ -1,37 +0,0 @@
-#!@@PERL@@
-# $Id: update_nodes.pl,v 1.7 2005/02/22 17:11:18 smsimms Exp $
-# Author: Christopher Browne
-# Copyright 2004 Afilias Canada
-
-use Getopt::Long;
-
-# Defaults
-$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
-$SHOW_USAGE  = 0;
-
-# Read command-line options
-GetOptions("config=s" => \$CONFIG_FILE,
-	   "help"     => \$SHOW_USAGE);
-
-my $USAGE =
-"Usage: update_nodes [--config file]
-
-    Updates the functions on all nodes.
-
-";
-
-if ($SHOW_USAGE) {
-  print $USAGE;
-  exit 0;
-}
-
-require '@@PGLIBDIR@@/slon-tools.pm';
-require $CONFIG_FILE;
-
-open(SLONIK, ">", "/tmp/update_nodes.$$");
-print SLONIK genheader();
-foreach my $node (@NODES) {
-  print SLONIK "  update functions (id = $node);\n";
-};
-close SLONIK;
-run_slonik_script("/tmp/update_nodes.$$");
--- /dev/null
+++ tools/altperl/slonik_merge_sets.pl
@@ -0,0 +1,66 @@
+#!@@PERL@@
+# $Id: slonik_merge_sets.pl,v 1.1 2005/05/31 16:11:05 cbbrowne Exp $
+# Author: Christopher Browne
+# Copyright 2004 Afilias Canada
+
+use Getopt::Long;
+
+# Defaults
+$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
+$SHOW_USAGE  = 0;
+
+# Read command-line options
+GetOptions("config=s" => \$CONFIG_FILE,
+	   "help"     => \$SHOW_USAGE);
+
+my $USAGE =
+"Usage: merge_sets [--config file] node# set# set#
+
+    Merges the contents of the second set into the first one.
+
+";
+
+if ($SHOW_USAGE) {
+  print $USAGE;
+  exit 0;
+}
+
+require '@@PGLIBDIR@@/slon-tools.pm';
+require $CONFIG_FILE;
+
+my ($node, $set1, $set2) = @ARGV;
+if ($node =~ /^(?:node)?(\d+)$/) {
+  # Set name is in proper form
+  $node = $1;
+} else {
+  print "Valid node names are node1, node2, ...\n\n";
+  die $USAGE;
+}
+
+if ($set1 =~ /^(?:set)?(\d+)$/) {
+  $set1 = $1;
+} else {
+  print "Valid set names are set1, set2, ...\n\n";
+  die $USAGE;
+}
+
+if ($set2 =~ /^(?:set)?(\d+)$/) {
+  $set2 = $1;
+} else {
+  print "Valid set names are set1, set2, ...\n\n";
+  die $USAGE;
+}
+
+my ($dbname, $dbhost) = ($DBNAME[$MASTERNODE], $HOST[$MASTERNODE]);
+
+open(SLONIK, ">", "/tmp/slonik.$$");
+print SLONIK genheader();
+print SLONIK "  try {\n";
+print SLONIK "    merge set (id = $set1, add id = $set2, origin = $node);\n";
+print SLONIK "  } on error {\n";
+print SLONIK "    echo 'Failure to merge sets $set1 and $set2 with origin $node';\n";
+print SLONIK "    exit 1;\n";
+print SLONIK "  }\n";
+print SLONIK "  echo 'Replication set $set2 merged in with $set1 on origin $node';\n";
+close SLONIK;
+run_slonik_script("/tmp/slonik.$$");
--- /dev/null
+++ tools/altperl/slony_show_configuration.pl
@@ -0,0 +1,56 @@
+#!@@PERL@@
+# $Id: slony_show_configuration.pl,v 1.1 2005/05/31 16:11:05 cbbrowne Exp $
+# Author: Christopher Browne
+# Copyright 2004 Afilias Canada
+
+# This script simply displays an overview of node configuration
+# for a given SLONY node set
+
+use Getopt::Long;
+
+# Defaults
+$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
+$SHOW_USAGE  = 0;
+
+# Read command-line options
+GetOptions("config=s" => \$CONFIG_FILE,
+	   "help"     => \$SHOW_USAGE);
+
+my $USAGE =
+"Usage: show_configuration [--config file]
+
+";
+
+if ($SHOW_USAGE) {
+  print $USAGE;
+  exit 0;
+}
+
+require '@@PGLIBDIR@@/slon-tools.pm';
+require $CONFIG_FILE;
+
+print "Slony Configuration\n-------------------------------------\n";
+if ($ENV{"SLONYNODES"}) {
+  print "With node configuration from ", $ENV{"SLONYNODES"}, "\n";
+}
+if ($ENV{"SLONYSET"}) {
+  print "With set configuration from ", $ENV{"SLONYSET"}, "\n";
+}
+
+print qq{
+Slony-I Cluster: $CLUSTER_NAME
+Logs stored under $LOGDIR
+Slony Binaries in: @@PGBINDIR@@
+};
+if ($APACHE_ROTATOR) {
+  print "Rotating logs using Apache Rotator: $APACHE_ROTATOR\n";
+}
+print qq{
+Node information
+--------------------------------
+};
+foreach $node (@NODES) {
+  printf("Node: %2d Host: %15s User: %8s Port: %4d Forwarding? %4s Parent: %2d Database: %10s\n         DSN: %s\n",
+	 $node, $HOST[$node], $USER[$node], $PORT[$node], $NOFORWARD[$node],
+	 $PARENT[$node], $DBNAME[$node], $DSN[$node]);
+}
--- tools/altperl/merge_sets.pl
+++ /dev/null
@@ -1,66 +0,0 @@
-#!@@PERL@@
-# $Id: merge_sets.pl,v 1.9 2005/02/22 17:11:18 smsimms Exp $
-# Author: Christopher Browne
-# Copyright 2004 Afilias Canada
-
-use Getopt::Long;
-
-# Defaults
-$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
-$SHOW_USAGE  = 0;
-
-# Read command-line options
-GetOptions("config=s" => \$CONFIG_FILE,
-	   "help"     => \$SHOW_USAGE);
-
-my $USAGE =
-"Usage: merge_sets [--config file] node# set# set#
-
-    Merges the contents of the second set into the first one.
-
-";
-
-if ($SHOW_USAGE) {
-  print $USAGE;
-  exit 0;
-}
-
-require '@@PGLIBDIR@@/slon-tools.pm';
-require $CONFIG_FILE;
-
-my ($node, $set1, $set2) = @ARGV;
-if ($node =~ /^(?:node)?(\d+)$/) {
-  # Set name is in proper form
-  $node = $1;
-} else {
-  print "Valid node names are node1, node2, ...\n\n";
-  die $USAGE;
-}
-
-if ($set1 =~ /^(?:set)?(\d+)$/) {
-  $set1 = $1;
-} else {
-  print "Valid set names are set1, set2, ...\n\n";
-  die $USAGE;
-}
-
-if ($set2 =~ /^(?:set)?(\d+)$/) {
-  $set2 = $1;
-} else {
-  print "Valid set names are set1, set2, ...\n\n";
-  die $USAGE;
-}
-
-my ($dbname, $dbhost) = ($DBNAME[$MASTERNODE], $HOST[$MASTERNODE]);
-
-open(SLONIK, ">", "/tmp/slonik.$$");
-print SLONIK genheader();
-print SLONIK "  try {\n";
-print SLONIK "    merge set (id = $set1, add id = $set2, origin = $node);\n";
-print SLONIK "  } on error {\n";
-print SLONIK "    echo 'Failure to merge sets $set1 and $set2 with origin $node';\n";
-print SLONIK "    exit 1;\n";
-print SLONIK "  }\n";
-print SLONIK "  echo 'Replication set $set2 merged in with $set1 on origin $node';\n";
-close SLONIK;
-run_slonik_script("/tmp/slonik.$$");
--- /dev/null
+++ tools/altperl/slonik_drop_set.pl
@@ -0,0 +1,51 @@
+#!@@PERL@@
+# $Id: slonik_drop_set.pl,v 1.1 2005/05/31 16:11:05 cbbrowne Exp $
+# Author: Christopher Browne
+# Copyright 2004 Afilias Canada
+
+use Getopt::Long;
+
+# Defaults
+$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
+$SHOW_USAGE  = 0;
+
+# Read command-line options
+GetOptions("config=s" => \$CONFIG_FILE,
+	   "help"     => \$SHOW_USAGE);
+
+my $USAGE =
+"Usage: drop_set [--config file] set#
+
+    Drops a set.
+
+";
+
+if ($SHOW_USAGE) {
+  print $USAGE;
+  exit 0;
+}
+
+require '@@PGLIBDIR@@/slon-tools.pm';
+require $CONFIG_FILE;
+
+my ($set) = @ARGV;
+if ($set =~ /^(?:set)?(\d+)$/) {
+  $set = $1;
+} else {
+  print "Need set identifier\n";
+  die $USAGE;
+}
+
+get_set($set) or die "Non-existent set specified.\n";
+
+$FILE = "/tmp/dropset.$$";
+open(SLONIK, ">", $FILE);
+print SLONIK genheader();
+print SLONIK "  try {\n";
+print SLONIK "        drop set (id = $set, origin = $SET_ORIGIN);\n";
+print SLONIK "  } on error {\n";
+print SLONIK "        exit 1;\n";
+print SLONIK "  }\n";
+print SLONIK "  echo 'Dropped set $set';\n";
+close SLONIK;
+run_slonik_script($FILE);
--- /dev/null
+++ tools/altperl/slonik_restart_node.pl
@@ -0,0 +1,57 @@
+#!/usr/bin/perl
+# $Id: slonik_restart_node.pl,v 1.1 2005/05/31 16:11:05 cbbrowne Exp $
+# Author: Christopher Browne
+# Copyright 2004 Afilias Canada
+
+use Getopt::Long;
+
+# Defaults
+$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
+$SHOW_USAGE  = 0;
+$ALL_NODES   = 0;
+
+# Read command-line options
+GetOptions("config=s" => \$CONFIG_FILE,
+	   "help"     => \$SHOW_USAGE,
+	   "all"      => \$ALL_NODES);
+
+my $USAGE =
+"Usage: restart_node [--config file] [--all] [node# ...]
+
+    Restart one or more nodes
+
+";
+
+if ($SHOW_USAGE) {
+  print $USAGE;
+  exit 0;
+}
+
+require '@@PGLIBDIR@@/slon-tools.pm';
+require $CONFIG_FILE;
+
+my @nodes;
+if ($ALL_NODES) {
+    @nodes = @NODES;
+}
+else {
+    foreach my $node (@ARGV) {
+	if ($node =~ /^(?:node)?(\d+)$/) {
+	    push @nodes, ($1);
+	}
+	else {
+	    die $USAGE;
+	}
+    }
+}
+
+die $USAGE unless scalar @nodes;
+
+my $FILE="/tmp/restart.$$";
+open(SLONIK, ">", $FILE);
+print SLONIK genheader();
+foreach my $node (@nodes) {
+    print SLONIK "  restart node $node;\n";
+}
+close SLONIK;
+run_slonik_script($FILE);
--- tools/altperl/drop_set.pl
+++ /dev/null
@@ -1,51 +0,0 @@
-#!@@PERL@@
-# $Id: drop_set.pl,v 1.10 2005/02/23 20:30:51 smsimms Exp $
-# Author: Christopher Browne
-# Copyright 2004 Afilias Canada
-
-use Getopt::Long;
-
-# Defaults
-$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
-$SHOW_USAGE  = 0;
-
-# Read command-line options
-GetOptions("config=s" => \$CONFIG_FILE,
-	   "help"     => \$SHOW_USAGE);
-
-my $USAGE =
-"Usage: drop_set [--config file] set#
-
-    Drops a set.
-
-";
-
-if ($SHOW_USAGE) {
-  print $USAGE;
-  exit 0;
-}
-
-require '@@PGLIBDIR@@/slon-tools.pm';
-require $CONFIG_FILE;
-
-my ($set) = @ARGV;
-if ($set =~ /^(?:set)?(\d+)$/) {
-  $set = $1;
-} else {
-  print "Need set identifier\n";
-  die $USAGE;
-}
-
-get_set($set) or die "Non-existent set specified.\n";
-
-$FILE = "/tmp/dropset.$$";
-open(SLONIK, ">", $FILE);
-print SLONIK genheader();
-print SLONIK "  try {\n";
-print SLONIK "        drop set (id = $set, origin = $SET_ORIGIN);\n";
-print SLONIK "  } on error {\n";
-print SLONIK "        exit 1;\n";
-print SLONIK "  }\n";
-print SLONIK "  echo 'Dropped set $set';\n";
-close SLONIK;
-run_slonik_script($FILE);
--- /dev/null
+++ tools/altperl/slonik_failover.pl
@@ -0,0 +1,58 @@
+#!@@PERL@@
+# $Id: slonik_failover.pl,v 1.1 2005/05/31 16:11:05 cbbrowne Exp $
+# Author: Christopher Browne
+# Copyright 2004 Afilias Canada
+
+use Getopt::Long;
+
+# Defaults
+$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
+$SHOW_USAGE  = 0;
+
+# Read command-line options
+GetOptions("config=s" => \$CONFIG_FILE,
+	   "help"     => \$SHOW_USAGE);
+
+my $USAGE =
+"Usage: failover [--config file] dead_node backup_node
+
+    Abandons dead_node, making backup_node the origin for all sets on
+    dead_node.
+
+    move_set should be used if dead_node is still available, so that
+    transactions are not lost.
+
+";
+
+if ($SHOW_USAGE) {
+  print $USAGE;
+  exit 0;
+}
+
+require '@@PGLIBDIR@@/slon-tools.pm';
+require $CONFIG_FILE;
+
+my ($node1, $node2) = @ARGV;
+if ($node1 =~ /^(?:node)?(\d+)$/) {
+  $node1 = $1;
+} else {
+  die $USAGE;
+}
+
+if ($node2 =~ /^(?:node)?(\d+)$/) {
+  $node2 = $1;
+} else {
+  die $USAGE;
+}
+
+open(SLONIK, ">", "/tmp/slonik.$$");
+print SLONIK genheader();
+print SLONIK "  try {\n";
+print SLONIK "      failover (id = $node1, backup node = $node2);\n";
+print SLONIK "  } on error {\n";
+print SLONIK "      echo 'Failure to fail node $node1 over to $node2';\n";
+print SLONIK "      exit 1;\n";
+print SLONIK "  }\n";
+print SLONIK "  echo 'Replication sets originating on $node1 failed over to $node2';\n";
+close SLONIK;
+run_slonik_script("/tmp/slonik.$$");
--- /dev/null
+++ tools/altperl/slonik_unsubscribe_set.pl
@@ -0,0 +1,57 @@
+#!@@PERL@@
+# $Id: slonik_unsubscribe_set.pl,v 1.1 2005/05/31 16:11:05 cbbrowne Exp $
+# Author: Christopher Browne
+# Copyright 2004 Afilias Canada
+
+use Getopt::Long;
+
+# Defaults
+$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
+$SHOW_USAGE  = 0;
+
+# Read command-line options
+GetOptions("config=s" => \$CONFIG_FILE,
+	   "help"     => \$SHOW_USAGE);
+
+my $USAGE =
+"Usage: unsubscribe_set [--config file] set# node#
+
+    Stops replicating a set on the specified node.
+
+";
+
+if ($SHOW_USAGE) {
+  print $USAGE;
+  exit 0;
+}
+
+require '@@PGLIBDIR@@/slon-tools.pm';
+require $CONFIG_FILE;
+
+my ($set, $node) = @ARGV;
+if ($node =~ /^(?:node)?(\d+)$/) {
+  $node = $1;
+} else {
+  print "Need to specify node!\n\n";
+  die $USAGE;
+}
+
+if ($set =~ /^(?:set)?(\d+)$/) {
+  $set = $1;
+} else {
+  print "Need to specify set!\n\n";
+  die $USAGE;
+}
+
+open(SLONIK, ">", "/tmp/slonik-unsubscribe.$$");
+print SLONIK genheader();
+print SLONIK "  try {\n";
+print SLONIK "      unsubscribe set (id = $set, receiver = $node);\n";
+print SLONIK "  }\n";
+print SLONIK "  on error {\n";
+print SLONIK "      echo 'Failed to unsubscribe node $node from set $set';\n";
+print SLONIK "      exit 1;\n";
+print SLONIK "  }\n";
+print SLONIK "  echo 'unsubscribed node $node from set $set';\n";
+close SLONIK;
+run_slonik_script("/tmp/slonik-unsubscribe.$$");
--- tools/altperl/unsubscribe_set.pl
+++ /dev/null
@@ -1,57 +0,0 @@
-#!@@PERL@@
-# $Id: unsubscribe_set.pl,v 1.7 2005/02/22 16:51:10 smsimms Exp $
-# Author: Christopher Browne
-# Copyright 2004 Afilias Canada
-
-use Getopt::Long;
-
-# Defaults
-$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
-$SHOW_USAGE  = 0;
-
-# Read command-line options
-GetOptions("config=s" => \$CONFIG_FILE,
-	   "help"     => \$SHOW_USAGE);
-
-my $USAGE =
-"Usage: unsubscribe_set [--config file] set# node#
-
-    Stops replicating a set on the specified node.
-
-";
-
-if ($SHOW_USAGE) {
-  print $USAGE;
-  exit 0;
-}
-
-require '@@PGLIBDIR@@/slon-tools.pm';
-require $CONFIG_FILE;
-
-my ($set, $node) = @ARGV;
-if ($node =~ /^(?:node)?(\d+)$/) {
-  $node = $1;
-} else {
-  print "Need to specify node!\n\n";
-  die $USAGE;
-}
-
-if ($set =~ /^(?:set)?(\d+)$/) {
-  $set = $1;
-} else {
-  print "Need to specify set!\n\n";
-  die $USAGE;
-}
-
-open(SLONIK, ">", "/tmp/slonik-unsubscribe.$$");
-print SLONIK genheader();
-print SLONIK "  try {\n";
-print SLONIK "      unsubscribe set (id = $set, receiver = $node);\n";
-print SLONIK "  }\n";
-print SLONIK "  on error {\n";
-print SLONIK "      echo 'Failed to unsubscribe node $node from set $set';\n";
-print SLONIK "      exit 1;\n";
-print SLONIK "  }\n";
-print SLONIK "  echo 'unsubscribed node $node from set $set';\n";
-close SLONIK;
-run_slonik_script("/tmp/slonik-unsubscribe.$$");
--- tools/altperl/failover.pl
+++ /dev/null
@@ -1,58 +0,0 @@
-#!@@PERL@@
-# $Id: failover.pl,v 1.8 2005/02/22 16:51:09 smsimms Exp $
-# Author: Christopher Browne
-# Copyright 2004 Afilias Canada
-
-use Getopt::Long;
-
-# Defaults
-$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
-$SHOW_USAGE  = 0;
-
-# Read command-line options
-GetOptions("config=s" => \$CONFIG_FILE,
-	   "help"     => \$SHOW_USAGE);
-
-my $USAGE =
-"Usage: failover [--config file] dead_node backup_node
-
-    Abandons dead_node, making backup_node the origin for all sets on
-    dead_node.
-
-    move_set should be used if dead_node is still available, so that
-    transactions are not lost.
-
-";
-
-if ($SHOW_USAGE) {
-  print $USAGE;
-  exit 0;
-}
-
-require '@@PGLIBDIR@@/slon-tools.pm';
-require $CONFIG_FILE;
-
-my ($node1, $node2) = @ARGV;
-if ($node1 =~ /^(?:node)?(\d+)$/) {
-  $node1 = $1;
-} else {
-  die $USAGE;
-}
-
-if ($node2 =~ /^(?:node)?(\d+)$/) {
-  $node2 = $1;
-} else {
-  die $USAGE;
-}
-
-open(SLONIK, ">", "/tmp/slonik.$$");
-print SLONIK genheader();
-print SLONIK "  try {\n";
-print SLONIK "      failover (id = $node1, backup node = $node2);\n";
-print SLONIK "  } on error {\n";
-print SLONIK "      echo 'Failure to fail node $node1 over to $node2';\n";
-print SLONIK "      exit 1;\n";
-print SLONIK "  }\n";
-print SLONIK "  echo 'Replication sets originating on $node1 failed over to $node2';\n";
-close SLONIK;
-run_slonik_script("/tmp/slonik.$$");
--- tools/altperl/restart_node.pl
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/usr/bin/perl
-# $Id: restart_node.pl,v 1.7 2005/02/22 16:51:09 smsimms Exp $
-# Author: Christopher Browne
-# Copyright 2004 Afilias Canada
-
-use Getopt::Long;
-
-# Defaults
-$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
-$SHOW_USAGE  = 0;
-$ALL_NODES   = 0;
-
-# Read command-line options
-GetOptions("config=s" => \$CONFIG_FILE,
-	   "help"     => \$SHOW_USAGE,
-	   "all"      => \$ALL_NODES);
-
-my $USAGE =
-"Usage: restart_node [--config file] [--all] [node# ...]
-
-    Restart one or more nodes
-
-";
-
-if ($SHOW_USAGE) {
-  print $USAGE;
-  exit 0;
-}
-
-require '@@PGLIBDIR@@/slon-tools.pm';
-require $CONFIG_FILE;
-
-my @nodes;
-if ($ALL_NODES) {
-    @nodes = @NODES;
-}
-else {
-    foreach my $node (@ARGV) {
-	if ($node =~ /^(?:node)?(\d+)$/) {
-	    push @nodes, ($1);
-	}
-	else {
-	    die $USAGE;
-	}
-    }
-}
-
-die $USAGE unless scalar @nodes;
-
-my $FILE="/tmp/restart.$$";
-open(SLONIK, ">", $FILE);
-print SLONIK genheader();
-foreach my $node (@nodes) {
-    print SLONIK "  restart node $node;\n";
-}
-close SLONIK;
-run_slonik_script($FILE);
Index: ToDo
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/tools/altperl/ToDo,v
retrieving revision 1.3
retrieving revision 1.4
diff -Ltools/altperl/ToDo -Ltools/altperl/ToDo -u -w -r1.3 -r1.4
--- tools/altperl/ToDo
+++ tools/altperl/ToDo
@@ -1,13 +1,17 @@
+ToDo List
+----------------
+$Id$
+
 - Need to write a "repair_cluster.pl" script that 
   modifies configuration to reflect new configuration,
   dropping and adding paths and listeners.
 
-  This would compare the configuration computed (as in init_cluster)
-  with the configuration actually found on some node, add "additional"
-  bits, and drop obsolete bits.
+  This would compare the configuration computed (as in
+  slonik_init_cluster) with the configuration actually found on some
+  node, add "additional" bits, and drop obsolete bits.
 
-  [Note: If drop_node and store_node are used, this may not be as
-  immediately necessary, but would still be nice to have.]
+  [Note: If slonik_drop_node and slonik_store_node are used, this may
+  not be as immediately necessary, but would still be nice to have.]
 
 - At present, the configuration generated by this set of tools is
   fairly fragile.  If just about any sort of error is made, it is
--- tools/altperl/execute_script.pl
+++ /dev/null
@@ -1,92 +0,0 @@
-#!@@PERL@@
-# $Id: execute_script.pl,v 1.2 2005/03/16 21:15:10 smsimms Exp $
-# Author: Christopher Browne
-# Copyright 2004 Afilias Canada
-
-use Getopt::Long;
-
-# Defaults
-$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
-$SHOW_USAGE  = 0;
-$SCRIPT_ARG  = "";
-
-# Allow this to be specified.  Otherwise it will be pulled from
-# the get_set function.
-$node = 0;
-
-# Read command-line options
-GetOptions("config=s" => \$CONFIG_FILE,
-	   "help"     => \$SHOW_USAGE,
-	   "c=s"      => \$SCRIPT_ARG,
-           "n|node=s" => \$node);
-
-my $USAGE =
-"Usage:
-    execute_script [options] set# full_path_to_sql_script_file
-    execute_script [options] -c SCRIPT set#
-
-    Executes the contents of a SQL script file on the specified set.
-    The script only needs to exist on the machine running the slon
-    daemon.
-
-    set#        The set to which this script applies.
-
-    -c SCRIPT   Pass the SQL to be executed via the command line instead
-                of as a file.
-
-    -n NUM
-    --node=NUM  Override the set origin specified in the configuration
-                file.
-
-";
-
-if ($SHOW_USAGE) {
-  print $USAGE;
-  exit 0;
-}
-
-require '@@PGLIBDIR@@/slon-tools.pm';
-require $CONFIG_FILE;
-
-my ($set, $file) = @ARGV;
-if ($set =~ /^(?:set)?(\d+)$/) {
-  $set = $1;
-} else {
-  print "Invalid set identifier\n\n";
-  die $USAGE;
-}
-
-get_set($set) or die "Non-existent set specified.\n";
-$node = $SET_ORIGIN unless $node;
-
-# We can either have -c SCRIPT or a filename as an argument.  The
-# latter takes precedence.
-if ($file) {
-    unless ($file =~ /^\// and -f $file) {
-	print STDERR "SQL script path needs to be a full path, e.g. /tmp/my_script.sql\n\n";
-	die $USAGE;
-    }
-}
-elsif ($SCRIPT_ARG) {
-    # Put the script into a file
-    $file = "/tmp/execute_script.sql.$$";
-    my $fh;
-    open $fh, ">", $file;
-    print $fh $SCRIPT_ARG;
-    close $fh;
-}
-else {
-    print STDERR "You must include either a filename or a SQL statement on the command line to be run.\n\n";
-    die $USAGE;
-}
-
-my $FILE="/tmp/gensql.$$";
-open(SLONIK, ">", $FILE);
-print SLONIK genheader();
-print SLONIK "  execute script (\n";
-print SLONIK "    set id = $set,\n";
-print SLONIK "    filename = '$file',\n";
-print SLONIK "    event node = $node\n";
-print SLONIK "  );\n";
-close SLONIK;
-run_slonik_script($FILE);
--- tools/altperl/uninstall_nodes.pl
+++ /dev/null
@@ -1,40 +0,0 @@
-#!@@PERL@@
-# $Id: uninstall_nodes.pl,v 1.8 2005/03/11 18:55:44 smsimms Exp $
-# Author: Christopher Browne
-# Copyright 2004 Afilias Canada
-
-use Getopt::Long;
-
-# Defaults
-$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
-$SHOW_USAGE  = 0;
-
-# Read command-line options
-GetOptions("config=s" => \$CONFIG_FILE,
-	   "help"     => \$SHOW_USAGE);
-
-my $USAGE =
-"Usage: uninstall_nodes [--config file]
-
-    Removes Slony configuration from all nodes in a cluster.
-
-";
-
-if ($SHOW_USAGE) {
-  print $USAGE;
-  exit 0;
-}
-
-require '@@PGLIBDIR@@/slon-tools.pm';
-require $CONFIG_FILE;
-
-$FILE="/tmp/slonik.$$";
-open(SLONIK, ">$FILE");
-print SLONIK genheader();
-foreach my $node (@NODES) {
-    next if $node == $MASTERNODE; # Do this one last
-    print SLONIK "  uninstall node (id=$node);\n";
-}
-print SLONIK "  uninstall node (id=$MASTERNODE);\n";
-close SLONIK;
-run_slonik_script($FILE);
--- /dev/null
+++ tools/altperl/slonik_store_node.pl
@@ -0,0 +1,233 @@
+#!@@PERL@@
+# $Id: slonik_store_node.pl,v 1.1 2005/05/31 16:11:05 cbbrowne Exp $
+# Author: Steve Simms
+# Copyright 2005 PostgreSQL Global Development Group
+
+use Getopt::Long;
+
+# Defaults
+my $CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
+my $SHOW_USAGE  = 0;
+
+# Read command-line options
+GetOptions("config=s" => \$CONFIG_FILE,
+	   "help"     => \$SHOW_USAGE);
+
+my $USAGE =
+"Usage: store_node [--config file] node#
+
+    Generates the slonik commands necessary to add a node to a
+    cluster.  Also displays a report showing the relationships between
+    the various nodes.
+
+";
+
+if ($SHOW_USAGE) {
+  print $USAGE;
+  exit 0;
+}
+
+require '@@PGLIBDIR@@/slon-tools.pm';
+require $CONFIG_FILE;
+
+$node = $ARGV[0];
+
+# Node can be passed either as "node1" or just "1"
+if ($node =~ /^(?:node)?(\d+)$/) {
+  $node = $1;
+} else {
+  die $USAGE;
+}
+
+my $FILE="/tmp/store_node.$$";
+
+open(SLONIK, ">", $FILE);
+print SLONIK genheader();
+
+# STORE NODE
+print SLONIK "\n# STORE NODE\n";
+my ($dbname, $dbhost) = ($DBNAME[$node], $HOST[$node]);
+print SLONIK "  store node (id = $node, event node = $MASTERNODE, comment = 'Node $node - $dbname\@$dbhost');\n";
+print SLONIK "  echo 'Set up replication nodes';\n";
+
+# STORE PATH
+print SLONIK "\n# STORE PATH\n";
+
+my @COST;
+my @VIA;
+my @PATH;
+generate_listen_paths();
+
+print SLONIK "  echo 'Next: configure paths for each node/origin';\n";
+foreach my $nodea (@NODES) {
+    my $dsna = $DSN[$nodea];
+    foreach my $nodeb (@NODES) {
+	if ($nodea != $nodeb) {
+	    next unless ($node == $nodea or $node == $nodeb);
+	    my $dsnb = $DSN[$nodeb];
+	    my $providerba = $VIA[$nodea][$nodeb];
+	    my $providerab = $VIA[$nodeb][$nodea];
+	    if (!$printed[$nodea][$nodeb] and $providerab == $nodea) {
+		print SLONIK "  store path (server = $nodea, client = $nodeb, conninfo = '$dsna');\n";
+		$printed[$nodea][$nodeb] = "done";
+	    }
+	    if (!$printed[$nodeb][$nodea] and $providerba == $nodea) {
+		print SLONIK "  store path (server = $nodeb, client = $nodea, conninfo = '$dsnb');\n";
+		$printed[$nodeb][$nodea] = "done";
+	    }
+	}
+    }
+}
+
+# STORE LISTEN
+print SLONIK "\n# STORE LISTEN\n";
+foreach my $origin (@NODES) {
+    my $dsna = $DSN[$origin];
+    foreach my $receiver (@NODES) {
+	if ($origin != $receiver) {
+	    my $provider = $VIA[$origin][$receiver];
+	    next unless ($node == $origin   or
+			 $node == $receiver or
+			 $node == $provider);
+	    print SLONIK "  store listen (origin = $origin, receiver = $receiver, provider = $provider);\n";
+	}
+    }
+}
+print SLONIK "  echo 'Replication nodes prepared';\n";
+print SLONIK "  echo 'Please start a slon replication daemon for each node';\n";
+close SLONIK;
+run_slonik_script($FILE);
+report_on_paths();
+
+sub generate_listen_paths {
+  my $infinity = 10000000;	# Initial costs are all infinite
+  foreach my $node1 (@NODES) {
+    foreach my $node2 (@NODES) {
+      $COST[$node1][$node2] = $infinity;
+    }
+  }
+
+  # Initialize paths between parents and children, and based on them,
+  # generate initial seeding of listener paths, @VIA
+
+  foreach my $node1 (@NODES) {
+    $COST[$node1][$node1] = 0;
+    $VIA[$node1][$node1] = 0;
+    foreach my $node2 (@NODES) {
+      if ($node2 != $node1) {
+	if ((not ($PARENT[$node1] or $PARENT[$node2])) or
+	    ($PARENT[$node1] and $PARENT[$node1] == $node2) or
+	    ($PARENT[$node2] and $PARENT[$node2] == $node1)) {
+	  $PATH[$node1][$node2] = 1;
+	  $PATH[$node2][$node1] = 1;
+	  # Set up a cost 1 path between them
+	  # Parent to child
+	  $COST[$node1][$node2] = 1;
+	  $VIA[$node1][$node2] = $node1;
+
+	  # Child to parent
+	  $COST[$node2][$node1] = 1;
+	  $VIA[$node2][$node1] = $node2;
+	}
+      }
+    }
+  }
+
+  # Now, update the listener paths...
+  # 4 level nested iteration:
+  # 1 while not done, do
+  #   2 for each node, node1
+  #     3 for each node, node2, where node2 <> node1, where we don't
+  #           yet have a listener path
+  #       4 for each node node3 (<> node1 or node2),
+  #          consider introducing the listener path:
+  #                 node1 to node2 then node2 to node3
+  # In concept, it's an O(n^4) algorithm; since the number of nodes, n,
+  # is not likely to get particularly large, it's not worth tuning
+  # further.
+  $didwork = "yes";
+  while ($didwork eq "yes") {
+    $didwork = "no";
+    foreach my $node1 (@NODES) {
+      foreach my $node3 (@NODES) {
+	if (($VIA[$node3][$node1] == 0) && ($node3 != $node1)) {
+	  foreach my $node2 (@NODES) {
+	    if ($PATH[$node1][$node2] && ($VIA[$node2][$node3] != 0) && ($node2 != $node3) && ($node2 != $node1)) {
+	      # Consider introducing a path from n1 to n2 then n2 to n3
+	      # as a cheaper alternative to going direct from n1 to n3
+	      my $oldcost = $COST[$node3][$node1];
+	      my $newcost = $COST[$node1][$node2] + $COST[$node2][$node3];
+	      if ($newcost < $oldcost) {
+		$didwork = "yes";
+				# So we go via node 2
+		$VIA[$node3][$node1] = $node2;
+		$COST[$node3][$node1] = $newcost;
+
+		$VIA[$node1][$node3] = $node2;
+		$COST[$node1][$node3] = $newcost;
+	      }
+	    }
+	  }
+	}
+      }
+    }
+  }
+}
+
+sub report_on_paths {
+  print "# Configuration Summary:\n";
+  print "#\n";
+  print "# COST\n";
+  print "#      ";
+  foreach my $node2 (@NODES) {
+    printf "| %3d ", $node2;
+  }
+  print "|\n# ";
+  print ("-----+" x (scalar(@NODES) + 1));
+  print "\n";
+  foreach my $node1 (@NODES) {
+    printf "#  %3d ", $node1;
+    foreach my $node2 (@NODES) {
+      if ($COST[$node2][$node1] == $infinity) {
+	printf "| inf ";
+      } else {
+	printf "|%4d ", $COST[$node2][$node1];
+      }
+    }
+    print "|\n";
+  }
+  print "# \n";
+  print "# VIA\n";
+  print "#      ";
+  foreach my $node2 (@NODES) {
+    printf "| %3d ", $node2;
+  }
+  print "|\n# ";
+  print ("-----+" x (scalar(@NODES) + 1));
+  print "\n";
+  foreach my $node1 (@NODES) {
+    printf "#  %3d ", $node1;
+    foreach my $node2 (@NODES) {
+      printf "|%4d ", $VIA[$node2][$node1];
+    }
+    print "|\n";
+  }
+
+  print "# \n";
+  print "# PATHS\n";
+  print "#      ";
+  foreach my $node2 (@NODES) {
+    printf "| %3d ", $node2;
+  }
+  print "|\n# ";
+  print ("-----+" x (scalar(@NODES) + 1));
+  print "\n";
+  foreach my $node1 (@NODES) {
+    printf "#  %3d ", $node1;
+    foreach my $node2 (@NODES) {
+      printf "|%4d ", $PATH[$node2][$node1];
+    }
+    print "|\n";
+  }
+  print "\n";
+}
--- /dev/null
+++ tools/altperl/slonik_init_cluster.pl
@@ -0,0 +1,228 @@
+#!@@PERL@@
+# $Id: slonik_init_cluster.pl,v 1.1 2005/05/31 16:11:05 cbbrowne Exp $
+# Author: Christopher Browne
+# Copyright 2004 Afilias Canada
+
+use Getopt::Long;
+
+# Defaults
+my $CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
+my $SHOW_USAGE  = 0;
+
+# Read command-line options
+GetOptions("config=s" => \$CONFIG_FILE,
+	   "help"     => \$SHOW_USAGE);
+
+my $USAGE =
+"Usage: init_cluster [--config file]
+
+    Generates the slonik commands necessary to create a cluster and
+    prepare the nodes for use.  Also displays a report showing the
+    relationships between the various nodes.
+
+";
+
+if ($SHOW_USAGE) {
+  print $USAGE;
+  exit 0;
+}
+
+require '@@PGLIBDIR@@/slon-tools.pm';
+require $CONFIG_FILE;
+
+my $FILE="/tmp/init-cluster.$$";
+
+# INIT CLUSTER
+open(SLONIK, ">", $FILE);
+print SLONIK "\n# INIT CLUSTER\n";
+print SLONIK genheader();
+my ($dbname, $dbhost) = ($DBNAME[$MASTERNODE], $HOST[$MASTERNODE]);
+print SLONIK "  init cluster (id = $MASTERNODE, comment = 'Node $MASTERNODE - $dbname\@$dbhost');\n";
+
+# STORE NODE
+print SLONIK "\n# STORE NODE\n";
+foreach my $node (@NODES) {
+  if ($node != $MASTERNODE) {		# skip the master node; it's already initialized!
+    my ($dbname, $dbhost) = ($DBNAME[$node], $HOST[$node]);
+    print SLONIK "  store node (id = $node, event node = $MASTERNODE, comment = 'Node $node - $dbname\@$dbhost');\n";
+  }
+}
+print SLONIK "  echo 'Set up replication nodes';\n";
+
+# STORE PATH
+print SLONIK "\n# STORE PATH\n";
+
+my @COST;
+my @VIA;
+my @PATH;
+generate_listen_paths();
+
+print SLONIK "  echo 'Next: configure paths for each node/origin';\n";
+foreach my $nodea (@NODES) {
+  my $dsna = $DSN[$nodea];
+  foreach my $nodeb (@NODES) {
+    if ($nodea != $nodeb) {
+      my $dsnb = $DSN[$nodeb];
+      my $providerba = $VIA[$nodea][$nodeb];
+      my $providerab = $VIA[$nodeb][$nodea];
+      if (!$printed[$nodea][$nodeb] and $providerab == $nodea) {
+	print SLONIK "  store path (server = $nodea, client = $nodeb, conninfo = '$dsna');\n";
+	$printed[$nodea][$nodeb] = "done";
+      }
+      if (!$printed[$nodeb][$nodea] and $providerba == $nodea) {
+	print SLONIK "  store path (server = $nodeb, client = $nodea, conninfo = '$dsnb');\n";
+	$printed[$nodeb][$nodea] = "done";
+      }
+    }
+  }
+}
+
+# STORE LISTEN
+print SLONIK "\n# STORE LISTEN\n";
+foreach my $origin (@NODES) {
+  my $dsna = $DSN[$origin];
+  foreach my $receiver (@NODES) {
+    if ($origin != $receiver) {
+      my $provider = $VIA[$origin][$receiver];
+      print SLONIK "  store listen (origin = $origin, receiver = $receiver, provider = $provider);\n";
+    }
+  }
+}
+print SLONIK "  echo 'Replication nodes prepared';\n";
+print SLONIK "  echo 'Please start a slon replication daemon for each node';\n";
+close SLONIK;
+run_slonik_script($FILE);
+report_on_paths();
+
+sub generate_listen_paths {
+  my $infinity = 10000000;	# Initial costs are all infinite
+  foreach my $node1 (@NODES) {
+    foreach my $node2 (@NODES) {
+      $COST[$node1][$node2] = $infinity;
+    }
+  }
+
+  # Initialize paths between parents and children, and based on them,
+  # generate initial seeding of listener paths, @VIA
+
+  foreach my $node1 (@NODES) {
+    $COST[$node1][$node1] = 0;
+    $VIA[$node1][$node1] = 0;
+    foreach my $node2 (@NODES) {
+      if ($node2 != $node1) {
+	if ((not ($PARENT[$node1] or $PARENT[$node2])) or
+	    ($PARENT[$node1] and $PARENT[$node1] == $node2) or
+	    ($PARENT[$node2] and $PARENT[$node2] == $node1)) {
+	  $PATH[$node1][$node2] = 1;
+	  $PATH[$node2][$node1] = 1;
+	  # Set up a cost 1 path between them
+	  # Parent to child
+	  $COST[$node1][$node2] = 1;
+	  $VIA[$node1][$node2] = $node1;
+
+	  # Child to parent
+	  $COST[$node2][$node1] = 1;
+	  $VIA[$node2][$node1] = $node2;
+	}
+      }
+    }
+  }
+
+  # Now, update the listener paths...
+  # 4 level nested iteration:
+  # 1 while not done, do
+  #   2 for each node, node1
+  #     3 for each node, node2, where node2 <> node1, where we don't
+  #           yet have a listener path
+  #       4 for each node node3 (<> node1 or node2),
+  #          consider introducing the listener path:
+  #                 node1 to node2 then node2 to node3
+  # In concept, it's an O(n^4) algorithm; since the number of nodes, n,
+  # is not likely to get particularly large, it's not worth tuning
+  # further.
+  $didwork = "yes";
+  while ($didwork eq "yes") {
+    $didwork = "no";
+    foreach my $node1 (@NODES) {
+      foreach my $node3 (@NODES) {
+	if (($VIA[$node3][$node1] == 0) && ($node3 != $node1)) {
+	  foreach my $node2 (@NODES) {
+	    if ($PATH[$node1][$node2] && ($VIA[$node2][$node3] != 0) && ($node2 != $node3) && ($node2 != $node1)) {
+	      # Consider introducing a path from n1 to n2 then n2 to n3
+	      # as a cheaper alternative to going direct from n1 to n3
+	      my $oldcost = $COST[$node3][$node1];
+	      my $newcost = $COST[$node1][$node2] + $COST[$node2][$node3];
+	      if ($newcost < $oldcost) {
+		$didwork = "yes";
+				# So we go via node 2
+		$VIA[$node3][$node1] = $node2;
+		$COST[$node3][$node1] = $newcost;
+
+		$VIA[$node1][$node3] = $node2;
+		$COST[$node1][$node3] = $newcost;
+	      }
+	    }
+	  }
+	}
+      }
+    }
+  }
+}
+
+sub report_on_paths {
+  print "# Configuration Summary:\n";
+  print "#\n";
+  print "# COST\n";
+  print "#      ";
+  foreach my $node2 (@NODES) {
+    printf "| %3d ", $node2;
+  }
+  print "|\n# ";
+  print ("-----+" x (scalar(@NODES) + 1));
+  print "\n";
+  foreach my $node1 (@NODES) {
+    printf "#  %3d ", $node1;
+    foreach my $node2 (@NODES) {
+      if ($COST[$node2][$node1] == $infinity) {
+	printf "| inf ";
+      } else {
+	printf "|%4d ", $COST[$node2][$node1];
+      }
+    }
+    print "|\n";
+  }
+  print "# \n";
+  print "# VIA\n";
+  print "#      ";
+  foreach my $node2 (@NODES) {
+    printf "| %3d ", $node2;
+  }
+  print "|\n# ";
+  print ("-----+" x (scalar(@NODES) + 1));
+  print "\n";
+  foreach my $node1 (@NODES) {
+    printf "#  %3d ", $node1;
+    foreach my $node2 (@NODES) {
+      printf "|%4d ", $VIA[$node2][$node1];
+    }
+    print "|\n";
+  }
+
+  print "# \n";
+  print "# PATHS\n";
+  print "#      ";
+  foreach my $node2 (@NODES) {
+    printf "| %3d ", $node2;
+  }
+  print "|\n# ";
+  print ("-----+" x (scalar(@NODES) + 1));
+  print "\n";
+  foreach my $node1 (@NODES) {
+    printf "#  %3d ", $node1;
+    foreach my $node2 (@NODES) {
+      printf "|%4d ", $PATH[$node2][$node1];
+    }
+    print "|\n";
+  }
+  print "\n";
+}
--- /dev/null
+++ tools/altperl/slonik_move_set.pl
@@ -0,0 +1,64 @@
+#!@@PERL@@
+# $Id: slonik_move_set.pl,v 1.1 2005/05/31 16:11:05 cbbrowne Exp $
+# Author: Christopher Browne
+# Copyright 2004 Afilias Canada
+
+use Getopt::Long;
+
+# Defaults
+$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
+$SHOW_USAGE  = 0;
+
+# Read command-line options
+GetOptions("config=s" => \$CONFIG_FILE,
+	   "help"     => \$SHOW_USAGE);
+
+my $USAGE =
+"Usage: move_set [--config file] set# from_node# to_node#
+
+    Change a set's origin.
+
+";
+
+if ($SHOW_USAGE) {
+  print $USAGE;
+  exit 0;
+}
+
+require '@@PGLIBDIR@@/slon-tools.pm';
+require $CONFIG_FILE;
+
+my ($set, $node1, $node2) = @ARGV;
+if ($set =~ /^(?:set)?(\d+)$/) {
+  # Node name is in proper form
+  $set = $1;
+} else {
+  print "Valid set names are set1, set2, ...\n\n";
+  die $USAGE;
+}
+
+if ($node1 =~ /^(?:node)?(\d+)$/) {
+  $node1 = $1;
+} else {
+  print "Valid node names are node1, node2, ...\n\n";
+  die $USAGE;
+}
+
+if ($node2 =~ /^(?:node)?(\d+)$/) {
+  $node2 = $1;
+} else {
+  print "Valid node names are node1, node2, ...\n\n";
+  die $USAGE;
+}
+
+open(SLONIK, ">", "/tmp/slonik.$$");
+print SLONIK genheader();
+print SLONIK "  echo 'Locking down set $set on node $node1';\n";
+print SLONIK "  lock set (id = $set, origin = $node1);\n";
+print SLONIK "  echo 'Locked down - moving it';\n";
+print SLONIK "  move set (id = $set, old origin = $node1, new origin = $node2);\n";
+print SLONIK "  echo 'Replication set $set moved from node $node1 to $node2.  Remember to';\n";
+print SLONIK "  echo 'update your configuration file, if necessary, to note the new location';\n";
+print SLONIK "  echo 'for the set.';\n";
+close SLONIK;
+run_slonik_script("/tmp/slonik.$$");
--- /dev/null
+++ tools/altperl/slonik_execute_script.pl
@@ -0,0 +1,92 @@
+#!@@PERL@@
+# $Id: slonik_execute_script.pl,v 1.1 2005/05/31 16:11:05 cbbrowne Exp $
+# Author: Christopher Browne
+# Copyright 2004 Afilias Canada
+
+use Getopt::Long;
+
+# Defaults
+$CONFIG_FILE = '@@SYSCONFDIR@@/slon_tools.conf';
+$SHOW_USAGE  = 0;
+$SCRIPT_ARG  = "";
+
+# Allow this to be specified.  Otherwise it will be pulled from
+# the get_set function.
+$node = 0;
+
+# Read command-line options
+GetOptions("config=s" => \$CONFIG_FILE,
+	   "help"     => \$SHOW_USAGE,
+	   "c=s"      => \$SCRIPT_ARG,
+           "n|node=s" => \$node);
+
+my $USAGE =
+"Usage:
+    execute_script [options] set# full_path_to_sql_script_file
+    execute_script [options] -c SCRIPT set#
+
+    Executes the contents of a SQL script file on the specified set.
+    The script only needs to exist on the machine running the slon
+    daemon.
+
+    set#        The set to which this script applies.
+
+    -c SCRIPT   Pass the SQL to be executed via the command line instead
+                of as a file.
+
+    -n NUM
+    --node=NUM  Override the set origin specified in the configuration
+                file.
+
+";
+
+if ($SHOW_USAGE) {
+  print $USAGE;
+  exit 0;
+}
+
+require '@@PGLIBDIR@@/slon-tools.pm';
+require $CONFIG_FILE;
+
+my ($set, $file) = @ARGV;
+if ($set =~ /^(?:set)?(\d+)$/) {
+  $set = $1;
+} else {
+  print "Invalid set identifier\n\n";
+  die $USAGE;
+}
+
+get_set($set) or die "Non-existent set specified.\n";
+$node = $SET_ORIGIN unless $node;
+
+# We can either have -c SCRIPT or a filename as an argument.  The
+# latter takes precedence.
+if ($file) {
+    unless ($file =~ /^\// and -f $file) {
+	print STDERR "SQL script path needs to be a full path, e.g. /tmp/my_script.sql\n\n";
+	die $USAGE;
+    }
+}
+elsif ($SCRIPT_ARG) {
+    # Put the script into a file
+    $file = "/tmp/execute_script.sql.$$";
+    my $fh;
+    open $fh, ">", $file;
+    print $fh $SCRIPT_ARG;
+    close $fh;
+}
+else {
+    print STDERR "You must include either a filename or a SQL statement on the command line to be run.\n\n";
+    die $USAGE;
+}
+
+my $FILE="/tmp/gensql.$$";
+open(SLONIK, ">", $FILE);
+print SLONIK genheader();
+print SLONIK "  execute script (\n";
+print SLONIK "    set id = $set,\n";
+print SLONIK "    filename = '$file',\n";
+print SLONIK "    event node = $node\n";
+print SLONIK "  );\n";
+close SLONIK;
+run_slonik_script($FILE);
Index: README
===================================================================
RCS file: /usr/local/cvsroot/slony1/slony1-engine/tools/altperl/README,v
retrieving revision 1.12
retrieving revision 1.13
diff -Ltools/altperl/README -Ltools/altperl/README -u -w -r1.12 -r1.13
--- tools/altperl/README
+++ tools/altperl/README
@@ -39,11 +39,11 @@
 
 4. Initialize the Slony-I cluster:
 
-   /usr/local/slony/bin/init_cluster
+   /usr/local/slony/bin/slonik_init_cluster
 
    Verify that the output looks reasonable, then run:
 
-   /usr/local/slony/bin/init_cluster | /usr/local/pgsql/bin/slonik
+   /usr/local/slony/bin/slonik_init_cluster | /usr/local/pgsql/bin/slonik
 
 5. Start up slon daemons for both servers:
 
@@ -52,11 +52,11 @@
 
 6. Set up set 1 on the "master" node:
 
-   /usr/local/slony/bin/create_set set1
+   /usr/local/slony/bin/slonik_create_set set1
 
 7. Subscribe node 2 to set 1:
 
-   /usr/local/slony/bin/subscribe_set set1 node2
+   /usr/local/slony/bin/slonik_subscribe_set set1 node2
 
 After some period of time (from a few seconds to a few days depending
 on the size of the set), you should have a working replica of the


More information about the Slony1-commit mailing list