You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-07-15 01:04:37 +02:00
Split cfgLoad() into multiple functions to make testing easier.
Mainly this helps with unit tests that need to do log expect testing. Add harnessCfgLoad() test function, which allows a new config to be loaded for unit testing without resetting log functions, opening a log file, or taking locks.
This commit is contained in:
@ -47,6 +47,10 @@
|
|||||||
<p>Storage object improvements. Convert all functions to variadic functions. Enforce read-only storage. Add <code>storageLocalWrite()</code> helper function. Add <code>storageExists()</code>, <code>storagePathCreate()</code>, and <code>storageRemove()</code>. Add <code>StorageFile</code> object and <code>storageOpenRead()</code>/<code>storageOpenWrite()</code>. Abstract Posix driver code into a separate module. Add <code>storagePathRemove()</code> and use it in the Perl Posix driver.</p>
|
<p>Storage object improvements. Convert all functions to variadic functions. Enforce read-only storage. Add <code>storageLocalWrite()</code> helper function. Add <code>storageExists()</code>, <code>storagePathCreate()</code>, and <code>storageRemove()</code>. Add <code>StorageFile</code> object and <code>storageOpenRead()</code>/<code>storageOpenWrite()</code>. Abstract Posix driver code into a separate module. Add <code>storagePathRemove()</code> and use it in the Perl Posix driver.</p>
|
||||||
</release-item>
|
</release-item>
|
||||||
|
|
||||||
|
<release-item>
|
||||||
|
<p>Split <code>cfgLoad()</code> into multiple functions to make testing easier. Mainly this helps with unit tests that need to do log expect testing.</p>
|
||||||
|
</release-item>
|
||||||
|
|
||||||
<release-item>
|
<release-item>
|
||||||
<p>Allow <code>MemContext</code> objects to be copied to a new parent. This makes it easier to create objects and then copy them to another context when they are complete without having to worry about freeing them on error. Update <code>List</code>, <code>StringList</code>, and <code>Buffer</code> to allow moves. Update <code>Ini</code> and <code>Storage</code> to take advantage of moves.</p>
|
<p>Allow <code>MemContext</code> objects to be copied to a new parent. This makes it easier to create objects and then copy them to another context when they are complete without having to worry about freeing them on error. Update <code>List</code>, <code>StringList</code>, and <code>Buffer</code> to allow moves. Update <code>Ini</code> and <code>Storage</code> to take advantage of moves.</p>
|
||||||
</release-item>
|
</release-item>
|
||||||
@ -128,6 +132,10 @@
|
|||||||
<p>Move <id>archive-stop</id> and <id>expire</id> tests to the <id>mock</id> module. These are mock integration tests so they should be grouped with the other mock integration tests.</p>
|
<p>Move <id>archive-stop</id> and <id>expire</id> tests to the <id>mock</id> module. These are mock integration tests so they should be grouped with the other mock integration tests.</p>
|
||||||
</release-item>
|
</release-item>
|
||||||
|
|
||||||
|
<release-item>
|
||||||
|
<p>Add <code>harnessCfgLoad()</code> test function, which allows a new config to be loaded for unit testing without resetting log functions, opening a log file, or taking locks.</p>
|
||||||
|
</release-item>
|
||||||
|
|
||||||
<release-item>
|
<release-item>
|
||||||
<p>Include VM type in <id>gcov</id> path to avoid conflicts between VMs with different architectures.</p>
|
<p>Include VM type in <id>gcov</id> path to avoid conflicts between VMs with different architectures.</p>
|
||||||
</release-item>
|
</release-item>
|
||||||
|
@ -47,6 +47,7 @@ These includes are from the src directory. There is no Perl-specific code in th
|
|||||||
#include "config/config.h"
|
#include "config/config.h"
|
||||||
#include "config/define.h"
|
#include "config/define.h"
|
||||||
#include "config/load.h"
|
#include "config/load.h"
|
||||||
|
#include "config/parse.h"
|
||||||
#include "perl/config.h"
|
#include "perl/config.h"
|
||||||
#include "postgres/pageChecksum.h"
|
#include "postgres/pageChecksum.h"
|
||||||
#include "storage/driver/posix.h"
|
#include "storage/driver/posix.h"
|
||||||
|
@ -19,7 +19,11 @@ CODE:
|
|||||||
// This should run in a temp context but for some reason getopt_long gets upset when if gets called again after the previous
|
// This should run in a temp context but for some reason getopt_long gets upset when if gets called again after the previous
|
||||||
// arg list being freed. So, this is a memory leak but it is only used for testing, not production.
|
// arg list being freed. So, this is a memory leak but it is only used for testing, not production.
|
||||||
StringList *paramList = strLstNewSplitZ(strCat(strNew("pgbackrest|"), parseParam), "|");
|
StringList *paramList = strLstNewSplitZ(strCat(strNew("pgbackrest|"), parseParam), "|");
|
||||||
cfgLoadParam(strLstSize(paramList), strLstPtr(paramList), strNew(backrestBin));
|
|
||||||
|
// Don't use cfgLoad() because it has a lot of side effects that we don't want
|
||||||
|
configParse(strLstSize(paramList), strLstPtr(paramList));
|
||||||
|
cfgExeSet(strNew(backrestBin));
|
||||||
|
cfgLoadUpdateOption();
|
||||||
|
|
||||||
String *result = perlOptionJson();
|
String *result = perlOptionJson();
|
||||||
|
|
||||||
|
@ -45,17 +45,158 @@ cfgLoadLogSetting()
|
|||||||
logInit(logLevelConsole, logLevelStdErr, logLevelFile, logTimestamp);
|
logInit(logLevelConsole, logLevelStdErr, logLevelFile, logTimestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Update options that have complex rules
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
void
|
||||||
|
cfgLoadUpdateOption()
|
||||||
|
{
|
||||||
|
// Set default for repo-host-cmd
|
||||||
|
if (cfgOptionValid(cfgOptRepoHost) && cfgOptionTest(cfgOptRepoHost) &&
|
||||||
|
cfgOptionSource(cfgOptRepoHostCmd) == cfgSourceDefault)
|
||||||
|
{
|
||||||
|
cfgOptionDefaultSet(cfgOptRepoHostCmd, varNewStr(cfgExe()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set default for pg-host-cmd
|
||||||
|
if (cfgOptionValid(cfgOptPgHostCmd))
|
||||||
|
{
|
||||||
|
for (unsigned int optionIdx = 0; optionIdx < cfgOptionIndexTotal(cfgOptPgHost); optionIdx++)
|
||||||
|
{
|
||||||
|
if (cfgOptionTest(cfgOptPgHost + optionIdx) && cfgOptionSource(cfgOptPgHostCmd + optionIdx) == cfgSourceDefault)
|
||||||
|
cfgOptionDefaultSet(cfgOptPgHostCmd + optionIdx, varNewStr(cfgExe()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Protocol timeout should be greater than db timeout
|
||||||
|
if (cfgOptionTest(cfgOptDbTimeout) && cfgOptionTest(cfgOptProtocolTimeout) &&
|
||||||
|
cfgOptionDbl(cfgOptProtocolTimeout) <= cfgOptionDbl(cfgOptDbTimeout))
|
||||||
|
{
|
||||||
|
// If protocol-timeout is default then increase it to be greater than db-timeout
|
||||||
|
if (cfgOptionSource(cfgOptProtocolTimeout) == cfgSourceDefault)
|
||||||
|
cfgOptionSet(cfgOptProtocolTimeout, cfgSourceDefault, varNewDbl(cfgOptionDbl(cfgOptDbTimeout) + 30));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
THROW(OptionInvalidValueError,
|
||||||
|
"'%f' is not valid for '%s' option\nHINT '%s' option (%f) should be greater than '%s' option (%f).",
|
||||||
|
cfgOptionDbl(cfgOptProtocolTimeout), cfgOptionName(cfgOptProtocolTimeout),
|
||||||
|
cfgOptionName(cfgOptProtocolTimeout), cfgOptionDbl(cfgOptProtocolTimeout), cfgOptionName(cfgOptDbTimeout),
|
||||||
|
cfgOptionDbl(cfgOptDbTimeout));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure that repo and pg host settings are not both set - cannot both be remote
|
||||||
|
if (cfgOptionValid(cfgOptPgHost) && cfgOptionValid(cfgOptRepoHost))
|
||||||
|
{
|
||||||
|
bool pgHostFound = false;
|
||||||
|
|
||||||
|
for (unsigned int optionIdx = 0; optionIdx < cfgOptionIndexTotal(cfgOptPgHost); optionIdx++)
|
||||||
|
{
|
||||||
|
if (cfgOptionTest(cfgOptPgHost + optionIdx))
|
||||||
|
{
|
||||||
|
pgHostFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If a pg-host was found, see if a repo-host is configured
|
||||||
|
if (pgHostFound == true)
|
||||||
|
{
|
||||||
|
for (unsigned int optionIdx = 0; optionIdx < cfgOptionIndexTotal(cfgOptRepoHost); optionIdx++)
|
||||||
|
{
|
||||||
|
if (cfgOptionTest(cfgOptRepoHost + optionIdx))
|
||||||
|
THROW(ConfigError, "pg and repo hosts cannot both be configured as remote");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warn when repo-retention-full is not set on a configured repo
|
||||||
|
if (cfgOptionValid(cfgOptRepoRetentionFull))
|
||||||
|
{
|
||||||
|
for (unsigned int optionIdx = 0; optionIdx < cfgOptionIndexTotal(cfgOptRepoType); optionIdx++)
|
||||||
|
{
|
||||||
|
// If the repo-type is defined, then see if corresponding retention-full is set
|
||||||
|
if (cfgOptionTest(cfgOptRepoType + optionIdx) && !cfgOptionTest(cfgOptRepoRetentionFull + optionIdx))
|
||||||
|
{
|
||||||
|
LOG_WARN("option %s is not set, the repository may run out of space\n"
|
||||||
|
"HINT: to retain full backups indefinitely (without warning), set option '%s' to the maximum.",
|
||||||
|
cfgOptionName(cfgOptRepoRetentionFull + optionIdx),
|
||||||
|
cfgOptionName(cfgOptRepoRetentionFull + optionIdx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If archive retention is valid for the command, then set archive settings
|
||||||
|
if (cfgOptionValid(cfgOptRepoRetentionArchive))
|
||||||
|
{
|
||||||
|
// For each possible repo, check and adjust the settings as appropriate
|
||||||
|
for (unsigned int optionIdx = 0; optionIdx < cfgOptionIndexTotal(cfgOptRepoType); optionIdx++)
|
||||||
|
{
|
||||||
|
const String *archiveRetentionType = cfgOptionStr(cfgOptRepoRetentionArchiveType + optionIdx);
|
||||||
|
|
||||||
|
const String *msgArchiveOff = strNewFmt("WAL segments will not be expired: option '%s=%s' but",
|
||||||
|
cfgOptionName(cfgOptRepoRetentionArchiveType), strPtr(archiveRetentionType));
|
||||||
|
|
||||||
|
// If the archive retention is not explicitly set then determine what it should be defaulted to
|
||||||
|
// to.
|
||||||
|
if (!cfgOptionTest(cfgOptRepoRetentionArchive + optionIdx))
|
||||||
|
{
|
||||||
|
// If repo-retention-archive-type is default, then if repo-retention-full is set, set the repo-retention-archive
|
||||||
|
// to this value, else ignore archiving
|
||||||
|
if (strEqZ(archiveRetentionType, CFGOPTVAL_TMP_REPO_RETENTION_ARCHIVE_TYPE_FULL))
|
||||||
|
{
|
||||||
|
if (cfgOptionTest(cfgOptRepoRetentionFull + optionIdx))
|
||||||
|
{
|
||||||
|
cfgOptionSet(cfgOptRepoRetentionArchive + optionIdx, cfgSourceDefault,
|
||||||
|
varNewInt(cfgOptionInt(cfgOptRepoRetentionFull + optionIdx)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strEqZ(archiveRetentionType, CFGOPTVAL_TMP_REPO_RETENTION_ARCHIVE_TYPE_DIFF))
|
||||||
|
{
|
||||||
|
// if repo-retention-diff is set then user must have set it
|
||||||
|
if (cfgOptionTest(cfgOptRepoRetentionDiff + optionIdx))
|
||||||
|
{
|
||||||
|
cfgOptionSet(cfgOptRepoRetentionArchive + optionIdx, cfgSourceDefault,
|
||||||
|
varNewInt(cfgOptionInt(cfgOptRepoRetentionDiff + optionIdx)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_WARN("%s neither option '%s' nor option '%s' is set", strPtr(msgArchiveOff),
|
||||||
|
cfgOptionName(cfgOptRepoRetentionArchive + optionIdx),
|
||||||
|
cfgOptionName(cfgOptRepoRetentionDiff + optionIdx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (strEqZ(archiveRetentionType, CFGOPTVAL_TMP_REPO_RETENTION_ARCHIVE_TYPE_INCR))
|
||||||
|
{
|
||||||
|
LOG_WARN("%s option '%s' is not set", strPtr(msgArchiveOff),
|
||||||
|
cfgOptionName(cfgOptRepoRetentionArchive + optionIdx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// If repo-retention-archive is set then check repo-retention-archive-type and issue a warning if the
|
||||||
|
// corresponding setting is UNDEF since UNDEF means backups will not be expired but they should be in the
|
||||||
|
// practice of setting this value even though expiring the archive itself is OK and will be performed.
|
||||||
|
if ((strEqZ(archiveRetentionType, CFGOPTVAL_TMP_REPO_RETENTION_ARCHIVE_TYPE_DIFF)) &&
|
||||||
|
(!cfgOptionTest(cfgOptRepoRetentionDiff + optionIdx)))
|
||||||
|
{
|
||||||
|
LOG_WARN("option '%s' is not set for '%s=%s'\n"
|
||||||
|
"HINT: to retain differential backups indefinitely (without warning), set option '%s' to the maximum.",
|
||||||
|
cfgOptionName(cfgOptRepoRetentionDiff + optionIdx),
|
||||||
|
cfgOptionName(cfgOptRepoRetentionArchiveType + optionIdx),
|
||||||
|
CFGOPTVAL_TMP_REPO_RETENTION_ARCHIVE_TYPE_DIFF,
|
||||||
|
cfgOptionName(cfgOptRepoRetentionDiff + optionIdx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Load the configuration
|
Load the configuration
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
void
|
void
|
||||||
cfgLoad(unsigned int argListSize, const char *argList[])
|
cfgLoad(unsigned int argListSize, const char *argList[])
|
||||||
{
|
|
||||||
cfgLoadParam(argListSize, argList, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
cfgLoadParam(unsigned int argListSize, const char *argList[], String *exe)
|
|
||||||
{
|
{
|
||||||
MEM_CONTEXT_TEMP_BEGIN()
|
MEM_CONTEXT_TEMP_BEGIN()
|
||||||
{
|
{
|
||||||
@ -65,9 +206,17 @@ cfgLoadParam(unsigned int argListSize, const char *argList[], String *exe)
|
|||||||
// Load the log settings
|
// Load the log settings
|
||||||
cfgLoadLogSetting();
|
cfgLoadLogSetting();
|
||||||
|
|
||||||
// Only continue if a command was set. If no command is set then help will be displayed
|
// Neutralize the umask to make the repository file/path modes more consistent
|
||||||
|
if (cfgOptionValid(cfgOptNeutralUmask) && cfgOptionBool(cfgOptNeutralUmask))
|
||||||
|
umask(0000);
|
||||||
|
|
||||||
|
// If a command is set
|
||||||
if (cfgCommand() != cfgCmdNone)
|
if (cfgCommand() != cfgCmdNone)
|
||||||
{
|
{
|
||||||
|
// Acquire a lock if required
|
||||||
|
if (cfgLockRequired())
|
||||||
|
lockAcquire(cfgOptionStr(cfgOptLockPath), cfgOptionStr(cfgOptStanza), cfgLockType(), 0, true);
|
||||||
|
|
||||||
// Open the log file if this command logs to a file
|
// Open the log file if this command logs to a file
|
||||||
if (cfgLogFile())
|
if (cfgLogFile())
|
||||||
{
|
{
|
||||||
@ -79,156 +228,8 @@ cfgLoadParam(unsigned int argListSize, const char *argList[], String *exe)
|
|||||||
// Begin the command
|
// Begin the command
|
||||||
cmdBegin(true);
|
cmdBegin(true);
|
||||||
|
|
||||||
// If an exe was passed in then use it
|
// Update options that have complex rules
|
||||||
if (exe != NULL)
|
cfgLoadUpdateOption();
|
||||||
cfgExeSet(exe);
|
|
||||||
|
|
||||||
// Set default for repo-host-cmd
|
|
||||||
if (cfgOptionValid(cfgOptRepoHost) && cfgOptionTest(cfgOptRepoHost) &&
|
|
||||||
cfgOptionSource(cfgOptRepoHostCmd) == cfgSourceDefault)
|
|
||||||
{
|
|
||||||
cfgOptionDefaultSet(cfgOptRepoHostCmd, varNewStr(cfgExe()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set default for pg-host-cmd
|
|
||||||
if (cfgOptionValid(cfgOptPgHostCmd))
|
|
||||||
{
|
|
||||||
for (unsigned int optionIdx = 0; optionIdx < cfgOptionIndexTotal(cfgOptPgHost); optionIdx++)
|
|
||||||
{
|
|
||||||
if (cfgOptionTest(cfgOptPgHost + optionIdx) && cfgOptionSource(cfgOptPgHostCmd + optionIdx) == cfgSourceDefault)
|
|
||||||
cfgOptionDefaultSet(cfgOptPgHostCmd + optionIdx, varNewStr(cfgExe()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cfgLockRequired())
|
|
||||||
lockAcquire(cfgOptionStr(cfgOptLockPath), cfgOptionStr(cfgOptStanza), cfgLockType(), 0, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Neutralize the umask to make the repository file/path modes more consistent
|
|
||||||
if (cfgOptionValid(cfgOptNeutralUmask) && cfgOptionBool(cfgOptNeutralUmask))
|
|
||||||
umask(0000);
|
|
||||||
|
|
||||||
// Protocol timeout should be greater than db timeout
|
|
||||||
if (cfgOptionTest(cfgOptDbTimeout) && cfgOptionTest(cfgOptProtocolTimeout) &&
|
|
||||||
cfgOptionDbl(cfgOptProtocolTimeout) <= cfgOptionDbl(cfgOptDbTimeout))
|
|
||||||
{
|
|
||||||
// If protocol-timeout is default then increase it to be greater than db-timeout
|
|
||||||
if (cfgOptionSource(cfgOptProtocolTimeout) == cfgSourceDefault)
|
|
||||||
cfgOptionSet(cfgOptProtocolTimeout, cfgSourceDefault, varNewDbl(cfgOptionDbl(cfgOptDbTimeout) + 30));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
THROW(OptionInvalidValueError,
|
|
||||||
"'%f' is not valid for '%s' option\nHINT '%s' option (%f) should be greater than '%s' option (%f).",
|
|
||||||
cfgOptionDbl(cfgOptProtocolTimeout), cfgOptionName(cfgOptProtocolTimeout),
|
|
||||||
cfgOptionName(cfgOptProtocolTimeout), cfgOptionDbl(cfgOptProtocolTimeout), cfgOptionName(cfgOptDbTimeout),
|
|
||||||
cfgOptionDbl(cfgOptDbTimeout));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure that repo and pg host settings are not both set - cannot both be remote
|
|
||||||
if (cfgOptionValid(cfgOptPgHost) && cfgOptionValid(cfgOptRepoHost))
|
|
||||||
{
|
|
||||||
bool pgHostFound = false;
|
|
||||||
|
|
||||||
for (unsigned int optionIdx = 0; optionIdx < cfgOptionIndexTotal(cfgOptPgHost); optionIdx++)
|
|
||||||
{
|
|
||||||
if (cfgOptionTest(cfgOptPgHost + optionIdx))
|
|
||||||
{
|
|
||||||
pgHostFound = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If a pg-host was found, see if a repo-host is configured
|
|
||||||
if (pgHostFound == true)
|
|
||||||
{
|
|
||||||
for (unsigned int optionIdx = 0; optionIdx < cfgOptionIndexTotal(cfgOptRepoHost); optionIdx++)
|
|
||||||
{
|
|
||||||
if (cfgOptionTest(cfgOptRepoHost + optionIdx))
|
|
||||||
THROW(ConfigError, "pg and repo hosts cannot both be configured as remote");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Warn when repo-retention-full is not set on a configured repo
|
|
||||||
if (cfgOptionValid(cfgOptRepoRetentionFull))
|
|
||||||
{
|
|
||||||
for (unsigned int optionIdx = 0; optionIdx < cfgOptionIndexTotal(cfgOptRepoType); optionIdx++)
|
|
||||||
{
|
|
||||||
// If the repo-type is defined, then see if corresponding retention-full is set
|
|
||||||
if (cfgOptionTest(cfgOptRepoType + optionIdx) && !cfgOptionTest(cfgOptRepoRetentionFull + optionIdx))
|
|
||||||
{
|
|
||||||
LOG_WARN("option %s is not set, the repository may run out of space\n"
|
|
||||||
"HINT: to retain full backups indefinitely (without warning), set option '%s' to the maximum.",
|
|
||||||
cfgOptionName(cfgOptRepoRetentionFull + optionIdx),
|
|
||||||
cfgOptionName(cfgOptRepoRetentionFull + optionIdx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If archive retention is valid for the command, then set archive settings
|
|
||||||
if (cfgOptionValid(cfgOptRepoRetentionArchive))
|
|
||||||
{
|
|
||||||
// For each possible repo, check and adjust the settings as appropriate
|
|
||||||
for (unsigned int optionIdx = 0; optionIdx < cfgOptionIndexTotal(cfgOptRepoType); optionIdx++)
|
|
||||||
{
|
|
||||||
const String *archiveRetentionType = cfgOptionStr(cfgOptRepoRetentionArchiveType + optionIdx);
|
|
||||||
|
|
||||||
const String *msgArchiveOff = strNewFmt("WAL segments will not be expired: option '%s=%s' but",
|
|
||||||
cfgOptionName(cfgOptRepoRetentionArchiveType), strPtr(archiveRetentionType));
|
|
||||||
|
|
||||||
// If the archive retention is not explicitly set then determine what it should be defaulted to
|
|
||||||
// to.
|
|
||||||
if (!cfgOptionTest(cfgOptRepoRetentionArchive + optionIdx))
|
|
||||||
{
|
|
||||||
// If repo-retention-archive-type is default, then if repo-retention-full is set, set the repo-retention-archive
|
|
||||||
// to this value, else ignore archiving
|
|
||||||
if (strEqZ(archiveRetentionType, CFGOPTVAL_TMP_REPO_RETENTION_ARCHIVE_TYPE_FULL))
|
|
||||||
{
|
|
||||||
if (cfgOptionTest(cfgOptRepoRetentionFull + optionIdx))
|
|
||||||
{
|
|
||||||
cfgOptionSet(cfgOptRepoRetentionArchive + optionIdx, cfgSourceDefault,
|
|
||||||
varNewInt(cfgOptionInt(cfgOptRepoRetentionFull + optionIdx)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (strEqZ(archiveRetentionType, CFGOPTVAL_TMP_REPO_RETENTION_ARCHIVE_TYPE_DIFF))
|
|
||||||
{
|
|
||||||
// if repo-retention-diff is set then user must have set it
|
|
||||||
if (cfgOptionTest(cfgOptRepoRetentionDiff + optionIdx))
|
|
||||||
{
|
|
||||||
cfgOptionSet(cfgOptRepoRetentionArchive + optionIdx, cfgSourceDefault,
|
|
||||||
varNewInt(cfgOptionInt(cfgOptRepoRetentionDiff + optionIdx)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_WARN("%s neither option '%s' nor option '%s' is set", strPtr(msgArchiveOff),
|
|
||||||
cfgOptionName(cfgOptRepoRetentionArchive + optionIdx),
|
|
||||||
cfgOptionName(cfgOptRepoRetentionDiff + optionIdx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (strEqZ(archiveRetentionType, CFGOPTVAL_TMP_REPO_RETENTION_ARCHIVE_TYPE_INCR))
|
|
||||||
{
|
|
||||||
LOG_WARN("%s option '%s' is not set", strPtr(msgArchiveOff),
|
|
||||||
cfgOptionName(cfgOptRepoRetentionArchive + optionIdx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// If repo-retention-archive is set then check repo-retention-archive-type and issue a warning if the
|
|
||||||
// corresponding setting is UNDEF since UNDEF means backups will not be expired but they should be in the
|
|
||||||
// practice of setting this value even though expiring the archive itself is OK and will be performed.
|
|
||||||
if ((strEqZ(archiveRetentionType, CFGOPTVAL_TMP_REPO_RETENTION_ARCHIVE_TYPE_DIFF)) &&
|
|
||||||
(!cfgOptionTest(cfgOptRepoRetentionDiff + optionIdx)))
|
|
||||||
{
|
|
||||||
LOG_WARN("option '%s' is not set for '%s=%s'\n"
|
|
||||||
"HINT: to retain differential backups indefinitely (without warning), set option '%s' to the maximum.",
|
|
||||||
cfgOptionName(cfgOptRepoRetentionDiff + optionIdx),
|
|
||||||
cfgOptionName(cfgOptRepoRetentionArchiveType + optionIdx),
|
|
||||||
CFGOPTVAL_TMP_REPO_RETENTION_ARCHIVE_TYPE_DIFF,
|
|
||||||
cfgOptionName(cfgOptRepoRetentionDiff + optionIdx));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MEM_CONTEXT_TEMP_END();
|
MEM_CONTEXT_TEMP_END();
|
||||||
|
@ -8,7 +8,7 @@ Configuration Load
|
|||||||
Functions
|
Functions
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
void cfgLoad(unsigned int argListSize, const char *argList[]);
|
void cfgLoad(unsigned int argListSize, const char *argList[]);
|
||||||
void cfgLoadParam(unsigned int argListSize, const char *argList[], String *exe);
|
|
||||||
void cfgLoadLogSetting();
|
void cfgLoadLogSetting();
|
||||||
|
void cfgLoadUpdateOption();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -186,9 +186,6 @@ sub configTestLoad
|
|||||||
$self->testResult(
|
$self->testResult(
|
||||||
sub {configLoad(false, backrestBin(), cfgCommandName($iCommandId), \$strConfigJson)},
|
sub {configLoad(false, backrestBin(), cfgCommandName($iCommandId), \$strConfigJson)},
|
||||||
true, 'config load: ' . join(" ", @stryArg));
|
true, 'config load: ' . join(" ", @stryArg));
|
||||||
|
|
||||||
# Release any lock that was taken during configLoad.
|
|
||||||
lockRelease(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
21
test/src/common/harnessConfig.c
Normal file
21
test/src/common/harnessConfig.c
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/***********************************************************************************************************************************
|
||||||
|
Harness for Loading Test Configurations
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
#include "common/logTest.h"
|
||||||
|
|
||||||
|
#include "config/load.h"
|
||||||
|
#include "config/parse.h"
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Load a test configuration without any side effects
|
||||||
|
|
||||||
|
Log testing requires that log levels be set in a certain way but calls to cfgLoad() will reset that. Also there's no need to open
|
||||||
|
log files, acquire locks, etc.
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
void
|
||||||
|
harnessCfgLoad(unsigned int argListSize, const char *argList[])
|
||||||
|
{
|
||||||
|
configParse(argListSize, argList);
|
||||||
|
logInit(logLevelInfo, logLevelOff, logLevelOff, false);
|
||||||
|
cfgLoadUpdateOption();
|
||||||
|
}
|
8
test/src/common/harnessConfig.h
Normal file
8
test/src/common/harnessConfig.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
/***********************************************************************************************************************************
|
||||||
|
Harness for Loading Test Configurations
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Functions
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
void harnessCfgLoad(unsigned int argListSize, const char *argList[]);
|
@ -11,6 +11,11 @@ Log Test Harness
|
|||||||
|
|
||||||
#ifndef NO_LOG
|
#ifndef NO_LOG
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Has the log harness been init'd?
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
static bool harnessLogInit = false;
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Name of file where logs are stored for testing
|
Name of file where logs are stored for testing
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
@ -23,13 +28,18 @@ Initialize log for testing
|
|||||||
void
|
void
|
||||||
testLogInit()
|
testLogInit()
|
||||||
{
|
{
|
||||||
logInit(logLevelInfo, logLevelOff, logLevelOff, false);
|
if (!harnessLogInit)
|
||||||
|
{
|
||||||
|
logInit(logLevelInfo, logLevelOff, logLevelOff, false);
|
||||||
|
|
||||||
stdoutFile = strNewFmt("%s/stdout.log", testPath());
|
stdoutFile = strNewFmt("%s/stdout.log", testPath());
|
||||||
logHandleStdOut = open(strPtr(stdoutFile), O_WRONLY | O_CREAT | O_TRUNC, 0640);
|
logHandleStdOut = open(strPtr(stdoutFile), O_WRONLY | O_CREAT | O_TRUNC, 0640);
|
||||||
|
|
||||||
stderrFile = strNewFmt("%s/stderr.log", testPath());
|
stderrFile = strNewFmt("%s/stderr.log", testPath());
|
||||||
logHandleStdErr = open(strPtr(stderrFile), O_WRONLY | O_CREAT | O_TRUNC, 0640);
|
logHandleStdErr = open(strPtr(stderrFile), O_WRONLY | O_CREAT | O_TRUNC, 0640);
|
||||||
|
|
||||||
|
harnessLogInit = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
|
@ -6,6 +6,8 @@ Test Archive Push Command
|
|||||||
#include "config/load.h"
|
#include "config/load.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
|
#include "common/harnessConfig.h"
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Test Run
|
Test Run
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
@ -22,8 +24,7 @@ testRun()
|
|||||||
strLstAddZ(argList, "--archive-timeout=1");
|
strLstAddZ(argList, "--archive-timeout=1");
|
||||||
strLstAddZ(argList, "--stanza=db");
|
strLstAddZ(argList, "--stanza=db");
|
||||||
strLstAddZ(argList, "archive-push");
|
strLstAddZ(argList, "archive-push");
|
||||||
cfgLoad(strLstSize(argList), strLstPtr(argList));
|
harnessCfgLoad(strLstSize(argList), strLstPtr(argList));
|
||||||
logInit(logLevelInfo, logLevelOff, logLevelOff, false);
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
String *segment = strNew("000000010000000100000001");
|
String *segment = strNew("000000010000000100000001");
|
||||||
@ -114,8 +115,7 @@ testRun()
|
|||||||
strLstAddZ(argList, "--log-level-console=off");
|
strLstAddZ(argList, "--log-level-console=off");
|
||||||
strLstAddZ(argList, "--log-level-stderr=off");
|
strLstAddZ(argList, "--log-level-stderr=off");
|
||||||
strLstAdd(argList, strNewFmt("--pg1-path=%s/db", testPath()));
|
strLstAdd(argList, strNewFmt("--pg1-path=%s/db", testPath()));
|
||||||
cfgLoad(strLstSize(argList), strLstPtr(argList));
|
harnessCfgLoad(strLstSize(argList), strLstPtr(argList));
|
||||||
logInit(logLevelInfo, logLevelOff, logLevelOff, false);
|
|
||||||
|
|
||||||
TEST_ERROR(
|
TEST_ERROR(
|
||||||
cmdArchivePush(), ArchiveTimeoutError,
|
cmdArchivePush(), ArchiveTimeoutError,
|
||||||
|
@ -42,11 +42,6 @@ testRun()
|
|||||||
TEST_RESULT_INT(logLevelStdErr, logLevelError, "stderr logging is error");
|
TEST_RESULT_INT(logLevelStdErr, logLevelError, "stderr logging is error");
|
||||||
TEST_RESULT_INT(logLevelFile, logLevelOff, "file logging is off");
|
TEST_RESULT_INT(logLevelFile, logLevelOff, "file logging is off");
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
|
||||||
TEST_RESULT_VOID(cfgLoadParam(strLstSize(argList), strLstPtr(argList), strNew("pgbackrest2")), "load local config");
|
|
||||||
|
|
||||||
TEST_RESULT_STR(strPtr(cfgExe()), "pgbackrest2", "check exe");
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
argList = strLstNew();
|
argList = strLstNew();
|
||||||
strLstAdd(argList, strNew("pgbackrest"));
|
strLstAdd(argList, strNew("pgbackrest"));
|
||||||
|
Reference in New Issue
Block a user