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

Add infoBackupLoadFileReconstruct() to InfoBackup object.

Check the backup.info file against the backup path.  Add any backups that are missing and remove any backups that no longer exist.

It's important to run this before backup or expire to be sure we are using the most up-to-date list of backups.
This commit is contained in:
Cynthia Shang 2019-10-08 16:04:27 -04:00 committed by David Steele
parent b2825b82c7
commit 4e4d1f414a
4 changed files with 696 additions and 8 deletions

View File

@ -291,13 +291,13 @@ command/restore/restore.o: command/restore/restore.c build.auto.h command/backup
command/stanza/common.o: command/stanza/common.c build.auto.h command/check/common.h common/assert.h common/crypto/common.h common/debug.h common/encode.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h db/db.h db/helper.h info/info.h info/infoPg.h postgres/client.h postgres/interface.h postgres/version.h protocol/client.h protocol/command.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c command/stanza/common.c -o command/stanza/common.o
command/stanza/create.o: command/stanza/create.c build.auto.h command/control/common.h command/stanza/common.h command/stanza/create.h common/assert.h common/crypto/common.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h info/info.h info/infoArchive.h info/infoBackup.h info/infoPg.h postgres/interface.h postgres/version.h protocol/client.h protocol/command.h protocol/helper.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
command/stanza/create.o: command/stanza/create.c build.auto.h command/backup/common.h command/control/common.h command/stanza/common.h command/stanza/create.h common/assert.h common/crypto/common.h common/crypto/hash.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h info/info.h info/infoArchive.h info/infoBackup.h info/infoPg.h info/manifest.h postgres/interface.h postgres/version.h protocol/client.h protocol/command.h protocol/helper.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c command/stanza/create.c -o command/stanza/create.o
command/stanza/delete.o: command/stanza/delete.c build.auto.h command/backup/common.h command/control/common.h command/stanza/delete.h common/assert.h common/crypto/common.h common/crypto/hash.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h info/info.h info/infoArchive.h info/infoBackup.h info/infoPg.h info/manifest.h postgres/interface.h protocol/client.h protocol/command.h protocol/helper.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c command/stanza/delete.c -o command/stanza/delete.o
command/stanza/upgrade.o: command/stanza/upgrade.c build.auto.h command/control/common.h command/stanza/common.h command/stanza/upgrade.h common/assert.h common/crypto/common.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h info/info.h info/infoArchive.h info/infoBackup.h info/infoPg.h postgres/interface.h postgres/version.h protocol/client.h protocol/command.h protocol/helper.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
command/stanza/upgrade.o: command/stanza/upgrade.c build.auto.h command/backup/common.h command/control/common.h command/stanza/common.h command/stanza/upgrade.h common/assert.h common/crypto/common.h common/crypto/hash.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h info/info.h info/infoArchive.h info/infoBackup.h info/infoPg.h info/manifest.h postgres/interface.h postgres/version.h protocol/client.h protocol/command.h protocol/helper.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c command/stanza/upgrade.c -o command/stanza/upgrade.o
command/storage/list.o: command/storage/list.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/handleWrite.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/json.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
@ -489,7 +489,7 @@ info/info.o: info/info.c build.auto.h common/assert.h common/crypto/hash.h commo
info/infoArchive.o: info/infoArchive.c build.auto.h common/assert.h common/crypto/cipherBlock.h common/crypto/common.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h info/info.h info/infoArchive.h info/infoPg.h postgres/interface.h postgres/version.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c info/infoArchive.c -o info/infoArchive.o
info/infoBackup.o: info/infoBackup.c build.auto.h command/backup/common.h common/assert.h common/crypto/cipherBlock.h common/crypto/common.h common/crypto/hash.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/regExp.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/json.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h info/info.h info/infoBackup.h info/infoPg.h info/manifest.h postgres/interface.h postgres/version.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h
info/infoBackup.o: info/infoBackup.c build.auto.h command/backup/common.h common/assert.h common/crypto/cipherBlock.h common/crypto/common.h common/crypto/hash.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/regExp.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/json.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h info/info.h info/infoBackup.h info/infoPg.h info/manifest.h postgres/interface.h postgres/version.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h version.h
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c info/infoBackup.c -o info/infoBackup.o
info/infoPg.o: info/infoPg.c build.auto.h common/assert.h common/crypto/common.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/json.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h info/info.h info/infoPg.h postgres/interface.h postgres/version.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h

View File

@ -8,6 +8,7 @@ Backup Info Handler
#include <string.h>
#include <inttypes.h>
#include "command/backup/common.h"
#include "common/crypto/cipherBlock.h"
#include "common/debug.h"
#include "common/ini.h"
@ -22,10 +23,10 @@ Backup Info Handler
#include "postgres/interface.h"
#include "postgres/version.h"
#include "storage/helper.h"
#include "version.h"
/***********************************************************************************************************************************
Constants
??? INFO_BACKUP_SECTION should be in a separate include since it will also be used when reading the manifest
***********************************************************************************************************************************/
#define INFO_BACKUP_SECTION "backup"
#define INFO_BACKUP_SECTION_BACKUP_CURRENT INFO_BACKUP_SECTION ":current"
@ -75,7 +76,7 @@ infoBackupNewInternal(void)
InfoBackup *this = memNew(sizeof(InfoBackup));
this->memContext = memContextCurrent();
this->backup = lstNew(sizeof(InfoBackupData));
this->backup = lstNewP(sizeof(InfoBackupData), .comparator = lstComparatorStr);
FUNCTION_TEST_RETURN(this);
}
@ -347,6 +348,97 @@ infoBackupData(const InfoBackup *this, unsigned int backupDataIdx)
FUNCTION_LOG_RETURN(INFO_BACKUP_DATA, *((InfoBackupData *)lstGet(this->backup, backupDataIdx)));
}
/***********************************************************************************************************************************
Add a backup to the current list
***********************************************************************************************************************************/
void
infoBackupDataAdd(const InfoBackup *this, const Manifest *manifest)
{
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(INFO_BACKUP, this);
FUNCTION_LOG_PARAM(MANIFEST, manifest);
FUNCTION_LOG_END();
ASSERT(this != NULL);
ASSERT(manifest != NULL);
MEM_CONTEXT_TEMP_BEGIN()
{
const ManifestData *manData = manifestData(manifest);
// Calculate backup sizes and references
uint64_t backupSize = 0;
uint64_t backupSizeDelta = 0;
uint64_t backupRepoSize = 0;
uint64_t backupRepoSizeDelta = 0;
StringList *referenceList = strLstNew();
for (unsigned int fileIdx = 0; fileIdx < manifestFileTotal(manifest); fileIdx++)
{
const ManifestFile *file = manifestFile(manifest, fileIdx);
backupSize += file->size;
backupRepoSize += file->sizeRepo > 0 ? file->sizeRepo : file->size;
// If a reference to a file exists, then it is in a previous backup and the delta calculation was already done
if (file->reference != NULL)
strLstAdd(referenceList, file->reference);
else
{
backupSizeDelta += file->size;
backupRepoSizeDelta += file->sizeRepo > 0 ? file->sizeRepo : file->size;
}
}
MEM_CONTEXT_BEGIN(lstMemContext(this->backup))
{
InfoBackupData infoBackupData =
{
.backupLabel = strDup(manData->backupLabel),
.backrestFormat = REPOSITORY_FORMAT,
.backrestVersion = strDup(manData->backrestVersion),
.backupInfoRepoSize = backupRepoSize,
.backupInfoRepoSizeDelta = backupRepoSizeDelta,
.backupInfoSize = backupSize,
.backupInfoSizeDelta = backupSizeDelta,
.backupPgId = manData->pgId,
.backupTimestampStart = (uint64_t)manData->backupTimestampStart,
.backupTimestampStop= (uint64_t)manData->backupTimestampStop,
.backupType = backupTypeStr(manData->backupType),
.backupArchiveStart = strDup(manData->archiveStart),
.backupArchiveStop = strDup(manData->archiveStop),
.optionArchiveCheck = manData->backupOptionArchiveCheck,
.optionArchiveCopy = manData->backupOptionArchiveCopy,
.optionBackupStandby = manData->backupOptionStandby != NULL ? varBool(manData->backupOptionStandby) : false,
.optionChecksumPage = manData->backupOptionChecksumPage != NULL ?
varBool(manData->backupOptionChecksumPage) : false,
.optionCompress = manData->backupOptionCompress,
.optionHardlink = manData->backupOptionHardLink,
.optionOnline = manData->backupOptionOnline,
};
if (manData->backupType != backupTypeFull)
{
strLstSort(referenceList, sortOrderAsc);
infoBackupData.backupReference = strLstDup(referenceList);
infoBackupData.backupPrior = strDup(manData->backupLabelPrior);
}
// Add the backup data to the current backup list
lstAdd(this->backup, &infoBackupData);
// Ensure the list is sorted ascending by the backupLabel
lstSort(this->backup, sortOrderAsc);
}
MEM_CONTEXT_END();
}
MEM_CONTEXT_TEMP_END();
FUNCTION_LOG_RETURN_VOID();
}
/***********************************************************************************************************************************
Delete a backup from the current backup list
***********************************************************************************************************************************/
@ -518,6 +610,99 @@ infoBackupLoadFile(const Storage *storage, const String *fileName, CipherType ci
FUNCTION_LOG_RETURN(INFO_BACKUP, data.infoBackup);
}
/***********************************************************************************************************************************
Load backup info and update it by adding valid backups from the repo or removing backups no longer in the repo
***********************************************************************************************************************************/
InfoBackup *
infoBackupLoadFileReconstruct(const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE, storage);
FUNCTION_LOG_PARAM(STRING, fileName);
FUNCTION_LOG_PARAM(ENUM, cipherType);
FUNCTION_TEST_PARAM(STRING, cipherPass);
FUNCTION_LOG_END();
ASSERT(storage != NULL);
ASSERT(fileName != NULL);
ASSERT((cipherType == cipherTypeNone && cipherPass == NULL) || (cipherType != cipherTypeNone && cipherPass != NULL));
InfoBackup *infoBackup = infoBackupLoadFile(storage, fileName, cipherType, cipherPass);
MEM_CONTEXT_TEMP_BEGIN()
{
// Get a list of backups in the repo
StringList *backupList = strLstSort(
storageListP(
storage, STRDEF(STORAGE_REPO_BACKUP), .expression = backupRegExpP(.full = true, .differential = true,
.incremental = true)),
sortOrderAsc);
// Get the current list of backups from backup.info
StringList *backupCurrentList = strLstSort(infoBackupDataLabelList(infoBackup, NULL), sortOrderAsc);
// For each backup in the repo, check if it exists in backup.info
for (unsigned int backupIdx = 0; backupIdx < strLstSize(backupList); backupIdx++)
{
String *backupLabel = strLstGet(backupList, backupIdx);
// If it does not exist in the list of current backups, then if it is valid, add it
if (!strLstExists(backupCurrentList, backupLabel))
{
String *manifestFileName = strNewFmt(STORAGE_REPO_BACKUP "/%s/" BACKUP_MANIFEST_FILE, strPtr(backupLabel));
// Check if a completed backup exists (backup.manifest only - ignore .copy)
if (storageExistsNP(storage, manifestFileName))
{
bool found = false;
const Manifest *manifest = manifestLoadFile(
storage, manifestFileName, cipherType, infoPgCipherPass(infoBackup->infoPg));
const ManifestData *manData = manifestData(manifest);
// If the pg data for the manifest exists in the history, then add it to current, but if something doesn't match
// then warn that the backup is not valid
for (unsigned int pgIdx = 0; pgIdx < infoPgDataTotal(infoBackup->infoPg); pgIdx++)
{
InfoPgData pgHistory = infoPgData(infoBackup->infoPg, pgIdx);
// If there is an exact match with the history, system and version then add it to the current backup list
if (manData->pgId == pgHistory.id && manData->pgSystemId == pgHistory.systemId &&
manData->pgVersion == pgHistory.version)
{
LOG_WARN("backup '%s' found in repository added to " INFO_BACKUP_FILE, strPtr(backupLabel));
infoBackupDataAdd(infoBackup, manifest);
found = true;
break;
}
}
if (!found)
LOG_WARN("invalid backup '%s' cannot be added to current backups", strPtr(manData->backupLabel));
}
}
}
// Get the updated list of current backups and remove backups from current that are no longer in the repository
backupCurrentList = infoBackupDataLabelList(infoBackup, NULL);
for (unsigned int backupCurrIdx = 0; backupCurrIdx < strLstSize(backupCurrentList); backupCurrIdx++)
{
String *backupLabel = strLstGet(backupCurrentList, backupCurrIdx);
String *manifestFileName = strNewFmt(STORAGE_REPO_BACKUP "/%s/" BACKUP_MANIFEST_FILE, strPtr(backupLabel));
// Remove backup from the current list in the infoBackup object
if (!storageExistsNP(storage, manifestFileName))
{
LOG_WARN("backup '%s' missing manifest removed from " INFO_BACKUP_FILE, strPtr(backupLabel));
infoBackupDataDelete(infoBackup, backupLabel);
}
}
}
MEM_CONTEXT_TEMP_END();
FUNCTION_LOG_RETURN(INFO_BACKUP, infoBackup);
}
/***********************************************************************************************************************************
Helper function to save backup info files
***********************************************************************************************************************************/

View File

@ -15,6 +15,7 @@ typedef struct InfoBackup InfoBackup;
#include "common/type/string.h"
#include "common/type/stringList.h"
#include "info/infoPg.h"
#include "info/manifest.h"
#include "storage/storage.h"
/***********************************************************************************************************************************
@ -32,6 +33,7 @@ Information about an existing backup
***********************************************************************************************************************************/
typedef struct InfoBackupData
{
const String *backupLabel; // backupLabel must be first to allow for built-in list sorting
unsigned int backrestFormat;
const String *backrestVersion;
const String *backupArchiveStart;
@ -40,12 +42,11 @@ typedef struct InfoBackupData
uint64_t backupInfoRepoSizeDelta;
uint64_t backupInfoSize;
uint64_t backupInfoSizeDelta;
const String *backupLabel;
unsigned int backupPgId;
const String *backupPrior;
StringList *backupReference;
uint64_t backupTimestampStart;
uint64_t backupTimestampStop;
uint64_t backupTimestampStart; // ??? Need to fix this so it is time_t
uint64_t backupTimestampStop; // ??? Need to fix this so it is time_t
const String *backupType;
bool optionArchiveCheck;
bool optionArchiveCopy;
@ -64,6 +65,8 @@ InfoBackup *infoBackupNew(unsigned int pgVersion, uint64_t pgSystemId, const Str
/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
// Add backup to current section
void infoBackupDataAdd(const InfoBackup *this, const Manifest *manifest);
// Remove a backup from the current section
void infoBackupDataDelete(const InfoBackup *this, const String *backupDeleteLabel);
InfoBackup *infoBackupPgSet(InfoBackup *this, unsigned int pgVersion, uint64_t pgSystemId);
@ -89,6 +92,8 @@ Helper functions
***********************************************************************************************************************************/
InfoBackup *infoBackupLoadFile(
const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass);
InfoBackup *infoBackupLoadFileReconstruct(
const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass);
void infoBackupSaveFile(
InfoBackup *infoBackup, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass);

View File

@ -6,6 +6,7 @@ Test Backup Info Handler
#include "common/io/bufferWrite.h"
#include "storage/posix/storage.h"
#include "common/harnessConfig.h"
#include "common/harnessInfo.h"
/***********************************************************************************************************************************
@ -224,6 +225,503 @@ testRun(void)
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_STR(
strPtr(infoBackupDataToLog(&backupData)), "{label: 20161219-212741F_20161219-212918I, pgId: 1}", "check log format");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("infoBackupDataAdd - full backup");
#define TEST_MANIFEST_BACKUPDB \
"\n" \
"[backup:db]\n" \
"db-catalog-version=201409291\n" \
"db-control-version=942\n" \
"db-id=1\n" \
"db-system-id=6569239123849665679\n" \
"db-version=\"9.4\"\n"
#define TEST_MANIFEST_FILE_DEFAULT \
"\n" \
"[target:file:default]\n" \
"group=\"group1\"\n" \
"master=false\n" \
"mode=\"0600\"\n" \
"user=\"user1\"\n"
#define TEST_MANIFEST_LINK_DEFAULT \
"\n" \
"[target:link:default]\n" \
"group=\"group1\"\n" \
"user=false\n"
#define TEST_MANIFEST_PATH_DEFAULT \
"\n" \
"[target:path:default]\n" \
"group=false\n" \
"mode=\"0700\"\n" \
"user=\"user1\"\n"
Manifest *manifest = NULL;
const Buffer *manifestContent = harnessInfoChecksumZ
(
"[backup]\n"
"backup-label=\"20190818-084502F\"\n"
"backup-timestamp-copy-start=1565282141\n"
"backup-timestamp-start=1565282140\n"
"backup-timestamp-stop=1565282142\n"
"backup-type=\"full\"\n"
TEST_MANIFEST_BACKUPDB
"\n"
"[backup:option]\n"
"option-archive-check=true\n"
"option-archive-copy=true\n"
"option-compress=false\n"
"option-hardlink=false\n"
"option-online=false\n"
"\n"
"[backup:target]\n"
"pg_data={\"path\":\"/pg/base\",\"type\":\"path\"}\n"
"\n"
"[cipher]\n"
"cipher-pass=\"somepass\"\n"
"\n"
"[target:file]\n"
"pg_data/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"size\":4,\"timestamp\":1565282114}\n"
"pg_data/postgresql.conf={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"repo-size\":24,\"size\":7,"
"\"timestamp\":1565282214}\n"
TEST_MANIFEST_FILE_DEFAULT
"\n"
"[target:path]\n"
"pg_data={}\n"
TEST_MANIFEST_PATH_DEFAULT
);
TEST_ASSIGN(manifest, manifestNewLoad(ioBufferReadNew(manifestContent)), "load manifest");
TEST_RESULT_VOID(infoBackupDataAdd(infoBackup, manifest), "add a backup");
TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 1, "backup added to current");
TEST_ASSIGN(backupData, infoBackupData(infoBackup, 0), "get added backup");
TEST_RESULT_STR(strPtr(backupData.backupLabel), "20190818-084502F", "backup label set");
TEST_RESULT_UINT(backupData.backrestFormat, REPOSITORY_FORMAT, "backrest format");
TEST_RESULT_STR(strPtr(backupData.backrestVersion), PROJECT_VERSION, "backuprest version");
TEST_RESULT_INT(backupData.backupPgId, 1, "pg id");
TEST_RESULT_PTR(backupData.backupArchiveStart, NULL, "archive start NULL");
TEST_RESULT_PTR(backupData.backupArchiveStop, NULL, "archive stop NULL");
TEST_RESULT_STR(strPtr(backupData.backupType), "full", "backup type set");
TEST_RESULT_PTR(strPtr(backupData.backupPrior), NULL, "no backup prior");
TEST_RESULT_PTR(backupData.backupReference, NULL, "no backup reference");
TEST_RESULT_INT(backupData.backupTimestampStart, 1565282140, "timestamp start");
TEST_RESULT_INT(backupData.backupTimestampStop, 1565282142, "timestamp stop");
TEST_RESULT_BOOL(backupData.optionArchiveCheck, true, "option archive check");
TEST_RESULT_BOOL(backupData.optionArchiveCopy, true, "option archive copy");
TEST_RESULT_BOOL(backupData.optionBackupStandby, false, "no option backup standby");
TEST_RESULT_BOOL(backupData.optionChecksumPage, false, "no option checksum page");
TEST_RESULT_BOOL(backupData.optionCompress, false, "option compress");
TEST_RESULT_BOOL(backupData.optionHardlink, false, "option hardlink");
TEST_RESULT_BOOL(backupData.optionOnline, false, "option online");
TEST_RESULT_UINT(backupData.backupInfoSize, 11, "database size");
TEST_RESULT_UINT(backupData.backupInfoSizeDelta, 11, "backup size");
TEST_RESULT_UINT(backupData.backupInfoRepoSize, 28, "repo size");
TEST_RESULT_UINT(backupData.backupInfoRepoSizeDelta, 28, "repo backup size");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("infoBackupDataAdd - incr backup");
#define TEST_MANIFEST_DB \
"\n" \
"[db]\n" \
"mail={\"db-id\":16456,\"db-last-system-id\":12168}\n" \
"postgres={\"db-id\":12173,\"db-last-system-id\":12168}\n" \
"template0={\"db-id\":12168,\"db-last-system-id\":12168}\n" \
"template1={\"db-id\":1,\"db-last-system-id\":12168}\n" \
manifestContent = harnessInfoChecksumZ
(
"[backup]\n"
"backup-archive-start=\"000000030000028500000089\"\n"
"backup-archive-stop=\"000000030000028500000090\"\n"
"backup-label=\"20190818-084502F_20190820-084502I\"\n"
"backup-lsn-start=\"285/89000028\"\n"
"backup-lsn-stop=\"285/89001F88\"\n"
"backup-prior=\"20190818-084502F\"\n"
"backup-timestamp-copy-start=1565282141\n"
"backup-timestamp-start=1565282140\n"
"backup-timestamp-stop=1565282142\n"
"backup-type=\"diff\"\n"
TEST_MANIFEST_BACKUPDB
"\n"
"[backup:option]\n"
"option-archive-check=true\n"
"option-archive-copy=true\n"
"option-backup-standby=true\n"
"option-buffer-size=16384\n"
"option-checksum-page=true\n"
"option-compress=true\n"
"option-compress-level=3\n"
"option-compress-level-network=3\n"
"option-delta=false\n"
"option-hardlink=true\n"
"option-online=true\n"
"option-process-max=32\n"
"\n"
"[backup:target]\n"
"pg_data={\"path\":\"/pg/base\",\"type\":\"path\"}\n"
"pg_data/base/1={\"path\":\"../../base-1\",\"type\":\"link\"}\n"
"pg_data/pg_hba.conf={\"file\":\"pg_hba.conf\",\"path\":\"../pg_config\",\"type\":\"link\"}\n"
"pg_data/pg_stat={\"path\":\"../pg_stat\",\"type\":\"link\"}\n"
"pg_data/postgresql.conf={\"file\":\"postgresql.conf\",\"path\":\"../pg_config\",\"type\":\"link\"}\n"
"pg_tblspc/1={\"path\":\"/tblspc/ts1\",\"tablespace-id\":\"1\",\"tablespace-name\":\"ts1\",\"type\":\"link\"}\n"
TEST_MANIFEST_DB
"\n"
"[target:file]\n"
"pg_data/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"master\":true"
",\"reference\":\"20190818-084502F_20190819-084506D\",\"size\":4,\"timestamp\":1565282114}\n"
"pg_data/base/16384/17000={\"checksum\":\"e0101dd8ffb910c9c202ca35b5f828bcb9697bed\",\"checksum-page\":false"
",\"checksum-page-error\":[1],\"repo-size\":4096,\"size\":8192,\"timestamp\":1565282114}\n"
"pg_data/base/16384/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"group\":false,\"size\":4"
",\"timestamp\":1565282115}\n"
"pg_data/base/32768/33000={\"checksum\":\"7a16d165e4775f7c92e8cdf60c0af57313f0bf90\",\"checksum-page\":true"
",\"reference\":\"20190818-084502F\",\"size\":1073741824,\"timestamp\":1565282116}\n"
"pg_data/base/32768/33000.32767={\"checksum\":\"6e99b589e550e68e934fd235ccba59fe5b592a9e\",\"checksum-page\":true"
",\"reference\":\"20190818-084502F_20190819-084506I\",\"size\":32768,\"timestamp\":1565282114}\n"
"pg_data/postgresql.conf={\"checksum\":\"6721d92c9fcdf4248acff1f9a1377127d9064807\",\"master\":true,\"size\":4457"
",\"timestamp\":1565282114}\n"
"pg_data/special={\"master\":true,\"mode\":\"0640\",\"size\":0,\"timestamp\":1565282120,\"user\":false}\n"
TEST_MANIFEST_FILE_DEFAULT
"\n"
"[target:link]\n"
"pg_data/pg_stat={\"destination\":\"../pg_stat\"}\n"
"pg_data/postgresql.conf={\"destination\":\"../pg_config/postgresql.conf\",\"group\":false,\"user\":\"user1\"}\n"
TEST_MANIFEST_LINK_DEFAULT
"\n"
"[target:path]\n"
"pg_data={\"user\":\"user2\"}\n"
"pg_data/base={\"group\":\"group2\"}\n"
"pg_data/base/16384={\"mode\":\"0750\"}\n"
"pg_data/base/32768={}\n"
"pg_data/base/65536={\"user\":false}\n"
TEST_MANIFEST_PATH_DEFAULT
);
TEST_ASSIGN(manifest, manifestNewLoad(ioBufferReadNew(manifestContent)), "load manifest");
TEST_RESULT_VOID(infoBackupDataAdd(infoBackup, manifest), "add a backup");
TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 2, "backup added to current");
TEST_ASSIGN(backupData, infoBackupData(infoBackup, 1), "get added backup");
TEST_RESULT_STR(strPtr(backupData.backupLabel), "20190818-084502F_20190820-084502I", "backup label set");
TEST_RESULT_UINT(backupData.backrestFormat, REPOSITORY_FORMAT, "backrest format");
TEST_RESULT_STR(strPtr(backupData.backrestVersion), PROJECT_VERSION, "backuprest version");
TEST_RESULT_STR(strPtr(backupData.backupArchiveStart), "000000030000028500000089", "archive start set");
TEST_RESULT_STR(strPtr(backupData.backupArchiveStop), "000000030000028500000090", "archive stop set");
TEST_RESULT_STR(strPtr(backupData.backupType), "diff", "backup type set");
TEST_RESULT_STR(strPtr(backupData.backupPrior), "20190818-084502F", "backup prior set");
TEST_RESULT_STR(
strPtr(strLstJoin(backupData.backupReference, ", ")),
"20190818-084502F, 20190818-084502F_20190819-084506D, 20190818-084502F_20190819-084506I",
"backup reference set and ordered");
TEST_RESULT_BOOL(backupData.optionArchiveCheck, true, "option archive check");
TEST_RESULT_BOOL(backupData.optionArchiveCopy, true, "option archive copy");
TEST_RESULT_BOOL(backupData.optionBackupStandby, true, "option backup standby");
TEST_RESULT_BOOL(backupData.optionChecksumPage, true, "no option checksum page");
TEST_RESULT_BOOL(backupData.optionCompress, true, "option compress");
TEST_RESULT_BOOL(backupData.optionHardlink, true, "option hardlink");
TEST_RESULT_BOOL(backupData.optionOnline, true, "option online");
TEST_RESULT_UINT(backupData.backupInfoSize, 1073787249, "database size");
TEST_RESULT_UINT(backupData.backupInfoSizeDelta, 12653, "backup size");
TEST_RESULT_UINT(backupData.backupInfoRepoSize, 1073783153, "repo size");
TEST_RESULT_UINT(backupData.backupInfoRepoSizeDelta, 8557, "repo backup size");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("infoBackupLoadFileReconstruct - skip/add backups");
// Load configuration to set repo-path and stanza
StringList *argList = strLstNew();
strLstAddZ(argList, "--stanza=db");
strLstAdd(argList, strNewFmt("--repo-path=%s", testPath()));
harnessCfgLoad(cfgCmdArchiveGet, argList);
// Create manifest for upgrade db (id=2), save to disk
manifestContent = harnessInfoChecksumZ
(
"[backup]\n"
"backup-archive-start=\"000000030000028500000066\"\n"
"backup-archive-stop=\"000000030000028500000070\"\n"
"backup-label=\"20190923-164324F\"\n"
"backup-lsn-start=\"0/66000028\"\n"
"backup-lsn-stop=\"0/700000F8\"\n"
"backup-timestamp-copy-start=1569257007\n"
"backup-timestamp-start=1569257004\n"
"backup-timestamp-stop=1569257014\n"
"backup-type=\"full\"\n"
"\n"
"[backup:db]\n"
"db-catalog-version=201809051\n"
"db-control-version=1100\n"
"db-id=2\n"
"db-system-id=6739907367085689196\n"
"db-version=\"11\"\n"
"\n"
"[backup:option]\n"
"option-archive-check=true\n"
"option-archive-copy=false\n"
"option-backup-standby=false\n"
"option-buffer-size=4194304\n"
"option-checksum-page=false\n"
"option-compress=true\n"
"option-compress-level=6\n"
"option-compress-level-network=3\n"
"option-delta=false\n"
"option-hardlink=false\n"
"option-online=true\n"
"option-process-max=3\n"
"\n"
"[backup:target]\n"
"pg_data={\"path\":\"/pg/base\",\"type\":\"path\"}\n"
TEST_MANIFEST_DB
"\n"
"[target:file]\n"
"pg_data/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"master\":true"
",\"reference\":\"20190818-084502F_20190819-084506D\",\"size\":4,\"timestamp\":1569256970}\n"
"pg_data/backup_label={\"checksum\":\"e0101dd8ffb910c9c202ca35b5f828bcb9697bed\",\"checksum-page\":false"
",\"checksum-page-error\":[1],\"size\":249,\"timestamp\":1569257013}\n"
"pg_data/base/13050/PG_VERSION={\"checksum\":\"dd71038f3463f511ee7403dbcbc87195302d891c\",\"repo-size\":23,\"size\":3,\"timestamp\":1569256971}\n"
TEST_MANIFEST_FILE_DEFAULT
"\n"
"[target:path]\n"
"pg_data={}\n"
"pg_data/base={}\n"
"pg_data/base/13050={}\n"
TEST_MANIFEST_PATH_DEFAULT
);
TEST_RESULT_VOID(
storagePutNP(storageNewWriteNP(storageRepoWrite(),
strNew(STORAGE_REPO_BACKUP "/20190923-164324F/" BACKUP_MANIFEST_FILE)), manifestContent),
"write main manifest for pgId=2 - valid backup to add");
manifestContent = harnessInfoChecksumZ
(
"[backup]\n"
"backup-label=\"20190818-084444F\"\n"
"backup-timestamp-copy-start=1565282141\n"
"backup-timestamp-start=1565282140\n"
"backup-timestamp-stop=1565282142\n"
"backup-type=\"full\"\n"
TEST_MANIFEST_BACKUPDB
"\n"
"[backup:option]\n"
"option-archive-check=true\n"
"option-archive-copy=true\n"
"option-compress=false\n"
"option-hardlink=false\n"
"option-online=false\n"
"\n"
"[backup:target]\n"
"pg_data={\"path\":\"/pg/base\",\"type\":\"path\"}\n"
"\n"
"[cipher]\n"
"cipher-pass=\"somepass\"\n"
"\n"
"[target:file]\n"
"pg_data/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"size\":4,\"timestamp\":1565282114}\n"
"pg_data/postgresql.conf={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"repo-size\":24,\"size\":7,"
"\"timestamp\":1565282214}\n"
TEST_MANIFEST_FILE_DEFAULT
"\n"
"[target:path]\n"
"pg_data={}\n"
TEST_MANIFEST_PATH_DEFAULT
);
TEST_RESULT_VOID(
storagePutNP(storageNewWriteNP(storageRepoWrite(),
strNew(STORAGE_REPO_BACKUP "/20190818-084444F/" BACKUP_MANIFEST_FILE INFO_COPY_EXT)),
manifestContent), "write manifest copy for pgId=1");
manifestContent = harnessInfoChecksumZ
(
"[backup]\n"
"backup-label=\"20190818-084555F\"\n"
"backup-timestamp-copy-start=1565282141\n"
"backup-timestamp-start=1565282140\n"
"backup-timestamp-stop=1565282142\n"
"backup-type=\"full\"\n"
"\n"
"[backup:db]\n"
"db-catalog-version=201809051\n"
"db-control-version=1100\n"
"db-id=1\n"
"db-system-id=6739907367085689196\n"
"db-version=\"11\"\n"
"\n"
"[backup:option]\n"
"option-archive-check=true\n"
"option-archive-copy=true\n"
"option-compress=false\n"
"option-hardlink=false\n"
"option-online=false\n"
"\n"
"[backup:target]\n"
"pg_data={\"path\":\"/pg/base\",\"type\":\"path\"}\n"
"\n"
"[cipher]\n"
"cipher-pass=\"somepass\"\n"
"\n"
"[target:file]\n"
"pg_data/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"size\":4,\"timestamp\":1565282114}\n"
TEST_MANIFEST_FILE_DEFAULT
"\n"
"[target:path]\n"
"pg_data={}\n"
TEST_MANIFEST_PATH_DEFAULT
);
TEST_RESULT_VOID(
storagePutNP(storageNewWriteNP(storageRepoWrite(),
strNew(STORAGE_REPO_BACKUP "/20190818-084555F/" BACKUP_MANIFEST_FILE)),
manifestContent), "write manifest - invalid backup pgId mismatch");
manifestContent = harnessInfoChecksumZ
(
"[backup]\n"
"backup-label=\"20190818-084666F\"\n"
"backup-timestamp-copy-start=1565282141\n"
"backup-timestamp-start=1565282140\n"
"backup-timestamp-stop=1565282142\n"
"backup-type=\"full\"\n"
"\n"
"[backup:db]\n"
"db-catalog-version=201809051\n"
"db-control-version=1100\n"
"db-id=2\n"
"db-system-id=6739907367085689666\n"
"db-version=\"11\"\n"
"\n"
"[backup:option]\n"
"option-archive-check=true\n"
"option-archive-copy=true\n"
"option-compress=false\n"
"option-hardlink=false\n"
"option-online=false\n"
"\n"
"[backup:target]\n"
"pg_data={\"path\":\"/pg/base\",\"type\":\"path\"}\n"
"\n"
"[cipher]\n"
"cipher-pass=\"somepass\"\n"
"\n"
"[target:file]\n"
"pg_data/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"size\":4,\"timestamp\":1565282114}\n"
TEST_MANIFEST_FILE_DEFAULT
"\n"
"[target:path]\n"
"pg_data={}\n"
TEST_MANIFEST_PATH_DEFAULT
);
TEST_RESULT_VOID(
storagePutNP(storageNewWriteNP(storageRepoWrite(),
strNew(STORAGE_REPO_BACKUP "/20190818-084666F/" BACKUP_MANIFEST_FILE)),
manifestContent), "write manifest - invalid backup system-id mismatch");
manifestContent = harnessInfoChecksumZ
(
"[backup]\n"
"backup-label=\"20190818-084777F\"\n"
"backup-timestamp-copy-start=1565282141\n"
"backup-timestamp-start=1565282140\n"
"backup-timestamp-stop=1565282142\n"
"backup-type=\"full\"\n"
"\n"
"[backup:db]\n"
"db-catalog-version=201809051\n"
"db-control-version=1100\n"
"db-id=2\n"
"db-system-id=6739907367085689196\n"
"db-version=\"10\"\n"
"\n"
"[backup:option]\n"
"option-archive-check=true\n"
"option-archive-copy=true\n"
"option-compress=false\n"
"option-hardlink=false\n"
"option-online=false\n"
"\n"
"[backup:target]\n"
"pg_data={\"path\":\"/pg/base\",\"type\":\"path\"}\n"
"\n"
"[cipher]\n"
"cipher-pass=\"somepass\"\n"
"\n"
"[target:file]\n"
"pg_data/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"size\":4,\"timestamp\":1565282114}\n"
TEST_MANIFEST_FILE_DEFAULT
"\n"
"[target:path]\n"
"pg_data={}\n"
TEST_MANIFEST_PATH_DEFAULT
);
TEST_RESULT_VOID(
storagePutNP(storageNewWriteNP(storageRepoWrite(),
strNew(STORAGE_REPO_BACKUP "/20190818-084777F/" BACKUP_MANIFEST_FILE)),
manifestContent), "write manifest - invalid backup version mismatch");
TEST_RESULT_VOID(
storagePathCreateNP(storageRepoWrite(), strNew(STORAGE_REPO_BACKUP "/20190818-084502F")),
"create backup on disk that is in current but no manifest");
TEST_RESULT_STR(
strPtr(strLstJoin(strLstSort(storageListP(storageRepo(), STRDEF(STORAGE_REPO_BACKUP),
.expression = backupRegExpP(.full = true, .differential = true, .incremental = true)), sortOrderAsc), ", ")),
"20190818-084444F, 20190818-084502F, 20190818-084555F, 20190818-084666F, 20190818-084777F, 20190923-164324F",
"confirm backups on disk");
// With the infoBackup from above, upgrade the DB so there a 2 histories then save to disk
TEST_ASSIGN(infoBackup, infoBackupPgSet(infoBackup, PG_VERSION_11, 6739907367085689196), "upgrade db");
TEST_RESULT_VOID(
infoBackupSaveFile(infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL),
"save backup info");
infoBackup = NULL;
TEST_ASSIGN(
infoBackup, infoBackupLoadFile(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL),
"get saved backup info");
TEST_RESULT_INT(infoBackupDataTotal(infoBackup), 2, "backup list contains backups to be removed");
TEST_RESULT_INT(infoPgDataTotal(infoBackup->infoPg), 2, "multiple DB history");
TEST_ASSIGN(
infoBackup, infoBackupLoadFileReconstruct(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL),
"reconstruct");
TEST_RESULT_INT(infoBackupDataTotal(infoBackup), 1, "backup list contains 1 backup");
TEST_ASSIGN(backupData, infoBackupData(infoBackup, 0), "get the backup");
TEST_RESULT_STR(strPtr(backupData.backupLabel), "20190923-164324F",
"backups not on disk removed, valid backup on disk added, manifest copy-only ignored");
harnessLogResult(
"P00 WARN: invalid backup '20190818-084555F' cannot be added to current backups\n"
"P00 WARN: invalid backup '20190818-084666F' cannot be added to current backups\n"
"P00 WARN: invalid backup '20190818-084777F' cannot be added to current backups\n"
"P00 WARN: backup '20190923-164324F' found in repository added to backup.info\n"
"P00 WARN: backup '20190818-084502F' missing manifest removed from backup.info\n"
"P00 WARN: backup '20190818-084502F_20190820-084502I' missing manifest removed from backup.info");
TEST_RESULT_VOID(
storageCopyNP(
storageNewReadNP(storageRepo(), strNew(STORAGE_REPO_BACKUP "/20190818-084444F/" BACKUP_MANIFEST_FILE INFO_COPY_EXT)),
storageNewWriteNP(storageRepoWrite(), strNew(STORAGE_REPO_BACKUP "/20190818-084444F/" BACKUP_MANIFEST_FILE))),
"write manifest from copy-only for pgId=1");
TEST_RESULT_VOID(
infoBackupSaveFile(infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL),
"save updated backup info");
infoBackup = NULL;
TEST_ASSIGN(
infoBackup, infoBackupLoadFileReconstruct(storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL),
"reconstruct");
TEST_RESULT_STR(
strPtr(strLstJoin(infoBackupDataLabelList(infoBackup, NULL), ", ")), "20190818-084444F, 20190923-164324F",
"previously ignored pgId=1 manifest copy-only now added before existing");
harnessLogResult(
"P00 WARN: backup '20190818-084444F' found in repository added to backup.info\n"
"P00 WARN: invalid backup '20190818-084555F' cannot be added to current backups\n"
"P00 WARN: invalid backup '20190818-084666F' cannot be added to current backups\n"
"P00 WARN: invalid backup '20190818-084777F' cannot be added to current backups");
}
// *****************************************************************************************************************************