2018-01-17 15:52:00 -05:00
|
|
|
/***********************************************************************************************************************************
|
|
|
|
Test Archive Push Command
|
|
|
|
***********************************************************************************************************************************/
|
2020-08-05 18:25:07 -04:00
|
|
|
#include "common/io/fdRead.h"
|
|
|
|
#include "common/io/fdWrite.h"
|
2019-03-29 13:26:33 +00:00
|
|
|
#include "common/time.h"
|
|
|
|
#include "postgres/version.h"
|
2019-05-03 15:46:15 -04:00
|
|
|
#include "storage/posix/storage.h"
|
2018-09-14 16:08:33 -04:00
|
|
|
|
2018-04-13 16:05:52 -04:00
|
|
|
#include "common/harnessConfig.h"
|
2019-03-29 13:26:33 +00:00
|
|
|
#include "common/harnessFork.h"
|
2019-04-23 14:02:30 -04:00
|
|
|
#include "common/harnessInfo.h"
|
2021-05-17 07:20:28 -04:00
|
|
|
#include "common/harnessPostgres.h"
|
2021-05-25 11:06:05 -04:00
|
|
|
#include "common/harnessProtocol.h"
|
2018-04-13 16:05:52 -04:00
|
|
|
|
2018-01-17 15:52:00 -05:00
|
|
|
/***********************************************************************************************************************************
|
|
|
|
Test Run
|
|
|
|
***********************************************************************************************************************************/
|
2018-01-31 18:22:25 -05:00
|
|
|
void
|
2018-08-03 19:19:14 -04:00
|
|
|
testRun(void)
|
2018-01-17 15:52:00 -05:00
|
|
|
{
|
2018-05-18 11:57:32 -04:00
|
|
|
FUNCTION_HARNESS_VOID();
|
|
|
|
|
2018-05-05 09:38:09 -04:00
|
|
|
// Create default storage object for testing
|
2021-05-22 09:30:54 -04:00
|
|
|
Storage *storageTest = storagePosixNewP(TEST_PATH_STR, .write = true);
|
2018-05-05 09:38:09 -04:00
|
|
|
|
2018-01-17 15:52:00 -05:00
|
|
|
// *****************************************************************************************************************************
|
2019-03-29 13:26:33 +00:00
|
|
|
if (testBegin("archivePushReadyList(), archivePushProcessList(), and archivePushDrop()"))
|
2018-01-17 15:52:00 -05:00
|
|
|
{
|
|
|
|
StringList *argList = strLstNew();
|
|
|
|
strLstAddZ(argList, "--stanza=db");
|
2021-05-22 09:30:54 -04:00
|
|
|
strLstAddZ(argList, "--pg1-path=" TEST_PATH "/db");
|
|
|
|
strLstAddZ(argList, "--spool-path=" TEST_PATH "/spool");
|
2020-01-15 12:24:58 -07:00
|
|
|
strLstAddZ(argList, "--" CFGOPT_ARCHIVE_ASYNC);
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argList, .role = cfgCmdRoleAsync);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2021-05-21 17:36:43 -04:00
|
|
|
storagePathCreateP(storagePgWrite(), STRDEF("pg_wal/archive_status"));
|
|
|
|
storagePathCreateP(storageTest, STRDEF("spool/archive/db/out"));
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
// Create ok files to indicate WAL that has already been archived
|
2019-11-17 15:10:40 -05:00
|
|
|
storagePutP(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageNewWriteP(storageSpoolWrite(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.ok")), NULL);
|
2019-11-17 15:10:40 -05:00
|
|
|
storagePutP(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageNewWriteP(storageSpoolWrite(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000003.ok")), NULL);
|
2019-11-17 15:10:40 -05:00
|
|
|
storagePutP(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageNewWriteP(storageSpoolWrite(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000004.ok")), NULL);
|
2019-11-17 15:10:40 -05:00
|
|
|
storagePutP(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageNewWriteP(storageSpoolWrite(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000005.error")), NULL);
|
2019-11-17 15:10:40 -05:00
|
|
|
storagePutP(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageNewWriteP(storageSpoolWrite(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000006.error")), NULL);
|
2019-11-17 15:10:40 -05:00
|
|
|
storagePutP(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageNewWriteP(storageSpoolWrite(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/global.error")), NULL);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
// Create ready files for wal that still needs to be archived
|
2021-05-21 17:36:43 -04:00
|
|
|
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/archive_status/000000010000000100000002.ready")), NULL);
|
|
|
|
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/archive_status/000000010000000100000003.ready")), NULL);
|
|
|
|
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/archive_status/000000010000000100000005.ready")), NULL);
|
|
|
|
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/archive_status/000000010000000100000006.ready")), NULL);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2021-01-08 12:49:33 -05:00
|
|
|
TEST_RESULT_STRLST_Z(
|
2021-05-22 09:30:54 -04:00
|
|
|
archivePushProcessList(STRDEF(TEST_PATH "/db/pg_wal")),
|
2021-01-08 12:49:33 -05:00
|
|
|
"000000010000000100000002\n000000010000000100000005\n000000010000000100000006\n", "ready list");
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2021-01-08 12:49:33 -05:00
|
|
|
TEST_RESULT_STRLST_Z(
|
2021-05-21 17:36:43 -04:00
|
|
|
strLstSort(storageListP(storageSpool(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT)), sortOrderAsc),
|
2021-01-08 12:49:33 -05:00
|
|
|
"000000010000000100000003.ok\n", "remaining status list");
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
// Test drop
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
StringList *argListDrop = strLstDup(argList);
|
|
|
|
strLstAdd(argListDrop, strNewFmt("--archive-push-queue-max=%zu", (size_t)1024 * 1024 * 1024));
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argListDrop, .role = cfgCmdRoleAsync);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
// Write the files that we claim are in pg_wal
|
|
|
|
Buffer *walBuffer = bufNew((size_t)16 * 1024 * 1024);
|
|
|
|
bufUsedSet(walBuffer, bufSize(walBuffer));
|
|
|
|
memset(bufPtr(walBuffer), 0, bufSize(walBuffer));
|
2021-05-17 07:20:28 -04:00
|
|
|
hrnPgWalToBuffer((PgWal){.version = PG_VERSION_10, .systemId = 0xFACEFACEFACEFACE}, walBuffer);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2021-05-21 17:36:43 -04:00
|
|
|
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/000000010000000100000002")), walBuffer);
|
|
|
|
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/000000010000000100000003")), walBuffer);
|
|
|
|
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/000000010000000100000005")), walBuffer);
|
|
|
|
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/000000010000000100000006")), walBuffer);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
// Queue max is high enough that no WAL will be dropped
|
|
|
|
TEST_RESULT_BOOL(
|
2021-05-22 09:30:54 -04:00
|
|
|
archivePushDrop(STRDEF("pg_wal"), archivePushProcessList(STRDEF(TEST_PATH "/db/pg_wal"))), false,
|
2019-03-29 13:26:33 +00:00
|
|
|
"wal is not dropped");
|
|
|
|
|
|
|
|
// Now set queue max low enough that WAL will be dropped
|
|
|
|
argListDrop = strLstDup(argList);
|
|
|
|
strLstAdd(argListDrop, strNewFmt("--archive-push-queue-max=%zu", (size_t)16 * 1024 * 1024 * 2));
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argListDrop, .role = cfgCmdRoleAsync);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
TEST_RESULT_BOOL(
|
2021-05-22 09:30:54 -04:00
|
|
|
archivePushDrop(STRDEF("pg_wal"), archivePushProcessList(STRDEF(TEST_PATH "/db/pg_wal"))), true,
|
2019-03-29 13:26:33 +00:00
|
|
|
"wal is dropped");
|
|
|
|
}
|
|
|
|
|
|
|
|
// *****************************************************************************************************************************
|
|
|
|
if (testBegin("archivePushCheck()"))
|
|
|
|
{
|
|
|
|
StringList *argList = strLstNew();
|
|
|
|
strLstAddZ(argList, "--stanza=test");
|
2021-05-22 09:30:54 -04:00
|
|
|
strLstAddZ(argList, "--pg1-path=" TEST_PATH "/pg");
|
|
|
|
strLstAddZ(argList, "--repo1-path=" TEST_PATH "/repo");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argList);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
// Check mismatched pg_control and archive.info
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
2019-11-17 15:10:40 -05:00
|
|
|
storagePutP(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageNewWriteP(storageTest, STRDEF("pg/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL)),
|
2021-05-17 07:20:28 -04:00
|
|
|
hrnPgControlToBuffer((PgControl){.version = PG_VERSION_96, .systemId = 0xFACEFACEFACEFACE}));
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
// Create incorrect archive info
|
2019-11-17 15:10:40 -05:00
|
|
|
storagePutP(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageNewWriteP(storageTest, STRDEF("repo/archive/test/archive.info")),
|
2019-04-23 14:02:30 -04:00
|
|
|
harnessInfoChecksumZ(
|
2019-03-29 13:26:33 +00:00
|
|
|
"[db]\n"
|
|
|
|
"db-id=1\n"
|
|
|
|
"\n"
|
|
|
|
"[db:history]\n"
|
|
|
|
"1={\"db-id\":5555555555555555555,\"db-version\":\"9.4\"}\n"));
|
|
|
|
|
|
|
|
TEST_ERROR(
|
2021-03-25 12:54:49 -04:00
|
|
|
archivePushCheck(true), RepoInvalidError,
|
|
|
|
"unable to find a valid repository:\n"
|
|
|
|
"repo1: [ArchiveMismatchError] PostgreSQL version 9.6, system-id 18072658121562454734 do not match repo1 stanza version"
|
|
|
|
" 9.4, system-id 5555555555555555555"
|
2019-03-29 13:26:33 +00:00
|
|
|
"\nHINT: are you archiving to the correct stanza?");
|
|
|
|
|
|
|
|
// Fix the version
|
2019-11-17 15:10:40 -05:00
|
|
|
storagePutP(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageNewWriteP(storageTest, STRDEF("repo/archive/test/archive.info")),
|
2019-04-23 14:02:30 -04:00
|
|
|
harnessInfoChecksumZ(
|
2019-03-29 13:26:33 +00:00
|
|
|
"[db]\n"
|
|
|
|
"db-id=1\n"
|
|
|
|
"\n"
|
|
|
|
"[db:history]\n"
|
|
|
|
"1={\"db-id\":5555555555555555555,\"db-version\":\"9.6\"}\n"));
|
|
|
|
|
|
|
|
TEST_ERROR(
|
2021-03-25 12:54:49 -04:00
|
|
|
archivePushCheck(true), RepoInvalidError,
|
|
|
|
"unable to find a valid repository:\n"
|
|
|
|
"repo1: [ArchiveMismatchError] PostgreSQL version 9.6, system-id 18072658121562454734 do not match repo1 stanza version"
|
|
|
|
" 9.6, system-id 5555555555555555555"
|
2019-03-29 13:26:33 +00:00
|
|
|
"\nHINT: are you archiving to the correct stanza?");
|
|
|
|
|
|
|
|
// Fix archive info
|
2019-11-17 15:10:40 -05:00
|
|
|
storagePutP(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageNewWriteP(storageTest, STRDEF("repo/archive/test/archive.info")),
|
2019-04-23 14:02:30 -04:00
|
|
|
harnessInfoChecksumZ(
|
2019-03-29 13:26:33 +00:00
|
|
|
"[db]\n"
|
|
|
|
"db-id=1\n"
|
|
|
|
"\n"
|
|
|
|
"[db:history]\n"
|
|
|
|
"1={\"db-id\":18072658121562454734,\"db-version\":\"9.6\"}\n"));
|
|
|
|
|
|
|
|
ArchivePushCheckResult result = {0};
|
2021-01-21 15:21:50 -05:00
|
|
|
TEST_ASSIGN(result, archivePushCheck(true), "get archive check result");
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
TEST_RESULT_UINT(result.pgVersion, PG_VERSION_96, "check pg version");
|
|
|
|
TEST_RESULT_UINT(result.pgSystemId, 0xFACEFACEFACEFACE, "check pg system id");
|
2021-03-25 12:54:49 -04:00
|
|
|
|
|
|
|
ArchivePushFileRepoData *repoData = lstGet(result.repoList, 0);
|
|
|
|
TEST_RESULT_UINT(repoData->repoIdx, 0, "check repo idx");
|
|
|
|
TEST_RESULT_STR_Z(repoData->archiveId, "9.6-1", "check archive id");
|
|
|
|
TEST_RESULT_UINT(repoData->cipherType, cipherTypeNone, "check cipher type");
|
|
|
|
TEST_RESULT_STR_Z(repoData->cipherPass, NULL, "check cipher pass (not set in this test)");
|
2021-01-21 15:21:50 -05:00
|
|
|
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
TEST_TITLE("mismatched repos when pg-path not present");
|
|
|
|
|
|
|
|
argList = strLstNew();
|
|
|
|
strLstAddZ(argList, "--stanza=test");
|
2021-05-22 09:30:54 -04:00
|
|
|
strLstAddZ(argList, "--repo2-path=" TEST_PATH "/repo2");
|
|
|
|
strLstAddZ(argList, "--repo4-path=" TEST_PATH "/repo4");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argList);
|
2021-01-21 15:21:50 -05:00
|
|
|
|
|
|
|
// repo2 has correct info
|
|
|
|
storagePutP(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageNewWriteP(storageTest, STRDEF("repo2/archive/test/archive.info")),
|
2021-01-21 15:21:50 -05:00
|
|
|
harnessInfoChecksumZ(
|
|
|
|
"[db]\n"
|
|
|
|
"db-id=1\n"
|
|
|
|
"\n"
|
|
|
|
"[db:history]\n"
|
|
|
|
"1={\"db-id\":18072658121562454734,\"db-version\":\"9.6\"}\n"));
|
|
|
|
|
|
|
|
// repo4 has incorrect info
|
|
|
|
storagePutP(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageNewWriteP(storageTest, STRDEF("repo4/archive/test/archive.info")),
|
2021-01-21 15:21:50 -05:00
|
|
|
harnessInfoChecksumZ(
|
|
|
|
"[db]\n"
|
|
|
|
"db-id=1\n"
|
|
|
|
"\n"
|
|
|
|
"[db:history]\n"
|
|
|
|
"1={\"db-id\":5555555555555555555,\"db-version\":\"9.4\"}\n"));
|
|
|
|
|
2021-03-25 12:54:49 -04:00
|
|
|
TEST_ASSIGN(result, archivePushCheck(false), "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");
|
|
|
|
TEST_RESULT_STRLST_Z(
|
|
|
|
result.errorList,
|
|
|
|
"repo4: [ArchiveMismatchError] repo2 stanza version 9.6, system-id 18072658121562454734 do not match repo4 stanza"
|
|
|
|
" version 9.4, system-id 5555555555555555555\n"
|
|
|
|
"HINT: are you archiving to the correct stanza?\n",
|
|
|
|
"check error list");
|
|
|
|
|
|
|
|
repoData = lstGet(result.repoList, 0);
|
|
|
|
TEST_RESULT_UINT(repoData->repoIdx, 0, "check repo idx");
|
|
|
|
TEST_RESULT_STR_Z(repoData->archiveId, "9.6-1", "check archive id");
|
|
|
|
TEST_RESULT_UINT(repoData->cipherType, cipherTypeNone, "check cipher type");
|
|
|
|
TEST_RESULT_STR_Z(repoData->cipherPass, NULL, "check cipher pass (not set in this test)");
|
2021-01-21 15:21:50 -05:00
|
|
|
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
TEST_TITLE("matched repos when pg-path not present");
|
|
|
|
|
|
|
|
// repo4 has correct info
|
|
|
|
storagePutP(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageNewWriteP(storageTest, STRDEF("repo4/archive/test/archive.info")),
|
2021-01-21 15:21:50 -05:00
|
|
|
harnessInfoChecksumZ(
|
|
|
|
"[db]\n"
|
|
|
|
"db-id=2\n"
|
|
|
|
"\n"
|
|
|
|
"[db:history]\n"
|
|
|
|
"1={\"db-id\":5555555555555555555,\"db-version\":\"9.4\"}\n"
|
|
|
|
"2={\"db-id\":18072658121562454734,\"db-version\":\"9.6\"}\n"));
|
|
|
|
|
|
|
|
TEST_ASSIGN(result, archivePushCheck(false), "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");
|
2021-03-25 12:54:49 -04:00
|
|
|
|
|
|
|
repoData = lstGet(result.repoList, 0);
|
|
|
|
TEST_RESULT_UINT(repoData->repoIdx, 0, "check repo idx");
|
|
|
|
TEST_RESULT_STR_Z(repoData->archiveId, "9.6-1", "check repo2 archive id");
|
|
|
|
TEST_RESULT_UINT(repoData->cipherType, cipherTypeNone, "check repo2 cipher pass");
|
|
|
|
TEST_RESULT_STR_Z(repoData->cipherPass, NULL, "check repo2 cipher pass (not set in this test)");
|
|
|
|
|
|
|
|
repoData = lstGet(result.repoList, 1);
|
|
|
|
TEST_RESULT_UINT(repoData->repoIdx, 1, "check repo idx");
|
|
|
|
TEST_RESULT_STR_Z(repoData->archiveId, "9.6-2", "check repo4 archive id");
|
|
|
|
TEST_RESULT_UINT(repoData->cipherType, cipherTypeNone, "check repo4 cipher type");
|
|
|
|
TEST_RESULT_STR_Z(repoData->cipherPass, NULL, "check repo4 cipher pass (not set in this test)");
|
2019-03-29 13:26:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// *****************************************************************************************************************************
|
2021-05-25 11:06:05 -04:00
|
|
|
if (testBegin("Synchronous cmdArchivePush() and archivePushFile()"))
|
2019-03-29 13:26:33 +00:00
|
|
|
{
|
2020-02-12 17:18:48 -07:00
|
|
|
TEST_TITLE("command must be run on the pg host");
|
|
|
|
|
2019-03-29 13:26:33 +00:00
|
|
|
StringList *argList = strLstNew();
|
2020-10-19 14:03:48 -04:00
|
|
|
hrnCfgArgRawZ(argList, cfgOptPgHost, "host");
|
|
|
|
hrnCfgArgRawZ(argList, cfgOptPgPath, "/pg");
|
2020-02-12 17:18:48 -07:00
|
|
|
strLstAddZ(argList, "--" CFGOPT_STANZA "=test2");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argList, .role = cfgCmdRoleMain);
|
2020-02-12 17:18:48 -07:00
|
|
|
|
|
|
|
TEST_ERROR(cmdArchivePush(), HostInvalidError, "archive-push command must be run on the PostgreSQL host");
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
argList = strLstNew();
|
2019-03-29 13:26:33 +00:00
|
|
|
strLstAddZ(argList, "--stanza=test");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argList);
|
2018-01-17 15:52:00 -05:00
|
|
|
|
|
|
|
TEST_ERROR(cmdArchivePush(), ParamRequiredError, "WAL segment to push required");
|
|
|
|
|
2019-12-11 14:36:39 -05:00
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
StringList *argListTemp = strLstDup(argList);
|
|
|
|
strLstAddZ(argListTemp, "pg_wal/000000010000000100000001");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp);
|
2019-12-11 14:36:39 -05:00
|
|
|
|
|
|
|
TEST_ERROR(
|
|
|
|
cmdArchivePush(), OptionRequiredError,
|
|
|
|
"option 'pg1-path' must be specified when relative wal paths are used"
|
|
|
|
"\nHINT: is %f passed to archive-push instead of %p?"
|
|
|
|
"\nHINT: PostgreSQL may pass relative paths even with %p depending on the environment.");
|
|
|
|
|
2019-03-29 13:26:33 +00:00
|
|
|
// Create pg_control and archive.info
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
2021-05-22 09:30:54 -04:00
|
|
|
strLstAddZ(argList, "--pg1-path=" TEST_PATH "/pg");
|
|
|
|
strLstAddZ(argList, "--repo1-path=" TEST_PATH "/repo");
|
2018-01-17 15:52:00 -05:00
|
|
|
|
2019-12-11 14:36:39 -05:00
|
|
|
argListTemp = strLstDup(argList);
|
2019-03-29 13:26:33 +00:00
|
|
|
strLstAddZ(argListTemp, "pg_wal/000000010000000100000001");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp);
|
2018-01-17 15:52:00 -05:00
|
|
|
|
2019-11-17 15:10:40 -05:00
|
|
|
storagePutP(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageNewWriteP(storageTest, STRDEF("pg/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL)),
|
2021-05-17 07:20:28 -04:00
|
|
|
hrnPgControlToBuffer((PgControl){.version = PG_VERSION_11, .systemId = 0xFACEFACEFACEFACE}));
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2019-11-17 15:10:40 -05:00
|
|
|
storagePutP(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageNewWriteP(storageTest, STRDEF("repo/archive/test/archive.info")),
|
2019-04-23 14:02:30 -04:00
|
|
|
harnessInfoChecksumZ(
|
2019-03-29 13:26:33 +00:00
|
|
|
"[db]\n"
|
|
|
|
"db-id=1\n"
|
|
|
|
"\n"
|
|
|
|
"[db:history]\n"
|
|
|
|
"1={\"db-id\":18072658121562454734,\"db-version\":\"11\"}\n"));
|
|
|
|
|
|
|
|
// Generate WAL with incorrect headers and try to push them
|
2018-01-17 15:52:00 -05:00
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
2019-03-29 13:26:33 +00:00
|
|
|
Buffer *walBuffer1 = bufNew((size_t)16 * 1024 * 1024);
|
|
|
|
bufUsedSet(walBuffer1, bufSize(walBuffer1));
|
|
|
|
memset(bufPtr(walBuffer1), 0, bufSize(walBuffer1));
|
2021-05-17 07:20:28 -04:00
|
|
|
hrnPgWalToBuffer((PgWal){.version = PG_VERSION_10, .systemId = 0xFACEFACEFACEFACE}, walBuffer1);
|
2018-05-05 09:38:09 -04:00
|
|
|
|
2021-05-21 17:36:43 -04:00
|
|
|
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/000000010000000100000001")), walBuffer1);
|
2018-01-17 15:52:00 -05:00
|
|
|
|
2020-07-30 07:49:06 -04:00
|
|
|
THROW_ON_SYS_ERROR(chdir(strZ(cfgOptionStr(cfgOptPgPath))) != 0, PathMissingError, "unable to chdir()");
|
2019-10-30 14:55:25 +01:00
|
|
|
|
2018-04-12 20:42:26 -04:00
|
|
|
TEST_ERROR(
|
2019-03-29 13:26:33 +00:00
|
|
|
cmdArchivePush(), ArchiveMismatchError,
|
2021-05-22 09:30:54 -04:00
|
|
|
"WAL file '" TEST_PATH "/pg/pg_wal/000000010000000100000001' version 10, system-id 18072658121562454734 do not match"
|
2021-03-23 18:20:26 -04:00
|
|
|
" stanza version 11, system-id 18072658121562454734");
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
memset(bufPtr(walBuffer1), 0, bufSize(walBuffer1));
|
2021-05-17 07:20:28 -04:00
|
|
|
hrnPgWalToBuffer((PgWal){.version = PG_VERSION_11, .systemId = 0xECAFECAFECAFECAF}, walBuffer1);
|
2021-03-25 15:33:50 -04:00
|
|
|
const char *walBuffer1Sha1 = strZ(bufHex(cryptoHashOne(HASH_TYPE_SHA1_STR, walBuffer1)));
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2021-05-21 17:36:43 -04:00
|
|
|
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/000000010000000100000001")), walBuffer1);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
TEST_ERROR(
|
|
|
|
cmdArchivePush(), ArchiveMismatchError,
|
2021-05-22 09:30:54 -04:00
|
|
|
"WAL file '" TEST_PATH "/pg/pg_wal/000000010000000100000001' version 11, system-id 17055110554209741999 do not match"
|
2021-03-23 18:20:26 -04:00
|
|
|
" stanza version 11, system-id 18072658121562454734");
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2021-03-25 15:33:50 -04:00
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
TEST_TITLE("push by ignoring the invalid header");
|
|
|
|
|
|
|
|
argListTemp = strLstDup(argList);
|
|
|
|
hrnCfgArgRawNegate(argListTemp, cfgOptArchiveHeaderCheck);
|
|
|
|
strLstAddZ(argListTemp, "pg_wal/000000010000000100000001");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp);
|
2021-03-25 15:33:50 -04:00
|
|
|
|
|
|
|
TEST_RESULT_VOID(cmdArchivePush(), "push the WAL segment");
|
2021-05-22 14:09:45 -04:00
|
|
|
TEST_RESULT_LOG("P00 INFO: pushed WAL file '000000010000000100000001' to the archive");
|
2021-03-25 15:33:50 -04:00
|
|
|
|
|
|
|
TEST_RESULT_BOOL(
|
|
|
|
storageExistsP(
|
|
|
|
storageRepoIdx(0),
|
|
|
|
strNewFmt(STORAGE_REPO_ARCHIVE "/11-1/000000010000000100000001-%s.gz", walBuffer1Sha1)),
|
|
|
|
true, "check repo for WAL file");
|
|
|
|
TEST_STORAGE_REMOVE(
|
|
|
|
storageRepoIdxWrite(0), strZ(strNewFmt(STORAGE_REPO_ARCHIVE "/11-1/000000010000000100000001-%s.gz", walBuffer1Sha1)));
|
|
|
|
|
2019-03-29 13:26:33 +00:00
|
|
|
// Generate valid WAL and push them
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
2021-03-25 15:33:50 -04:00
|
|
|
argListTemp = strLstDup(argList);
|
|
|
|
strLstAddZ(argListTemp, "pg_wal/000000010000000100000001");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp);
|
2021-03-25 15:33:50 -04:00
|
|
|
|
2019-03-29 13:26:33 +00:00
|
|
|
memset(bufPtr(walBuffer1), 0, bufSize(walBuffer1));
|
2021-05-17 07:20:28 -04:00
|
|
|
hrnPgWalToBuffer((PgWal){.version = PG_VERSION_11, .systemId = 0xFACEFACEFACEFACE}, walBuffer1);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2020-07-20 09:47:43 -04:00
|
|
|
// Check sha1 checksum against fixed values once to make sure they are not getting munged. After this we'll calculate them
|
|
|
|
// directly from the buffers to reduce the cost of maintaining checksums.
|
2021-03-25 15:33:50 -04:00
|
|
|
walBuffer1Sha1 = TEST_64BIT() ?
|
2020-07-20 09:59:16 -04:00
|
|
|
(TEST_BIG_ENDIAN() ? "1c5f963d720bb199d7935dbd315447ea2ec3feb2" : "aae7591a1dbc58f21d0d004886075094f622e6dd") :
|
|
|
|
"28a13fd8cf6fcd9f9a8108aed4c8bcc58040863a";
|
2020-07-20 09:47:43 -04:00
|
|
|
|
2021-05-21 17:36:43 -04:00
|
|
|
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/000000010000000100000001")), walBuffer1);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
TEST_RESULT_VOID(cmdArchivePush(), "push the WAL segment");
|
2021-05-22 14:09:45 -04:00
|
|
|
TEST_RESULT_LOG("P00 INFO: pushed WAL file '000000010000000100000001' to the archive");
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
TEST_RESULT_BOOL(
|
2019-11-17 15:10:40 -05:00
|
|
|
storageExistsP(
|
2020-07-20 09:47:43 -04:00
|
|
|
storageTest, strNewFmt("repo/archive/test/11-1/0000000100000001/000000010000000100000001-%s.gz", walBuffer1Sha1)),
|
2019-03-29 13:26:33 +00:00
|
|
|
true, "check repo for WAL file");
|
|
|
|
|
|
|
|
TEST_RESULT_VOID(cmdArchivePush(), "push the WAL segment again");
|
2021-05-22 14:09:45 -04:00
|
|
|
TEST_RESULT_LOG(
|
2021-01-21 15:21:50 -05:00
|
|
|
"P00 WARN: WAL file '000000010000000100000001' already exists in the repo1 archive with the same checksum\n"
|
2019-03-29 13:26:33 +00:00
|
|
|
" HINT: this is valid in some recovery scenarios but may also indicate a problem.\n"
|
|
|
|
"P00 INFO: pushed WAL file '000000010000000100000001' to the archive");
|
|
|
|
|
|
|
|
// Now create a new WAL buffer with a different checksum to test checksum errors
|
|
|
|
Buffer *walBuffer2 = bufNew((size_t)16 * 1024 * 1024);
|
|
|
|
bufUsedSet(walBuffer2, bufSize(walBuffer2));
|
|
|
|
memset(bufPtr(walBuffer2), 0xFF, bufSize(walBuffer2));
|
2021-05-17 07:20:28 -04:00
|
|
|
hrnPgWalToBuffer((PgWal){.version = PG_VERSION_11, .systemId = 0xFACEFACEFACEFACE}, walBuffer2);
|
2020-07-30 07:49:06 -04:00
|
|
|
const char *walBuffer2Sha1 = strZ(bufHex(cryptoHashOne(HASH_TYPE_SHA1_STR, walBuffer2)));
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2021-05-21 17:36:43 -04:00
|
|
|
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/000000010000000100000001")), walBuffer2);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2021-01-21 15:21:50 -05:00
|
|
|
TEST_ERROR(
|
|
|
|
cmdArchivePush(), ArchiveDuplicateError,
|
|
|
|
"WAL file '000000010000000100000001' already exists in the repo1 archive with a different checksum");
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2020-05-01 10:30:35 -04:00
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
TEST_TITLE("WAL with absolute path and no pg1-path");
|
|
|
|
|
|
|
|
argListTemp = strLstNew();
|
|
|
|
strLstAddZ(argListTemp, "--" CFGOPT_STANZA "=test");
|
2021-05-22 09:30:54 -04:00
|
|
|
hrnCfgArgRawZ(argListTemp, cfgOptRepoPath, TEST_PATH "/repo");
|
|
|
|
strLstAddZ(argListTemp, TEST_PATH "/pg/pg_wal/000000010000000100000002");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2020-07-14 15:05:31 -04:00
|
|
|
TEST_RESULT_VOID(
|
2021-05-21 17:36:43 -04:00
|
|
|
storagePutP(storageNewWriteP(storageTest, STRDEF("pg/pg_wal/000000010000000100000002")), walBuffer2), "write WAL");
|
2020-07-14 15:05:31 -04:00
|
|
|
|
|
|
|
// Create tmp file to make it look like a prior push failed partway through to ensure that retries work
|
|
|
|
TEST_RESULT_VOID(
|
|
|
|
storagePutP(
|
|
|
|
storageNewWriteP(
|
|
|
|
storageTest,
|
2020-07-20 09:47:43 -04:00
|
|
|
strNewFmt("repo/archive/test/11-1/0000000100000001/000000010000000100000002-%s.gz.pgbackrest.tmp",
|
|
|
|
walBuffer2Sha1)),
|
2020-07-14 15:05:31 -04:00
|
|
|
BUFSTRDEF("PARTIAL")),
|
|
|
|
"write WAL tmp file");
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
TEST_RESULT_VOID(cmdArchivePush(), "push the WAL segment");
|
2021-05-22 14:09:45 -04:00
|
|
|
TEST_RESULT_LOG("P00 INFO: pushed WAL file '000000010000000100000002' to the archive");
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2020-07-14 15:05:31 -04:00
|
|
|
TEST_RESULT_BOOL(
|
2020-07-20 09:47:43 -04:00
|
|
|
storageExistsP(
|
|
|
|
storageTest, strNewFmt("repo/archive/test/11-1/0000000100000001/000000010000000100000002-%s.gz", walBuffer2Sha1)),
|
2020-07-14 15:05:31 -04:00
|
|
|
true, "check repo for WAL file");
|
2019-03-29 13:26:33 +00:00
|
|
|
TEST_RESULT_BOOL(
|
2019-11-17 15:10:40 -05:00
|
|
|
storageExistsP(
|
2019-03-29 13:26:33 +00:00
|
|
|
storageTest,
|
2020-07-20 09:47:43 -04:00
|
|
|
strNewFmt("repo/archive/test/11-1/0000000100000001/000000010000000100000002-%s.gz.pgbackrest.tmp", walBuffer2Sha1)),
|
2020-07-14 15:05:31 -04:00
|
|
|
false, "check WAL tmp file is gone");
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
// Push a history file
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
argListTemp = strLstDup(argList);
|
|
|
|
strLstAddZ(argListTemp, "pg_wal/00000001.history");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2021-05-21 17:36:43 -04:00
|
|
|
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/00000001.history")), BUFSTRDEF("FAKEHISTORY"));
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
TEST_RESULT_VOID(cmdArchivePush(), "push a history file");
|
2021-05-22 14:09:45 -04:00
|
|
|
TEST_RESULT_LOG("P00 INFO: pushed WAL file '00000001.history' to the archive");
|
2018-01-17 15:52:00 -05:00
|
|
|
|
2019-03-29 13:26:33 +00:00
|
|
|
TEST_RESULT_BOOL(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageExistsP(storageTest, STRDEF("repo/archive/test/11-1/00000001.history")), true, "check repo for history file");
|
2018-01-17 15:52:00 -05:00
|
|
|
|
2019-03-29 13:26:33 +00:00
|
|
|
// Check drop functionality
|
2018-01-17 15:52:00 -05:00
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
2021-05-21 17:36:43 -04:00
|
|
|
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/archive_status/000000010000000100000001.ready")), NULL);
|
|
|
|
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/archive_status/000000010000000100000002.ready")), NULL);
|
2018-01-17 15:52:00 -05:00
|
|
|
|
2019-03-29 13:26:33 +00:00
|
|
|
argListTemp = strLstDup(argList);
|
|
|
|
strLstAddZ(argListTemp, "--archive-push-queue-max=16m");
|
|
|
|
strLstAddZ(argListTemp, "pg_wal/000000010000000100000002");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp);
|
2018-01-17 15:52:00 -05:00
|
|
|
|
2019-03-29 13:26:33 +00:00
|
|
|
TEST_RESULT_VOID(cmdArchivePush(), "drop WAL file");
|
2021-05-22 14:09:45 -04:00
|
|
|
TEST_RESULT_LOG("P00 WARN: dropped WAL file '000000010000000100000002' because archive queue exceeded 16MB");
|
2018-01-17 15:52:00 -05:00
|
|
|
|
2019-03-29 13:26:33 +00:00
|
|
|
argListTemp = strLstDup(argList);
|
|
|
|
strLstAddZ(argListTemp, "--archive-push-queue-max=1GB");
|
|
|
|
strLstAddZ(argListTemp, "pg_wal/000000010000000100000002");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp);
|
2018-01-17 15:52:00 -05:00
|
|
|
|
2019-03-29 13:26:33 +00:00
|
|
|
TEST_RESULT_VOID(cmdArchivePush(), "push WAL file again");
|
2021-05-22 14:09:45 -04:00
|
|
|
TEST_RESULT_LOG(
|
2021-01-21 15:21:50 -05:00
|
|
|
"P00 WARN: WAL file '000000010000000100000002' already exists in the repo1 archive with the same checksum\n"
|
2019-03-29 13:26:33 +00:00
|
|
|
" HINT: this is valid in some recovery scenarios but may also indicate a problem.\n"
|
|
|
|
"P00 INFO: pushed WAL file '000000010000000100000002' to the archive");
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
2021-01-21 15:21:50 -05:00
|
|
|
TEST_TITLE("multiple repos, one encrypted");
|
|
|
|
|
|
|
|
// Remove old repo
|
2021-06-02 11:46:54 -04:00
|
|
|
HRN_STORAGE_PATH_REMOVE(storageTest, "repo", .errorOnMissing = true, .recurse = true);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2021-01-21 15:21:50 -05:00
|
|
|
// repo2 is encrypted
|
2021-05-21 17:36:43 -04:00
|
|
|
StorageWrite *infoWrite = storageNewWriteP(storageTest, STRDEF("repo2/archive/test/archive.info"));
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2019-06-24 10:20:47 -04:00
|
|
|
ioFilterGroupAdd(
|
|
|
|
ioWriteFilterGroup(storageWriteIo(infoWrite)), cipherBlockNew(cipherModeEncrypt, cipherTypeAes256Cbc,
|
|
|
|
BUFSTRDEF("badpassphrase"), NULL));
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2019-11-17 15:10:40 -05:00
|
|
|
storagePutP(
|
2019-03-29 13:26:33 +00:00
|
|
|
infoWrite,
|
2019-04-23 14:02:30 -04:00
|
|
|
harnessInfoChecksumZ(
|
2019-03-29 13:26:33 +00:00
|
|
|
"[cipher]\n"
|
|
|
|
"cipher-pass=\"badsubpassphrase\"\n"
|
|
|
|
"\n"
|
|
|
|
"[db]\n"
|
|
|
|
"db-id=1\n"
|
|
|
|
"\n"
|
|
|
|
"[db:history]\n"
|
|
|
|
"1={\"db-id\":18072658121562454734,\"db-version\":\"11\"}"));
|
|
|
|
|
2021-01-21 15:21:50 -05:00
|
|
|
// repo3 is not encrypted
|
|
|
|
storagePutP(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageNewWriteP(storageTest, STRDEF("repo3/archive/test/archive.info")),
|
2021-01-21 15:21:50 -05:00
|
|
|
harnessInfoChecksumZ(
|
|
|
|
"[db]\n"
|
|
|
|
"db-id=1\n"
|
|
|
|
"\n"
|
|
|
|
"[db:history]\n"
|
|
|
|
"1={\"db-id\":18072658121562454734,\"db-version\":\"11\"}"));
|
|
|
|
|
2019-03-29 13:26:33 +00:00
|
|
|
// Push encrypted WAL segment
|
2021-01-21 15:21:50 -05:00
|
|
|
argListTemp = strLstNew();
|
|
|
|
hrnCfgArgRawZ(argListTemp, cfgOptStanza, "test");
|
2021-05-22 09:30:54 -04:00
|
|
|
hrnCfgArgKeyRawZ(argListTemp, cfgOptPgPath, 1, TEST_PATH "/pg");
|
|
|
|
hrnCfgArgKeyRawZ(argListTemp, cfgOptRepoPath, 2, TEST_PATH "/repo2");
|
2021-04-28 11:36:20 -04:00
|
|
|
hrnCfgArgKeyRawStrId(argListTemp, cfgOptRepoCipherType, 2, cipherTypeAes256Cbc);
|
2021-01-21 15:21:50 -05:00
|
|
|
hrnCfgEnvKeyRawZ(cfgOptRepoCipherPass, 2, "badpassphrase");
|
2021-05-22 09:30:54 -04:00
|
|
|
hrnCfgArgKeyRawZ(argListTemp, cfgOptRepoPath, 3, TEST_PATH "/repo3");
|
2021-01-21 15:21:50 -05:00
|
|
|
hrnCfgArgRawNegate(argListTemp, cfgOptCompress);
|
2019-03-29 13:26:33 +00:00
|
|
|
strLstAddZ(argListTemp, "pg_wal/000000010000000100000002");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp);
|
2021-01-21 15:21:50 -05:00
|
|
|
hrnCfgEnvKeyRemoveRaw(cfgOptRepoCipherPass, 2);
|
2018-01-17 15:52:00 -05:00
|
|
|
|
2019-03-29 13:26:33 +00:00
|
|
|
TEST_RESULT_VOID(cmdArchivePush(), "push the WAL segment");
|
2021-05-22 14:09:45 -04:00
|
|
|
TEST_RESULT_LOG("P00 INFO: pushed WAL file '000000010000000100000002' to the archive");
|
2018-05-05 09:38:09 -04:00
|
|
|
|
2019-03-29 13:26:33 +00:00
|
|
|
TEST_RESULT_BOOL(
|
2019-11-17 15:10:40 -05:00
|
|
|
storageExistsP(
|
2021-01-21 15:21:50 -05:00
|
|
|
storageTest, strNewFmt("repo2/archive/test/11-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1)),
|
|
|
|
true, "check repo2 for WAL file");
|
|
|
|
|
|
|
|
TEST_RESULT_BOOL(
|
|
|
|
storageExistsP(
|
|
|
|
storageTest, strNewFmt("repo3/archive/test/11-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1)),
|
|
|
|
true, "check repo3 for WAL file");
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
2021-02-26 16:52:59 -05:00
|
|
|
TEST_TITLE("write error on one repo but other repo succeeds");
|
2021-01-21 15:21:50 -05:00
|
|
|
|
|
|
|
storageRemoveP(
|
|
|
|
storageTest, strNewFmt("repo2/archive/test/11-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1),
|
|
|
|
.errorOnMissing = true);
|
2021-02-26 16:52:59 -05:00
|
|
|
storageRemoveP(
|
|
|
|
storageTest, strNewFmt("repo3/archive/test/11-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1),
|
|
|
|
.errorOnMissing = true);
|
|
|
|
|
|
|
|
HRN_STORAGE_MODE(storageTest, "repo2/archive/test/11-1/0000000100000001", .mode = 0500);
|
|
|
|
|
|
|
|
TEST_ERROR(
|
|
|
|
cmdArchivePush(), CommandError,
|
|
|
|
strZ(
|
|
|
|
strNewFmt(
|
|
|
|
"archive-push command encountered error(s):\n"
|
2021-05-22 09:30:54 -04:00
|
|
|
"repo2: [FileOpenError] unable to open file '" TEST_PATH "/repo2/archive/test/11-1/0000000100000001"
|
2021-02-26 16:52:59 -05:00
|
|
|
"/000000010000000100000002-%s' for write: [13] Permission denied", walBuffer2Sha1)));
|
|
|
|
|
|
|
|
TEST_RESULT_BOOL(
|
|
|
|
storageExistsP(
|
|
|
|
storageTest, strNewFmt("repo2/archive/test/11-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1)),
|
|
|
|
false, "check repo2 for no WAL file");
|
|
|
|
TEST_RESULT_BOOL(
|
|
|
|
storageExistsP(
|
|
|
|
storageTest, strNewFmt("repo3/archive/test/11-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1)),
|
|
|
|
true, "check repo3 for WAL file");
|
|
|
|
|
|
|
|
HRN_STORAGE_MODE(storageTest, "repo2/archive/test/11-1/0000000100000001");
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
TEST_TITLE("push WAL to one repo");
|
2021-01-21 15:21:50 -05:00
|
|
|
|
|
|
|
TEST_RESULT_VOID(cmdArchivePush(), "push the WAL segment");
|
2021-05-22 14:09:45 -04:00
|
|
|
TEST_RESULT_LOG(
|
2021-01-21 15:21:50 -05:00
|
|
|
"P00 WARN: WAL file '000000010000000100000002' already exists in the repo3 archive with the same checksum\n"
|
|
|
|
" HINT: this is valid in some recovery scenarios but may also indicate a problem.\n"
|
|
|
|
"P00 INFO: pushed WAL file '000000010000000100000002' to the archive");
|
|
|
|
|
|
|
|
TEST_RESULT_BOOL(
|
|
|
|
storageExistsP(
|
|
|
|
storageTest, strNewFmt("repo2/archive/test/11-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1)),
|
|
|
|
true, "check repo2 for WAL file");
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
TEST_TITLE("WAL already exists in both repos");
|
|
|
|
|
|
|
|
TEST_RESULT_VOID(cmdArchivePush(), "push the WAL segment");
|
2021-05-22 14:09:45 -04:00
|
|
|
TEST_RESULT_LOG(
|
2021-01-21 15:21:50 -05:00
|
|
|
"P00 WARN: WAL file '000000010000000100000002' already exists in the repo2 archive with the same checksum\n"
|
|
|
|
" HINT: this is valid in some recovery scenarios but may also indicate a problem.\n"
|
2021-02-26 15:58:11 -05:00
|
|
|
"P00 WARN: WAL file '000000010000000100000002' already exists in the repo3 archive with the same checksum\n"
|
2021-01-21 15:21:50 -05:00
|
|
|
" HINT: this is valid in some recovery scenarios but may also indicate a problem.\n"
|
|
|
|
"P00 INFO: pushed WAL file '000000010000000100000002' to the archive");
|
2021-03-25 12:54:49 -04:00
|
|
|
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
TEST_TITLE("push succeeds on one repo when other repo fails to load archive.info");
|
|
|
|
|
|
|
|
TEST_STORAGE_REMOVE(
|
|
|
|
storageTest, strZ(strNewFmt("repo2/archive/test/11-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1)));
|
|
|
|
TEST_STORAGE_REMOVE(
|
|
|
|
storageTest, strZ(strNewFmt("repo3/archive/test/11-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1)));
|
|
|
|
HRN_STORAGE_MODE(storageTest, "repo2", .mode = 0200);
|
|
|
|
|
|
|
|
TEST_ERROR(
|
|
|
|
cmdArchivePush(), CommandError,
|
|
|
|
"archive-push command encountered error(s):\n"
|
2021-05-22 09:30:54 -04:00
|
|
|
"repo2: [FileOpenError] unable to load info file '" TEST_PATH "/repo2/archive/test/archive.info' or"
|
|
|
|
" '" TEST_PATH "/repo2/archive/test/archive.info.copy':\n"
|
|
|
|
"FileOpenError: unable to open file '" TEST_PATH "/repo2/archive/test/archive.info' for read: [13] Permission denied\n"
|
|
|
|
"FileOpenError: unable to open file '" TEST_PATH "/repo2/archive/test/archive.info.copy' for read:"
|
|
|
|
" [13] Permission denied\n"
|
2021-03-25 12:54:49 -04:00
|
|
|
"HINT: archive.info cannot be opened but is required to push/get WAL segments.\n"
|
|
|
|
"HINT: is archive_command configured correctly in postgresql.conf?\n"
|
|
|
|
"HINT: has a stanza-create been performed?\n"
|
|
|
|
"HINT: use --no-archive-check to disable archive checks during backup if you have an alternate archiving scheme.");
|
|
|
|
|
|
|
|
// Make sure WAL got pushed to repo3
|
|
|
|
TEST_STORAGE_REMOVE(
|
|
|
|
storageTest, strZ(strNewFmt("repo3/archive/test/11-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1)));
|
|
|
|
|
|
|
|
HRN_STORAGE_MODE(storageTest, "repo2");
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
TEST_TITLE("push succeeds on one repo when other repo fails to read path");
|
|
|
|
|
|
|
|
HRN_STORAGE_MODE(storageTest, "repo2/archive/test/11-1", .mode = 0200);
|
|
|
|
|
|
|
|
TEST_ERROR(
|
|
|
|
cmdArchivePush(), CommandError,
|
|
|
|
"archive-push command encountered error(s):\n"
|
2021-05-22 09:30:54 -04:00
|
|
|
"repo2: [PathOpenError] unable to list file info for path '" TEST_PATH "/repo2/archive/test/11-1/0000000100000001':"
|
|
|
|
" [13] Permission denied");
|
2021-03-25 12:54:49 -04:00
|
|
|
|
|
|
|
// Make sure WAL got pushed to repo3
|
|
|
|
TEST_STORAGE_REMOVE(
|
|
|
|
storageTest, strZ(strNewFmt("repo3/archive/test/11-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1)));
|
|
|
|
|
|
|
|
HRN_STORAGE_MODE(storageTest, "repo2/archive/test/11-1");
|
2019-03-29 13:26:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// *****************************************************************************************************************************
|
|
|
|
if (testBegin("Asynchronous cmdArchivePush() and cmdArchivePushAsync()"))
|
|
|
|
{
|
|
|
|
harnessLogLevelSet(logLevelDetail);
|
2018-05-05 09:38:09 -04:00
|
|
|
|
2021-05-25 11:06:05 -04:00
|
|
|
// Install local command handler shim
|
|
|
|
static const ProtocolServerHandler testLocalHandlerList[] = {PROTOCOL_SERVER_HANDLER_ARCHIVE_PUSH_LIST};
|
|
|
|
hrnProtocolLocalShimInstall(testLocalHandlerList, PROTOCOL_SERVER_HANDLER_LIST_SIZE(testLocalHandlerList));
|
|
|
|
|
2020-02-12 17:18:48 -07:00
|
|
|
TEST_TITLE("command must be run on the pg host");
|
|
|
|
|
|
|
|
StringList *argList = strLstNew();
|
2020-10-19 14:03:48 -04:00
|
|
|
hrnCfgArgRawZ(argList, cfgOptPgHost, "host");
|
|
|
|
hrnCfgArgRawZ(argList, cfgOptPgPath, "/pg");
|
2020-02-12 17:18:48 -07:00
|
|
|
strLstAddZ(argList, "--" CFGOPT_SPOOL_PATH "=/spool");
|
|
|
|
strLstAddZ(argList, "--" CFGOPT_STANZA "=test2");
|
|
|
|
strLstAddZ(argList, "--" CFGOPT_ARCHIVE_ASYNC);
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argList, .role = cfgCmdRoleAsync);
|
2020-02-12 17:18:48 -07:00
|
|
|
|
|
|
|
TEST_ERROR(cmdArchivePush(), HostInvalidError, "archive-push command must be run on the PostgreSQL host");
|
|
|
|
|
2020-05-01 10:30:35 -04:00
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
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");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argList, .role = cfgCmdRoleAsync);
|
2020-05-01 10:30:35 -04:00
|
|
|
|
|
|
|
TEST_ERROR(cmdArchivePush(), OptionRequiredError, "'archive-push' command in async mode requires option 'pg1-path'");
|
|
|
|
|
2019-03-29 13:26:33 +00:00
|
|
|
// Call with a bogus exe name so the async process will error out and we can make sure timeouts work
|
2018-05-05 09:38:09 -04:00
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
2020-02-12 17:18:48 -07:00
|
|
|
argList = strLstNew();
|
2019-03-29 13:26:33 +00:00
|
|
|
strLstAddZ(argList, "--stanza=test");
|
|
|
|
strLstAddZ(argList, "--archive-async");
|
|
|
|
strLstAddZ(argList, "--archive-timeout=1");
|
2021-05-22 09:30:54 -04:00
|
|
|
strLstAddZ(argList, "--spool-path=" TEST_PATH " /spool");
|
|
|
|
strLstAddZ(argList, "--pg1-path=" TEST_PATH "/pg");
|
|
|
|
strLstAddZ(argList, "--repo1-path=" TEST_PATH "/repo");
|
2019-03-29 13:26:33 +00:00
|
|
|
strLstAddZ(argList, "pg_wal/bogus");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argList, .exeBogus = true);
|
2018-05-05 09:38:09 -04:00
|
|
|
|
2019-12-11 14:36:39 -05:00
|
|
|
storagePathCreateP(storageTest, cfgOptionStr(cfgOptPgPath));
|
2020-07-30 07:49:06 -04:00
|
|
|
THROW_ON_SYS_ERROR(chdir(strZ(cfgOptionStr(cfgOptPgPath))) != 0, PathMissingError, "unable to chdir()");
|
2019-10-30 14:55:25 +01:00
|
|
|
|
2018-05-05 09:38:09 -04:00
|
|
|
TEST_ERROR(
|
|
|
|
cmdArchivePush(), ArchiveTimeoutError,
|
2019-03-29 13:26:33 +00:00
|
|
|
"unable to push WAL file 'bogus' to the archive asynchronously after 1 second(s)");
|
|
|
|
|
|
|
|
// Create pg_control and archive.info
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
argList = strLstNew();
|
|
|
|
strLstAddZ(argList, "--stanza=test");
|
|
|
|
strLstAddZ(argList, "--archive-async");
|
|
|
|
strLstAddZ(argList, "--no-compress");
|
2021-05-22 09:30:54 -04:00
|
|
|
strLstAddZ(argList, "--spool-path=" TEST_PATH "/spool");
|
|
|
|
strLstAddZ(argList, "--pg1-path=" TEST_PATH "/pg");
|
|
|
|
strLstAddZ(argList, "--repo1-path=" TEST_PATH "/repo");
|
2019-03-29 13:26:33 +00:00
|
|
|
strLstAddZ(argList, "--log-subprocess");
|
|
|
|
|
2019-11-17 15:10:40 -05:00
|
|
|
storagePutP(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageNewWriteP(storageTest, STRDEF("pg/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL)),
|
2021-05-17 07:20:28 -04:00
|
|
|
hrnPgControlToBuffer((PgControl){.version = PG_VERSION_94, .systemId = 0xAAAABBBBCCCCDDDD}));
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2019-11-17 15:10:40 -05:00
|
|
|
storagePutP(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageNewWriteP(storageTest, STRDEF("repo/archive/test/archive.info")),
|
2019-04-23 14:02:30 -04:00
|
|
|
harnessInfoChecksumZ(
|
2019-03-29 13:26:33 +00:00
|
|
|
"[db]\n"
|
|
|
|
"db-id=1\n"
|
|
|
|
"\n"
|
|
|
|
"[db:history]\n"
|
|
|
|
"1={\"db-id\":12297848147757817309,\"db-version\":\"9.4\"}\n"));
|
|
|
|
|
|
|
|
// Write out an error file that will be ignored on the first pass, then the async process will write a new one
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
StringList *argListTemp = strLstDup(argList);
|
2021-05-22 09:30:54 -04:00
|
|
|
strLstAddZ(argListTemp, TEST_PATH "/pg/pg_xlog/000000010000000100000001");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2021-05-21 17:36:43 -04:00
|
|
|
storagePathCreateP(storagePgWrite(), STRDEF("pg_xlog/archive_status"));
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2019-11-17 15:10:40 -05:00
|
|
|
storagePutP(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageNewWriteP(storageSpoolWrite(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.error")),
|
2019-04-20 08:16:17 -04:00
|
|
|
BUFSTRDEF("25\nbogus error"));
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
TEST_ERROR(cmdArchivePush(), AssertError, "no WAL files to process");
|
|
|
|
|
2021-05-21 17:36:43 -04:00
|
|
|
storageRemoveP(storageSpoolWrite(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/global.error"), .errorOnMissing = true);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
// Acquire a lock so the async process will not be able to run -- this will result in a timeout
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
argListTemp = strLstDup(argList);
|
2021-05-22 09:30:54 -04:00
|
|
|
strLstAddZ(argListTemp, TEST_PATH "/pg/pg_xlog/000000010000000100000001");
|
2019-03-29 13:26:33 +00:00
|
|
|
strLstAddZ(argListTemp, "--archive-timeout=1");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2020-07-30 07:49:06 -04:00
|
|
|
THROW_ON_SYS_ERROR(chdir(strZ(cfgOptionStr(cfgOptPgPath))) != 0, PathMissingError, "unable to chdir()");
|
2019-10-30 14:55:25 +01:00
|
|
|
|
2019-03-29 13:26:33 +00:00
|
|
|
HARNESS_FORK_BEGIN()
|
|
|
|
{
|
|
|
|
HARNESS_FORK_CHILD_BEGIN(0, true)
|
|
|
|
{
|
2021-05-21 17:36:43 -04:00
|
|
|
IoRead *read = ioFdReadNew(STRDEF("child read"), HARNESS_FORK_CHILD_READ(), 2000);
|
2019-03-29 13:26:33 +00:00
|
|
|
ioReadOpen(read);
|
2021-05-21 17:36:43 -04:00
|
|
|
IoWrite *write = ioFdWriteNew(STRDEF("child write"), HARNESS_FORK_CHILD_WRITE(), 2000);
|
2019-03-29 13:26:33 +00:00
|
|
|
ioWriteOpen(write);
|
|
|
|
|
2020-11-23 12:41:54 -05:00
|
|
|
lockAcquire(
|
|
|
|
cfgOptionStr(cfgOptLockPath), cfgOptionStr(cfgOptStanza), STRDEF("555-fefefefe"), cfgLockType(), 30000, true);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
// Let the parent know the lock has been acquired and wait for the parent to allow lock release
|
2021-05-21 17:36:43 -04:00
|
|
|
ioWriteStrLine(write, strNew());
|
2019-03-29 13:26:33 +00:00
|
|
|
ioWriteFlush(write);
|
|
|
|
ioReadLine(read);
|
|
|
|
|
|
|
|
lockRelease(true);
|
|
|
|
}
|
|
|
|
HARNESS_FORK_CHILD_END();
|
|
|
|
|
|
|
|
HARNESS_FORK_PARENT_BEGIN()
|
|
|
|
{
|
2021-05-21 17:36:43 -04:00
|
|
|
IoRead *read = ioFdReadNew(STRDEF("parent read"), HARNESS_FORK_PARENT_READ_PROCESS(0), 2000);
|
2019-03-29 13:26:33 +00:00
|
|
|
ioReadOpen(read);
|
2021-05-21 17:36:43 -04:00
|
|
|
IoWrite *write = ioFdWriteNew(STRDEF("parent write"), HARNESS_FORK_PARENT_WRITE_PROCESS(0), 2000);
|
2019-03-29 13:26:33 +00:00
|
|
|
ioWriteOpen(write);
|
|
|
|
|
|
|
|
// Wait for the child to acquire the lock
|
|
|
|
ioReadLine(read);
|
|
|
|
|
|
|
|
TEST_ERROR(
|
|
|
|
cmdArchivePush(), ArchiveTimeoutError,
|
|
|
|
"unable to push WAL file '000000010000000100000001' to the archive asynchronously after 1 second(s)");
|
|
|
|
|
|
|
|
// Notify the child to release the lock
|
2019-04-22 18:46:29 -04:00
|
|
|
ioWriteLine(write, bufNew(0));
|
2019-03-29 13:26:33 +00:00
|
|
|
ioWriteFlush(write);
|
|
|
|
}
|
|
|
|
HARNESS_FORK_PARENT_END();
|
|
|
|
}
|
|
|
|
HARNESS_FORK_END();
|
|
|
|
|
|
|
|
// Actually push a WAL file
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
argListTemp = strLstDup(argList);
|
2021-05-22 09:30:54 -04:00
|
|
|
strLstAddZ(argListTemp, TEST_PATH "/pg/pg_xlog/000000010000000100000001");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2021-05-21 17:36:43 -04:00
|
|
|
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_xlog/archive_status/000000010000000100000001.ready")), NULL);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
Buffer *walBuffer1 = bufNew((size_t)16 * 1024 * 1024);
|
|
|
|
bufUsedSet(walBuffer1, bufSize(walBuffer1));
|
|
|
|
memset(bufPtr(walBuffer1), 0xFF, bufSize(walBuffer1));
|
2021-05-17 07:20:28 -04:00
|
|
|
hrnPgWalToBuffer((PgWal){.version = PG_VERSION_94, .systemId = 0xAAAABBBBCCCCDDDD}, walBuffer1);
|
2020-07-30 07:49:06 -04:00
|
|
|
const char *walBuffer1Sha1 = strZ(bufHex(cryptoHashOne(HASH_TYPE_SHA1_STR, walBuffer1)));
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2021-05-21 17:36:43 -04:00
|
|
|
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_xlog/000000010000000100000001")), walBuffer1);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
TEST_RESULT_VOID(cmdArchivePush(), "push the WAL segment");
|
2021-05-22 14:09:45 -04:00
|
|
|
TEST_RESULT_LOG("P00 INFO: pushed WAL file '000000010000000100000001' to the archive asynchronously");
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
TEST_RESULT_BOOL(
|
2019-11-17 15:10:40 -05:00
|
|
|
storageExistsP(
|
2020-07-20 09:47:43 -04:00
|
|
|
storageTest, strNewFmt("repo/archive/test/9.4-1/0000000100000001/000000010000000100000001-%s", walBuffer1Sha1)),
|
2019-03-29 13:26:33 +00:00
|
|
|
true, "check repo for WAL file");
|
|
|
|
|
|
|
|
// Direct tests of the async function
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
argList = strLstNew();
|
|
|
|
strLstAddZ(argList, "--stanza=test");
|
2020-12-10 17:58:59 -05:00
|
|
|
hrnCfgArgRawZ(argList, cfgOptCompressType, "none");
|
2021-05-22 09:30:54 -04:00
|
|
|
strLstAddZ(argList, "--spool-path=" TEST_PATH "/spool");
|
2020-01-15 12:24:58 -07:00
|
|
|
strLstAddZ(argList, "--" CFGOPT_ARCHIVE_ASYNC);
|
2021-05-22 09:30:54 -04:00
|
|
|
strLstAddZ(argList, "--pg1-path=" TEST_PATH "/pg");
|
|
|
|
strLstAddZ(argList, "--repo1-path=" TEST_PATH "/repo");
|
2019-03-29 13:26:33 +00:00
|
|
|
strLstAddZ(argList, "--log-subprocess");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argList, .role = cfgCmdRoleAsync);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
TEST_ERROR(cmdArchivePushAsync(), ParamRequiredError, "WAL path to push required");
|
|
|
|
|
|
|
|
// Check that global.error is created
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
// Remove data from prior tests
|
2021-06-02 11:46:54 -04:00
|
|
|
HRN_STORAGE_PATH_REMOVE(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT, .recurse = true);
|
2019-11-17 15:10:40 -05:00
|
|
|
storagePathCreateP(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT_STR);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2021-06-02 11:46:54 -04:00
|
|
|
HRN_STORAGE_PATH_REMOVE(storagePgWrite(), "pg_xlog/archive_status", .recurse = true);
|
2021-05-21 17:36:43 -04:00
|
|
|
storagePathCreateP(storagePgWrite(), STRDEF("pg_xlog/archive_status"));
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2021-05-22 09:30:54 -04:00
|
|
|
strLstAddZ(argList, TEST_PATH "/pg/pg_xlog");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argList, .role = cfgCmdRoleAsync);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
TEST_ERROR(cmdArchivePushAsync(), AssertError, "no WAL files to process");
|
|
|
|
|
2019-12-26 18:08:27 -07:00
|
|
|
TEST_RESULT_STR_Z(
|
2021-05-21 17:36:43 -04:00
|
|
|
strNewBuf(storageGetP(storageNewReadP(storageSpool(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/global.error")))),
|
2019-03-29 13:26:33 +00:00
|
|
|
"25\nno WAL files to process", "check global.error");
|
|
|
|
|
2021-01-08 12:49:33 -05:00
|
|
|
TEST_RESULT_STRLST_Z(
|
2021-05-21 17:36:43 -04:00
|
|
|
strLstSort(storageListP(storageSpool(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT)), sortOrderAsc),
|
2021-01-08 12:49:33 -05:00
|
|
|
"global.error\n", "check status files");
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
2021-01-21 15:21:50 -05:00
|
|
|
TEST_TITLE("add repo, push already pushed WAL and new WAL");
|
|
|
|
|
|
|
|
// Add repo3
|
2021-05-22 09:30:54 -04:00
|
|
|
hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 3, TEST_PATH "/repo3");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argList, .role = cfgCmdRoleAsync);
|
2021-01-21 15:21:50 -05:00
|
|
|
|
|
|
|
storagePutP(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageNewWriteP(storageTest, STRDEF("repo3/archive/test/archive.info")),
|
2021-01-21 15:21:50 -05:00
|
|
|
harnessInfoChecksumZ(
|
|
|
|
"[db]\n"
|
|
|
|
"db-id=1\n"
|
|
|
|
"\n"
|
|
|
|
"[db:history]\n"
|
|
|
|
"1={\"db-id\":12297848147757817309,\"db-version\":\"9.4\"}\n"));
|
2020-11-09 16:10:59 -05:00
|
|
|
|
2019-03-29 13:26:33 +00:00
|
|
|
// Recreate ready file for WAL 1
|
2021-05-21 17:36:43 -04:00
|
|
|
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_xlog/archive_status/000000010000000100000001.ready")), NULL);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2021-01-21 15:21:50 -05:00
|
|
|
TEST_RESULT_BOOL(
|
|
|
|
storageExistsP(
|
|
|
|
storageTest, strNewFmt("repo/archive/test/9.4-1/0000000100000001/000000010000000100000001-%s", walBuffer1Sha1)),
|
|
|
|
true, "check repo1 for WAL 1 file");
|
|
|
|
|
2019-03-29 13:26:33 +00:00
|
|
|
// Create a ready file for WAL 2 but don't create the segment yet -- this will test the file error
|
2021-05-21 17:36:43 -04:00
|
|
|
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_xlog/archive_status/000000010000000100000002.ready")), NULL);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
TEST_RESULT_VOID(cmdArchivePushAsync(), "push WAL segments");
|
2021-05-22 09:30:54 -04:00
|
|
|
TEST_RESULT_LOG_FMT(
|
|
|
|
"P00 INFO: push 2 WAL file(s) to archive: 000000010000000100000001...000000010000000100000002\n"
|
|
|
|
"P01 WARN: WAL file '000000010000000100000001' already exists in the repo1 archive with the same checksum\n"
|
|
|
|
" HINT: this is valid in some recovery scenarios but may also indicate a problem.\n"
|
|
|
|
"P01 DETAIL: pushed WAL file '000000010000000100000001' to the archive\n"
|
|
|
|
"P01 WARN: could not push WAL file '000000010000000100000002' to the archive (will be retried): "
|
2021-05-25 11:06:05 -04:00
|
|
|
"[55] raised from local-1 shim protocol: " STORAGE_ERROR_READ_MISSING,
|
2021-05-22 09:30:54 -04:00
|
|
|
TEST_PATH "/pg/pg_xlog/000000010000000100000002");
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
TEST_RESULT_BOOL(
|
2019-11-17 15:10:40 -05:00
|
|
|
storageExistsP(
|
2020-07-20 09:47:43 -04:00
|
|
|
storageTest, strNewFmt("repo/archive/test/9.4-1/0000000100000001/000000010000000100000001-%s", walBuffer1Sha1)),
|
2021-01-21 15:21:50 -05:00
|
|
|
true, "check repo1 for WAL 1 file");
|
|
|
|
|
|
|
|
TEST_RESULT_BOOL(
|
|
|
|
storageExistsP(
|
|
|
|
storageTest, strNewFmt("repo/archive/test/9.4-1/0000000100000001/000000010000000100000001-%s", walBuffer1Sha1)),
|
|
|
|
true, "check repo3 for WAL 1 file");
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2021-01-08 12:49:33 -05:00
|
|
|
TEST_RESULT_STRLST_Z(
|
2021-05-21 17:36:43 -04:00
|
|
|
strLstSort(storageListP(storageSpool(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT)), sortOrderAsc),
|
2021-01-08 12:49:33 -05:00
|
|
|
"000000010000000100000001.ok\n000000010000000100000002.error\n", "check status files");
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2020-11-09 16:10:59 -05:00
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
TEST_TITLE("create and push previously missing WAL");
|
|
|
|
|
2019-03-29 13:26:33 +00:00
|
|
|
// Create WAL 2 segment
|
|
|
|
Buffer *walBuffer2 = bufNew((size_t)16 * 1024 * 1024);
|
|
|
|
bufUsedSet(walBuffer2, bufSize(walBuffer2));
|
|
|
|
memset(bufPtr(walBuffer2), 0x0C, bufSize(walBuffer2));
|
2021-05-17 07:20:28 -04:00
|
|
|
hrnPgWalToBuffer((PgWal){.version = PG_VERSION_94, .systemId = 0xAAAABBBBCCCCDDDD}, walBuffer2);
|
2020-07-30 07:49:06 -04:00
|
|
|
const char *walBuffer2Sha1 = strZ(bufHex(cryptoHashOne(HASH_TYPE_SHA1_STR, walBuffer2)));
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2021-05-21 17:36:43 -04:00
|
|
|
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_xlog/000000010000000100000002")), walBuffer2);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
argListTemp = strLstDup(argList);
|
|
|
|
strLstAddZ(argListTemp, "--archive-push-queue-max=1gb");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp, .role = cfgCmdRoleAsync);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
TEST_RESULT_VOID(cmdArchivePushAsync(), "push WAL segments");
|
2021-05-22 14:09:45 -04:00
|
|
|
TEST_RESULT_LOG(
|
2019-03-29 13:26:33 +00:00
|
|
|
"P00 INFO: push 1 WAL file(s) to archive: 000000010000000100000002\n"
|
2019-04-09 11:08:27 -04:00
|
|
|
"P01 DETAIL: pushed WAL file '000000010000000100000002' to the archive");
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
TEST_RESULT_BOOL(
|
2019-11-17 15:10:40 -05:00
|
|
|
storageExistsP(
|
2020-07-20 09:47:43 -04:00
|
|
|
storageTest, strNewFmt("repo/archive/test/9.4-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1)),
|
2021-01-21 15:21:50 -05:00
|
|
|
true, "check repo1 for WAL 2 file");
|
|
|
|
TEST_RESULT_BOOL(
|
|
|
|
storageExistsP(
|
|
|
|
storageTest, strNewFmt("repo3/archive/test/9.4-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1)),
|
|
|
|
true, "check repo3 for WAL 2 file");
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2021-01-08 12:49:33 -05:00
|
|
|
TEST_RESULT_STRLST_Z(
|
2021-05-21 17:36:43 -04:00
|
|
|
strLstSort(storageListP(storageSpool(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT)), sortOrderAsc),
|
2021-01-08 12:49:33 -05:00
|
|
|
"000000010000000100000001.ok\n000000010000000100000002.ok\n", "check status files");
|
2019-03-29 13:26:33 +00:00
|
|
|
|
2021-01-21 15:21:50 -05:00
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
TEST_TITLE("push wal 2 again to get warnings from both repos");
|
|
|
|
|
|
|
|
// Remove the OK file so the WAL gets pushed again
|
|
|
|
storageRemoveP(storageSpoolWrite(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000002.ok"));
|
|
|
|
|
|
|
|
TEST_RESULT_VOID(cmdArchivePushAsync(), "push WAL segments");
|
2021-05-22 14:09:45 -04:00
|
|
|
TEST_RESULT_LOG(
|
2021-01-21 15:21:50 -05:00
|
|
|
"P00 INFO: push 1 WAL file(s) to archive: 000000010000000100000002\n"
|
|
|
|
"P01 WARN: WAL file '000000010000000100000002' already exists in the repo1 archive with the same checksum\n"
|
|
|
|
" HINT: this is valid in some recovery scenarios but may also indicate a problem.\n"
|
2021-02-26 15:58:11 -05:00
|
|
|
"P01 WARN: WAL file '000000010000000100000002' already exists in the repo3 archive with the same checksum\n"
|
2021-01-21 15:21:50 -05:00
|
|
|
" HINT: this is valid in some recovery scenarios but may also indicate a problem.\n"
|
|
|
|
"P01 DETAIL: pushed WAL file '000000010000000100000002' to the archive");
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
TEST_TITLE("create and push WAL 3 to both repos");
|
|
|
|
|
|
|
|
// Create WAL 3 segment
|
|
|
|
Buffer *walBuffer3 = bufNew((size_t)16 * 1024 * 1024);
|
|
|
|
bufUsedSet(walBuffer3, bufSize(walBuffer3));
|
|
|
|
memset(bufPtr(walBuffer3), 0x44, bufSize(walBuffer3));
|
2021-05-17 07:20:28 -04:00
|
|
|
hrnPgWalToBuffer((PgWal){.version = PG_VERSION_94, .systemId = 0xAAAABBBBCCCCDDDD}, walBuffer3);
|
2021-01-21 15:21:50 -05:00
|
|
|
const char *walBuffer3Sha1 = strZ(bufHex(cryptoHashOne(HASH_TYPE_SHA1_STR, walBuffer3)));
|
|
|
|
|
2021-05-21 17:36:43 -04:00
|
|
|
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_xlog/000000010000000100000003")), walBuffer3);
|
2021-01-21 15:21:50 -05:00
|
|
|
|
|
|
|
// Create ready file
|
2021-05-21 17:36:43 -04:00
|
|
|
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_xlog/archive_status/000000010000000100000003.ready")), NULL);
|
2021-01-21 15:21:50 -05:00
|
|
|
|
|
|
|
TEST_RESULT_VOID(cmdArchivePushAsync(), "push WAL segment");
|
2021-05-22 14:09:45 -04:00
|
|
|
TEST_RESULT_LOG(
|
2021-01-21 15:21:50 -05:00
|
|
|
"P00 INFO: push 1 WAL file(s) to archive: 000000010000000100000003\n"
|
|
|
|
"P01 DETAIL: pushed WAL file '000000010000000100000003' to the archive");
|
|
|
|
|
|
|
|
TEST_RESULT_BOOL(
|
|
|
|
storageExistsP(
|
|
|
|
storageTest, strNewFmt("repo/archive/test/9.4-1/0000000100000001/000000010000000100000003-%s", walBuffer3Sha1)),
|
|
|
|
true, "check repo1 for WAL 3 file");
|
|
|
|
TEST_RESULT_BOOL(
|
|
|
|
storageExistsP(
|
|
|
|
storageTest, strNewFmt("repo3/archive/test/9.4-1/0000000100000001/000000010000000100000003-%s", walBuffer3Sha1)),
|
|
|
|
true, "check repo3 for WAL 3 file");
|
|
|
|
|
|
|
|
// Remove the ready file to prevent WAL 3 from being considered for the next test
|
2021-05-21 17:36:43 -04:00
|
|
|
storageRemoveP(storagePgWrite(), STRDEF("pg_xlog/archive_status/000000010000000100000003.ready"), .errorOnMissing = true);
|
2021-01-21 15:21:50 -05:00
|
|
|
|
2019-03-29 13:26:33 +00:00
|
|
|
// Check that drop functionality works
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
// Remove status files
|
2021-06-02 11:46:54 -04:00
|
|
|
HRN_STORAGE_PATH_REMOVE(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT, .recurse = true);
|
2019-11-17 15:10:40 -05:00
|
|
|
storagePathCreateP(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT_STR);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
argListTemp = strLstDup(argList);
|
|
|
|
strLstAddZ(argListTemp, "--archive-push-queue-max=16m");
|
2021-06-01 09:03:44 -04:00
|
|
|
HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp, .role = cfgCmdRoleAsync);
|
2019-03-29 13:26:33 +00:00
|
|
|
|
|
|
|
TEST_RESULT_VOID(cmdArchivePushAsync(), "push WAL segments");
|
2021-05-22 14:09:45 -04:00
|
|
|
TEST_RESULT_LOG(
|
2019-03-29 13:26:33 +00:00
|
|
|
"P00 INFO: push 2 WAL file(s) to archive: 000000010000000100000001...000000010000000100000002\n"
|
|
|
|
"P00 WARN: dropped WAL file '000000010000000100000001' because archive queue exceeded 16MB\n"
|
|
|
|
"P00 WARN: dropped WAL file '000000010000000100000002' because archive queue exceeded 16MB");
|
|
|
|
|
2019-12-26 18:08:27 -07:00
|
|
|
TEST_RESULT_STR_Z(
|
|
|
|
strNewBuf(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageGetP(storageNewReadP(storageSpool(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.ok")))),
|
2019-03-29 13:26:33 +00:00
|
|
|
"0\ndropped WAL file '000000010000000100000001' because archive queue exceeded 16MB", "check WAL 1 warning");
|
|
|
|
|
2019-12-26 18:08:27 -07:00
|
|
|
TEST_RESULT_STR_Z(
|
|
|
|
strNewBuf(
|
2021-05-21 17:36:43 -04:00
|
|
|
storageGetP(storageNewReadP(storageSpool(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000002.ok")))),
|
2019-03-29 13:26:33 +00:00
|
|
|
"0\ndropped WAL file '000000010000000100000002' because archive queue exceeded 16MB", "check WAL 2 warning");
|
|
|
|
|
2021-01-08 12:49:33 -05:00
|
|
|
TEST_RESULT_STRLST_Z(
|
2021-05-21 17:36:43 -04:00
|
|
|
strLstSort(storageListP(storageSpool(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT)), sortOrderAsc),
|
2021-01-08 12:49:33 -05:00
|
|
|
"000000010000000100000001.ok\n000000010000000100000002.ok\n", "check status files");
|
2021-05-25 11:06:05 -04:00
|
|
|
|
|
|
|
// Uninstall local command handler shim
|
|
|
|
hrnProtocolLocalShimUninstall();
|
|
|
|
}
|
2018-05-18 11:57:32 -04:00
|
|
|
|
2021-03-10 18:42:22 -05:00
|
|
|
FUNCTION_HARNESS_RETURN_VOID();
|
2018-01-17 15:52:00 -05:00
|
|
|
}
|