Chris Browne cbbrowne at lists.slony.info
Mon Feb 23 09:19:17 PST 2009
Update of /home/cvsd/slony1/slony1-engine/src/upgrade_to_20
In directory main.slony.info:/tmp/cvs-serv1289

Added Files:
      Tag: REL_2_0_STABLE
	README check_readiness.sh dbutil.c dump_config.sh lock_sets.sh 
	slony_upgrade_20.c slony_upgrade_20.h upgrade_12_20_common.sh 
	upgrade_12_20_part1.sh upgrade_function.sql 
Log Message:
Add in preliminaries for a tool (which isn't yet fully implemented) to
do upgrade from v1.2 to v2.0


--- NEW FILE: slony_upgrade_20.c ---
/*-------------------------------------------------------------------------
 * slony_upgrade_to_20
 *
 *	Program to upgrade Slony-I from 1.2 to 2.0
 *
 *	Copyright (c) 2009, PostgreSQL Global Development Group
 *	Author: Christopher Browne, Afilias Canada
 *
 *	$Id: slony_upgrade_20.c,v 1.1.2.1 2009-02-23 17:19:15 cbbrowne Exp $
 *-------------------------------------------------------------------------
 */


#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/types.h>

#include "libpq-fe.h"
#include "c.h"
 
main(int argc, char *const argv[]) {
    printf("Upgrade from older versions to 2.0 is not yet implemented!\n");
}


--- NEW FILE: dbutil.c ---
/*-------------------------------------------------------------------------
 * dbutil.c
 *
 *	General database support functions.
 *
 *	Copyright (c) 2003-2004, PostgreSQL Global Development Group
 *	Author: Jan Wieck, Afilias USA INC.
 *
 *	$Id: dbutil.c,v 1.1.2.1 2009-02-23 17:19:15 cbbrowne Exp $
 *-------------------------------------------------------------------------
 */


#ifndef WIN32
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#endif
#include "postgres.h"
#include "libpq-fe.h"

#include "slony_upgrade_20.h"


/*
 * Local functions
 */
static int	slon_appendquery_int(SlonDString * dsp, char *fmt, va_list ap);


/* ----------
 * slon_mkquery
 *
 *	A simple query formatting and quoting function using dynamic string
 *	buffer allocation.
 *	Similar to sprintf() it uses formatting symbols:
 *		%s		String argument
 *		%q		Quoted literal (\ and ' will be escaped)
 *		%d		Integer argument
 * ----------
 */
int
slon_mkquery(SlonDString * dsp, char *fmt,...)
{
	va_list		ap;

	dstring_reset(dsp);

	va_start(ap, fmt);
	slon_appendquery_int(dsp, fmt, ap);
	va_end(ap);

	dstring_terminate(dsp);

	return 0;
}


/* ----------
 * slon_appendquery
 *
 *	Append query string material to an existing dynamic string.
 * ----------
 */
int
slon_appendquery(SlonDString * dsp, char *fmt,...)
{
	va_list		ap;

	va_start(ap, fmt);
	slon_appendquery_int(dsp, fmt, ap);
	va_end(ap);

	dstring_terminate(dsp);

	return 0;
}


/* ----------
 * slon_appendquery_int
 *
 *	Implementation of slon_mkquery() and slon_appendquery().
 * ----------
 */
static int
slon_appendquery_int(SlonDString * dsp, char *fmt, va_list ap)
{
	char	   *s;
	char		buf[64];

	while (*fmt)
	{
		switch (*fmt)
		{
			case '%':
				fmt++;
				switch (*fmt)
				{
					case 's':
						s = va_arg(ap, char *);
						dstring_append(dsp, s);
						fmt++;
						break;

					case 'q':
						s = va_arg(ap, char *);
						while (s && *s != '\0')
						{
							switch (*s)
							{
								case '\'':
									dstring_addchar(dsp, '\'');
									break;
								case '\\':
									dstring_addchar(dsp, '\\');
									break;
								default:
									break;
							}
							dstring_addchar(dsp, *s);
							s++;
						}
						fmt++;
						break;

					case 'Q':
						s = va_arg(ap, char *);
						while (s && *s != '\0')
						{
							switch (*s)
							{
								case '\'':
								case '\\':
									dstring_addchar(dsp, '\\');
									break;
								default:
									break;
							}
							dstring_addchar(dsp, *s);
							s++;
						}
						fmt++;
						break;

					case 'd':
						sprintf(buf, "%d", va_arg(ap, int));
						dstring_append(dsp, buf);
						fmt++;
						break;

					default:
						dstring_addchar(dsp, '%');
						dstring_addchar(dsp, *fmt);
						fmt++;
						break;
				}
				break;

			case '\\':
				fmt++;
				dstring_addchar(dsp, *fmt);
				fmt++;
				break;

			default:
				dstring_addchar(dsp, *fmt);
				fmt++;
				break;
		}
	}

	dstring_terminate(dsp);

	return 0;
}

--- NEW FILE: dump_config.sh ---
#!/bin/sh
# $Id: dump_config.sh,v 1.1.2.1 2009-02-23 17:19:15 cbbrowne Exp $

source upgrade_12_20_common.sh

echo "Dumping configuration info about upgrade"
date

echo "Cluster: ${CLUSTER}"
echo "PostgreSQL binaries in: ${PGBINDIR}"
echo "Slony-I tools in: ${SLTOOLDIR}"
echo "Acceptable replication lag: ${ACCEPTABLELAG}"

echo "Number of nodes: ${NUMNODES}"

node=1
while : ; do
    eval db=\$DB${node}
    eval host=\$HOST${node}
    eval user=\$USER${node}
    eval port=\$PORT${node}
    echo "Node ${node} - DB connection - PGDATABASE=${db} PGHOST=${host} PGUSER=${user} PGPORT=${port}"
    if [ ${node} -ge ${NUMNODES} ]; then
	break;
    else
	node=$((${node} + 1))
    fi
done


--- NEW FILE: upgrade_function.sql ---
SET SEARCH_PATH TO @CLUSTERNAME@, pg_catalog;

BEGIN;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE ;

lock table sl_config_lock;

-- Redo stored triggers
create or replace function redo_table_triggers (i_tab_id integer) as $$
declare
	prec record;
	c_localnode integer;
	c_n integer;
begin
	c_localnode := getLocalNodeId('_ at CLUSTERNAME@');
	select t.tab_reloid, t.tab_altered, t.tab_idxname, s.set_origin, pgx.indexrelid, 
	   slon_quote_brute(pgn.nspname) || '.' || slon_quote_brute(pgc.relname) as tab_fqname 
	   into prec
	from
		sl_table t, sl_set s, pg_class pgc, pg_namespace pgn,
		pg_index pgx, pg_class pgxc
	where
		t.tab_id = i_tab_id and
		t.tab_reloid = pgc.oid and
		pgc.relname = pgn.oid and
		pgx.indrelid = t.tab_reloid and
		pgx.indexrelid = pgxc.oid and
		pgxc.relname = t.tab_idxname
	for update;
	if not found then
		raise exception 'Table with id % not found!', i_tab_id;
	end if;
	if not prec.tab_altered then
		raise exception 'Table % - % - not in altered state', i_tab_id, prec.tab_fqname;
	end if;
	execute 'lock table ' || prec.tab_fqname || ' in access exclusive mode';

	execute 'create trigger "_ at CLUSTERNAME@_logtrigger"' || 'after insert or update or delete on ' ||
		prec.tab_fqname || ' for each row execute procedure logTrigger(' ||
		quote_literal('_ at CLUSTERNAME@') || ',' ||
		quote_literal(i_tab_id) || ',' ||
		quote_literal(determineAttKindUnique(prec.tab_fqname, prec.tab_idxname)) || ');';

	execute 'create trigger "_ at CLUSTERNAME@_denyaccess"' ||
		' before insert or update or delete on ' || prec.tab_fqname ||
		' for each row execute procedure denyAccess(' || quote_literal('_ at CLUSTERNAME@') || ');';

	if c_localnode := prec.set_origin then
		execute 'drop trigger "_ at CLUSTERNAME@_logtrigger_' || i_tab_id || '" on ' || prec.tab_fqname;

		execute 'alter table ' || prec.tab_fqname || ' enable trigger "_ at CLUSTERNAME@_logtrigger"';
		execute 'alter table ' || prec.tab_fqname || ' disable trigger "_ at CLUSTERNAME@_denyaccess"';
	else
		execute 'drop trigger "_ at CLUSTERNAME@_denyaccess_' || i_tab_id || '" on ' || prec.tab_fqname;
		update pg_trigger set tgrelid = prec.tab_reloid where tgrelid = prec.indexrelid;
		get diagnostics c_n = row_count;
		if c_n > 0 then
			update pg_class set reltriggers = reltriggers + c_n where oid = prec.tab_reloid;
		end if;
		update pg_rewrite set ev_class = prec.tab_reloid where ev_class = prec.indexrelid;
		get diagnostics c_n = row_count;
		if c_n > 0 then
			update pg_class set relhasrules = true where oid = prec.tab_reloid;
		end if;
		execute 'alter table ' || prec.tab_fqname || ' disable trigger "_ at CLUSTERNAME@_logtrigger"';
		execute 'alter table ' || prec.tab_fqname || ' enable trigger "_ at CLUSTERNAME@_denyaccess"';
	end if;
end
$$ language plpgsql;

select redo_table_triggers(tab_id) from sl_table;
drop function redo_table_triggers(tab_id integer);

alter table sl_node drop column no_spool;
drop table sl_trigger;

truncate sl_log_1, sl_log_2, sl_event, sl_setsync;

alter table sl_set drop column set_locked;
alter table sl_set add column set_locked bigint;
comment on column sl_set.set_locked is 'Transaction ID where the set was locked';

alter table sl_log_1 drop column log_xid;
alter table sl_log_2 drop column log_xid
alter table sl_log_1 add column log_txid bigint;
alter table sl_log_2 add column log_txid bigint;
comment on column sl_log_1.log_txid is 'Transaction ID on the origin node';
comment on column sl_log_2.log_txid is 'Transaction ID on the origin node';

alter table sl_event drop column ev_minxid;
alter table sl_event drop column ev_maxxid;
alter table sl_event add column ev_snapshot "pg_catalog".txid_snapshot;
comment on column sl_event.ev_snapshot is 'TXID in provider node for this event';

alter table sl_setsync add column ev_snapshot "pg_catalog".txid_snapshot;
comment on column sl_setsync.ev_snapshot is 'TXID in provider node seen by the event';

drop function alterTableForReplication(int4);
drop function pre74(int4);

select setval('sl_event_seq', 0);
select setval('sl_action', 0);

select createevent('_ at CLUSTERNAME@', 'SYNC', NULL);

-- insert into sl_setsync(ssy_setid, ssy_origin, ssy_seqno, ssy_snapshot, ssy_action_list) values 
-- MUMBLE...  Need to grab a transaction ID from the source node...

prepare transaction '@CLUSTERNAME@ upgrade from Slony-I 1.2 to 2.0';
--- NEW FILE: check_readiness.sh ---
#!/bin/sh
# $Id: check_readiness.sh,v 1.1.2.1 2009-02-23 17:19:15 cbbrowne Exp $

source upgrade_12_20_common.sh

echo "Check cluster readiness for upgrade"
date

echo "Cluster: ${CLUSTER}"
echo "PostgreSQL binaries in: ${PGBINDIR}"
echo "Slony-I tools in: ${SLTOOLDIR}"

echo "Number of nodes: ${NUMNODES}"

echo "Checking node readiness"

node=1
while : ; do
    eval db=\$DB${node}
    eval host=\$HOST${node}
    eval user=\$USER${node}
    eval port=\$PORT${node}
    psqlargs=" -d ${host} -p ${port} -d ${db} -U ${user} "

    echo "Checking Node ${node} - DB connection - PGDATABASE=${db} PGHOST=${host} PGUSER=${user} PGPORT=${port}"
    echo "--------------------------------------------------------------------------------------------"

    SETS=`${PSQL} -tq -R " " ${psqlargs} -c "select set_id from ${CLSCHEMA}.sl_set where set_origin = ${CLSCHEMA}.getlocalnodeid('_${CLUSTER}') and set_locked is null;"`

    if [ "x${SETS}" != "x" ]; then
	err 3 "node ${node} still has unlocked sets - ${SETS}"
    else
	echo "set locking - done!"
    fi

    WORSTLAG=`${PSQL} ${psqlargs} -tA -F "," -A -c "select st_received, st_lag_num_events, st_lag_time, st_lag_time > ${ACCEPTABLELAG} as bad_lag from _slony_regress1.sl_status where st_lag_time > ${ACCEPTABLELAG} order by st_lag_time desc limit 1;"`
    if [ "x${WORSTLAG}" != "x" ]; then
	bnode=`echo ${WORSTLAG} | cut -d "," -f 1`
	bevents=`echo ${WORSTLAG} | cut -d "," -f 2`
	blag=`echo ${WORSTLAG} | cut -d "," -f 3`
	err 3 "replication node ${bnode} is lagging by (events,lag) = (${bevents},${blag}) - lag > ${ACCEPTABLELAG}"
    else
	echo "No lags > ${ACCEPTABLELAG}"
    fi

    if [ ${node} -ge ${NUMNODES} ]; then
	break;
    else
	node=$((${node} + 1))
    fi
done

echo "All nodes checked - no problems found!"
--- NEW FILE: slony_upgrade_20.h ---
/*-------------------------------------------------------------------------
 * slony_logshipper.h
 *
 *	Definitions for slony_logshipper
 *
 *	Copyright (c) 2003-2004, PostgreSQL Global Development Group
 *	Author: Jan Wieck, Afilias USA INC.
 *
 *	$Id: slony_upgrade_20.h,v 1.1.2.1 2009-02-23 17:19:15 cbbrowne Exp $
 *-------------------------------------------------------------------------
 */


/* ----------
 * SlonDString
 * ----------
 */
#define		SLON_DSTRING_SIZE_INIT	256
#define		SLON_DSTRING_SIZE_INC	2

typedef struct
{
	size_t		n_alloc;
	size_t		n_used;
	char	   *data;
}	SlonDString;

#define		dstring_init(__ds) \
do { \
	(__ds)->n_alloc = SLON_DSTRING_SIZE_INIT; \
	(__ds)->n_used = 0; \
	(__ds)->data = malloc(SLON_DSTRING_SIZE_INIT); \
	if ((__ds)->data == NULL) { \
		perror("dstring_init: malloc()"); \
		exit(-1); \
	} \
} while (0)
#define		dstring_reset(__ds) \
do { \
	(__ds)->n_used = 0; \
	(__ds)->data[0] = '\0'; \
} while (0)
#define		dstring_free(__ds) \
do { \
	free((__ds)->data); \
	(__ds)->n_used = 0; \
	(__ds)->data = NULL; \
} while (0)
#define		dstring_nappend(__ds,__s,__n) \
do { \
	if ((__ds)->n_used + (__n) >= (__ds)->n_alloc)	\
	{ \
		while ((__ds)->n_used + (__n) >= (__ds)->n_alloc) \
			(__ds)->n_alloc *= SLON_DSTRING_SIZE_INC; \
		(__ds)->data = realloc((__ds)->data, (__ds)->n_alloc); \
		if ((__ds)->data == NULL) \
		{ \
			perror("dstring_nappend: realloc()"); \
			exit(-1); \
		} \
	} \
	memcpy(&((__ds)->data[(__ds)->n_used]), (__s), (__n)); \
	(__ds)->n_used += (__n); \
} while (0)
#define		dstring_append(___ds,___s) \
do { \
	register int ___n = strlen((___s)); \
	dstring_nappend((___ds),(___s),___n); \
} while (0)
#define		dstring_addchar(__ds,__c) \
do { \
	if ((__ds)->n_used + 1 >= (__ds)->n_alloc)	\
	{ \
		(__ds)->n_alloc *= SLON_DSTRING_SIZE_INC; \
		(__ds)->data = realloc((__ds)->data, (__ds)->n_alloc); \
		if ((__ds)->data == NULL) \
		{ \
			perror("dstring_append: realloc()"); \
			exit(-1); \
		} \
	} \
	(__ds)->data[(__ds)->n_used++] = (__c); \
} while (0)
#define		dstring_terminate(__ds) \
do { \
	(__ds)->data[(__ds)->n_used] = '\0'; \
} while (0)
#define		dstring_data(__ds)	((__ds)->data)


typedef enum {
	LOG_DEBUG = 0,
	LOG_INFO,
	LOG_WARN,
	LOG_ERROR
} log_level;


#ifndef MSGMAX
#define MSGMAX 1024
#endif


/*
 * Functions in dbutil.c
 */
int			slon_mkquery(SlonDString * dsp, char *fmt,...);
int			slon_appendquery(SlonDString * dsp, char *fmt,...);


/*
 * Local Variables:
 *	tab-width: 4
 *	c-indent-level: 4
 *	c-basic-offset: 4
 * End:
 */

--- NEW FILE: README ---
The set of scripts do the following:

 1.  Locks all replication sets (akin to how MOVE SET works), so we
     can make certain that replication stops for a bit.

 2.  Waits for that to propagate everywhere, therefore establishing
     that all nodes are up to date.

 3.  Tells the administrator, "go ahead, install upgraded Slony-I."

 4.  Then, we go to each node, in turn, and, within a transaction, do
     the following:

     - First, load a function that does the work that follows,
       transforming from 1.2.16-ish to a "pre-2.0" state, *for the
       tables.* It does *not* load new functions; that's a subsequent
       step, #6.

     - It redoes the triggers and rules on the tables, replacing
       old Slony-I-generated logtrigger/denyaccess triggers with new
       ones, cleaning up FK triggers, and such.  (There's more detail
       to fill in here - nothing frightening, I don't think, just more
       detail!)

     - It should drop old Slony-I stored functions that are no longer
       needed in v2.0

     - It runs TRUNCATE against the 4 tables mentioned earlier

     - We run CreateEvent() against each node to capture at what point
       it is at, and store the event number and transaction ID in a
       file.

       ===> Note that this must happen on EACH node; we'll be reading
            these values in the next step. <===

     - We inserts an sl_setsync entry, just as happens in copy_set()
       in src/slon/remote_worker.c, to indicate, for each replication
       set, that it is freshly copied on each subscriber node.

     - There will probably be a custom UPGRADE function; it can be
       dropped out at this point as it is never needed again.

     - Finally, we set this up to be a prepared truncation...
        PREPARE TRANSACTION "Slony-I 1.2 to 2.0 upgrade - @CLUSTER@";

     Note that at this point, that node is Pretty Locked Down.  This
     transaction has acquired locks on ALL tables involved in
     replication, including the application tables.

 5. If step #4 works successfully on all nodes, then we know we have a
    successful upgrade, and can safely go to each node and run COMMIT
    PREPARED on that transaction on each node.

    If any of them fail, then we should prefer to roll back all of the
    prepared transactions, undoing all of the work of step #4, go fix
    whatever was broken, and retry.

 6. Now, we need to update the functions.

    A slonik script runs UPDATE FUNCTIONS against all nodes.

At the "grand steps" level, that seems like it covers what needs to be
done.

Note the ===> CREATE EVENT <=== step; this needs to be run against
each node *during* the upgrade process, and note that the output of
that is used to "seed" sl_setsync on the other nodes.  

As a result, it is NOT as simple as throwing the queries at each node,
in turn; we need to have the big transaction partway done on every
node.  The upgrade is *not* implementable as a simple shell script -
it needs to be implemented in a language that supports having all of
the transactions open at once, which effectively points us to one of:

  a) C
  b) Perl with DBI
  c) Some other language that supports opening multiple DB connections
     at once

C and Perl both seem like reasonable choices, since Slony-I already
uses and has dependancies on these languages.  It seems like a poor
idea to introduce any other languages to the mix.

--- NEW FILE: upgrade_12_20_common.sh ---
#!/bin/sh
# $Id: upgrade_12_20_common.sh,v 1.1.2.1 2009-02-23 17:19:15 cbbrowne Exp $

# We begin by setting DB configuration defaults/overrides
CLUSTER=${CLUSTER1:-"slony_regress1"}
NUMNODES=${NUMNODES:-"2"}
ACCEPTABLELAG="'935 seconds'::interval"

PGBINDIR=${PGBINDIR:-"/usr/local/pgsql/bin"}
SLTOOLDIR=${SLTOOLDIR:-".."}

DB1=${DB1:-"slonyregress1"}
HOST1=${HOST1:-"localhost"}
USER1=${USER1:-${PGUSER:-"postgres"}}
PORT1=${PORT1:-${PGPORT:-"5432"}}

DB2=${DB2:-"slonyregress2"}
HOST2=${HOST2:-"localhost"}
USER2=${USER2:-${PGUSER:-"postgres"}}
PORT2=${PORT2:-${PGPORT:-"5432"}}

DB3=${DB3:-"slonyregress3"}
HOST3=${HOST3:-"localhost"}
USER3=${USER3:-${PGUSER:-"postgres"}}
PORT3=${PORT3:-${PGPORT:-"5432"}}

DB4=${DB4:-"slonyregress4"}
HOST4=${HOST4:-"localhost"}
USER4=${USER4:-${PGUSER:-"postgres"}}
PORT4=${PORT4:-${PGPORT:-"5432"}}

# Feel free to add additional entries for each database that is to be
# part of the upgrade

# Note that environment variables may be used as alternatives to
# updates to this script; set values for DB1, DB2, ..., HOST1, HOST2,
# ..., USER1, USER2, ..., and so forth

# Now, derived values to be used later...
PSQL=${PGBINDIR}/psql
CLSCHEMA="\"_${CLUSTER}\""

err()
{
    exitval=$1
    shift
    echo 1>&2 "$0: ERROR: $*"
    numerrors=`expr ${numerrors} + 1`

    exit $exitval
}

--- NEW FILE: lock_sets.sh ---
#!/bin/sh
# $Id: lock_sets.sh,v 1.1.2.1 2009-02-23 17:19:15 cbbrowne Exp $

source upgrade_12_20_common.sh

echo "Dumping configuration info about upgrade"
date

echo "Cluster: ${CLUSTER}"
echo "PostgreSQL binaries in: ${PGBINDIR}"
echo "Slony-I tools in: ${SLTOOLDIR}"

echo "Number of nodes: ${NUMNODES}"

echo "Locking nodes..."

node=1
while : ; do
    eval db=\$DB${node}
    eval host=\$HOST${node}
    eval user=\$USER${node}
    eval port=\$PORT${node}

    echo "Node ${node} - DB connection - PGDATABASE=${db} PGHOST=${host} PGUSER=${user} PGPORT=${port}"
    echo "--------------------------------------------------------------------------------------------"

    SETS=`${PSQL} -tq -R " " -d ${db} -h ${host} -U ${user} -p ${port} -c "select set_id from ${CLSCHEMA}.sl_set where set_origin = ${CLSCHEMA}.getlocalnodeid('_${CLUSTER}') and set_locked is null;"`

    echo "Unlocked replication sets originating on this node: ${SETS}"

    echo "Locking them..."
    ${PSQL} -d ${db} -h ${host} -U ${user} -p ${port} -c "select ${CLSCHEMA}.lockSet(set_id) from ${CLSCHEMA}.sl_set where set_origin = ${CLSCHEMA}.getlocalnodeid('_${CLUSTER}') and set_locked is null;"

    if [ ${node} -ge ${NUMNODES} ]; then
	break;
    else
	node=$((${node} + 1))
    fi
done


--- NEW FILE: upgrade_12_20_part1.sh ---
#!/bin/sh
# $Id: upgrade_12_20_part1.sh,v 1.1.2.1 2009-02-23 17:19:15 cbbrowne Exp $

# We begin by setting DB configuration defaults/overrides

CLUSTER=${CLUSTER1:-"slony_regress1"}

DB1=${DB1:-"slonyregress1"}
HOST1=${HOST1:-"localhost"}
USER1=${USER1:-${PGUSER:-"postgres"}}
WEAKUSER1=${WEAKUSER1:-${WEAKUSER:-${PGUSER:-"weakuser"}}}
PORT1=${PORT1:-${PGPORT:-"5432"}}
PGBINDIR1=${PGBINDIR1:-${PGBINDIR:-"/usr/local/pgsql/bin"}}

DB2=${DB2:-"slonyregress2"}
HOST2=${HOST2:-"localhost"}
USER2=${USER2:-${PGUSER:-"postgres"}}
WEAKUSER2=${WEAKUSER2:-${WEAKUSER:-${PGUSER:-"weakuser"}}}
PORT2=${PORT2:-${PGPORT:-"5432"}}
PGBINDIR2=${PGBINDIR2:-${PGBINDIR:-"/usr/local/pgsql/bin"}}

DB3=${DB3:-"slonyregress3"}
HOST3=${HOST3:-"localhost"}
USER3=${USER3:-${PGUSER:-"postgres"}}
WEAKUSER3=${WEAKUSER3:-${WEAKUSER:-${PGUSER:-"weakuser"}}}
PORT3=${PORT3:-${PGPORT:-"5432"}}
PGBINDIR3=${PGBINDIR3:-${PGBINDIR:-"/usr/local/pgsql/bin"}}

DB4=${DB4:-"slonyregress4"}
HOST4=${HOST4:-"localhost"}
USER4=${USER4:-${PGUSER:-"postgres"}}
WEAKUSER4=${WEAKUSER4:-${WEAKUSER:-${PGUSER:-"weakuser"}}}
PORT4=${PORT4:-${PGPORT:-"5432"}}
PGBINDIR4=${PGBINDIR4:-${PGBINDIR:-"/usr/local/pgsql/bin"}}

DB5=${DB5:-"slonyregress5"}
HOST5=${HOST5:-"localhost"}
USER5=${USER5:-${PGUSER:-"postgres"}}
WEAKUSER5=${WEAKUSER5:-${WEAKUSER:-${PGUSER:-"weakuser"}}}
PORT5=${PORT5:-${PGPORT:-"5432"}}
PGBINDIR5=${PGBINDIR5:-${PGBINDIR:-"/usr/local/pgsql/bin"}}

DB6=${DB6:-"slonyregress6"}
HOST6=${HOST6:-"localhost"}
USER6=${USER6:-${PGUSER:-"postgres"}}
WEAKUSER6=${WEAKUSER6:-${WEAKUSER:-${PGUSER:-"weakuser"}}}
PORT6=${PORT6:-${PGPORT:-"5432"}}
PGBINDIR6=${PGBINDIR6:-${PGBINDIR:-"/usr/local/pgsql/bin"}}

DB7=${DB7:-"slonyregress7"}
HOST7=${HOST7:-"localhost"}
USER7=${USER7:-${PGUSER:-"postgres"}}
WEAKUSER7=${WEAKUSER7:-${WEAKUSER:-${PGUSER:-"weakuser"}}}
PORT7=${PORT7:-${PGPORT:-"5432"}}
PGBINDIR7=${PGBINDIR7:-${PGBINDIR:-"/usr/local/pgsql/bin"}}

DB8=${DB8:-"slonyregress8"}
HOST8=${HOST8:-"localhost"}
USER8=${USER8:-${PGUSER:-"postgres"}}
WEAKUSER8=${WEAKUSER8:-${WEAKUSER:-${PGUSER:-"weakuser"}}}
PORT8=${PORT8:-${PGPORT:-"5432"}}
PGBINDIR8=${PGBINDIR8:-${PGBINDIR:-"/usr/local/pgsql/bin"}}

DB9=${DB9:-"slonyregress9"}
HOST9=${HOST9:-"localhost"}
USER9=${USER9:-${PGUSER:-"postgres"}}
WEAKUSER9=${WEAKUSER9:-${WEAKUSER:-${PGUSER:-"weakuser"}}}
PORT9=${PORT9:-${PGPORT:-"5432"}}
PGBINDIR9=${PGBINDIR9:-${PGBINDIR:-"/usr/local/pgsql/bin"}}

DB10=${DB10:-"slonyregress10"}
HOST10=${HOST10:-"localhost"}
USER10=${USER10:-${PGUSER:-"postgres"}}
WEAKUSER10=${WEAKUSER01:-${WEAKUSER:-${PGUSER:-"weakuser"}}}
PORT10=${PORT10:-${PGPORT:-"5432"}}
PGBINDIR10=${PGBINDIR10:-${PGBINDIR:-"/usr/local/pgsql/bin"}}

DB11=${DB11:-"slonyregress11"}
HOST11=${HOST11:-"localhost"}
USER11=${USER11:-${PGUSER:-"postgres"}}
WEAKUSER11=${WEAKUSER11:-${WEAKUSER:-${PGUSER:-"weakuser"}}}
PORT11=${PORT11:-${PGPORT:-"5432"}}
PGBINDIR11=${PGBINDIR11:-${PGBINDIR:-"/usr/local/pgsql/bin"}}

DB12=${DB12:-"slonyregress12"}
HOST12=${HOST12:-"localhost"}
USER12=${USER12:-${PGUSER:-"postgres"}}
WEAKUSER12=${WEAKUSER12:-${WEAKUSER:-${PGUSER:-"weakuser"}}}
PORT12=${PORT12:-${PGPORT:-"5432"}}
PGBINDIR12=${PGBINDIR12:-${PGBINDIR:-"/usr/local/pgsql/bin"}}

DB13=${DB13:-"slonyregress13"}
HOST13=${HOST13:-"localhost"}
USER13=${USER13:-${PGUSER:-"postgres"}}
WEAKUSER13=${WEAKUSER13:-${WEAKUSER:-${PGUSER:-"weakuser"}}}
PORT13=${PORT13:-${PGPORT:-"5432"}}
PGBINDIR13=${PGBINDIR13:-${PGBINDIR:-"/usr/local/pgsql/bin"}}

# Where to look for tools (e.g. - slony1_dump.sh)
SLTOOLDIR=${SLTOOLDIR:-"../tools"}




More information about the Slony1-commit mailing list