From: Tom Lane Date: Sat, 28 Aug 2004 21:36:25 +0000 (+0000) Subject: Remove contrib/rserv, since there are better replication solutions X-Git-Tag: REL8_0_0BETA2~35 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d77f74fa7ef52dd13040dc1d57d88a1595e4205a;p=postgresql Remove contrib/rserv, since there are better replication solutions available elsewhere (including a descendant project on gborg). --- diff --git a/contrib/Makefile b/contrib/Makefile index 7dc0405f94..1a25bfd17e 100644 --- a/contrib/Makefile +++ b/contrib/Makefile @@ -1,4 +1,4 @@ -# $PostgreSQL: pgsql/contrib/Makefile,v 1.49 2004/06/01 05:15:47 tgl Exp $ +# $PostgreSQL: pgsql/contrib/Makefile,v 1.50 2004/08/28 21:36:24 tgl Exp $ subdir = contrib top_builddir = .. @@ -31,7 +31,6 @@ WANTED_DIRS = \ pgbench \ pgcrypto \ pgstattuple \ - rserv \ rtree_gist \ seg \ spi \ diff --git a/contrib/README b/contrib/README index 37904cdb3e..7cacdc2bde 100644 --- a/contrib/README +++ b/contrib/README @@ -170,10 +170,6 @@ reindexdb - Reindexes a database by Shaun Thomas -rserv - - Replication server - by Vadim B. Mikheev - rtree_gist - Support for emulating RTREE indexing in GiST by Oleg Bartunov and Teodor Sigaev diff --git a/contrib/rserv/ApplySnapshot.in b/contrib/rserv/ApplySnapshot.in deleted file mode 100644 index 0f8523ef32..0000000000 --- a/contrib/rserv/ApplySnapshot.in +++ /dev/null @@ -1,54 +0,0 @@ -# -*- perl -*- -## ApplySnapshot -# Vadim Mikheev, (c) 2000, PostgreSQL Inc. - -eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' - & eval 'exec perl -S $0 $argv:q' - if 0; - -use lib "@LIBDIR@"; -use IO::File; -use RServ; -use Getopt::Long; - -$| = 1; - -$result = GetOptions("debug!", "verbose!", "help", - "host=s", "user=s", "password=s"); - -my $debug = $opt_debug || 0; -my $verbose = $opt_verbose || 0; -my $snapshot = $opt_snapshot || "__Snapshot"; - -if (defined($opt_help) || (scalar(@ARGV) < 1)) { - print "Usage: $0 --host=name --user=name --password=string slavedb\n"; - exit ((scalar(@ARGV) < 1)? 1:0); -} - -my $slave = $ARGV[0] || "slave"; - -my $sinfo = "dbname=$slave"; -$sinfo = "$sinfo host=$opt_host" if (defined($opt_host)); -$sinfo = "$sinfo user=$opt_user" if (defined($opt_user)); -$sinfo = "$sinfo password=$opt_password" if (defined($opt_password)); - -my $conn = Pg::connectdb($sinfo); - -my $inpf = new IO::File; -$inpf = STDIN; - -$RServ::quiet = !$verbose; - -$res = ApplySnapshot ($conn, $inpf); - -if ($res > 0) -{ - printf STDERR "Snapshot applied\n"; -} -elsif ($res != 0) -{ - printf STDERR "ERROR\n"; - exit(1); -} - -exit(0); diff --git a/contrib/rserv/CleanLog.in b/contrib/rserv/CleanLog.in deleted file mode 100644 index 24e0a6c622..0000000000 --- a/contrib/rserv/CleanLog.in +++ /dev/null @@ -1,49 +0,0 @@ -# -*- perl -*- -## CleanLog -# Vadim Mikheev, (c) 2000, PostgreSQL Inc. - -eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' - & eval 'exec perl -S $0 $argv:q' - if 0; - -use lib "@LIBDIR@"; - -use Getopt::Long; -use RServ; - -$| = 1; - -$result = GetOptions("debug!", "verbose!", "help", "snapshot=s", - "host=s", "user=s", "password=s"); - -my $debug = $opt_debug || 0; -my $verbose = $opt_verbose || 0; -my $snapshot = $opt_snapshot || "__Snapshot"; - -if (defined($opt_help) || (scalar(@ARGV) < 2) || ($ARGV[1] !~ /^\d+$/)) { - print "Usage: $PROGRAM_NAME --host=name --user=name --password=string masterdb syncid\n"; - exit ((scalar(@ARGV) < 2)? 1: 0); -} - -my $dbname = $ARGV[0]; -my $howold = $ARGV[1]; - -my $minfo = "dbname=$dbname"; -$minfo = "$minfo host=$opt_host" if (defined($opt_host)); -$minfo = "$minfo user=$opt_user" if (defined($opt_user)); -$minfo = "$minfo password=$opt_password" if (defined($opt_password)); - -print "Master connection is $minfo\n" if ($debug); -print "Slave connection is $sinfo\n" if ($debug); - -my $conn = Pg::connectdb($minfo); - -$RServ::quiet = !$verbose; - -$res = CleanLog($conn, $howold); - -exit(1) if $res < 0; - -printf STDERR "Deleted %d log records\n", $res if $res > 0; - -exit(0); diff --git a/contrib/rserv/GetSyncID.in b/contrib/rserv/GetSyncID.in deleted file mode 100644 index 67eb31cebf..0000000000 --- a/contrib/rserv/GetSyncID.in +++ /dev/null @@ -1,57 +0,0 @@ -# -*- perl -*- -## GetSyncID -# Vadim Mikheev, (c) 2000, PostgreSQL Inc. - -eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' - & eval 'exec perl -S $0 $argv:q' - if 0; - -use lib "@LIBDIR@"; - -use Pg; -use Getopt::Long; -use RServ; - -$| = 1; - -my $verbose = 1; - -$result = GetOptions("debug!", "verbose!", "help", - "host=s", "user=s", "password=s"); - -my $debug = $opt_debug || 0; -my $verbose = $opt_verbose if (defined($opt_verbose)); - -if (defined($opt_help) || (scalar(@ARGV) < 1)) { - print "Usage: $0 --host=name --user=name --password=string slavedb\n"; - exit ((scalar(@ARGV) < 1)? 1: 0); -} - -my $dbname = $ARGV[0]; - -my $sinfo = "dbname=$dbname"; -$sinfo = "$sinfo host=$opt_host" if (defined($opt_host)); -$sinfo = "$sinfo user=$opt_user" if (defined($opt_user)); -$sinfo = "$sinfo password=$opt_password" if (defined($opt_password)); - -print("Connecting to '$sinfo'\n") if ($debug || $verbose); -my $conn = Pg::connectdb($sinfo); - -$RServ::quiet = !$verbose; - -$res = GetSyncID($conn); - -die "ERROR\n" if $res < 0; - -if (! defined $res) -{ - printf STDERR "No SyncID found\n"; -} -else -{ - print("Last SyncID applied: ") if ($verbose); - printf "%d", $res; - print("\n") if ($verbose); -} - -exit(0); diff --git a/contrib/rserv/InitRservTest.in b/contrib/rserv/InitRservTest.in deleted file mode 100644 index 3f1aac7021..0000000000 --- a/contrib/rserv/InitRservTest.in +++ /dev/null @@ -1,259 +0,0 @@ -#!/bin/sh -## InitRservTest -# erServer demonstration implementation -# (c) 2000 Vadim Mikheev, PostgreSQL Inc. - -[ -n "$RSERV_PERL" ] || RSERV_PERL=@LIBDIR@ -[ -n "$RSERV_SQL" ] || RSERV_SQL=@SQLDIR@ -[ -n "$RSERV_BIN" ] || RSERV_BIN=@BINDIR@ -export RSERV_PERL -export RSERV_SQL -export RSERV_BIN - -pargs= - -while [[ $1 == -* ]]; do - case "$1" in - --user) - shift - pargs="$pargs -U $1" - ;; - --host) - shift - pargs="$pargs -h $1" - ;; - *) - echo "Usage: $0 --user name --host name masterdb slavedb" - exit 1 - ;; - esac - shift -done - -masterdb=$1 -slavedb=$2 - -[ "${masterdb}" != "" ] || masterdb=master -[ "${slavedb}" != "" ] || slavedb=slave - -echo "Master -> $masterdb" -echo "Slave -> $slavedb" - -############################################################################ - -fill() -{ - table="create table test (i text, k int, l int); -copy test from stdin; -Line: 1 1 1 -Line: 2 2 2 -Line: 3 3 3 -Line: 4 4 4 -Line: 5 5 5 -Line: 6 6 6 -Line: 7 7 7 -Line: 8 8 8 -Line: 9 9 9 -Line: 10 10 10 -Line: 11 11 11 -Line: 12 12 12 -Line: 13 13 13 -Line: 14 14 14 -Line: 15 15 15 -Line: 16 16 16 -Line: 17 17 17 -Line: 18 18 18 -Line: 19 19 19 -Line: 20 20 20 -Line: 21 21 21 -Line: 22 22 22 -Line: 23 23 23 -Line: 24 24 24 -Line: 25 25 25 -Line: 26 26 26 -Line: 27 27 27 -Line: 28 28 28 -Line: 29 29 29 -Line: 30 30 30 -Line: 31 31 31 -Line: 32 32 32 -Line: 33 33 33 -Line: 34 34 34 -Line: 35 35 35 -Line: 36 36 36 -Line: 37 37 37 -Line: 38 38 38 -Line: 39 39 39 -Line: 40 40 40 -Line: 41 41 41 -Line: 42 42 42 -Line: 43 43 43 -Line: 44 44 44 -Line: 45 45 45 -Line: 46 46 46 -Line: 47 47 47 -Line: 48 48 48 -Line: 49 49 49 -Line: 50 50 50 -Line: 51 51 51 -Line: 52 52 52 -Line: 53 53 53 -Line: 54 54 54 -Line: 55 55 55 -Line: 56 56 56 -Line: 57 57 57 -Line: 58 58 58 -Line: 59 59 59 -Line: 60 60 60 -Line: 61 61 61 -Line: 62 62 62 -Line: 63 63 63 -Line: 64 64 64 -Line: 65 65 65 -Line: 66 66 66 -Line: 67 67 67 -Line: 68 68 68 -Line: 69 69 69 -Line: 70 70 70 -Line: 71 71 71 -Line: 72 72 72 -Line: 73 73 73 -Line: 74 74 74 -Line: 75 75 75 -Line: 76 76 76 -Line: 77 77 77 -Line: 78 78 78 -Line: 79 79 79 -Line: 80 80 80 -Line: 81 81 81 -Line: 82 82 82 -Line: 83 83 83 -Line: 84 84 84 -Line: 85 85 85 -Line: 86 86 86 -Line: 87 87 87 -Line: 88 88 88 -Line: 89 89 89 -Line: 90 90 90 -Line: 91 91 91 -Line: 92 92 92 -Line: 93 93 93 -Line: 94 94 94 -Line: 95 95 95 -Line: 96 96 96 -Line: 97 97 97 -Line: 98 98 98 -Line: 99 99 99 -Line: 100 100 100 -\\."; - echo "$table" | psql $pargs $1 || exit - if [ "$1" = "$masterdb" ] - then - rm -rf __tmpf__ - psql $pargs -c "select * into table testoid from test" $1 || exit - psql $pargs -c "copy testoid with oids to '`pwd`/__tmpf__'" $1 || exit - psql $pargs -c "select * into table teststr from test" $1 || exit - else - psql $pargs -c "select * into table testoid from test where k < 0" $1 || exit - psql $pargs -c "copy testoid with oids from '`pwd`/__tmpf__'" $1 || exit - psql $pargs -c "select * into table teststr from test" $1 || exit - rm -rf __tmpf__ - fi - psql $pargs -c "create unique index i_test on test (k)" $1 || exit - psql $pargs -c "create unique index i_testoid on testoid (oid)" $1 || exit - psql $pargs -c "create unique index i_teststr on teststr (i)" $1 || exit - psql $pargs -c vacuum $1 || exit -} - -############################################################################ - -echo -echo -echo ' ATTENTION' -echo -echo This script will destroy databases with names MASTER and SLAVE -echo -echo -n "Are you going to continue ? [Y/N] " - -read answ - -case $answ in - Y*|y*) - ;; - *) - exit - ;; -esac - -echo -echo - -sql="drop database $masterdb" -echo $sql -psql $pargs -c "$sql" template1 -sql="create database $masterdb" -echo $sql -psql $pargs -c "$sql" template1 || exit - -echo Setup master system -psql $pargs $masterdb < $RSERV_SQL/master.sql || exit - -echo Wait for template1 to become available... -sleep 1 - -sql="drop database $slavedb" -echo $sql -psql $pargs -c "$sql" template1 -sql="create database $slavedb" -echo $sql -psql $pargs -c "$sql" template1 || exit - -echo Setup slave system -psql $pargs $slavedb < $RSERV_SQL/slave.sql || exit - -echo Create and fill test, testoid and teststr tables in master db -fill $masterdb -echo -echo Register test, testoid and teststr tables for replication on master -echo -$RSERV_BIN/MasterAddTable $masterdb test k -$RSERV_BIN/MasterAddTable $masterdb testoid oid -$RSERV_BIN/MasterAddTable $masterdb teststr i - -echo Create and fill test, testoid and teststr tables in slave db -fill $slavedb -echo -echo Register test, testoid and teststr tables for replication on slave -echo -$RSERV_BIN/SlaveAddTable $slavedb test k -$RSERV_BIN/SlaveAddTable $slavedb testoid oid -$RSERV_BIN/SlaveAddTable $slavedb teststr i - -echo -echo -echo -echo -echo -echo -echo -echo -echo " Now make changes in $masterdb db and run" -echo -echo " Replicate $masterdb $slavedb" -echo -echo " to replicate the master on the slave." -echo -echo " You may also use the RservTest tcl utility" -echo " to demonstrate this functionality." -echo -echo -echo -echo -echo -echo -echo -echo - -exit - -############################################################################ diff --git a/contrib/rserv/Makefile b/contrib/rserv/Makefile deleted file mode 100644 index a26c435628..0000000000 --- a/contrib/rserv/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -# Makefile for erServer demonstration implementation -# (c) 2000 Vadim Mikheev, PostgreSQL Inc. - -NAME = rserv -MODULES = rserv -DATA = RServ.pm -DATA_built = master.sql slave.sql -SQLS = $(DATA_built) -DOCS = README.rserv -SCRIPTS_built = RservTest -SCRIPTS_built += MasterInit MasterAddTable Replicate MasterSync CleanLog -SCRIPTS_built += SlaveInit SlaveAddTable GetSyncID -SCRIPTS_built += PrepareSnapshot ApplySnapshot -SCRIPTS_built += InitRservTest - - -ifdef USE_PGXS -PGXS = $(shell pg_config --pgxs) -include $(PGXS) -else -subdir = contrib/rserv -top_builddir = ../.. -include $(top_builddir)/src/Makefile.global -include $(top_srcdir)/contrib/contrib-global.mk -endif - - -$(SQLS): %.sql: %.sql.in - sed 's,@MODULE_FILENAME@,$$libdir/$(NAME),g' $< >$@ - -$(SCRIPTS_built): %: %.in - sed -e 's,@MODULE_FILENAME@,$$libdir/$(NAME),g' \ - -e 's:@SQLDIR@:$(datadir)/contrib:g' \ - -e 's:@BINDIR@:$(bindir):g' \ - -e 's:@LIBDIR@:$(datadir)/contrib:g' $< >$@ - chmod a+x $@ diff --git a/contrib/rserv/MasterAddTable.in b/contrib/rserv/MasterAddTable.in deleted file mode 100644 index 16ecfc7295..0000000000 --- a/contrib/rserv/MasterAddTable.in +++ /dev/null @@ -1,61 +0,0 @@ -# -*- perl -*- -## MasterAddTable -# Vadim Mikheev, (c) 2000, PostgreSQL Inc. - -eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' - & eval 'exec perl -S $0 $argv:q' - if 0; - -use Pg; -use Getopt::Long; - -$| = 1; - -$result = GetOptions("debug!", "verbose!", "help", - "host=s", "user=s", "password=s"); - -my $debug = $opt_debug || 0; -my $verbose = $opt_verbose || 0; - -if (defined($opt_help) || (scalar(@ARGV) < 3)) { - print "Usage: $0 --host=name --user=name --password=string masterdb table column\n"; - exit ((scalar(@ARGV) < 3)? 1: 0); -} - -my $dbname = $ARGV[0]; -my $table = $ARGV[1]; -my $keyname = $ARGV[2]; - -my $minfo = "dbname=$dbname"; -$minfo = "$minfo host=$opt_host" if (defined($opt_host)); -$minfo = "$minfo user=$opt_user" if (defined($opt_user)); -$minfo = "$minfo password=$opt_password" if (defined($opt_password)); - -my $conn = Pg::connectdb($minfo); - -my $result = $conn->exec("BEGIN"); -die $conn->errorMessage if $result->resultStatus ne PGRES_COMMAND_OK; - -$result = $conn->exec("select pgc.oid, pga.attnum from pg_class pgc" . - ", pg_attribute pga where pgc.relname = '$table'" . - " and pgc.oid = pga.attrelid" . - " and pga.attname = '$keyname'"); -die $conn->errorMessage if $result->resultStatus ne PGRES_TUPLES_OK; - -my @row = $result->fetchrow; -die "Can't find table/key\n" if ! defined $row[0] || ! defined $row[1]; - -$result = $conn->exec("create trigger _RSERV_TRIGGER_T_ after" . - " insert or update or delete on $table" . - " for each row execute procedure" . - " _rserv_log_('$row[1]')"); -die $conn->errorMessage if $result->resultStatus ne PGRES_COMMAND_OK; - -$result = $conn->exec("insert into _RSERV_TABLES_ (tname, cname, reloid, key)" . - " values ('$table', '$keyname', $row[0], $row[1])"); -die $conn->errorMessage if $result->resultStatus ne PGRES_COMMAND_OK; - -$result = $conn->exec("COMMIT"); -die $conn->errorMessage if $result->resultStatus ne PGRES_COMMAND_OK; - -exit(0); diff --git a/contrib/rserv/MasterInit.in b/contrib/rserv/MasterInit.in deleted file mode 100644 index 52744db84c..0000000000 --- a/contrib/rserv/MasterInit.in +++ /dev/null @@ -1,109 +0,0 @@ -# -*- perl -*- -## MasterInit -# Vadim Mikheev, (c) 2000, PostgreSQL Inc. - -eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' - & eval 'exec perl -S $0 $argv:q' - if 0; - -use Pg; -use Getopt::Long; - -$| = 1; - -$result = GetOptions("debug!", "verbose!", "help", - "host=s", "user=s", "password=s"); - -my $debug = $opt_debug || 0; -my $verbose = $opt_verbose || 0; - -if (defined($opt_help) || (scalar(@ARGV) < 1)) { - print "Usage: $0 --host=name --user=name --password=string masterdb\n"; - exit ((scalar(@ARGV) < 1)? 1:0); -} - -my $module_filename = '@MODULE_FILENAME@'; - -my $master = $ARGV[0] || "master"; - -my $minfo = "dbname=$master"; -$minfo = "$minfo host=$opt_host" if (defined($opt_host)); -$minfo = "$minfo user=$opt_user" if (defined($opt_user)); -$minfo = "$minfo password=$opt_password" if (defined($opt_password)); - -sub RollbackAndQuit { - $conn = shift @_; - - print STDERR "Error in query: ", $conn->errorMessage; - $conn->exec("ROLLBACK"); - exit (-1); -} - -my $conn = Pg::connectdb($minfo); -if ($conn->status != PGRES_CONNECTION_OK) { - print STDERR "Failed opening $minfo\n"; - exit 1; -} - -my $result = $conn->exec("BEGIN"); -RollbackAndQuit($conn) if ($result->resultStatus ne PGRES_COMMAND_OK); - -$result = $conn->exec("set transaction isolation level serializable"); -RollbackAndQuit($conn) if ($result->resultStatus ne PGRES_COMMAND_OK); - -# List of slave servers -$result = $conn->exec("create table _RSERV_SERVERS_" . - " (server serial, host text, post int4, dbase text)"); -RollbackAndQuit($conn) if ($result->resultStatus ne PGRES_COMMAND_OK); - -# List of replicated tables -$result = $conn->exec("create table _RSERV_TABLES_" . - " (tname name, cname name, reloid oid, key int4)"); -RollbackAndQuit($conn) if ($result->resultStatus ne PGRES_COMMAND_OK); - -# Bookkeeping log for row replication -$result = $conn->exec("create table _RSERV_LOG_" . - " (reloid oid, logid int4, logtime timestamp, deleted int4, key text)"); -RollbackAndQuit($conn) if ($result->resultStatus ne PGRES_COMMAND_OK); - -# This is to speedup lookup of deleted tuples -$result = $conn->exec("create index _RSERV_LOG_INDX_DLT_ID_ on _RSERV_LOG_ (deleted, logid)"); -RollbackAndQuit($conn) if ($result->resultStatus ne PGRES_COMMAND_OK); - -# This is to speedup cleanup -$result = $conn->exec("create index _RSERV_LOG_INDX_TM_ID_ on _RSERV_LOG_ (logtime, logid)"); -RollbackAndQuit($conn) if ($result->resultStatus ne PGRES_COMMAND_OK); - -# This is to speedup trigger and lookup of updated tuples -$result = $conn->exec("create index _RSERV_LOG_INDX_REL_KEY_ on _RSERV_LOG_ (reloid, key)"); -RollbackAndQuit($conn) if ($result->resultStatus ne PGRES_COMMAND_OK); - -# Sync point for each slave server -$result = $conn->exec("create table _RSERV_SYNC_" . - " (server int4, syncid int4, synctime timestamp" . - ", status int4, minid int4, maxid int4, active text)"); -RollbackAndQuit($conn) if ($result->resultStatus ne PGRES_COMMAND_OK); - -$result = $conn->exec("create index _RSERV_SYNC_INDX_SRV_ID_ on _RSERV_SYNC_ (server, syncid)"); -RollbackAndQuit($conn) if ($result->resultStatus ne PGRES_COMMAND_OK); - -# Sync point reference numbers -$result = $conn->exec("create sequence _rserv_sync_seq_"); -RollbackAndQuit($conn) if ($result->resultStatus ne PGRES_COMMAND_OK); - -$result = $conn->exec("CREATE FUNCTION _rserv_log_() RETURNS trigger" . - " AS '$module_filename' LANGUAGE 'c'"); -RollbackAndQuit($conn) if ($result->resultStatus ne PGRES_COMMAND_OK); - -$result = $conn->exec("CREATE FUNCTION _rserv_sync_(int4) RETURNS int4" . - " AS '$module_filename' LANGUAGE 'c'"); -RollbackAndQuit($conn) if ($result->resultStatus ne PGRES_COMMAND_OK); - -$result = $conn->exec("CREATE FUNCTION _rserv_debug_(int4) RETURNS int4" . - " AS '$module_filename' LANGUAGE 'c'"); -RollbackAndQuit($conn) if ($result->resultStatus ne PGRES_COMMAND_OK); - -$result = $conn->exec("COMMIT"); -RollbackAndQuit($conn) if ($result->resultStatus ne PGRES_COMMAND_OK); - -exit (0); diff --git a/contrib/rserv/MasterSync.in b/contrib/rserv/MasterSync.in deleted file mode 100644 index 6abdfaffa2..0000000000 --- a/contrib/rserv/MasterSync.in +++ /dev/null @@ -1,50 +0,0 @@ -# -*- perl -*- -## MasterSync -# Vadim Mikheev, (c) 2000, PostgreSQL Inc. - -eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' - & eval 'exec perl -S $0 $argv:q' - if 0; - -use lib "@LIBDIR@"; - -use Getopt::Long; -use RServ; - -$| = 1; - -$result = GetOptions("debug!", "verbose!", "quiet!", "help", - "host=s", "user=s", "password=s"); - -my $debug = $opt_debug || 0; -my $verbose = $opt_verbose || 0; -my $quiet = $opt_quiet || 0; - -if (defined($opt_help) || (scalar(@ARGV) < 2) || ($ARGV[1] !~ /^\d+$/)) { - print "Usage: $0 --host=name --user=name --password=string masterdb syncid\n"; - exit ((scalar(@ARGV) < 2)? 1:0); -} - -my $master = $ARGV[0] || "master"; -my $server = 0; -my $syncid = $ARGV[1] || die "SyncID not specified"; - -my $minfo = "dbname=$master"; -$minfo = "$minfo host=$opt_host" if (defined($opt_host)); -$minfo = "$minfo user=$opt_user" if (defined($opt_user)); -$minfo = "$minfo password=$opt_password" if (defined($opt_password)); - -my $conn = Pg::connectdb($minfo); - -$RServ::quiet = !$verbose; - -$res = SyncSyncID($conn, $server, $syncid); - -if ($res == 0) -{ - printf STDERR "SyncID updated on $master\n" if ($verbose); - exit(0); -} - -printf STDERR "ERROR\n" unless ($quiet); -exit(1); diff --git a/contrib/rserv/PrepareSnapshot.in b/contrib/rserv/PrepareSnapshot.in deleted file mode 100644 index 707c15e6a4..0000000000 --- a/contrib/rserv/PrepareSnapshot.in +++ /dev/null @@ -1,58 +0,0 @@ -# -*- perl -*- -## PrepareSnapshot -# Vadim Mikheev, (c) 2000, PostgreSQL Inc. - -eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' - & eval 'exec perl -S $0 $argv:q' - if 0; - -use lib "@LIBDIR@"; - -use IO::File; -use Getopt::Long; -use RServ; - -$| = 1; - -$result = GetOptions("debug!", "verbose!", "help", "snapshot=s", - "host=s", "user=s", "password=s"); - -my $debug = $opt_debug || 0; -my $verbose = $opt_verbose || 0; -my $snapshot = $opt_snapshot || "__Snapshot"; - -if (defined($opt_help) || (scalar(@ARGV) < 1)) { - print "Usage: $0 --snapshot=file --host=name --user=name --password=string masterdb\n"; - exit ((scalar(@ARGV) < 1)? 1:0); -} - -my $master = $ARGV[0] || "master"; -my $server = 0; - -my $minfo = "dbname=$master"; -$minfo = "$minfo host=$opt_host" if (defined($opt_host)); -$minfo = "$minfo user=$opt_user" if (defined($opt_user)); -$minfo = "$minfo password=$opt_password" if (defined($opt_password)); - -my $conn = Pg::connectdb($minfo); - -my $outf = new IO::File; -$outf = STDOUT; - -$RServ::quiet = !$verbose; - -$res = PrepareSnapshot ($conn, $outf, $server); - -if ($res == 0) -{ - printf STDERR "Sync-ed\n"; - exit(0); -} -if ($res > 0) -{ - printf STDERR "Snapshot dumped to STDOUT\n"; - exit(0); -} - -printf STDERR "ERROR\n"; -exit(1); diff --git a/contrib/rserv/README.rserv b/contrib/rserv/README.rserv deleted file mode 100644 index 1a61fefd2d..0000000000 --- a/contrib/rserv/README.rserv +++ /dev/null @@ -1,133 +0,0 @@ -erServer demonstration implementation -(c) 2000, Vadim Mikheev and Thomas Lockhart, PostgreSQL Inc. - -Version 0.1: - Replicates a master database to a single slave database. - Tested under Linux (Mandrake 7.2). - -Requirements: - -- PostgreSQL >= 7.0.X - A separate Makefile is required for PostgreSQL 7.0.x and earlier -- Perl5 and the PostgreSQL perl interface -- TCL and the PostgreSQL tcl interface (for demo only) - - -How to compile: - -- make all -- make install - -Scripts and libraries are installed in places which are consistant -with the way other contrib/ code is installed; underneath the core -items in a contrib/ directory. - - -The toolset: - -MasterInit dbname - sets up structures and user-defined functions for a master - database. - -SlaveInit dbname - sets up structures for a slave database. Does not include triggers, - but only bookkeeping tables. - -MasterAddTable dbname table column - sets up triggers for the specified table and column. Note that this - column must be updated for replication to occur. - -SlaveAddTable dbname table column - sets up bookkeeping for the specified table and column. - -Replicate masterdb slavedb - actually replicate changes from a master to single slave. Note that - this must be repeated to replicate to multiple slaves, but the - bookkeeping for each slave is handled separately so each can be - updated at different times and with different sets of changes. - -GetSyncID [--noverbose] slavedb - returns the last syncid the specified slave has seen. May be used - in conjunction with SyncSyncID and CleanLog using the --noverbose - option. - -MasterSync masterdb syncid - registers a syncid with the specified master database. Used to - propagate replication success back to the master database. - -CleanLog masterdb syncid - removes obsolete entries in the master database replication log - table up to the specified replication sequence number. - -Other utilities: - -PrepareSnapshot - build a file of replication information from the specified masterdb. - -ApplySnapshot - use a file of replication information to apply to the specified - slavedb. - - -How to run a demo: - -Run the InitRservTest script. It will create two local databases -'master' & 'slave' with table 'test' in them. It accepts the following -arguments: - --help - Print a usage message and quit. - --user name - Access the database with another username. - --host name - Access a remote database. Note that the shared library *must* be - visible in the same path as installed on the build machine. - masterdb - slavedb - Names of test databases. Defaults to 'master' and 'slave', - respectively. - -Once the test databases are set up, simply updating the master table -is sufficient to log a replication event. You can update the table -test then run "Replicate master slave", or you can use the demo -program RservTest. - -Run the tcl/tk GUI demo program, RservTest. It has a single window, -which has four buttons and three data entry boxes. - - -------------------------------------------------- - | PostgreSQL Asynchronous Replication | - | Master Slave | - | < master > < slave > | - | | - | [ Update ] < > | - | [ Replicate ] | - | [ Show ] ____________ | - | | - | [ Quit ] | - | | - -------------------------------------------------- - -The demo has the following behaviors: - -If you enter a string into the data entry field to the right of -[Update], then that string will be used to either update the master -database or to query the slave database. - -If you click [Update], then the string in the data entry box will be -entered into the master database. - -If you click [Replicate], then all changes since the last replication -will be propagated to the slave database. - -If you click [Show], then the slave database will be queried to find -the string in the data entry box to the right of the [Update] -button. If the string does not (yet) exist in the slave database, then -"n/a" will appear to the right of the [Show] button. If the string -does exist in the slave database, then it will be printed to the right -of the [Show] button. - - -Todo: -1. Support for multiple slave servers. -2. Explicit support for master/slave failover. -3. More docs. diff --git a/contrib/rserv/RServ.pm b/contrib/rserv/RServ.pm deleted file mode 100644 index de0f037cbe..0000000000 --- a/contrib/rserv/RServ.pm +++ /dev/null @@ -1,761 +0,0 @@ -# -*- perl -*- -# RServ.pm -# Vadim Mikheev, (c) 2000, PostgreSQL Inc. - -package RServ; - -require Exporter; -@ISA = qw(Exporter); -@EXPORT = qw(PrepareSnapshot ApplySnapshot GetSyncID SyncSyncID CleanLog); -@EXPORT_OK = qw(); - -use Pg; - -$debug = 0; -$quiet = 1; - -my %Mtables = (); -my %Stables = (); - -sub PrepareSnapshot -{ - my ($conn, $outf, $server) = @_; # (@_[0], @_[1], @_[2]); - - my $result = $conn->exec("BEGIN"); - if ($result->resultStatus ne PGRES_COMMAND_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - $result = $conn->exec("set transaction isolation level serializable"); - if ($result->resultStatus ne PGRES_COMMAND_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - - # MAP oid --> tabname, keyname - $result = $conn->exec("select pgc.oid, pgc.relname, pga.attname" . - " from _RSERV_TABLES_ rt, pg_class pgc, pg_attribute pga" . - " where pgc.oid = rt.reloid and pga.attrelid = rt.reloid" . - " and pga.attnum = rt.key"); - if ($result->resultStatus ne PGRES_TUPLES_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - - my @row; - while (@row = $result->fetchrow) - { - # printf "$row[0], $row[1], $row[2]\n"; - push @{$Mtables{$row[0]}}, $row[1], $row[2]; - } - - # Read last succeeded sync - $sql = "select syncid, synctime, minid, maxid, active from _RSERV_SYNC_" . - " where server = $server and syncid = (select max(syncid) from" . - " _RSERV_SYNC_ where server = $server and status > 0)"; - - printf "$sql\n" if $debug; - - $result = $conn->exec($sql); - if ($result->resultStatus ne PGRES_TUPLES_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - - my @lastsync = $result->fetchrow; - - my $sinfo = ""; - if ($lastsync[3] ne '') # sync info - { - $sinfo = "and (l.logid >= $lastsync[3]"; - $sinfo .= " or l.logid in ($lastsync[4])" if $lastsync[4] ne ''; - $sinfo .= ")"; - } - - my $havedeal = 0; - - # DELETED rows - $sql = "select l.reloid, l.key from _RSERV_LOG_ l" . - " where l.deleted = 1 $sinfo order by l.reloid"; - - printf "$sql\n" if $debug; - - $result = $conn->exec($sql); - if ($result->resultStatus ne PGRES_TUPLES_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - - $lastoid = ''; - while (@row = $result->fetchrow) - { - next unless exists $Mtables{$row[0]}; - if ($lastoid != $row[0]) - { - if ($lastoid eq '') - { - my $syncid = GetSYNCID($conn, $outf); - return($syncid) if $syncid < 0; - $havedeal = 1; - } - else - { - printf $outf "\\.\n"; - } - printf $outf "-- DELETE $Mtables{$row[0]}[0]\n"; - $lastoid = $row[0]; - } - if (! defined $row[1]) - { - print STDERR "NULL key\n" unless ($quiet); - $conn->exec("ROLLBACK"); - return(-2); - } - printf $outf "%s\n", OutputValue($row[1]); - } - printf $outf "\\.\n" if $lastoid ne ''; - - # UPDATED rows - - my ($taboid, $tabname, $tabkey); - foreach $taboid (keys %Mtables) - { - ($tabname, $tabkey) = @{$Mtables{$taboid}}; - my $oidkey = ($tabkey eq 'oid') ? "_$tabname.oid," : ''; - $sql = sprintf "select $oidkey _$tabname.* from _RSERV_LOG_ l," . - " $tabname _$tabname where l.reloid = $taboid and l.deleted = 0 $sinfo" . - " and l.key = _$tabname.${tabkey}::text"; - - printf "$sql\n" if $debug; - - $result = $conn->exec($sql); - if ($result->resultStatus ne PGRES_TUPLES_OK) - { - printf $outf "-- ERROR\n" if $havedeal; - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - next if $result->ntuples <= 0; - if (! $havedeal) - { - my $syncid = GetSYNCID($conn, $outf); - return($syncid) if $syncid < 0; - $havedeal = 1; - } - printf $outf "-- UPDATE $tabname\n"; - while (@row = $result->fetchrow) - { - for ($i = 0; $i <= $#row; $i++) - { - printf $outf " " if $i; - printf $outf "%s", OutputValue($row[$i]); - } - printf $outf "\n"; - } - printf $outf "\\.\n"; - } - - unless ($havedeal) - { - $conn->exec("ROLLBACK"); - return(0); - } - - # Remember this snapshot info - $result = $conn->exec("select _rserv_sync_($server)"); - if ($result->resultStatus ne PGRES_TUPLES_OK) - { - printf $outf "-- ERROR\n"; - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - - $result = $conn->exec("COMMIT"); - if ($result->resultStatus ne PGRES_COMMAND_OK) - { - printf $outf "-- ERROR\n"; - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - printf $outf "-- OK\n"; - - return(1); - -} - -sub OutputValue -{ - my ($val) = @_; # @_[0]; - - return("\\N") unless defined $val; - - $val =~ s/\\/\\\\/g; - $val =~ s/ /\\011/g; - $val =~ s/\n/\\012/g; - $val =~ s/\'/\\047/g; - - return($val); -} - -# Get syncid for new snapshot -sub GetSYNCID -{ - my ($conn, $outf) = @_; # (@_[0], @_[1]); - - my $result = $conn->exec("select nextval('_rserv_sync_seq_')"); - if ($result->resultStatus ne PGRES_TUPLES_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - - my @row = $result->fetchrow; - - printf $outf "-- SYNCID $row[0]\n"; - return($row[0]); -} - - -sub CleanLog -{ - my ($conn, $howold) = @_; # (@_[0], @_[1]); - - my $result = $conn->exec("BEGIN"); - if ($result->resultStatus ne PGRES_COMMAND_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - - my $sql = "select rs.maxid, rs.active from _RSERV_SYNC_ rs" . - " where rs.syncid = (select max(rs2.syncid) from _RSERV_SYNC_ rs2" . - " where rs2.server = rs.server and rs2.status > 0) order by rs.maxid"; - - printf "$sql\n" if $debug; - - $result = $conn->exec($sql); - if ($result->resultStatus ne PGRES_TUPLES_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - return(-1); - } - my $maxid = ''; - my %active = (); - while (my @row = $result->fetchrow) - { - $maxid = $row[0] if $maxid eq ''; - last if $row[0] > $maxid; - my @ids = split(/[ ]+,[ ]+/, $row[1]); - foreach $aid (@ids) - { - $active{$aid} = 1 unless exists $active{$aid}; - } - } - if ($maxid eq '') - { - print STDERR "No Sync IDs\n" unless ($quiet); - return(0); - } - my $alist = join(',', keys %active); - my $sinfo = "logid < $maxid"; - $sinfo .= " and logid not in ($alist)" if $alist ne ''; - - $sql = "delete from _RSERV_LOG_ where " . - "logtime < now() - '$howold second'::interval and $sinfo"; - - printf "$sql\n" if $debug; - - $result = $conn->exec($sql); - if ($result->resultStatus ne PGRES_COMMAND_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - $maxid = $result->cmdTuples; - - $result = $conn->exec("COMMIT"); - if ($result->resultStatus ne PGRES_COMMAND_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - - return($maxid); -} - -sub ApplySnapshot -{ - my ($conn, $inpf) = @_; # (@_[0], @_[1]); - - my $result = $conn->exec("BEGIN"); - if ($result->resultStatus ne PGRES_COMMAND_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - - $result = $conn->exec("SET CONSTRAINTS ALL DEFERRED"); - if ($result->resultStatus ne PGRES_COMMAND_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - - # MAP name --> oid, keyname, keynum - my $sql = "select pgc.oid, pgc.relname, pga.attname, rt.key" . - " from _RSERV_SLAVE_TABLES_ rt, pg_class pgc, pg_attribute pga" . - " where pgc.oid = rt.reloid and pga.attrelid = rt.reloid" . - " and pga.attnum = rt.key"; - $result = $conn->exec($sql); - if ($result->resultStatus ne PGRES_TUPLES_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - - while (@row = $result->fetchrow) - { - # printf " %s %s\n", $row[1], $row[0]; - push @{$Stables{$row[1]}}, $row[0], $row[2], $row[3]; - } - - my $ok = 0; - my $syncid = ''; - while(<$inpf>) - { - $_ =~ s/\n//; - my ($cmt, $cmd, $prm) = split (/[ ]+/, $_, 3); - if ($cmt ne '--') - { - printf STDERR "Invalid format\n" unless ($quiet); - $conn->exec("ROLLBACK"); - return(-2); - } - if ($cmd eq 'DELETE') - { - if ($syncid eq '') - { - printf STDERR "Sync ID unspecified\n" unless ($quiet); - $conn->exec("ROLLBACK"); - return(-2); - } - $result = DoDelete($conn, $inpf, $prm); - if ($result) - { - $conn->exec("ROLLBACK"); - return($result); - } - } - elsif ($cmd eq 'UPDATE') - { - if ($syncid eq '') - { - printf STDERR "Sync ID unspecified\n" unless ($quiet); - $conn->exec("ROLLBACK"); - return(-2); - } - $result = DoUpdate($conn, $inpf, $prm); - if ($result) - { - $conn->exec("ROLLBACK"); - return($result); - } - } - elsif ($cmd eq 'SYNCID') - { - if ($syncid ne '') - { - printf STDERR "Second Sync ID ?!\n" unless ($quiet); - $conn->exec("ROLLBACK"); - return(-2); - } - if ($prm !~ /^\d+$/) - { - printf STDERR "Invalid Sync ID $prm\n" unless ($quiet); - $conn->exec("ROLLBACK"); - return(-2); - } - $syncid = $prm; - - printf STDERR "Sync ID $syncid\n" unless ($quiet); - - $result = $conn->exec("select syncid, synctime from " . - "_RSERV_SLAVE_SYNC_ where syncid = " . - "(select max(syncid) from _RSERV_SLAVE_SYNC_)"); - if ($result->resultStatus ne PGRES_TUPLES_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - my @row = $result->fetchrow; - if (! defined $row[0]) - { - $result = $conn->exec("insert into" . - " _RSERV_SLAVE_SYNC_(syncid, synctime) values ($syncid, now())"); - } - elsif ($row[0] >= $prm) - { - printf STDERR "Sync-ed to ID $row[0] ($row[1])\n" unless ($quiet); - $conn->exec("ROLLBACK"); - return(0); - } - else - { - $result = $conn->exec("update _RSERV_SLAVE_SYNC_" . - " set syncid = $syncid, synctime = now()"); - } - if ($result->resultStatus ne PGRES_COMMAND_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - } - elsif ($cmd eq 'OK') - { - $ok = 1; - last; - } - elsif ($cmd eq 'ERROR') - { - printf STDERR "ERROR signaled\n" unless ($quiet); - $conn->exec("ROLLBACK"); - return(-2); - } - else - { - printf STDERR "Unknown command $cmd\n" unless ($quiet); - $conn->exec("ROLLBACK"); - return(-2); - } - } - - if (! $ok) - { - printf STDERR "No OK flag in input\n" unless ($quiet); - $conn->exec("ROLLBACK"); - return(-2); - } - - $result = $conn->exec("COMMIT"); - if ($result->resultStatus ne PGRES_COMMAND_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - - return(1); -} - -sub DoDelete -{ - my ($conn, $inpf, $tabname) = @_; # (@_[0], @_[1], @_[2]); - - my $ok = 0; - while(<$inpf>) - { - if ($_ !~ /\n$/) - { - printf STDERR "Invalid format\n" unless ($quiet); - return(-2); - } - my $key = $_; - $key =~ s/\n//; - if ($key eq '\.') - { - $ok = 1; - last; - } - - my $sql = "delete from $tabname where $Stables{$tabname}->[1] = '$key'"; - - printf "$sql\n" if $debug; - - my $result = $conn->exec($sql); - if ($result->resultStatus ne PGRES_COMMAND_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - return(-1); - } - } - - if (! $ok) - { - printf STDERR "No end of input in DELETE section\n" unless ($quiet); - return(-2); - } - - return(0); -} - - -sub DoUpdate -{ - my ($conn, $inpf, $tabname) = @_; # (@_[0], @_[1], @_[2]); - my $oidkey = ($Stables{$tabname}->[2] < 0) ? 1 : 0; - - my @CopyBuf = (); - my $CBufLen = 0; - my $CBufMax = 16 * 1024 * 1024; # max size of buf for copy - - my $sql = "select attnum, attname from pg_attribute" . - " where attrelid = $Stables{$tabname}->[0] and attnum > 0"; - - my $result = $conn->exec($sql); - if ($result->resultStatus ne PGRES_TUPLES_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - return(-1); - } - - my @anames = (); - while (@row = $result->fetchrow) - { - $anames[$row[0]] = $row[1]; - } - - my $istring; - my $ok = 0; - while(<$inpf>) - { - if ($_ !~ /\n$/) - { - printf STDERR "Invalid format\n" unless ($quiet); - return(-2); - } - $istring = $_; - $istring =~ s/\n//; - if ($istring eq '\.') - { - $ok = 1; - last; - } - my @vals = split(/ /, $istring); - if ($oidkey) - { - if ($vals[0] !~ /^\d+$/ || $vals[0] <= 0) - { - printf STDERR "Invalid OID\n" unless ($quiet); - return(-2); - } - $oidkey = $vals[0]; - } - else - { - unshift @vals, ''; - } - - $sql = "update $tabname set "; - my $ocnt = 0; - for (my $i = 1; $i <= $#anames; $i++) - { - if ($vals[$i] eq '\N') - { - if ($i == $Stables{$tabname}->[2]) - { - printf STDERR "NULL key\n" unless ($quiet); - return(-2); - } - $vals[$i] = 'null'; - } - else - { - $vals[$i] = "'" . $vals[$i] . "'"; - next if $i == $Stables{$tabname}->[2]; - } - $ocnt++; - $sql .= ', ' if $ocnt > 1; - $sql .= "$anames[$i] = $vals[$i]"; - } - if ($oidkey) - { - $sql .= " where $Stables{$tabname}->[1] = $oidkey"; - } - else - { - $sql .= " where $Stables{$tabname}->[1] = $vals[$Stables{$tabname}->[2]]"; - } - - printf "$sql\n" if $debug; - - $result = $conn->exec($sql); - if ($result->resultStatus ne PGRES_COMMAND_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - return(-1); - } - next if $result->cmdTuples == 1; # updated - - if ($result->cmdTuples > 1) - { - printf STDERR "Duplicate keys\n" unless ($quiet); - return(-2); - } - - # no key - copy - push @CopyBuf, "$istring\n"; - $CBufLen += length($istring); - - if ($CBufLen >= $CBufMax) - { - $result = DoCopy($conn, $tabname, $oidkey, \@CopyBuf); - return($result) if $result; - @CopyBuf = (); - $CBufLen = 0; - } - } - - if (! $ok) - { - printf STDERR "No end of input in UPDATE section\n" unless ($quiet); - return(-2); - } - - if ($CBufLen) - { - $result = DoCopy($conn, $tabname, $oidkey, \@CopyBuf); - return($result) if $result; - } - - return(0); -} - - -sub DoCopy -{ - my ($conn, $tabname, $withoids, $CBuf) = @_; # (@_[0], @_[1], @_[2], @_[3]); - - my $sql = "COPY $tabname " . (($withoids) ? "WITH OIDS " : '') . -"FROM STDIN"; - my $result = $conn->exec($sql); - if ($result->resultStatus ne PGRES_COPY_IN) - { - print STDERR $conn->errorMessage unless ($quiet); - return(-1); - } - - foreach $str (@{$CBuf}) - { - $conn->putline($str); - } - - $conn->putline("\\.\n"); - - if ($conn->endcopy) - { - print STDERR $conn->errorMessage unless ($quiet); - return(-1); - } - - return(0); - -} - - -# -# Returns last SyncID applied on Slave -# -sub GetSyncID -{ - my ($conn) = @_; # (@_[0]); - - my $result = $conn->exec("select max(syncid) from _RSERV_SLAVE_SYNC_"); - if ($result->resultStatus ne PGRES_TUPLES_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - return(-1); - } - my @row = $result->fetchrow; - return(undef) unless defined $row[0]; # null - return($row[0]); -} - -# -# Updates _RSERV_SYNC_ on Master with Slave SyncID -# -sub SyncSyncID -{ - my ($conn, $server, $syncid) = @_; # (@_[0], @_[1], @_[2]); - - my $result = $conn->exec("BEGIN"); - if ($result->resultStatus ne PGRES_COMMAND_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - - $result = $conn->exec("select synctime, status from _RSERV_SYNC_" . - " where server = $server and syncid = $syncid" . - " for update"); - if ($result->resultStatus ne PGRES_TUPLES_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - my @row = $result->fetchrow; - if (! defined $row[0]) - { - printf STDERR "No SyncID $syncid found for server $server\n" unless ($quiet); - $conn->exec("ROLLBACK"); - return(0); - } - if ($row[1] > 0) - { - printf STDERR "SyncID $syncid for server $server already updated\n" unless ($quiet); - $conn->exec("ROLLBACK"); - return(0); - } - $result = $conn->exec("update _RSERV_SYNC_" . - " set synctime = now(), status = 1" . - " where server = $server and syncid = $syncid"); - if ($result->resultStatus ne PGRES_COMMAND_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - $result = $conn->exec("delete from _RSERV_SYNC_" . - " where server = $server and syncid < $syncid"); - if ($result->resultStatus ne PGRES_COMMAND_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - - $result = $conn->exec("COMMIT"); - if ($result->resultStatus ne PGRES_COMMAND_OK) - { - print STDERR $conn->errorMessage unless ($quiet); - $conn->exec("ROLLBACK"); - return(-1); - } - - return(1); -} - -1; diff --git a/contrib/rserv/Replicate.in b/contrib/rserv/Replicate.in deleted file mode 100644 index 7ad48434a8..0000000000 --- a/contrib/rserv/Replicate.in +++ /dev/null @@ -1,102 +0,0 @@ -# -*- perl -*- -## Replicate -# Vadim Mikheev, (c) 2000, PostgreSQL Inc. - -eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' - & eval 'exec perl -S $0 $argv:q' - if 0; - -use lib "@LIBDIR@"; - -use IO::File; -use Getopt::Long; -use RServ; - -$| = 1; - -$result = GetOptions("debug!", "verbose!", "help", "snapshot=s", - "masterhost=s", "slavehost=s", "host=s", - "masteruser=s", "slaveuser=s", "user=s", - "masterpassword=s", "slavepassword=s", "password=s"); - -my $debug = $opt_debug || 0; -my $verbose = $opt_verbose || 0; -my $snapshot = $opt_snapshot || "__Snapshot"; - -if (defined($opt_help) || (scalar(@ARGV) < 2)) { - print "Usage: $0 --snapshot=file --host=name --user=name --password=string masterdb slavedb\n"; - print "\t--masterhost=name --masteruser=name --masterpassword=string\n"; - print "\t--slavehost=name --slaveuser=name --slavepassword=string\n"; - exit ((scalar(@ARGV) < 2)? 1:0); -} - -my $master = $ARGV[0] || "master"; -my $slave = $ARGV[1] || "slave"; -my $server = 0; - -my $minfo = "dbname=$master"; -$minfo = "$minfo host=$opt_masterhost" if (defined($opt_masterhost)); -$minfo = "$minfo user=$opt_masteruser" if (defined($opt_masteruser)); -$minfo = "$minfo password=$opt_masterpassword" if (defined($opt_masterpassword)); -my $sinfo = "dbname=$slave"; -$sinfo = "$sinfo host=$opt_slavehost" if (defined($opt_slavehost)); -$sinfo = "$sinfo user=$opt_slaveuser" if (defined($opt_slaveuser)); -$sinfo = "$sinfo password=$opt_slavepassword" if (defined($opt_slavepassword)); - -print "Master connection is $minfo\n" if ($debug); -print "Slave connection is $sinfo\n" if ($debug); - -my $mconn = Pg::connectdb($minfo); -my $sconn = Pg::connectdb($sinfo); - -$RServ::quiet = !$verbose; - -SyncSync($mconn, $sconn); - -my $outf = new IO::File; -open $outf, ">$snapshot"; -print "\n>>>>>>>>>>>>> Prepare Snapshot\n\n" if ($verbose); -$res = PrepareSnapshot($mconn, $outf, $server); -close $outf; -die "\n>>>>>>>>>>>>> ERROR\n" if $res < 0; -if ($res == 0) -{ - print "\n>>>>>>>>>>>>> DBases are sync-ed\n" if ($verbose); - exit(0); -} - -my $inpf = new IO::File; -open $inpf, "<$snapshot"; -print "\n>>>>>>>>>>>>> Apply Snapshot\n\n" if ($verbose); -$res = ApplySnapshot($sconn, $inpf); -close $inpf; -die "\n>>>>>>>>>>>>> ERROR\n" if $res < 0; - -if ($res > 0) -{ - print "Snapshot applied\n" if ($verbose); - unlink $snapshot unless ($debug); - SyncSync($mconn, $sconn); -} - -exit(0); - -########################################################################### - -sub SyncSync -{ - ($mconn, $sconn) = @_; - - print "\n>>>>>>>>>>>>> Sync SyncID\n\n" if ($verbose); - print "Get last SyncID from Slave DB\n" if ($verbose); - $syncid = GetSyncID($sconn); - if ($syncid > 0) - { - print "Last SyncID applied: $syncid\n" if ($verbose); - print "Sync SyncID\n" if ($verbose); - - $res = SyncSyncID($mconn, $server, $syncid); - - print "Succeeded\n" if (($res > 0) && ($verbose)); - } -} diff --git a/contrib/rserv/RservTest.in b/contrib/rserv/RservTest.in deleted file mode 100644 index d3840d5994..0000000000 --- a/contrib/rserv/RservTest.in +++ /dev/null @@ -1,313 +0,0 @@ -#!/bin/sh -## pgserv.tcl -# (c) 2000 Thomas Lockhart, PostgreSQL Inc. -# The next line will reinvoke as wish *DO NOT REMOVE OR ALTER* \ -exec wish "$0" "$@" - -puts "Starting Replication Server demo" - -set RSERV_BIN "@BINDIR@" - -# Bring in the interfaces we will be using... - -#package require Pgtcl -load libpgtcl[info sharedlibextension] - -# elog -# Information or error log and exit handler -proc {elog} {level message} { - global show - switch -exact -- $level { - DEBUG { - if {$show(debug)} { - puts "DEBUG $message" - } - } - ERROR { - if {$show(error)} { - puts "ERROR $message" - } - FATAL { - if ($show(error)} { - puts "FATAL $message" - } - exit 1 - } - default { - puts "INFO $message" - } - } -} - -proc {ShowUsage} {} { - global argv0 - puts "Usage: $argv0 --host name --user name --password string masterdb slavedb" - puts "\t--masterhost name --masteruser name --masterpassword string" - puts "\t--slavehost name --slaveuser name --slavepassword string" -} - -# Initial values for database access -# master, slave variables are tied to text input boxes, -# and will be updated on user input -proc {SetDbInfo} {db name {host ""} {user ""} {pass ""}} { - global dbinfo - set dbinfo($db,name) $name - set dbinfo($db,host) $host - set dbinfo($db,user) $user - set dbinfo($db,pass) $pass -} - -# ConnInfo -# Connection information for pgtcl library -proc {ConnInfo} {{db master}} { - global dbinfo - set ci "dbname=$dbinfo($db,name)" - if {[string length $dbinfo($db,host)] > 0} { - set ci "$ci host=$dbinfo($db,host)" - } - if {[string length $dbinfo($db,user)] > 0} { - set ci "$ci user=$dbinfo($db,user)" - } - if {[string length $dbinfo($db,pass)] > 0} { - set ci "$ci password=$dbinfo($db,pass)" - } -# puts "Construct conninfo $ci" - return $ci -} - -# ConnInfoParams -# Connection information for (perl) callable programs -proc {ConnInfoParams} {{db master}} { - global dbinfo - set ci "" - if {[string length $dbinfo($db,host)] > 0} { - set ci "$ci --host=$dbinfo($db,host)" - } - if {[string length $dbinfo($db,user)] > 0} { - set ci "$ci --user=$dbinfo($db,user)" - } - if {[string length $dbinfo($db,pass)] > 0} { - set ci "$ci --password=$dbinfo($db,pass)" - } -# puts "Construct conninfo $ci" - return $ci -} - -# ConnInfoMaster -# Connection information for (perl) callable programs -proc {ConnInfoMaster} {{db master}} { - global dbinfo - set ci $dbinfo($db,name) - if {[string length $dbinfo($db,host)] > 0} { - set ci "$ci --masterhost=$dbinfo($db,host)" - } - if {[string length $dbinfo($db,user)] > 0} { - set ci "$ci --masteruser=$dbinfo($db,user)" - } - if {[string length $dbinfo($db,pass)] > 0} { - set ci "$ci --masterpassword=$dbinfo($db,pass)" - } -# puts "Construct conninfo $ci" - return $ci -} - -# ConnInfoSlave -# Connection information for (perl) callable programs -proc {ConnInfoSlave} {{db slave}} { - global dbinfo - set ci $dbinfo($db,name) - if {[string length $dbinfo($db,host)] > 0} { - set ci "$ci --slavehost=$dbinfo($db,host)" - } - if {[string length $dbinfo($db,user)] > 0} { - set ci "$ci --slaveuser=$dbinfo($db,user)" - } - if {[string length $dbinfo($db,pass)] > 0} { - set ci "$ci --slavepassword=$dbinfo($db,pass)" - } -# puts "Construct conninfo $ci" - return $ci -} - - -SetDbInfo master master localhost -SetDbInfo slave slave localhost -set dbinfo(snapshot,name) "__Snapshot" - -set update "" - -set show(debug) 1 -set show(error) 1 - -set argi 0 -while {$argi < $argc} { -# puts "argi is $argi; argc is $argc" - set arg [lindex $argv $argi] - switch -glob -- $arg { - -h - - --host { - incr argi - set dbinfo(master,host) [lindex $argv $argi] - set dbinfo(slave,host) [lindex $argv $argi] - } - --masterhost { - incr argi - set dbinfo(master,host) [lindex $argv $argi] - } - --slavehost { - incr argi - set dbinfo(slave,host) [lindex $argv $argi] - } - -u - - --user { - incr argi - set dbinfo(master,user) [lindex $argv $argi] - set dbinfo(slave,user) [lindex $argv $argi] - } - --masteruser { - incr argi - set dbinfo(master,user) [lindex $argv $argi] - } - --slaveuser { - incr argi - set dbinfo(slave,user) [lindex $argv $argi] - } - -s - - --snapshot { - incr argi - set dbinfo(snapshot,name) [lindex $argv $argi] - } - -* { - elog ERROR "$argv0: invalid parameter '$arg'" - ShowUsage - exit 1 - } - default { - break - } - } - incr argi -} - -if {$argi < $argc} { - set dbinfo(master,name) [lindex $argv $argi] - incr argi -} -if {$argi < $argc} { - set dbinfo(slave,name) [lindex $argv $argi] - incr argi -} -if {$argi < $argc} { - elog "$argv0: too many parameters" - ShowUsage - exit 1 -} - -elog DEBUG "User is $dbinfo(master,user) $dbinfo(slave,user)" -elog DEBUG "Host is $dbinfo(master,host) $dbinfo(slave,host)" - -# -# TK layout -# - -wm title . "Async Replication" - -wm geom . 400x400 - -proc {CreateResultFrame} {b l w} { - pack [frame $b -borderwidth 10] -fill x - pack [button $b.run -text $l -command $l -width $w] -side left -# pack [entry $b.e -textvariable NewRow] -side left -} - -set t .top -pack [frame $t -borderwidth 10] -fill x -pack [frame $t.h -borderwidth 10] -fill x -pack [label $t.h.h -text "PostgreSQL Async Replication Server"] - -set b .b -pack [frame $b -borderwidth 10] -fill x -pack [frame $b.l -borderwidth 10] -fill x -pack [label $b.l.ml -text "Master"] -side left -pack [label $b.l.sl -text "Slave"] -side right -pack [entry $b.m -textvariable dbinfo(master,name) -width 25] -side left -pack [entry $b.s -textvariable dbinfo(slave,name) -width 25] -side right - -set b .u -pack [frame $b -borderwidth 10] -fill x -pack [button $b.run -text update -command Update -width 10] -side left -pack [entry $b.e -textvariable update -width 50] -side left - -set r [CreateResultFrame .r Replicate 10] - -set b .s -pack [frame $b -borderwidth 10] -fill x -pack [button $b.b -text Show -command Show -width 10] -side left -pack [label $b.e -text ""] -side left - -set b .button -pack [frame $b -borderwidth 10] -fill x - -pack [button $b.quit -text "Quit" -command Shutdown] - -# -# Functions mapped to buttons -# - -proc {Update} {} { - global dbinfo - global update - - elog DEBUG "Opening database [ConnInfo master]..." - set res [catch {set db [pg_connect -conninfo "[ConnInfo master]"]} msg] - if {$res} { - elog ERROR "Database '$dbinfo(master,name)' is not available: $res ($msg)" - } else { - elog DEBUG "Insert $update into database $dbinfo(master,name)..." - set res [pg_exec $db "insert into test select '$update', max(k)+1, max(l)+1 from test"] - elog DEBUG [pg_result $res -status] - catch {pg_disconnect $db} - } -} - -proc {Replicate} {} { - global dbinfo - global RSERV_BIN - - elog DEBUG "Replicating [ConnInfoCmd master]..." - exec "$RSERV_BIN/Replicate" --snapshot=$dbinfo(snapshot,name) [ConnInfoParams] [ConnInfoMaster] [ConnInfoSlave] -} - -proc {Show} {} { - global dbinfo - global update - - elog DEBUG "Opening database [ConnInfo slave]..." - set res [catch {set db [pg_connect -conninfo "[ConnInfo slave]"]} msg] - if {$res} { - elog ERROR "DB $dbinfo(slave,name) not available: $res ($msg)" - } else { - elog DEBUG "Select $update from database $dbinfo(slave,name)..." - set res [pg_exec $db "select i from test where i='$update'"] - if {[pg_result $res -status] != "PGRES_TUPLES_OK"} { - .s.e config -text "n/a" - } else { - set ntups [pg_result $res -numTuples] - if {$ntups <= 0} { - .s.e config -text "n/a" - } else { - for {set i 0} {$i < $ntups} {incr i} { - set val [pg_result $res -getTuple $i] - .s.e config -text $val - } - } - pg_result $res -clear - } - catch {pg_disconnect $db} - } -} - -proc {Shutdown} {} { - global dbinfo - exit -} diff --git a/contrib/rserv/SlaveAddTable.in b/contrib/rserv/SlaveAddTable.in deleted file mode 100644 index 4f1c8b91ab..0000000000 --- a/contrib/rserv/SlaveAddTable.in +++ /dev/null @@ -1,59 +0,0 @@ -# -*- perl -*- -## SlaveAddTable -# Vadim Mikheev, (c) 2000, PostgreSQL Inc. - -eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' - & eval 'exec perl -S $0 $argv:q' - if 0; - -use Pg; -use Getopt::Long; - -$| = 1; - -$result = GetOptions("debug!", "verbose!", "help", - "host=s", "user=s", "password=s"); - -my $debug = $opt_debug || 0; -my $verbose = $opt_verbose || 0; - -if (defined($opt_help) || (scalar(@ARGV) < 3)) { - print "Usage: $0 --host=name --user=name --password=string slavedb table column\n"; - exit ((scalar(@ARGV) < 3)? 1: 0); -} - -my $dbname = $ARGV[0]; -my $table = $ARGV[1]; -my $keyname = $ARGV[2]; - -my $sinfo = "dbname=$dbname"; -$sinfo = "$sinfo host=$opt_host" if (defined($opt_host)); -$sinfo = "$sinfo user=$opt_user" if (defined($opt_user)); -$sinfo = "$sinfo password=$opt_password" if (defined($opt_password)); - -my $dbname = $ARGV[0]; -my $table = $ARGV[1]; -my $keyname = $ARGV[2]; - -my $conn = Pg::connectdb($sinfo); - -my $result = $conn->exec("BEGIN"); -die $conn->errorMessage if $result->resultStatus ne PGRES_COMMAND_OK; - -$result = $conn->exec("select pgc.oid, pga.attnum from pg_class pgc" . - ", pg_attribute pga" . - " where pgc.relname = '$table' and pgc.oid = pga.attrelid" . - " and pga.attname = '$keyname'"); -die $conn->errorMessage if $result->resultStatus ne PGRES_TUPLES_OK; - -my @row = $result->fetchrow; -die "Can't find table/key\n" if ! defined $row[0] || ! defined $row[1]; - -$result = $conn->exec("insert into _RSERV_SLAVE_TABLES_ (tname, cname, reloid, key)" . - " values ('$table', '$keyname', $row[0], $row[1])"); -die $conn->errorMessage if $result->resultStatus ne PGRES_COMMAND_OK; - -$result = $conn->exec("COMMIT"); -die $conn->errorMessage if $result->resultStatus ne PGRES_COMMAND_OK; - -exit(0); diff --git a/contrib/rserv/SlaveInit.in b/contrib/rserv/SlaveInit.in deleted file mode 100644 index d4b145dd8a..0000000000 --- a/contrib/rserv/SlaveInit.in +++ /dev/null @@ -1,65 +0,0 @@ -# -*- perl -*- -## SlaveInit -# Vadim Mikheev, (c) 2000, PostgreSQL Inc. - -eval '(exit $?0)' && eval 'exec perl -S $0 ${1+"$@"}' - & eval 'exec perl -S $0 $argv:q' - if 0; - -use Pg; -use Getopt::Long; - -$| = 1; - -$result = GetOptions("debug!", "verbose!", "quiet!", "help", - "host=s", "user=s", "password=s"); - -my $debug = $opt_debug || 0; -my $verbose = $opt_verbose || 0; -my $quiet = $opt_quiet || 0; - -if (defined($opt_help) || (scalar(@ARGV) < 1)) { - print "Usage: $0 --host=name --user=name --password=string slavedb\n"; - exit ((scalar(@ARGV) < 1)? 1:0); -} - -my $slave = $ARGV[0] || "slave"; - -my $sinfo = "dbname=$slave"; -$sinfo = "$sinfo host=$opt_host" if (defined($opt_host)); -$sinfo = "$sinfo user=$opt_user" if (defined($opt_user)); -$sinfo = "$sinfo password=$opt_password" if (defined($opt_password)); - -sub RollbackAndQuit { - my $conn = shift @_; - - print STDERR $conn->errorMessage; - $conn->exec("ROLLBACK"); - exit (-1); -} - -print("Connecting to $sinfo\n") if ($debug || $verbose); -my $conn = Pg::connectdb($sinfo); -if ($conn->status != PGRES_CONNECTION_OK) { - print STDERR "Failed opening $sinfo\n"; - exit 1; -} - -my $result = $conn->exec("BEGIN"); -RollbackAndQuit($conn) if ($result->resultStatus ne PGRES_COMMAND_OK); - -$result = $conn->exec("set transaction isolation level serializable"); -RollbackAndQuit($conn) if ($result->resultStatus ne PGRES_COMMAND_OK); - -$result = $conn->exec("create table _RSERV_SLAVE_TABLES_" . - " (tname name, cname name, reloid oid, key int4)"); -RollbackAndQuit($conn) if ($result->resultStatus ne PGRES_COMMAND_OK); - -$result = $conn->exec("create table _RSERV_SLAVE_SYNC_" . - " (syncid int4, synctime timestamp)"); -RollbackAndQuit($conn) if ($result->resultStatus ne PGRES_COMMAND_OK); - -$result = $conn->exec("COMMIT"); -RollbackAndQuit($conn) if ($result->resultStatus ne PGRES_COMMAND_OK); - -exit (0); diff --git a/contrib/rserv/master.sql.in b/contrib/rserv/master.sql.in deleted file mode 100644 index ed6d2045bc..0000000000 --- a/contrib/rserv/master.sql.in +++ /dev/null @@ -1,101 +0,0 @@ --- erServer --- Master server setup for erServer demonstration implementation --- (c) 2000 Vadim Mikheev, PostgreSQL Inc. --- - --- --- Slave servers --- -drop table _RSERV_SERVERS_; - -create table _RSERV_SERVERS_ -( - server int4, -- slave server id - host text, -- server' host - port int4, -- server' port - dbase text -- db name -); - - --- --- Tables to sync --- -drop table _RSERV_TABLES_; - -create table _RSERV_TABLES_ -( - tname name, -- table name - cname name, -- column name - reloid oid, -- table oid - key int4 -- key attnum -); - - --- --- Log for inserts/updates/deletes to sync-ed tables --- -drop table _RSERV_LOG_; - -create table _RSERV_LOG_ -( - reloid oid, - logid int4, -- xid of last update xaction - logtime timestamp, -- last update xaction start time - deleted int4, -- deleted or inserted/updated - key text -- -); - --- This is to speedup lookup deleted tuples -create index _RSERV_LOG_INDX_DLT_ID_ on _RSERV_LOG_ (deleted, logid); - --- This is to speedup cleanup -create index _RSERV_LOG_INDX_TM_ID_ on _RSERV_LOG_ (logtime, logid); - --- This is to speedup trigger and lookup updated tuples -create index _RSERV_LOG_INDX_REL_KEY_ on _RSERV_LOG_ (reloid, key); - - --- --- How much each slave servers are sync-ed --- -drop table _RSERV_SYNC_; - -create table _RSERV_SYNC_ -( - server int4, - syncid int4, -- from _rserv_sync_seq_ - synctime timestamp, -- - status int4, -- prepared (0) | applied - minid int4, -- min xid from serializable snapshot - maxid int4, -- max xid from serializable snapshot - active text -- list of active xactions -); - -create index _RSERV_SYNC_INDX_SRV_ID_ on _RSERV_SYNC_ (server, syncid); - -drop sequence _rserv_sync_seq_; -create sequence _rserv_sync_seq_; - -drop function _rserv_log_(); - -CREATE FUNCTION _rserv_log_() - RETURNS trigger - AS '@MODULE_FILENAME@' - LANGUAGE 'c' -; - -drop function _rserv_sync_(int4); - -CREATE FUNCTION _rserv_sync_(int4) - RETURNS int4 - AS '@MODULE_FILENAME@' - LANGUAGE 'c' -; - -drop function _rserv_debug_(int4); - -CREATE FUNCTION _rserv_debug_(int4) - RETURNS int4 - AS '@MODULE_FILENAME@' - LANGUAGE 'c' -; diff --git a/contrib/rserv/regress.sh b/contrib/rserv/regress.sh deleted file mode 100755 index 96ca481934..0000000000 --- a/contrib/rserv/regress.sh +++ /dev/null @@ -1,32 +0,0 @@ -# regress.sh -# rserv regression test script -# (c) 2000 Thomas Lockhart, PostgreSQL Inc. - -dropdb master -dropdb slave - -createdb master -createdb slave - -MasterInit master -SlaveInit slave - -psql -c "create table t1 (i int, t text, d timestamp default text 'now');" master -MasterAddTable master t1 d - -psql -c "create table t1 (i int, t text, d timestamp default text 'now');" slave -SlaveAddTable slave t1 d - -psql -c "insert into t1 values (1, 'one');" master -psql -c "insert into t1 values (2, 'two');" master - -Replicate master slave -MasterSync master `GetSyncID --noverbose slave` - -psql -c "insert into t1 values (3, 'three');" master -psql -c "insert into t1 values (4, 'four');" master - -Replicate master slave -MasterSync master `GetSyncID --noverbose slave` - -exit diff --git a/contrib/rserv/rserv.c b/contrib/rserv/rserv.c deleted file mode 100644 index 78f23bbb23..0000000000 --- a/contrib/rserv/rserv.c +++ /dev/null @@ -1,352 +0,0 @@ -/* rserv.c - * Support functions for erServer replication. - * (c) 2000 Vadim Mikheev, PostgreSQL Inc. - */ - -#include "executor/spi.h" /* this is what you need to work with SPI */ -#include "commands/trigger.h" /* -"- and triggers */ -#include "utils/tqual.h" /* -"- and SnapshotData */ -#include /* tolower () */ - -#ifdef PG_FUNCTION_INFO_V1 -#define CurrentTriggerData ((TriggerData *) fcinfo->context) -#endif - -#ifdef PG_FUNCTION_INFO_V1 -PG_FUNCTION_INFO_V1(_rserv_log_); -PG_FUNCTION_INFO_V1(_rserv_sync_); -PG_FUNCTION_INFO_V1(_rserv_debug_); -Datum _rserv_log_(PG_FUNCTION_ARGS); -Datum _rserv_sync_(PG_FUNCTION_ARGS); -Datum _rserv_debug_(PG_FUNCTION_ARGS); - -#else -HeapTuple _rserv_log_(void); -int32 _rserv_sync_(int32); -int32 _rserv_debug_(int32); -#endif - -static int debug = 0; - -static char *OutputValue(char *key, char *buf, int size); - -#ifdef PG_FUNCTION_INFO_V1 -Datum -_rserv_log_(PG_FUNCTION_ARGS) -#else -HeapTuple -_rserv_log_() -#endif -{ - Trigger *trigger; /* to get trigger name */ - int nargs; /* # of args specified in CREATE TRIGGER */ - char **args; /* argument: argnum */ - Relation rel; /* triggered relation */ - HeapTuple tuple; /* tuple to return */ - HeapTuple newtuple = NULL; /* tuple to return */ - TupleDesc tupdesc; /* tuple description */ - int keynum; - char *key; - char *okey; - char *newkey = NULL; - int deleted; - char sql[8192]; - char outbuf[8192]; - char oidbuf[64]; - int ret; - - /* Called by trigger manager ? */ - if (!CurrentTriggerData) - /* internal error */ - elog(ERROR, "_rserv_log_: triggers are not initialized"); - - /* Should be called for ROW trigger */ - if (TRIGGER_FIRED_FOR_STATEMENT(CurrentTriggerData->tg_event)) - /* internal error */ - elog(ERROR, "_rserv_log_: can't process STATEMENT events"); - - tuple = CurrentTriggerData->tg_trigtuple; - - trigger = CurrentTriggerData->tg_trigger; - nargs = trigger->tgnargs; - args = trigger->tgargs; - - if (nargs != 1) /* odd number of arguments! */ - /* internal error */ - elog(ERROR, "_rserv_log_: need in *one* argument"); - - keynum = atoi(args[0]); - - if (keynum < 0 && keynum != ObjectIdAttributeNumber) - /* internal error */ - elog(ERROR, "_rserv_log_: invalid keynum %d", keynum); - - rel = CurrentTriggerData->tg_relation; - tupdesc = rel->rd_att; - - deleted = (TRIGGER_FIRED_BY_DELETE(CurrentTriggerData->tg_event)) ? - 1 : 0; - - if (TRIGGER_FIRED_BY_UPDATE(CurrentTriggerData->tg_event)) - newtuple = CurrentTriggerData->tg_newtuple; - -#ifndef PG_FUNCTION_INFO_V1 - - /* - * Setting CurrentTriggerData to NULL prevents direct calls to trigger - * functions in queries. Normally, trigger functions have to be called - * by trigger manager code only. - */ - CurrentTriggerData = NULL; -#endif - - /* Connect to SPI manager */ - if ((ret = SPI_connect()) < 0) - /* internal error */ - elog(ERROR, "_rserv_log_: SPI_connect returned %d", ret); - - if (keynum == ObjectIdAttributeNumber) - { - snprintf(oidbuf, sizeof(oidbuf), "%u", HeapTupleGetOid(tuple)); - key = oidbuf; - } - else - key = SPI_getvalue(tuple, tupdesc, keynum); - - if (key == NULL) - ereport(ERROR, - (errcode(ERRCODE_NOT_NULL_VIOLATION), - errmsg("key must be not null"))); - - if (newtuple && keynum != ObjectIdAttributeNumber) - { - newkey = SPI_getvalue(newtuple, tupdesc, keynum); - if (newkey == NULL) - ereport(ERROR, - (errcode(ERRCODE_NOT_NULL_VIOLATION), - errmsg("key must be not null"))); - if (strcmp(newkey, key) == 0) - newkey = NULL; - else - deleted = 1; /* old key was deleted */ - } - - if (strpbrk(key, "\\ \n'")) - okey = OutputValue(key, outbuf, sizeof(outbuf)); - else - okey = key; - - snprintf(sql, 8192, "update _RSERV_LOG_ set logid = %d, logtime = now(), " - "deleted = %d where reloid = %u and key = '%s'", - GetCurrentTransactionId(), deleted, rel->rd_id, okey); - - if (debug) - elog(DEBUG4, "sql: %s", sql); - - ret = SPI_exec(sql, 0); - - if (ret < 0) - ereport(ERROR, - (errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION), - errmsg("SPI_exec(update) returned %d", ret))); - - /* - * If no tuple was UPDATEd then do INSERT... - */ - if (SPI_processed > 1) - ereport(ERROR, - (errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION), - errmsg("duplicate tuples"))); - - else if (SPI_processed == 0) - { - snprintf(sql, 8192, "insert into _RSERV_LOG_ " - "(reloid, logid, logtime, deleted, key) " - "values (%u, %d, now(), %d, '%s')", - rel->rd_id, GetCurrentTransactionId(), - deleted, okey); - - if (debug) - elog(DEBUG4, "sql: %s", sql); - - ret = SPI_exec(sql, 0); - - if (ret < 0) - ereport(ERROR, - (errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION), - errmsg("SPI_exec(insert) returned %d", ret))); - } - - if (okey != key && okey != outbuf) - pfree(okey); - - if (newkey) - { - if (strpbrk(newkey, "\\ \n'")) - okey = OutputValue(newkey, outbuf, sizeof(outbuf)); - else - okey = newkey; - - snprintf(sql, 8192, "insert into _RSERV_LOG_ " - "(reloid, logid, logtime, deleted, key) " - "values (%u, %d, now(), 0, '%s')", - rel->rd_id, GetCurrentTransactionId(), okey); - - if (debug) - elog(DEBUG4, "sql: %s", sql); - - ret = SPI_exec(sql, 0); - - if (ret < 0) - ereport(ERROR, - (errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION), - errmsg("SPI_exec returned %d", ret))); - - if (okey != newkey && okey != outbuf) - pfree(okey); - } - - SPI_finish(); - -#ifdef PG_FUNCTION_INFO_V1 - return (PointerGetDatum(tuple)); -#else - return (tuple); -#endif -} - -#ifdef PG_FUNCTION_INFO_V1 -Datum -_rserv_sync_(PG_FUNCTION_ARGS) -#else -int32 -_rserv_sync_(int32 server) -#endif -{ -#ifdef PG_FUNCTION_INFO_V1 - int32 server = PG_GETARG_INT32(0); -#endif - char sql[8192]; - char buf[8192]; - char *active = buf; - uint32 xcnt; - int ret; - - if (SerializableSnapshot == NULL) - /* internal error */ - elog(ERROR, "_rserv_sync_: SerializableSnapshot is NULL"); - - buf[0] = 0; - for (xcnt = 0; xcnt < SerializableSnapshot->xcnt; xcnt++) - { - snprintf(buf + strlen(buf), 8192 - strlen(buf), - "%s%u", (xcnt) ? ", " : "", - SerializableSnapshot->xip[xcnt]); - } - - if ((ret = SPI_connect()) < 0) - /* internal error */ - elog(ERROR, "_rserv_sync_: SPI_connect returned %d", ret); - - snprintf(sql, 8192, "insert into _RSERV_SYNC_ " - "(server, syncid, synctime, status, minid, maxid, active) " - "values (%u, currval('_rserv_sync_seq_'), now(), 0, %d, %d, '%s')", - server, SerializableSnapshot->xmin, SerializableSnapshot->xmax, active); - - ret = SPI_exec(sql, 0); - - if (ret < 0) - ereport(ERROR, - (errcode(ERRCODE_TRIGGERED_ACTION_EXCEPTION), - errmsg("SPI_exec returned %d", ret))); - - SPI_finish(); - - return (0); -} - -#ifdef PG_FUNCTION_INFO_V1 -Datum -_rserv_debug_(PG_FUNCTION_ARGS) -#else -int32 -_rserv_debug_(int32 newval) -#endif -{ -#ifdef PG_FUNCTION_INFO_V1 - int32 newval = PG_GETARG_INT32(0); -#endif - int32 oldval = debug; - - debug = newval; - - return (oldval); -} - -#define ExtendBy 1024 - -static char * -OutputValue(char *key, char *buf, int size) -{ - int i = 0; - char *out = buf; - char *subst = NULL; - int slen = 0; - - size--; - for (;;) - { - switch (*key) - { - case '\\': - subst = "\\\\"; - slen = 2; - break; - case ' ': - subst = "\\011"; - slen = 4; - break; - case '\n': - subst = "\\012"; - slen = 4; - break; - case '\'': - subst = "\\047"; - slen = 4; - break; - case '\0': - out[i] = 0; - return (out); - default: - slen = 1; - break; - } - - if (i + slen >= size) - { - if (out == buf) - { - out = (char *) palloc(size + ExtendBy); - strncpy(out, buf, i); - size += ExtendBy; - } - else - { - out = (char *) repalloc(out, size + ExtendBy); - size += ExtendBy; - } - } - - if (slen == 1) - out[i++] = *key; - else - { - memcpy(out + i, subst, slen); - i += slen; - } - key++; - } - - return (out); - -} diff --git a/contrib/rserv/slave.sql.in b/contrib/rserv/slave.sql.in deleted file mode 100644 index 93ac5caced..0000000000 --- a/contrib/rserv/slave.sql.in +++ /dev/null @@ -1,22 +0,0 @@ --- erServer --- Slave server setup for erServer demonstration implementation --- (c) 2000 Vadim Mikheev, PostgreSQL Inc. --- - -drop table _RSERV_SLAVE_TABLES_; - -create table _RSERV_SLAVE_TABLES_ -( - tname name, -- table name - cname name, -- column name - reloid oid, -- table oid - key int4 -- key attnum -); - -drop table _RSERV_SLAVE_SYNC_; - -create table _RSERV_SLAVE_SYNC_ -( - syncid int4, - synctime timestamp -);