<!--  -->
<sect1 id="adminscripts">
<title>&slony1; Administration Scripts</title>

<indexterm><primary>administration scripts for &slony1;</primary></indexterm>

<para> A number of tools have grown over the course of the history of
&slony1; to help users manage their clusters.  This section along with
the ones on <xref linkend="monitoring"> discusses them. </para>

<sect2 id="altperl"> <title>altperl Scripts</title>

<indexterm><primary>altperl scripts for &slony1;</primary></indexterm>

<para>There is a set of scripts to simplify administration
of set of &slony1; instances. The scripts support having arbitrary numbers of
nodes. They may be installed as part of the installation process:</para>

<para><command>
 ./configure --with-perltools
</command></para>

<para>This will produce a number of scripts with the prefix
<command>slonik_</command>.  They eliminate tedium by always referring
to a central configuration file for the details of your site
configuration. A documented sample of this file is provided in
<filename>altperl/slon_tools.conf-sample</filename>. Most also include
some command line help with the "--help" option, making them easier to
learn and use.
</para>

<para>Most generate Slonik scripts that are printed to STDOUT. 
At one time, the commands were passed directly to <xref linkend="slonik"> for execution. 
Unfortunately, this turned out to be a pretty large calibre
<quote>foot gun</quote>, as minor typos on the command line led, on a
couple of occasions, to pretty calamitous actions. The savvy administrator should review the script
<emphasis>before</emphasis> piping it to <xref linkend="slonik">.</para>

<sect3><title>Support for Multiple Clusters</title>
<indexterm><primary>Multiple Cluster support for the altperl tools</primary></indexterm>

<para>The UNIX environment variable <envar>SLONYNODES</envar> is used
to determine what Perl configuration file will be used to control the
shape of the nodes in a &slony1; cluster. If it is not provided, a
default <filename>slon_tools.conf</filename> location will be
referenced. </para>

<para>What variables are set up.
<itemizedlist>

<listitem><para><envar>$CLUSTER_NAME</envar>=orglogs;	# What is the name of the replication cluster?</para></listitem>
<listitem><para><envar>$LOGDIR</envar>='/opt/OXRS/log/LOGDBS';	# What is the base directory for logs?</para></listitem>
<listitem><para><envar>$APACHE_ROTATOR</envar>="/opt/twcsds004/OXRS/apache/rotatelogs";  # If set, where to find Apache log rotator</para></listitem>
<listitem><para><envar>foldCase</envar> # If set to 1, object names (including schema names) will be
folded to lower case.  By default, your object names will be left
alone.  Note that &postgres; itself folds object names to lower case;
if you create a table via the command <command> CREATE TABLE
SOME_THING (Id INTEGER, STudlYName text);</command>, the result will
be that all of those components are forced to lower case, thus
equivalent to <command> create table some_thing (id integer,
studlyname text);</command>, and the name of table and, in this case,
the fields will all, in fact, be lower case. </para>

</listitem>
</itemizedlist>
</para>

<para> You then define the set of nodes that are to be replicated
using a set of calls to <function>add_node()</function>.
</para>

<para><command>
  add_node (host => '10.20.30.40', dbname => 'orglogs', port => 5437,
			  user => 'postgres', node => 4, parent => 1);
</command></para>

<para>The set of parameters for <function>add_node()</function> are thus:</para>

<programlisting>
my %PARAMS =   (host=> undef,		# Host name
	   	dbname => 'template1',	# database name
		port => 5432,		# Port number
		user => 'postgres',	# user to connect as
		node => undef,		# node number
		password => undef,	# password for user
		parent => 1,		# which node is parent to this node
		noforward => undef,	# shall this node be set up to forward results?
		sslmode => undef,	# SSL mode argument - determine
					# priority of SSL usage
					# = disable,allow,prefer,require
		options => undef	# extra command line options to pass to the
					# slon daemon
);
</programlisting>
</sect3>

<sect3><title>Set configuration - cluster.set1, cluster.set2</title>
<indexterm><primary>cluster.set1 - replication set configuration for Perl tools</primary></indexterm>

<para>The UNIX environment variable <envar>SLONYSET</envar> is used to
determine what Perl configuration file will be used to determine what
objects will be contained in a particular replication set.</para>

<para>Unlike <envar>SLONYNODES</envar>, which is essential for
<emphasis>all</emphasis> of the <xref linkend="slonik">-generating
scripts, this only needs to be set when running
<filename>create_set</filename>, as that is the only script used to
control what tables will be in a particular replication set.</para>

</sect3>
<sect3><title>slonik_build_env</title>
<indexterm><primary>slonik_build_env</primary></indexterm>

<para>Queries a database, generating output hopefully suitable for
<filename>slon_tools.conf</filename> consisting of:</para>
<itemizedlist>

<listitem><para> a set of <function>add_node()</function> calls to configure the cluster</para></listitem>
<listitem><para> The arrays <envar>@KEYEDTABLES</envar>,
<envar>@SERIALTABLES</envar>, and <envar>@SEQUENCES</envar></para>

<para> Note that in &slony1; 2.0 and later, <envar>@SERIALTABLES</envar> is no longer meaningful as <xref linkend="stmtsetaddtable"> no longer supports the <envar>SERIAL</envar> option. </para>

</listitem>
</itemizedlist>
</sect3>
<sect3><title>slonik_print_preamble</title>
<indexterm><primary>altperl print preamble</primary></indexterm>

<para>This generates just the <quote>preamble</quote> that is required
by all slonik scripts.  In effect, this provides a
<quote>skeleton</quote> slonik script that does not do
anything.</para>
</sect3>
<sect3><title>slonik_create_set</title>
<indexterm><primary>altperl create set</primary></indexterm>

<para>This requires <envar>SLONYSET</envar> to be set as well as
<envar>SLONYNODES</envar>; it is used to generate the
<command>slonik</command> script to set up a replication set
consisting of a set of tables and sequences that are to be
replicated.</para>
</sect3>
<sect3 id="slonik-drop-node"><title>slonik_drop_node</title>
<indexterm><primary>altperl drop node</primary></indexterm>

<para>Generates Slonik script to drop a node from a &slony1;
cluster.</para>

</sect3>
<sect3 id="slonik-drop-set"><title>slonik_drop_set</title>
<indexterm><primary>altperl drop set</primary></indexterm>

<para>Generates Slonik script to drop a replication set
(<emphasis>e.g.</emphasis> - set of tables and sequences) from a
&slony1; cluster.</para>

<para> This represents a pretty big potential <quote>foot gun</quote>
as this eliminates a replication set all at once.  A typo that points
it to the wrong set could be rather damaging.  Compare to <xref
linkend="slonik-unsubscribe-set"> and <xref
linkend="slonik-drop-node">; with both of those, attempting to drop a
subscription or a node that is vital to your operations will be
blocked (via a foreign key constraint violation) if there exists a
downstream subscriber that would be adversely affected.  In contrast,
there will be no warnings or errors if you drop a set; the set will
simply disappear from replication.
</para>

</sect3>

<sect3 id="slonik-drop-table"><title>slonik_drop_table</title>
<indexterm><primary>altperl drop table</primary></indexterm>

<para>Generates Slonik script to drop a table from replication.
Requires, as input, the ID number of the table (available from table
<envar>sl_table</envar>) that is to be dropped. </para>
</sect3>

<sect3><title>slonik_execute_script</title>
<indexterm><primary>altperl execute script</primary></indexterm>

<para>Generates Slonik script to push DDL changes to a replication set.</para>
</sect3>
<sect3><title>slonik_failover</title>

<indexterm><primary>altperl failover</primary></indexterm>
<para>Generates Slonik script to request failover from a dead node to some new origin</para>
</sect3>
<sect3><title>slonik_init_cluster</title>
<indexterm><primary>altperl init cluster</primary></indexterm>

<para>Generates Slonik script to initialize a whole &slony1; cluster,
including setting up the nodes, communications paths, and the listener
routing.</para>
</sect3>
<sect3><title>slonik_merge_sets</title>
<indexterm><primary>altperl merge sets</primary></indexterm>

<para>Generates Slonik script to merge two replication sets together.</para>
</sect3>
<sect3><title>slonik_move_set</title>

<indexterm><primary>altperl move set</primary></indexterm>
<para>Generates Slonik script to move the origin of a particular set to a different node.</para>
</sect3>
<sect3><title>replication_test</title>
<indexterm><primary>altperl replication test</primary></indexterm>

<para>Script to test whether &slony1; is successfully replicating
data.</para>
</sect3>
<sect3><title>slonik_restart_node</title>
<indexterm><primary>altperl restart node</primary></indexterm>

<para>Generates Slonik script to request the restart of a node.  This was
particularly useful pre-1.0.5 when nodes could get snarled up when
slon daemons died.</para>
</sect3>
<sect3><title>slonik_restart_nodes</title>
<indexterm><primary>altperl restart nodes</primary></indexterm>

<para>Generates Slonik script to restart all nodes in the cluster.  Not
particularly useful.</para>
</sect3>
<sect3><title>slony_show_configuration</title>
<indexterm><primary>altperl show configuration</primary></indexterm>

<para>Displays an overview of how the environment (e.g. - <envar>SLONYNODES</envar>) is set
to configure things.</para>
</sect3>
<sect3><title>slon_kill</title>

<indexterm><primary>altperl kill slon</primary></indexterm>
<para>Kills slony watchdog and all slon daemons for the specified set.  It
only works if those processes are running on the local host, of
course!</para>
</sect3>
<sect3><title>slon_start</title>
<indexterm><primary>altperl start slon</primary></indexterm>

<para>This starts a slon daemon for the specified cluster and node, and uses
slon_watchdog to keep it running.</para>
</sect3>
<sect3 id="slonwatchdog"><title>slon_watchdog</title>

<indexterm><primary>altperl slon watchdog</primary></indexterm>
<para>Used by <command>slon_start</command>.</para>

</sect3><sect3><title>slon_watchdog2</title>
<indexterm><primary>altperl slon watchdog 2</primary></indexterm>

<para>This is a somewhat smarter watchdog; it monitors a particular
&slony1; node, and restarts the slon process if it hasn't seen updates
go in in 20 minutes or more.</para>

<para>This is helpful if there is an unreliable network connection such that
the slon sometimes stops working without becoming aware of it.</para>

</sect3>
<sect3><title>slonik_store_node</title>

<indexterm><primary>altperl store node</primary></indexterm>
<para>Adds a node to an existing cluster.</para>
</sect3>
<sect3><title>slonik_subscribe_set</title>

<indexterm><primary>altperl subscribe set</primary></indexterm>
<para>Generates Slonik script to subscribe a particular node to a particular replication set.</para>

</sect3><sect3><title>slonik_uninstall_nodes</title>
<indexterm><primary>altperl unsubscribe nodes</primary></indexterm>

<para>This goes through and drops the &slony1; schema from each node;
use this if you want to destroy replication throughout a cluster.  As
its effects are necessarily rather destructive, this has the potential
to be pretty unsafe.</para>

</sect3>

<sect3 id="slonik-unsubscribe-set"><title>slonik_unsubscribe_set</title>
<indexterm><primary>altperl unsubscribe set</primary></indexterm>

<para>Generates Slonik script to unsubscribe a node from a replication set.</para>

</sect3>
<sect3><title>slonik_update_nodes</title>
<indexterm><primary>altperl update nodes</primary></indexterm>

<para>Generates Slonik script to tell all the nodes to update the
&slony1; functions.  This will typically be needed when you upgrade
from one version of &slony1; to another.</para>
</sect3>
</sect2>

<sect2 id="mkslonconf"><title>mkslonconf.sh</title>

<indexterm><primary>generating slon.conf files for &slony1;</primary></indexterm>

<para> This is a shell script designed to rummage through a &slony1;
cluster and generate a set of <filename>slon.conf</filename> files
that &lslon; accesses via the <command> slon -f slon.conf </command>
option. </para>

<para> With all of the configuration residing in a configuration file
for each &lslon;, they can be invoked with minimal muss and fuss, with
no risk of forgetting the <command>-a</command> option and thereby
breaking a <link linkend="logshipping"> log shipping </link>
node. </para>

<para> Running it requires the following environment configuration: </para>

<itemizedlist>

<listitem><para> Firstly, the environment needs to be set up with
suitable parameters for libpq to connect to one of the databases in
the cluster.  Thus, you need some suitable combination of the
following environment variables set:</para>

<itemizedlist>
<listitem><para><envar>PGPORT</envar></para></listitem>
<listitem><para><envar>PGDATABASE</envar></para></listitem>
<listitem><para><envar>PGHOST</envar></para></listitem>
<listitem><para><envar>PGUSER</envar></para></listitem>
<listitem><para><envar>PGSERVICE</envar></para></listitem>
</itemizedlist>

</listitem>

<listitem><para> <envar>SLONYCLUSTER</envar> - the name of the
&slony1; cluster to be <quote>rummaged</quote>.  </para></listitem>

<listitem><para> <envar>MKDESTINATION</envar> - a directory for
configuration to reside in; the script will create
<filename>MKDESTINATION/$SLONYCLUSTER/conf</filename> for the &lslon;
configuration files, and
<filename>MKDESTINATION/$SLONYCLUSTER/pid</filename> for &lslon; to
store PID files in. </para></listitem>

<listitem><para> <envar>LOGHOME</envar> - a directory for log files to
reside in; a directory of the form
<command>$LOGHOME/$SLONYCLUSTER/node[number]</command> will be created
for each node. </para></listitem>

</itemizedlist>

<para> For any <quote>new</quote> nodes that it discovers, this script
will create a new &lslon; conf file. </para>

<warning><para> It is fair to say that there are several conditions to
beware of; none of these should be greatly surprising...</para>

<itemizedlist>

<listitem><para> The DSN is pulled from the minimum value found for
each node in <envar>sl_path</envar>.  You may very well need to modify
this.</para></listitem>

<listitem><para> Various parameters are set to default values; you may
wish to customize them by hand. </para></listitem>

<listitem><para> If you are running &lslon; processes on multiple
nodes (<emphasis>e.g.</emphasis> - as when running &slony1; across a
WAN), this script will happily create fresh new config files for
&lslon;s you wanted to have run on another host.  </para>

<para> Be sure to check out what nodes it set up before restarting
&lslon;s.  </para>

<para> This would usually only cause some minor inconvenience due to,
for instance, a &lslon; running at a non-preferred site, and either
failing due to lack of network connectivity (in which no damage is
done!) or running a bit less efficiently than it might have due to
living at the wrong end of the network <quote>pipe.</quote> </para>

<para> On the other hand, if you are running a log shipping node at
the remote site, accidentally introducing a &lslon; that
<emphasis>isn't</emphasis> collecting logs could ruin your whole
week. </para>
</listitem>
</itemizedlist>

</warning>

<para> The file layout set up by <filename>mkslonconf.sh</filename>
was specifically set up to allow managing &lslon;s across a
multiplicity of clusters using the script in the following
section... </para>

</sect2>

<sect2 id="startslon"> <title>start_slon.sh</title>

<para> This <filename>rc.d</filename>-style script was introduced in
&slony1; version 2.0; it provides automatable ways of:</para>

<itemizedlist>
<listitem><para>Starting the &lslon;, via <command> start_slon.sh start </command> </para> </listitem>
</itemizedlist>
<para> Attempts to start the &lslon;, checking first to verify that it
is not already running, that configuration exists, and that the log
file location is writable.  Failure cases include:</para>

<itemizedlist>
<listitem><para> No <link linkend="runtime-config"> slon runtime configuration file </link> exists, </para></listitem>
<listitem><para> A &lslon; is found with the PID indicated via the runtime configuration, </para></listitem>
<listitem><para> The specified <envar>SLON_LOG</envar> location is not writable. </para></listitem>
<listitem><para>Stopping the &lslon;, via <command> start_slon.sh stop </command> </para> 
<para> This fails (doing nothing) if the PID (indicated via the runtime configuration file) does not exist; </para> </listitem>
<listitem><para>Monitoring the status of the &lslon;, via <command> start_slon.sh status </command> </para> 
<para> This indicates whether or not the &lslon; is running, and, if so, prints out the process ID. </para> </listitem>

</itemizedlist>

<para> The following environment variables are used to control &lslon; configuration:</para>

<glosslist>
<glossentry><glossterm> <envar> SLON_BIN_PATH </envar> </glossterm>
<glossdef><para> This indicates where the &lslon; binary program is found. </para> </glossdef> </glossentry>
<glossentry><glossterm> <envar> SLON_CONF </envar> </glossterm>
<glossdef><para> This indicates the location of the <link linkend="runtime-config"> slon runtime configuration file </link> that controls how the &lslon; behaves. </para> 
<para> Note that this file is <emphasis>required</emphasis> to contain a value for <link linkend="slon-config-logging-pid-file">log_pid_file</link>; that is necessary to allow this script to detect whether the &lslon; is running or not. </para>
</glossdef> </glossentry>
<glossentry><glossterm> <envar> SLON_LOG </envar> </glossterm>
<glossdef><para> This file is the location where &lslon; log files are to be stored, if need be.  There is an option <xref linkend ="slon-config-logging-syslog"> for &lslon; to use <application>syslog</application> to manage logging; in that case, you may prefer to set <envar>SLON_LOG</envar> to <filename>/dev/null</filename>.  </para> </glossdef> </glossentry>
</glosslist>

<para> Note that these environment variables may either be set, in the
script, or overridden by values passed in from the environment.  The
latter usage makes it easy to use this script in conjunction with the
regression tests so that it is regularly tested. </para>

</sect2>

<sect2 id="launchclusters"><title> launch_clusters.sh </title>

<indexterm><primary>launching &slony1; cluster using slon.conf files</primary></indexterm>

<para> This is a shell script which uses the configuration as set up
by <filename>mkslonconf.sh</filename> and is intended to support an
approach to running &slony1; involving regularly
(<emphasis>e.g.</emphasis> via a cron process) checking to ensure that
&lslon; processes are running.</para>

<para> It uses the following environment variables:</para>

<itemizedlist>

<listitem><para><envar>PATH</envar> which needs to contain, preferably
at the beginning, a path to the &lslon; binaries that should be
run.</para></listitem>

<listitem><para><envar>SLHOME</envar> indicates the
<quote>home</quote> directory for &lslon; configuration files; they
are expected to be arranged in subdirectories, one for each cluster,
with filenames of the form <filename>node1.conf</filename>,
<filename>node2.conf</filename>, and such </para>

<para> The script uses the command <command>find $SLHOME/$cluster/conf
-name "node[0-9]*.conf"</command> to find &lslon; configuration files.</para>

<para> If you remove some of these files, or rename them so their
names do not conform to the <command>find</command> command, they
won't be found; that is an easy way to drop nodes out of this system.</para>
</listitem>

<listitem><para><envar>LOGHOME </envar> indicates the
<quote>home</quote> directory for log storage.</para>

<para> This script does not assume the use of the Apache log rotator
to manage logs; in that &postgres; version 8 does its own log
rotation, it seems undesirable to retain a dependancy on specific log
rotation <quote>technology.</quote> </para></listitem>

<listitem><para><envar>CLUSTERS</envar> is a list of &slony1; clusters
under management. </para></listitem>

</itemizedlist>

<para> In effect, you could run this every five minutes, and it would
launch any missing &lslon; processes. </para>
</sect2>

<sect2 id="upstartscript"><title> Upstart Script </title>

<indexterm><primary> upstart script </primary></indexterm>

<para> <ulink url="http://upstart.ubuntu.com/"> Upstart</ulink> is a
recent alternative to <application>/sbin/init</application> to handle
automatically starting tasks and services when a system boots.  It is
particularly popular on the Ubuntu Linux distribution.
</para>

<para> <filename> share/upstart-slon.conf-sample </filename> is a
sample script for use with <application>upstart</application>.
Deployment will require some customization in order to indicate where
&slony1; binaries and configuration are found in a particular
environment.</para>

</sect2>

<sect2 id="extractschema"><title> <filename> slony1_extract_schema.sh </filename> </title>

<indexterm><primary>script - slony1_extract_schema.sh</primary></indexterm>

<para> You may find that you wish to create a new node some time well
after creating a cluster.  The script <filename>
slony1_extract_schema.sh </filename> will help you with this.</para>

<para> A command line might look like the following:</para>

<para><command> PGPORT=5881 PGHOST=master.int.example.info ./slony1_extract_schema.sh payroll payroll temppayroll </command> </para>

<para> It performs the following:</para>

<itemizedlist>
<listitem><para> It dumps the origin node's schema, including the data in the &slony1; cluster schema. </para>

<para> Note that the extra environment variables <envar>PGPORT</envar>
and <envar>PGHOST</envar> to indicate additional information about
where the database resides. </para></listitem>

<listitem><para> This data is loaded into the freshly created temporary database, <envar>temppayroll</envar> </para> </listitem>
<listitem><para> The table and sequence OIDs in &slony1; tables are corrected   to point to the temporary database's configuration.  </para> </listitem>
<listitem><para>  A slonik script is run to perform <xref linkend="stmtuninstallnode"> on the temporary database.   This eliminates all the special &slony1; tables, schema, and removes &slony1; triggers from replicated tables. </para> </listitem>
<listitem><para> Finally, <application>pg_dump</application> is run against the temporary database, delivering a copy of the cleaned up schema to standard output. </para> </listitem>
</itemizedlist>

</sect2>
<sect2><title> slony-cluster-analysis </title>

<indexterm><primary>script - slony-cluster-analysis</primary></indexterm>

<para> If you are running a lot of replicated databases, where there
are numerous &slony1; clusters, it can get painful to track and
document this.  The following tools may be of some assistance in this.</para>

<para> <application>slony-cluster-analysis.sh</application> is a shell
script intended to provide some over-time analysis of the
configuration of a &slony1; cluster.  You pass in the usual
<application>libpq</application> environment variables
(<envar>PGHOST</envar>, <envar>PGPORT</envar>,
<envar>PGDATABASE</envar>, and such) to connect to a member of a
&slony1; cluster, and pass the name of the cluster as an argument.</para>

<para> The script then does the following:</para>
<itemizedlist>
<listitem><para> Runs a series of queries against the &slony1; tables to get lists of nodes, paths, sets, and tables. </para> </listitem>
<listitem><para> This is stowed in a temporary file in <filename>/tmp</filename> </para> </listitem>
<listitem><para> A comparison is done between the present configuration and the configuration the last time the tool was run.  If the configuration differs, an email of the difference (generated using <application>diff</application>) is sent to a configurable email address. </para> </listitem>
<listitem><para> If the configuration has changed, the old configuration file is renamed to indicate when the script noticed the change. </para></listitem>
<listitem><para> Ultimately, the current configuration is stowed in <envar>LOGDIR</envar> in a filename like <filename>cluster.last </filename> </para> </listitem>
</itemizedlist>

<para> There is a sample <quote>wrapper</quote> script,
<filename>slony-cluster-analysis-mass.sh</filename>, which sets things
up to point to a whole bunch of &slony1; clusters.</para>

<para> This should make it easier for a group of DBAs to keep track of
two things: </para>

<itemizedlist>

<listitem><para> Documenting the current state of system
configuration.  </para></listitem>

<listitem><para> Noticing when configuration
changes. </para></listitem>
</itemizedlist>

</sect2>

<sect2 id="configurereplication"> <title> Generating slonik scripts
using <filename>configure-replication.sh</filename> </title>

<indexterm><primary> generate slonik scripts for a cluster </primary></indexterm>

<para> The <filename>tools</filename> script
<filename>configure-replication.sh</filename> is intended to automate
generating slonik scripts to configure replication. </para>

<para> This script uses a number (possibly large, if your
configuration needs to be particularly complex) of environment
variables to determine the shape of the configuration of a cluster.
It uses default values extensively, and in many cases, relatively few
environment values need to be set in order to get a viable
configuration. </para>

<sect3><title>Global Values</title>

<para> There are some values that will be used universally across a
cluster: </para>

<variablelist>
<varlistentry><term><envar>  CLUSTER </envar></term>
<listitem><para> Name of Slony-I cluster</para></listitem></varlistentry>
<varlistentry><term><envar>  NUMNODES </envar></term>
<listitem><para> Number of nodes to set up</para></listitem></varlistentry>

<varlistentry><term><envar>  PGUSER </envar></term>
<listitem><para> name of PostgreSQL user controlling replication</para>

<para> Traditionally, people have used a database superuser for this,
but that is not necessary as discussed <xref linkend="superuser">
</para>
</listitem>
</varlistentry>
<varlistentry><term><envar>  PGPORT </envar></term>
<listitem><para> default port number</para></listitem></varlistentry>
<varlistentry><term><envar>  PGDATABASE </envar></term>
<listitem><para> default database name</para></listitem></varlistentry>

<varlistentry><term><envar>  TABLES </envar></term>
<listitem><para> a list of fully qualified table names (<emphasis>e.g.</emphasis> - complete with
           namespace, such as <command>public.my_table</command>)</para></listitem></varlistentry>
<varlistentry><term><envar>  SEQUENCES </envar></term>
<listitem><para> a list of fully qualified sequence names (<emphasis>e.g.</emphasis> - complete with
           namespace, such as <command>public.my_sequence</command>)</para></listitem></varlistentry>

</variablelist>

<para>Defaults are provided for <emphasis>all</emphasis> of these
values, so that if you run
<filename>configure-replication.sh</filename> without setting any
environment variables, you will get a set of slonik scripts.  They may
not correspond, of course, to any database you actually want to
use...</para>
</sect3>

<sect3><title>Node-Specific Values</title>

<para>For each node, there are also four environment variables; for node 1: </para>
<variablelist>
<varlistentry><term><envar>  DB1 </envar></term>
<listitem><para> database to connect to</para></listitem></varlistentry>
<varlistentry><term><envar>  USER1 </envar></term>
<listitem><para> superuser to connect as</para></listitem></varlistentry>
<varlistentry><term><envar>  PORT1 </envar></term>
<listitem><para> port</para></listitem></varlistentry>
<varlistentry><term><envar>  HOST1 </envar></term>
<listitem><para> host</para></listitem></varlistentry>
</variablelist>

<para> It is quite likely that <envar>DB*</envar>,
<envar>USER*</envar>, and <envar>PORT*</envar> should be drawn from
the global <envar>PGDATABASE</envar>, <envar>PGUSER</envar>, and
<envar>PGPORT</envar> values above; having the discipline of that sort
of uniformity is usually a good thing.</para>

<para> In contrast, <envar>HOST*</envar> values should be set
explicitly for <envar>HOST1</envar>, <envar>HOST2</envar>, ..., as you
don't get much benefit from the redundancy replication provides if all
your databases are on the same server!</para>

</sect3>

<sect3><title>Resulting slonik scripts</title>

<para> slonik config files are generated in a temp directory under
<filename>/tmp</filename>.  The usage is thus:</para>

<itemizedlist>

<listitem> <para><filename>preamble.slonik</filename> is a
<quote>preamble</quote> containing connection info used by the other
scripts.</para>

<para> Verify the info in this one closely; you may want to keep this
permanently to use with future maintenance you may want to do on the
cluster.</para></listitem>

<listitem><para> <filename>create_nodes.slonik</filename></para>

<para>This is the first script to run; it sets up the requested nodes
as being &slony1; nodes, adding in some &slony1;-specific config
tables and such.</para>

<para>You can/should start slon processes any time after this step has
run.</para></listitem>

<listitem><para><filename>  store_paths.slonik</filename></para>

<para> This is the second script to run; it indicates how the &lslon;s
should intercommunicate.  It assumes that all &lslon;s can talk to all
nodes, which may not be a valid assumption in a complexly-firewalled
environment.  If that assumption is untrue, you will need to modify
the script to fix the paths.</para></listitem>

<listitem><para><filename>create_set.slonik</filename></para>

<para> This sets up the replication set consisting of the whole bunch
of tables and sequences that make up your application's database
schema.</para>

<para> When you run this script, all that happens is that triggers are
added on the origin node (node #1) that start collecting updates;
replication won't start until #5...</para>

<para>There are two assumptions in this script that could be
invalidated by circumstances:</para>

<itemizedlist>
     <listitem><para> That all of the tables and sequences have been
     included.</para>

     <para> This becomes invalid if new tables get added to your
     schema and don't get added to the <envar>TABLES</envar>
     list.</para> </listitem>

     <listitem><para> That all tables have been defined with primary
     keys.</para>

     <para> Best practice is to always have and use true primary keys.
     If you have tables that require choosing a candidate primary key,
     you will have to modify this script by hand to accomodate
     that. </para></listitem>

</itemizedlist>
</listitem>

<listitem><para> <filename> subscribe_set_2.slonik </filename></para>

  <para> And 3, and 4, and 5, if you set the number of nodes
  higher... </para>

  <para> This is the step that <quote>fires up</quote>
  replication.</para>

  <para> The assumption that the script generator makes is that all
  the subscriber nodes will want to subscribe directly to the origin
  node.  If you plan to have <quote>sub-clusters,</quote> perhaps
  where there is something of a <quote>master</quote> location at each
  data centre, you may need to revise that.</para>

  <para> The slon processes really ought to be running by the time you
  attempt running this step.  To do otherwise would be rather
  foolish.</para> </listitem>
</itemizedlist>

</sect3>
</sect2>

<sect2 id="bsd-ports-profile"> <title> <filename> slon.in-profiles </filename> </title>
<subtitle> Apache-Style profiles for FreeBSD <filename>ports/databases/slony/*</filename> </subtitle>

<indexterm><primary> Apache-style profiles for FreeBSD </primary> <secondary>FreeBSD </secondary> </indexterm>

<para> In the <filename>tools</filename> area, <filename>slon.in-profiles</filename> is a
script that might be used to start up &lslon; instances at the time of
system startup.  It is designed to interact with the FreeBSD Ports
system.</para>

</sect2>

<sect2 id="duplicate-node"> <title> <filename> duplicate-node.sh </filename> </title>
<indexterm><primary> duplicating nodes </primary> </indexterm>
<para> In the <filename>tools</filename> area,
<filename>duplicate-node.sh</filename> is a script that may be used to
help create a new node that duplicates one of the ones in the
cluster. </para>

<para> The script expects the following parameters: </para>
<itemizedlist>
<listitem><para> Cluster name </para> </listitem>
<listitem><para> New node number </para> </listitem>
<listitem><para> Origin node </para> </listitem>
<listitem><para> Node being duplicated </para> </listitem>
<listitem><para> New node </para> </listitem>
</itemizedlist>

<para> For each of the nodes specified, the script offers flags to
specify <function>libpq</function>-style parameters for
<envar>PGHOST</envar>, <envar>PGPORT</envar>,
<envar>PGDATABASE</envar>, and <envar>PGUSER</envar>; it is expected
that <filename>.pgpass</filename> will be used for storage of
passwords, as is generally considered best practice. Those values may
inherit from the <function>libpq</function> environment variables, if
not set, which is useful when using this for testing.  When
<quote>used in anger,</quote> however, it is likely that nearly all of
the 14 available parameters should be used. </para>

<para> The script prepares files, normally in
<filename>/tmp</filename>, and will report the name of the directory
that it creates that contain SQL and &lslonik; scripts to set up the
new node. </para>

<itemizedlist>
<listitem><para> <filename> schema.sql </filename> </para> 
<para> This is drawn from the origin node, and contains the <quote>pristine</quote> database schema that must be applied first.</para></listitem>
<listitem><para> <filename> slonik.preamble </filename> </para> 

<para> This <quote>preamble</quote> is used by the subsequent set of slonik scripts. </para> </listitem>
<listitem><para> <filename> step1-storenode.slonik </filename> </para> 
<para> A &lslonik; script to set up the new node. </para> </listitem>
<listitem><para> <filename> step2-storepath.slonik </filename> </para> 
<para> A &lslonik; script to set up path communications between the provider node and the new node. </para> </listitem>
<listitem><para> <filename> step3-subscribe-sets.slonik </filename> </para> 
<para> A &lslonik; script to request subscriptions for all replications sets.</para> </listitem>
</itemizedlist>

<para> For testing purposes, this is sufficient to get a new node working.  The configuration may not necessarily reflect what is desired as a final state:</para>

<itemizedlist>
<listitem><para> Additional communications paths may be desirable in order to have redundancy. </para> </listitem>
<listitem><para> It is assumed, in the generated scripts, that the new node should support forwarding; that may not be true. </para> </listitem>
<listitem><para> It may be desirable later, after the subscription process is complete, to revise subscriptions. </para> </listitem>
</itemizedlist>

</sect2>
<sect2 id="slonikconfdump"> <title>slonikconfdump.sh</title>

<indexterm><primary>altperl configuration dump</primary></indexterm>

<para> The tool <filename>tools/slonikconfdump.sh</filename> was
created to help dump out a &lslonik; script to duplicate the
configuration of a functioning &slony1; cluster.  It should be
particularly useful when upgrading &slony1; to version 2.0; see <xref
linkend="upgrade20"> for more details.</para>

<para> It dumps out: </para>

<itemizedlist>
<listitem><para>Cluster name </para> </listitem>
<listitem><para>Node connection information </para> <para> Note that it uses the first value it finds (<emphasis>e.g.</emphasis> - for the lowest numbered client node). </para> </listitem>
<listitem><para> Nodes </para> </listitem>
<listitem><para> Sets </para> </listitem>
<listitem><para> Tables </para> </listitem>
<listitem><para> Sequences </para> </listitem>
<listitem><para> Subscriptions </para> 

<para> Note that the subscriptions are ordered by set, then by
provider, then by receiver.  This ordering does not necessarily
indicate the order in which subscriptions need to be
applied. </para></listitem>
</itemizedlist>

<para> It may be run as follows: </para>
<programlisting>
chris@dba2:Slony-I/CMD/slony1-2.0/tools> SLONYCLUSTER=slony_regress1 PGDATABASE=slonyregress1 bash slonikconfdump.sh
# building slonik config files for cluster slony_regress1
# generated by: slonikconfdump.sh
# Generated on:  Tue Jun 9 17:34:12 EDT 2009
cluster name=slony_regress1;
include &lt;admin-conninfos.slonik&gt;;  # Draw in ADMIN CONNINFO lines
node 1 admin conninfo='dbname=slonyregress1 host=localhost user=chris port=7083';
node 2 admin conninfo='dbname=slonyregress2 host=localhost user=chris port=7083';
init cluster (id=1, comment='Regress test node');
store node (id=2, comment='node 2');
store path (server=1, client=2, conninfo='dbname=slonyregress1 host=localhost user=chris port=7083', connretry=10);
store path (server=2, client=1, conninfo='dbname=slonyregress2 host=localhost user=chris port=7083', connretry=10);
create set (id=1, origin=1, comment='All test1 tables');
set add table (id=1, set id=1, origin=1, fully qualified name='"public"."table1"', comment='accounts table, key='table1_pkey');
set add table (id=2, set id=1, origin=1, fully qualified name='"public"."table2"', comment='public.table2, key='table2_id_key');
set add table (id=4, set id=1, origin=1, fully qualified name='"public"."table4"', comment='a table of many types, key='table4_pkey');
set add table (id=5, set id=1, origin=1, fully qualified name='"public"."table5"', comment='a table with composite PK strewn across the table, key='table5_pkey');
subscribe set (id=1, provider=1, receiver=2, forward=YES);
chris@dba2:Slony-I/CMD/slony1-2.0/tools>
</programlisting>

<para> The output should be reviewed before it is applied elsewhere.
Particular attention should be paid to the <command>ADMIN
CONNINFO</command>, as it picks the first value that it sees for each
node; in a complex environment, where visibility of nodes may vary
from subnet to subnet, it may not pick the right value.  In addition,
<command>SUBSCRIBE SET</command> statements do not necessarily
indicate the order in which subscriptions need to be applied.</para>

</sect2>


<sect2 id="gensync"><title>Parallel to Watchdog: generate_syncs.sh</title>

<indexterm><primary>generate SYNCs</primary></indexterm>
<para>A new script for &slony1; 1.1 is
<application>generate_syncs.sh</application>, which addresses the following kind of
situation.</para>

<para>Supposing you have some possibly-flakey server where the
<application>slon</application> daemon that might not run all the time, you might
return from a weekend away only to discover the following situation.</para>

<para>On Friday night, something went <quote>bump</quote> and while the
database came back up, none of the <application>slon</application> daemons
survived.  Your online application then saw nearly three days worth of
reasonably heavy transaction load.</para>

<para>When you restart <application>slon</application> on Monday, it
hasn't done a SYNC on the master since Friday, so that the next
<quote>SYNC set</quote> comprises all of the updates between Friday
and Monday.  Yuck.</para>

<para>If you run <application>generate_syncs.sh</application> as a cron job every
20 minutes, it will force in a periodic <command>SYNC</command> on the origin, which
means that between Friday and Monday, the numerous updates are split
into more than 100 syncs, which can be applied incrementally, making
the cleanup a lot less unpleasant.</para>

<para>Note that if <command>SYNC</command>s <emphasis>are</emphasis> running
regularly, this script won't bother doing anything.</para>
</sect2>

</sect1>
<!-- Keep this comment at the end of the file
Local variables:
mode:sgml
sgml-omittag:nil
sgml-shorttag:t
sgml-minimize-attributes:nil
sgml-always-quote-attributes:t
sgml-indent-step:1
sgml-indent-data:t
sgml-parent-document:"slony.sgml"
sgml-exposed-tags:nil
sgml-local-catalogs:("/usr/lib/sgml/catalog")
sgml-local-ecat-files:nil
End:
-->
