From c94e52f697cdae67c35fe8cb0f95088029231b95 Mon Sep 17 00:00:00 2001 From: David Steele Date: Mon, 16 Oct 2017 14:34:44 -0400 Subject: [PATCH] Remove error when overlapping timelines are detected. Overlapping timelines are valid in many Point-in-Time-Recovery (PITR) scenarios. Reported by blogh. --- doc/xml/release.xml | 10 +++++ lib/pgBackRest/Archive/Common.pm | 45 +++++-------------- lib/pgBackRest/Backup/Backup.pm | 4 +- .../Module/Archive/ArchiveCommonTest.pm | 19 -------- 4 files changed, 24 insertions(+), 54 deletions(-) diff --git a/doc/xml/release.xml b/doc/xml/release.xml index 5e19fd06d..3a3477f3f 100644 --- a/doc/xml/release.xml +++ b/doc/xml/release.xml @@ -12,6 +12,16 @@ + + + + + + +

Remove error when overlapping timelines are detected. Overlapping timelines are valid in many Point-in-Time-Recovery (PITR) scenarios.

+
+
+

Update C naming conventions.

diff --git a/lib/pgBackRest/Archive/Common.pm b/lib/pgBackRest/Archive/Common.pm index 879e97818..83682b127 100644 --- a/lib/pgBackRest/Archive/Common.pm +++ b/lib/pgBackRest/Archive/Common.pm @@ -281,9 +281,7 @@ sub walSegmentFind ); # Error if not a segment - my $bTimeline = $strWalSegment =~ /^[0-F]{16}$/ ? false : true; - - if ($bTimeline && !walIsSegment($strWalSegment)) + if (!walIsSegment($strWalSegment)) { confess &log(ERROR, "${strWalSegment} is not a WAL segment", ERROR_ASSERT); } @@ -294,35 +292,13 @@ sub walSegmentFind do { - # If the WAL segment includes the timeline then use it, otherwise contruct a regexp with the major WAL part to find paths - # where the wal could be found. - my @stryTimelineMajor; - - if ($bTimeline) - { - @stryTimelineMajor = (substr($strWalSegment, 0, 16)); - } - else - { - @stryTimelineMajor = $oStorageRepo->list( - STORAGE_REPO_ARCHIVE . "/${strArchiveId}", - {strExpression => '[0-F]{8}' . substr($strWalSegment, 0, 8), bIgnoreMissing => true}); - } - - # Search each timelin/major path - foreach my $strTimelineMajor (@stryTimelineMajor) - { - # Construct the name of the WAL segment to find - my $strWalSegmentFind = $bTimeline ? substr($strWalSegment, 0, 24) : $strTimelineMajor . substr($strWalSegment, 8, 16); - - # Get the name of the requested WAL segment (may have hash info and compression extension) - push(@stryWalFileName, $oStorageRepo->list( - STORAGE_REPO_ARCHIVE . "/${strArchiveId}/${strTimelineMajor}", - {strExpression => - "^${strWalSegmentFind}" . (walIsPartial($strWalSegment) ? "\\.partial" : '') . - "-[0-f]{40}(\\." . COMPRESS_EXT . "){0,1}\$", - bIgnoreMissing => true})); - } + # Get the name of the requested WAL segment (may have compression extension) + push(@stryWalFileName, $oStorageRepo->list( + STORAGE_REPO_ARCHIVE . "/${strArchiveId}/" . substr($strWalSegment, 0, 16), + {strExpression => + '^' . substr($strWalSegment, 0, 24) . (walIsPartial($strWalSegment) ? "\\.partial" : '') . + "-[0-f]{40}(\\." . COMPRESS_EXT . "){0,1}\$", + bIgnoreMissing => true})); } while (@stryWalFileName == 0 && waitMore($oWait)); @@ -331,8 +307,9 @@ sub walSegmentFind if (@stryWalFileName > 1) { confess &log(ERROR, - "duplicates found in archive for WAL segment " . ($bTimeline ? $strWalSegment : "XXXXXXXX${strWalSegment}") . ': ' . - join(', ', @stryWalFileName), ERROR_ARCHIVE_DUPLICATE); + "duplicates found in archive for WAL segment ${strWalSegment}: " . join(', ', @stryWalFileName) . + "\nHINT: are multiple primaries archiving to this stanza?", + ERROR_ARCHIVE_DUPLICATE); } # If waiting and no WAL segment was found then throw an error diff --git a/lib/pgBackRest/Backup/Backup.pm b/lib/pgBackRest/Backup/Backup.pm index 67ff5de2e..f37ea6dc3 100644 --- a/lib/pgBackRest/Backup/Backup.pm +++ b/lib/pgBackRest/Backup/Backup.pm @@ -889,7 +889,9 @@ sub process foreach my $strArchive (@stryArchive) { - my $strArchiveFile = walSegmentFind($oStorageRepo, $strArchiveId, $strArchive, cfgOption(CFGOPT_ARCHIVE_TIMEOUT)); + my $strArchiveFile = walSegmentFind( + $oStorageRepo, $strArchiveId, substr($strArchiveStop, 0, 8) . $strArchive, cfgOption(CFGOPT_ARCHIVE_TIMEOUT)); + $strArchive = substr($strArchiveFile, 0, 24); if (cfgOption(CFGOPT_ARCHIVE_COPY)) diff --git a/test/lib/pgBackRestTest/Module/Archive/ArchiveCommonTest.pm b/test/lib/pgBackRestTest/Module/Archive/ArchiveCommonTest.pm index 56fe38336..bb87e09f5 100644 --- a/test/lib/pgBackRestTest/Module/Archive/ArchiveCommonTest.pm +++ b/test/lib/pgBackRestTest/Module/Archive/ArchiveCommonTest.pm @@ -130,11 +130,6 @@ sub run $self->testResult( sub {walSegmentFind(storageRepo(), $strArchiveId, $strWalSegment)}, $strWalSegmentHash, "${strWalSegment} WAL found"); - #--------------------------------------------------------------------------------------------------------------------------- - $self->testResult( - sub {walSegmentFind(storageRepo(), $strArchiveId, substr($strWalSegment, 8, 16))}, $strWalSegmentHash, - "${strWalSegment} WAL found without timeline"); - #--------------------------------------------------------------------------------------------------------------------------- my $strWalSegmentHash2 = "${strWalSegment}-a0b0d38b8aa263e25b8ff52a0a4ba85b6be97f9b.gz"; @@ -144,21 +139,7 @@ sub run sub {walSegmentFind(storageRepo(), $strArchiveId, $strWalSegment)}, ERROR_ARCHIVE_DUPLICATE, "duplicates found in archive for WAL segment ${strWalSegment}: ${strWalSegmentHash}, ${strWalSegmentHash2}"); - #--------------------------------------------------------------------------------------------------------------------------- - my $strWalSegment3 = '00000002' . substr($strWalSegment, 8, 16); - my $strWalSegmentHash3 = "${strWalSegment3}-dcdd09246e1918e88c67cf44b35edc23b803d879"; - my $strWalMajorPath3 = "${strArchivePath}/" . substr($strWalSegment3, 0, 16); - - storageRepo()->pathCreate($strWalMajorPath3, {bCreateParent => true}); - storageRepo()->put("${strWalMajorPath3}/${strWalSegmentHash3}"); - - $self->testException( - sub {walSegmentFind(storageRepo(), $strArchiveId, substr($strWalSegment, 8, 16))}, ERROR_ARCHIVE_DUPLICATE, - "duplicates found in archive for WAL segment XXXXXXXX" . substr($strWalSegment, 8, 16) . - ": ${strWalSegmentHash}, ${strWalSegmentHash2}, ${strWalSegmentHash3}"); - storageRepo()->remove("${strWalMajorPath}/${strWalSegmentHash}"); - storageRepo()->remove("${strWalMajorPath3}/${strWalSegmentHash3}"); #--------------------------------------------------------------------------------------------------------------------------- $self->testResult(