diff --git a/doc/xml/release.xml b/doc/xml/release.xml
index 8d6df37b5..0f24d479f 100644
--- a/doc/xml/release.xml
+++ b/doc/xml/release.xml
@@ -64,6 +64,14 @@
WAL prior to the first full backup was previously expired after the first full backup. Now it is preserved according to retention settings.
+
+
+
+
+
+ Allow pg-path1 to be optional for synchronous archive-push.
+
+
diff --git a/src/command/archive/push/push.c b/src/command/archive/push/push.c
index 60cd4c731..8aa10cdf4 100644
--- a/src/command/archive/push/push.c
+++ b/src/command/archive/push/push.c
@@ -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(
diff --git a/test/src/module/command/archivePushTest.c b/test/src/module/command/archivePushTest.c
index 68177abfd..7e391b887 100644
--- a/test/src/module/command/archivePushTest.c
+++ b/test/src/module/command/archivePushTest.c
@@ -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();