pgbackrest.git / summary / log / commit / refs

commit    e3fcd8cd9e0be42a32fc4cbd2ae3db2c072eabcd
Author:   Stefan Fercot <stefan.fercot@enterprisedb.com>
Commit:   GitHub <noreply@github.com>
Date:     Thu Aug 31 20:36:52 2023 +0000

    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.


doc/xml/release.xml | 14 ++++++++++++++ src/command/backup/backup.c | 10 +++++++--- src/command/info/info.c | 16 ++++++++++++++-- src/common/lock.c | 16 ++++++++++++++++ src/common/lock.h | 6 +++++- test/src/module/command/infoTest.c | 8 ++++++-- test/src/module/common/lockTest.c | 27 ++++++++++++++++++--------- 7 files changed, 80 insertions(+), 17 deletions(-) diff --git a/doc/xml/release.xml b/doc/xml/release.xml index 1460d9922..35ec4c077 100644 --- a/doc/xml/release.xml +++ b/doc/xml/release.xml @@ -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"/> diff --git a/src/command/backup/backup.c b/src/command/backup/backup.c index f74e19e87..1422d38d5 100644 --- a/src/command/backup/backup.c +++ b/src/command/backup/backup.c @@ -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() { diff --git a/src/command/info/info.c b/src/command/info/info.c index 9f40f8e68..530490f7c 100644 --- a/src/command/info/info.c +++ b/src/command/info/info.c @@ -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; } } } diff --git a/src/common/lock.c b/src/common/lock.c index 5e27e3db4..76d049cff 100644 --- a/src/common/lock.c +++ b/src/common/lock.c @@ -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) diff --git a/src/common/lock.h b/src/common/lock.h index 950c8fc87..48df7a409 100644 --- a/src/common/lock.h +++ b/src/common/lock.h @@ -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, ...) \ diff --git a/test/src/module/command/infoTest.c b/test/src/module/command/infoTest.c index 86b2bd088..bd330b4f6 100644 --- a/test/src/module/command/infoTest.c +++ b/test/src/module/command/infoTest.c @@ -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\"" "}" "}," diff --git a/test/src/module/common/lockTest.c b/test/src/module/common/lockTest.c index 5407ef444..cd042b15c 100644 --- a/test/src/module/common/lockTest.c +++ b/test/src/module/common/lockTest.c @@ -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"); + TEST_RESULT_VOID( + lockWriteDataP( + lockTypeBackup, .percentComplete = VARUINT(5555), .sizeComplete = VARUINT64(1754824), .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)); - TEST_RESULT_UINT( - varUInt(lockReadFileData(backupLockFile, lockLocal.file[lockTypeBackup].fd).percentComplete), 5555, - "verify percentComplete"); - - TEST_RESULT_VOID(lockWriteDataP(lockTypeBackup, .percentComplete = VARUINT(8888)), "write lock data"); + 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)); - TEST_RESULT_UINT( - varUInt(lockReadFileData(backupLockFile, lockLocal.file[lockTypeBackup].fd).percentComplete), 8888, - "verify percentComplete"); + 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, [parent: fbd992adc7b1]