1
0
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:
David Steele
2019-09-06 13:48:28 -04:00
parent 7334f30c35
commit 4d84820021
40 changed files with 2204 additions and 1449 deletions
+8
View File
@@ -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
View File
@@ -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
+1 -1
View File
@@ -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;
+1 -1
View File
@@ -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)));
+1 -1
View File
@@ -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);
+3 -3
View File
@@ -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));
+2 -2
View File
@@ -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));
+6 -8
View File
@@ -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)));
+4 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
static void
infoLoadCallback(void *data, const String *section, const String *key, const String *value)
{
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();
Ini *result = NULL;
ASSERT(data != NULL);
ASSERT(section != NULL);
ASSERT(key != NULL);
ASSERT(value != NULL);
MEM_CONTEXT_TEMP_BEGIN()
InfoLoadData *loadData = (InfoLoadData *)data;
// Calculate checksum
if (!(strEq(section, INFO_SECTION_BACKREST_STR) && strEq(key, INFO_KEY_CHECKSUM_STR)))
{
const String *fileNameExt = copyFile ? strNewFmt("%s" INFO_COPY_EXT, strPtr(fileName)) : fileName;
// Attempt to load the file
StorageRead *infoRead = storageNewReadP(storage, fileNameExt, .compressible = cipherType == cipherTypeNone);
if (cipherType != cipherTypeNone)
if (loadData->sectionLast == NULL || !strEq(section, loadData->sectionLast))
{
ioFilterGroupAdd(
ioReadFilterGroup(storageReadIo(infoRead)),
cipherBlockNew(cipherModeDecrypt, cipherType, BUFSTR(cipherPass), NULL));
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
View File
@@ -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
View File
@@ -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();
}
+9 -6
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
static void
infoPgLoadCallback(void *data, const String *section, const String *key, const String *value)
{
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();
InfoPg *this = infoPgNewInternal();
ASSERT(data != NULL);
ASSERT(section != NULL);
ASSERT(key != NULL);
ASSERT(value != NULL);
MEM_CONTEXT_BEGIN(this->memContext)
InfoPgLoadData *loadData = (InfoPgLoadData *)data;
// Process db section
if (strEq(section, INFO_SECTION_DB_STR))
{
// Load info
Ini *iniLocal = NULL;
this->info = infoNewLoad(storage, fileName, cipherType, cipherPass, &iniLocal);
MEM_CONTEXT_TEMP_BEGIN()
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))
{
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--)
{
// 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();
}
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;
}
MEM_CONTEXT_END();
// 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);
static void
infoPgSaveCallback(void *data, const String *sectionNext, InfoSave *infoSaveData)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM_P(VOID, data);
FUNCTION_TEST_PARAM(STRING, sectionNext);
FUNCTION_TEST_PARAM(INFO_SAVE, infoSaveData);
FUNCTION_TEST_END();
MEM_CONTEXT_TEMP_BEGIN()
ASSERT(data != NULL);
ASSERT(infoSaveData != NULL);
InfoPgSaveData *saveData = (InfoPgSaveData *)data;
if (infoSaveSection(infoSaveData, INFO_SECTION_DB_STR, sectionNext))
{
// Set the db section
InfoPgData pgData = infoPgDataCurrent(this);
if (saveData->callbackFunction != NULL)
saveData->callbackFunction(saveData->callbackData, INFO_SECTION_DB_STR, infoSaveData);
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));
InfoPgData pgData = infoPgDataCurrent(saveData->infoPg);
if (type == infoPgBackup || type == infoPgManifest)
if (saveData->infoPg->type == infoPgBackup)
{
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));
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
View File
@@ -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
View File
@@ -295,7 +295,7 @@ unit:
# ----------------------------------------------------------------------------------------------------------------------------
- name: ini
total: 4
total: 5
coverage:
common/ini: full
+54 -18
View File
@@ -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]"
+51 -17
View File
@@ -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]"
+6 -2
View File
@@ -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
+6 -2
View File
@@ -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
+6 -2
View File
@@ -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
------------------------------------------------------------------------------------------------------------------------------------
+6 -2
View File
@@ -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
------------------------------------------------------------------------------------------------------------------------------------
+39 -13
View File
@@ -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]
+18 -6
View File
@@ -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]
+45 -15
View File
@@ -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
------------------------------------------------------------------------------------------------------------------------------------
+42 -14
View File
@@ -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
------------------------------------------------------------------------------------------------------------------------------------
+85 -17
View File
@@ -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));
}
+3
View File
@@ -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);
+10 -10
View File
@@ -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");
+4 -4
View File
@@ -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))));
}
//******************************************************************************************************************************
+2 -2
View File
@@ -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");
+127 -18
View File
@@ -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();
+63 -75
View File
@@ -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");
}
}
+83 -80
View File
@@ -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
View File
@@ -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
View File
@@ -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
//--------------------------------------------------------------------------------------------------------------------------
String *content = NULL;
String *fileNameCopy = strNewFmt("%s/test.ini.copy", testPath());
content = strNew
(
// Format error
// --------------------------------------------------------------------------------------------------------------------------
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
//--------------------------------------------------------------------------------------------------------------------------
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())));
String *callbackContent = strNew("");
// Only copy exists and one is required
//--------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_VOID(
storagePutNP(storageNewWriteNP(storageLocalWrite(), fileNameCopy), BUFSTR(content)), "put info.copy to file");
TEST_ERROR(
infoNewLoad(ioBufferReadNew(contentLoad), harnessInfoLoadNewCallback, callbackContent), FormatError,
"expected format 5 but found 4");
TEST_RESULT_STR(strPtr(callbackContent), "", " check callback content");
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(
// Checksum not found
// --------------------------------------------------------------------------------------------------------------------------
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);
}
}