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

Add temporary mem contexts and fix a leak in the command/restore module.

restoreRecoveryConf() and restoreRecoveryWriteConf() do enough work to deserve their own memory contexts.

restoreFilePgPath() was leaking a String every time it was called, which could be a lot.

Also fix a spacing issue.
This commit is contained in:
David Steele 2022-04-25 15:03:37 -04:00
parent 4e7414d48f
commit 55a828f999

View File

@ -715,7 +715,7 @@ restoreManifestOwnerReplace(const String *const owner, const String *const owner
{ \
const String *owner = strLstGet(type##List, ownerIdx); \
\
if (type##Name() == NULL || !strEq(type##Name(), owner)) \
if (type##Name() == NULL || !strEq(type##Name(), owner)) \
LOG_WARN_FMT("unknown " #type " '%s' in backup manifest mapped to current " #type, strZ(owner)); \
} \
} \
@ -1664,35 +1664,29 @@ restoreRecoveryOption(unsigned int pgVersion)
// Helper to convert recovery options to text format
static String *
restoreRecoveryConf(unsigned int pgVersion, const String *restoreLabel)
restoreRecoveryConf(const unsigned int pgVersion, const String *const restoreLabel)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(UINT, pgVersion);
FUNCTION_LOG_PARAM(STRING, restoreLabel);
FUNCTION_LOG_END();
String *result = NULL;
String *const result = strNew();
MEM_CONTEXT_TEMP_BEGIN()
{
result = strCatFmt(strNew(), "# Recovery settings generated by " PROJECT_NAME " restore on %s\n", strZ(restoreLabel));
strCatFmt(result, "# Recovery settings generated by " PROJECT_NAME " restore on %s\n", strZ(restoreLabel));
// Output all recovery options
KeyValue *optionKv = restoreRecoveryOption(pgVersion);
const VariantList *optionKeyList = kvKeyList(optionKv);
const KeyValue *const optionKv = restoreRecoveryOption(pgVersion);
const VariantList *const optionKeyList = kvKeyList(optionKv);
for (unsigned int optionKeyIdx = 0; optionKeyIdx < varLstSize(optionKeyList); optionKeyIdx++)
{
const Variant *optionKey = varLstGet(optionKeyList, optionKeyIdx);
const Variant *const optionKey = varLstGet(optionKeyList, optionKeyIdx);
strCatFmt(result, "%s = '%s'\n", strZ(varStr(optionKey)), strZ(varStr(kvGet(optionKv, optionKey))));
}
// Move to prior context
MEM_CONTEXT_PRIOR_BEGIN()
{
result = strDup(result);
}
MEM_CONTEXT_PRIOR_END();
}
MEM_CONTEXT_TEMP_END();
@ -1701,7 +1695,7 @@ restoreRecoveryConf(unsigned int pgVersion, const String *restoreLabel)
// Helper to write recovery options into recovery.conf
static void
restoreRecoveryWriteConf(const Manifest *manifest, unsigned int pgVersion, const String *restoreLabel)
restoreRecoveryWriteConf(const Manifest *const manifest, const unsigned int pgVersion, const String *const restoreLabel)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(MANIFEST, manifest);
@ -1712,18 +1706,22 @@ restoreRecoveryWriteConf(const Manifest *manifest, unsigned int pgVersion, const
// Only write recovery.conf if recovery type != none
if (cfgOptionStrId(cfgOptType) != CFGOPTVAL_TYPE_NONE)
{
LOG_INFO_FMT("write %s", strZ(storagePathP(storagePg(), PG_FILE_RECOVERYCONF_STR)));
MEM_CONTEXT_TEMP_BEGIN()
{
LOG_INFO_FMT("write %s", strZ(storagePathP(storagePg(), PG_FILE_RECOVERYCONF_STR)));
// Use the data directory to set permissions and ownership for recovery file
const ManifestPath *dataPath = manifestPathFind(manifest, MANIFEST_TARGET_PGDATA_STR);
mode_t recoveryFileMode = dataPath->mode & (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
// Use the data directory to set permissions and ownership for recovery file
const ManifestPath *const dataPath = manifestPathFind(manifest, MANIFEST_TARGET_PGDATA_STR);
const mode_t recoveryFileMode = dataPath->mode & (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
// Write recovery.conf
storagePutP(
storageNewWriteP(
storagePgWrite(), PG_FILE_RECOVERYCONF_STR, .noCreatePath = true, .modeFile = recoveryFileMode, .noAtomic = true,
.noSyncPath = true, .user = dataPath->user, .group = dataPath->group),
BUFSTR(restoreRecoveryConf(pgVersion, restoreLabel)));
// Write recovery.conf
storagePutP(
storageNewWriteP(
storagePgWrite(), PG_FILE_RECOVERYCONF_STR, .noCreatePath = true, .modeFile = recoveryFileMode,
.noAtomic = true, .noSyncPath = true, .user = dataPath->user, .group = dataPath->group),
BUFSTR(restoreRecoveryConf(pgVersion, restoreLabel)));
}
MEM_CONTEXT_TEMP_END();
}
FUNCTION_LOG_RETURN_VOID();
@ -2087,7 +2085,7 @@ restoreFileZeroed(const String *manifestName, RegExp *zeroExp)
// Helper function to construct the absolute pg path for any file
static String *
restoreFilePgPath(const Manifest *manifest, const String *manifestName)
restoreFilePgPath(const Manifest *const manifest, const String *const manifestName)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(MANIFEST, manifest);
@ -2097,10 +2095,12 @@ restoreFilePgPath(const Manifest *manifest, const String *manifestName)
ASSERT(manifest != NULL);
ASSERT(manifestName != NULL);
String *result = strNewFmt("%s/%s", strZ(manifestTargetBase(manifest)->path), strZ(manifestPathPg(manifestName)));
String *const pathPg = manifestPathPg(manifestName);
String *const result = strNewFmt(
"%s/%s%s", strZ(manifestTargetBase(manifest)->path), strZ(pathPg),
strEqZ(manifestName, MANIFEST_TARGET_PGDATA "/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL) ? "." STORAGE_FILE_TEMP_EXT : "");
if (strEq(manifestName, STRDEF(MANIFEST_TARGET_PGDATA "/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL)))
result = strNewFmt("%s." STORAGE_FILE_TEMP_EXT, strZ(result));
strFree(pathPg);
FUNCTION_TEST_RETURN(STRING, result);
}