aboutsummaryrefslogtreecommitdiff
path: root/src/bin/pg_rewind/RewindTest.pm
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/pg_rewind/RewindTest.pm')
-rw-r--r--src/bin/pg_rewind/RewindTest.pm216
1 files changed, 73 insertions, 143 deletions
diff --git a/src/bin/pg_rewind/RewindTest.pm b/src/bin/pg_rewind/RewindTest.pm
index a4c17371dcf..c1c7d1fa19f 100644
--- a/src/bin/pg_rewind/RewindTest.pm
+++ b/src/bin/pg_rewind/RewindTest.pm
@@ -9,22 +9,20 @@ package RewindTest;
# To run a test, the test script (in t/ subdirectory) calls the functions
# in this module. These functions should be called in this sequence:
#
-# 1. init_rewind_test - sets up log file etc.
+# 1. setup_cluster - creates a PostgreSQL cluster that runs as the master
#
-# 2. setup_cluster - creates a PostgreSQL cluster that runs as the master
+# 2. start_master - starts the master server
#
-# 3. start_master - starts the master server
-#
-# 4. create_standby - runs pg_basebackup to initialize a standby server, and
+# 3. create_standby - runs pg_basebackup to initialize a standby server, and
# sets it up to follow the master.
#
-# 5. promote_standby - runs "pg_ctl promote" to promote the standby server.
+# 4. promote_standby - runs "pg_ctl promote" to promote the standby server.
# The old master keeps running.
#
-# 6. run_pg_rewind - stops the old master (if it's still running) and runs
+# 5. run_pg_rewind - stops the old master (if it's still running) and runs
# pg_rewind to synchronize it with the now-promoted standby server.
#
-# 7. clean_rewind_test - stops both servers used in the test, if they're
+# 6. clean_rewind_test - stops both servers used in the test, if they're
# still running.
#
# The test script can use the helper functions master_psql and standby_psql
@@ -37,27 +35,23 @@ package RewindTest;
use strict;
use warnings;
-use TestLib;
-use Test::More;
-
use Config;
+use Exporter 'import';
use File::Copy;
use File::Path qw(rmtree);
-use IPC::Run qw(run start);
+use IPC::Run qw(run);
+use PostgresNode;
+use TestLib;
+use Test::More;
-use Exporter 'import';
our @EXPORT = qw(
- $connstr_master
- $connstr_standby
- $test_master_datadir
- $test_standby_datadir
+ $node_master
+ $node_standby
- append_to_file
master_psql
standby_psql
check_query
- init_rewind_test
setup_cluster
start_master
create_standby
@@ -66,32 +60,24 @@ our @EXPORT = qw(
clean_rewind_test
);
-our $test_master_datadir = "$tmp_check/data_master";
-our $test_standby_datadir = "$tmp_check/data_standby";
-
-# Define non-conflicting ports for both nodes.
-my $port_master = $ENV{PGPORT};
-my $port_standby = $port_master + 1;
-
-my $connstr_master = "port=$port_master";
-my $connstr_standby = "port=$port_standby";
-
-$ENV{PGDATABASE} = "postgres";
+# Our nodes.
+our $node_master;
+our $node_standby;
sub master_psql
{
my $cmd = shift;
- system_or_bail 'psql', '-q', '--no-psqlrc', '-d', $connstr_master,
- '-c', "$cmd";
+ system_or_bail 'psql', '-q', '--no-psqlrc', '-d',
+ $node_master->connstr('postgres'), '-c', "$cmd";
}
sub standby_psql
{
my $cmd = shift;
- system_or_bail 'psql', '-q', '--no-psqlrc', '-d', $connstr_standby,
- '-c', "$cmd";
+ system_or_bail 'psql', '-q', '--no-psqlrc', '-d',
+ $node_standby->connstr('postgres'), '-c', "$cmd";
}
# Run a query against the master, and check that the output matches what's
@@ -103,8 +89,9 @@ sub check_query
# we want just the output, no formatting
my $result = run [
- 'psql', '-q', '-A', '-t', '--no-psqlrc', '-d',
- $connstr_master, '-c', $query ],
+ 'psql', '-q', '-A', '-t', '--no-psqlrc', '-d',
+ $node_master->connstr('postgres'),
+ '-c', $query ],
'>', \$stdout, '2>', \$stderr;
# We don't use ok() for the exit code and stderr, because we want this
@@ -125,56 +112,16 @@ sub check_query
}
}
-# Run a query once a second, until it returns 't' (i.e. SQL boolean true).
-sub poll_query_until
-{
- my ($query, $connstr) = @_;
-
- my $max_attempts = 30;
- my $attempts = 0;
- my ($stdout, $stderr);
-
- while ($attempts < $max_attempts)
- {
- my $cmd = [ 'psql', '-At', '-c', "$query", '-d', "$connstr" ];
- my $result = run $cmd, '>', \$stdout, '2>', \$stderr;
-
- chomp($stdout);
- $stdout =~ s/\r//g if $Config{osname} eq 'msys';
- if ($stdout eq "t")
- {
- return 1;
- }
-
- # Wait a second before retrying.
- sleep 1;
- $attempts++;
- }
-
- # The query result didn't change in 30 seconds. Give up. Print the stderr
- # from the last attempt, hopefully that's useful for debugging.
- diag $stderr;
- return 0;
-}
-
-sub append_to_file
-{
- my ($filename, $str) = @_;
-
- open my $fh, ">>", $filename or die "could not open file $filename";
- print $fh $str;
- close $fh;
-}
-
sub setup_cluster
{
+
# Initialize master, data checksums are mandatory
- rmtree($test_master_datadir);
- standard_initdb($test_master_datadir);
+ $node_master = get_new_node();
+ $node_master->init;
# Custom parameters for master's postgresql.conf
- append_to_file(
- "$test_master_datadir/postgresql.conf", qq(
+ $node_master->append_conf(
+ "postgresql.conf", qq(
wal_level = hot_standby
max_wal_senders = 2
wal_keep_segments = 20
@@ -185,17 +132,11 @@ hot_standby = on
autovacuum = off
max_connections = 10
));
-
- # Accept replication connections on master
- configure_hba_for_replication $test_master_datadir;
}
sub start_master
{
- system_or_bail('pg_ctl' , '-w',
- '-D' , $test_master_datadir,
- '-l', "$log_path/master.log",
- "-o", "-p $port_master", 'start');
+ $node_master->start;
#### Now run the test-specific parts to initialize the master before setting
# up standby
@@ -203,24 +144,20 @@ sub start_master
sub create_standby
{
+ $node_standby = get_new_node();
+ $node_master->backup('my_backup');
+ $node_standby->init_from_backup($node_master, 'my_backup');
+ my $connstr_master = $node_master->connstr('postgres');
- # Set up standby with necessary parameter
- rmtree $test_standby_datadir;
-
- # Base backup is taken with xlog files included
- system_or_bail('pg_basebackup', '-D', $test_standby_datadir,
- '-p', $port_master, '-x');
- append_to_file(
- "$test_standby_datadir/recovery.conf", qq(
+ $node_standby->append_conf(
+ "recovery.conf", qq(
primary_conninfo='$connstr_master application_name=rewind_standby'
standby_mode=on
recovery_target_timeline='latest'
));
# Start standby
- system_or_bail('pg_ctl', '-w', '-D', $test_standby_datadir,
- '-l', "$log_path/standby.log",
- '-o', "-p $port_standby", 'start');
+ $node_standby->start;
# The standby may have WAL to apply before it matches the primary. That
# is fine, because no test examines the standby before promotion.
@@ -234,14 +171,15 @@ sub promote_standby
# Wait for the standby to receive and write all WAL.
my $wal_received_query =
"SELECT pg_current_xlog_location() = write_location FROM pg_stat_replication WHERE application_name = 'rewind_standby';";
- poll_query_until($wal_received_query, $connstr_master)
+ $node_master->poll_query_until('postgres', $wal_received_query)
or die "Timed out while waiting for standby to receive and write WAL";
# Now promote slave and insert some new data on master, this will put
# the master out-of-sync with the standby. Wait until the standby is
# out of recovery mode, and is ready to accept read-write connections.
- system_or_bail('pg_ctl', '-w', '-D', $test_standby_datadir, 'promote');
- poll_query_until("SELECT NOT pg_is_in_recovery()", $connstr_standby)
+ system_or_bail('pg_ctl', '-w', '-D', $node_standby->data_dir, 'promote');
+ $node_standby->poll_query_until('postgres',
+ "SELECT NOT pg_is_in_recovery()")
or die "Timed out while waiting for promotion of standby";
# Force a checkpoint after the promotion. pg_rewind looks at the control
@@ -255,10 +193,14 @@ sub promote_standby
sub run_pg_rewind
{
- my $test_mode = shift;
+ my $test_mode = shift;
+ my $master_pgdata = $node_master->data_dir;
+ my $standby_pgdata = $node_standby->data_dir;
+ my $standby_connstr = $node_standby->connstr('postgres');
+ my $tmp_folder = TestLib::tempdir;
# Stop the master and be ready to perform the rewind
- system_or_bail('pg_ctl', '-D', $test_master_datadir, '-m', 'fast', 'stop');
+ $node_master->stop;
# At this point, the rewind processing is ready to run.
# We now have a very simple scenario with a few diverged WAL record.
@@ -267,31 +209,33 @@ sub run_pg_rewind
# Keep a temporary postgresql.conf for master node or it would be
# overwritten during the rewind.
- copy("$test_master_datadir/postgresql.conf",
- "$tmp_check/master-postgresql.conf.tmp");
+ copy(
+ "$master_pgdata/postgresql.conf",
+ "$tmp_folder/master-postgresql.conf.tmp");
# Now run pg_rewind
if ($test_mode eq "local")
{
+
# Do rewind using a local pgdata as source
# Stop the master and be ready to perform the rewind
- system_or_bail('pg_ctl', '-D', $test_standby_datadir,
- '-m', 'fast', 'stop');
- command_ok(['pg_rewind',
- "--debug",
- "--source-pgdata=$test_standby_datadir",
- "--target-pgdata=$test_master_datadir"],
- 'pg_rewind local');
+ $node_standby->stop;
+ command_ok(
+ [ 'pg_rewind',
+ "--debug",
+ "--source-pgdata=$standby_pgdata",
+ "--target-pgdata=$master_pgdata" ],
+ 'pg_rewind local');
}
elsif ($test_mode eq "remote")
{
+
# Do rewind using a remote connection as source
- command_ok(['pg_rewind',
- "--debug",
- "--source-server",
- "port=$port_standby dbname=postgres",
- "--target-pgdata=$test_master_datadir"],
- 'pg_rewind remote');
+ command_ok(
+ [ 'pg_rewind', "--debug",
+ "--source-server", $standby_connstr,
+ "--target-pgdata=$master_pgdata" ],
+ 'pg_rewind remote');
}
else
{
@@ -301,21 +245,21 @@ sub run_pg_rewind
}
# Now move back postgresql.conf with old settings
- move("$tmp_check/master-postgresql.conf.tmp",
- "$test_master_datadir/postgresql.conf");
+ move(
+ "$tmp_folder/master-postgresql.conf.tmp",
+ "$master_pgdata/postgresql.conf");
# Plug-in rewound node to the now-promoted standby node
- append_to_file(
- "$test_master_datadir/recovery.conf", qq(
+ my $port_standby = $node_standby->port;
+ $node_master->append_conf(
+ 'recovery.conf', qq(
primary_conninfo='port=$port_standby'
standby_mode=on
recovery_target_timeline='latest'
));
# Restart the master to check that rewind went correctly
- system_or_bail('pg_ctl', '-w', '-D', $test_master_datadir,
- '-l', "$log_path/master.log",
- '-o', "-p $port_master", 'start');
+ $node_master->start;
#### Now run the test-specific parts to check the result
}
@@ -323,22 +267,8 @@ recovery_target_timeline='latest'
# Clean up after the test. Stop both servers, if they're still running.
sub clean_rewind_test
{
- if ($test_master_datadir)
- {
- system
- 'pg_ctl', '-D', $test_master_datadir, '-m', 'immediate', 'stop';
- }
- if ($test_standby_datadir)
- {
- system
- 'pg_ctl', '-D', $test_standby_datadir, '-m', 'immediate', 'stop';
- }
+ $node_master->teardown_node if defined $node_master;
+ $node_standby->teardown_node if defined $node_standby;
}
-# Stop the test servers, just in case they're still running.
-END
-{
- my $save_rc = $?;
- clean_rewind_test();
- $? = $save_rc;
-}
+1;