You've already forked pgbackrest
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:
@ -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"/>
|
||||
|
@ -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()
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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, ...) \
|
||||
|
@ -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\""
|
||||
"}"
|
||||
"},"
|
||||
|
@ -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,
|
||||
|
Reference in New Issue
Block a user