1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-07-15 01:04:37 +02:00

Add backup size completed/total to info command JSON output.

This allows for backup progress to be monitored by external processes, whereas before backup progress was only available via text output.
This commit is contained in:
Stefan Fercot
2023-08-31 22:36:52 +02:00
committed by GitHub
parent fbd992adc7
commit e3fcd8cd9e
7 changed files with 82 additions and 19 deletions

View File

@ -16,6 +16,20 @@
<release-list>
<release date="XXXX-XX-XX" version="2.48dev" title="Under Development">
<release-core-list>
<release-feature-list>
<release-item>
<github-issue id="2007"/>
<github-pull-request id="2141"/>
<release-item-contributor-list>
<release-item-contributor id="stefan.fercot"/>
<release-item-reviewer id="david.steele"/>
</release-item-contributor-list>
<p>Add backup size completed/total to <cmd>info</cmd> command <proper>JSON</proper> output.</p>
</release-item>
</release-feature-list>
<release-improvement-list>
<release-item>
<github-pull-request id="2057"/>

View File

@ -1585,7 +1585,9 @@ backupJobResult(
if (percentComplete - *currentPercentComplete > 10)
{
*currentPercentComplete = percentComplete;
lockWriteDataP(lockTypeBackup, .percentComplete = VARUINT(*currentPercentComplete));
lockWriteDataP(
lockTypeBackup, .percentComplete = VARUINT(*currentPercentComplete), .sizeComplete = VARUINT64(*sizeProgress),
.size = VARUINT64(sizeTotal));
}
}
MEM_CONTEXT_TEMP_END();
@ -2193,9 +2195,11 @@ backupProcess(
// Process jobs
uint64_t sizeProgress = 0;
// Initialize the percent complete to zero
// Initialize percent complete and bytes completed/total
unsigned int currentPercentComplete = 0;
lockWriteDataP(lockTypeBackup, .percentComplete = VARUINT(currentPercentComplete));
lockWriteDataP(
lockTypeBackup, .percentComplete = VARUINT(currentPercentComplete), .sizeComplete = VARUINT64(sizeProgress),
.size = VARUINT64(sizeTotal));
MEM_CONTEXT_TEMP_RESET_BEGIN()
{

View File

@ -75,6 +75,8 @@ VARIANT_STRDEF_STATIC(STATUS_KEY_LOCK_VAR, "lock");
VARIANT_STRDEF_STATIC(STATUS_KEY_LOCK_BACKUP_VAR, "backup");
VARIANT_STRDEF_STATIC(STATUS_KEY_LOCK_BACKUP_HELD_VAR, "held");
VARIANT_STRDEF_STATIC(STATUS_KEY_LOCK_BACKUP_PERCENT_COMPLETE_VAR, "pct-cplt");
VARIANT_STRDEF_STATIC(STATUS_KEY_LOCK_BACKUP_SIZE_COMPLETE_VAR, "size-cplt");
VARIANT_STRDEF_STATIC(STATUS_KEY_LOCK_BACKUP_SIZE_VAR, "size");
VARIANT_STRDEF_STATIC(STATUS_KEY_MESSAGE_VAR, "message");
#define INFO_STANZA_STATUS_OK "ok"
@ -134,6 +136,8 @@ typedef struct InfoStanzaRepo
bool backupLockChecked; // Has the check for a backup lock already been performed?
bool backupLockHeld; // Is backup lock held on the system where info command is run?
const Variant *percentComplete; // Percentage of backup complete * 100 (when not NULL)
const Variant *sizeComplete; // Completed size of the backup in bytes
const Variant *size; // Total size of the backup in bytes
InfoRepoData *repoList; // List of configured repositories
} InfoStanzaRepo;
@ -239,6 +243,12 @@ stanzaStatus(const int code, const InfoStanzaRepo *const stanzaData, Variant *st
if (stanzaData->percentComplete != NULL && cfgOptionStrId(cfgOptOutput) != CFGOPTVAL_OUTPUT_JSON)
kvPut(backupLockKv, STATUS_KEY_LOCK_BACKUP_PERCENT_COMPLETE_VAR, stanzaData->percentComplete);
if (stanzaData->sizeComplete != NULL)
kvPut(backupLockKv, STATUS_KEY_LOCK_BACKUP_SIZE_COMPLETE_VAR, stanzaData->sizeComplete);
if (stanzaData->size != NULL)
kvPut(backupLockKv, STATUS_KEY_LOCK_BACKUP_SIZE_VAR, stanzaData->size);
FUNCTION_TEST_RETURN_VOID();
}
@ -1290,8 +1300,10 @@ infoUpdateStanza(
if (stanzaRepo->backupLockHeld)
{
stanzaRepo->percentComplete =
lockRead(cfgOptionStr(cfgOptLockPath), stanzaRepo->name, lockTypeBackup).data.percentComplete;
const LockData lockData = lockRead(cfgOptionStr(cfgOptLockPath), stanzaRepo->name, lockTypeBackup).data;
stanzaRepo->percentComplete = lockData.percentComplete;
stanzaRepo->sizeComplete = lockData.sizeComplete;
stanzaRepo->size = lockData.size;
}
}
}

View File

@ -35,6 +35,8 @@ Constants
#define LOCK_KEY_EXEC_ID STRID6("execId", 0x12e0c56051)
#define LOCK_KEY_PERCENT_COMPLETE STRID6("pctCplt", 0x14310a140d01)
#define LOCK_KEY_PROCESS_ID STRID5("pid", 0x11300)
#define LOCK_KEY_SIZE_COMPLETE STRID6("szCplt", 0x50c4286931)
#define LOCK_KEY_SIZE STRID5("sz", 0x3530)
/***********************************************************************************************************************************
Lock type names
@ -152,6 +154,12 @@ lockReadFileData(const String *const lockFile, const int fd)
result.percentComplete = varNewUInt(jsonReadUInt(json));
result.processId = jsonReadInt(jsonReadKeyRequireStrId(json, LOCK_KEY_PROCESS_ID));
if (jsonReadKeyExpectStrId(json, LOCK_KEY_SIZE))
result.size = varNewUInt64(jsonReadUInt(json));
if (jsonReadKeyExpectStrId(json, LOCK_KEY_SIZE_COMPLETE))
result.sizeComplete = varNewUInt64(jsonReadUInt(json));
}
MEM_CONTEXT_PRIOR_END();
}
@ -266,6 +274,8 @@ lockWriteData(const LockType lockType, const LockWriteDataParam param)
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(ENUM, lockType);
FUNCTION_LOG_PARAM(VARIANT, param.percentComplete);
FUNCTION_LOG_PARAM(VARIANT, param.sizeComplete);
FUNCTION_LOG_PARAM(VARIANT, param.size);
FUNCTION_LOG_END();
ASSERT(lockType < lockTypeAll);
@ -285,6 +295,12 @@ lockWriteData(const LockType lockType, const LockWriteDataParam param)
jsonWriteInt(jsonWriteKeyStrId(json, LOCK_KEY_PROCESS_ID), getpid());
if (param.size != NULL)
jsonWriteUInt64(jsonWriteKeyStrId(json, LOCK_KEY_SIZE), varUInt64(param.size));
if (param.sizeComplete != NULL)
jsonWriteUInt64(jsonWriteKeyStrId(json, LOCK_KEY_SIZE_COMPLETE), varUInt64(param.sizeComplete));
jsonWriteObjectEnd(json);
if (lockType == lockTypeBackup && lockLocal.held)

View File

@ -24,7 +24,9 @@ typedef struct LockData
{
pid_t processId; // Process holding the lock
const String *execId; // Exec id of process holding the lock
Variant *percentComplete; // Percentage of backup complete * 100 (when not NULL)
const Variant *percentComplete; // Percentage of backup complete * 100 (when not NULL)
const Variant *sizeComplete; // Completed size of the backup in bytes
const Variant *size; // Total size of the backup in bytes
} LockData;
#include "common/time.h"
@ -65,6 +67,8 @@ typedef struct LockWriteDataParam
{
VAR_PARAM_HEADER;
const Variant *percentComplete; // Percentage of backup complete * 100 (when not NULL)
const Variant *sizeComplete; // Completed size of the backup in bytes
const Variant *size; // Total size of the backup in bytes
} LockWriteDataParam;
#define lockWriteDataP(lockType, ...) \

View File

@ -1025,7 +1025,11 @@ testRun(void)
{
lockInit(cfgOptionStr(cfgOptLockPath), STRDEF("999-ffffffff"), STRDEF("stanza2"), lockTypeBackup);
TEST_RESULT_INT_NE(lockAcquireP(), -1, "create backup/expire lock");
TEST_RESULT_VOID(lockWriteDataP(lockTypeBackup, .percentComplete = VARUINT(4545)), "write lock data");
TEST_RESULT_VOID(
lockWriteDataP(
lockTypeBackup, .percentComplete = VARUINT(4545), .sizeComplete = VARUINT64(1435765),
.size = VARUINT64(3159000)),
"write lock data");
// Notify parent that lock has been acquired
HRN_FORK_CHILD_NOTIFY_PUT();
@ -1365,7 +1369,7 @@ testRun(void)
"],"
"\"status\":{"
"\"code\":4,"
"\"lock\":{\"backup\":{\"held\":true}},"
"\"lock\":{\"backup\":{\"held\":true,\"size\":3159000,\"size-cplt\":1435765}},"
"\"message\":\"different across repos\""
"}"
"},"

View File

@ -224,21 +224,30 @@ testRun(void)
TEST_RESULT_PTR(
lockReadFileData(backupLockFile, lockLocal.file[lockTypeBackup].fd).percentComplete, NULL, "verify percentComplete");
TEST_RESULT_VOID(lockWriteDataP(lockTypeBackup, .percentComplete = VARUINT(5555)), "write lock data");
THROW_ON_SYS_ERROR_FMT(
lseek(lockLocal.file[lockTypeBackup].fd, 0, SEEK_SET) == -1, FileOpenError, STORAGE_ERROR_READ_SEEK, (uint64_t)0,
strZ(lockLocal.file[lockTypeBackup].name));
TEST_RESULT_UINT(
varUInt(lockReadFileData(backupLockFile, lockLocal.file[lockTypeBackup].fd).percentComplete), 5555,
"verify percentComplete");
TEST_RESULT_VOID(
lockWriteDataP(
lockTypeBackup, .percentComplete = VARUINT(5555), .sizeComplete = VARUINT64(1754824), .size = VARUINT64(3159000)),
"write lock data");
TEST_RESULT_VOID(lockWriteDataP(lockTypeBackup, .percentComplete = VARUINT(8888)), "write lock data");
THROW_ON_SYS_ERROR_FMT(
lseek(lockLocal.file[lockTypeBackup].fd, 0, SEEK_SET) == -1, FileOpenError, STORAGE_ERROR_READ_SEEK, (uint64_t)0,
strZ(lockLocal.file[lockTypeBackup].name));
TEST_RESULT_UINT(
varUInt(lockReadFileData(backupLockFile, lockLocal.file[lockTypeBackup].fd).percentComplete), 8888,
"verify percentComplete");
LockData lockDataResult = lockReadFileData(backupLockFile, lockLocal.file[lockTypeBackup].fd);
TEST_RESULT_UINT(varUInt(lockDataResult.percentComplete), 5555, "verify percentComplete");
TEST_RESULT_UINT(varUInt64(lockDataResult.sizeComplete), 1754824, "verify sizeProgress");
TEST_RESULT_UINT(varUInt64(lockDataResult.size), 3159000, "verify sizeTotal");
TEST_RESULT_VOID(
lockWriteDataP(
lockTypeBackup, .percentComplete = VARUINT(8888), .sizeComplete = VARUINT64(2807719), .size = VARUINT64(3159000)),
"write lock data");
THROW_ON_SYS_ERROR_FMT(
lseek(lockLocal.file[lockTypeBackup].fd, 0, SEEK_SET) == -1, FileOpenError, STORAGE_ERROR_READ_SEEK, (uint64_t)0,
strZ(lockLocal.file[lockTypeBackup].name));
lockDataResult = lockReadFileData(backupLockFile, lockLocal.file[lockTypeBackup].fd);
TEST_RESULT_UINT(varUInt(lockDataResult.percentComplete), 8888, "verify percentComplete");
TEST_RESULT_UINT(varUInt64(lockDataResult.sizeComplete), 2807719, "verify sizeProgress");
TEST_RESULT_UINT(varUInt64(lockDataResult.size), 3159000, "verify sizeTotal");
TEST_ERROR(
lockAcquireP(.returnOnNoLock = true), AssertError,