1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-03-03 14:52:21 +02:00

Add infoBackup object to encapsulate the backup.info file.

The infoBackup object is the counterpart to the infoArchive object which encapsulates the archive.info file.

Currently the object is read-only, i.e. it is not possible to create a new or modify an existing backup.info file.

There a number of constants that will also be used in the infoManifest object so go ahead and create a module to contain them so they don't need to be moved later.

Contributed by Cynthia Shang.
This commit is contained in:
Cynthia Shang 2018-12-13 15:46:18 -05:00 committed by David Steele
parent 56d466ce4b
commit e6ef40e8a3
13 changed files with 664 additions and 4 deletions

View File

@ -91,6 +91,14 @@
<p>Allow arbitary <code>InOut</code> filters to be chained in <code>IoFilterGroup</code>.</p>
</release-item>
<release-item>
<release-item-contributor-list>
<release-item-contributor id="cynthia.shang"/>
</release-item-contributor-list>
<p>Add <code>infoBackup</code> object to encapsulate the <file>backup.info</file> file.</p>
</release-item>
<release-item>
<release-item-contributor-list>
<release-item-contributor id="cynthia.shang"/>

View File

@ -165,7 +165,7 @@ install: pgbackrest
command/archive/common.o: command/archive/common.c command/archive/common.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/read.h common/io/write.h common/log.h common/logLevel.h common/memContext.h common/regExp.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 common/wait.h postgres/version.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
$(CC) $(CFLAGS) -c command/archive/common.c -o command/archive/common.o
command/archive/get/file.o: command/archive/get/file.c command/archive/common.h command/archive/get/file.h command/control/control.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h compress/gzip.h compress/gzipDecompress.h config/config.auto.h config/config.h config/define.auto.h config/define.h crypto/cipherBlock.h crypto/crypto.h info/infoArchive.h info/infoPg.h postgres/interface.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
command/archive/get/file.o: command/archive/get/file.c command/archive/common.h command/archive/get/file.h command/control/control.h common/debug.h common/error.auto.h common/error.h common/ini.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h compress/gzip.h compress/gzipDecompress.h config/config.auto.h config/config.h config/define.auto.h config/define.h crypto/cipherBlock.h crypto/crypto.h info/infoArchive.h info/infoPg.h postgres/interface.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
$(CC) $(CFLAGS) -c command/archive/get/file.c -o command/archive/get/file.o
command/archive/get/get.o: command/archive/get/get.c command/archive/common.h command/archive/get/file.h command/command.h common/assert.h common/debug.h common/error.auto.h common/error.h common/fork.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/regExp.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 common/wait.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/load.h crypto/crypto.h perl/exec.h postgres/interface.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
@ -336,6 +336,12 @@ info/info.o: info/info.c common/debug.h common/error.auto.h common/error.h commo
info/infoArchive.o: info/infoArchive.c 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/memContext.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 crypto/crypto.h info/infoArchive.h info/infoPg.h postgres/interface.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
$(CC) $(CFLAGS) -c info/infoArchive.c -o info/infoArchive.o
info/infoBackup.o: info/infoBackup.c 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/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/json.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h crypto/crypto.h crypto/hash.h info/info.h info/infoBackup.h info/infoManifest.h info/infoPg.h postgres/interface.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
$(CC) $(CFLAGS) -c info/infoBackup.c -o info/infoBackup.o
info/infoManifest.o: info/infoManifest.c common/error.auto.h common/error.h common/memContext.h common/type/buffer.h common/type/string.h info/infoManifest.h
$(CC) $(CFLAGS) -c info/infoManifest.c -o info/infoManifest.o
info/infoPg.o: info/infoPg.c 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/memContext.h common/stackTrace.h common/time.h common/type/buffer.h common/type/convert.h common/type/json.h common/type/keyValue.h common/type/list.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h crypto/crypto.h crypto/hash.h info/info.h info/infoPg.h postgres/interface.h postgres/version.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
$(CC) $(CFLAGS) -c info/infoPg.c -o info/infoPg.o

View File

@ -25,7 +25,8 @@ STRING_STATIC(INFO_SECTION_CIPHER_STR, "cipher");
STRING_STATIC(INFO_KEY_CIPHER_PASS_STR, "cipher-pass");
STRING_STATIC(INFO_KEY_CHECKSUM_STR, "backrest-checksum");
STRING_STATIC(INFO_KEY_FORMAT_STR, "backrest-format");
STRING_EXTERN(INFO_KEY_FORMAT_STR, INFO_KEY_FORMAT);
STRING_EXTERN(INFO_KEY_VERSION_STR, INFO_KEY_VERSION);
/***********************************************************************************************************************************
Object type

View File

@ -14,6 +14,14 @@ typedef struct Info Info;
#include "crypto/hash.h"
#include "storage/storage.h"
/***********************************************************************************************************************************
Constants
***********************************************************************************************************************************/
#define INFO_KEY_FORMAT "backrest-format"
STRING_DECLARE(INFO_KEY_VERSION_STR);
#define INFO_KEY_VERSION "backrest-version"
STRING_DECLARE(INFO_KEY_FORMAT_STR);
/***********************************************************************************************************************************
Constructor
***********************************************************************************************************************************/

258
src/info/infoBackup.c Normal file
View File

@ -0,0 +1,258 @@
/***********************************************************************************************************************************
Backup Info Handler
***********************************************************************************************************************************/
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "common/debug.h"
#include "common/log.h"
#include "common/memContext.h"
#include "common/ini.h"
#include "common/type/json.h"
#include "common/type/list.h"
#include "info/info.h"
#include "info/infoBackup.h"
#include "info/infoManifest.h"
#include "info/infoPg.h"
#include "postgres/interface.h"
#include "storage/helper.h"
/***********************************************************************************************************************************
Internal constants
??? INFO_BACKUP_SECTION should be in a separate include since it will also be used when reading the manifest
***********************************************************************************************************************************/
#define INFO_BACKUP_SECTION "backup"
#define INFO_BACKUP_SECTION_BACKUP_CURRENT INFO_BACKUP_SECTION ":current"
STRING_STATIC(INFO_BACKUP_KEY_BACKUP_INFO_REPO_SIZE_STR, "backup-info-repo-size");
STRING_STATIC(INFO_BACKUP_KEY_BACKUP_INFO_REPO_SIZE_DELTA_STR, "backup-info-repo-size-delta");
STRING_STATIC(INFO_BACKUP_KEY_BACKUP_INFO_SIZE_STR, "backup-info-size");
STRING_STATIC(INFO_BACKUP_KEY_BACKUP_INFO_SIZE_DELTA_STR, "backup-info-size-delta");
STRING_STATIC(INFO_BACKUP_KEY_BACKUP_REFERENCE_STR, "backup-reference");
/***********************************************************************************************************************************
Object type
***********************************************************************************************************************************/
struct InfoBackup
{
MemContext *memContext; // Context that contains the InfoBackup
InfoPg *infoPg; // Contents of the DB data
List *backup; // List of current backups and their associated data
};
/***********************************************************************************************************************************
Create a new InfoBackup object
// ??? Need loadFile parameter
// ??? Need to handle ignoreMissing = true
***********************************************************************************************************************************/
InfoBackup *
infoBackupNew(const Storage *storage, const String *fileName, bool ignoreMissing, CipherType cipherType, const String *cipherPass)
{
FUNCTION_DEBUG_BEGIN(logLevelDebug);
FUNCTION_DEBUG_PARAM(STRING, fileName);
FUNCTION_DEBUG_PARAM(BOOL, ignoreMissing);
FUNCTION_DEBUG_PARAM(ENUM, cipherType);
// cipherPass omitted for security
FUNCTION_DEBUG_ASSERT(fileName != NULL);
FUNCTION_DEBUG_END();
InfoBackup *this = NULL;
MEM_CONTEXT_NEW_BEGIN("infoBackup")
{
// Create object
this = memNew(sizeof(InfoBackup));
this->memContext = MEM_CONTEXT_NEW();
// Catch file missing error and add backup-specific hints before rethrowing
TRY_BEGIN()
{
this->infoPg = infoPgNew(storage, fileName, infoPgBackup, cipherType, cipherPass);
}
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 Ini *infoIni = infoPgIni(this->infoPg);
const String *backupCurrentSection = strNew(INFO_BACKUP_SECTION_BACKUP_CURRENT);
// If there are current backups, then parse the json for each into a list object
if (strLstExists(iniSectionList(infoIni), backupCurrentSection))
{
// Initialize the store and get the list of backup labels
this->backup = lstNew(sizeof(InfoBackupData));
const StringList *backupLabelList = iniSectionKeyList(infoIni, 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(varStr(iniGet(infoIni, backupCurrentSection, backupLabelKey)));
InfoBackupData infoBackupData =
{
.backrestFormat = (unsigned int) varUInt64(kvGet(backupKv, varNewStr(INFO_KEY_FORMAT_STR))),
.backrestVersion = varStrForce(kvGet(backupKv, varNewStr(INFO_KEY_VERSION_STR))),
.backupInfoRepoSize = varUInt64(kvGet(backupKv, varNewStr(INFO_BACKUP_KEY_BACKUP_INFO_REPO_SIZE_STR))),
.backupInfoRepoSizeDelta = varUInt64(
kvGet(backupKv, varNewStr(INFO_BACKUP_KEY_BACKUP_INFO_REPO_SIZE_DELTA_STR))),
.backupInfoSize = varUInt64(kvGet(backupKv, varNewStr(INFO_BACKUP_KEY_BACKUP_INFO_SIZE_STR))),
.backupInfoSizeDelta = varUInt64(kvGet(backupKv, varNewStr(INFO_BACKUP_KEY_BACKUP_INFO_SIZE_DELTA_STR))),
.backupLabel = strDup(backupLabelKey),
.backupPgId = cvtZToUInt(strPtr(varStrForce(kvGet(backupKv, varNewStr(INFO_KEY_DB_ID_STR))))),
.backupTimestampStart = varUInt64(kvGet(backupKv, varNewStr(INFO_MANIFEST_KEY_BACKUP_TIMESTAMP_START_STR))),
.backupTimestampStop= varUInt64(kvGet(backupKv, varNewStr(INFO_MANIFEST_KEY_BACKUP_TIMESTAMP_STOP_STR))),
.backupType = varStrForce(kvGet(backupKv, varNewStr(INFO_MANIFEST_KEY_BACKUP_TYPE_STR))),
// Possible NULL values
.backupArchiveStart = varStr(kvGet(backupKv, varNewStr(INFO_MANIFEST_KEY_BACKUP_ARCHIVE_START_STR))),
.backupArchiveStop = varStr(kvGet(backupKv, varNewStr(INFO_MANIFEST_KEY_BACKUP_ARCHIVE_STOP_STR))),
.backupPrior = varStr(kvGet(backupKv, varNewStr(INFO_MANIFEST_KEY_BACKUP_PRIOR_STR))),
.backupReference = (kvGet(backupKv, varNewStr(INFO_BACKUP_KEY_BACKUP_REFERENCE_STR)) != NULL ?
strLstNewVarLst(varVarLst(kvGet(backupKv, varNewStr(INFO_BACKUP_KEY_BACKUP_REFERENCE_STR)))) :
NULL),
// Options
.optionArchiveCheck = varBool(kvGet(backupKv, varNewStr(INFO_MANIFEST_KEY_OPT_ARCHIVE_CHECK_STR))),
.optionArchiveCopy = varBool(kvGet(backupKv, varNewStr(INFO_MANIFEST_KEY_OPT_ARCHIVE_COPY_STR))),
.optionBackupStandby = varBool(kvGet(backupKv, varNewStr(INFO_MANIFEST_KEY_OPT_BACKUP_STANDBY_STR))),
.optionChecksumPage = varBool(kvGet(backupKv, varNewStr(INFO_MANIFEST_KEY_OPT_CHECKSUM_PAGE_STR))),
.optionCompress = varBool(kvGet(backupKv, varNewStr(INFO_MANIFEST_KEY_OPT_COMPRESS_STR))),
.optionHardlink = varBool(kvGet(backupKv, varNewStr(INFO_MANIFEST_KEY_OPT_HARDLINK_STR))),
.optionOnline = varBool(kvGet(backupKv, varNewStr(INFO_MANIFEST_KEY_OPT_ONLINE_STR))),
};
// Add the backup data to the list
lstAdd(this->backup, &infoBackupData);
}
}
}
MEM_CONTEXT_NEW_END();
// Return buffer
FUNCTION_DEBUG_RESULT(INFO_BACKUP, this);
}
/***********************************************************************************************************************************
Checks the backup info file's DB section against the PG version, system id, catolog and constrol version passed in and returns
the history id of the current PG database.
// ??? Should we still check that the file exists if it is required?
***********************************************************************************************************************************/
unsigned int
infoBackupCheckPg(
const InfoBackup *this,
unsigned int pgVersion,
uint64_t pgSystemId,
uint32_t pgCatalogVersion,
uint32_t pgControlVersion)
{
FUNCTION_DEBUG_BEGIN(logLevelTrace);
FUNCTION_DEBUG_PARAM(INFO_BACKUP, this);
FUNCTION_DEBUG_PARAM(UINT, pgVersion);
FUNCTION_DEBUG_PARAM(UINT64, pgSystemId);
FUNCTION_DEBUG_PARAM(UINT32, pgCatalogVersion);
FUNCTION_DEBUG_PARAM(UINT32, pgControlVersion);
FUNCTION_DEBUG_ASSERT(this != NULL);
FUNCTION_DEBUG_END();
InfoPgData backupPg = infoPgDataCurrent(this->infoPg);
if (backupPg.version != pgVersion || backupPg.systemId != pgSystemId)
THROW(BackupMismatchError, strPtr(strNewFmt(
"database version = %s, system-id %" PRIu64 " does not match backup version = %s, system-id = %" PRIu64 "\n"
"HINT: is this the correct stanza?",
strPtr(pgVersionToStr(pgVersion)), pgSystemId, strPtr(pgVersionToStr(backupPg.version)), backupPg.systemId)));
if (backupPg.catalogVersion != pgCatalogVersion || backupPg.controlVersion != pgControlVersion)
{
THROW(BackupMismatchError, strPtr(strNewFmt(
"database control-version = %" PRIu32 ", catalog-version %" PRIu32
" does not match backup control-version = %" PRIu32 ", catalog-version = %" PRIu32 "\n"
"HINT: this may be a symptom of database or repository corruption!",
pgControlVersion, pgCatalogVersion, backupPg.controlVersion, backupPg.catalogVersion)));
}
FUNCTION_DEBUG_RESULT(UINT, backupPg.id);
}
/***********************************************************************************************************************************
Get PostgreSQL info
***********************************************************************************************************************************/
InfoPg *
infoBackupPg(const InfoBackup *this)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(INFO_BACKUP, this);
FUNCTION_TEST_ASSERT(this != NULL);
FUNCTION_TEST_END();
FUNCTION_TEST_RESULT(INFO_PG, this->infoPg);
}
/***********************************************************************************************************************************
Get total current backups
***********************************************************************************************************************************/
unsigned int
infoBackupDataTotal(const InfoBackup *this)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(INFO_BACKUP, this);
FUNCTION_TEST_ASSERT(this != NULL);
FUNCTION_TEST_END();
FUNCTION_TEST_RESULT(UINT, (this->backup == NULL ? 0 : lstSize(this->backup)));
}
/***********************************************************************************************************************************
Return a structure of the backup data from a specific index
***********************************************************************************************************************************/
InfoBackupData
infoBackupData(const InfoBackup *this, unsigned int backupDataIdx)
{
FUNCTION_DEBUG_BEGIN(logLevelTrace);
FUNCTION_DEBUG_PARAM(INFO_BACKUP, this);
FUNCTION_DEBUG_PARAM(UINT, backupDataIdx);
FUNCTION_DEBUG_ASSERT(this != NULL);
FUNCTION_DEBUG_END();
FUNCTION_DEBUG_RESULT(INFO_BACKUP_DATA, *((InfoBackupData *)lstGet(this->backup, backupDataIdx)));
}
/***********************************************************************************************************************************
Render as string for logging
***********************************************************************************************************************************/
String *
infoBackupDataToLog(const InfoBackupData *this)
{
return strNewFmt("{label: %s, pgId: %u}", strPtr(this->backupLabel), this->backupPgId);
}
/***********************************************************************************************************************************
Free the info
***********************************************************************************************************************************/
void
infoBackupFree(InfoBackup *this)
{
FUNCTION_DEBUG_BEGIN(logLevelTrace);
FUNCTION_DEBUG_PARAM(INFO_BACKUP, this);
FUNCTION_DEBUG_END();
if (this != NULL)
memContextFree(this->memContext);
FUNCTION_DEBUG_RESULT_VOID();
}

88
src/info/infoBackup.h Normal file
View File

@ -0,0 +1,88 @@
/***********************************************************************************************************************************
Backup Info Handler
***********************************************************************************************************************************/
#ifndef INFO_INFOBACKUP_H
#define INFO_INFOBACKUP_H
/***********************************************************************************************************************************
Object type
***********************************************************************************************************************************/
typedef struct InfoBackup InfoBackup;
#include "common/type/string.h"
#include "info/infoPg.h"
#include "storage/storage.h"
/***********************************************************************************************************************************
Constants
***********************************************************************************************************************************/
#define INFO_BACKUP_FILE "backup.info"
/***********************************************************************************************************************************
Information about an existing backup
***********************************************************************************************************************************/
typedef struct InfoBackupData
{
unsigned int backrestFormat;
const String *backrestVersion;
const String *backupArchiveStart;
const String *backupArchiveStop;
uint64_t backupInfoRepoSize;
uint64_t backupInfoRepoSizeDelta;
uint64_t backupInfoSize;
uint64_t backupInfoSizeDelta;
const String *backupLabel;
unsigned int backupPgId;
const String *backupPrior;
StringList *backupReference;
uint64_t backupTimestampStart;
uint64_t backupTimestampStop;
const String *backupType;
bool optionArchiveCheck;
bool optionArchiveCopy;
bool optionBackupStandby;
bool optionChecksumPage;
bool optionCompress;
bool optionHardlink;
bool optionOnline;
} InfoBackupData;
/***********************************************************************************************************************************
Constructor
***********************************************************************************************************************************/
InfoBackup *infoBackupNew(
const Storage *storage, const String *fileName, bool ignoreMissing, CipherType cipherType, const String *cipherPass);
/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
unsigned int infoBackupCheckPg(
const InfoBackup *this, unsigned int pgVersion, uint64_t pgSystemId, uint32_t pgCatalogVersion, uint32_t pgControlVersion);
/***********************************************************************************************************************************
Getters
***********************************************************************************************************************************/
InfoPg *infoBackupPg(const InfoBackup *this);
InfoBackupData infoBackupData(const InfoBackup *this, unsigned int backupDataIdx);
unsigned int infoBackupDataTotal(const InfoBackup *this);
/***********************************************************************************************************************************
Destructor
***********************************************************************************************************************************/
void infoBackupFree(InfoBackup *this);
/***********************************************************************************************************************************
Macros for function logging
***********************************************************************************************************************************/
String *infoBackupDataToLog(const InfoBackupData *this);
#define FUNCTION_DEBUG_INFO_BACKUP_TYPE \
InfoBackup *
#define FUNCTION_DEBUG_INFO_BACKUP_FORMAT(value, buffer, bufferSize) \
objToLog(value, "InfoBackup", buffer, bufferSize)
#define FUNCTION_DEBUG_INFO_BACKUP_DATA_TYPE \
InfoBackupData
#define FUNCTION_DEBUG_INFO_BACKUP_DATA_FORMAT(value, buffer, bufferSize) \
FUNCTION_DEBUG_STRING_OBJECT_FORMAT(&value, infoBackupDataToLog, buffer, bufferSize)
#endif

22
src/info/infoManifest.c Normal file
View File

@ -0,0 +1,22 @@
/***********************************************************************************************************************************
Manifest Info Handler
***********************************************************************************************************************************/
#include "common/type/string.h"
#include "info/infoManifest.h"
/***********************************************************************************************************************************
Constants
***********************************************************************************************************************************/
STRING_EXTERN(INFO_MANIFEST_KEY_BACKUP_ARCHIVE_START_STR, INFO_MANIFEST_KEY_BACKUP_ARCHIVE_START);
STRING_EXTERN(INFO_MANIFEST_KEY_BACKUP_ARCHIVE_STOP_STR, INFO_MANIFEST_KEY_BACKUP_ARCHIVE_STOP);
STRING_EXTERN(INFO_MANIFEST_KEY_BACKUP_PRIOR_STR, INFO_MANIFEST_KEY_BACKUP_PRIOR);
STRING_EXTERN(INFO_MANIFEST_KEY_BACKUP_TIMESTAMP_START_STR, INFO_MANIFEST_KEY_BACKUP_TIMESTAMP_START);
STRING_EXTERN(INFO_MANIFEST_KEY_BACKUP_TIMESTAMP_STOP_STR, INFO_MANIFEST_KEY_BACKUP_TIMESTAMP_STOP);
STRING_EXTERN(INFO_MANIFEST_KEY_BACKUP_TYPE_STR, INFO_MANIFEST_KEY_BACKUP_TYPE);
STRING_EXTERN(INFO_MANIFEST_KEY_OPT_ARCHIVE_CHECK_STR, INFO_MANIFEST_KEY_OPT_ARCHIVE_CHECK);
STRING_EXTERN(INFO_MANIFEST_KEY_OPT_ARCHIVE_COPY_STR, INFO_MANIFEST_KEY_OPT_ARCHIVE_COPY);
STRING_EXTERN(INFO_MANIFEST_KEY_OPT_BACKUP_STANDBY_STR, INFO_MANIFEST_KEY_OPT_BACKUP_STANDBY);
STRING_EXTERN(INFO_MANIFEST_KEY_OPT_CHECKSUM_PAGE_STR, INFO_MANIFEST_KEY_OPT_CHECKSUM_PAGE);
STRING_EXTERN(INFO_MANIFEST_KEY_OPT_COMPRESS_STR, INFO_MANIFEST_KEY_OPT_COMPRESS);
STRING_EXTERN(INFO_MANIFEST_KEY_OPT_HARDLINK_STR, INFO_MANIFEST_KEY_OPT_HARDLINK);
STRING_EXTERN(INFO_MANIFEST_KEY_OPT_ONLINE_STR, INFO_MANIFEST_KEY_OPT_ONLINE);

34
src/info/infoManifest.h Normal file
View File

@ -0,0 +1,34 @@
/***********************************************************************************************************************************
Manifest Info Handler
***********************************************************************************************************************************/
#ifndef INFO_INFOMANIFEST_H
#define INFO_INFOMANIFEST_H
#define INFO_MANIFEST_KEY_BACKUP_ARCHIVE_START "backup-archive-start"
STRING_DECLARE(INFO_MANIFEST_KEY_BACKUP_ARCHIVE_START_STR);
#define INFO_MANIFEST_KEY_BACKUP_ARCHIVE_STOP "backup-archive-stop"
STRING_DECLARE(INFO_MANIFEST_KEY_BACKUP_ARCHIVE_STOP_STR);
#define INFO_MANIFEST_KEY_BACKUP_PRIOR "backup-prior"
STRING_DECLARE(INFO_MANIFEST_KEY_BACKUP_PRIOR_STR);
#define INFO_MANIFEST_KEY_BACKUP_TIMESTAMP_START "backup-timestamp-start"
STRING_DECLARE(INFO_MANIFEST_KEY_BACKUP_TIMESTAMP_START_STR);
#define INFO_MANIFEST_KEY_BACKUP_TIMESTAMP_STOP "backup-timestamp-stop"
STRING_DECLARE(INFO_MANIFEST_KEY_BACKUP_TIMESTAMP_STOP_STR);
#define INFO_MANIFEST_KEY_BACKUP_TYPE "backup-type"
STRING_DECLARE(INFO_MANIFEST_KEY_BACKUP_TYPE_STR);
#define INFO_MANIFEST_KEY_OPT_ARCHIVE_CHECK "option-archive-check"
STRING_DECLARE(INFO_MANIFEST_KEY_OPT_ARCHIVE_CHECK_STR);
#define INFO_MANIFEST_KEY_OPT_ARCHIVE_COPY "option-archive-copy"
STRING_DECLARE(INFO_MANIFEST_KEY_OPT_ARCHIVE_COPY_STR);
#define INFO_MANIFEST_KEY_OPT_BACKUP_STANDBY "option-backup-standby"
STRING_DECLARE(INFO_MANIFEST_KEY_OPT_BACKUP_STANDBY_STR);
#define INFO_MANIFEST_KEY_OPT_CHECKSUM_PAGE "option-checksum-page"
STRING_DECLARE(INFO_MANIFEST_KEY_OPT_CHECKSUM_PAGE_STR);
#define INFO_MANIFEST_KEY_OPT_COMPRESS "option-compress"
STRING_DECLARE(INFO_MANIFEST_KEY_OPT_COMPRESS_STR);
#define INFO_MANIFEST_KEY_OPT_HARDLINK "option-hardlink"
STRING_DECLARE(INFO_MANIFEST_KEY_OPT_HARDLINK_STR);
#define INFO_MANIFEST_KEY_OPT_ONLINE "option-online"
STRING_DECLARE(INFO_MANIFEST_KEY_OPT_ONLINE_STR);
#endif

View File

@ -25,7 +25,7 @@ Internal constants
***********************************************************************************************************************************/
STRING_STATIC(INFO_SECTION_DB_HISTORY_STR, "db:history");
STRING_STATIC(INFO_KEY_DB_ID_STR, "db-id");
STRING_EXTERN(INFO_KEY_DB_ID_STR, INFO_KEY_DB_ID);
STRING_STATIC(INFO_KEY_DB_CATALOG_VERSION_STR, "db-catalog-version");
STRING_STATIC(INFO_KEY_DB_CONTROL_VERSION_STR, "db-control-version");
STRING_STATIC(INFO_KEY_DB_SYSTEM_ID_STR, "db-system-id");
@ -229,6 +229,21 @@ infoPgDataTotal(const InfoPg *this)
FUNCTION_DEBUG_RESULT(UINT, lstSize(this->history));
}
/***********************************************************************************************************************************
Return the ini object
***********************************************************************************************************************************/
Ini *
infoPgIni(const InfoPg *this)
{
FUNCTION_DEBUG_BEGIN(logLevelTrace);
FUNCTION_DEBUG_PARAM(INFO_PG, this);
FUNCTION_DEBUG_ASSERT(this != NULL);
FUNCTION_DEBUG_END();
FUNCTION_DEBUG_RESULT(INI, infoIni(this->info));
}
/***********************************************************************************************************************************
Render as string for logging
***********************************************************************************************************************************/

View File

@ -13,6 +13,13 @@ typedef struct InfoPg InfoPg;
#include "crypto/crypto.h"
#include "storage/storage.h"
#include "common/ini.h"
/***********************************************************************************************************************************
Constants
***********************************************************************************************************************************/
#define INFO_KEY_DB_ID "db-id"
STRING_DECLARE(INFO_KEY_DB_ID_STR);
/***********************************************************************************************************************************
Information about the PostgreSQL cluster
@ -54,6 +61,7 @@ const String *infoPgCipherPass(const InfoPg *this);
InfoPgData infoPgData(const InfoPg *this, unsigned int pgDataIdx);
InfoPgData infoPgDataCurrent(const InfoPg *this);
unsigned int infoPgDataTotal(const InfoPg *this);
Ini *infoPgIni(const InfoPg *this);
/***********************************************************************************************************************************
Destructor

View File

@ -587,6 +587,13 @@ unit:
coverage:
info/infoArchive: full
# ----------------------------------------------------------------------------------------------------------------------------
- name: info-backup
total: 2
coverage:
info/infoBackup: full
# ********************************************************************************************************************************
- name: command

View File

@ -0,0 +1,199 @@
/***********************************************************************************************************************************
Test Backup Info Handler
***********************************************************************************************************************************/
/***********************************************************************************************************************************
Test Run
***********************************************************************************************************************************/
void
testRun(void)
{
// Initialize test variables
//--------------------------------------------------------------------------------------------------------------------------
String *content = NULL;
String *fileName = strNewFmt("%s/test.ini", testPath());
InfoBackup *infoBackup = NULL;
// *****************************************************************************************************************************
if (testBegin("infoBackupNew(), infoBackupDataTotal(), infoBackupCheckPg(), infoBackupFree()"))
{
// File missing, ignoreMissing=false -- error
//--------------------------------------------------------------------------------------------------------------------------
TEST_ERROR_FMT(
infoBackupNew(storageLocal(), fileName, false, cipherTypeNone, NULL), FileMissingError,
"unable to load info file '%s/test.ini' or '%s/test.ini.copy':\n"
"FileMissingError: unable to open '%s/test.ini' for read: [2] No such file or directory\n"
"FileMissingError: unable to open '%s/test.ini.copy' for read: [2] No such file or directory\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());
// File exists, ignoreMissing=false, no backup:current section
//--------------------------------------------------------------------------------------------------------------------------
content = strNew
(
"[backrest]\n"
"backrest-checksum=\"5c17df9523543f5283efdc3c5aa7eb933c63ea0b\"\n"
"backrest-format=5\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"
);
TEST_RESULT_VOID(
storagePutNP(storageNewWriteNP(storageLocalWrite(), fileName), bufNewStr(content)), "put backup info to file");
TEST_ASSIGN(infoBackup, infoBackupNew(storageLocal(), fileName, false, cipherTypeNone, NULL), " new backup info");
TEST_RESULT_PTR(infoBackupPg(infoBackup), infoBackup->infoPg, " infoPg set");
TEST_RESULT_PTR(infoBackup->backup, NULL, " backupCurrent NULL");
TEST_RESULT_INT(infoBackupDataTotal(infoBackup), 0, " infoBackupDataTotal returns 0");
// infoBackupCheckPg
//--------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_INT(infoBackupCheckPg(infoBackup, 90400, 6569239123849665679, 201409291, 942), 1, "check PG data");
TEST_ERROR_FMT(
infoBackupCheckPg(infoBackup, 90500, 6569239123849665679, 201409291, 942), BackupMismatchError,
"database version = 9.5, system-id 6569239123849665679 does not match "
"backup version = 9.4, system-id = 6569239123849665679\n"
"HINT: is this the correct stanza?");
TEST_ERROR_FMT(
infoBackupCheckPg(infoBackup, 90400, 6569239123849665999, 201409291, 942), BackupMismatchError,
"database version = 9.4, system-id 6569239123849665999 does not match "
"backup version = 9.4, system-id = 6569239123849665679\n"
"HINT: is this the correct stanza?");
TEST_ERROR_FMT(
infoBackupCheckPg(infoBackup, 90400, 6569239123849665679, 201409291, 941), BackupMismatchError,
"database control-version = 941, catalog-version 201409291"
" does not match backup control-version = 942, catalog-version = 201409291\n"
"HINT: this may be a symptom of database or repository corruption!");
TEST_ERROR_FMT(
infoBackupCheckPg(infoBackup, 90400, 6569239123849665679, 201509291, 942), BackupMismatchError,
"database control-version = 942, catalog-version 201509291"
" does not match backup control-version = 942, catalog-version = 201409291\n"
"HINT: this may be a symptom of database or repository corruption!");
// Free
//--------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_VOID(infoBackupFree(infoBackup), "infoBackupFree() - free backup info");
TEST_RESULT_VOID(infoBackupFree(NULL), " NULL ptr");
}
// *****************************************************************************************************************************
if (testBegin("infoBackupData(), infoBackupDataTotal(), infoBackupDataToLog()"))
{
// File exists, ignoreMissing=false, backup:current section exists
//--------------------------------------------------------------------------------------------------------------------------
content = strNew
(
"[backrest]\n"
"backrest-checksum=\"b944d83dcfa33ac0eb88d41b16efc5aaa5da7ec1\"\n"
"backrest-format=5\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"
"[backup:current]\n"
"20161219-212741F={\"backrest-format\":5,\"backrest-version\":\"2.04\","
"\"backup-archive-start\":\"00000007000000000000001C\",\"backup-archive-stop\":\"00000007000000000000001C\","
"\"backup-info-repo-size\":3159776,\"backup-info-repo-size-delta\":3159776,\"backup-info-size\":26897030,"
"\"backup-info-size-delta\":26897030,\"backup-timestamp-start\":1482182846,\"backup-timestamp-stop\":1482182861,"
"\"backup-type\":\"full\",\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,"
"\"option-backup-standby\":false,\"option-checksum-page\":false,\"option-compress\":true,\"option-hardlink\":false,"
"\"option-online\":true}\n"
"20161219-212741F_20161219-212803D={\"backrest-format\":5,\"backrest-version\":\"2.04\","
"\"backup-archive-start\":\"00000008000000000000001E\",\"backup-archive-stop\":\"00000008000000000000001E\","
"\"backup-info-repo-size\":3159811,\"backup-info-repo-size-delta\":15765,\"backup-info-size\":26897030,"
"\"backup-info-size-delta\":163866,\"backup-prior\":\"20161219-212741F\",\"backup-reference\":[\"20161219-212741F\"],"
"\"backup-timestamp-start\":1482182877,\"backup-timestamp-stop\":1482182883,\"backup-type\":\"diff\",\"db-id\":1,"
"\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
"\"option-checksum-page\":false,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
"20161219-212741F_20161219-212918I={\"backrest-format\":5,\"backrest-version\":\"2.04\","
"\"backup-archive-start\":null,\"backup-archive-stop\":null,"
"\"backup-info-repo-size\":3159811,\"backup-info-repo-size-delta\":15765,\"backup-info-size\":26897030,"
"\"backup-info-size-delta\":163866,\"backup-prior\":\"20161219-212741F\",\"backup-reference\":[\"20161219-212741F\","
"\"20161219-212741F_20161219-212803D\"],"
"\"backup-timestamp-start\":1482182877,\"backup-timestamp-stop\":1482182883,\"backup-type\":\"incr\",\"db-id\":1,"
"\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
"\"option-checksum-page\":false,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\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), bufNewStr(content)), "put backup info current to file");
TEST_ASSIGN(infoBackup, infoBackupNew(storageLocal(), fileName, false, cipherTypeNone, NULL), " new backup info");
TEST_RESULT_INT(infoBackupDataTotal(infoBackup), 3, " backup list contains backups");
InfoBackupData backupData = infoBackupData(infoBackup, 0);
TEST_RESULT_STR(strPtr(backupData.backupLabel), "20161219-212741F", "full backup label");
TEST_RESULT_STR(strPtr(backupData.backupType), "full", " backup type full");
TEST_RESULT_INT(backupData.backrestFormat, 5, " backrest format");
TEST_RESULT_STR(strPtr(backupData.backrestVersion), "2.04", " backrest version");
TEST_RESULT_STR(strPtr(backupData.backupArchiveStart), "00000007000000000000001C", " archive start");
TEST_RESULT_STR(strPtr(backupData.backupArchiveStop), "00000007000000000000001C", " archive stop");
TEST_RESULT_INT(backupData.backupInfoRepoSize, 3159776, " repo size");
TEST_RESULT_INT(backupData.backupInfoRepoSizeDelta, 3159776, " repo delta");
TEST_RESULT_INT(backupData.backupInfoSize, 26897030, " backup size");
TEST_RESULT_INT(backupData.backupInfoSizeDelta, 26897030, " backup delta");
TEST_RESULT_INT(backupData.backupPgId, 1, " pg id");
TEST_RESULT_PTR(backupData.backupPrior, NULL, " backup prior NULL");
TEST_RESULT_PTR(backupData.backupReference, NULL, " backup reference NULL");
TEST_RESULT_INT(backupData.backupTimestampStart, 1482182846, " timestamp start");
TEST_RESULT_INT(backupData.backupTimestampStop, 1482182861, " timestamp stop");
backupData = infoBackupData(infoBackup, 1);
TEST_RESULT_STR(strPtr(backupData.backupLabel), "20161219-212741F_20161219-212803D", "diff backup label");
TEST_RESULT_STR(strPtr(backupData.backupType), "diff", " backup type diff");
TEST_RESULT_INT(backupData.backupInfoRepoSize, 3159811, " repo size");
TEST_RESULT_INT(backupData.backupInfoRepoSizeDelta, 15765, " repo delta");
TEST_RESULT_INT(backupData.backupInfoSize, 26897030, " backup size");
TEST_RESULT_INT(backupData.backupInfoSizeDelta, 163866, " backup delta");
TEST_RESULT_STR(strPtr(backupData.backupPrior), "20161219-212741F", " backup prior exists");
TEST_RESULT_BOOL(
(strLstSize(backupData.backupReference) == 1 && strLstExistsZ(backupData.backupReference, "20161219-212741F")), true,
" backup reference exists");
backupData = infoBackupData(infoBackup, 2);
TEST_RESULT_STR(strPtr(backupData.backupLabel), "20161219-212741F_20161219-212918I", "incr backup label");
TEST_RESULT_PTR(backupData.backupArchiveStart, NULL, " archive start NULL");
TEST_RESULT_PTR(backupData.backupArchiveStop, NULL, " archive stop NULL");
TEST_RESULT_STR(strPtr(backupData.backupType), "incr", " backup type incr");
TEST_RESULT_STR(strPtr(backupData.backupPrior), "20161219-212741F", " backup prior exists");
TEST_RESULT_BOOL(
(strLstSize(backupData.backupReference) == 2 && strLstExistsZ(backupData.backupReference, "20161219-212741F") &&
strLstExistsZ(backupData.backupReference, "20161219-212741F_20161219-212803D")), true, " backup reference exists");
TEST_RESULT_BOOL(backupData.optionArchiveCheck, true, " option archive check");
TEST_RESULT_BOOL(backupData.optionArchiveCopy, false, " option archive copy");
TEST_RESULT_BOOL(backupData.optionBackupStandby, false, " option backup standby");
TEST_RESULT_BOOL(backupData.optionChecksumPage, false, " option checksum page");
TEST_RESULT_BOOL(backupData.optionCompress, true, " option compress");
TEST_RESULT_BOOL(backupData.optionHardlink, false, " option hardlink");
TEST_RESULT_BOOL(backupData.optionOnline, true, " option online");
// infoBackupDataToLog
//--------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_STR(
strPtr(infoBackupDataToLog(&backupData)), "{label: 20161219-212741F_20161219-212918I, pgId: 1}", "check log format");
}
}

View File

@ -9,7 +9,7 @@ void
testRun(void)
{
// *****************************************************************************************************************************
if (testBegin("infoPgNew(), infoPgFree(), infoPgDataCurrent(), infoPgDataToLog(), infoPgAdd()"))
if (testBegin("infoPgNew(), infoPgFree(), infoPgDataCurrent(), infoPgDataToLog(), infoPgAdd(), infoPgIni()"))
{
String *content = NULL;
String *fileName = strNewFmt("%s/test.ini", testPath());
@ -139,6 +139,12 @@ testRun(void)
TEST_RESULT_INT(infoPgDataTest.catalogVersion, 201608131, " catalog-version set");
TEST_RESULT_INT(infoPgDataTest.controlVersion, 960, " control-version set");
// infoPgIni
//--------------------------------------------------------------------------------------------------------------------------
Ini *infoIni = NULL;
TEST_ASSIGN(infoIni, infoPgIni(infoPg), "get ini from infoPg");
TEST_RESULT_BOOL(strLstExists(iniSectionList(infoIni), strNew("backrest")), true, " section exists in ini");
// Errors
//--------------------------------------------------------------------------------------------------------------------------
TEST_ERROR(infoPgNew(storageLocal(), fileName, 10, cipherTypeNone, NULL), AssertError, "invalid InfoPg type 10");