1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-12 10:04:14 +02:00

Allow pg-path1 to be optional for synchronous archive-push.

If the WAL path is absolute then pg1-path should be optional but in fact it was required to load pg_control.

Skip the pg_control check when pg1-path is not specified. The check against the stanza version/system-id remains to protect the repo from corruption.
This commit is contained in:
David Steele 2020-05-01 10:30:35 -04:00
parent 1d45282b97
commit 816ba9244f
3 changed files with 56 additions and 23 deletions

View File

@ -64,6 +64,14 @@
<p>WAL prior to the first full backup was previously expired after the first full backup. Now it is preserved according to retention settings.</p>
</release-item>
<release-item>
<release-item-contributor-list>
<release-item-reviewer id="cynthia.shang"/>
</release-item-contributor-list>
<p>Allow <br-option>pg-path1</br-option> to be optional for synchronous <cmd>archive-push</cmd>.</p>
</release-item>
<release-item>
<release-item-contributor-list>
<release-item-contributor id="cynthia.shang"/>

View File

@ -200,9 +200,10 @@ typedef struct ArchivePushCheckResult
} ArchivePushCheckResult;
static ArchivePushCheckResult
archivePushCheck(CipherType cipherType, const String *cipherPass)
archivePushCheck(bool pgPathSet, CipherType cipherType, const String *cipherPass)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(BOOL, pgPathSet);
FUNCTION_LOG_PARAM(ENUM, cipherType);
FUNCTION_TEST_PARAM(STRING, cipherPass);
FUNCTION_LOG_END();
@ -211,9 +212,6 @@ archivePushCheck(CipherType cipherType, const String *cipherPass)
MEM_CONTEXT_TEMP_BEGIN()
{
// Get info from pg_control
PgControl controlInfo = pgControlFromFile(storagePg());
// Attempt to load the archive info file
InfoArchive *info = infoArchiveLoadFile(storageRepo(), INFO_ARCHIVE_PATH_FILE_STR, cipherType, cipherPass);
@ -221,21 +219,27 @@ archivePushCheck(CipherType cipherType, const String *cipherPass)
String *archiveId = infoPgArchiveId(infoArchivePg(info), infoPgDataCurrentId(infoArchivePg(info)));
InfoPgData archiveInfo = infoPgData(infoArchivePg(info), infoPgDataCurrentId(infoArchivePg(info)));
// Ensure that the version and system identifier match
if (controlInfo.version != archiveInfo.version || controlInfo.systemId != archiveInfo.systemId)
// Ensure that stanza version and system identifier match pg_control when available
if (pgPathSet)
{
THROW_FMT(
ArchiveMismatchError,
"PostgreSQL version %s, system-id %" PRIu64 " do not match stanza version %s, system-id %" PRIu64
"\nHINT: are you archiving to the correct stanza?",
strPtr(pgVersionToStr(controlInfo.version)), controlInfo.systemId, strPtr(pgVersionToStr(archiveInfo.version)),
archiveInfo.systemId);
// Get info from pg_control
PgControl controlInfo = pgControlFromFile(storagePg());
if (controlInfo.version != archiveInfo.version || controlInfo.systemId != archiveInfo.systemId)
{
THROW_FMT(
ArchiveMismatchError,
"PostgreSQL version %s, system-id %" PRIu64 " do not match stanza version %s, system-id %" PRIu64
"\nHINT: are you archiving to the correct stanza?",
strPtr(pgVersionToStr(controlInfo.version)), controlInfo.systemId, strPtr(pgVersionToStr(archiveInfo.version)),
archiveInfo.systemId);
}
}
MEM_CONTEXT_PRIOR_BEGIN()
{
result.pgVersion = controlInfo.version;
result.pgSystemId = controlInfo.systemId;
result.pgVersion = archiveInfo.version;
result.pgSystemId = archiveInfo.systemId;
result.archiveId = strDup(archiveId);
result.archiveCipherPass = strDup(infoArchiveCipherPass(info));
}
@ -278,6 +282,10 @@ cmdArchivePush(void)
bool forked = false; // Has the async process been forked yet?
bool throwOnError = false; // Should we throw errors?
// pg1-path is not optional for async mode
if (!cfgOptionTest(cfgOptPgPath))
THROW(OptionRequiredError, "'" CFGCMD_ARCHIVE_PUSH "' command in async mode requires option '" CFGOPT_PG1_PATH "'");
// Loop and wait for the WAL segment to be pushed
Wait *wait = waitNew((TimeMSec)(cfgOptionDbl(cfgOptArchiveTimeout) * MSEC_PER_SEC));
@ -341,7 +349,8 @@ cmdArchivePush(void)
// Get archive info
ArchivePushCheckResult archiveInfo = archivePushCheck(
cipherType(cfgOptionStr(cfgOptRepoCipherType)), cfgOptionStrNull(cfgOptRepoCipherPass));
cfgOptionTest(cfgOptPgPath), cipherType(cfgOptionStr(cfgOptRepoCipherType)),
cfgOptionStrNull(cfgOptRepoCipherPass));
// Check if the push queue has been exceeded
if (cfgOptionTest(cfgOptArchivePushQueueMax) &&
@ -484,7 +493,7 @@ cmdArchivePushAsync(void)
// Get archive info
jobData.archiveInfo = archivePushCheck(
cipherType(cfgOptionStr(cfgOptRepoCipherType)), cfgOptionStrNull(cfgOptRepoCipherPass));
true, cipherType(cfgOptionStr(cfgOptRepoCipherType)), cfgOptionStrNull(cfgOptRepoCipherPass));
// Create the parallel executor
ProtocolParallel *parallelExec = protocolParallelNew(

View File

@ -133,7 +133,7 @@ testRun(void)
"1={\"db-id\":5555555555555555555,\"db-version\":\"9.4\"}\n"));
TEST_ERROR(
archivePushCheck(cipherTypeNone, NULL), ArchiveMismatchError,
archivePushCheck(true, cipherTypeNone, NULL), ArchiveMismatchError,
"PostgreSQL version 9.6, system-id 18072658121562454734 do not match stanza version 9.4, system-id 5555555555555555555"
"\nHINT: are you archiving to the correct stanza?");
@ -148,7 +148,7 @@ testRun(void)
"1={\"db-id\":5555555555555555555,\"db-version\":\"9.6\"}\n"));
TEST_ERROR(
archivePushCheck(cipherTypeNone, NULL), ArchiveMismatchError,
archivePushCheck(true, cipherTypeNone, NULL), ArchiveMismatchError,
"PostgreSQL version 9.6, system-id 18072658121562454734 do not match stanza version 9.6, system-id 5555555555555555555"
"\nHINT: are you archiving to the correct stanza?");
@ -163,7 +163,7 @@ testRun(void)
"1={\"db-id\":18072658121562454734,\"db-version\":\"9.6\"}\n"));
ArchivePushCheckResult result = {0};
TEST_ASSIGN(result, archivePushCheck(cipherTypeNone, NULL), "get archive check result");
TEST_ASSIGN(result, archivePushCheck(true, cipherTypeNone, NULL), "get archive check result");
TEST_RESULT_UINT(result.pgVersion, PG_VERSION_96, "check pg version");
TEST_RESULT_UINT(result.pgSystemId, 0xFACEFACEFACEFACE, "check pg system id");
@ -290,12 +290,16 @@ testRun(void)
TEST_ERROR(cmdArchivePush(), ArchiveDuplicateError, "WAL file '000000010000000100000001' already exists in the archive");
// Save it to a new file instead
argListTemp = strLstDup(argList);
strLstAddZ(argListTemp, "pg_wal/000000010000000100000002");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("WAL with absolute path and no pg1-path");
argListTemp = strLstNew();
strLstAddZ(argListTemp, "--" CFGOPT_STANZA "=test");
strLstAdd(argListTemp, strNewFmt("--" CFGOPT_REPO1_PATH "=%s/repo", testPath()));
strLstAdd(argListTemp, strNewFmt("%s/pg/pg_wal/000000010000000100000002", testPath()));
harnessCfgLoad(cfgCmdArchivePush, argListTemp);
storagePutP(storageNewWriteP(storagePgWrite(), strNew("pg_wal/000000010000000100000002")), walBuffer2);
TEST_RESULT_VOID(storagePutP(storageNewWriteP(storageTest, strNew("pg/pg_wal/000000010000000100000002")), walBuffer2), "write WAL");
TEST_RESULT_VOID(cmdArchivePush(), "push the WAL segment");
harnessLogResult("P00 INFO: pushed WAL file '000000010000000100000002' to the archive");
@ -433,6 +437,18 @@ testRun(void)
TEST_ERROR(cmdArchivePush(), HostInvalidError, "archive-push command must be run on the PostgreSQL host");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("pg1-path must be set when async");
argList = strLstNew();
strLstAddZ(argList, "--" CFGOPT_SPOOL_PATH "=/spool");
strLstAddZ(argList, "--" CFGOPT_STANZA "=test2");
strLstAddZ(argList, "--" CFGOPT_ARCHIVE_ASYNC);
strLstAddZ(argList, "/000000010000000100000001");
harnessCfgLoadRole(cfgCmdArchivePush, cfgCmdRoleAsync, argList);
TEST_ERROR(cmdArchivePush(), OptionRequiredError, "'archive-push' command in async mode requires option 'pg1-path'");
// Call with a bogus exe name so the async process will error out and we can make sure timeouts work
// -------------------------------------------------------------------------------------------------------------------------
argList = strLstNew();