diff --git a/src/bin/pg_rewind/filemap.c b/src/bin/pg_rewind/filemap.c index 69d7728ce44..743484f4833 100644 --- a/src/bin/pg_rewind/filemap.c +++ b/src/bin/pg_rewind/filemap.c @@ -732,11 +732,11 @@ decide_wal_file_action(const char *fname, XLogSegNo last_common_segno, */ if (file_segno < last_common_segno && source_size == target_size) { pg_log_debug("WAL segment \"%s\" not copied to target", fname); return FILE_ACTION_NONE; } + pg_log_debug("WAL segment \"%s\" is copied to target", fname); return FILE_ACTION_COPY; } diff --git a/src/bin/pg_rewind/t/011_avoid_copying_common_wals.pl b/src/bin/pg_rewind/t/011_avoid_copying_common_wals.pl index 8d49ebde04d..bcad03a50c5 100644 --- a/src/bin/pg_rewind/t/011_avoid_copying_common_wals.pl +++ b/src/bin/pg_rewind/t/011_avoid_copying_common_wals.pl @@ -7,7 +7,6 @@ use strict; use warnings FATAL => 'all'; use PostgreSQL::Test::Utils; use Test::More; -use File::Spec; use File::stat qw(stat); use FindBin; @@ -32,7 +31,7 @@ RewindTest::primary_psql("SELECT pg_switch_wal()"); # Segment before divergerec that will be copied over because file size differs RewindTest::primary_psql("INSERT INTO t VALUES(0)"); -my $wal_seg_before_diverge_copied = $node_primary->safe_psql('postgres', 'SELECT pg_walfile_name(pg_current_wal_lsn())'); +my $corrupt_wal_seg = $node_primary->safe_psql('postgres', 'SELECT pg_walfile_name(pg_current_wal_lsn())'); RewindTest::primary_psql("SELECT pg_switch_wal()"); # last common checkpoint @@ -40,39 +39,40 @@ RewindTest::primary_psql("CHECKPOINT"); RewindTest::promote_standby; -# Segment after divergerec, expected to be copied -my $wal_seg_copied = $node_standby->safe_psql('postgres', 'SELECT pg_walfile_name(pg_current_wal_lsn())'); +# New Timeline Segment after divergerec, expected to be copied +my $new_timeline_wal_seg = $node_standby->safe_psql('postgres', 'SELECT pg_walfile_name(pg_current_wal_lsn())'); # Get stat info for the WAL file that should be skipped -my $wal_skipped_path = File::Spec->catfile($node_primary->data_dir, 'pg_wal', $wal_seg_skipped); +my $wal_skipped_path = $node_primary->data_dir . '/pg_wal/' . $wal_seg_skipped; my $wal_skipped_stat = stat($wal_skipped_path); defined($wal_skipped_stat) or die("unable to stat $wal_skipped_path"); # Store modification time for later comparison my $wal_seg_skipped_mod_time = $wal_skipped_stat->mtime; -# Append an additional byte to segment on target before divergerec to test it's copied over from source -my $wal_seg_before_diverge_copied_path = File::Spec->catfile($node_primary->data_dir, 'pg_wal', $wal_seg_before_diverge_copied); -open my $fh, ">>", $wal_seg_before_diverge_copied_path - or die "could not open $wal_seg_before_diverge_copied_path"; +# Corrupt a segment on target before divergerec to test it's copied over from source, +# by appending an additional byte to it. +my $corrupt_wal_seg_in_target_path = $node_primary->data_dir . '/pg_wal/' . $corrupt_wal_seg; +open my $fh, ">>", $corrupt_wal_seg_in_target_path + or die "could not open $corrupt_wal_seg_in_target_path"; print $fh 'a'; close $fh; -my $wal_seg_existing_copied_stat = stat($wal_seg_before_diverge_copied_path); -ok(defined($wal_seg_existing_copied_stat), "WAL segment $wal_seg_before_diverge_copied should exist in target before rewind"); +my $corrupt_wal_seg_stat_before_rewind = stat($corrupt_wal_seg_in_target_path); +ok(defined($corrupt_wal_seg_stat_before_rewind), "WAL segment $corrupt_wal_seg should exist in target before rewind"); # Verify that the WAL segment on new timeline does not exist in target before rewind -my $wal_copied_path = File::Spec->catfile($node_primary->data_dir, 'pg_wal', $wal_seg_copied); -my $wal_copied_stat = stat($wal_copied_path); -ok(!defined($wal_copied_stat), "WAL segment $wal_seg_copied should not exist in target before rewind"); +my $new_timeline_wal_seg_path = $node_primary->data_dir . '/pg_wal/' . $new_timeline_wal_seg; +my $new_timeline_wal_seg_stat = stat($new_timeline_wal_seg_path); +ok(!defined($new_timeline_wal_seg_stat), "WAL segment $new_timeline_wal_seg should not exist in target before rewind"); $node_standby->stop(); $node_primary->stop(); # Sleep to allow mtime to be different -usleep(1000); +usleep(1000000); command_checks_all( [ @@ -84,28 +84,37 @@ command_checks_all( 0, [qr// ], - [qr/WAL segment \"$wal_seg_skipped\" not copied to target/], + [ + qr/WAL segment \"$wal_seg_skipped\" not copied to target/, + qr/WAL segment \"$corrupt_wal_seg\" is copied to target/ + ], 'run pg_rewind' ); # Verify that the copied WAL segment now exists in target -$wal_copied_stat = stat($wal_copied_path); -ok(defined($wal_copied_stat), "WAL segment $wal_seg_copied should exist in target after rewind"); +$new_timeline_wal_seg_stat = stat($new_timeline_wal_seg_path); +ok(defined($new_timeline_wal_seg_stat), "WAL segment $new_timeline_wal_seg should exist in target after rewind"); # Get current modification time of the skipped WAL segment -my $wal_skipped_stat_after = stat($wal_skipped_path); -defined($wal_skipped_stat_after) or die("unable to stat $wal_skipped_path after rewind"); -my $wal_seg_latest_skipped_mod_time = $wal_skipped_stat_after->mtime; +my $wal_skipped_stat_after_rewind = stat($wal_skipped_path); +defined($wal_skipped_stat_after_rewind) or die("unable to stat $wal_skipped_path after rewind"); +my $wal_seg_latest_skipped_mod_time = $wal_skipped_stat_after_rewind->mtime; # Validate that modification time hasn't changed, is($wal_seg_latest_skipped_mod_time, $wal_seg_skipped_mod_time, "WAL segment $wal_seg_skipped modification time should be unchanged (not overwritten)"); -# Validate WAL with size different prior to divergerec was updated -my $wal_seg_existing_copied_after_stat = stat($wal_seg_before_diverge_copied_path); -defined($wal_seg_existing_copied_after_stat) or die("unable to stat $wal_skipped_path"); - -isnt($wal_seg_existing_copied_stat->size, $wal_seg_existing_copied_after_stat->size, "WAL segment $wal_seg_before_diverge_copied with byte difference did not get copied"); +# Validate that the WAL segment with same filename as the +# corrupt WAL segment in target has been copied from source +# where we have it intact. +my $corrupt_wal_seg_in_source_path = $node_standby->data_dir . '/pg_wal/' . $corrupt_wal_seg; +my $corrupt_wal_seg_source_stat = stat($corrupt_wal_seg_in_source_path); +ok(defined($corrupt_wal_seg_source_stat), "WAL segment $corrupt_wal_seg should exist in source after rewind"); +my $corrupt_wal_seg_stat_after_rewind = stat($corrupt_wal_seg_in_target_path); +ok(defined($corrupt_wal_seg_stat_after_rewind), "WAL segment $corrupt_wal_seg should exist in target after rewind"); +ok($corrupt_wal_seg_stat_before_rewind->size != $corrupt_wal_seg_source_stat->size,"WAL segment $corrupt_wal_seg has different size in source vs target before rewind"); +ok($corrupt_wal_seg_stat_after_rewind->mtime > $corrupt_wal_seg_stat_before_rewind->mtime,"WAL segment $corrupt_wal_seg was copied: mtime after rewind > mtime before rewind"); +ok($corrupt_wal_seg_stat_after_rewind->size == $corrupt_wal_seg_source_stat->size, "WAL segment $corrupt_wal_seg was copied: file sizes are same between target and source after rewind"); done_testing();