Index: README =================================================================== RCS file: /home/dpavlin/private/cvsroot/rserv/README,v retrieving revision 1.8 diff -u -w -r1.8 README --- README 29 Oct 2003 18:00:15 -0000 1.8 +++ README 3 Nov 2003 21:27:45 -0000 @@ -8,14 +8,14 @@ distribution. Originally written by Vadim Mikheev from PostgreSQL Inc., it also include -changes made by Nélio Alves Pereira Filho and Dobrica Pavlinusic and -contributions from Grant McLean and Michael A Nachbaur. +changes made by Nélio Alves Pereira Filho, Grant McLean, Michael A Nachbaur +and Dobrica Pavlinusic. -Main goals are secure remote replication using ssh, ease of installation and -documentation. We aim to create stable and easy to use replication until -PGReplication is included in official PostgreSQL. However, it's not planned -to discontinue project at that time. You will just have choice of two -replication mechanisms. +Main goals are multi-master capabilities, secure remote replication using +ssh, ease of installation and documentation. We aim to create stable and +easy to use replication until PGReplication is included in official +PostgreSQL. However, it's not planned to discontinue project at that time. +You will just have choice of two replication mechanisms. This project is released under the Berkeley/BSD license. @@ -29,13 +29,17 @@ doc/README.rserv original README for RServ 0.1 doc/eRserver.ChangeLog non-english ChangeLog from Nélio doc/eRserver.HOWTO not quite accurate HOWTO from Sekar Gopi +doc/ErServer_internals.txt explanation of ErServer 1.2 internals doc/rserv-design.txt design notes for version 0.3 -doc/rserv-explained.pod explanation of RServ working (use perldoc to view) +doc/rserv-explained.pod explanation of RServ 0.3 working (use perldoc to view) lib/ contains C source code for rserv.so used by trigger in RServ misc/master.sql database schema of RServ specific part in master database with comments -misc/regress.sh original regress script +misc/regress.sh original regress script for master->slave replication +regress-2s.sh regress script for master->slave1, master->slave2 +regress-casc.sh regress script for master->slave1, slave1->slave2 +regress-mm.sh regress for multi-master master<->slave replication misc/slave.sql database schema for slave (changed) misc/rserv_test.pl bulk inserter for populating database misc/rep-demo.sql test database for regression test @@ -50,5 +54,5 @@ be fed to psql on slave to transform the structure and data from master to slave. It can be used to make regression testing of RServ replication (that's why I -originally written it). +originally wrote it). Index: bin/MultiMasterInit =================================================================== RCS file: /home/dpavlin/private/cvsroot/rserv/bin/MultiMasterInit,v retrieving revision 1.2 diff -u -w -r1.2 MultiMasterInit --- bin/MultiMasterInit 2 Nov 2003 10:21:45 -0000 1.2 +++ bin/MultiMasterInit 3 Nov 2003 17:12:03 -0000 @@ -173,6 +173,9 @@ Exec2($mconn,$sconn,"CREATE FUNCTION _rserv_debug_(int4) RETURNS int4" . " AS '$lib' LANGUAGE 'c'"); +Exec2($mconn,$sconn,"CREATE FUNCTION _rserv_xid_() RETURNS int4" . + " AS '$lib' LANGUAGE 'c'"); + # Now, lets add the needed information in the slave database Exec2($mconn,$sconn,"create table _RSERV_SLAVE_TABLES_" . Index: lib/rserv.c =================================================================== RCS file: /home/dpavlin/private/cvsroot/rserv/lib/rserv.c,v retrieving revision 1.4 diff -u -w -r1.4 rserv.c --- lib/rserv.c 28 Oct 2003 18:43:15 -0000 1.4 +++ lib/rserv.c 3 Nov 2003 17:11:26 -0000 @@ -16,14 +16,17 @@ PG_FUNCTION_INFO_V1(_rserv_log_); PG_FUNCTION_INFO_V1(_rserv_sync_); PG_FUNCTION_INFO_V1(_rserv_debug_); +PG_FUNCTION_INFO_V1(_rserv_xid_); Datum _rserv_log_(PG_FUNCTION_ARGS); Datum _rserv_sync_(PG_FUNCTION_ARGS); Datum _rserv_debug_(PG_FUNCTION_ARGS); +Datum _rserv_xid_(PG_FUNCTION_ARGS); #else HeapTuple _rserv_log_(void); int32 _rserv_sync_(int32); int32 _rserv_debug_(int32); +int32 _rserv_xid_(void); #endif static int debug = 0; @@ -335,3 +338,17 @@ return (out); } + +#ifdef PG_FUNCTION_INFO_V1 +Datum +_rserv_xid_(PG_FUNCTION_ARGS) +#else +int32 +_rserv_xid_(void) +#endif +{ + int32 curr_xid = GetCurrentTransactionId(); + + return (curr_xid); +} + Index: share/RServ.pm =================================================================== RCS file: /home/dpavlin/private/cvsroot/rserv/share/RServ.pm,v retrieving revision 1.17 diff -u -w -r1.17 RServ.pm --- share/RServ.pm 2 Nov 2003 21:07:20 -0000 1.17 +++ share/RServ.pm 3 Nov 2003 21:15:43 -0000 @@ -132,8 +132,6 @@ $sinfo .= ")"; } - my @keys; # keys in this snapshot - my $havedeal = 0; # DELETED rows @@ -171,7 +169,6 @@ return(-2); } printf $outf "%s\n", OutputValue($row[1]); - push @keys,OutputKey($row[2],$Mtables{$row[0]}[2]); } printf $outf "\\.\n" if ($lastoid != -1); @@ -185,7 +182,7 @@ my $oidkey = ($tabkey eq 'oid') ? "_$tabname.oid," : ''; - $sql = sprintf "SELECT \"_$tabname\".\"${tabkey}\",$oidkey \"_$tabname\".* FROM \"$tabname\" ". + $sql = sprintf "SELECT $oidkey \"_$tabname\".* FROM \"$tabname\" ". "\"_$tabname\", _RSERV_LOG_ l WHERE l.reloid = $taboid AND l.update = 1". " $sinfo AND \"_$tabname\".\"${tabkey}\"=l.key::${keytype}". $sel_server; @@ -211,7 +208,6 @@ printf "-- UPDATE $tabname\n" if $debug; while (@row = $result->fetchrow) { - push @keys,OutputKey(shift @row,$keytype); for (my $i = 0; $i <= $#row; $i++) { printf $outf " " if $i; @@ -235,7 +231,7 @@ my $oidkey = ($tabkey eq 'oid') ? "_$tabname.oid," : ''; - $sql = sprintf "SELECT \"_$tabname\".\"${tabkey}\", $oidkey \"_$tabname\".* FROM \"$tabname\" ". + $sql = sprintf "SELECT $oidkey \"_$tabname\".* FROM \"$tabname\" ". "\"_$tabname\", _RSERV_LOG_ l WHERE l.reloid = $taboid AND l.insert = 1". " $sinfo AND \"_$tabname\".\"${tabkey}\"=l.key::${keytype}". $sel_server; @@ -261,7 +257,6 @@ printf "-- INSERT $tabname\n" if $debug; while (@row = $result->fetchrow) { - push @keys,OutputKey(shift @row,$keytype); for (my $i = 0; $i <= $#row; $i++) { printf $outf " " if $i; @@ -303,14 +298,6 @@ return(-1); } - if ($multimaster) { - # save keys -# my $key_out = "-- KEYS ".($#keys+1)."\n(\"key\" like ".join(") or (\"key\" like ",@keys).")\n"; - my $key_out = "-- KEYS ".($#keys+1)."\n".join(",",@keys)."\n"; - print $outf $key_out; - print $key_out if ($debug); - } - printf $outf "-- OK\n"; printf "-- OK\n" if $debug; @@ -332,24 +319,6 @@ return($val); } -sub OutputKey { - my $val = shift; - my $cast = shift || ''; -# $cast = "::$cast" if ($cast); - $cast = "::text"; -# $cast = ""; - - return "null" if (! defined($val)); - - print STDERR "Key: ${val}${cast}\n" if ($debug); - - if ($val =~ m/^\d+$/) { - return "${val}${cast}"; - } else { - return "'$val'${cast}"; - } -} - # Get syncid for new snapshot sub GetSYNCID { @@ -491,11 +460,6 @@ print STDERR "Snapshot tables oids: ",join(",",keys %Stables),"\n" if ($debug); - # save keys from snapshot because we want to update _rserv_log_ with - # correct source server later... - my @keys; - my $keys_sql; - my $ok = 0; my $syncid = -1; while(<$inpf>) { @@ -590,6 +554,17 @@ } } elsif ($cmd eq 'OK') { $ok = 1; + if ($multimaster) { + # now, update server in _rserv_log_ based on transaction xid + ExecFatch($sconn,"select count(*) from _rserv_log_"); + ExecDebug($sconn,"select * from _rserv_log_"); + my $keys_sql = qq{ + update _rserv_log_ set server=$serverId + where logid = (select _rserv_xid_()) + }; + + Exec($sconn,$keys_sql); + } last; } elsif ($cmd eq 'ERROR') { printf STDERR "ERROR signaled\n" unless ($quiet); @@ -603,38 +578,6 @@ } $serverId = $prm; print STDERR "Server ID $serverId\n" unless ($quiet); - } elsif ($cmd eq 'KEYS') { - if ($prm !~ /^\d+$/) { - printf STDERR "Invalid numer of keys $prm\n" unless ($quiet); - $sconn->exec("ROLLBACK"); - return(-2); - } - my $keys = <$inpf>; - chomp($keys); - if ($multimaster) { -ExecFatch($sconn,"select count(*) from _rserv_log_"); -ExecDebug($sconn,"select * from _rserv_log_"); -my ($logid) = ExecFatch($sconn,"select distinct logid from _rserv_log_ where key in ($keys)"); - $keys_sql = qq{ - update _rserv_log_ set server=$serverId - where key in ($keys) - }; - $keys_sql = qq{ - update _rserv_log_ set server=$serverId - where logid = $logid - }; - - print STDERR "$keys_sql\n" if ($debug); - $result = $sconn->exec($keys_sql); -ExecDebug($sconn,"explain analyze $keys_sql"); - print STDERR "expected $prm updates, got ",$result->ntuples,"\n" if ($result->ntuples != $prm); -# if ($result->resultStatus ne PGRES_COMMAND_OK || $result->ntuples != $prm) { - if (0) { - print STDERR "FATAL: Cannot update source server in _rserv_log_: ",$sconn->errorMessage,"\n"; - $sconn->exec("ROLLBACK"); - return(-1); - } - } } else { printf STDERR "Unknown command $cmd\n" unless ($quiet); $sconn->exec("ROLLBACK"); @@ -642,7 +585,6 @@ } } -ExecFatch($sconn,"select count(*) from _rserv_log_"); if (! $ok) { printf STDERR "No OK flag in input\n" unless ($quiet); $sconn->exec("ROLLBACK"); @@ -1067,11 +1009,16 @@ # XXX TODO: return results?! } +# exec sql query and return one row from it sub ExecFatch { my $conn = shift || die "ExecFatch need conn!"; my $sql = shift || die "ExecFatch need SQL!"; - print STDERR "ExecFatch: $sql\n" if ($debug); + if ($debug) { + # re-format SQL in one line (for nicer output) + $sql =~ s/[\s\n\r]+/ /gs; + print STDERR "Exec: $sql\n"; + } my $result = $conn->exec($sql); RollbackAndQuit($conn) if ($result->resultStatus ne PGRES_TUPLES_OK); @@ -1083,11 +1030,18 @@ return @row; } +# exec sql query and dump all rows retured to STDERR (great for debugging) sub ExecDebug { + return if (! $debug); + my $conn = shift || die "ExecDebug need conn!"; my $sql = shift || die "ExecDebug need SQL!"; - print STDERR "ExecDebug: $sql\n" if ($debug); + if ($debug) { + # re-format SQL in one line (for nicer output) + $sql =~ s/[\s\n\r]+/ /gs; + print STDERR "Exec: $sql\n"; + } my $result = $conn->exec($sql); RollbackAndQuit($conn) if ($result->resultStatus ne PGRES_TUPLES_OK);