You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2026-05-22 10:15:16 +02:00
Improve performance of info file load/save.
Info files required three copies in memory to be loaded (the original string, an ini representation, and the final info object). Not only was this memory inefficient but the Ini object does sequential scans when searching for keys making large files very slow to load. This has not been an issue since archive.info and backup.info are very small, but it becomes a big deal when loading manifests with hundreds of thousands of files. Instead of holding copies of the data in memory, use a callback to deliver the ini data directly to the object when loading. Use a similar method for save to avoid having an intermediate copy. Save is a bit complex because sections/keys must be written in alpha order or older versions of pgBackRest will not calculate the correct checksum. Also move the load retry logic to helper functions rather than embedding it in the Info object. This allows for more flexibility in loading and ensures that stack traces will be available when developing unit tests. Reviewed by Cynthia Shang.
This commit is contained in:
@@ -15,6 +15,14 @@
|
||||
<release date="XXXX-XX-XX" version="2.18dev" title="UNDER DEVELOPMENT">
|
||||
<release-core-list>
|
||||
<release-development-list>
|
||||
<release-item>
|
||||
<release-item-contributor-list>
|
||||
<release-item-reviewer id="cynthia.shang"/>
|
||||
</release-item-contributor-list>
|
||||
|
||||
<p>Improve performance of info file load/save.</p>
|
||||
</release-item>
|
||||
|
||||
<release-item>
|
||||
<release-item-contributor-list>
|
||||
<release-item-reviewer id="cynthia.shang"/>
|
||||
|
||||
+4
-4
@@ -335,7 +335,7 @@ common/exit.o: common/exit.c build.auto.h command/command.h common/assert.h comm
|
||||
common/fork.o: common/fork.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/log.h common/logLevel.h common/stackTrace.h common/type/convert.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c common/fork.c -o common/fork.o
|
||||
|
||||
common/ini.o: common/ini.c build.auto.h common/assert.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/write.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/variant.h common/type/variantList.h
|
||||
common/ini.o: common/ini.c build.auto.h common/assert.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/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/variant.h common/type/variantList.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c common/ini.c -o common/ini.o
|
||||
|
||||
common/io/bufferRead.o: common/io/bufferRead.c build.auto.h common/assert.h common/debug.h common/error.auto.h common/error.h common/io/bufferRead.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/read.intern.h common/log.h common/logLevel.h common/macro.h common/memContext.h common/object.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/variant.h common/type/variantList.h
|
||||
@@ -473,13 +473,13 @@ db/helper.o: db/helper.c build.auto.h common/assert.h common/debug.h common/erro
|
||||
db/protocol.o: db/protocol.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/io.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/protocol.h postgres/client.h postgres/interface.h protocol/client.h protocol/command.h protocol/server.h storage/info.h storage/read.h storage/storage.h storage/write.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c db/protocol.c -o db/protocol.o
|
||||
|
||||
info/info.o: info/info.c build.auto.h common/assert.h common/crypto/cipherBlock.h common/crypto/common.h common/crypto/hash.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/filter.intern.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/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h info/info.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h version.h
|
||||
info/info.o: info/info.c build.auto.h common/assert.h common/crypto/hash.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/filter.intern.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/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h info/info.h storage/helper.h storage/info.h storage/read.h storage/storage.h storage/write.h version.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) $(CMAKE) -c info/info.c -o info/info.o
|
||||
|
||||
info/infoArchive.o: info/infoArchive.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/keyValue.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
|
||||
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/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 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/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 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/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
|
||||
$(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
|
||||
|
||||
@@ -50,7 +50,7 @@ archiveGetCheck(const String *archiveFile, CipherType cipherType, const String *
|
||||
PgControl controlInfo = pgControlFromFile(storagePg(), cfgOptionStr(cfgOptPgPath));
|
||||
|
||||
// Attempt to load the archive info file
|
||||
InfoArchive *info = infoArchiveNewLoad(storageRepo(), INFO_ARCHIVE_PATH_FILE_STR, cipherType, cipherPass);
|
||||
InfoArchive *info = infoArchiveLoadFile(storageRepo(), INFO_ARCHIVE_PATH_FILE_STR, cipherType, cipherPass);
|
||||
|
||||
// Loop through the pg history in case the WAL we need is not in the most recent archive id
|
||||
String *archiveId = NULL;
|
||||
|
||||
@@ -216,7 +216,7 @@ archivePushCheck(CipherType cipherType, const String *cipherPass)
|
||||
PgControl controlInfo = pgControlFromFile(storagePg(), cfgOptionStr(cfgOptPgPath));
|
||||
|
||||
// Attempt to load the archive info file
|
||||
InfoArchive *info = infoArchiveNewLoad(storageRepo(), INFO_ARCHIVE_PATH_FILE_STR, cipherType, cipherPass);
|
||||
InfoArchive *info = infoArchiveLoadFile(storageRepo(), INFO_ARCHIVE_PATH_FILE_STR, cipherType, cipherPass);
|
||||
|
||||
// Get archive id for the most recent version -- archive-push will only operate against the most recent version
|
||||
String *archiveId = infoPgArchiveId(infoArchivePg(info), infoPgDataCurrentId(infoArchivePg(info)));
|
||||
|
||||
@@ -27,7 +27,7 @@ cmdCheck(void)
|
||||
storageRepo();
|
||||
|
||||
// Attempt to load the archive info file
|
||||
InfoArchive *archiveInfo = infoArchiveNewLoad(
|
||||
InfoArchive *archiveInfo = infoArchiveLoadFile(
|
||||
storageRepo(), INFO_ARCHIVE_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
const String *archiveId = infoArchiveId(archiveInfo);
|
||||
|
||||
@@ -306,7 +306,7 @@ removeExpiredArchive(InfoBackup *infoBackup)
|
||||
if (strLstSize(globalBackupRetentionList) > 0)
|
||||
{
|
||||
// Attempt to load the archive info file
|
||||
InfoArchive *infoArchive = infoArchiveNewLoad(
|
||||
InfoArchive *infoArchive = infoArchiveLoadFile(
|
||||
storageRepo(), INFO_ARCHIVE_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
|
||||
@@ -670,14 +670,14 @@ cmdExpire(void)
|
||||
storageRepo();
|
||||
|
||||
// Load the backup.info
|
||||
InfoBackup *infoBackup = infoBackupNewLoad(
|
||||
InfoBackup *infoBackup = infoBackupLoadFile(
|
||||
storageRepo(), INFO_BACKUP_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
|
||||
expireFullBackup(infoBackup);
|
||||
expireDiffBackup(infoBackup);
|
||||
|
||||
infoBackupSave(
|
||||
infoBackupSaveFile(
|
||||
infoBackup, storageRepoWrite(), INFO_BACKUP_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
|
||||
|
||||
@@ -305,7 +305,7 @@ stanzaInfoList(const String *stanza, StringList *stanzaList)
|
||||
TRY_BEGIN()
|
||||
{
|
||||
// Attempt to load the backup info file
|
||||
info = infoBackupNewLoad(
|
||||
info = infoBackupLoadFile(
|
||||
storageRepo(), strNewFmt(STORAGE_PATH_BACKUP "/%s/%s", strPtr(stanzaListName), INFO_BACKUP_FILE),
|
||||
cipherType(cfgOptionStr(cfgOptRepoCipherType)), cfgOptionStr(cfgOptRepoCipherPass));
|
||||
}
|
||||
@@ -352,7 +352,7 @@ stanzaInfoList(const String *stanza, StringList *stanzaList)
|
||||
varLstAdd(dbSection, pgInfo);
|
||||
|
||||
// Get the archive info for the DB from the archive.info file
|
||||
InfoArchive *info = infoArchiveNewLoad(
|
||||
InfoArchive *info = infoArchiveLoadFile(
|
||||
storageRepo(), strNewFmt(STORAGE_PATH_ARCHIVE "/%s/%s", strPtr(stanzaListName), INFO_ARCHIVE_FILE),
|
||||
cipherType(cfgOptionStr(cfgOptRepoCipherType)), cfgOptionStr(cfgOptRepoCipherPass));
|
||||
archiveDbList(stanzaListName, &pgData, archiveSection, info, (pgIdx == 0 ? true : false));
|
||||
|
||||
@@ -73,9 +73,8 @@ cmdStanzaCreate(void)
|
||||
String *cipherPassSub = cipherPassGen(cipherType(cfgOptionStr(cfgOptRepoCipherType)));
|
||||
|
||||
// Create and save archive info
|
||||
infoArchive = infoArchiveNew(
|
||||
pgControl.version, pgControl.systemId, cipherType(cfgOptionStr(cfgOptRepoCipherType)), cipherPassSub);
|
||||
infoArchiveSave(
|
||||
infoArchive = infoArchiveNew(pgControl.version, pgControl.systemId, cipherPassSub);
|
||||
infoArchiveSaveFile(
|
||||
infoArchive, storageRepoWriteStanza, INFO_ARCHIVE_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
|
||||
@@ -84,21 +83,20 @@ cmdStanzaCreate(void)
|
||||
|
||||
// Create and save backup info
|
||||
infoBackup = infoBackupNew(
|
||||
pgControl.version, pgControl.systemId, pgControl.controlVersion, pgControl.catalogVersion,
|
||||
cipherType(cfgOptionStr(cfgOptRepoCipherType)), cipherPassSub);
|
||||
infoBackupSave(
|
||||
pgControl.version, pgControl.systemId, pgControl.controlVersion, pgControl.catalogVersion, cipherPassSub);
|
||||
infoBackupSaveFile(
|
||||
infoBackup, storageRepoWriteStanza, INFO_BACKUP_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
}
|
||||
// Else if at least one archive and one backup info file exists, then ensure both are valid
|
||||
else if ((archiveInfoFileExists || archiveInfoFileCopyExists) && (backupInfoFileExists || backupInfoFileCopyExists))
|
||||
{
|
||||
infoArchive = infoArchiveNewLoad(
|
||||
infoArchive = infoArchiveLoadFile(
|
||||
storageRepoReadStanza, INFO_ARCHIVE_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
InfoPgData archiveInfo = infoPgData(infoArchivePg(infoArchive), infoPgDataCurrentId(infoArchivePg(infoArchive)));
|
||||
|
||||
infoBackup = infoBackupNewLoad(
|
||||
infoBackup = infoBackupLoadFile(
|
||||
storageRepoReadStanza, INFO_BACKUP_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
InfoPgData backupInfo = infoPgData(infoBackupPg(infoBackup), infoPgDataCurrentId(infoBackupPg(infoBackup)));
|
||||
|
||||
@@ -45,12 +45,12 @@ cmdStanzaUpgrade(void)
|
||||
PgControl pgControl = pgValidate();
|
||||
|
||||
// Load the info files (errors if missing)
|
||||
InfoArchive *infoArchive = infoArchiveNewLoad(
|
||||
InfoArchive *infoArchive = infoArchiveLoadFile(
|
||||
storageRepoReadStanza, INFO_ARCHIVE_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
InfoPgData archiveInfo = infoPgData(infoArchivePg(infoArchive), infoPgDataCurrentId(infoArchivePg(infoArchive)));
|
||||
|
||||
InfoBackup *infoBackup = infoBackupNewLoad(
|
||||
InfoBackup *infoBackup = infoBackupLoadFile(
|
||||
storageRepoReadStanza, INFO_BACKUP_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
InfoPgData backupInfo = infoPgData(infoBackupPg(infoBackup), infoPgDataCurrentId(infoBackupPg(infoBackup)));
|
||||
@@ -80,7 +80,7 @@ cmdStanzaUpgrade(void)
|
||||
// Save archive info
|
||||
if (infoArchiveUpgrade)
|
||||
{
|
||||
infoArchiveSave(
|
||||
infoArchiveSaveFile(
|
||||
infoArchive, storageRepoWriteStanza, INFO_ARCHIVE_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
}
|
||||
@@ -88,7 +88,7 @@ cmdStanzaUpgrade(void)
|
||||
// Save backup info
|
||||
if (infoBackupUpgrade)
|
||||
{
|
||||
infoBackupSave(
|
||||
infoBackupSaveFile(
|
||||
infoBackup, storageRepoWriteStanza, INFO_BACKUP_PATH_FILE_STR, cipherType(cfgOptionStr(cfgOptRepoCipherType)),
|
||||
cfgOptionStr(cfgOptRepoCipherPass));
|
||||
}
|
||||
|
||||
+66
-31
@@ -9,6 +9,7 @@ Ini Handler
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/memContext.h"
|
||||
#include "common/log.h"
|
||||
#include "common/ini.h"
|
||||
#include "common/type/keyValue.h"
|
||||
#include "common/object.h"
|
||||
@@ -31,9 +32,11 @@ Create a new Ini object
|
||||
Ini *
|
||||
iniNew(void)
|
||||
{
|
||||
FUNCTION_TEST_VOID();
|
||||
|
||||
Ini *this = NULL;
|
||||
|
||||
MEM_CONTEXT_NEW_BEGIN("ini")
|
||||
MEM_CONTEXT_NEW_BEGIN("Ini")
|
||||
{
|
||||
// Create object
|
||||
this = memNew(sizeof(Ini));
|
||||
@@ -44,8 +47,7 @@ iniNew(void)
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
// Return buffer
|
||||
return this;
|
||||
FUNCTION_TEST_RETURN(this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@@ -344,51 +346,84 @@ iniSet(Ini *this, const String *section, const String *key, const String *value)
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Save the ini file
|
||||
Load an ini file and return data to a callback
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
iniSave(Ini *this, IoWrite *write)
|
||||
iniLoad(
|
||||
IoRead *read, void (*callbackFunction)(void *data, const String *section, const String *key, const String *value),
|
||||
void *callbackData)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INI, this);
|
||||
FUNCTION_TEST_PARAM(IO_WRITE, write);
|
||||
FUNCTION_TEST_END();
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(IO_READ, read);
|
||||
FUNCTION_LOG_PARAM(FUNCTIONP, callbackFunction);
|
||||
FUNCTION_LOG_PARAM_P(VOID, callbackData);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
ASSERT(write != NULL);
|
||||
ASSERT(read != NULL);
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
ioWriteOpen(write);
|
||||
// Track the current section
|
||||
String *section = NULL;
|
||||
|
||||
StringList *sectionList = strLstSort(iniSectionList(this), sortOrderAsc);
|
||||
// Keep track of the line number for error reporting
|
||||
unsigned int lineIdx = 0;
|
||||
|
||||
for (unsigned int sectionIdx = 0; sectionIdx < strLstSize(sectionList); sectionIdx++)
|
||||
MEM_CONTEXT_TEMP_RESET_BEGIN()
|
||||
{
|
||||
const String *section = strLstGet(sectionList, sectionIdx);
|
||||
ioReadOpen(read);
|
||||
|
||||
if (sectionIdx != 0)
|
||||
ioWrite(write, LF_BUF);
|
||||
|
||||
ioWrite(write, BRACKETL_BUF);
|
||||
ioWriteStr(write, section);
|
||||
ioWriteLine(write, BRACKETR_BUF);
|
||||
|
||||
StringList *keyList = strLstSort(iniSectionKeyList(this, section), sortOrderAsc);
|
||||
|
||||
for (unsigned int keyIdx = 0; keyIdx < strLstSize(keyList); keyIdx++)
|
||||
do
|
||||
{
|
||||
const String *key = strLstGet(keyList, keyIdx);
|
||||
const String *line = strTrim(ioReadLineParam(read, true));
|
||||
const char *linePtr = strPtr(line);
|
||||
|
||||
ioWriteStr(write, key);
|
||||
ioWrite(write, EQ_BUF);
|
||||
ioWriteStrLine(write, iniGet(this, section, key));
|
||||
// Only interested in lines that are not blank or comments
|
||||
if (strSize(line) > 0 && linePtr[0] != '#')
|
||||
{
|
||||
// Looks like this line is a section
|
||||
if (linePtr[0] == '[')
|
||||
{
|
||||
// Make sure the section ends with ]
|
||||
if (linePtr[strSize(line) - 1] != ']')
|
||||
THROW_FMT(FormatError, "ini section should end with ] at line %u: %s", lineIdx + 1, linePtr);
|
||||
|
||||
// Assign section
|
||||
memContextSwitch(MEM_CONTEXT_OLD());
|
||||
section = strNewN(linePtr + 1, strSize(line) - 2);
|
||||
memContextSwitch(MEM_CONTEXT_TEMP());
|
||||
}
|
||||
// Else it should be a key/value
|
||||
else
|
||||
{
|
||||
if (section == NULL)
|
||||
THROW_FMT(FormatError, "key/value found outside of section at line %u: %s", lineIdx + 1, linePtr);
|
||||
|
||||
// Find the =
|
||||
const char *lineEqual = strstr(linePtr, "=");
|
||||
|
||||
if (lineEqual == NULL)
|
||||
THROW_FMT(FormatError, "missing '=' in key/value at line %u: %s", lineIdx + 1, linePtr);
|
||||
|
||||
// Extract the key
|
||||
String *key = strTrim(strNewN(linePtr, (size_t)(lineEqual - linePtr)));
|
||||
|
||||
if (strSize(key) == 0)
|
||||
THROW_FMT(FormatError, "key is zero-length at line %u: %s", lineIdx++, linePtr);
|
||||
|
||||
// Callback with the section/key/value
|
||||
callbackFunction(callbackData, section, key, strTrim(strNew(lineEqual + 1)));
|
||||
}
|
||||
}
|
||||
|
||||
ioWriteClose(write);
|
||||
lineIdx++;
|
||||
MEM_CONTEXT_TEMP_RESET(1000);
|
||||
}
|
||||
while (!ioReadEof(read));
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_TEST_RETURN_VOID();
|
||||
FUNCTION_LOG_RETURN_VOID();
|
||||
}
|
||||
|
||||
+8
-1
@@ -12,6 +12,7 @@ Ini object
|
||||
|
||||
typedef struct Ini Ini;
|
||||
|
||||
#include "common/io/read.h"
|
||||
#include "common/io/write.h"
|
||||
#include "common/type/variant.h"
|
||||
|
||||
@@ -25,7 +26,6 @@ Functions
|
||||
***********************************************************************************************************************************/
|
||||
Ini *iniMove(Ini *this, MemContext *parentNew);
|
||||
void iniParse(Ini *this, const String *content);
|
||||
void iniSave(Ini *this, IoWrite *write);
|
||||
void iniSet(Ini *this, const String *section, const String *key, const String *value);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@@ -45,6 +45,13 @@ Destructor
|
||||
***********************************************************************************************************************************/
|
||||
void iniFree(Ini *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Helper Functions
|
||||
***********************************************************************************************************************************/
|
||||
void iniLoad(
|
||||
IoRead *read, void (*callbackFunction)(void *data, const String *section, const String *key, const String *value),
|
||||
void *callbackData);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
|
||||
+379
-250
@@ -7,7 +7,7 @@ Info Handler
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common/crypto/cipherBlock.h"
|
||||
#include "common/type/convert.h"
|
||||
#include "common/crypto/hash.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/encode.h"
|
||||
@@ -24,16 +24,18 @@ Info Handler
|
||||
/***********************************************************************************************************************************
|
||||
Internal constants
|
||||
***********************************************************************************************************************************/
|
||||
STRING_STATIC(INFO_SECTION_BACKREST_STR, "backrest");
|
||||
#define INFO_SECTION_BACKREST "backrest"
|
||||
STRING_STATIC(INFO_SECTION_BACKREST_STR, INFO_SECTION_BACKREST);
|
||||
STRING_STATIC(INFO_SECTION_CIPHER_STR, "cipher");
|
||||
|
||||
STRING_STATIC(INFO_KEY_CIPHER_PASS_STR, "cipher-pass");
|
||||
STRING_STATIC(INFO_KEY_CHECKSUM_STR, "backrest-checksum");
|
||||
#define INFO_KEY_CHECKSUM "backrest-checksum"
|
||||
STRING_STATIC(INFO_KEY_CHECKSUM_STR, INFO_KEY_CHECKSUM);
|
||||
STRING_EXTERN(INFO_KEY_FORMAT_STR, INFO_KEY_FORMAT);
|
||||
STRING_EXTERN(INFO_KEY_VERSION_STR, INFO_KEY_VERSION);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Object type
|
||||
Object types
|
||||
***********************************************************************************************************************************/
|
||||
struct Info
|
||||
{
|
||||
@@ -41,7 +43,71 @@ struct Info
|
||||
const String *cipherPass; // Cipher passphrase if set
|
||||
};
|
||||
|
||||
OBJECT_DEFINE_FREE(INFO);
|
||||
struct InfoSave
|
||||
{
|
||||
MemContext *memContext; // Mem context
|
||||
IoWrite *write; // Write object
|
||||
IoFilter *checksum; // hash to generate file checksum
|
||||
String *sectionLast; // The last section seen
|
||||
};
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros and buffer constants for checksum generation
|
||||
***********************************************************************************************************************************/
|
||||
#define INFO_CHECKSUM_BEGIN(checksum) \
|
||||
do \
|
||||
{ \
|
||||
ioFilterProcessIn(checksum, BRACEL_BUF); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
BUFFER_STRDEF_STATIC(INFO_CHECKSUM_SECTION_END_BUF, "\":{");
|
||||
|
||||
#define INFO_CHECKSUM_SECTION(checksum, section) \
|
||||
do \
|
||||
{ \
|
||||
ioFilterProcessIn(checksum, QUOTED_BUF); \
|
||||
ioFilterProcessIn(checksum, BUFSTR(section)); \
|
||||
ioFilterProcessIn(checksum, INFO_CHECKSUM_SECTION_END_BUF); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
BUFFER_STRDEF_STATIC(INFO_CHECKSUM_SECTION_NEXT_END_BUF, "},");
|
||||
|
||||
#define INFO_CHECKSUM_SECTION_NEXT(checksum) \
|
||||
do \
|
||||
{ \
|
||||
ioFilterProcessIn(checksum, INFO_CHECKSUM_SECTION_NEXT_END_BUF); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
BUFFER_STRDEF_STATIC(INFO_CHECKSUM_KEY_VALUE_END_BUF, "\":");
|
||||
|
||||
#define INFO_CHECKSUM_KEY_VALUE(checksum, key, value) \
|
||||
do \
|
||||
{ \
|
||||
ioFilterProcessIn(checksum, QUOTED_BUF); \
|
||||
ioFilterProcessIn(checksum, BUFSTR(key)); \
|
||||
ioFilterProcessIn(checksum, INFO_CHECKSUM_KEY_VALUE_END_BUF); \
|
||||
ioFilterProcessIn(checksum, BUFSTR(value)); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define INFO_CHECKSUM_KEY_VALUE_NEXT(checksum) \
|
||||
do \
|
||||
{ \
|
||||
ioFilterProcessIn(checksum, COMMA_BUF); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
BUFFER_STRDEF_STATIC(INFO_CHECKSUM_END_BUF, "}}");
|
||||
|
||||
#define INFO_CHECKSUM_END(checksum) \
|
||||
do \
|
||||
{ \
|
||||
ioFilterProcessIn(checksum, INFO_CHECKSUM_END_BUF); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Internal constructor
|
||||
@@ -49,333 +115,321 @@ Internal constructor
|
||||
static Info *
|
||||
infoNewInternal(void)
|
||||
{
|
||||
FUNCTION_LOG_VOID(logLevelTrace);
|
||||
FUNCTION_TEST_VOID();
|
||||
|
||||
Info *this = memNew(sizeof(Info));
|
||||
this->memContext = memContextCurrent();
|
||||
|
||||
FUNCTION_TEST_RETURN(this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Create new object
|
||||
***********************************************************************************************************************************/
|
||||
Info *
|
||||
infoNew(const String *cipherPass)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_TEST_PARAM(STRING, cipherPass); // Use FUNCTION_TEST so cipher is not logged
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
Info *this = NULL;
|
||||
|
||||
MEM_CONTEXT_NEW_BEGIN("Info")
|
||||
{
|
||||
// Create object
|
||||
this = memNew(sizeof(Info));
|
||||
this->memContext = MEM_CONTEXT_NEW();
|
||||
this = infoNewInternal();
|
||||
|
||||
// Cipher used to encrypt/decrypt subsequent dependent files. Value may be NULL.
|
||||
this->cipherPass = strDup(cipherPass);
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
FUNCTION_LOG_RETURN(INFO, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Create new object
|
||||
***********************************************************************************************************************************/
|
||||
Info *
|
||||
infoNew(CipherType cipherType, const String *cipherPassSub)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(ENUM, cipherType);
|
||||
FUNCTION_TEST_PARAM(STRING, cipherPassSub); // Use FUNCTION_TEST so cipher is not logged
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
// Ensure cipherPassSub is set and not an empty string when cipherType is not NONE and is not set when cipherType is NONE
|
||||
ASSERT(
|
||||
!((cipherType == cipherTypeNone && cipherPassSub != NULL) ||
|
||||
(cipherType != cipherTypeNone && (cipherPassSub == NULL || strSize(cipherPassSub) == 0))));
|
||||
|
||||
Info *this = infoNewInternal();
|
||||
|
||||
// Cipher used to encrypt/decrypt subsequent dependent files. Value may be NULL.
|
||||
if (cipherPassSub != NULL)
|
||||
this->cipherPass = cipherPassSub;
|
||||
|
||||
FUNCTION_LOG_RETURN(INFO, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Generate hash for the contents of an ini file
|
||||
***********************************************************************************************************************************/
|
||||
String *
|
||||
infoHash(const Ini *ini)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INI, ini);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(ini != NULL);
|
||||
|
||||
String *result = NULL;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
IoFilter *hash = cryptoHashNew(HASH_TYPE_SHA1_STR);
|
||||
StringList *sectionList = strLstSort(iniSectionList(ini), sortOrderAsc);
|
||||
|
||||
// Initial JSON opening bracket
|
||||
ioFilterProcessIn(hash, BUFSTRDEF("{"));
|
||||
|
||||
// Loop through sections and create hash for checking checksum
|
||||
for (unsigned int sectionIdx = 0; sectionIdx < strLstSize(sectionList); sectionIdx++)
|
||||
{
|
||||
String *section = strLstGet(sectionList, sectionIdx);
|
||||
|
||||
// Add a comma before additional sections
|
||||
if (sectionIdx != 0)
|
||||
ioFilterProcessIn(hash, BUFSTRDEF(","));
|
||||
|
||||
// Create the section header
|
||||
ioFilterProcessIn(hash, BUFSTRDEF("\""));
|
||||
ioFilterProcessIn(hash, BUFSTR(section));
|
||||
ioFilterProcessIn(hash, BUFSTRDEF("\":{"));
|
||||
|
||||
StringList *keyList = strLstSort(iniSectionKeyList(ini, section), sortOrderAsc);
|
||||
unsigned int keyListSize = strLstSize(keyList);
|
||||
|
||||
// Loop through values and build the section
|
||||
for (unsigned int keyIdx = 0; keyIdx < keyListSize; keyIdx++)
|
||||
{
|
||||
String *key = strLstGet(keyList, keyIdx);
|
||||
|
||||
// Skip the backrest checksum in the file
|
||||
if (!strEq(section, INFO_SECTION_BACKREST_STR) || !strEq(key, INFO_KEY_CHECKSUM_STR))
|
||||
{
|
||||
ioFilterProcessIn(hash, BUFSTRDEF("\""));
|
||||
ioFilterProcessIn(hash, BUFSTR(key));
|
||||
ioFilterProcessIn(hash, BUFSTRDEF("\":"));
|
||||
ioFilterProcessIn(hash, BUFSTR(iniGet(ini, section, strLstGet(keyList, keyIdx))));
|
||||
|
||||
if ((keyListSize > 1) && (keyIdx < keyListSize - 1))
|
||||
ioFilterProcessIn(hash, BUFSTRDEF(","));
|
||||
}
|
||||
}
|
||||
|
||||
// Close the key/value list
|
||||
ioFilterProcessIn(hash, BUFSTRDEF("}"));
|
||||
}
|
||||
|
||||
// JSON closing bracket
|
||||
ioFilterProcessIn(hash, BUFSTRDEF("}"));
|
||||
|
||||
Variant *resultVar = ioFilterResult(hash);
|
||||
|
||||
memContextSwitch(MEM_CONTEXT_OLD());
|
||||
result = strDup(varStr(resultVar));
|
||||
memContextSwitch(MEM_CONTEXT_TEMP());
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_TEST_RETURN(result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Load and validate the info file (or copy)
|
||||
***********************************************************************************************************************************/
|
||||
static Ini *
|
||||
infoLoad(Info *this, const Storage *storage, const String *fileName, bool copyFile, CipherType cipherType, const String *cipherPass)
|
||||
typedef struct InfoLoadData
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelTrace)
|
||||
FUNCTION_LOG_PARAM(INFO, this);
|
||||
FUNCTION_LOG_PARAM(STORAGE, storage);
|
||||
FUNCTION_LOG_PARAM(STRING, fileName); // Full path/filename to load
|
||||
FUNCTION_LOG_PARAM(BOOL, copyFile); // Is this the copy file?
|
||||
FUNCTION_LOG_PARAM(ENUM, cipherType);
|
||||
FUNCTION_TEST_PARAM(STRING, cipherPass);
|
||||
FUNCTION_LOG_END();
|
||||
MemContext *memContext; // Mem context to use for storing data in this structure
|
||||
InfoLoadNewCallback *callbackFunction; // Callback function for child object
|
||||
void *callbackData; // Callback data for child object
|
||||
Info *info; // Info object
|
||||
String *sectionLast; // The last section seen during load
|
||||
IoFilter *checksumActual; // Checksum calculated from the file
|
||||
String *checksumExpected; // Checksum found in ini file
|
||||
} InfoLoadData;
|
||||
|
||||
ASSERT(this != NULL);
|
||||
ASSERT(fileName != NULL);
|
||||
|
||||
Ini *result = NULL;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
static void
|
||||
infoLoadCallback(void *data, const String *section, const String *key, const String *value)
|
||||
{
|
||||
const String *fileNameExt = copyFile ? strNewFmt("%s" INFO_COPY_EXT, strPtr(fileName)) : fileName;
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM_P(VOID, data);
|
||||
FUNCTION_TEST_PARAM(STRING, section);
|
||||
FUNCTION_TEST_PARAM(STRING, key);
|
||||
FUNCTION_TEST_PARAM(STRING, value);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Attempt to load the file
|
||||
StorageRead *infoRead = storageNewReadP(storage, fileNameExt, .compressible = cipherType == cipherTypeNone);
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(section != NULL);
|
||||
ASSERT(key != NULL);
|
||||
ASSERT(value != NULL);
|
||||
|
||||
if (cipherType != cipherTypeNone)
|
||||
InfoLoadData *loadData = (InfoLoadData *)data;
|
||||
|
||||
// Calculate checksum
|
||||
if (!(strEq(section, INFO_SECTION_BACKREST_STR) && strEq(key, INFO_KEY_CHECKSUM_STR)))
|
||||
{
|
||||
ioFilterGroupAdd(
|
||||
ioReadFilterGroup(storageReadIo(infoRead)),
|
||||
cipherBlockNew(cipherModeDecrypt, cipherType, BUFSTR(cipherPass), NULL));
|
||||
if (loadData->sectionLast == NULL || !strEq(section, loadData->sectionLast))
|
||||
{
|
||||
if (loadData->sectionLast != NULL)
|
||||
INFO_CHECKSUM_SECTION_NEXT(loadData->checksumActual);
|
||||
|
||||
INFO_CHECKSUM_SECTION(loadData->checksumActual, section);
|
||||
|
||||
MEM_CONTEXT_BEGIN(loadData->memContext)
|
||||
{
|
||||
loadData->sectionLast = strDup(section);
|
||||
}
|
||||
|
||||
// Load and parse the info file
|
||||
Buffer *buffer = NULL;
|
||||
|
||||
TRY_BEGIN()
|
||||
{
|
||||
buffer = storageGetNP(infoRead);
|
||||
}
|
||||
CATCH(CryptoError)
|
||||
{
|
||||
THROW_FMT(
|
||||
CryptoError, "'%s' %s\nHINT: Is or was the repo encrypted?", strPtr(storagePathNP(storage, fileNameExt)),
|
||||
errorMessage());
|
||||
}
|
||||
TRY_END();
|
||||
|
||||
result = iniNew();
|
||||
iniParse(result, strNewBuf(buffer));
|
||||
|
||||
// Make sure the ini is valid by testing the checksum
|
||||
const String *infoChecksumJson = iniGet(result, INFO_SECTION_BACKREST_STR, INFO_KEY_CHECKSUM_STR);
|
||||
const String *checksum = infoHash(result);
|
||||
|
||||
if (strSize(infoChecksumJson) == 0)
|
||||
{
|
||||
THROW_FMT(
|
||||
ChecksumError, "invalid checksum in '%s', expected '%s' but no checksum found",
|
||||
strPtr(storagePathNP(storage, fileNameExt)), strPtr(checksum));
|
||||
MEM_CONTEXT_END();
|
||||
}
|
||||
else
|
||||
INFO_CHECKSUM_KEY_VALUE_NEXT(loadData->checksumActual);
|
||||
|
||||
INFO_CHECKSUM_KEY_VALUE(loadData->checksumActual, key, value);
|
||||
}
|
||||
|
||||
// Process backrest section
|
||||
if (strEq(section, INFO_SECTION_BACKREST_STR))
|
||||
{
|
||||
const String *infoChecksum = jsonToStr(infoChecksumJson);
|
||||
|
||||
if (!strEq(infoChecksum, checksum))
|
||||
// Validate format
|
||||
if (strEq(key, INFO_KEY_FORMAT_STR))
|
||||
{
|
||||
THROW_FMT(
|
||||
ChecksumError, "invalid checksum in '%s', expected '%s' but found '%s'",
|
||||
strPtr(storagePathNP(storage, fileNameExt)), strPtr(checksum), strPtr(infoChecksum));
|
||||
if (jsonToUInt(value) != REPOSITORY_FORMAT)
|
||||
THROW_FMT(FormatError, "expected format %d but found %d", REPOSITORY_FORMAT, cvtZToInt(strPtr(value)));
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure that the format is current, otherwise error
|
||||
if (jsonToUInt(iniGet(result, INFO_SECTION_BACKREST_STR, INFO_KEY_FORMAT_STR)) != REPOSITORY_FORMAT)
|
||||
// Store checksum to be validated later
|
||||
else if (strEq(key, INFO_KEY_CHECKSUM_STR))
|
||||
{
|
||||
THROW_FMT(
|
||||
FormatError, "invalid format in '%s', expected %d but found %d", strPtr(fileNameExt), REPOSITORY_FORMAT,
|
||||
varIntForce(VARSTR(iniGet(result, INFO_SECTION_BACKREST_STR, INFO_KEY_FORMAT_STR))));
|
||||
MEM_CONTEXT_BEGIN(loadData->memContext)
|
||||
{
|
||||
loadData->checksumExpected = jsonToStr(value);
|
||||
}
|
||||
|
||||
iniMove(result, MEM_CONTEXT_OLD());
|
||||
MEM_CONTEXT_END();
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
}
|
||||
// Process cipher section
|
||||
else if (strEq(section, INFO_SECTION_CIPHER_STR))
|
||||
{
|
||||
// No validation needed for cipher-pass, just store it
|
||||
if (strEq(key, INFO_KEY_CIPHER_PASS_STR))
|
||||
{
|
||||
MEM_CONTEXT_BEGIN(loadData->info->memContext)
|
||||
{
|
||||
loadData->info->cipherPass = jsonToStr(value);
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
}
|
||||
}
|
||||
// Else pass to callback for processing
|
||||
else
|
||||
loadData->callbackFunction(loadData->callbackData, section, key, value);
|
||||
|
||||
FUNCTION_LOG_RETURN(INI, result);
|
||||
FUNCTION_TEST_RETURN_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Create new object and load contents from a file
|
||||
***********************************************************************************************************************************/
|
||||
Info *
|
||||
infoNewLoad(const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass, Ini **ini)
|
||||
infoNewLoad(IoRead *read, InfoLoadNewCallback *callbackFunction, void *callbackData)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(STORAGE, storage);
|
||||
FUNCTION_LOG_PARAM(STRING, fileName); // Full path/filename to load
|
||||
FUNCTION_LOG_PARAM(ENUM, cipherType);
|
||||
FUNCTION_TEST_PARAM(STRING, cipherPass);
|
||||
FUNCTION_LOG_PARAM_P(INI, ini);
|
||||
FUNCTION_LOG_PARAM(IO_READ, read);
|
||||
FUNCTION_LOG_PARAM(FUNCTIONP, callbackFunction);
|
||||
FUNCTION_LOG_PARAM_P(VOID, callbackData);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(storage != NULL);
|
||||
ASSERT(fileName != NULL);
|
||||
ASSERT(cipherType == cipherTypeNone || cipherPass != NULL);
|
||||
ASSERT(read != NULL);
|
||||
ASSERT(callbackFunction != NULL);
|
||||
ASSERT(callbackData != NULL);
|
||||
|
||||
Info *this = infoNewInternal();
|
||||
Info *this = NULL;
|
||||
|
||||
MEM_CONTEXT_BEGIN(this->memContext)
|
||||
MEM_CONTEXT_NEW_BEGIN("Info")
|
||||
{
|
||||
Ini *iniLocal = NULL;
|
||||
this = infoNewInternal();
|
||||
|
||||
// Attempt to load the primary file
|
||||
TRY_BEGIN()
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
iniLocal = infoLoad(this, storage, fileName, false, cipherType, cipherPass);
|
||||
}
|
||||
CATCH_ANY()
|
||||
// Load and parse the info file
|
||||
InfoLoadData data =
|
||||
{
|
||||
// On error store the error and try to load the copy
|
||||
String *primaryError = strNewFmt("%s: %s", errorTypeName(errorType()), errorMessage());
|
||||
bool primaryMissing = errorType() == &FileMissingError;
|
||||
const ErrorType *primaryErrorType = errorType();
|
||||
.memContext = MEM_CONTEXT_TEMP(),
|
||||
.callbackFunction = callbackFunction,
|
||||
.callbackData = callbackData,
|
||||
.info = this,
|
||||
.checksumActual = cryptoHashNew(HASH_TYPE_SHA1_STR),
|
||||
};
|
||||
|
||||
INFO_CHECKSUM_BEGIN(data.checksumActual);
|
||||
|
||||
TRY_BEGIN()
|
||||
{
|
||||
iniLocal = infoLoad(this, storage, fileName, true, cipherType, cipherPass);
|
||||
iniLoad(read, infoLoadCallback, &data);
|
||||
}
|
||||
CATCH_ANY()
|
||||
CATCH(CryptoError)
|
||||
{
|
||||
// If both copies of the file have the same error then throw that error,
|
||||
// else if one file is missing but the other is in error and it is not missing, throw that error
|
||||
// else throw an open error
|
||||
THROWP_FMT(
|
||||
errorType() == primaryErrorType ? errorType() :
|
||||
(errorType() == &FileMissingError ? primaryErrorType :
|
||||
(primaryMissing ? errorType() : &FileOpenError)),
|
||||
"unable to load info file '%s' or '%s" INFO_COPY_EXT "':\n%s\n%s: %s",
|
||||
strPtr(storagePathNP(storage, fileName)), strPtr(storagePathNP(storage, fileName)),
|
||||
strPtr(primaryError), errorTypeName(errorType()), errorMessage());
|
||||
}
|
||||
TRY_END();
|
||||
THROW_FMT(CryptoError, "%s\nHINT: is or was the repo encrypted?", errorMessage());
|
||||
}
|
||||
TRY_END();
|
||||
|
||||
// Load the cipher passphrase if it exists
|
||||
const String *cipherPassSub = iniGetDefault(iniLocal, INFO_SECTION_CIPHER_STR, INFO_KEY_CIPHER_PASS_STR, NULL);
|
||||
INFO_CHECKSUM_END(data.checksumActual);
|
||||
|
||||
if (cipherPassSub != NULL)
|
||||
this->cipherPass = jsonToStr(cipherPassSub);
|
||||
// Verify the checksum
|
||||
const String *checksumActual = varStr(ioFilterResult(data.checksumActual));
|
||||
|
||||
if (ini != NULL)
|
||||
*ini = iniMove(iniLocal, MEM_CONTEXT_OLD());
|
||||
if (data.checksumExpected == NULL)
|
||||
THROW_FMT(ChecksumError, "invalid checksum, actual '%s' but no checksum found", strPtr(checksumActual));
|
||||
else if (!strEq(data.checksumExpected, checksumActual))
|
||||
{
|
||||
THROW_FMT(
|
||||
ChecksumError, "invalid checksum, actual '%s' but expected '%s'", strPtr(checksumActual),
|
||||
strPtr(data.checksumExpected));
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
FUNCTION_LOG_RETURN(INFO, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Check if the section should be saved
|
||||
***********************************************************************************************************************************/
|
||||
bool
|
||||
infoSaveSection(InfoSave *infoSaveData, const String *section, const String *sectionNext)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INFO_SAVE, infoSaveData);
|
||||
FUNCTION_TEST_PARAM(STRING, section);
|
||||
FUNCTION_TEST_PARAM(STRING, sectionNext);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RETURN(
|
||||
(infoSaveData->sectionLast == NULL || strCmp(section, infoSaveData->sectionLast) > 0) &&
|
||||
(sectionNext == NULL || strCmp(section, sectionNext) < 0));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Save a JSON formatted value and update checksum
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
infoSaveValue(InfoSave *infoSaveData, const String *section, const String *key, const String *jsonValue)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(INFO_SAVE, infoSaveData);
|
||||
FUNCTION_TEST_PARAM(STRING, section);
|
||||
FUNCTION_TEST_PARAM(STRING, key);
|
||||
FUNCTION_TEST_PARAM(STRING, jsonValue);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(infoSaveData != NULL);
|
||||
ASSERT(section != NULL);
|
||||
ASSERT(key != NULL);
|
||||
ASSERT(jsonValue != NULL);
|
||||
|
||||
// Save section
|
||||
if (infoSaveData->sectionLast == NULL || !strEq(section, infoSaveData->sectionLast))
|
||||
{
|
||||
if (infoSaveData->sectionLast != NULL)
|
||||
{
|
||||
INFO_CHECKSUM_SECTION_NEXT(infoSaveData->checksum);
|
||||
ioWriteLine(infoSaveData->write, BUFSTRDEF(""));
|
||||
}
|
||||
|
||||
INFO_CHECKSUM_SECTION(infoSaveData->checksum, section);
|
||||
|
||||
ioWrite(infoSaveData->write, BRACKETL_BUF);
|
||||
ioWrite(infoSaveData->write, BUFSTR(section));
|
||||
ioWriteLine(infoSaveData->write, BRACKETR_BUF);
|
||||
|
||||
MEM_CONTEXT_BEGIN(infoSaveData->memContext)
|
||||
{
|
||||
infoSaveData->sectionLast = strDup(section);
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
}
|
||||
else
|
||||
INFO_CHECKSUM_KEY_VALUE_NEXT(infoSaveData->checksum);
|
||||
|
||||
// Save key/value
|
||||
INFO_CHECKSUM_KEY_VALUE(infoSaveData->checksum, key, jsonValue);
|
||||
|
||||
ioWrite(infoSaveData->write, BUFSTR(key));
|
||||
ioWrite(infoSaveData->write, EQ_BUF);
|
||||
ioWriteLine(infoSaveData->write, BUFSTR(jsonValue));
|
||||
|
||||
FUNCTION_TEST_RETURN_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Save to file
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
infoSave(
|
||||
Info *this, Ini *ini, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass)
|
||||
infoSave(Info *this, IoWrite *write, InfoSaveCallback *callbackFunction, void *callbackData)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(INFO, this);
|
||||
FUNCTION_LOG_PARAM(INI, ini);
|
||||
FUNCTION_LOG_PARAM(STORAGE, storage);
|
||||
FUNCTION_LOG_PARAM(STRING, fileName);
|
||||
FUNCTION_LOG_PARAM(ENUM, cipherType);
|
||||
FUNCTION_TEST_PARAM(STRING, cipherPass);
|
||||
FUNCTION_LOG_PARAM(IO_WRITE, write);
|
||||
FUNCTION_LOG_PARAM(FUNCTIONP, callbackFunction);
|
||||
FUNCTION_LOG_PARAM_P(VOID, callbackData);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
ASSERT(ini != NULL);
|
||||
ASSERT(storage != NULL);
|
||||
ASSERT(fileName != NULL);
|
||||
ASSERT(cipherType == cipherTypeNone || cipherPass != NULL);
|
||||
ASSERT(
|
||||
!((cipherType != cipherTypeNone && this->cipherPass == NULL) ||
|
||||
(cipherType == cipherTypeNone && this->cipherPass != NULL)));
|
||||
ASSERT(write != NULL);
|
||||
ASSERT(callbackFunction != NULL);
|
||||
ASSERT(callbackData != NULL);
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
InfoSave data =
|
||||
{
|
||||
.memContext = MEM_CONTEXT_TEMP(),
|
||||
.write = write,
|
||||
};
|
||||
|
||||
ioWriteOpen(data.write);
|
||||
|
||||
// Begin checksum calculation
|
||||
data.checksum = cryptoHashNew(HASH_TYPE_SHA1_STR);
|
||||
INFO_CHECKSUM_BEGIN(data.checksum);
|
||||
|
||||
// Add version and format
|
||||
iniSet(ini, INFO_SECTION_BACKREST_STR, INFO_KEY_VERSION_STR, jsonFromStr(STRDEF(PROJECT_VERSION)));
|
||||
iniSet(ini, INFO_SECTION_BACKREST_STR, INFO_KEY_FORMAT_STR, jsonFromUInt(REPOSITORY_FORMAT));
|
||||
callbackFunction(callbackData, INFO_SECTION_BACKREST_STR, &data);
|
||||
infoSaveValue(&data, INFO_SECTION_BACKREST_STR, INFO_KEY_FORMAT_STR, jsonFromUInt(REPOSITORY_FORMAT));
|
||||
infoSaveValue(&data, INFO_SECTION_BACKREST_STR, INFO_KEY_VERSION_STR, jsonFromStr(STRDEF(PROJECT_VERSION)));
|
||||
|
||||
// Add cipher passphrase if defined
|
||||
if (this->cipherPass != NULL)
|
||||
iniSet(ini, INFO_SECTION_CIPHER_STR, INFO_KEY_CIPHER_PASS_STR, jsonFromStr(this->cipherPass));
|
||||
|
||||
// Add checksum (this must be set after all other values or it will not be valid)
|
||||
iniSet(ini, INFO_SECTION_BACKREST_STR, INFO_KEY_CHECKSUM_STR, jsonFromStr(infoHash(ini)));
|
||||
|
||||
// Save info file
|
||||
IoWrite *infoWrite = storageWriteIo(storageNewWriteP(storage, fileName, .compressible = cipherType == cipherTypeNone));
|
||||
|
||||
if (cipherType != cipherTypeNone)
|
||||
{
|
||||
ioFilterGroupAdd(
|
||||
ioWriteFilterGroup(infoWrite), cipherBlockNew(cipherModeEncrypt, cipherType, BUFSTR(cipherPass), NULL));
|
||||
callbackFunction(callbackData, INFO_SECTION_CIPHER_STR, &data);
|
||||
infoSaveValue(&data, INFO_SECTION_CIPHER_STR, INFO_KEY_CIPHER_PASS_STR, jsonFromStr(this->cipherPass));
|
||||
}
|
||||
|
||||
iniSave(ini, infoWrite);
|
||||
// Flush out any additional sections
|
||||
callbackFunction(callbackData, NULL, &data);
|
||||
|
||||
// Copy to .copy file
|
||||
storageCopyNP(
|
||||
storageNewReadNP(storage, fileName), storageNewWriteNP(storage, strNewFmt("%s" INFO_COPY_EXT, strPtr(fileName))));
|
||||
// Add checksum (this must be set after all other values or it will not be valid)
|
||||
INFO_CHECKSUM_END(data.checksum);
|
||||
|
||||
ioWrite(data.write, BUFSTRDEF("\n[" INFO_SECTION_BACKREST "]\n" INFO_KEY_CHECKSUM "="));
|
||||
ioWriteLine(data.write, BUFSTR(jsonFromVar(ioFilterResult(data.checksum), 0)));
|
||||
|
||||
// Close the file
|
||||
ioWriteClose(data.write);
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
@@ -396,3 +450,78 @@ infoCipherPass(const Info *this)
|
||||
|
||||
FUNCTION_TEST_RETURN(this->cipherPass);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Load info file(s) and throw error for each attempt if none are successful
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
infoLoad(const String *error, InfoLoadCallback *callbackFunction, void *callbackData)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelTrace);
|
||||
FUNCTION_LOG_PARAM(STRING, error);
|
||||
FUNCTION_LOG_PARAM(FUNCTIONP, callbackFunction);
|
||||
FUNCTION_LOG_PARAM_P(VOID, callbackData);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(error != NULL);
|
||||
ASSERT(callbackFunction != NULL);
|
||||
ASSERT(callbackData != NULL);
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
unsigned int try = 0;
|
||||
bool done = false;
|
||||
bool loaded = false;
|
||||
const ErrorType *loadErrorType = NULL;
|
||||
String *loadErrorMessage = NULL;
|
||||
|
||||
do
|
||||
{
|
||||
// Attempt to load the file
|
||||
TRY_BEGIN()
|
||||
{
|
||||
loaded = callbackFunction(callbackData, try);
|
||||
done = true;
|
||||
|
||||
// There must be at least one attempt to the load file
|
||||
ASSERT(loaded || try > 0);
|
||||
}
|
||||
CATCH_ANY()
|
||||
{
|
||||
// Set error type if none has been set
|
||||
if (loadErrorType == NULL)
|
||||
{
|
||||
loadErrorType = errorType();
|
||||
loadErrorMessage = strNewFmt("%s:", strPtr(error));
|
||||
}
|
||||
// Else if the error type is different
|
||||
else if (loadErrorType != errorType())
|
||||
{
|
||||
// Set type that is not file missing (which is likely the most common error)
|
||||
if (loadErrorType == &FileMissingError)
|
||||
{
|
||||
loadErrorType = errorType();
|
||||
}
|
||||
// Else set a generic error
|
||||
else if (errorType() != &FileMissingError)
|
||||
loadErrorType = &FileOpenError;
|
||||
}
|
||||
|
||||
// Append new error
|
||||
strCatFmt(loadErrorMessage, "\n%s: %s", errorTypeName(errorType()), errorMessage());
|
||||
|
||||
// Try again
|
||||
try++;
|
||||
}
|
||||
TRY_END();
|
||||
}
|
||||
while (!done);
|
||||
|
||||
// Error when no file was loaded
|
||||
if (!loaded)
|
||||
THROWP(loadErrorType, strPtr(loadErrorMessage));
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_LOG_RETURN_VOID();
|
||||
}
|
||||
|
||||
+24
-9
@@ -11,8 +11,8 @@ Object type
|
||||
#define INFO_PREFIX info
|
||||
|
||||
typedef struct Info Info;
|
||||
typedef struct InfoSave InfoSave;
|
||||
|
||||
#include "common/crypto/common.h"
|
||||
#include "common/ini.h"
|
||||
#include "storage/storage.h"
|
||||
|
||||
@@ -26,29 +26,39 @@ Constants
|
||||
#define INFO_KEY_VERSION "backrest-version"
|
||||
STRING_DECLARE(INFO_KEY_FORMAT_STR);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Function types for loading and saving
|
||||
***********************************************************************************************************************************/
|
||||
// The purpose of this callback is to attempt a load (from file or otherwise). Return true when the load is successful or throw an
|
||||
// error. Return false when there are no more loads to try, but always make at least one load attempt. The try parameter will
|
||||
// start at 0 and be incremented on each call.
|
||||
typedef bool InfoLoadCallback(void *data, unsigned int try);
|
||||
|
||||
typedef void InfoLoadNewCallback(void *data, const String *section, const String *key, const String *value);
|
||||
typedef void InfoSaveCallback(void *data, const String *sectionNext, InfoSave *infoSaveData);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Constructors
|
||||
***********************************************************************************************************************************/
|
||||
Info *infoNew(CipherType cipherType, const String *cipherPassSub);
|
||||
Info *infoNewLoad(const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass, Ini **ini);
|
||||
Info *infoNew(const String *cipherPassSub);
|
||||
Info *infoNewLoad(IoRead *read, InfoLoadNewCallback *callbackFunction, void *callbackData);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
***********************************************************************************************************************************/
|
||||
void infoSave(
|
||||
Info *this, Ini *ini, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass);
|
||||
void infoSave(Info *this, IoWrite *write, InfoSaveCallback *callbackFunction, void *callbackData);
|
||||
bool infoSaveSection(InfoSave *infoSaveData, const String *section, const String *sectionNext);
|
||||
void infoSaveValue(InfoSave *infoSaveData, const String *section, const String *key, const String *jsonValue);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Getters
|
||||
***********************************************************************************************************************************/
|
||||
const String *infoCipherPass(const Info *this);
|
||||
String *infoHash(const Ini *ini);
|
||||
Ini *infoIni(const Info *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Destructor
|
||||
Helper functions
|
||||
***********************************************************************************************************************************/
|
||||
void infoFree(Info *this);
|
||||
void infoLoad(const String *error, InfoLoadCallback *callbackFunction, void *callbackData);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
@@ -58,4 +68,9 @@ Macros for function logging
|
||||
#define FUNCTION_LOG_INFO_FORMAT(value, buffer, bufferSize) \
|
||||
objToLog(value, "Info", buffer, bufferSize)
|
||||
|
||||
#define FUNCTION_LOG_INFO_SAVE_TYPE \
|
||||
InfoSave *
|
||||
#define FUNCTION_LOG_INFO_SAVE_FORMAT(value, buffer, bufferSize) \
|
||||
objToLog(value, "InfoSave", buffer, bufferSize)
|
||||
|
||||
#endif
|
||||
|
||||
+212
-111
@@ -8,6 +8,7 @@ Archive Info Handler
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "common/crypto/cipherBlock.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/log.h"
|
||||
#include "common/ini.h"
|
||||
@@ -32,7 +33,6 @@ struct InfoArchive
|
||||
{
|
||||
MemContext *memContext; // Mem context
|
||||
InfoPg *infoPg; // Contents of the DB data
|
||||
String *archiveId; // Archive id for the current PG version
|
||||
};
|
||||
|
||||
OBJECT_DEFINE_FREE(INFO_ARCHIVE);
|
||||
@@ -43,141 +43,67 @@ Internal constructor
|
||||
static InfoArchive *
|
||||
infoArchiveNewInternal(void)
|
||||
{
|
||||
FUNCTION_LOG_VOID(logLevelTrace);
|
||||
FUNCTION_TEST_VOID();
|
||||
|
||||
InfoArchive *this = memNew(sizeof(InfoArchive));
|
||||
this->memContext = memContextCurrent();
|
||||
|
||||
FUNCTION_TEST_RETURN(this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Create new object without loading it from a file
|
||||
***********************************************************************************************************************************/
|
||||
InfoArchive *
|
||||
infoArchiveNew(unsigned int pgVersion, uint64_t pgSystemId, const String *cipherPassSub)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(UINT, pgVersion);
|
||||
FUNCTION_LOG_PARAM(UINT64, pgSystemId);
|
||||
FUNCTION_TEST_PARAM(STRING, cipherPassSub);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(pgVersion > 0 && pgSystemId > 0);
|
||||
|
||||
InfoArchive *this = NULL;
|
||||
|
||||
MEM_CONTEXT_NEW_BEGIN("InfoArchive")
|
||||
{
|
||||
// Create object
|
||||
this = memNew(sizeof(InfoArchive));
|
||||
this->memContext = MEM_CONTEXT_NEW();
|
||||
this = infoArchiveNewInternal();
|
||||
|
||||
// Initialize the pg data
|
||||
this->infoPg = infoPgNew(infoPgArchive, cipherPassSub);
|
||||
infoArchivePgSet(this, pgVersion, pgSystemId);
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
FUNCTION_LOG_RETURN(INFO_ARCHIVE, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Create new object without loading it from a file
|
||||
***********************************************************************************************************************************/
|
||||
InfoArchive *
|
||||
infoArchiveNew(unsigned int pgVersion, uint64_t pgSystemId, CipherType cipherType, const String *cipherPassSub)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(UINT, pgVersion);
|
||||
FUNCTION_LOG_PARAM(UINT64, pgSystemId);
|
||||
FUNCTION_LOG_PARAM(ENUM, cipherType);
|
||||
FUNCTION_TEST_PARAM(STRING, cipherPassSub);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(pgVersion > 0 && pgSystemId > 0);
|
||||
|
||||
InfoArchive *this = infoArchiveNewInternal();
|
||||
|
||||
// Initialize the pg data
|
||||
this->infoPg = infoPgNew(cipherType, cipherPassSub);
|
||||
infoArchivePgSet(this, pgVersion, pgSystemId);
|
||||
|
||||
FUNCTION_LOG_RETURN(INFO_ARCHIVE, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Create new object and load contents from a file
|
||||
***********************************************************************************************************************************/
|
||||
InfoArchive *
|
||||
infoArchiveNewLoad(const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass)
|
||||
static InfoArchive *
|
||||
infoArchiveNewLoad(IoRead *read)
|
||||
{
|
||||
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_PARAM(IO_READ, read);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(storage != NULL);
|
||||
ASSERT(fileName != NULL);
|
||||
ASSERT(cipherType == cipherTypeNone || cipherPass != NULL);
|
||||
ASSERT(read != NULL);
|
||||
|
||||
InfoArchive *this = infoArchiveNewInternal();
|
||||
InfoArchive *this = NULL;
|
||||
|
||||
MEM_CONTEXT_BEGIN(this->memContext)
|
||||
MEM_CONTEXT_NEW_BEGIN("InfoArchive")
|
||||
{
|
||||
// Catch file missing error and add archive-specific hints before rethrowing
|
||||
TRY_BEGIN()
|
||||
{
|
||||
this->infoPg = infoPgNewLoad(storage, fileName, infoPgArchive, cipherType, cipherPass, NULL);
|
||||
this = infoArchiveNewInternal();
|
||||
this->infoPg = infoPgNewLoad(read, infoPgArchive, NULL, NULL);
|
||||
}
|
||||
CATCH_ANY()
|
||||
{
|
||||
THROWP_FMT(
|
||||
errorType(),
|
||||
"%s\n"
|
||||
"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.",
|
||||
errorMessage());
|
||||
}
|
||||
TRY_END();
|
||||
|
||||
// Store the archiveId for the current PG db-version db-id
|
||||
this->archiveId = infoPgArchiveId(this->infoPg, infoPgDataCurrentId(this->infoPg));
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
FUNCTION_LOG_RETURN(INFO_ARCHIVE, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Set the infoPg data
|
||||
***********************************************************************************************************************************/
|
||||
InfoArchive *
|
||||
infoArchivePgSet(InfoArchive *this, unsigned int pgVersion, uint64_t pgSystemId)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(INFO_ARCHIVE, this);
|
||||
FUNCTION_LOG_PARAM(UINT, pgVersion);
|
||||
FUNCTION_LOG_PARAM(UINT64, pgSystemId);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
|
||||
this->infoPg = infoPgSet(this->infoPg, infoPgArchive, pgVersion, pgSystemId, 0, 0);
|
||||
this->archiveId = infoPgArchiveId(this->infoPg, infoPgDataCurrentId(this->infoPg));
|
||||
|
||||
FUNCTION_LOG_RETURN(INFO_ARCHIVE, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Save to file
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
infoArchiveSave(
|
||||
InfoArchive *this, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(INFO_ARCHIVE, this);
|
||||
FUNCTION_LOG_PARAM(STORAGE, storage);
|
||||
FUNCTION_LOG_PARAM(STRING, fileName);
|
||||
FUNCTION_LOG_PARAM(ENUM, cipherType);
|
||||
FUNCTION_TEST_PARAM(STRING, cipherPass);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
ASSERT(storage != NULL);
|
||||
ASSERT(fileName != NULL);
|
||||
ASSERT(cipherType == cipherTypeNone || cipherPass != NULL);
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
infoPgSave(infoArchivePg(this), iniNew(), storage, fileName, infoPgArchive, cipherType, cipherPass);
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_LOG_RETURN_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Given a backrest history id and postgres systemId and version, return the archiveId of the best match
|
||||
***********************************************************************************************************************************/
|
||||
@@ -237,6 +163,29 @@ infoArchiveIdHistoryMatch(
|
||||
FUNCTION_LOG_RETURN(STRING, archiveId);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Save to file
|
||||
***********************************************************************************************************************************/
|
||||
static void
|
||||
infoArchiveSave(InfoArchive *this, IoWrite *write)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(INFO_ARCHIVE, this);
|
||||
FUNCTION_LOG_PARAM(IO_WRITE, write);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
ASSERT(write != NULL);
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
infoPgSave(infoArchivePg(this), write, NULL, NULL);
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_LOG_RETURN_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Get the current archive id
|
||||
***********************************************************************************************************************************/
|
||||
@@ -249,7 +198,7 @@ infoArchiveId(const InfoArchive *this)
|
||||
|
||||
ASSERT(this != NULL);
|
||||
|
||||
FUNCTION_TEST_RETURN(this->archiveId);
|
||||
FUNCTION_TEST_RETURN(infoPgArchiveId(this->infoPg, infoPgDataCurrentId(this->infoPg)));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@@ -281,3 +230,155 @@ infoArchivePg(const InfoArchive *this)
|
||||
|
||||
FUNCTION_TEST_RETURN(this->infoPg);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Set the infoPg data
|
||||
***********************************************************************************************************************************/
|
||||
InfoArchive *
|
||||
infoArchivePgSet(InfoArchive *this, unsigned int pgVersion, uint64_t pgSystemId)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(INFO_ARCHIVE, this);
|
||||
FUNCTION_LOG_PARAM(UINT, pgVersion);
|
||||
FUNCTION_LOG_PARAM(UINT64, pgSystemId);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
|
||||
this->infoPg = infoPgSet(this->infoPg, infoPgArchive, pgVersion, pgSystemId, 0, 0);
|
||||
|
||||
FUNCTION_LOG_RETURN(INFO_ARCHIVE, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Helper function to load archive info files
|
||||
***********************************************************************************************************************************/
|
||||
typedef struct InfoArchiveLoadFileData
|
||||
{
|
||||
MemContext *memContext; // Mem context
|
||||
const Storage *storage; // Storage to load from
|
||||
const String *fileName; // Base filename
|
||||
CipherType cipherType; // Cipher type
|
||||
const String *cipherPass; // Cipher passphrase
|
||||
InfoArchive *infoArchive; // Loaded infoArchive object
|
||||
} InfoArchiveLoadFileData;
|
||||
|
||||
static bool
|
||||
infoArchiveLoadFileCallback(void *data, unsigned int try)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelTrace);
|
||||
FUNCTION_LOG_PARAM_P(VOID, data);
|
||||
FUNCTION_LOG_PARAM(UINT, try);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(data != NULL);
|
||||
|
||||
InfoArchiveLoadFileData *loadData = (InfoArchiveLoadFileData *)data;
|
||||
bool result = false;
|
||||
|
||||
if (try < 2)
|
||||
{
|
||||
// Construct filename based on try
|
||||
const String *fileName = try == 0 ? loadData->fileName : strNewFmt("%s" INFO_COPY_EXT, strPtr(loadData->fileName));
|
||||
|
||||
// Attempt to load the file
|
||||
IoRead *read = storageReadIo(storageNewReadNP(loadData->storage, fileName));
|
||||
cipherBlockFilterGroupAdd(ioReadFilterGroup(read), loadData->cipherType, cipherModeDecrypt, loadData->cipherPass);
|
||||
|
||||
MEM_CONTEXT_BEGIN(loadData->memContext)
|
||||
{
|
||||
loadData->infoArchive = infoArchiveNewLoad(read);
|
||||
result = true;
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
}
|
||||
|
||||
FUNCTION_LOG_RETURN(BOOL, result);
|
||||
}
|
||||
|
||||
InfoArchive *
|
||||
infoArchiveLoadFile(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));
|
||||
|
||||
InfoArchiveLoadFileData data =
|
||||
{
|
||||
.memContext = memContextCurrent(),
|
||||
.storage = storage,
|
||||
.fileName = fileName,
|
||||
.cipherType = cipherType,
|
||||
.cipherPass = cipherPass,
|
||||
};
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
const char *fileNamePath = strPtr(storagePathNP(storage, fileName));
|
||||
|
||||
TRY_BEGIN()
|
||||
{
|
||||
infoLoad(
|
||||
strNewFmt("unable to load info file '%s' or '%s" INFO_COPY_EXT "'", fileNamePath, fileNamePath),
|
||||
infoArchiveLoadFileCallback, &data);
|
||||
}
|
||||
CATCH_ANY()
|
||||
{
|
||||
THROWP_FMT(
|
||||
errorType(),
|
||||
"%s\n"
|
||||
"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.",
|
||||
errorMessage());
|
||||
}
|
||||
TRY_END();
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_LOG_RETURN(INFO_ARCHIVE, data.infoArchive);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Helper function to save archive info files
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
infoArchiveSaveFile(
|
||||
InfoArchive *infoArchive, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(INFO_ARCHIVE, infoArchive);
|
||||
FUNCTION_LOG_PARAM(STORAGE, storage);
|
||||
FUNCTION_LOG_PARAM(STRING, fileName);
|
||||
FUNCTION_LOG_PARAM(ENUM, cipherType);
|
||||
FUNCTION_TEST_PARAM(STRING, cipherPass);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(infoArchive != NULL);
|
||||
ASSERT(storage != NULL);
|
||||
ASSERT(fileName != NULL);
|
||||
ASSERT((cipherType == cipherTypeNone && cipherPass == NULL) || (cipherType != cipherTypeNone && cipherPass != NULL));
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
// Save the file
|
||||
IoWrite *write = storageWriteIo(storageNewWriteNP(storage, fileName));
|
||||
cipherBlockFilterGroupAdd(ioWriteFilterGroup(write), cipherType, cipherModeEncrypt, cipherPass);
|
||||
infoArchiveSave(infoArchive, write);
|
||||
|
||||
// Make a copy of the file
|
||||
storageCopy(
|
||||
storageNewReadNP(storage, fileName), storageNewWriteNP(storage, strNewFmt("%s" INFO_COPY_EXT, strPtr(fileName))));
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_LOG_RETURN_VOID();
|
||||
}
|
||||
|
||||
@@ -31,10 +31,7 @@ Archive info filename
|
||||
/***********************************************************************************************************************************
|
||||
Constructors
|
||||
***********************************************************************************************************************************/
|
||||
InfoArchive *infoArchiveNew(
|
||||
const unsigned int pgVersion, const uint64_t pgSystemId, CipherType cipherType, const String *cipherPassSub);
|
||||
InfoArchive *infoArchiveNewLoad(
|
||||
const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass);
|
||||
InfoArchive *infoArchiveNew(const unsigned int pgVersion, const uint64_t pgSystemId, const String *cipherPassSub);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
@@ -43,8 +40,6 @@ const String *infoArchiveIdHistoryMatch(
|
||||
const InfoArchive *this, const unsigned int historyId, const unsigned int pgVersion, const uint64_t pgSystemId);
|
||||
InfoArchive *infoArchivePgSet(
|
||||
InfoArchive *this, unsigned int pgVersion, uint64_t pgSystemId);
|
||||
void infoArchiveSave(
|
||||
InfoArchive *this, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Getters
|
||||
@@ -58,6 +53,14 @@ Destructor
|
||||
***********************************************************************************************************************************/
|
||||
void infoArchiveFree(InfoArchive *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Helper functions
|
||||
***********************************************************************************************************************************/
|
||||
InfoArchive *infoArchiveLoadFile(
|
||||
const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass);
|
||||
void infoArchiveSaveFile(
|
||||
InfoArchive *infoArchive, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
|
||||
+243
-106
@@ -8,6 +8,7 @@ Backup Info Handler
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "common/crypto/cipherBlock.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/ini.h"
|
||||
#include "common/log.h"
|
||||
@@ -28,6 +29,7 @@ Constants
|
||||
***********************************************************************************************************************************/
|
||||
#define INFO_BACKUP_SECTION "backup"
|
||||
#define INFO_BACKUP_SECTION_BACKUP_CURRENT INFO_BACKUP_SECTION ":current"
|
||||
STRING_STATIC(INFO_BACKUP_SECTION_BACKUP_CURRENT_STR, INFO_BACKUP_SECTION_BACKUP_CURRENT);
|
||||
|
||||
VARIANT_STRDEF_STATIC(INFO_BACKUP_KEY_BACKUP_ARCHIVE_START_VAR, "backup-archive-start");
|
||||
VARIANT_STRDEF_STATIC(INFO_BACKUP_KEY_BACKUP_ARCHIVE_STOP_VAR, "backup-archive-stop");
|
||||
@@ -69,102 +71,75 @@ Create new object
|
||||
static InfoBackup *
|
||||
infoBackupNewInternal(void)
|
||||
{
|
||||
FUNCTION_LOG_VOID(logLevelTrace);
|
||||
FUNCTION_TEST_VOID();
|
||||
|
||||
InfoBackup *this = memNew(sizeof(InfoBackup));
|
||||
this->memContext = memContextCurrent();
|
||||
this->backup = lstNew(sizeof(InfoBackupData));
|
||||
|
||||
FUNCTION_TEST_RETURN(this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Create new object without loading it from a file
|
||||
***********************************************************************************************************************************/
|
||||
InfoBackup *
|
||||
infoBackupNew(
|
||||
unsigned int pgVersion, uint64_t pgSystemId, const uint32_t pgControlVersion, const uint32_t pgCatalogVersion,
|
||||
const String *cipherPassSub)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(UINT, pgVersion);
|
||||
FUNCTION_LOG_PARAM(UINT64, pgSystemId);
|
||||
FUNCTION_LOG_PARAM(UINT32, pgControlVersion);
|
||||
FUNCTION_LOG_PARAM(UINT32, pgCatalogVersion);
|
||||
FUNCTION_TEST_PARAM(STRING, cipherPassSub);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(pgVersion > 0 && pgSystemId > 0 && pgControlVersion > 0 && pgCatalogVersion > 0);
|
||||
|
||||
InfoBackup *this = NULL;
|
||||
|
||||
MEM_CONTEXT_NEW_BEGIN("InfoBackup")
|
||||
{
|
||||
// Create object
|
||||
this = memNew(sizeof(InfoBackup));
|
||||
this->memContext = MEM_CONTEXT_NEW();
|
||||
this = infoBackupNewInternal();
|
||||
|
||||
// Initialize the pg data
|
||||
this->infoPg = infoPgNew(infoPgBackup, cipherPassSub);
|
||||
infoBackupPgSet(this, pgVersion, pgSystemId, pgControlVersion, pgCatalogVersion);
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
FUNCTION_LOG_RETURN(INFO_BACKUP, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Create new object without loading it from a file
|
||||
***********************************************************************************************************************************/
|
||||
InfoBackup *
|
||||
infoBackupNew(unsigned int pgVersion, uint64_t pgSystemId, const uint32_t pgControlVersion, const uint32_t pgCatalogVersion,
|
||||
CipherType cipherType, const String *cipherPassSub)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(UINT, pgVersion);
|
||||
FUNCTION_LOG_PARAM(UINT64, pgSystemId);
|
||||
FUNCTION_LOG_PARAM(ENUM, cipherType);
|
||||
FUNCTION_TEST_PARAM(STRING, cipherPassSub);
|
||||
FUNCTION_LOG_PARAM(UINT32, pgControlVersion);
|
||||
FUNCTION_LOG_PARAM(UINT32, pgCatalogVersion);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(pgVersion > 0 && pgSystemId > 0 && pgControlVersion > 0 && pgCatalogVersion > 0);
|
||||
|
||||
InfoBackup *this = infoBackupNewInternal();
|
||||
|
||||
// Initialize the pg data
|
||||
this->infoPg = infoPgNew(cipherType, cipherPassSub);
|
||||
infoBackupPgSet(this, pgVersion, pgSystemId, pgControlVersion, pgCatalogVersion);
|
||||
|
||||
FUNCTION_LOG_RETURN(INFO_BACKUP, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Create new object and load contents from a file
|
||||
***********************************************************************************************************************************/
|
||||
InfoBackup *
|
||||
infoBackupNewLoad(const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass)
|
||||
static void
|
||||
infoBackupLoadCallback(void *data, const String *section, const String *key, const String *value)
|
||||
{
|
||||
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();
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM_P(VOID, data);
|
||||
FUNCTION_TEST_PARAM(STRING, section);
|
||||
FUNCTION_TEST_PARAM(STRING, key);
|
||||
FUNCTION_TEST_PARAM(STRING, value);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(storage != NULL);
|
||||
ASSERT(fileName != NULL);
|
||||
ASSERT(cipherType == cipherTypeNone || cipherPass != NULL);
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(section != NULL);
|
||||
ASSERT(key != NULL);
|
||||
ASSERT(value != NULL);
|
||||
|
||||
InfoBackup *this = infoBackupNewInternal();
|
||||
InfoBackup *infoBackup = (InfoBackup *)data;
|
||||
|
||||
MEM_CONTEXT_BEGIN(this->memContext)
|
||||
// Process current backup list
|
||||
if (strEq(section, INFO_BACKUP_SECTION_BACKUP_CURRENT_STR))
|
||||
{
|
||||
Ini *ini = NULL;
|
||||
const KeyValue *backupKv = jsonToKv(value);
|
||||
|
||||
// Catch file missing error and add backup-specific hints before rethrowing
|
||||
TRY_BEGIN()
|
||||
MEM_CONTEXT_BEGIN(lstMemContext(infoBackup->backup))
|
||||
{
|
||||
this->infoPg = infoPgNewLoad(storage, fileName, infoPgBackup, cipherType, cipherPass, &ini);
|
||||
}
|
||||
CATCH_ANY()
|
||||
{
|
||||
THROWP_FMT(
|
||||
errorType(),
|
||||
"%s\n"
|
||||
"HINT: backup.info cannot be opened and is required to perform a backup.\n"
|
||||
"HINT: has a stanza-create been performed?",
|
||||
errorMessage());
|
||||
}
|
||||
TRY_END();
|
||||
|
||||
const String *backupCurrentSection = STRDEF(INFO_BACKUP_SECTION_BACKUP_CURRENT);
|
||||
|
||||
// If there are current backups, then parse the json for each into a list object
|
||||
if (strLstExists(iniSectionList(ini), backupCurrentSection))
|
||||
{
|
||||
// Initialize the store and get the list of backup labels
|
||||
this->backup = lstNew(sizeof(InfoBackupData));
|
||||
const StringList *backupLabelList = iniSectionKeyList(ini, backupCurrentSection);
|
||||
|
||||
// For each backup label, store the information
|
||||
for (unsigned int backupLabelIdx = 0; backupLabelIdx < strLstSize(backupLabelList); backupLabelIdx++)
|
||||
{
|
||||
const String *backupLabelKey = strLstGet(backupLabelList, backupLabelIdx);
|
||||
const KeyValue *backupKv = jsonToKv(iniGet(ini, backupCurrentSection, backupLabelKey));
|
||||
|
||||
InfoBackupData infoBackupData =
|
||||
{
|
||||
.backrestFormat = varUIntForce(kvGet(backupKv, VARSTR(INFO_KEY_FORMAT_STR))),
|
||||
@@ -173,16 +148,16 @@ infoBackupNewLoad(const Storage *storage, const String *fileName, CipherType cip
|
||||
.backupInfoRepoSizeDelta = varUInt64(kvGet(backupKv, INFO_BACKUP_KEY_BACKUP_INFO_REPO_SIZE_DELTA_VAR)),
|
||||
.backupInfoSize = varUInt64(kvGet(backupKv, INFO_BACKUP_KEY_BACKUP_INFO_SIZE_VAR)),
|
||||
.backupInfoSizeDelta = varUInt64(kvGet(backupKv, INFO_BACKUP_KEY_BACKUP_INFO_SIZE_DELTA_VAR)),
|
||||
.backupLabel = strDup(backupLabelKey),
|
||||
.backupLabel = strDup(key),
|
||||
.backupPgId = cvtZToUInt(strPtr(varStrForce(kvGet(backupKv, INFO_KEY_DB_ID_VAR)))),
|
||||
.backupTimestampStart = varUInt64(kvGet(backupKv, INFO_BACKUP_KEY_BACKUP_TIMESTAMP_START_VAR)),
|
||||
.backupTimestampStop= varUInt64(kvGet(backupKv, INFO_BACKUP_KEY_BACKUP_TIMESTAMP_STOP_VAR)),
|
||||
.backupType = varStrForce(kvGet(backupKv, INFO_BACKUP_KEY_BACKUP_TYPE_VAR)),
|
||||
|
||||
// Possible NULL values
|
||||
.backupArchiveStart = varStr(kvGet(backupKv, INFO_BACKUP_KEY_BACKUP_ARCHIVE_START_VAR)),
|
||||
.backupArchiveStop = varStr(kvGet(backupKv, INFO_BACKUP_KEY_BACKUP_ARCHIVE_STOP_VAR)),
|
||||
.backupPrior = varStr(kvGet(backupKv, INFO_BACKUP_KEY_BACKUP_PRIOR_VAR)),
|
||||
.backupArchiveStart = strDup(varStr(kvGet(backupKv, INFO_BACKUP_KEY_BACKUP_ARCHIVE_START_VAR))),
|
||||
.backupArchiveStop = strDup(varStr(kvGet(backupKv, INFO_BACKUP_KEY_BACKUP_ARCHIVE_STOP_VAR))),
|
||||
.backupPrior = strDup(varStr(kvGet(backupKv, INFO_BACKUP_KEY_BACKUP_PRIOR_VAR))),
|
||||
.backupReference =
|
||||
kvGet(backupKv, INFO_BACKUP_KEY_BACKUP_REFERENCE_VAR) != NULL ?
|
||||
strLstNewVarLst(varVarLst(kvGet(backupKv, INFO_BACKUP_KEY_BACKUP_REFERENCE_VAR))) : NULL,
|
||||
@@ -198,13 +173,31 @@ infoBackupNewLoad(const Storage *storage, const String *fileName, CipherType cip
|
||||
};
|
||||
|
||||
// Add the backup data to the list
|
||||
lstAdd(this->backup, &infoBackupData);
|
||||
}
|
||||
}
|
||||
|
||||
iniFree(ini);
|
||||
lstAdd(infoBackup->backup, &infoBackupData);
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
}
|
||||
|
||||
FUNCTION_TEST_RETURN_VOID();
|
||||
}
|
||||
|
||||
static InfoBackup *
|
||||
infoBackupNewLoad(IoRead *read)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(IO_READ, read);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(read != NULL);
|
||||
|
||||
InfoBackup *this = NULL;
|
||||
|
||||
MEM_CONTEXT_NEW_BEGIN("InfoBackup")
|
||||
{
|
||||
this = infoBackupNewInternal();
|
||||
this->infoPg = infoPgNewLoad(read, infoPgBackup, infoBackupLoadCallback, this);
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
FUNCTION_LOG_RETURN(INFO_BACKUP, this);
|
||||
}
|
||||
@@ -212,31 +205,26 @@ infoBackupNewLoad(const Storage *storage, const String *fileName, CipherType cip
|
||||
/***********************************************************************************************************************************
|
||||
Save to file
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
infoBackupSave(
|
||||
InfoBackup *this, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass)
|
||||
static void
|
||||
infoBackupSaveCallback(void *data, const String *sectionNext, InfoSave *infoSaveData)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(INFO_BACKUP, this);
|
||||
FUNCTION_LOG_PARAM(STORAGE, storage);
|
||||
FUNCTION_LOG_PARAM(STRING, fileName);
|
||||
FUNCTION_LOG_PARAM(ENUM, cipherType);
|
||||
FUNCTION_TEST_PARAM(STRING, cipherPass);
|
||||
FUNCTION_LOG_END();
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM_P(VOID, data);
|
||||
FUNCTION_TEST_PARAM(STRING, sectionNext);
|
||||
FUNCTION_TEST_PARAM(INFO_SAVE, infoSaveData);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
ASSERT(storage != NULL);
|
||||
ASSERT(fileName != NULL);
|
||||
ASSERT(cipherType == cipherTypeNone || cipherPass != NULL);
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(infoSaveData != NULL);
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
InfoBackup *infoBackup = (InfoBackup *)data;
|
||||
|
||||
if (infoSaveSection(infoSaveData, INFO_BACKUP_SECTION_BACKUP_CURRENT_STR, sectionNext))
|
||||
{
|
||||
Ini *ini = iniNew();
|
||||
|
||||
// Set the backup current section
|
||||
for (unsigned int backupIdx = 0; backupIdx < infoBackupDataTotal(this); backupIdx++)
|
||||
for (unsigned int backupIdx = 0; backupIdx < infoBackupDataTotal(infoBackup); backupIdx++)
|
||||
{
|
||||
InfoBackupData backupData = infoBackupData(this, backupIdx);
|
||||
InfoBackupData backupData = infoBackupData(infoBackup, backupIdx);
|
||||
|
||||
KeyValue *backupDataKv = kvNew();
|
||||
kvPut(backupDataKv, VARSTR(INFO_KEY_FORMAT_STR), VARUINT(backupData.backrestFormat));
|
||||
@@ -272,10 +260,28 @@ infoBackupSave(
|
||||
kvPut(backupDataKv, INFO_BACKUP_KEY_OPT_HARDLINK_VAR, VARBOOL(backupData.optionHardlink));
|
||||
kvPut(backupDataKv, INFO_BACKUP_KEY_OPT_ONLINE_VAR, VARBOOL(backupData.optionOnline));
|
||||
|
||||
iniSet(ini, STRDEF(INFO_BACKUP_SECTION_BACKUP_CURRENT), backupData.backupLabel, jsonFromKv(backupDataKv, 0));
|
||||
infoSaveValue(
|
||||
infoSaveData, INFO_BACKUP_SECTION_BACKUP_CURRENT_STR, backupData.backupLabel, jsonFromKv(backupDataKv, 0));
|
||||
}
|
||||
}
|
||||
|
||||
infoPgSave(infoBackupPg(this), ini, storage, fileName, infoPgBackup, cipherType, cipherPass);
|
||||
FUNCTION_TEST_RETURN_VOID();
|
||||
}
|
||||
|
||||
static void
|
||||
infoBackupSave(InfoBackup *this, IoWrite *write)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(INFO_BACKUP, this);
|
||||
FUNCTION_LOG_PARAM(IO_WRITE, write);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
ASSERT(write != NULL);
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
infoPgSave(infoBackupPg(this), write, infoBackupSaveCallback, this);
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
@@ -328,7 +334,7 @@ infoBackupDataTotal(const InfoBackup *this)
|
||||
|
||||
ASSERT(this != NULL);
|
||||
|
||||
FUNCTION_TEST_RETURN((this->backup == NULL ? 0 : lstSize(this->backup)));
|
||||
FUNCTION_TEST_RETURN(lstSize(this->backup));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@@ -423,6 +429,137 @@ infoBackupCipherPass(const InfoBackup *this)
|
||||
FUNCTION_TEST_RETURN(infoPgCipherPass(this->infoPg));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Helper function to load backup info files
|
||||
***********************************************************************************************************************************/
|
||||
typedef struct InfoBackupLoadFileData
|
||||
{
|
||||
MemContext *memContext; // Mem context
|
||||
const Storage *storage; // Storage to load from
|
||||
const String *fileName; // Base filename
|
||||
CipherType cipherType; // Cipher type
|
||||
const String *cipherPass; // Cipher passphrase
|
||||
InfoBackup *infoBackup; // Loaded infoBackup object
|
||||
} InfoBackupLoadFileData;
|
||||
|
||||
static bool
|
||||
infoBackupLoadFileCallback(void *data, unsigned int try)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelTrace);
|
||||
FUNCTION_LOG_PARAM_P(VOID, data);
|
||||
FUNCTION_LOG_PARAM(UINT, try);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(data != NULL);
|
||||
|
||||
InfoBackupLoadFileData *loadData = (InfoBackupLoadFileData *)data;
|
||||
bool result = false;
|
||||
|
||||
if (try < 2)
|
||||
{
|
||||
// Construct filename based on try
|
||||
const String *fileName = try == 0 ? loadData->fileName : strNewFmt("%s" INFO_COPY_EXT, strPtr(loadData->fileName));
|
||||
|
||||
// Attempt to load the file
|
||||
IoRead *read = storageReadIo(storageNewReadNP(loadData->storage, fileName));
|
||||
cipherBlockFilterGroupAdd(ioReadFilterGroup(read), loadData->cipherType, cipherModeDecrypt, loadData->cipherPass);
|
||||
|
||||
MEM_CONTEXT_BEGIN(loadData->memContext)
|
||||
{
|
||||
loadData->infoBackup = infoBackupNewLoad(read);
|
||||
result = true;
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
}
|
||||
|
||||
FUNCTION_LOG_RETURN(BOOL, result);
|
||||
}
|
||||
|
||||
InfoBackup *
|
||||
infoBackupLoadFile(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));
|
||||
|
||||
InfoBackupLoadFileData data =
|
||||
{
|
||||
.memContext = memContextCurrent(),
|
||||
.storage = storage,
|
||||
.fileName = fileName,
|
||||
.cipherType = cipherType,
|
||||
.cipherPass = cipherPass,
|
||||
};
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
const char *fileNamePath = strPtr(storagePathNP(storage, fileName));
|
||||
|
||||
TRY_BEGIN()
|
||||
{
|
||||
infoLoad(
|
||||
strNewFmt("unable to load info file '%s' or '%s" INFO_COPY_EXT "'", fileNamePath, fileNamePath),
|
||||
infoBackupLoadFileCallback, &data);
|
||||
}
|
||||
CATCH_ANY()
|
||||
{
|
||||
THROWP_FMT(
|
||||
errorType(),
|
||||
"%s\n"
|
||||
"HINT: backup.info cannot be opened and is required to perform a backup.\n"
|
||||
"HINT: has a stanza-create been performed?",
|
||||
errorMessage());
|
||||
}
|
||||
TRY_END();
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_LOG_RETURN(INFO_BACKUP, data.infoBackup);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Helper function to save backup info files
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
infoBackupSaveFile(
|
||||
InfoBackup *infoBackup, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(INFO_BACKUP, infoBackup);
|
||||
FUNCTION_LOG_PARAM(STORAGE, storage);
|
||||
FUNCTION_LOG_PARAM(STRING, fileName);
|
||||
FUNCTION_LOG_PARAM(ENUM, cipherType);
|
||||
FUNCTION_TEST_PARAM(STRING, cipherPass);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(infoBackup != NULL);
|
||||
ASSERT(storage != NULL);
|
||||
ASSERT(fileName != NULL);
|
||||
ASSERT((cipherType == cipherTypeNone && cipherPass == NULL) || (cipherType != cipherTypeNone && cipherPass != NULL));
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
// Save the file
|
||||
IoWrite *write = storageWriteIo(storageNewWriteNP(storage, fileName));
|
||||
cipherBlockFilterGroupAdd(ioWriteFilterGroup(write), cipherType, cipherModeEncrypt, cipherPass);
|
||||
infoBackupSave(infoBackup, write);
|
||||
|
||||
// Make a copy of the file
|
||||
storageCopy(
|
||||
storageNewReadNP(storage, fileName), storageNewWriteNP(storage, strNewFmt("%s" INFO_COPY_EXT, strPtr(fileName))));
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
FUNCTION_LOG_RETURN_VOID();
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Render as string for logging
|
||||
***********************************************************************************************************************************/
|
||||
|
||||
+12
-10
@@ -61,9 +61,7 @@ Constructors
|
||||
***********************************************************************************************************************************/
|
||||
InfoBackup *infoBackupNew(
|
||||
unsigned int pgVersion, uint64_t pgSystemId, const uint32_t pgControlVersion, const uint32_t pgCatalogVersion,
|
||||
CipherType cipherType, const String *cipherPassSub);
|
||||
InfoBackup *infoBackupNewLoad(
|
||||
const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass);
|
||||
const String *cipherPassSub);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
@@ -72,17 +70,13 @@ Functions
|
||||
void infoBackupDataDelete(const InfoBackup *this, const String *backupDeleteLabel);
|
||||
InfoBackup *infoBackupPgSet(
|
||||
InfoBackup *this, unsigned int pgVersion, uint64_t pgSystemId, uint32_t pgControlVersion, uint32_t pgCatalogVersion);
|
||||
void infoBackupSave(
|
||||
InfoBackup *this, const Storage *storage, const String *fileName, CipherType cipherType, const String *cipherPass);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
infoBackupDataLabelList - get a list of current backup labels
|
||||
***********************************************************************************************************************************/
|
||||
StringList *infoBackupDataLabelList(const InfoBackup *this, const String *expression);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Getters
|
||||
***********************************************************************************************************************************/
|
||||
// Get a list of current backup labels
|
||||
StringList *infoBackupDataLabelList(const InfoBackup *this, const String *expression);
|
||||
|
||||
InfoPg *infoBackupPg(const InfoBackup *this);
|
||||
InfoBackupData infoBackupData(const InfoBackup *this, unsigned int backupDataIdx);
|
||||
unsigned int infoBackupDataTotal(const InfoBackup *this);
|
||||
@@ -93,6 +87,14 @@ Destructor
|
||||
***********************************************************************************************************************************/
|
||||
void infoBackupFree(InfoBackup *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Helper functions
|
||||
***********************************************************************************************************************************/
|
||||
InfoBackup *infoBackupLoadFile(
|
||||
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);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
|
||||
+199
-123
@@ -3,6 +3,8 @@ PostgreSQL Info Handler
|
||||
***********************************************************************************************************************************/
|
||||
#include "build.auto.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@@ -27,6 +29,7 @@ Internal constants
|
||||
STRING_STATIC(INFO_SECTION_DB_STR, "db");
|
||||
STRING_STATIC(INFO_SECTION_DB_HISTORY_STR, "db:history");
|
||||
|
||||
STRING_STATIC(INFO_KEY_DB_ID_STR, INFO_KEY_DB_ID);
|
||||
VARIANT_STRDEF_EXTERN(INFO_KEY_DB_ID_VAR, INFO_KEY_DB_ID);
|
||||
VARIANT_STRDEF_STATIC(INFO_KEY_DB_CATALOG_VERSION_VAR, "db-catalog-version");
|
||||
VARIANT_STRDEF_STATIC(INFO_KEY_DB_CONTROL_VERSION_VAR, "db-control-version");
|
||||
@@ -40,139 +43,172 @@ struct InfoPg
|
||||
{
|
||||
MemContext *memContext; // Mem context
|
||||
Info *info; // Info contents
|
||||
InfoPgType type; // Type of info file being loaded
|
||||
List *history; // A list of InfoPgData
|
||||
unsigned int historyCurrent; // Index of the current history item
|
||||
};
|
||||
|
||||
OBJECT_DEFINE_FREE(INFO_PG);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Internal constructor
|
||||
***********************************************************************************************************************************/
|
||||
static InfoPg *
|
||||
infoPgNewInternal(void)
|
||||
infoPgNewInternal(InfoPgType type)
|
||||
{
|
||||
FUNCTION_LOG_VOID(logLevelTrace);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(ENUM, type);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
InfoPg *this = memNew(sizeof(InfoPg));
|
||||
this->memContext = memContextCurrent();
|
||||
this->type = type;
|
||||
this->history = lstNew(sizeof(InfoPgData));
|
||||
|
||||
FUNCTION_TEST_RETURN(this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Create new object
|
||||
***********************************************************************************************************************************/
|
||||
InfoPg *
|
||||
infoPgNew(InfoPgType type, const String *cipherPassSub)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(ENUM, type);
|
||||
FUNCTION_TEST_PARAM(STRING, cipherPassSub);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
InfoPg *this = NULL;
|
||||
|
||||
MEM_CONTEXT_NEW_BEGIN("InfoPg")
|
||||
{
|
||||
// Create object
|
||||
this = memNew(sizeof(InfoPg));
|
||||
this->memContext = MEM_CONTEXT_NEW();
|
||||
|
||||
// Get the pg history list
|
||||
this->history = lstNew(sizeof(InfoPgData));
|
||||
|
||||
this->historyCurrent = 0;
|
||||
this = infoPgNewInternal(type);
|
||||
this->info = infoNew(cipherPassSub);
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
FUNCTION_LOG_RETURN(INFO_PG, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Create new object
|
||||
***********************************************************************************************************************************/
|
||||
InfoPg *
|
||||
infoPgNew(CipherType cipherType, const String *cipherPassSub)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(ENUM, cipherType);
|
||||
FUNCTION_TEST_PARAM(STRING, cipherPassSub);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
InfoPg *this = infoPgNewInternal();
|
||||
|
||||
this->info = infoNew(cipherType, cipherPassSub);
|
||||
|
||||
FUNCTION_LOG_RETURN(INFO_PG, this);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Create new object and load contents from a file
|
||||
***********************************************************************************************************************************/
|
||||
InfoPg *
|
||||
infoPgNewLoad(
|
||||
const Storage *storage, const String *fileName, InfoPgType type, CipherType cipherType, const String *cipherPass, Ini **ini)
|
||||
typedef struct InfoPgLoadData
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(STORAGE, storage);
|
||||
FUNCTION_LOG_PARAM(STRING, fileName);
|
||||
FUNCTION_LOG_PARAM(ENUM, type);
|
||||
FUNCTION_LOG_PARAM(ENUM, cipherType);
|
||||
FUNCTION_TEST_PARAM(STRING, cipherPass);
|
||||
FUNCTION_LOG_PARAM_P(INI, ini);
|
||||
FUNCTION_LOG_END();
|
||||
InfoLoadNewCallback *callbackFunction; // Callback function for child object
|
||||
void *callbackData; // Callback data for child object
|
||||
InfoPg *infoPg; // Pg info
|
||||
unsigned int currentId; // Current database id
|
||||
} InfoPgLoadData;
|
||||
|
||||
ASSERT(storage != NULL);
|
||||
ASSERT(fileName != NULL);
|
||||
ASSERT(cipherType == cipherTypeNone || cipherPass != NULL);
|
||||
|
||||
InfoPg *this = infoPgNewInternal();
|
||||
|
||||
MEM_CONTEXT_BEGIN(this->memContext)
|
||||
static void
|
||||
infoPgLoadCallback(void *data, const String *section, const String *key, const String *value)
|
||||
{
|
||||
// Load info
|
||||
Ini *iniLocal = NULL;
|
||||
this->info = infoNewLoad(storage, fileName, cipherType, cipherPass, &iniLocal);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM_P(VOID, data);
|
||||
FUNCTION_TEST_PARAM(STRING, section);
|
||||
FUNCTION_TEST_PARAM(STRING, key);
|
||||
FUNCTION_TEST_PARAM(STRING, value);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(section != NULL);
|
||||
ASSERT(key != NULL);
|
||||
ASSERT(value != NULL);
|
||||
|
||||
InfoPgLoadData *loadData = (InfoPgLoadData *)data;
|
||||
|
||||
// Process db section
|
||||
if (strEq(section, INFO_SECTION_DB_STR))
|
||||
{
|
||||
const StringList *pgHistoryKey = iniSectionKeyList(iniLocal, INFO_SECTION_DB_HISTORY_STR);
|
||||
|
||||
// Get the current history id
|
||||
unsigned int pgId = jsonToUInt(iniGet(iniLocal, INFO_SECTION_DB_STR, varStr(INFO_KEY_DB_ID_VAR)));
|
||||
|
||||
// History must include at least one item or the file is corrupt
|
||||
ASSERT(strLstSize(pgHistoryKey) > 0);
|
||||
|
||||
// Iterate in reverse because we would like the most recent pg history to be in position 0. If we need to look at the
|
||||
// history list at all we'll be iterating from newest to oldest and putting newest in position 0 makes for more natural
|
||||
// looping. Cast the index check to an integer to test for >= 0 (for readability).
|
||||
for (unsigned int pgHistoryIdx = strLstSize(pgHistoryKey) - 1; (int)pgHistoryIdx >= 0; pgHistoryIdx--)
|
||||
if (strEq(key, INFO_KEY_DB_ID_STR))
|
||||
loadData->currentId = jsonToUInt(value);
|
||||
}
|
||||
// Process db:history section
|
||||
else if (strEq(section, INFO_SECTION_DB_HISTORY_STR))
|
||||
{
|
||||
// Load JSON data into a KeyValue
|
||||
const KeyValue *pgDataKv = jsonToKv(
|
||||
iniGet(iniLocal, INFO_SECTION_DB_HISTORY_STR, strLstGet(pgHistoryKey, pgHistoryIdx)));
|
||||
// Load JSON loadData into a KeyValue
|
||||
const KeyValue *pgDataKv = jsonToKv(value);
|
||||
|
||||
// Get db values that are common to all info files
|
||||
InfoPgData infoPgData =
|
||||
{
|
||||
.id = cvtZToUInt(strPtr(strLstGet(pgHistoryKey, pgHistoryIdx))),
|
||||
.id = cvtZToUInt(strPtr(key)),
|
||||
.version = pgVersionFromStr(varStr(kvGet(pgDataKv, INFO_KEY_DB_VERSION_VAR))),
|
||||
|
||||
// This is different in archive.info due to a typo that can't be fixed without a format version bump
|
||||
.systemId = varUInt64Force(
|
||||
kvGet(pgDataKv, type == infoPgArchive ? INFO_KEY_DB_ID_VAR : INFO_KEY_DB_SYSTEM_ID_VAR)),
|
||||
kvGet(pgDataKv, loadData->infoPg->type == infoPgArchive ? INFO_KEY_DB_ID_VAR : INFO_KEY_DB_SYSTEM_ID_VAR)),
|
||||
};
|
||||
|
||||
// Set index if this is the current history item
|
||||
if (infoPgData.id == pgId)
|
||||
this->historyCurrent = lstSize(this->history);
|
||||
|
||||
// Get values that are only in backup and manifest files. These are really vestigial since stanza-create verifies
|
||||
// the control and catalog versions so there is no good reason to store them. However, for backward compatibility
|
||||
// we must write them at least, even if we give up reading them.
|
||||
if (type == infoPgBackup || type == infoPgManifest)
|
||||
// Get values that are only in backup info files. These are really vestigial since stanza-create verifies the control and
|
||||
// catalog versions so there is no good reason to store them. However, for backward compatibility we must write them at
|
||||
// least, even if we give up reading them.
|
||||
if (loadData->infoPg->type == infoPgBackup)
|
||||
{
|
||||
infoPgData.catalogVersion = varUIntForce(kvGet(pgDataKv, INFO_KEY_DB_CATALOG_VERSION_VAR));
|
||||
infoPgData.controlVersion = varUIntForce(kvGet(pgDataKv, INFO_KEY_DB_CONTROL_VERSION_VAR));
|
||||
}
|
||||
else if (type != infoPgArchive)
|
||||
THROW_FMT(AssertError, "invalid InfoPg type %u", type);
|
||||
|
||||
// Using lstAdd because it is more efficient than lstInsert and loading this file is in critical code paths
|
||||
lstAdd(this->history, &infoPgData);
|
||||
// Insert at beginning of list so the history is reverse ordered
|
||||
lstInsert(loadData->infoPg->history, 0, &infoPgData);
|
||||
}
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
// Callback if set
|
||||
else if (loadData->callbackFunction != NULL)
|
||||
loadData->callbackFunction(loadData->callbackData, section, key, value);
|
||||
|
||||
if (ini != NULL)
|
||||
*ini = iniMove(iniLocal, MEM_CONTEXT_OLD());
|
||||
FUNCTION_TEST_RETURN_VOID();
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
InfoPg *
|
||||
infoPgNewLoad(IoRead *read, InfoPgType type, InfoLoadNewCallback *callbackFunction, void *callbackData)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(IO_READ, read);
|
||||
FUNCTION_LOG_PARAM(ENUM, type);
|
||||
FUNCTION_LOG_PARAM(FUNCTIONP, callbackFunction);
|
||||
FUNCTION_LOG_PARAM_P(VOID, callbackData);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(read != NULL);
|
||||
ASSERT(type == infoPgBackup || type == infoPgArchive);
|
||||
ASSERT((callbackFunction == NULL && callbackData == NULL) || (callbackFunction != NULL && callbackData != NULL));
|
||||
|
||||
InfoPg *this = NULL;
|
||||
|
||||
MEM_CONTEXT_NEW_BEGIN("InfoPg")
|
||||
{
|
||||
this = infoPgNewInternal(type);
|
||||
|
||||
// Set historyCurrent to UINT_MAX so we can detect if it was loaded correctly
|
||||
this->historyCurrent = UINT_MAX;
|
||||
|
||||
// Load
|
||||
InfoPgLoadData loadData =
|
||||
{
|
||||
.callbackFunction = callbackFunction,
|
||||
.callbackData = callbackData,
|
||||
.infoPg = this,
|
||||
};
|
||||
|
||||
this->info = infoNewLoad(read, infoPgLoadCallback, &loadData);
|
||||
|
||||
// History must include at least one item or the file is corrupt
|
||||
CHECK(lstSize(this->history) > 0);
|
||||
|
||||
// If the current id was not found then the file is corrupt
|
||||
CHECK(loadData.currentId > 0);
|
||||
|
||||
// Find the current history item
|
||||
for (unsigned int historyIdx = 0; historyIdx < lstSize(this->history); historyIdx++)
|
||||
{
|
||||
if (((InfoPgData *)lstGet(this->history, historyIdx))->id == loadData.currentId)
|
||||
this->historyCurrent = historyIdx;
|
||||
}
|
||||
|
||||
// If the current id did not match the history list then the file is corrupt
|
||||
CHECK(this->historyCurrent != UINT_MAX);
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
FUNCTION_LOG_RETURN(INFO_PG, this);
|
||||
}
|
||||
@@ -198,7 +234,7 @@ infoPgAdd(InfoPg *this, const InfoPgData *infoPgData)
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Set the InfoPg object data based on values passed.
|
||||
Set the InfoPg object data based on values passed
|
||||
***********************************************************************************************************************************/
|
||||
InfoPg *
|
||||
infoPgSet(
|
||||
@@ -234,7 +270,7 @@ infoPgSet(
|
||||
.systemId = pgSystemId,
|
||||
};
|
||||
|
||||
if (type == infoPgBackup || type == infoPgManifest)
|
||||
if (type == infoPgBackup)
|
||||
{
|
||||
infoPgData.catalogVersion = pgCatalogVersion;
|
||||
infoPgData.controlVersion = pgControlVersion;
|
||||
@@ -253,54 +289,63 @@ infoPgSet(
|
||||
/***********************************************************************************************************************************
|
||||
Save to file
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
infoPgSave(
|
||||
InfoPg *this, Ini *ini, const Storage *storage, const String *fileName, InfoPgType type, CipherType cipherType,
|
||||
const String *cipherPass)
|
||||
typedef struct InfoPgSaveData
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(INFO_PG, this);
|
||||
FUNCTION_LOG_PARAM(INI, ini);
|
||||
FUNCTION_LOG_PARAM(STORAGE, storage);
|
||||
FUNCTION_LOG_PARAM(STRING, fileName);
|
||||
FUNCTION_LOG_PARAM(ENUM, type);
|
||||
FUNCTION_LOG_PARAM(ENUM, cipherType);
|
||||
FUNCTION_TEST_PARAM(STRING, cipherPass);
|
||||
FUNCTION_LOG_END();
|
||||
InfoSaveCallback *callbackFunction; // Callback function for child object
|
||||
void *callbackData; // Callback data for child object
|
||||
InfoPgType type; // Type of info file being loaded
|
||||
InfoPg *infoPg; // InfoPg object to be saved
|
||||
} InfoPgSaveData;
|
||||
|
||||
ASSERT(this != NULL);
|
||||
ASSERT(ini != NULL);
|
||||
ASSERT(storage != NULL);
|
||||
ASSERT(fileName != NULL);
|
||||
ASSERT(cipherType == cipherTypeNone || cipherPass != NULL);
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
static void
|
||||
infoPgSaveCallback(void *data, const String *sectionNext, InfoSave *infoSaveData)
|
||||
{
|
||||
// Set the db section
|
||||
InfoPgData pgData = infoPgDataCurrent(this);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM_P(VOID, data);
|
||||
FUNCTION_TEST_PARAM(STRING, sectionNext);
|
||||
FUNCTION_TEST_PARAM(INFO_SAVE, infoSaveData);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
iniSet(ini, INFO_SECTION_DB_STR, varStr(INFO_KEY_DB_ID_VAR), jsonFromUInt(pgData.id));
|
||||
iniSet(ini, INFO_SECTION_DB_STR, varStr(INFO_KEY_DB_VERSION_VAR), jsonFromStr(pgVersionToStr(pgData.version)));
|
||||
iniSet(ini, INFO_SECTION_DB_STR, varStr(INFO_KEY_DB_SYSTEM_ID_VAR), jsonFromUInt64(pgData.systemId));
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(infoSaveData != NULL);
|
||||
|
||||
if (type == infoPgBackup || type == infoPgManifest)
|
||||
InfoPgSaveData *saveData = (InfoPgSaveData *)data;
|
||||
|
||||
if (infoSaveSection(infoSaveData, INFO_SECTION_DB_STR, sectionNext))
|
||||
{
|
||||
if (saveData->callbackFunction != NULL)
|
||||
saveData->callbackFunction(saveData->callbackData, INFO_SECTION_DB_STR, infoSaveData);
|
||||
|
||||
iniSet(ini, INFO_SECTION_DB_STR, varStr(INFO_KEY_DB_CATALOG_VERSION_VAR), jsonFromUInt(pgData.catalogVersion));
|
||||
iniSet(ini, INFO_SECTION_DB_STR, varStr(INFO_KEY_DB_CONTROL_VERSION_VAR), jsonFromUInt(pgData.controlVersion));
|
||||
InfoPgData pgData = infoPgDataCurrent(saveData->infoPg);
|
||||
|
||||
if (saveData->infoPg->type == infoPgBackup)
|
||||
{
|
||||
infoSaveValue(
|
||||
infoSaveData, INFO_SECTION_DB_STR, varStr(INFO_KEY_DB_CATALOG_VERSION_VAR), jsonFromUInt(pgData.catalogVersion));
|
||||
infoSaveValue(
|
||||
infoSaveData, INFO_SECTION_DB_STR, varStr(INFO_KEY_DB_CONTROL_VERSION_VAR), jsonFromUInt(pgData.controlVersion));
|
||||
}
|
||||
else if (type != infoPgArchive)
|
||||
THROW_FMT(AssertError, "invalid InfoPg type %u", type);
|
||||
|
||||
infoSaveValue(infoSaveData, INFO_SECTION_DB_STR, varStr(INFO_KEY_DB_ID_VAR), jsonFromUInt(pgData.id));
|
||||
infoSaveValue(infoSaveData, INFO_SECTION_DB_STR, varStr(INFO_KEY_DB_SYSTEM_ID_VAR), jsonFromUInt64(pgData.systemId));
|
||||
infoSaveValue(
|
||||
infoSaveData, INFO_SECTION_DB_STR, varStr(INFO_KEY_DB_VERSION_VAR), jsonFromStr(pgVersionToStr(pgData.version)));
|
||||
}
|
||||
|
||||
if (infoSaveSection(infoSaveData, INFO_SECTION_DB_HISTORY_STR, sectionNext))
|
||||
{
|
||||
if (saveData->callbackFunction != NULL)
|
||||
saveData->callbackFunction(saveData->callbackData, INFO_SECTION_DB_HISTORY_STR, infoSaveData);
|
||||
|
||||
// Set the db history section in reverse so oldest history is first instead of last to be consistent with load
|
||||
for (unsigned int pgDataIdx = infoPgDataTotal(this) - 1; (int)pgDataIdx >= 0; pgDataIdx--)
|
||||
for (unsigned int pgDataIdx = infoPgDataTotal(saveData->infoPg) - 1; (int)pgDataIdx >= 0; pgDataIdx--)
|
||||
{
|
||||
InfoPgData pgData = infoPgData(this, pgDataIdx);
|
||||
InfoPgData pgData = infoPgData(saveData->infoPg, pgDataIdx);
|
||||
|
||||
KeyValue *pgDataKv = kvNew();
|
||||
kvPut(pgDataKv, INFO_KEY_DB_VERSION_VAR, VARSTR(pgVersionToStr(pgData.version)));
|
||||
|
||||
if (type == infoPgBackup || type == infoPgManifest)
|
||||
if (saveData->infoPg->type == infoPgBackup)
|
||||
{
|
||||
kvPut(pgDataKv, INFO_KEY_DB_CATALOG_VERSION_VAR, VARUINT(pgData.catalogVersion));
|
||||
kvPut(pgDataKv, INFO_KEY_DB_CONTROL_VERSION_VAR, VARUINT(pgData.controlVersion));
|
||||
@@ -309,10 +354,41 @@ infoPgSave(
|
||||
else
|
||||
kvPut(pgDataKv, INFO_KEY_DB_ID_VAR, VARUINT64(pgData.systemId));
|
||||
|
||||
iniSet(ini, INFO_SECTION_DB_HISTORY_STR, varStrForce(VARUINT(pgData.id)), jsonFromKv(pgDataKv, 0));
|
||||
infoSaveValue(infoSaveData, INFO_SECTION_DB_HISTORY_STR, varStrForce(VARUINT(pgData.id)), jsonFromKv(pgDataKv, 0));
|
||||
}
|
||||
}
|
||||
|
||||
infoSave(infoPgInfo(this), ini, storage, fileName, cipherType, cipherPass);
|
||||
// Process the callback even if none of the sections above get executed
|
||||
if (saveData->callbackFunction != NULL)
|
||||
saveData->callbackFunction(saveData->callbackData, sectionNext, infoSaveData);
|
||||
|
||||
FUNCTION_TEST_RETURN_VOID()
|
||||
}
|
||||
|
||||
void
|
||||
infoPgSave(InfoPg *this, IoWrite *write, InfoSaveCallback *callbackFunction, void *callbackData)
|
||||
{
|
||||
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||
FUNCTION_LOG_PARAM(INFO_PG, this);
|
||||
FUNCTION_LOG_PARAM(IO_WRITE, write);
|
||||
FUNCTION_LOG_PARAM(FUNCTIONP, callbackFunction);
|
||||
FUNCTION_LOG_PARAM_P(VOID, callbackData);
|
||||
FUNCTION_LOG_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
ASSERT(write != NULL);
|
||||
ASSERT((callbackFunction == NULL && callbackData == NULL) || (callbackFunction != NULL && callbackData != NULL));
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
InfoPgSaveData saveData =
|
||||
{
|
||||
.callbackFunction = callbackFunction,
|
||||
.callbackData = callbackData,
|
||||
.infoPg = this,
|
||||
};
|
||||
|
||||
infoSave(infoPgInfo(this), write, infoPgSaveCallback, &saveData);
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
|
||||
+3
-12
@@ -44,15 +44,13 @@ typedef enum
|
||||
{
|
||||
infoPgArchive, // archive info file
|
||||
infoPgBackup, // backup info file
|
||||
infoPgManifest, // manifest file
|
||||
} InfoPgType;
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Constructors
|
||||
***********************************************************************************************************************************/
|
||||
InfoPg *infoPgNew(CipherType cipherType, const String *cipherPass);
|
||||
InfoPg *infoPgNewLoad(
|
||||
const Storage *storage, const String *fileName, InfoPgType type, CipherType cipherType, const String *cipherPass, Ini **ini);
|
||||
InfoPg *infoPgNew(InfoPgType type, const String *cipherPassSub);
|
||||
InfoPg *infoPgNewLoad(IoRead *read, InfoPgType type, InfoLoadNewCallback *callbackFunction, void *callbackData);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
@@ -61,9 +59,7 @@ void infoPgAdd(InfoPg *this, const InfoPgData *infoPgData);
|
||||
InfoPg *infoPgSet(
|
||||
InfoPg *this, InfoPgType type, const unsigned int pgVersion, const uint64_t pgSystemId, const uint32_t pgControlVersion,
|
||||
const uint32_t pgCatalogVersion);
|
||||
void infoPgSave(
|
||||
InfoPg *this, Ini *ini, const Storage *storage, const String *fileName, InfoPgType type, CipherType cipherType,
|
||||
const String *cipherPass);
|
||||
void infoPgSave(InfoPg *this, IoWrite *write, InfoSaveCallback *callbackFunction, void *callbackData);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Getters
|
||||
@@ -77,11 +73,6 @@ Info *infoPgInfo(const InfoPg *this);
|
||||
unsigned int infoPgDataTotal(const InfoPg *this);
|
||||
unsigned int infoPgCurrentDataId(const InfoPg *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Destructor
|
||||
***********************************************************************************************************************************/
|
||||
void infoPgFree(InfoPg *this);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
|
||||
+1
-1
@@ -295,7 +295,7 @@ unit:
|
||||
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: ini
|
||||
total: 4
|
||||
total: 5
|
||||
|
||||
coverage:
|
||||
common/ini: full
|
||||
|
||||
@@ -32,7 +32,6 @@ P00 INFO: stanza-create command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -46,10 +45,12 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
-----------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -61,6 +62,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
full backup - error on identical link destinations (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --type=full --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -253,7 +257,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -270,6 +273,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
full backup - invalid cmd line (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --type=full --stanza=bogus backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -522,7 +528,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -539,6 +544,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
full backup - invalid repo (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --repo1-path=/bogus_path --type=full --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -1176,7 +1184,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -1194,6 +1201,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
incr backup - resume and add tablespace 2 (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --process-max=1 --delta --stanza=db backup --test --test-delay=0.2 --test-point=backup-resume=y
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -1384,7 +1394,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -1402,6 +1411,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
diff backup - cannot resume - new diff (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --process-max=1 --delta --type=diff --stanza=db backup --test --test-delay=0.2 --test-point=backup-noresume=y
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -1583,7 +1595,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -1601,6 +1612,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
diff backup - cannot resume - disabled / no repo link (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --no-resume --process-max=1 --delta --type=diff --stanza=db backup --test --test-delay=0.2 --test-point=backup-noresume=y
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -1782,7 +1796,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -1800,6 +1813,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
restore, backup '[BACKUP-DIFF-2]', expect exit 40 - fail on used path (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --set=[BACKUP-DIFF-2] --stanza=db restore
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -2054,7 +2070,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -2073,6 +2088,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
incr backup - update files - fail on missing backup.info (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -2095,7 +2113,6 @@ P00 INFO: stanza-create command end: aborted with exception [055]
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
-----------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -2107,6 +2124,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
incr backup - update files (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -2285,7 +2305,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -2305,6 +2324,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
diff backup - updates since last full (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --process-max=1 --delta --type=diff --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -2486,7 +2508,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -2507,6 +2528,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
incr backup - remove files - but won't affect manifest (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --stanza=db backup --test --test-delay=1 --test-point=manifest-build=y
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -2666,7 +2690,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -2688,6 +2711,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
diff backup - remove files during backup (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --process-max=1 --delta --type=diff --stanza=db backup --test --test-delay=1 --test-point=manifest-build=y
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -2868,7 +2894,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -2891,6 +2916,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
full backup - update file (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --type=full --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -3066,7 +3094,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -3090,6 +3117,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
info db stanza - normal output (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --log-level-console=warn --stanza=db info
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -3628,7 +3658,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -3646,6 +3675,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
restore delta, remap - selective restore 16384 (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --delta --db-include=16384 --stanza=db restore
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -4123,7 +4155,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -4142,6 +4173,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
diff backup - option backup-standby reset - backup performed from master (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --no-online --log-level-console=info --backup-standby --type=diff --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -4299,7 +4333,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -4318,3 +4351,6 @@ db-version="9.4"
|
||||
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
@@ -18,7 +18,6 @@ stanza-create db - create required data for stanza (backup host)
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -35,10 +34,12 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
+ supplemental file: /archive/db/archive.info
|
||||
---------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -53,6 +54,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
full backup - error on identical link destinations (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --type=full --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -234,7 +238,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -254,6 +257,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
full backup - resume (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --force --checksum-page --type=full --stanza=db backup --test --test-delay=0.2 --test-point=backup-resume=y
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -430,7 +436,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -450,6 +455,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
full backup - invalid repo (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --repo1-path=/bogus_path --type=full --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -731,7 +739,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -752,6 +759,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
incr backup - resume and add tablespace 2 (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --process-max=1 --stanza=db backup --test --test-delay=0.2 --test-point=backup-resume=y
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -945,7 +955,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -966,6 +975,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
diff backup - cannot resume - new diff (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --process-max=1 --type=diff --stanza=db backup --test --test-delay=0.2 --test-point=backup-noresume=y
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -1155,7 +1167,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -1176,6 +1187,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
diff backup - cannot resume - disabled / no repo link (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --no-resume --process-max=1 --type=diff --stanza=db backup --test --test-delay=0.2 --test-point=backup-noresume=y
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -1365,7 +1379,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -1386,6 +1399,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
restore, backup '[BACKUP-DIFF-2]', expect exit 40 - fail on used path (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --set=[BACKUP-DIFF-2] --stanza=db restore
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -1592,7 +1608,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -1614,6 +1629,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
incr backup - update files (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -1799,7 +1817,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -1822,6 +1839,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
diff backup - updates since last full (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --process-max=1 --type=diff --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -2010,7 +2030,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -2034,6 +2053,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
incr backup - remove files - but won't affect manifest (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --stanza=db backup --test --test-delay=1 --test-point=manifest-build=y
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -2219,7 +2241,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -2244,6 +2265,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
diff backup - remove files during backup (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --process-max=1 --type=diff --stanza=db backup --test --test-delay=1 --test-point=manifest-build=y
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -2430,7 +2454,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -2456,6 +2479,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
full backup - update file (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --type=full --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -2636,7 +2662,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -2663,6 +2688,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
info db stanza - normal output (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --log-level-console=warn --stanza=db info
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -3194,7 +3222,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -3215,6 +3242,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
restore delta, remap - selective restore 16384 (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --delta --db-include=16384 --stanza=db restore
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -3583,7 +3613,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -3605,6 +3634,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
diff backup - option backup-standby reset - backup performed from master (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --no-online --log-level-console=info --backup-standby --type=diff --stanza=db backup
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -3797,7 +3829,6 @@ backrest-checksum="[CHECKSUM]"
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -3819,3 +3850,6 @@ db-version="9.4"
|
||||
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
@@ -34,7 +34,6 @@ P00 INFO: stanza-create command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -51,10 +50,12 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
-----------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -69,6 +70,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push --compress [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001] --compress --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-cipher-pass=<redacted> --repo1-cipher-type=aes-256-cbc --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
|
||||
@@ -36,7 +36,6 @@ P00 INFO: stanza-create command end: completed successfully
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -50,10 +49,12 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
+ supplemental file: /archive/db/archive.info
|
||||
---------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -65,6 +66,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push --cmd-ssh=/usr/bin/ssh --compress [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001] --cmd-ssh=/usr/bin/ssh --compress --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-host=backup --repo1-host-cmd=[BACKREST-BIN] --repo1-host-config=[TEST_PATH]/backup/pgbackrest.conf --repo1-host-user=[USER-1] --stanza=db
|
||||
|
||||
@@ -10,7 +10,6 @@ P00 INFO: stanza-create command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -27,10 +26,12 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
-----------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -45,6 +46,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --log-level-console=warn --archive-push-queue-max=33554432 --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ P00 INFO: stanza-create command end: completed successfully
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -26,10 +25,12 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
+ supplemental file: /archive/db/archive.info
|
||||
---------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -41,6 +42,9 @@ db-version="9.4"
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --log-level-console=warn --archive-push-queue-max=33554432 --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -307,7 +307,6 @@ P00 INFO: expire command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -325,6 +324,9 @@ db-version="9.2"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201204301,"db-control-version":922,"db-system-id":1000000000000000092,"db-version":"9.2"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> ls [TEST_PATH]/db-master/repo/backup/db | grep -v "backup.*"
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
[BACKUP-FULL-1]
|
||||
@@ -911,7 +913,6 @@ P00 INFO: expire command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -928,6 +929,9 @@ db-version="9.2"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201204301,"db-control-version":922,"db-system-id":1000000000000000092,"db-version":"9.2"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> ls [TEST_PATH]/db-master/repo/backup/db | grep -v "backup.*"
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
[BACKUP-FULL-2]
|
||||
@@ -1274,7 +1278,6 @@ P00 INFO: expire command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -1292,6 +1295,9 @@ db-version="9.2"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201204301,"db-control-version":922,"db-system-id":1000000000000000092,"db-version":"9.2"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> ls [TEST_PATH]/db-master/repo/backup/db | grep -v "backup.*"
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
[BACKUP-FULL-2]
|
||||
@@ -1928,7 +1934,6 @@ P00 INFO: expire command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -1947,6 +1952,9 @@ db-version="9.2"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201204301,"db-control-version":922,"db-system-id":1000000000000000092,"db-version":"9.2"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> ls [TEST_PATH]/db-master/repo/backup/db | grep -v "backup.*"
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
[BACKUP-FULL-3]
|
||||
@@ -2047,7 +2055,6 @@ P00 INFO: expire command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -2065,6 +2072,9 @@ db-version="9.2"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201204301,"db-control-version":922,"db-system-id":1000000000000000092,"db-version":"9.2"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> ls [TEST_PATH]/db-master/repo/backup/db | grep -v "backup.*"
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
[BACKUP-FULL-3]
|
||||
@@ -2156,7 +2166,6 @@ P00 INFO: expire command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -2175,6 +2184,9 @@ db-version="9.2"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201204301,"db-control-version":922,"db-system-id":1000000000000000092,"db-version":"9.2"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> ls [TEST_PATH]/db-master/repo/backup/db | grep -v "backup.*"
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
[BACKUP-FULL-3]
|
||||
@@ -2299,7 +2311,6 @@ P00 INFO: expire command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -2317,6 +2328,9 @@ db-version="9.2"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201204301,"db-control-version":922,"db-system-id":1000000000000000092,"db-version":"9.2"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> ls [TEST_PATH]/db-master/repo/backup/db | grep -v "backup.*"
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
[BACKUP-FULL-4]
|
||||
@@ -2434,7 +2448,6 @@ P00 INFO: expire command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -2455,6 +2468,9 @@ db-version="9.2"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201204301,"db-control-version":922,"db-system-id":1000000000000000092,"db-version":"9.2"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> ls [TEST_PATH]/db-master/repo/backup/db | grep -v "backup.*"
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
[BACKUP-FULL-4]
|
||||
@@ -2589,7 +2605,6 @@ P00 INFO: expire command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -2612,6 +2627,9 @@ db-version="9.2"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201204301,"db-control-version":922,"db-system-id":1000000000000000092,"db-version":"9.2"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> ls [TEST_PATH]/db-master/repo/backup/db | grep -v "backup.*"
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
[BACKUP-FULL-4]
|
||||
@@ -2756,7 +2774,6 @@ P00 INFO: expire command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -2774,6 +2791,9 @@ db-version="9.2"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201204301,"db-control-version":922,"db-system-id":1000000000000000092,"db-version":"9.2"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> ls [TEST_PATH]/db-master/repo/backup/db | grep -v "backup.*"
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
[BACKUP-FULL-8]
|
||||
@@ -2925,7 +2945,6 @@ P00 INFO: expire command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -2946,6 +2965,9 @@ db-version="9.2"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201204301,"db-control-version":922,"db-system-id":1000000000000000092,"db-version":"9.2"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> ls [TEST_PATH]/db-master/repo/backup/db | grep -v "backup.*"
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
[BACKUP-FULL-8]
|
||||
@@ -3013,7 +3035,6 @@ db-version="9.2"
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -3034,6 +3055,9 @@ db-version="9.2"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201204301,"db-control-version":922,"db-system-id":1000000000000000092,"db-version":"9.2"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> ls [TEST_PATH]/db-master/repo/backup/db | grep -v "backup.*"
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
[BACKUP-FULL-8]
|
||||
@@ -3110,7 +3134,6 @@ P00 INFO: expire command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -3131,6 +3154,9 @@ db-version="9.2"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201204301,"db-control-version":922,"db-system-id":1000000000000000092,"db-version":"9.2"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> ls [TEST_PATH]/db-master/repo/backup/db | grep -v "backup.*"
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
[BACKUP-FULL-8]
|
||||
|
||||
@@ -75,7 +75,6 @@ P00 INFO: expire command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -94,6 +93,9 @@ db-version="9.2"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201204301,"db-control-version":922,"db-system-id":1000000000000000092,"db-version":"9.2"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> ls [TEST_PATH]/db-master/repo/backup/db | grep -v "backup.*"
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
[BACKUP-FULL-1]
|
||||
@@ -486,7 +488,6 @@ P00 INFO: expire command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -508,6 +509,9 @@ db-version="9.3"
|
||||
1={"db-catalog-version":201204301,"db-control-version":922,"db-system-id":1000000000000000092,"db-version":"9.2"}
|
||||
2={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> ls [TEST_PATH]/db-master/repo/backup/db | grep -v "backup.*"
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
[BACKUP-FULL-2]
|
||||
@@ -1160,7 +1164,6 @@ P00 INFO: expire command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -1181,6 +1184,9 @@ db-version="10"
|
||||
2={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
3={"db-catalog-version":201707211,"db-control-version":1002,"db-system-id":1000000000000000100,"db-version":"10"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> ls [TEST_PATH]/db-master/repo/backup/db | grep -v "backup.*"
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
[BACKUP-FULL-4]
|
||||
@@ -1310,7 +1316,6 @@ P00 INFO: expire command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -1331,6 +1336,9 @@ db-version="10"
|
||||
2={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
3={"db-catalog-version":201707211,"db-control-version":1002,"db-system-id":1000000000000000100,"db-version":"10"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> ls [TEST_PATH]/db-master/repo/backup/db | grep -v "backup.*"
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
[BACKUP-FULL-4]
|
||||
@@ -1375,7 +1383,6 @@ db-version="10"
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -1396,6 +1403,9 @@ db-version="10"
|
||||
2={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
3={"db-catalog-version":201707211,"db-control-version":1002,"db-system-id":1000000000000000100,"db-version":"10"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> ls [TEST_PATH]/db-master/repo/backup/db | grep -v "backup.*"
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
[BACKUP-FULL-4]
|
||||
@@ -1451,7 +1461,6 @@ P00 INFO: expire command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -1471,6 +1480,9 @@ db-version="10"
|
||||
2={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
3={"db-catalog-version":201707211,"db-control-version":1002,"db-system-id":1000000000000000100,"db-version":"10"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> ls [TEST_PATH]/db-master/repo/backup/db | grep -v "backup.*"
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
[BACKUP-FULL-5]
|
||||
|
||||
@@ -30,7 +30,6 @@ P00 INFO: stanza-create command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -44,10 +43,12 @@ db-version="9.3"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
-----------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -59,6 +60,9 @@ db-version="9.3"
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
stanza-create db - do not fail on rerun of stanza-create - info files exist and DB section ok (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -69,7 +73,6 @@ P00 INFO: stanza-create command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -83,10 +86,12 @@ db-version="9.3"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
-----------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -98,6 +103,9 @@ db-version="9.3"
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
stanza-create db - fail on database mismatch and warn force option deprecated (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online --force stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -111,7 +119,6 @@ P00 INFO: stanza-create command end: aborted with exception [028]
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -125,10 +132,12 @@ db-version="9.3"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
-----------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -140,6 +149,9 @@ db-version="9.3"
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
stanza-upgrade db - already up to date (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online stanza-upgrade
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -150,7 +162,6 @@ P00 INFO: stanza-upgrade command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -164,10 +175,12 @@ db-version="9.3"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
-----------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -179,6 +192,9 @@ db-version="9.3"
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001] --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
@@ -196,7 +212,6 @@ P00 INFO: stanza-create command end: aborted with exception [055]
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -210,6 +225,9 @@ db-version="9.3"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000002] --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
@@ -230,7 +248,6 @@ P00 INFO: stanza-upgrade command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -245,10 +262,12 @@ db-version="9.4"
|
||||
1={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
2={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
-----------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -261,6 +280,9 @@ db-version="9.4"
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
2={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-get 000000010000000100000002 [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: archive-get command begin [BACKREST-VERSION]: [000000010000000100000002, [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG] --compress-level=3 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-path=[TEST_PATH]/db-master/repo --stanza=db
|
||||
@@ -320,7 +342,6 @@ P00 INFO: stanza-upgrade command end: completed successfully
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -339,10 +360,12 @@ db-version="9.5"
|
||||
2={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
3={"db-catalog-version":201510051,"db-control-version":942,"db-system-id":1000000000000000095,"db-version":"9.5"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
-----------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -356,6 +379,9 @@ db-version="9.5"
|
||||
2={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
3={"db-id":1000000000000000095,"db-version":"9.5"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
stanza-upgrade db - upgrade fails with mismatched db-ids (db-master host)
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db --no-online stanza-upgrade
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -369,7 +395,6 @@ P00 INFO: stanza-upgrade command end: aborted with exception [028]
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/backup/db/backup.info
|
||||
---------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -388,10 +413,12 @@ db-version="9.5"
|
||||
2={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
3={"db-catalog-version":201510051,"db-control-version":942,"db-system-id":1000000000000000095,"db-version":"9.5"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
+ supplemental file: [TEST_PATH]/db-master/repo/archive/db/archive.info
|
||||
-----------------------------------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -403,6 +430,9 @@ db-version="9.3"
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --log-level-console=warn --archive-push-queue-max=33554432 --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ P00 INFO: stanza-create command end: completed successfully
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -51,10 +50,12 @@ db-version="9.3"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
+ supplemental file: /archive/db/archive.info
|
||||
---------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -69,6 +70,9 @@ db-version="9.3"
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
stanza-create db - do not fail on rerun of stanza-create - info files exist and DB section ok (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --no-online stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -81,7 +85,6 @@ P00 INFO: stanza-create command end: completed successfully
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -98,10 +101,12 @@ db-version="9.3"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
+ supplemental file: /archive/db/archive.info
|
||||
---------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -116,6 +121,9 @@ db-version="9.3"
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
stanza-create db - fail on database mismatch and warn force option deprecated (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --no-online --force stanza-create
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -131,7 +139,6 @@ P00 INFO: stanza-create command end: aborted with exception [028]
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -148,10 +155,12 @@ db-version="9.3"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
+ supplemental file: /archive/db/archive.info
|
||||
---------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -166,6 +175,9 @@ db-version="9.3"
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
stanza-upgrade db - already up to date (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --no-online stanza-upgrade
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -178,7 +190,6 @@ P00 INFO: stanza-upgrade command end: completed successfully
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -195,10 +206,12 @@ db-version="9.3"
|
||||
[db:history]
|
||||
1={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
+ supplemental file: /archive/db/archive.info
|
||||
---------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -213,6 +226,9 @@ db-version="9.3"
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: archive-push command begin [BACKREST-VERSION]: [[TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001] --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-host=backup --repo1-host-cmd=[BACKREST-BIN] --repo1-host-config=[TEST_PATH]/backup/pgbackrest.conf --repo1-host-user=[USER-2] --stanza=db
|
||||
@@ -241,7 +257,6 @@ P00 INFO: stanza-upgrade command end: completed successfully
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -259,10 +274,12 @@ db-version="9.4"
|
||||
1={"db-catalog-version":201306121,"db-control-version":937,"db-system-id":1000000000000000093,"db-version":"9.3"}
|
||||
2={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
+ supplemental file: /archive/db/archive.info
|
||||
---------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -278,6 +295,9 @@ db-version="9.4"
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
2={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --stanza=db archive-get 000000010000000100000002 [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
P00 INFO: archive-get command begin [BACKREST-VERSION]: [000000010000000100000002, [TEST_PATH]/db-master/db/base/pg_xlog/RECOVERYXLOG] --compress-level=3 --compress-level-network=1 --config=[TEST_PATH]/db-master/pgbackrest.conf --db-timeout=45 --lock-path=[TEST_PATH]/db-master/lock --log-level-console=detail --log-level-file=trace --log-level-stderr=off --log-path=[TEST_PATH]/db-master/log --log-subprocess --no-log-timestamp --pg1-path=[TEST_PATH]/db-master/db/base --protocol-timeout=60 --repo1-host=backup --repo1-host-cmd=[BACKREST-BIN] --repo1-host-config=[TEST_PATH]/backup/pgbackrest.conf --repo1-host-user=[USER-2] --stanza=db
|
||||
@@ -379,7 +399,6 @@ P00 INFO: stanza-upgrade command end: completed successfully
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -401,10 +420,12 @@ db-version="9.5"
|
||||
2={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
3={"db-catalog-version":201510051,"db-control-version":942,"db-system-id":1000000000000000095,"db-version":"9.5"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
+ supplemental file: /archive/db/archive.info
|
||||
---------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -421,6 +442,9 @@ db-version="9.5"
|
||||
2={"db-id":1000000000000000094,"db-version":"9.4"}
|
||||
3={"db-id":1000000000000000095,"db-version":"9.5"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
stanza-upgrade db - upgrade fails with mismatched db-ids (backup host)
|
||||
> [CONTAINER-EXEC] backup [BACKREST-BIN] --config=[TEST_PATH]/backup/pgbackrest.conf --stanza=db --no-online stanza-upgrade
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -436,7 +460,6 @@ P00 INFO: stanza-upgrade command end: aborted with exception [028]
|
||||
+ supplemental file: /backup/db/backup.info
|
||||
-------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -458,10 +481,12 @@ db-version="9.5"
|
||||
2={"db-catalog-version":201409291,"db-control-version":942,"db-system-id":1000000000000000094,"db-version":"9.4"}
|
||||
3={"db-catalog-version":201510051,"db-control-version":942,"db-system-id":1000000000000000095,"db-version":"9.5"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
+ supplemental file: /archive/db/archive.info
|
||||
---------------------------------------------
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
backrest-format=5
|
||||
backrest-version="[VERSION-1]"
|
||||
|
||||
@@ -476,6 +501,9 @@ db-version="9.3"
|
||||
[db:history]
|
||||
1={"db-id":1000000000000000093,"db-version":"9.3"}
|
||||
|
||||
[backrest]
|
||||
backrest-checksum="[CHECKSUM]"
|
||||
|
||||
> [CONTAINER-EXEC] db-master [BACKREST-BIN] --config=[TEST_PATH]/db-master/pgbackrest.conf --log-level-console=warn --archive-push-queue-max=33554432 --stanza=db archive-push [TEST_PATH]/db-master/db/base/pg_xlog/000000010000000100000001
|
||||
------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -1,19 +1,62 @@
|
||||
/***********************************************************************************************************************************
|
||||
Harness for Loading Test Configurations
|
||||
***********************************************************************************************************************************/
|
||||
#include "common/harnessDebug.h"
|
||||
#include "common/harnessInfo.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "common/io/bufferWrite.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/crypto/hash.h"
|
||||
#include "common/io/bufferRead.h"
|
||||
#include "common/io/filter/filter.intern.h"
|
||||
#include "common/type/json.h"
|
||||
#include "info/info.h"
|
||||
#include "version.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Load a test configuration without any side effects
|
||||
#include "common/harnessDebug.h"
|
||||
#include "common/harnessInfo.h"
|
||||
|
||||
There's no need to open log files, acquire locks, reset log levels, etc.
|
||||
/***********************************************************************************************************************************
|
||||
Add header and checksum to an info file
|
||||
|
||||
This prevents churn in headers and checksums in the unit tests. We purposefully do not use the checksum macros from the info module
|
||||
here as a cross-check of that code.
|
||||
***********************************************************************************************************************************/
|
||||
typedef struct HarnessInfoChecksumData
|
||||
{
|
||||
MemContext *memContext; // Mem context to use for storing data in this structure
|
||||
String *sectionLast; // The last section seen during load
|
||||
IoFilter *checksum; // Checksum calculated from the file
|
||||
} HarnessInfoChecksumData;
|
||||
|
||||
static void
|
||||
harnessInfoChecksumCallback(void *callbackData, const String *section, const String *key, const String *value)
|
||||
{
|
||||
HarnessInfoChecksumData *data = (HarnessInfoChecksumData *)callbackData;
|
||||
|
||||
// Calculate checksum
|
||||
if (data->sectionLast == NULL || !strEq(section, data->sectionLast))
|
||||
{
|
||||
if (data->sectionLast != NULL)
|
||||
ioFilterProcessIn(data->checksum, BUFSTRDEF("},"));
|
||||
|
||||
ioFilterProcessIn(data->checksum, BUFSTRDEF("\""));
|
||||
ioFilterProcessIn(data->checksum, BUFSTR(section));
|
||||
ioFilterProcessIn(data->checksum, BUFSTRDEF("\":{"));
|
||||
|
||||
MEM_CONTEXT_BEGIN(data->memContext)
|
||||
{
|
||||
data->sectionLast = strDup(section);
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
}
|
||||
else
|
||||
ioFilterProcessIn(data->checksum, BUFSTRDEF(","));
|
||||
|
||||
ioFilterProcessIn(data->checksum, BUFSTRDEF("\""));
|
||||
ioFilterProcessIn(data->checksum, BUFSTR(key));
|
||||
ioFilterProcessIn(data->checksum, BUFSTRDEF("\":"));
|
||||
ioFilterProcessIn(data->checksum, BUFSTR(value));
|
||||
}
|
||||
|
||||
Buffer *
|
||||
harnessInfoChecksum(const String *info)
|
||||
{
|
||||
@@ -25,18 +68,33 @@ harnessInfoChecksum(const String *info)
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
// Load data into an ini file
|
||||
Ini *ini = iniNew();
|
||||
iniParse(ini, info);
|
||||
// Initialize callback data
|
||||
HarnessInfoChecksumData data =
|
||||
{
|
||||
.memContext = MEM_CONTEXT_TEMP(),
|
||||
.checksum = cryptoHashNew(HASH_TYPE_SHA1_STR),
|
||||
};
|
||||
|
||||
// Add header and checksum values
|
||||
iniSet(ini, STRDEF("backrest"), STRDEF("backrest-version"), jsonFromStr(STRDEF(PROJECT_VERSION)));
|
||||
iniSet(ini, STRDEF("backrest"), STRDEF("backrest-format"), jsonFromUInt(REPOSITORY_FORMAT));
|
||||
iniSet(ini, STRDEF("backrest"), STRDEF("backrest-checksum"), jsonFromStr(infoHash(ini)));
|
||||
// Create buffer with space for data, header, and checksum
|
||||
result = bufNew(strSize(info) + 256);
|
||||
|
||||
bufCat(result, BUFSTRDEF("[backrest]\nbackrest-format="));
|
||||
bufCat(result, BUFSTR(jsonFromUInt(REPOSITORY_FORMAT)));
|
||||
bufCat(result, BUFSTRDEF("\nbackrest-version="));
|
||||
bufCat(result, BUFSTR(jsonFromStr(STRDEF(PROJECT_VERSION))));
|
||||
bufCat(result, BUFSTRDEF("\n\n"));
|
||||
bufCat(result, BUFSTR(info));
|
||||
|
||||
// Generate checksum by loading ini file
|
||||
ioFilterProcessIn(data.checksum, BUFSTRDEF("{"));
|
||||
iniLoad(ioBufferReadNew(result), harnessInfoChecksumCallback, &data);
|
||||
ioFilterProcessIn(data.checksum, BUFSTRDEF("}}"));
|
||||
|
||||
// Append checksum to buffer
|
||||
bufCat(result, BUFSTRDEF("\n[backrest]\nbackrest-checksum="));
|
||||
bufCat(result, BUFSTR(jsonFromVar(ioFilterResult(data.checksum), 0)));
|
||||
bufCat(result, BUFSTRDEF("\n"));
|
||||
|
||||
// Write to a buffer
|
||||
result = bufNew(0);
|
||||
iniSave(ini, ioBufferWriteNew(result));
|
||||
bufMove(result, MEM_CONTEXT_OLD());
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
@@ -51,5 +109,15 @@ harnessInfoChecksumZ(const char *info)
|
||||
FUNCTION_HARNESS_PARAM(STRINGZ, info);
|
||||
FUNCTION_HARNESS_END();
|
||||
|
||||
FUNCTION_HARNESS_RESULT(BUFFER, harnessInfoChecksum(STRDEF(info)));
|
||||
FUNCTION_HARNESS_RESULT(BUFFER, harnessInfoChecksum(STR(info)));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Test callback that logs the results to a string
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
harnessInfoLoadNewCallback(void *callbackData, const String *section, const String *key, const String *value)
|
||||
{
|
||||
if (callbackData != NULL)
|
||||
strCatFmt((String *)callbackData, "[%s] %s=%s\n", strPtr(section), strPtr(key), strPtr(value));
|
||||
}
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
Harness for Generating Test Info Files
|
||||
***********************************************************************************************************************************/
|
||||
#include "common/type/buffer.h"
|
||||
#include "info/info.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
***********************************************************************************************************************************/
|
||||
Buffer *harnessInfoChecksum(const String *info);
|
||||
Buffer *harnessInfoChecksumZ(const char *info);
|
||||
|
||||
void harnessInfoLoadNewCallback(void *callbackData, const String *section, const String *key, const String *value);
|
||||
|
||||
@@ -155,7 +155,7 @@ testRun(void)
|
||||
storagePutNP(storageNewWriteNP(storageTest, backupInfoFileName), harnessInfoChecksum(backupInfoBase));
|
||||
|
||||
InfoBackup *infoBackup = NULL;
|
||||
TEST_ASSIGN(infoBackup, infoBackupNewLoad(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
||||
TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
||||
|
||||
// Create backup directories and manifest files
|
||||
String *full1 = strNew("20181119-152138F");
|
||||
@@ -201,7 +201,7 @@ testRun(void)
|
||||
storagePutNP(storageNewWriteNP(storageTest, backupInfoFileName), harnessInfoChecksum(backupInfoBase));
|
||||
|
||||
InfoBackup *infoBackup = NULL;
|
||||
TEST_ASSIGN(infoBackup, infoBackupNewLoad(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
||||
TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
||||
|
||||
// Load Parameters
|
||||
StringList *argList = strLstDup(argListBase);
|
||||
@@ -253,7 +253,7 @@ testRun(void)
|
||||
storagePutNP(storageNewWriteNP(storageTest, backupInfoFileName), harnessInfoChecksum(backupInfoBase));
|
||||
|
||||
InfoBackup *infoBackup = NULL;
|
||||
TEST_ASSIGN(infoBackup, infoBackupNewLoad(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
||||
TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
||||
|
||||
// Load Parameters
|
||||
StringList *argList = strLstDup(argListAvoidWarn);
|
||||
@@ -328,7 +328,7 @@ testRun(void)
|
||||
"[db:history]\n"
|
||||
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6625592122879095702,"
|
||||
"\"db-version\":\"9.4\"}"));
|
||||
TEST_ASSIGN(infoBackup, infoBackupNewLoad(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
||||
TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
||||
|
||||
// Load parameters
|
||||
argList = strLstDup(argListAvoidWarn);
|
||||
@@ -374,7 +374,7 @@ testRun(void)
|
||||
"\"db-version\":\"9.4\"}"));
|
||||
|
||||
InfoBackup *infoBackup = NULL;
|
||||
TEST_ASSIGN(infoBackup, infoBackupNewLoad(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
||||
TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
||||
|
||||
// Create backup directories, manifest files and other path/file
|
||||
String *full = strNewFmt("%s/%s", strPtr(backupStanzaPath), "20181119-152100F");
|
||||
@@ -426,7 +426,7 @@ testRun(void)
|
||||
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6625592122879095702,"
|
||||
"\"db-version\":\"9.4\"}"));
|
||||
|
||||
TEST_ASSIGN(infoBackup,infoBackupNewLoad(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
||||
TEST_ASSIGN(infoBackup,infoBackupLoadFile(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
||||
|
||||
TEST_RESULT_VOID(removeExpiredBackup(infoBackup), "remove backups - backup.info current empty");
|
||||
|
||||
@@ -459,7 +459,7 @@ testRun(void)
|
||||
"\"db-version\":\"9.4\"}"));
|
||||
|
||||
InfoBackup *infoBackup = NULL;
|
||||
TEST_ASSIGN(infoBackup, infoBackupNewLoad(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
||||
TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
||||
|
||||
TEST_RESULT_VOID(removeExpiredArchive(infoBackup), "archive retention not set");
|
||||
harnessLogResult(
|
||||
@@ -555,7 +555,7 @@ testRun(void)
|
||||
"2={\"db-catalog-version\":201707211,\"db-control-version\":1002,\"db-system-id\":6626363367545678089,"
|
||||
"\"db-version\":\"10\"}\n"));
|
||||
|
||||
TEST_ASSIGN(infoBackup, infoBackupNewLoad(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
||||
TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
||||
|
||||
storagePutNP(
|
||||
storageNewWriteNP(storageTest, archiveInfoFileName),
|
||||
@@ -743,7 +743,7 @@ testRun(void)
|
||||
"20181119-152800F_20181119-152155I, 20181119-152800F_20181119-152252D\n"
|
||||
"P00 INFO: remove archive path: %s/%s/9.4-1", testPath(), strPtr(archiveStanzaPath))));
|
||||
|
||||
TEST_ASSIGN(infoBackup, infoBackupNewLoad(storageTest, backupInfoFileName, cipherTypeNone, NULL), " get backup.info");
|
||||
TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, backupInfoFileName, cipherTypeNone, NULL), " get backup.info");
|
||||
TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 2, " backup.info updated on disk");
|
||||
TEST_RESULT_STR(
|
||||
strPtr(strLstJoin(strLstSort(infoBackupDataLabelList(infoBackup, NULL), sortOrderAsc), ", ")),
|
||||
@@ -790,7 +790,7 @@ testRun(void)
|
||||
"2={\"db-catalog-version\":201707211,\"db-control-version\":1002,\"db-system-id\":6626363367545678089,"
|
||||
"\"db-version\":\"10\"}\n"));
|
||||
|
||||
TEST_ASSIGN(infoBackup, infoBackupNewLoad(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
||||
TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
||||
|
||||
archiveGenerate(storageTest, archiveStanzaPath, 1, 5, "9.4-1", "0000000100000000");
|
||||
|
||||
|
||||
@@ -740,14 +740,14 @@ testRun(void)
|
||||
TEST_ERROR_FMT(
|
||||
infoRender(), CryptoError,
|
||||
"unable to load info file '%s/backup.info' or '%s/backup.info.copy':\n"
|
||||
"CryptoError: '%s/backup.info' cipher header invalid\n"
|
||||
"HINT: Is or was the repo encrypted?\n"
|
||||
"CryptoError: cipher header invalid\n"
|
||||
"HINT: is or was the repo encrypted?\n"
|
||||
"FileMissingError: " STORAGE_ERROR_READ_MISSING "\n"
|
||||
"HINT: backup.info cannot be opened and is required to perform a backup.\n"
|
||||
"HINT: has a stanza-create been performed?\n"
|
||||
"HINT: use option --stanza if encryption settings are different for the stanza than the global settings",
|
||||
strPtr(backupStanza2Path), strPtr(backupStanza2Path), strPtr(backupStanza2Path),
|
||||
strPtr(strNewFmt("%s/backup.info.copy", strPtr(backupStanza2Path))));
|
||||
strPtr(backupStanza2Path), strPtr(backupStanza2Path), strPtr(strNewFmt("%s/backup.info.copy",
|
||||
strPtr(backupStanza2Path))));
|
||||
}
|
||||
|
||||
//******************************************************************************************************************************
|
||||
|
||||
@@ -571,13 +571,13 @@ testRun(void)
|
||||
|
||||
InfoArchive *infoArchive = NULL;
|
||||
TEST_ASSIGN(
|
||||
infoArchive, infoArchiveNewLoad(storageTest, archiveInfoFileName, cipherTypeAes256Cbc, strNew("12345678")),
|
||||
infoArchive, infoArchiveLoadFile(storageTest, archiveInfoFileName, cipherTypeAes256Cbc, strNew("12345678")),
|
||||
" load archive info");
|
||||
TEST_RESULT_PTR_NE(infoArchiveCipherPass(infoArchive), NULL, " cipher sub set");
|
||||
|
||||
InfoBackup *infoBackup = NULL;
|
||||
TEST_ASSIGN(
|
||||
infoBackup, infoBackupNewLoad(storageTest, backupInfoFileName, cipherTypeAes256Cbc, strNew("12345678")),
|
||||
infoBackup, infoBackupLoadFile(storageTest, backupInfoFileName, cipherTypeAes256Cbc, strNew("12345678")),
|
||||
" load backup info");
|
||||
TEST_RESULT_PTR_NE(infoBackupCipherPass(infoBackup), NULL, " cipher sub set");
|
||||
|
||||
|
||||
@@ -1,8 +1,31 @@
|
||||
/***********************************************************************************************************************************
|
||||
Test Ini
|
||||
***********************************************************************************************************************************/
|
||||
#include "common/io/bufferRead.h"
|
||||
#include "common/type/buffer.h"
|
||||
#include "storage/posix/storage.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Test callback to accumulate ini load results
|
||||
***********************************************************************************************************************************/
|
||||
static void
|
||||
testIniLoadCallback(void *data, const String *section, const String *key, const String *value)
|
||||
{
|
||||
strCatFmt((String *)data, "%s:%s:%s\n", strPtr(section), strPtr(key), strPtr(value));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Test callback to count ini load results
|
||||
***********************************************************************************************************************************/
|
||||
static void
|
||||
testIniLoadCountCallback(void *data, const String *section, const String *key, const String *value)
|
||||
{
|
||||
(*(unsigned int *)data)++;
|
||||
(void)section;
|
||||
(void)key;
|
||||
(void)value;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Test Run
|
||||
***********************************************************************************************************************************/
|
||||
@@ -11,8 +34,94 @@ testRun(void)
|
||||
{
|
||||
FUNCTION_HARNESS_VOID();
|
||||
|
||||
Storage *storageTest = storagePosixNew(
|
||||
strNew(testPath()), STORAGE_MODE_FILE_DEFAULT, STORAGE_MODE_PATH_DEFAULT, true, NULL);
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("iniLoad()"))
|
||||
{
|
||||
// Empty file
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
const Buffer *iniBuf = bufNew(0);
|
||||
String *result = strNew("");
|
||||
|
||||
TEST_RESULT_VOID(iniLoad(ioBufferReadNew(iniBuf), testIniLoadCallback, result), "load ini");
|
||||
TEST_RESULT_STR(strPtr(result), "", " check ini");
|
||||
|
||||
// Invalid section
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
iniBuf = BUFSTRZ(
|
||||
" [section ");
|
||||
|
||||
TEST_ERROR(
|
||||
iniLoad(ioBufferReadNew(iniBuf), testIniLoadCallback, result), FormatError,
|
||||
"ini section should end with ] at line 1: [section");
|
||||
|
||||
// Key outside of section
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
iniBuf = BUFSTRZ(
|
||||
"key=value\n");
|
||||
|
||||
TEST_ERROR(
|
||||
iniLoad(ioBufferReadNew(iniBuf), testIniLoadCallback, result), FormatError,
|
||||
"key/value found outside of section at line 1: key=value");
|
||||
|
||||
// Key outside of section
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
iniBuf = BUFSTRZ(
|
||||
"[section]\n"
|
||||
"key");
|
||||
|
||||
TEST_ERROR(
|
||||
iniLoad(ioBufferReadNew(iniBuf), testIniLoadCallback, result), FormatError,
|
||||
"missing '=' in key/value at line 2: key");
|
||||
|
||||
// Zero length key
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
iniBuf = BUFSTRZ(
|
||||
"[section]\n"
|
||||
"=value");
|
||||
|
||||
TEST_ERROR(
|
||||
iniLoad(ioBufferReadNew(iniBuf), testIniLoadCallback, result), FormatError,
|
||||
"key is zero-length at line 1: =value");
|
||||
|
||||
// One section
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
iniBuf = BUFSTRZ(
|
||||
"# comment\n"
|
||||
"[section1]\n"
|
||||
"key1=value1\n"
|
||||
"key2=value2");
|
||||
result = strNew("");
|
||||
|
||||
TEST_RESULT_VOID(iniLoad(ioBufferReadNew(iniBuf), testIniLoadCallback, result), "load ini");
|
||||
TEST_RESULT_STR(
|
||||
strPtr(result),
|
||||
"section1:key1:value1\n"
|
||||
"section1:key2:value2\n",
|
||||
" check ini");
|
||||
|
||||
// Two sections
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
iniBuf = BUFSTRZ(
|
||||
"# comment\n"
|
||||
"[section1]\n"
|
||||
"key1=value1\n"
|
||||
"key2=value2\n"
|
||||
"\n"
|
||||
"[section2]\n"
|
||||
"key1=\n"
|
||||
"\n"
|
||||
"key2=value2");
|
||||
result = strNew("");
|
||||
|
||||
TEST_RESULT_VOID(iniLoad(ioBufferReadNew(iniBuf), testIniLoadCallback, result), "load ini");
|
||||
TEST_RESULT_STR(
|
||||
strPtr(result),
|
||||
"section1:key1:value1\n"
|
||||
"section1:key2:value2\n"
|
||||
"section2:key1:\n"
|
||||
"section2:key2:value2\n",
|
||||
" check ini");
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("iniNew() and iniFree()"))
|
||||
@@ -102,25 +211,25 @@ testRun(void)
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("iniSave()"))
|
||||
if (testBegin("iniLoad() performance"))
|
||||
{
|
||||
Ini *ini = iniNew();
|
||||
iniSet(ini, strNew("section2"), strNew("key1"), strNew("value1"));
|
||||
iniSet(ini, strNew("section1"), strNew("key2"), strNew("value2"));
|
||||
iniSet(ini, strNew("section1"), strNew("key1"), strNew("value1"));
|
||||
String *iniStr = strNew("[section1]\n");
|
||||
unsigned int iniMax = 1000;
|
||||
|
||||
StorageWrite *write = storageNewWriteNP(storageTest, strNew("test.ini"));
|
||||
TEST_RESULT_VOID(iniSave(ini, storageWriteIo(write)), "save ini");
|
||||
// /backrest/test/test.pl --vm=u18 --smart --no-package --module=common --test=ini --run=5 --no-cleanup --vm-out
|
||||
// BASELINE PERF ON DESKTOP 50784ms
|
||||
|
||||
TEST_RESULT_STR(
|
||||
strPtr(strNewBuf(storageGetNP(storageNewReadNP(storageTest, strNew("test.ini"))))),
|
||||
"[section1]\n"
|
||||
"key1=value1\n"
|
||||
"key2=value2\n"
|
||||
"\n"
|
||||
"[section2]\n"
|
||||
"key1=value1\n",
|
||||
"check ini");
|
||||
for (unsigned int keyIdx = 0; keyIdx < iniMax; keyIdx++)
|
||||
strCatFmt(iniStr, "key%u=value%u\n", keyIdx, keyIdx);
|
||||
|
||||
TEST_LOG_FMT("ini size is %zu", strSize(iniStr));
|
||||
|
||||
TimeMSec timeBegin = timeMSec();
|
||||
unsigned int iniTotal = 0;
|
||||
|
||||
TEST_RESULT_VOID(iniLoad(ioBufferReadNew(BUFSTR(iniStr)), testIniLoadCountCallback, &iniTotal), "parse ini");
|
||||
TEST_LOG_FMT("parse completed in %ums", (unsigned int)(timeMSec() - timeBegin));
|
||||
TEST_RESULT_INT(iniTotal, iniMax, " check ini total");
|
||||
}
|
||||
|
||||
FUNCTION_HARNESS_RESULT_VOID();
|
||||
|
||||
@@ -3,7 +3,9 @@ Test Archive Info Handler
|
||||
***********************************************************************************************************************************/
|
||||
#include <stdio.h>
|
||||
|
||||
#include "storage/storage.intern.h"
|
||||
#include "common/io/bufferRead.h"
|
||||
#include "common/io/bufferWrite.h"
|
||||
#include "storage/posix/storage.h"
|
||||
|
||||
#include "common/harnessInfo.h"
|
||||
|
||||
@@ -13,33 +15,15 @@ Test Run
|
||||
void
|
||||
testRun(void)
|
||||
{
|
||||
// Initialize test variables
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
String *content = NULL;
|
||||
String *fileName = strNewFmt("%s/test.ini", testPath());
|
||||
String *fileName2 = strNewFmt("%s/test2.ini", testPath());
|
||||
InfoArchive *info = NULL;
|
||||
String *cipherPass = strNew("123xyz");
|
||||
// Create default storage object for testing
|
||||
Storage *storageTest = storagePosixNew(
|
||||
strNew(testPath()), STORAGE_MODE_FILE_DEFAULT, STORAGE_MODE_PATH_DEFAULT, true, NULL);
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin(
|
||||
"infoArchiveNewLoad(), infoArchiveNew(), infoArchiveNewInternal(), infoArchivePg(), infoArchiveCipherPass(), "
|
||||
"infoArchiveSave(), infoArchiveFree()"))
|
||||
if (testBegin("InfoArchive"))
|
||||
{
|
||||
TEST_ERROR_FMT(
|
||||
infoArchiveNewLoad(storageLocal(), fileName, cipherTypeNone, NULL), FileMissingError,
|
||||
"unable to load info file '%s/test.ini' or '%s/test.ini.copy':\n"
|
||||
"FileMissingError: " STORAGE_ERROR_READ_MISSING "\n"
|
||||
"FileMissingError: " STORAGE_ERROR_READ_MISSING "\n"
|
||||
"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.",
|
||||
testPath(), testPath(), strPtr(strNewFmt("%s/test.ini", testPath())),
|
||||
strPtr(strNewFmt("%s/test.ini.copy", testPath())));
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
content = strNew
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
const Buffer *contentLoad = harnessInfoChecksumZ
|
||||
(
|
||||
"[db]\n"
|
||||
"db-id=1\n"
|
||||
@@ -50,65 +34,53 @@ testRun(void)
|
||||
"1={\"db-id\":6569239123849665679,\"db-version\":\"9.4\"}\n"
|
||||
);
|
||||
|
||||
TEST_RESULT_VOID(
|
||||
storagePutNP(
|
||||
storageNewWriteNP(storageLocalWrite(), fileName), harnessInfoChecksum(content)), "put archive info to file");
|
||||
InfoArchive *info = NULL;
|
||||
|
||||
TEST_ASSIGN(info, infoArchiveNewLoad(storageLocal(), fileName, cipherTypeNone, NULL), " load new archive info");
|
||||
TEST_ASSIGN(info, infoArchiveNewLoad(ioBufferReadNew(contentLoad)), " load new archive info");
|
||||
TEST_RESULT_STR(strPtr(infoArchiveId(info)), "9.4-1", " archiveId set");
|
||||
TEST_RESULT_PTR(infoArchivePg(info), info->infoPg, " infoPg set");
|
||||
TEST_RESULT_PTR(infoArchiveCipherPass(info), NULL, " no cipher sub");
|
||||
|
||||
TEST_RESULT_VOID(
|
||||
infoArchiveSave(info, storageLocalWrite(), fileName2, cipherTypeNone, NULL), "infoArchiveSave() - no cipher");
|
||||
TEST_RESULT_BOOL(
|
||||
bufEq(
|
||||
storageGetNP(storageNewReadNP(storageLocal(), fileName)),
|
||||
storageGetNP(storageNewReadNP(storageLocal(), fileName2))),
|
||||
true, " saved files are equal");
|
||||
// Save info and verify
|
||||
Buffer *contentSave = bufNew(0);
|
||||
|
||||
// Remove the file just written and recreate it from scratch
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
storageRemoveP(storageLocalWrite(), fileName2, .errorOnMissing = true);
|
||||
TEST_RESULT_VOID(infoArchiveSave(info, ioBufferWriteNew(contentSave)), "info archive save");
|
||||
TEST_RESULT_STR(strPtr(strNewBuf(contentSave)), strPtr(strNewBuf(contentLoad)), " check save");
|
||||
|
||||
info = NULL;
|
||||
// Create the same content by creating a new object
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_ASSIGN(
|
||||
info, infoArchiveNew(PG_VERSION_94, 6569239123849665679, cipherTypeNone, NULL), "infoArchiveNew() - no sub cipher");
|
||||
info, infoArchiveNew(PG_VERSION_94, 6569239123849665679, NULL), "infoArchiveNew() - no sub cipher");
|
||||
TEST_RESULT_STR(strPtr(infoArchiveId(info)), "9.4-1", " archiveId set");
|
||||
TEST_RESULT_PTR(infoArchivePg(info), info->infoPg, " infoPg set");
|
||||
TEST_RESULT_PTR(infoArchiveCipherPass(info), NULL, " no cipher sub");
|
||||
TEST_RESULT_INT(infoPgDataTotal(info->infoPg), 1, " history set");
|
||||
|
||||
TEST_RESULT_VOID(
|
||||
infoArchiveSave(info, storageLocalWrite(), fileName2, cipherTypeNone, NULL), " save new");
|
||||
TEST_RESULT_BOOL(
|
||||
bufEq(
|
||||
storageGetNP(storageNewReadNP(storageLocal(), fileName)),
|
||||
storageGetNP(storageNewReadNP(storageLocal(), fileName2))),
|
||||
true, " saved files are equal");
|
||||
Buffer *contentCompare = bufNew(0);
|
||||
|
||||
TEST_RESULT_VOID(infoArchiveSave(info, ioBufferWriteNew(contentCompare)), "info archive save");
|
||||
TEST_RESULT_STR(strPtr(strNewBuf(contentCompare)), strPtr(strNewBuf(contentSave)), " check save");
|
||||
|
||||
// Remove both files and recreate from scratch with cipher
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
storageRemoveP(storageLocalWrite(), fileName, .errorOnMissing = true);
|
||||
storageRemoveP(storageLocalWrite(), fileName2, .errorOnMissing = true);
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_ASSIGN(
|
||||
info, infoArchiveNew(PG_VERSION_10, 6569239123849665999, cipherTypeAes256Cbc,
|
||||
strNew("zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO")),
|
||||
info,
|
||||
infoArchiveNew(
|
||||
PG_VERSION_10, 6569239123849665999, strNew("zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO")),
|
||||
"infoArchiveNew() - cipher sub");
|
||||
TEST_RESULT_VOID(
|
||||
infoArchiveSave(info, storageLocalWrite(), fileName, cipherTypeAes256Cbc, cipherPass), " save new encrypted");
|
||||
|
||||
info = NULL;
|
||||
TEST_ASSIGN(info, infoArchiveNewLoad(storageLocal(), fileName, cipherTypeAes256Cbc, cipherPass),
|
||||
" load encrypted archive info");
|
||||
contentSave = bufNew(0);
|
||||
|
||||
TEST_RESULT_VOID(infoArchiveSave(info, ioBufferWriteNew(contentSave)), " save new with cipher");
|
||||
|
||||
TEST_ASSIGN(info, infoArchiveNewLoad(ioBufferReadNew(contentSave)), " load encrypted archive info");
|
||||
TEST_RESULT_STR(strPtr(infoArchiveId(info)), "10-1", " archiveId set");
|
||||
TEST_RESULT_PTR(infoArchivePg(info), info->infoPg, " infoPg set");
|
||||
TEST_RESULT_STR(strPtr(infoArchiveCipherPass(info)),
|
||||
"zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO", " cipher sub set");
|
||||
TEST_RESULT_INT(infoPgDataTotal(info->infoPg), 1, " history set");
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
InfoPgData infoPgData = {0};
|
||||
TEST_RESULT_VOID(infoArchivePgSet(info, PG_VERSION_94, 6569239123849665679), "add another infoPg");
|
||||
TEST_RESULT_INT(infoPgDataTotal(info->infoPg), 2, " history incremented");
|
||||
@@ -116,19 +88,13 @@ testRun(void)
|
||||
TEST_RESULT_INT(infoPgData.version, PG_VERSION_94, " version set");
|
||||
TEST_RESULT_INT(infoPgData.systemId, 6569239123849665679, " systemId set");
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_ASSIGN(info, infoArchiveNewInternal(), "infoArchiveNewInternal()");
|
||||
TEST_RESULT_PTR(infoArchivePg(info), NULL, " infoPg not set");
|
||||
|
||||
// Free
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_RESULT_VOID(infoArchiveFree(info), "infoArchiveFree() - free archive info");
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("infoArchiveIdHistoryMatch()"))
|
||||
{
|
||||
content = strNew
|
||||
// infoArchiveIdHistoryMatch()
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
contentLoad = harnessInfoChecksumZ
|
||||
(
|
||||
"[db]\n"
|
||||
"db-id=2\n"
|
||||
@@ -140,11 +106,7 @@ testRun(void)
|
||||
"2={\"db-id\":6626363367545678089,\"db-version\":\"9.5\"}\n"
|
||||
);
|
||||
|
||||
TEST_RESULT_VOID(
|
||||
storagePutNP(
|
||||
storageNewWriteNP(storageLocalWrite(), fileName), harnessInfoChecksum(content)), "put archive info to file");
|
||||
|
||||
TEST_ASSIGN(info, infoArchiveNewLoad(storageLocal(), fileName, cipherTypeNone, NULL), "new archive info");
|
||||
TEST_ASSIGN(info, infoArchiveNewLoad(ioBufferReadNew(contentLoad)), "new archive info");
|
||||
TEST_RESULT_STR(strPtr(infoArchiveIdHistoryMatch(info, 2, 90500, 6626363367545678089)), "9.5-2", " full match found");
|
||||
|
||||
TEST_RESULT_STR(strPtr(infoArchiveIdHistoryMatch(info, 2, 90400, 6625592122879095702)), "9.4-1", " partial match found");
|
||||
@@ -155,4 +117,30 @@ testRun(void)
|
||||
TEST_ERROR(infoArchiveIdHistoryMatch(info, 2, 90400, 6626363367545678089), ArchiveMismatchError,
|
||||
"unable to retrieve the archive id for database version '9.4' and system-id '6626363367545678089'");
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("infoArchiveLoadFile() and infoArchiveSaveFile()"))
|
||||
{
|
||||
TEST_ERROR_FMT(
|
||||
infoArchiveLoadFile(storageTest, STRDEF(INFO_ARCHIVE_FILE), cipherTypeNone, NULL), FileMissingError,
|
||||
"unable to load info file '%s/archive.info' or '%s/archive.info.copy':\n"
|
||||
"FileMissingError: unable to open missing file '%s/archive.info' for read\n"
|
||||
"FileMissingError: unable to open missing file '%s/archive.info.copy' for read\n"
|
||||
"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.",
|
||||
testPath(), testPath(), testPath(), testPath());
|
||||
|
||||
InfoArchive *infoArchive = infoArchiveNew(PG_VERSION_10, 6569239123849665999, NULL);
|
||||
TEST_RESULT_VOID(
|
||||
infoArchiveSaveFile(infoArchive, storageTest, STRDEF(INFO_ARCHIVE_FILE), cipherTypeNone, NULL), "save archive info");
|
||||
|
||||
TEST_ASSIGN(infoArchive, infoArchiveLoadFile(storageTest, STRDEF(INFO_ARCHIVE_FILE), cipherTypeNone, NULL), "load main");
|
||||
TEST_RESULT_UINT(infoPgDataCurrent(infoArchive->infoPg).systemId, 6569239123849665999, " check file loaded");
|
||||
|
||||
storageRemoveP(storageTest, STRDEF(INFO_ARCHIVE_FILE), .errorOnMissing = true);
|
||||
TEST_ASSIGN(infoArchive, infoArchiveLoadFile(storageTest, STRDEF(INFO_ARCHIVE_FILE), cipherTypeNone, NULL), "load copy");
|
||||
TEST_RESULT_UINT(infoPgDataCurrent(infoArchive->infoPg).systemId, 6569239123849665999, " check file loaded");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
/***********************************************************************************************************************************
|
||||
Test Backup Info Handler
|
||||
***********************************************************************************************************************************/
|
||||
#include "storage/storage.intern.h"
|
||||
#include "command/backup/common.h"
|
||||
#include "common/io/bufferRead.h"
|
||||
#include "common/io/bufferWrite.h"
|
||||
#include "storage/posix/storage.h"
|
||||
|
||||
#include "common/harnessInfo.h"
|
||||
#include "command/backup/common.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Test Run
|
||||
@@ -12,32 +14,16 @@ Test Run
|
||||
void
|
||||
testRun(void)
|
||||
{
|
||||
// Initialize test variables
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
String *content = NULL;
|
||||
String *fileName = strNewFmt("%s/test.ini", testPath());
|
||||
String *fileName2 = strNewFmt("%s/test2.ini", testPath());
|
||||
InfoBackup *infoBackup = NULL;
|
||||
// Create default storage object for testing
|
||||
Storage *storageTest = storagePosixNew(
|
||||
strNew(testPath()), STORAGE_MODE_FILE_DEFAULT, STORAGE_MODE_PATH_DEFAULT, true, NULL);
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("infoBackupNew(), infoBackupNewLoad(), infoBackupDataTotal(), infoBackupPg(), infoBackupCipherPass(), "
|
||||
"infoBackupFree()"))
|
||||
if (testBegin("InfoBackup"))
|
||||
{
|
||||
// File missing
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_ERROR_FMT(
|
||||
infoBackupNewLoad(storageLocal(), fileName, cipherTypeNone, NULL), FileMissingError,
|
||||
"unable to load info file '%s/test.ini' or '%s/test.ini.copy':\n"
|
||||
"FileMissingError: " STORAGE_ERROR_READ_MISSING "\n"
|
||||
"FileMissingError: " STORAGE_ERROR_READ_MISSING "\n"
|
||||
"HINT: backup.info cannot be opened and is required to perform a backup.\n"
|
||||
"HINT: has a stanza-create been performed?",
|
||||
testPath(), testPath(), strPtr(strNewFmt("%s/test.ini", testPath())),
|
||||
strPtr(strNewFmt("%s/test.ini.copy", testPath())));
|
||||
|
||||
// File exists, no backup:current section
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
content = strNew
|
||||
// File with section to ignore
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
const Buffer *contentLoad = harnessInfoChecksumZ
|
||||
(
|
||||
"[db]\n"
|
||||
"db-catalog-version=201409291\n"
|
||||
@@ -46,53 +32,59 @@ testRun(void)
|
||||
"db-system-id=6569239123849665679\n"
|
||||
"db-version=\"9.4\"\n"
|
||||
"\n"
|
||||
"[ignore-section]\n"
|
||||
"key1=value1\n"
|
||||
"\n"
|
||||
"[db:history]\n"
|
||||
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6569239123849665679,"
|
||||
"\"db-version\":\"9.4\"}\n"
|
||||
);
|
||||
|
||||
TEST_RESULT_VOID(
|
||||
storagePutNP(
|
||||
storageNewWriteNP(storageLocalWrite(), fileName), harnessInfoChecksum(content)), "put backup info to file");
|
||||
// Load to make sure ignore-section is ignored
|
||||
InfoBackup *infoBackup;
|
||||
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(contentLoad)), " new backup info");
|
||||
|
||||
// Save to verify with new created info backup
|
||||
Buffer *contentSave = bufNew(0);
|
||||
|
||||
TEST_RESULT_VOID(infoBackupSave(infoBackup, ioBufferWriteNew(contentSave)), "info backup save");
|
||||
|
||||
// Create new info backup
|
||||
Buffer *contentCompare = bufNew(0);
|
||||
|
||||
TEST_ASSIGN(
|
||||
infoBackup, infoBackupNew(PG_VERSION_94, 6569239123849665679, 942, 201409291, cipherTypeNone, NULL),
|
||||
infoBackup, infoBackupNew(PG_VERSION_94, 6569239123849665679, 942, 201409291, NULL),
|
||||
"infoBackupNew() - no cipher sub");
|
||||
TEST_RESULT_VOID(
|
||||
infoBackupSave(infoBackup, storageLocalWrite(), fileName2, cipherTypeNone, NULL), " save backup info from new");
|
||||
TEST_RESULT_BOOL(
|
||||
bufEq(
|
||||
storageGetNP(storageNewReadNP(storageLocal(), fileName)),
|
||||
storageGetNP(storageNewReadNP(storageLocal(), fileName2))),
|
||||
true, " files are equal");
|
||||
TEST_RESULT_VOID(infoBackupSave(infoBackup, ioBufferWriteNew(contentCompare)), " save backup info from new");
|
||||
TEST_RESULT_STR(strPtr(strNewBuf(contentCompare)), strPtr(strNewBuf(contentSave)), " check save");
|
||||
|
||||
TEST_ASSIGN(infoBackup, infoBackupNewLoad(storageLocal(), fileName2, cipherTypeNone, NULL), "load backup info");
|
||||
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(contentCompare)), "load backup info");
|
||||
TEST_RESULT_PTR(infoBackupPg(infoBackup), infoBackup->infoPg, " infoPg set");
|
||||
TEST_RESULT_PTR(infoBackupCipherPass(infoBackup), NULL, " cipher sub not set");
|
||||
TEST_RESULT_PTR(infoBackup->backup, NULL, " backupCurrent NULL");
|
||||
TEST_RESULT_INT(infoBackupDataTotal(infoBackup), 0, " infoBackupDataTotal returns 0");
|
||||
|
||||
// Remove both files and recreate from scratch with cipher
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
storageRemoveP(storageLocalWrite(), fileName, .errorOnMissing = true);
|
||||
storageRemoveP(storageLocalWrite(), fileName2, .errorOnMissing = true);
|
||||
|
||||
// Check cipher pass
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_ASSIGN(
|
||||
infoBackup, infoBackupNew(PG_VERSION_10, 6569239123849665999, 1002, 201707211, cipherTypeAes256Cbc,
|
||||
infoBackup,
|
||||
infoBackupNew(
|
||||
PG_VERSION_10, 6569239123849665999, 1002, 201707211,
|
||||
strNew("zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO")),
|
||||
"infoBackupNew() - cipher sub");
|
||||
TEST_RESULT_VOID(
|
||||
infoBackupSave(infoBackup, storageLocalWrite(), fileName, cipherTypeAes256Cbc, strNew("123xyz")), " save new encrypted");
|
||||
|
||||
contentSave = bufNew(0);
|
||||
|
||||
TEST_RESULT_VOID(infoBackupSave(infoBackup, ioBufferWriteNew(contentSave)), " save new with cipher sub");
|
||||
|
||||
infoBackup = NULL;
|
||||
TEST_ASSIGN(infoBackup, infoBackupNewLoad(storageLocal(), fileName, cipherTypeAes256Cbc, strNew("123xyz")),
|
||||
" load encrypted backup info");
|
||||
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(contentSave)), " load backup info with cipher sub");
|
||||
TEST_RESULT_PTR(infoBackupPg(infoBackup), infoBackup->infoPg, " infoPg set");
|
||||
TEST_RESULT_STR(strPtr(infoBackupCipherPass(infoBackup)),
|
||||
"zWa/6Xtp-IVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO", " cipher sub set");
|
||||
TEST_RESULT_INT(infoPgDataTotal(infoBackup->infoPg), 1, " history set");
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// Add pg info
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
InfoPgData infoPgData = {0};
|
||||
TEST_RESULT_VOID(infoBackupPgSet(infoBackup, PG_VERSION_94, 6569239123849665679, 12345, 54321), "add another infoPg");
|
||||
TEST_RESULT_INT(infoPgDataTotal(infoBackup->infoPg), 2, " history incremented");
|
||||
@@ -102,22 +94,13 @@ testRun(void)
|
||||
TEST_RESULT_INT(infoPgData.controlVersion, 12345, " catalog set");
|
||||
TEST_RESULT_INT(infoPgData.catalogVersion, 54321, " catalog set");
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_ASSIGN(infoBackup, infoBackupNewInternal(), "infoBackupNewInternal()");
|
||||
TEST_RESULT_PTR(infoBackupPg(infoBackup), NULL, " infoPg not set");
|
||||
|
||||
// Free
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_RESULT_VOID(infoBackupFree(infoBackup), "infoBackupFree() - free backup info");
|
||||
}
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin(
|
||||
"infoBackupData(), infoBackupDataTotal(), infoBackupDataToLog(), infoBackupDataLabelList(), infoBackupDataDelete()"))
|
||||
{
|
||||
// File exists, backup:current section exists
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
content = strNew
|
||||
(
|
||||
|
||||
// backup:current section exists
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
contentLoad = harnessInfoChecksumZ(
|
||||
"[backup:current]\n"
|
||||
"20161219-212741F={\"backrest-format\":5,\"backrest-version\":\"2.04\","
|
||||
"\"backup-archive-start\":\"00000007000000000000001C\",\"backup-archive-stop\":\"00000007000000000000001C\","
|
||||
@@ -151,21 +134,9 @@ testRun(void)
|
||||
"\n"
|
||||
"[db:history]\n"
|
||||
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6569239123849665679,"
|
||||
"\"db-version\":\"9.4\"}\n"
|
||||
);
|
||||
"\"db-version\":\"9.4\"}\n");
|
||||
|
||||
TEST_RESULT_VOID(
|
||||
storagePutNP(
|
||||
storageNewWriteNP(storageLocalWrite(), fileName), harnessInfoChecksum(content)), "put backup info current to file");
|
||||
TEST_ASSIGN(infoBackup, infoBackupNewLoad(storageLocal(), fileName, cipherTypeNone, NULL), " new backup info");
|
||||
|
||||
// Save the file and verify it
|
||||
TEST_RESULT_VOID(infoBackupSave(infoBackup, storageLocalWrite(), fileName2, cipherTypeNone, NULL), "save file");
|
||||
TEST_RESULT_BOOL(
|
||||
bufEq(
|
||||
storageGetNP(storageNewReadNP(storageLocal(), fileName)),
|
||||
storageGetNP(storageNewReadNP(storageLocal(), fileName2))),
|
||||
true, "files are equal");
|
||||
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(contentLoad)), " new backup info");
|
||||
|
||||
TEST_RESULT_INT(infoBackupDataTotal(infoBackup), 3, " backup list contains backups");
|
||||
|
||||
@@ -216,15 +187,23 @@ testRun(void)
|
||||
TEST_RESULT_BOOL(backupData.optionHardlink, false, " option hardlink");
|
||||
TEST_RESULT_BOOL(backupData.optionOnline, true, " option online");
|
||||
|
||||
// Save info and verify
|
||||
contentSave = bufNew(0);
|
||||
|
||||
TEST_RESULT_VOID(infoBackupSave(infoBackup, ioBufferWriteNew(contentSave)), "info backup save");
|
||||
TEST_RESULT_STR(strPtr(strNewBuf(contentSave)), strPtr(strNewBuf(contentLoad)), " check save");
|
||||
|
||||
// infoBackupDataLabelList and infoBackupDataDelete
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_RESULT_STR(
|
||||
strPtr(strLstJoin(strLstSort(infoBackupDataLabelList(infoBackup, NULL), sortOrderAsc), ", ")),
|
||||
"20161219-212741F, 20161219-212741F_20161219-212803D, 20161219-212741F_20161219-212918I", "infoBackupDataLabelList without expression");
|
||||
"20161219-212741F, 20161219-212741F_20161219-212803D, 20161219-212741F_20161219-212918I",
|
||||
"infoBackupDataLabelList without expression");
|
||||
TEST_RESULT_STR(
|
||||
strPtr(strLstJoin(strLstSort(infoBackupDataLabelList(
|
||||
infoBackup, backupRegExpP(.full=true, .differential=true, .incremental=true)), sortOrderAsc), ", ")),
|
||||
"20161219-212741F, 20161219-212741F_20161219-212803D, 20161219-212741F_20161219-212918I", "infoBackupDataLabelList with expression");
|
||||
"20161219-212741F, 20161219-212741F_20161219-212803D, 20161219-212741F_20161219-212918I",
|
||||
"infoBackupDataLabelList with expression");
|
||||
TEST_RESULT_STR(
|
||||
strPtr(strLstJoin(infoBackupDataLabelList(infoBackup, backupRegExpP(.full=true)), ", ")),
|
||||
"20161219-212741F", " full=true");
|
||||
@@ -245,8 +224,32 @@ testRun(void)
|
||||
TEST_RESULT_UINT(strLstSize(infoBackupDataLabelList(infoBackup, NULL)), 0, " no backups remain");
|
||||
|
||||
// infoBackupDataToLog
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_RESULT_STR(
|
||||
strPtr(infoBackupDataToLog(&backupData)), "{label: 20161219-212741F_20161219-212918I, pgId: 1}", "check log format");
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("infoBackupLoadFile() and infoBackupSaveFile()"))
|
||||
{
|
||||
TEST_ERROR_FMT(
|
||||
infoBackupLoadFile(storageTest, STRDEF(INFO_BACKUP_FILE), cipherTypeNone, NULL), FileMissingError,
|
||||
"unable to load info file '%s/backup.info' or '%s/backup.info.copy':\n"
|
||||
"FileMissingError: unable to open missing file '%s/backup.info' for read\n"
|
||||
"FileMissingError: unable to open missing file '%s/backup.info.copy' for read\n"
|
||||
"HINT: backup.info cannot be opened and is required to perform a backup.\n"
|
||||
"HINT: has a stanza-create been performed?",
|
||||
testPath(), testPath(), testPath(), testPath());
|
||||
|
||||
InfoBackup *infoBackup = infoBackupNew(PG_VERSION_10, 6569239123849665999, 1002, 201707211, NULL);
|
||||
TEST_RESULT_VOID(
|
||||
infoBackupSaveFile(infoBackup, storageTest, STRDEF(INFO_BACKUP_FILE), cipherTypeNone, NULL), "save backup info");
|
||||
|
||||
TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, STRDEF(INFO_BACKUP_FILE), cipherTypeNone, NULL), "load main");
|
||||
TEST_RESULT_UINT(infoPgDataCurrent(infoBackup->infoPg).systemId, 6569239123849665999, " check file loaded");
|
||||
|
||||
storageRemoveP(storageTest, STRDEF(INFO_BACKUP_FILE), .errorOnMissing = true);
|
||||
TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, STRDEF(INFO_BACKUP_FILE), cipherTypeNone, NULL), "load copy");
|
||||
TEST_RESULT_UINT(infoPgDataCurrent(infoBackup->infoPg).systemId, 6569239123849665999, " check file loaded");
|
||||
}
|
||||
}
|
||||
|
||||
+119
-164
@@ -1,8 +1,29 @@
|
||||
/***********************************************************************************************************************************
|
||||
Test PostgreSQL Info Handler
|
||||
***********************************************************************************************************************************/
|
||||
#include "common/io/bufferRead.h"
|
||||
#include "common/io/bufferWrite.h"
|
||||
|
||||
#include "common/harnessInfo.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Test save callback
|
||||
***********************************************************************************************************************************/
|
||||
static void
|
||||
testInfoBackupSaveCallback(void *data, const String *sectionNext, InfoSave *infoSaveData)
|
||||
{
|
||||
(void)data;
|
||||
|
||||
if (infoSaveSection(infoSaveData, STRDEF("backup:current"), sectionNext))
|
||||
infoSaveValue(infoSaveData, STRDEF("backup:current"), STRDEF("20161219-212741F"), STRDEF("{}"));
|
||||
|
||||
if (infoSaveSection(infoSaveData, STRDEF("db:backup"), sectionNext))
|
||||
infoSaveValue(infoSaveData, STRDEF("db:backup"), STRDEF("key"), STRDEF("value"));
|
||||
|
||||
if (infoSaveSection(infoSaveData, STRDEF("later"), sectionNext))
|
||||
infoSaveValue(infoSaveData, STRDEF("later"), STRDEF("key"), STRDEF("value"));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Test Run
|
||||
***********************************************************************************************************************************/
|
||||
@@ -14,19 +35,19 @@ testRun(void)
|
||||
{
|
||||
InfoPg *infoPg = NULL;
|
||||
|
||||
TEST_ASSIGN(infoPg, infoPgNew(cipherTypeNone, NULL), "infoPgNew(cipherTypeNone, NULL)");
|
||||
TEST_ASSIGN(infoPg, infoPgNew(infoPgBackup, NULL), "infoPgNew(cipherTypeNone, NULL)");
|
||||
TEST_RESULT_INT(infoPgDataTotal(infoPg), 0, " 0 history");
|
||||
TEST_RESULT_STR(strPtr(infoCipherPass(infoPgInfo(infoPg))), NULL, " cipherPass NULL");
|
||||
TEST_RESULT_INT(infoPgDataCurrentId(infoPg), 0, " 0 historyCurrent");
|
||||
|
||||
TEST_ASSIGN(infoPg, infoPgNew(cipherTypeAes256Cbc, strNew("123xyz")), "infoPgNew(cipherTypeAes256Cbc, 123xyz)");
|
||||
TEST_ASSIGN(infoPg, infoPgNew(infoPgArchive, strNew("123xyz")), "infoPgNew(cipherTypeAes256Cbc, 123xyz)");
|
||||
TEST_RESULT_INT(infoPgDataTotal(infoPg), 0, " 0 history");
|
||||
TEST_RESULT_STR(strPtr(infoCipherPass(infoPgInfo(infoPg))), "123xyz", " cipherPass set");
|
||||
TEST_RESULT_INT(infoPgDataCurrentId(infoPg), 0, " 0 historyCurrent");
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_ASSIGN(
|
||||
infoPg, infoPgSet(infoPgNew(cipherTypeNone, NULL), infoPgArchive, PG_VERSION_94, 6569239123849665679, 0, 0),
|
||||
infoPg, infoPgSet(infoPgNew(infoPgArchive, NULL), infoPgArchive, PG_VERSION_94, 6569239123849665679, 0, 0),
|
||||
"infoPgSet - infoPgArchive");
|
||||
TEST_RESULT_INT(infoPgDataTotal(infoPg), 1, " 1 history");
|
||||
TEST_RESULT_INT(infoPgDataCurrentId(infoPg), 0, " 0 historyCurrent");
|
||||
@@ -52,7 +73,7 @@ testRun(void)
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_ASSIGN(
|
||||
infoPg, infoPgSet(infoPgNew(cipherTypeAes256Cbc, strNew("123xyz")), infoPgBackup, PG_VERSION_94, 6569239123849665679,
|
||||
infoPg, infoPgSet(infoPgNew(infoPgBackup, strNew("123xyz")), infoPgBackup, PG_VERSION_94, 6569239123849665679,
|
||||
201409291, 942), "infoPgSet - infoPgBackup");
|
||||
TEST_RESULT_INT(infoPgDataTotal(infoPg), 1, " 1 history");
|
||||
TEST_RESULT_INT(infoPgDataCurrentId(infoPg), 0, " 0 historyCurrent");
|
||||
@@ -64,209 +85,143 @@ testRun(void)
|
||||
TEST_RESULT_INT(pgData.controlVersion, 201409291, " control-version set");
|
||||
TEST_RESULT_STR(strPtr(infoCipherPass(infoPgInfo(infoPg))), "123xyz", " cipherPass set");
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_ASSIGN(
|
||||
infoPg, infoPgSet(infoPgNew(cipherTypeNone, NULL), infoPgManifest, PG_VERSION_95, 6569239123849665699,
|
||||
201510051, 950), "infoPgSet - infoPgManifest");
|
||||
TEST_RESULT_INT(infoPgDataTotal(infoPg), 1, " 1 history");
|
||||
TEST_RESULT_INT(infoPgDataCurrentId(infoPg), 0, " 0 historyCurrent");
|
||||
pgData = infoPgData(infoPg, infoPgDataCurrentId(infoPg));
|
||||
TEST_RESULT_INT(pgData.id, 1, " id set");
|
||||
TEST_RESULT_INT(pgData.systemId, 6569239123849665699, " system-id set");
|
||||
TEST_RESULT_INT(pgData.version, PG_VERSION_95, " version set");
|
||||
TEST_RESULT_INT(pgData.catalogVersion, 950, " catalog-version set");
|
||||
TEST_RESULT_INT(pgData.controlVersion, 201510051, " control-version set");
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_ASSIGN(infoPg, infoPgNewInternal(), "infoPgNewInternal()");
|
||||
TEST_RESULT_PTR(infoPgInfo(infoPg), NULL, " info not set");
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_ERROR(
|
||||
infoPgSet(infoPgNew(cipherTypeNone, NULL), 1000, PG_VERSION_94, 6569239123849665679, 201409291, 942),
|
||||
infoPgSet(infoPgNew(infoPgBackup, NULL), 1000, PG_VERSION_94, 6569239123849665679, 201409291, 942),
|
||||
AssertError, "invalid InfoPg type 1000");
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("infoPgNewLoad(), infoPgFree(), infoPgDataCurrent(), infoPgDataToLog(), infoPgAdd(), infoPgIni(), infoPgSave()"))
|
||||
if (testBegin("infoPgNewLoad(), infoPgFree(), infoPgDataCurrent(), infoPgDataToLog(), infoPgAdd(), infoPgSave()"))
|
||||
{
|
||||
String *content = NULL;
|
||||
String *fileName = strNewFmt("%s/test.ini", testPath());
|
||||
String *fileName2 = strNewFmt("%s/test2.ini", testPath());
|
||||
String *fileName3 = strNewFmt("%s/test3.ini", testPath());
|
||||
|
||||
// Archive info
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
content = strNew
|
||||
(
|
||||
const Buffer *contentLoad = harnessInfoChecksumZ(
|
||||
"[backup:current]\n"
|
||||
"20161219-212741F={}\n"
|
||||
"\n"
|
||||
"[db]\n"
|
||||
"db-id=1\n"
|
||||
"db-system-id=6569239123849665679\n"
|
||||
"db-version=\"9.4\"\n"
|
||||
"\n"
|
||||
"[db:backup]\n"
|
||||
"key=value\n"
|
||||
"\n"
|
||||
"[db:history]\n"
|
||||
"1={\"db-id\":6569239123849665679,\"db-version\":\"9.4\"}\n"
|
||||
);
|
||||
|
||||
TEST_RESULT_VOID(
|
||||
storagePutNP(storageNewWriteNP(storageLocalWrite(), fileName), harnessInfoChecksum(content)), "put info to file");
|
||||
"\n"
|
||||
"[later]\n"
|
||||
"key=value\n");
|
||||
|
||||
String *callbackContent = strNew("");
|
||||
InfoPg *infoPg = NULL;
|
||||
Ini *ini = NULL;
|
||||
|
||||
TEST_ASSIGN(
|
||||
infoPg, infoPgNewLoad(storageLocal(), fileName, infoPgArchive, cipherTypeNone, NULL, &ini), "load file");
|
||||
TEST_RESULT_STR(strPtr(iniGet(ini, strNew("db"), strNew("db-id"))), "1", " check ini");
|
||||
|
||||
// Save the file and verify it
|
||||
ini = iniNew();
|
||||
TEST_RESULT_VOID(
|
||||
infoPgSave(infoPg, ini, storageLocalWrite(), fileName3, infoPgArchive, cipherTypeNone, NULL), "infoPgSave - archive");
|
||||
TEST_RESULT_BOOL(
|
||||
bufEq(
|
||||
storageGetNP(storageNewReadNP(storageLocal(), fileName)),
|
||||
storageGetNP(storageNewReadNP(storageLocal(), fileName3))),
|
||||
true, " saved files are equal");
|
||||
|
||||
infoPg, infoPgNewLoad(ioBufferReadNew(contentLoad), infoPgArchive, harnessInfoLoadNewCallback, callbackContent),
|
||||
"load file");
|
||||
TEST_RESULT_STR(
|
||||
strPtr(callbackContent),
|
||||
"[backup:current] 20161219-212741F={}\n"
|
||||
"[db:backup] key=value\n"
|
||||
"[later] key=value\n",
|
||||
" check callback content");
|
||||
TEST_RESULT_INT(lstSize(infoPg->history), 1, " history record added");
|
||||
|
||||
InfoPgData infoPgData = infoPgDataCurrent(infoPg);
|
||||
TEST_RESULT_INT(infoPgData.id, 1, " id set");
|
||||
TEST_RESULT_INT(infoPgData.version, PG_VERSION_94, " version set");
|
||||
TEST_RESULT_INT(infoPgData.systemId, 6569239123849665679, " system-id set");
|
||||
TEST_RESULT_INT(infoPgData.catalogVersion, 0, " catalog-version not set");
|
||||
TEST_RESULT_INT(infoPgData.controlVersion, 0, " control-version not set");
|
||||
InfoPgData pgData = infoPgDataCurrent(infoPg);
|
||||
TEST_RESULT_INT(pgData.id, 1, " id set");
|
||||
TEST_RESULT_INT(pgData.version, PG_VERSION_94, " version set");
|
||||
TEST_RESULT_INT(pgData.systemId, 6569239123849665679, " system-id set");
|
||||
TEST_RESULT_INT(pgData.catalogVersion, 0, " catalog-version not set");
|
||||
TEST_RESULT_INT(pgData.controlVersion, 0, " control-version not set");
|
||||
TEST_RESULT_INT(infoPgDataTotal(infoPg), 1, " check pg data total");
|
||||
TEST_RESULT_STR(strPtr(infoPgArchiveId(infoPg, 0)), "9.4-1", " check pg archive id");
|
||||
TEST_RESULT_PTR(infoPgCipherPass(infoPg), NULL, " no cipher passphrase");
|
||||
|
||||
Buffer *contentSave = bufNew(0);
|
||||
|
||||
TEST_RESULT_VOID(infoPgSave(infoPg, ioBufferWriteNew(contentSave), testInfoBackupSaveCallback, (void *)1), "info save");
|
||||
TEST_RESULT_STR(strPtr(strNewBuf(contentSave)), strPtr(strNewBuf(contentLoad)), " check save");
|
||||
|
||||
// Backup info
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
content = strNew
|
||||
(
|
||||
"[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"
|
||||
"\n"
|
||||
"[db:history]\n"
|
||||
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6569239123849665679,"
|
||||
"\"db-version\":\"9.4\"}\n"
|
||||
);
|
||||
|
||||
TEST_RESULT_VOID(
|
||||
storagePutNP(storageNewWriteNP(storageLocalWrite(), fileName), harnessInfoChecksum(content)), "put info to file");
|
||||
TEST_ASSIGN(
|
||||
infoPg, infoPgNewLoad(storageLocal(), fileName, infoPgBackup, cipherTypeNone, NULL, NULL), "load file");
|
||||
|
||||
// Save the file and verify it
|
||||
ini = iniNew();
|
||||
TEST_RESULT_VOID(
|
||||
infoPgSave(infoPg, ini, storageLocalWrite(), fileName3, infoPgBackup, cipherTypeNone, NULL), "infoPgSave - backup");
|
||||
TEST_RESULT_BOOL(
|
||||
bufEq(
|
||||
storageGetNP(storageNewReadNP(storageLocal(), fileName)),
|
||||
storageGetNP(storageNewReadNP(storageLocal(), fileName3))),
|
||||
true, " saved files are equal");
|
||||
TEST_RESULT_INT(lstSize(infoPg->history), 1, " history record added");
|
||||
|
||||
infoPgData = infoPgDataCurrent(infoPg);
|
||||
TEST_RESULT_INT(infoPgData.id, 1, " id set");
|
||||
TEST_RESULT_INT(infoPgData.version, PG_VERSION_94, " version set");
|
||||
TEST_RESULT_INT(infoPgData.systemId, 6569239123849665679, " system-id set");
|
||||
TEST_RESULT_INT(infoPgData.catalogVersion, 201409291, " catalog-version set");
|
||||
TEST_RESULT_INT(infoPgData.controlVersion, 942, " control-version set");
|
||||
|
||||
// Manifest info
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
content = strNew
|
||||
(
|
||||
"[db]\n"
|
||||
"db-catalog-version=201510051\n"
|
||||
"db-control-version=942\n"
|
||||
"db-id=2\n"
|
||||
"db-system-id=6365925855999999999\n"
|
||||
#define CONTENT_DB \
|
||||
"[db]\n" \
|
||||
"db-catalog-version=201510051\n" \
|
||||
"db-control-version=942\n" \
|
||||
"db-id=2\n" \
|
||||
"db-system-id=6365925855999999999\n" \
|
||||
"db-version=\"9.5\"\n"
|
||||
"\n"
|
||||
"[db:history]\n"
|
||||
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6569239123849665679,"
|
||||
"\"db-version\":\"9.4\"}\n"
|
||||
"2={\"db-catalog-version\":201510051,\"db-control-version\":942,\"db-system-id\":6365925855999999999,"
|
||||
|
||||
#define CONTENT_DB_HISTORY \
|
||||
"\n" \
|
||||
"[db:history]\n" \
|
||||
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6569239123849665679," \
|
||||
"\"db-version\":\"9.4\"}\n" \
|
||||
"2={\"db-catalog-version\":201510051,\"db-control-version\":942,\"db-system-id\":6365925855999999999," \
|
||||
"\"db-version\":\"9.5\"}\n"
|
||||
);
|
||||
|
||||
// Put the file and load it
|
||||
TEST_RESULT_VOID(
|
||||
storagePutNP(storageNewWriteNP(storageLocalWrite(), fileName), harnessInfoChecksum(content)), "put info to file");
|
||||
TEST_ASSIGN(
|
||||
infoPg, infoPgNewLoad(storageLocal(), fileName, infoPgManifest, cipherTypeNone, NULL, NULL), "load file");
|
||||
contentLoad = harnessInfoChecksumZ(
|
||||
CONTENT_DB
|
||||
"\n"
|
||||
"[backup:current]\n"
|
||||
"20161219-212741F={}\n"
|
||||
CONTENT_DB_HISTORY);
|
||||
|
||||
// Save the file and verify it
|
||||
ini = iniNew();
|
||||
TEST_RESULT_VOID(
|
||||
infoPgSave(infoPg, ini, storageLocalWrite(), fileName2, infoPgManifest, cipherTypeNone, NULL), "infoPgSave - manifest");
|
||||
TEST_RESULT_BOOL(
|
||||
bufEq(
|
||||
storageGetNP(storageNewReadNP(storageLocal(), fileName)),
|
||||
storageGetNP(storageNewReadNP(storageLocal(), fileName2))),
|
||||
true, " saved files are equal");
|
||||
callbackContent = strNew("");
|
||||
|
||||
TEST_RESULT_INT(lstSize(infoPg->history), 2, "history record added");
|
||||
TEST_ASSIGN(infoPg, infoPgNewLoad(ioBufferReadNew(contentLoad), infoPgBackup, NULL, NULL), "load file");
|
||||
TEST_RESULT_STR(strPtr(callbackContent), "", " check callback content");
|
||||
|
||||
infoPgData = infoPgDataCurrent(infoPg);
|
||||
TEST_RESULT_INT(infoPgData.id, 2, " id set");
|
||||
TEST_RESULT_INT(infoPgData.version, PG_VERSION_95, " version set");
|
||||
TEST_RESULT_INT(infoPgData.systemId, 6365925855999999999, " system-id set");
|
||||
TEST_RESULT_INT(infoPgData.catalogVersion, 201510051, " catalog-version set");
|
||||
TEST_RESULT_INT(infoPgData.controlVersion, 942, " control-version set");
|
||||
TEST_RESULT_INT(infoPgDataTotal(infoPg), 2, " check pg data total");
|
||||
|
||||
pgData = infoPgDataCurrent(infoPg);
|
||||
TEST_RESULT_INT(pgData.id, 2, " id set");
|
||||
TEST_RESULT_INT(pgData.version, PG_VERSION_95, " version set");
|
||||
TEST_RESULT_INT(pgData.systemId, 6365925855999999999, " system-id set");
|
||||
TEST_RESULT_INT(pgData.catalogVersion, 201510051, " catalog-version set");
|
||||
TEST_RESULT_INT(pgData.controlVersion, 942, " control-version set");
|
||||
|
||||
pgData = infoPgData(infoPg, 1);
|
||||
TEST_RESULT_INT(pgData.id, 1, " id set");
|
||||
TEST_RESULT_INT(pgData.version, PG_VERSION_94, " version set");
|
||||
TEST_RESULT_INT(pgData.systemId, 6569239123849665679, " system-id set");
|
||||
TEST_RESULT_INT(pgData.catalogVersion, 201409291, " catalog-version set");
|
||||
TEST_RESULT_INT(pgData.controlVersion, 942, " control-version set");
|
||||
|
||||
contentSave = bufNew(0);
|
||||
|
||||
TEST_RESULT_VOID(infoPgSave(infoPg, ioBufferWriteNew(contentSave), NULL, NULL), "info save");
|
||||
TEST_RESULT_STR(
|
||||
strPtr(strNewBuf(contentSave)), strPtr(strNewBuf(harnessInfoChecksumZ(CONTENT_DB CONTENT_DB_HISTORY))),
|
||||
" check save");
|
||||
|
||||
// infoPgAdd
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
infoPgData.id = 3;
|
||||
infoPgData.version = PG_VERSION_96;
|
||||
infoPgData.systemId = 6399999999999999999;
|
||||
infoPgData.catalogVersion = 201608131;
|
||||
infoPgData.controlVersion = 960;
|
||||
TEST_RESULT_VOID(infoPgAdd(infoPg, &infoPgData), "infoPgAdd");
|
||||
pgData.id = 3;
|
||||
pgData.version = PG_VERSION_96;
|
||||
pgData.systemId = 6399999999999999999;
|
||||
pgData.catalogVersion = 201608131;
|
||||
pgData.controlVersion = 960;
|
||||
TEST_RESULT_VOID(infoPgAdd(infoPg, &pgData), "infoPgAdd");
|
||||
|
||||
InfoPgData infoPgDataTest = infoPgDataCurrent(infoPg);
|
||||
TEST_RESULT_INT(infoPgDataTest.id, 3, " id set");
|
||||
TEST_RESULT_INT(infoPgDataTest.version, PG_VERSION_96, " version set");
|
||||
TEST_RESULT_INT(infoPgDataTest.systemId, 6399999999999999999, " system-id set");
|
||||
TEST_RESULT_INT(infoPgDataTest.catalogVersion, 201608131, " catalog-version set");
|
||||
TEST_RESULT_INT(infoPgDataTest.controlVersion, 960, " control-version set");
|
||||
|
||||
// Errors
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_ERROR(infoPgNewLoad(storageLocal(), fileName, 10, cipherTypeNone, NULL, NULL), AssertError, "invalid InfoPg type 10");
|
||||
TEST_ERROR(
|
||||
infoPgNewLoad(storageLocal(), NULL, infoPgManifest, cipherTypeNone, NULL, NULL), AssertError,
|
||||
"assertion 'fileName != NULL' failed");
|
||||
|
||||
TEST_ERROR(infoPgDataCurrent(NULL), AssertError, "assertion 'this != NULL' failed");
|
||||
|
||||
TEST_ERROR(infoPgAdd(NULL, &infoPgData), AssertError, "assertion 'this != NULL' failed");
|
||||
TEST_ERROR(infoPgAdd(infoPg, NULL), AssertError, "assertion 'infoPgData != NULL' failed");
|
||||
TEST_ERROR(
|
||||
infoPgSave(infoPg, ini, storageLocalWrite(), fileName2, 10000, cipherTypeNone, NULL),
|
||||
AssertError, "invalid InfoPg type 10000");
|
||||
|
||||
// infoPgFree
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_RESULT_VOID(infoPgFree(infoPg), "infoPgFree() - free infoPg");
|
||||
InfoPgData pgDataTest = infoPgDataCurrent(infoPg);
|
||||
TEST_RESULT_INT(pgDataTest.id, 3, " id set");
|
||||
TEST_RESULT_INT(pgDataTest.version, PG_VERSION_96, " version set");
|
||||
TEST_RESULT_INT(pgDataTest.systemId, 6399999999999999999, " system-id set");
|
||||
TEST_RESULT_INT(pgDataTest.catalogVersion, 201608131, " catalog-version set");
|
||||
TEST_RESULT_INT(pgDataTest.controlVersion, 960, " control-version set");
|
||||
|
||||
// infoPgDataToLog
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
// test max values
|
||||
infoPgDataTest.id = (unsigned int)4294967295;
|
||||
infoPgDataTest.version = (unsigned int)4294967295;
|
||||
infoPgDataTest.systemId = 18446744073709551615U;
|
||||
infoPgDataTest.catalogVersion = (uint32_t)4294967295;
|
||||
infoPgDataTest.controlVersion = (uint32_t)4294967295;
|
||||
pgDataTest.id = (unsigned int)4294967295;
|
||||
pgDataTest.version = (unsigned int)4294967295;
|
||||
pgDataTest.systemId = 18446744073709551615U;
|
||||
pgDataTest.catalogVersion = (uint32_t)4294967295;
|
||||
pgDataTest.controlVersion = (uint32_t)4294967295;
|
||||
TEST_RESULT_STR(
|
||||
strPtr(infoPgDataToLog(&infoPgDataTest)),
|
||||
strPtr(infoPgDataToLog(&pgDataTest)),
|
||||
"{id: 4294967295, version: 4294967295, systemId: 18446744073709551615, catalogVersion: 4294967295, controlVersion:"
|
||||
" 4294967295}",
|
||||
" check max format");
|
||||
|
||||
+204
-259
@@ -1,302 +1,247 @@
|
||||
/***********************************************************************************************************************************
|
||||
Test Info Handler
|
||||
***********************************************************************************************************************************/
|
||||
#include "common/crypto/cipherBlock.h"
|
||||
#include "common/io/bufferRead.h"
|
||||
#include "common/io/bufferWrite.h"
|
||||
#include "storage/posix/storage.h"
|
||||
|
||||
#include "common/harnessInfo.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Test load callback
|
||||
***********************************************************************************************************************************/
|
||||
typedef struct TestInfoLoad
|
||||
{
|
||||
unsigned int test;
|
||||
} TestInfoLoad;
|
||||
|
||||
static bool
|
||||
testInfoLoadCallback(void *data, unsigned int try)
|
||||
{
|
||||
TestInfoLoad *testInfoLoad = (TestInfoLoad *)data;
|
||||
|
||||
if (testInfoLoad->test == 1)
|
||||
{
|
||||
if (try == 0)
|
||||
THROW(ChecksumError, "checksum error");
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
if (testInfoLoad->test == 2)
|
||||
{
|
||||
if (try < 2)
|
||||
THROW(FormatError, "format error");
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
if (testInfoLoad->test == 3)
|
||||
{
|
||||
if (try == 0)
|
||||
THROW(FileMissingError, "file missing error");
|
||||
else if (try == 1)
|
||||
THROW(ChecksumError, "checksum error\nHINT: have you checked the thing?");
|
||||
else if (try == 2)
|
||||
THROW(FormatError, "format error");
|
||||
else if (try == 3)
|
||||
THROW(FileMissingError, "file missing error");
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Test save callbacks
|
||||
***********************************************************************************************************************************/
|
||||
static void
|
||||
testInfoSaveCallback(void *data, const String *sectionNext, InfoSave *infoSaveData)
|
||||
{
|
||||
if (infoSaveSection(infoSaveData, STRDEF("c"), sectionNext))
|
||||
infoSaveValue(infoSaveData, STRDEF("c"), strNew("key"), (String *)data);
|
||||
|
||||
if (infoSaveSection(infoSaveData, STRDEF("d"), sectionNext))
|
||||
infoSaveValue(infoSaveData, STRDEF("d"), strNew("key"), (String *)data);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Test Run
|
||||
***********************************************************************************************************************************/
|
||||
void
|
||||
testRun(void)
|
||||
{
|
||||
// Create default storage object for testing
|
||||
Storage *storageTest = storagePosixNew(
|
||||
strNew(testPath()), STORAGE_MODE_FILE_DEFAULT, STORAGE_MODE_PATH_DEFAULT, true, NULL);
|
||||
|
||||
String *cipherPass = strNew("123xyz");
|
||||
String *fileName = strNewFmt("%s/test.ini", testPath());
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("infoNew() and infoNewInternal()"))
|
||||
{
|
||||
Info *info = NULL;
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("infoNew()"))
|
||||
{
|
||||
TEST_ASSIGN(info, infoNew(cipherTypeAes256Cbc, cipherPass), "infoNew(cipher)");
|
||||
TEST_RESULT_PTR(infoCipherPass(info), cipherPass, " cipherPass is set");
|
||||
TEST_ASSIGN(info, infoNew(strNew("123xyz")), "infoNew(cipher)");
|
||||
TEST_RESULT_STR(strPtr(infoCipherPass(info)), "123xyz", " cipherPass is set");
|
||||
|
||||
TEST_ASSIGN(info, infoNew(cipherTypeNone, NULL), "infoNew(NULL)");
|
||||
TEST_ASSIGN(info, infoNew(NULL), "infoNew(NULL)");
|
||||
TEST_RESULT_PTR(infoCipherPass(info), NULL, " cipherPass is NULL");
|
||||
|
||||
TEST_ERROR(
|
||||
infoNew(cipherTypeNone, strNew("")), AssertError,
|
||||
"assertion '!((cipherType == cipherTypeNone && cipherPassSub != NULL) || (cipherType != cipherTypeNone && "
|
||||
"(cipherPassSub == NULL || strSize(cipherPassSub) == 0)))' failed");
|
||||
TEST_ERROR(
|
||||
infoNew(cipherTypeAes256Cbc, strNew("")), AssertError,
|
||||
"assertion '!((cipherType == cipherTypeNone && cipherPassSub != NULL) || (cipherType != cipherTypeNone && "
|
||||
"(cipherPassSub == NULL || strSize(cipherPassSub) == 0)))' failed");
|
||||
TEST_ERROR(
|
||||
infoNew(cipherTypeAes256Cbc, NULL), AssertError,
|
||||
"assertion '!((cipherType == cipherTypeNone && cipherPassSub != NULL) || (cipherType != cipherTypeNone && "
|
||||
"(cipherPassSub == NULL || strSize(cipherPassSub) == 0)))' failed");
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("infoNewLoad(), infoFileName(), infoIni()"))
|
||||
if (testBegin("infoNewLoad() and infoSave()"))
|
||||
{
|
||||
// Initialize test variables
|
||||
// Format error
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
String *content = NULL;
|
||||
String *fileNameCopy = strNewFmt("%s/test.ini.copy", testPath());
|
||||
|
||||
content = strNew
|
||||
(
|
||||
const Buffer *contentLoad = BUFSTRDEF(
|
||||
"[backrest]\n"
|
||||
"backrest-checksum=\"1efa53e0611604ad7d833c5547eb60ff716e758c\"\n"
|
||||
"backrest-format=5\n"
|
||||
"backrest-version=\"2.04\"\n"
|
||||
"\n"
|
||||
"[db]\n"
|
||||
"db-id=1\n"
|
||||
"db-system-id=6569239123849665679\n"
|
||||
"db-version=\"9.4\"\n"
|
||||
"\n"
|
||||
"[db:history]\n"
|
||||
"1={\"db-id\":6569239123849665679,\"db-version\":\"9.4\"}\n"
|
||||
);
|
||||
"backrest-format=4\n");
|
||||
|
||||
// Info files missing and at least one is required
|
||||
String *callbackContent = strNew("");
|
||||
|
||||
TEST_ERROR(
|
||||
infoNewLoad(ioBufferReadNew(contentLoad), harnessInfoLoadNewCallback, callbackContent), FormatError,
|
||||
"expected format 5 but found 4");
|
||||
TEST_RESULT_STR(strPtr(callbackContent), "", " check callback content");
|
||||
|
||||
// Checksum not found
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_ERROR_FMT(
|
||||
infoNewLoad(storageLocal(), fileName, cipherTypeNone, NULL, NULL), FileMissingError,
|
||||
"unable to load info file '%s/test.ini' or '%s/test.ini.copy':\n"
|
||||
"FileMissingError: " STORAGE_ERROR_READ_MISSING "\n"
|
||||
"FileMissingError: " STORAGE_ERROR_READ_MISSING,
|
||||
testPath(), testPath(), strPtr(strNewFmt("%s/test.ini", testPath())),
|
||||
strPtr(strNewFmt("%s/test.ini.copy", testPath())));
|
||||
|
||||
// Only copy exists and one is required
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_RESULT_VOID(
|
||||
storagePutNP(storageNewWriteNP(storageLocalWrite(), fileNameCopy), BUFSTR(content)), "put info.copy to file");
|
||||
|
||||
TEST_ASSIGN(info, infoNewLoad(storageLocal(), fileName, cipherTypeNone, NULL, NULL), "load copy file");
|
||||
|
||||
TEST_RESULT_PTR(infoCipherPass(info), NULL, " cipherPass is not set");
|
||||
|
||||
// Remove the copy and store only the main info file and encrypt it. One is required.
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
StorageWrite *infoWrite = storageNewWriteNP(storageLocalWrite(), fileName);
|
||||
|
||||
ioFilterGroupAdd(
|
||||
ioWriteFilterGroup(storageWriteIo(infoWrite)), cipherBlockNew(cipherModeEncrypt, cipherTypeAes256Cbc,
|
||||
BUFSTRDEF("12345678"), NULL));
|
||||
|
||||
storageRemoveNP(storageLocalWrite(), fileNameCopy);
|
||||
storagePutNP(
|
||||
infoWrite,
|
||||
BUFSTRDEF(
|
||||
contentLoad = BUFSTRDEF(
|
||||
"[backrest]\n"
|
||||
"backrest-checksum=\"9d2f6dce339751e1a056187fad67d2834b3d4ab3\"\n"
|
||||
"backrest-format=5\n");
|
||||
|
||||
TEST_ERROR(
|
||||
infoNewLoad(ioBufferReadNew(contentLoad), harnessInfoLoadNewCallback, callbackContent), ChecksumError,
|
||||
"invalid checksum, actual 'a3765a8c2c1e5d35274a0b0ce118f4031faff0bd' but no checksum found");
|
||||
TEST_RESULT_STR(strPtr(callbackContent), "", " check callback content");
|
||||
|
||||
// Checksum invalid
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
contentLoad = BUFSTRDEF(
|
||||
"[backrest]\n"
|
||||
"backrest-checksum=\"BOGUS\"\n"
|
||||
"backrest-format=5\n"
|
||||
"backrest-version=\"2.04\"\n"
|
||||
"backrest-version=\"2.17\"\n");
|
||||
|
||||
TEST_ERROR(
|
||||
infoNewLoad(ioBufferReadNew(contentLoad), harnessInfoLoadNewCallback, callbackContent), ChecksumError,
|
||||
"invalid checksum, actual 'a9e578459485db14eb1093809a7964832be2779a' but expected 'BOGUS'");
|
||||
TEST_RESULT_STR(strPtr(callbackContent), "", " check callback content");
|
||||
|
||||
// Crypto expected
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
contentLoad = BUFSTRDEF(
|
||||
"[backrest]\n"
|
||||
"backrest-checksum=\"BOGUS\"\n"
|
||||
"backrest-format=5\n"
|
||||
"backrest-version=\"2.17\"\n");
|
||||
|
||||
IoRead *read = ioBufferReadNew(contentLoad);
|
||||
ioFilterGroupAdd(ioReadFilterGroup(read), cipherBlockNew(cipherModeDecrypt, cipherTypeAes256Cbc, BUFSTRDEF("X"), NULL));
|
||||
|
||||
TEST_ERROR(
|
||||
infoNewLoad(read, harnessInfoLoadNewCallback, callbackContent), CryptoError,
|
||||
"cipher header invalid\n"
|
||||
"HINT: is or was the repo encrypted?");
|
||||
TEST_RESULT_STR(strPtr(callbackContent), "", " check callback content");
|
||||
|
||||
// Base file with other content in cipher (this is to test that future additions don't break the code)
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
contentLoad = harnessInfoChecksumZ(
|
||||
"[cipher]\n"
|
||||
"cipher-other=1\n");
|
||||
|
||||
Info *info = NULL;
|
||||
callbackContent = strNew("");
|
||||
|
||||
TEST_ASSIGN(
|
||||
info, infoNewLoad(ioBufferReadNew(contentLoad), harnessInfoLoadNewCallback, callbackContent), "info with other cipher");
|
||||
TEST_RESULT_STR(strPtr(callbackContent), "", " check callback content");
|
||||
TEST_RESULT_PTR(infoCipherPass(info), NULL, " check cipher pass not set");
|
||||
|
||||
// Base file with content
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
contentLoad = harnessInfoChecksumZ(
|
||||
"[c]\n"
|
||||
"key=1\n"
|
||||
"\n"
|
||||
"[d]\n"
|
||||
"key=1\n");
|
||||
|
||||
callbackContent = strNew("");
|
||||
|
||||
TEST_ASSIGN(
|
||||
info, infoNewLoad(ioBufferReadNew(contentLoad), harnessInfoLoadNewCallback, callbackContent), "info with content");
|
||||
TEST_RESULT_STR(strPtr(callbackContent), "[c] key=1\n[d] key=1\n", " check callback content");
|
||||
TEST_RESULT_PTR(infoCipherPass(info), NULL, " check cipher pass not set");
|
||||
|
||||
Buffer *contentSave = bufNew(0);
|
||||
|
||||
TEST_RESULT_VOID(infoSave(info, ioBufferWriteNew(contentSave), testInfoSaveCallback, strNew("1")), "info save");
|
||||
TEST_RESULT_STR(strPtr(strNewBuf(contentSave)), strPtr(strNewBuf(contentLoad)), " check save");
|
||||
|
||||
// File with content and cipher
|
||||
// --------------------------------------------------------------------------------------------------------------------------
|
||||
contentLoad = harnessInfoChecksumZ(
|
||||
"[c]\n"
|
||||
"key=1\n"
|
||||
"\n"
|
||||
"[cipher]\n"
|
||||
"cipher-pass=\"ABCDEFGH\"\n"
|
||||
"cipher-pass=\"somepass\"\n"
|
||||
"\n"
|
||||
"[db]\n"
|
||||
"db-id=1\n"
|
||||
"db-system-id=6569239123849665679\n"
|
||||
"db-version=\"9.4\"\n"
|
||||
"\n"
|
||||
"[db:history]\n"
|
||||
"1={\"db-id\":6569239123849665679,\"db-version\":\"9.4\"}\n"));
|
||||
"[d]\n"
|
||||
"key=1\n");
|
||||
|
||||
// Only main info exists and is required
|
||||
Ini *ini = NULL;
|
||||
TEST_ASSIGN(info, infoNewLoad(storageLocal(), fileName, cipherTypeAes256Cbc, strNew("12345678"), &ini), "load file");
|
||||
callbackContent = strNew("");
|
||||
|
||||
TEST_RESULT_STR(strPtr(iniGet(ini, strNew("cipher"), strNew("cipher-pass"))), "\"ABCDEFGH\"", " check ini");
|
||||
TEST_RESULT_STR(strPtr(infoCipherPass(info)), "ABCDEFGH", " cipherPass is set");
|
||||
TEST_ASSIGN(
|
||||
info,
|
||||
infoNewLoad(ioBufferReadNew(contentLoad), harnessInfoLoadNewCallback, callbackContent), "info with content and cipher");
|
||||
TEST_RESULT_STR(strPtr(callbackContent), "[c] key=1\n[d] key=1\n", " check callback content");
|
||||
TEST_RESULT_STR(strPtr(infoCipherPass(info)), "somepass", " check cipher pass set");
|
||||
|
||||
// Invalid format
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
storageRemoveNP(storageLocalWrite(), fileName);
|
||||
contentSave = bufNew(0);
|
||||
|
||||
content = strNew
|
||||
(
|
||||
"[backrest]\n"
|
||||
"backrest-checksum=\"14617b089cb5c9b3224e739bb794e865b9bcdf4b\"\n"
|
||||
"backrest-format=4\n"
|
||||
"backrest-version=\"2.04\"\n"
|
||||
"\n"
|
||||
"[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"
|
||||
"\n"
|
||||
"[db:history]\n"
|
||||
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6569239123849665679,"
|
||||
"\"db-version\":\"9.4\"}\n"
|
||||
);
|
||||
|
||||
// Only main file exists but the backrest-format is invalid
|
||||
TEST_RESULT_VOID(
|
||||
storagePutNP(storageNewWriteNP(storageLocalWrite(), fileName), BUFSTR(content)), "put invalid br format to file");
|
||||
|
||||
TEST_ERROR_FMT(
|
||||
infoNewLoad(storageLocal(), fileName, cipherTypeNone, NULL, NULL), FormatError,
|
||||
"unable to load info file '%s/test.ini' or '%s/test.ini.copy':\n"
|
||||
"FormatError: invalid format in '%s/test.ini', expected 5 but found 4\n"
|
||||
"FileMissingError: " STORAGE_ERROR_READ_MISSING,
|
||||
testPath(), testPath(), testPath(), strPtr(strNewFmt("%s/test.ini.copy", testPath())));
|
||||
|
||||
content = strNew
|
||||
(
|
||||
"[backrest]\n"
|
||||
"backrest-checksum=\"14617b089cb5c9b3224e739bb794e865b9bcdf4b\"\n"
|
||||
"backrest-format=4\n"
|
||||
"backrest-version=\"2.05\"\n"
|
||||
"\n"
|
||||
"[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"
|
||||
"\n"
|
||||
"[db:history]\n"
|
||||
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6569239123849665679,"
|
||||
"\"db-version\":\"9.4\"}\n"
|
||||
);
|
||||
|
||||
TEST_RESULT_VOID(
|
||||
storagePutNP(
|
||||
storageNewWriteNP(storageLocalWrite(), fileNameCopy), BUFSTR(content)), "put invalid info to copy file");
|
||||
|
||||
TEST_ERROR(
|
||||
infoNewLoad(storageLocal(), fileName, cipherTypeNone, NULL, NULL), FileOpenError,
|
||||
strPtr(
|
||||
strNewFmt(
|
||||
"unable to load info file '%s/test.ini' or '%s/test.ini.copy':\n"
|
||||
"FormatError: invalid format in '%s/test.ini', expected 5 but found 4\n"
|
||||
"ChecksumError: invalid checksum in '%s/test.ini.copy', expected 'af92308095d6141bcda6b2df6d574f98d1115163'"
|
||||
" but found '14617b089cb5c9b3224e739bb794e865b9bcdf4b'",
|
||||
testPath(), testPath(), testPath(), testPath())));
|
||||
|
||||
// Invalid checksum
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
storageRemoveNP(storageLocalWrite(), fileName);
|
||||
storageRemoveNP(storageLocalWrite(), fileNameCopy);
|
||||
|
||||
// change the checksum
|
||||
content = strNew
|
||||
(
|
||||
"[backrest]\n"
|
||||
"backrest-checksum=\"4306ec205f71417c301e403c4714090e61c8a999\"\n"
|
||||
"backrest-format=5\n"
|
||||
"backrest-version=\"1.23\"\n"
|
||||
"\n"
|
||||
"[db]\n"
|
||||
"db-id=1\n"
|
||||
"db-system-id=6455618988686438683\n"
|
||||
"db-version=\"9.6\"\n"
|
||||
"\n"
|
||||
"[db:history]\n"
|
||||
"1={\"db-id\":6455618988686438683,\"db-version\":\"9.6\"}\n"
|
||||
"2={\"db-id\":6457457208275135411,\"db-version\":\"9.6\"}\n"
|
||||
);
|
||||
|
||||
TEST_RESULT_VOID(
|
||||
storagePutNP(storageNewWriteNP(storageLocalWrite(), fileNameCopy), BUFSTR(content)), "put invalid checksum to copy");
|
||||
|
||||
// Empty checksum for main file
|
||||
content = strNew
|
||||
(
|
||||
"[backrest]\n"
|
||||
"backrest-checksum=\n"
|
||||
"backrest-format=5\n"
|
||||
"backrest-version=\"1.23\"\n"
|
||||
"\n"
|
||||
"[db]\n"
|
||||
"db-id=1\n"
|
||||
"db-system-id=6455618988686438683\n"
|
||||
"db-version=\"9.6\"\n"
|
||||
"\n"
|
||||
"[db:history]\n"
|
||||
"1={\"db-id\":6455618988686438683,\"db-version\":\"9.6\"}\n"
|
||||
"2={\"db-id\":6457457208275135411,\"db-version\":\"9.6\"}\n"
|
||||
);
|
||||
|
||||
TEST_RESULT_VOID(
|
||||
storagePutNP(storageNewWriteNP(storageLocalWrite(), fileName), BUFSTR(content)), "put empty checksum to file");
|
||||
|
||||
// Copy file error
|
||||
TEST_ERROR(
|
||||
infoNewLoad(storageLocal(), fileName, cipherTypeNone, NULL, NULL), ChecksumError,
|
||||
strPtr(
|
||||
strNewFmt(
|
||||
"unable to load info file '%s/test.ini' or '%s/test.ini.copy':\n"
|
||||
"ChecksumError: invalid checksum in '%s/test.ini', expected '4306ec205f71417c301e403c4714090e61c8a736' but"
|
||||
" no checksum found\n"
|
||||
"ChecksumError: invalid checksum in '%s/test.ini.copy', expected '4306ec205f71417c301e403c4714090e61c8a736'"
|
||||
" but found '4306ec205f71417c301e403c4714090e61c8a999'",
|
||||
testPath(), testPath(), testPath(), testPath())));
|
||||
|
||||
// Encryption error
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
storageRemoveNP(storageLocalWrite(), fileName);
|
||||
TEST_ERROR_FMT(
|
||||
infoNewLoad(storageLocal(), fileName, cipherTypeAes256Cbc, strNew("12345678"), NULL), CryptoError,
|
||||
"unable to load info file '%s/test.ini' or '%s/test.ini.copy':\n"
|
||||
"FileMissingError: " STORAGE_ERROR_READ_MISSING "\n"
|
||||
"CryptoError: '%s/test.ini.copy' cipher header invalid\n"
|
||||
"HINT: Is or was the repo encrypted?",
|
||||
testPath(), testPath(), strPtr(strNewFmt("%s/test.ini", testPath())), testPath());
|
||||
|
||||
storageRemoveNP(storageLocalWrite(), fileNameCopy);
|
||||
|
||||
// infoFree()
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TEST_RESULT_VOID(infoFree(info), "infoFree() - free info memory context");
|
||||
TEST_RESULT_VOID(infoSave(info, ioBufferWriteNew(contentSave), testInfoSaveCallback, strNew("1")), "info save");
|
||||
TEST_RESULT_STR(strPtr(strNewBuf(contentSave)), strPtr(strNewBuf(contentLoad)), " check save");
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("infoSave()"))
|
||||
if (testBegin("infoLoad()"))
|
||||
{
|
||||
Ini *ini = iniNew();
|
||||
iniSet(ini, strNew("section1"), strNew("key1"), strNew("value1"));
|
||||
Info *info = infoNew(cipherTypeNone, NULL);
|
||||
TEST_RESULT_VOID(infoSave(info, ini, storageTest, fileName, cipherTypeNone, NULL), "save info");
|
||||
|
||||
ini = NULL;
|
||||
TEST_RESULT_VOID(infoNewLoad(storageTest, fileName, cipherTypeNone, NULL, &ini), " reload info");
|
||||
TEST_RESULT_STR(strPtr(iniGet(ini, strNew("section1"), strNew("key1"))), "value1", " check ini");
|
||||
|
||||
TEST_RESULT_BOOL(storageExistsNP(storageTest, fileName), true, "check main exists");
|
||||
TEST_RESULT_BOOL(storageExistsNP(storageTest, strNewFmt("%s" INFO_COPY_EXT, strPtr(fileName))), true, "check copy exists");
|
||||
// One error
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
TestInfoLoad testInfoLoad = {.test = 1};
|
||||
|
||||
TEST_ERROR(
|
||||
infoSave(info, ini, storageTest, fileName, cipherTypeAes256Cbc, cipherPass), AssertError,
|
||||
"assertion '!((cipherType != cipherTypeNone && this->cipherPass == NULL) || "
|
||||
"(cipherType == cipherTypeNone && this->cipherPass != NULL))' failed");
|
||||
infoLoad(STRDEF("unable to load info file"), testInfoLoadCallback, &testInfoLoad), ChecksumError,
|
||||
"unable to load info file:\n"
|
||||
"ChecksumError: checksum error");
|
||||
|
||||
// Add encryption
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
ini = iniNew();
|
||||
iniSet(ini, strNew("section1"), strNew("key1"), strNew("value4"));
|
||||
info = infoNew(cipherTypeAes256Cbc, strNew("/hall-pass"));
|
||||
TEST_RESULT_VOID(infoSave(info, ini, storageTest, fileName, cipherTypeAes256Cbc, cipherPass), "save encrypted info");
|
||||
|
||||
ini = NULL;
|
||||
TEST_RESULT_VOID(infoNewLoad(storageTest, fileName, cipherTypeAes256Cbc, cipherPass, &ini), " reload info");
|
||||
TEST_RESULT_STR(strPtr(iniGet(ini, strNew("section1"), strNew("key1"))), "value4", " check ini");
|
||||
TEST_RESULT_STR(strPtr(iniGet(ini, strNew("cipher"), strNew("cipher-pass"))), "\"/hall-pass\"", " check cipher-pass");
|
||||
// Two errors (same error)
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
testInfoLoad = (TestInfoLoad){.test = 2};
|
||||
|
||||
TEST_ERROR(
|
||||
infoSave(info, ini, storageTest, fileName, cipherTypeNone, NULL), AssertError,
|
||||
"assertion '!((cipherType != cipherTypeNone && this->cipherPass == NULL) || "
|
||||
"(cipherType == cipherTypeNone && this->cipherPass != NULL))' failed");
|
||||
infoLoad(STRDEF("unable to load info file(s)"), testInfoLoadCallback, &testInfoLoad), FormatError,
|
||||
"unable to load info file(s):\n"
|
||||
"FormatError: format error\n"
|
||||
"FormatError: format error");
|
||||
|
||||
// Four errors (mixed)
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
testInfoLoad = (TestInfoLoad){.test = 3};
|
||||
|
||||
TEST_ERROR(
|
||||
infoLoad(STRDEF("unable to load info file(s)"), testInfoLoadCallback, &testInfoLoad), FileOpenError,
|
||||
"unable to load info file(s):\n"
|
||||
"FileMissingError: file missing error\n"
|
||||
"ChecksumError: checksum error\n"
|
||||
"HINT: have you checked the thing?\n"
|
||||
"FormatError: format error\n"
|
||||
"FileMissingError: file missing error");
|
||||
|
||||
// Success
|
||||
//--------------------------------------------------------------------------------------------------------------------------
|
||||
testInfoLoad = (TestInfoLoad){0};
|
||||
|
||||
infoLoad(STRDEF("SHOULD BE NO ERROR"), testInfoLoadCallback, &testInfoLoad);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user