1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-12 10:04:14 +02:00

Display size option default and allowed values with appropriate units.

Size option default and allowed values were displayed in bytes, which was confusing for the user.

This also lays the groundwork for adding units to time options.

Move option parsing functions into a common module so they can be used from the build module.
This commit is contained in:
David Steele 2021-11-03 15:23:08 -04:00 committed by GitHub
parent 1b93a77236
commit 038abaa71d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 285 additions and 219 deletions

View File

@ -64,6 +64,24 @@
</release-item>
</release-development-list>
</release-core-list>
<release-doc-list>
<release-improvement-list>
<release-item>
<commit subject="Centralize logic to build value lists during config rendering."/>
<commit subject="Display size option default and allowed values with appropriate units.">
<github-pull-request id="1557"/>
</commit>
<release-item-contributor-list>
<release-item-contributor id="david.steele"/>
<release-item-reviewer id="reid.thompson"/>
</release-item-contributor-list>
<p>Display size option default and allowed values with appropriate units.</p>
</release-item>
</release-improvement-list>
</release-doc-list>
</release>
<release date="2021-11-01" version="2.36" title="Minor Bug Fixes and Improvements">

View File

@ -39,6 +39,7 @@ SRCS_BUILD = \
common/type/xml.c \
common/user.c \
common/wait.c \
config/common.c \
storage/posix/read.c \
storage/posix/storage.c \
storage/posix/write.c \

View File

@ -581,19 +581,19 @@ option:
buffer-size:
section: global
type: size
default: 1048576
default: 1MiB
allow-list:
- 16384
- 32768
- 65536
- 131072
- 262144
- 524288
- 1048576
- 2097152
- 4194304
- 8388608
- 16777216
- 16KiB
- 32KiB
- 64KiB
- 128KiB
- 256KiB
- 512KiB
- 1MiB
- 2MiB
- 4MiB
- 8MiB
- 16MiB
command:
archive-get: {}
archive-push: {}
@ -1032,8 +1032,8 @@ option:
archive-get-queue-max:
section: global
type: size
default: 134217728
allow-range: [0, 4503599627370496]
default: 128MiB
allow-range: [0, 4PiB]
command:
archive-get: {}
command-role:
@ -1054,7 +1054,7 @@ option:
section: global
type: size
required: false
allow-range: [0, 4503599627370496]
allow-range: [0, 4PiB]
command:
archive-push: {}
command-role:
@ -1148,8 +1148,8 @@ option:
manifest-save-threshold:
section: global
type: size
default: 1073741824
allow-range: [1, 1099511627776]
default: 1GiB
allow-range: [1, 1TiB]
command:
backup: {}
command-role:

View File

@ -7,6 +7,7 @@ Render Configuration Data
#include "common/log.h"
#include "common/type/convert.h"
#include "config/common.h"
#include "storage/posix/storage.h"
#include "build/common/render.h"
@ -383,7 +384,11 @@ bldCfgRenderScalar(const String *const scalar, const String *const optType)
if (strEq(optType, OPT_TYPE_TIME_STR))
{
value = (int64_t)(cvtZToDouble(strZ(scalar)) * 1000);
value = cfgParseTime(scalar);
}
else if (strEq(optType, OPT_TYPE_SIZE_STR))
{
value = cfgParseSize(scalar);
}
else
{
@ -515,7 +520,9 @@ bldCfgRenderValueAdd(
const String *const optType, const String *const value, StringList *const ruleDataList, StringList *const ruleStrList)
{
if (strEq(optType, OPT_TYPE_TIME_STR))
strLstAddIfMissing(ruleDataList, strNewFmt("%" PRId64, (int64_t)(cvtZToDouble(strZ(value)) * 1000)));
strLstAddIfMissing(ruleDataList, strNewFmt("%" PRId64, cfgParseTime(value)));
else if (strEq(optType, OPT_TYPE_SIZE_STR))
strLstAddIfMissing(ruleDataList, strNewFmt("%" PRId64, cfgParseSize(value)));
else
strLstAddIfMissing(ruleDataList, value);

View File

@ -132,12 +132,13 @@
<text>
<p>Buffer size used for copy, compress, encrypt, and other operations. The number of buffers used depends on options and each operation may use additional memory, e.g. <id>gz</id> compression may use an additional 256KiB of memory.</p>
<p>Size can be entered in bytes (default) or KB, MB, GB, TB, or PB where the multiplier is a power of 1024. For example, the case-insensitive value 32k (or 32KB) can be used instead of 32768.</p>
<!-- Be sure to update other copies of this block when modifying -->
<p>Size can be entered in bytes (default) or KiB, MiB, GiB, TiB, or PiB where the multiplier is a power of 1024. For example, the case-insensitive value 5GiB (or 5GB, 5g) can be used instead of 5368709120. Fractional values such as 2.5GiB are not allowed, use 2560MiB instead.</p>
<p>Allowed values, in bytes, are <id>16384</id>, <id>32768</id>, <id>65536</id>, <id>131072</id>, <id>262144</id>, <id>524288</id>, <id>1048576</id>, <id>2097152</id>, <id>4194304</id>, <id>8388608</id>, and <id>16777216</id>.</p>
<p>Allowed values are <id>16KiB</id>, <id>32KiB</id>, <id>64KiB</id>, <id>128KiB</id>, <id>256KiB</id>, <id>512KiB</id>, <id>1MiB</id>, <id>2MiB</id>, <id>4MiB</id>, <id>8MiB</id>, and <id>16MiB</id>.</p>
</text>
<example>32K</example>
<example>2MiB</example>
</config-key>
<!-- CONFIG - GENERAL SECTION - CMD KEY -->
@ -1138,10 +1139,11 @@
<text>
<p>Defines how often the manifest will be saved during a backup. Saving the manifest is important because it stores the checksums and allows the resume function to work efficiently. The actual threshold used is 1% of the backup size or <setting>manifest-save-threshold</setting>, whichever is greater.</p>
<p>Size can be entered in bytes (default) or KB, MB, GB, TB, or PB where the multiplier is a power of 1024.</p>
<!-- Be sure to update other copies of this block when modifying -->
<p>Size can be entered in bytes (default) or KiB, MiB, GiB, TiB, or PiB where the multiplier is a power of 1024. For example, the case-insensitive value 5GiB (or 5GB, 5g) can be used instead of 5368709120. Fractional values such as 2.5GiB are not allowed, use 2560MiB instead.</p>
</text>
<example>5G</example>
<example>8GiB</example>
</config-key>
<!-- CONFIG - BACKUP SECTION - EXPIRE-AUTO -->
@ -1225,10 +1227,11 @@
<text>
<p>Specifies the maximum size of the <cmd>archive-get</cmd> queue when <br-option>archive-async</br-option> is enabled. The queue is stored in the <br-option>spool-path</br-option> and is used to speed providing WAL to <postgres/>.</p>
<p>Size can be entered in bytes (default) or KB, MB, GB, TB, or PB where the multiplier is a power of 1024.</p>
<!-- Be sure to update other copies of this block when modifying -->
<p>Size can be entered in bytes (default) or KiB, MiB, GiB, TiB, or PiB where the multiplier is a power of 1024. For example, the case-insensitive value 5GiB (or 5GB, 5g) can be used instead of 5368709120. Fractional values such as 2.5GiB are not allowed, use 2560MiB instead.</p>
</text>
<example>1073741824</example>
<example>1GiB</example>
</config-key>
<!-- ======================================================================================================= -->
@ -1262,10 +1265,11 @@
<p>The purpose of this feature is to prevent the log volume from filling up at which point Postgres will stop completely. Better to lose the backup than have <postgres/> go down.</p>
<p>Size can be entered in bytes (default) or KB, MB, GB, TB, or PB where the multiplier is a power of 1024.</p>
<!-- Be sure to update other copies of this block when modifying -->
<p>Size can be entered in bytes (default) or KiB, MiB, GiB, TiB, or PiB where the multiplier is a power of 1024. For example, the case-insensitive value 5GiB (or 5GB, 5g) can be used instead of 5368709120. Fractional values such as 2.5GiB are not allowed, use 2560MiB instead.</p>
</text>
<example>1GB</example>
<example>1TiB</example>
</config-key>
<!-- ======================================================================================================= -->

View File

@ -150,61 +150,65 @@ helpRenderText(const String *text, const bool internal, size_t indent, bool inde
Helper function for helpRender() to output values as strings
***********************************************************************************************************************************/
static const String *
helpRenderValue(const Variant *value, ConfigOptionType type)
helpRenderValue(const ConfigOption optionId, const unsigned int optionIdx)
{
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(VARIANT, value);
FUNCTION_LOG_PARAM(ENUM, type);
FUNCTION_LOG_PARAM(ENUM, optionId);
FUNCTION_LOG_PARAM(UINT, optionIdx);
FUNCTION_LOG_END();
const String *result = NULL;
if (value != NULL)
if (cfgOptionIdxSource(optionId, 0) != cfgSourceDefault)
{
if (varType(value) == varTypeBool)
{
if (varBool(value))
result = Y_STR;
else
result = N_STR;
}
else if (varType(value) == varTypeKeyValue)
{
String *resultTemp = strNew();
const Variant *const value = cfgOptionIdxVar(optionId, optionIdx);
ASSERT(value != NULL);
const KeyValue *optionKv = varKv(value);
const VariantList *keyList = kvKeyList(optionKv);
for (unsigned int keyIdx = 0; keyIdx < varLstSize(keyList); keyIdx++)
switch (varType(value))
{
case varTypeKeyValue:
{
if (keyIdx != 0)
strCatZ(resultTemp, ", ");
String *resultTemp = strNew();
strCatFmt(
resultTemp, "%s=%s", strZ(varStr(varLstGet(keyList, keyIdx))),
strZ(varStrForce(kvGet(optionKv, varLstGet(keyList, keyIdx)))));
const KeyValue *optionKv = varKv(value);
const VariantList *keyList = kvKeyList(optionKv);
for (unsigned int keyIdx = 0; keyIdx < varLstSize(keyList); keyIdx++)
{
if (keyIdx != 0)
strCatZ(resultTemp, ", ");
strCatFmt(
resultTemp, "%s=%s", strZ(varStr(varLstGet(keyList, keyIdx))),
strZ(varStrForce(kvGet(optionKv, varLstGet(keyList, keyIdx)))));
}
result = resultTemp;
break;
}
result = resultTemp;
}
else if (varType(value) == varTypeVariantList)
{
String *resultTemp = strNew();
const VariantList *list = varVarLst(value);
for (unsigned int listIdx = 0; listIdx < varLstSize(list); listIdx++)
case varTypeVariantList:
{
if (listIdx != 0)
strCatZ(resultTemp, ", ");
String *resultTemp = strNew();
strCatFmt(resultTemp, "%s", strZ(varStr(varLstGet(list, listIdx))));
const VariantList *list = varVarLst(value);
for (unsigned int listIdx = 0; listIdx < varLstSize(list); listIdx++)
{
if (listIdx != 0)
strCatZ(resultTemp, ", ");
strCatFmt(resultTemp, "%s", strZ(varStr(varLstGet(list, listIdx))));
}
result = resultTemp;
break;
}
result = resultTemp;
default:
result = cfgOptionIdxDisplay(optionId, optionIdx);
break;
}
else
result = cfgOptionDisplayVar(value, type);
}
FUNCTION_LOG_RETURN_CONST(STRING, result);
@ -450,10 +454,7 @@ helpRender(const Buffer *const helpData)
// Output current and default values if they exist
const String *defaultValue = cfgOptionDefault(optionId);
const String *value = NULL;
if (cfgOptionIdxSource(optionId, 0) != cfgSourceDefault)
value = helpRenderValue(cfgOptionIdxVar(optionId, 0), cfgParseOptionType(optionId));
const String *value = helpRenderValue(optionId, 0);
if (value != NULL || defaultValue != NULL)
{
@ -517,10 +518,7 @@ helpRender(const Buffer *const helpData)
// Output current and default values if they exist
const String *defaultValue = cfgOptionDefault(option.id);
const String *value = NULL;
if (cfgOptionIdxSource(option.id, 0) != cfgSourceDefault)
value = helpRenderValue(cfgOptionIdxVar(option.id, 0), cfgParseOptionType(option.id));
const String *value = helpRenderValue(option.id, 0);
if (value != NULL || defaultValue != NULL)
{

121
src/config/common.c Normal file
View File

@ -0,0 +1,121 @@
/***********************************************************************************************************************************
Configuration Common
***********************************************************************************************************************************/
#include "build.auto.h"
#include "common/debug.h"
#include "common/regExp.h"
#include "common/time.h"
#include "config/common.h"
/**********************************************************************************************************************************/
// Helper to get the multiplier based on the qualifier
static int64_t
cfgParseSizeQualifier(const char qualifier)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(CHAR, qualifier);
FUNCTION_TEST_END();
int64_t result;
switch (qualifier)
{
case 'b':
result = 1;
break;
case 'k':
result = 1024;
break;
case 'm':
result = 1024 * 1024;
break;
case 'g':
result = 1024 * 1024 * 1024;
break;
case 't':
result = 1024LL * 1024LL * 1024LL * 1024LL;
break;
case 'p':
result = 1024LL * 1024LL * 1024LL * 1024LL * 1024LL;
break;
default:
THROW_FMT(AssertError, "'%c' is not a valid size qualifier", qualifier);
}
FUNCTION_TEST_RETURN(result);
}
int64_t
cfgParseSize(const String *const value)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(STRING, value);
FUNCTION_TEST_END();
ASSERT(value != NULL);
// Lowercase the value
String *valueLower = strLower(strDup(value));
// Match the value against possible values
if (regExpMatchOne(STRDEF("^[0-9]+(kib|kb|k|mib|mb|m|gib|gb|g|tib|tb|t|pib|pb|p|b)*$"), valueLower))
{
// Get the character array and size
const char *strArray = strZ(valueLower);
size_t size = strSize(valueLower);
int chrPos = -1;
// If there is a 'b' on the end, then see if the previous character is a number
if (strArray[size - 1] == 'b')
{
// If the previous character is a number, then the letter to look at is 'b' which is the last position else it is in the
// next to last position (e.g. kb - so the 'k' is the position of interest). Only need to test for <= 9 since the regex
// enforces the format. Also allow an 'i' before the 'b'.
if (strArray[size - 2] <= '9')
chrPos = (int)(size - 1);
else if (strArray[size - 2] == 'i')
chrPos = (int)(size - 3);
else
chrPos = (int)(size - 2);
}
// Else if there is no 'b' at the end but the last position is not a number then it must be one of the letters, e.g. 'k'
else if (strArray[size - 1] > '9')
chrPos = (int)(size - 1);
int64_t multiplier = 1;
// If a letter was found calculate multiplier, else do nothing since assumed value is already in bytes
if (chrPos != -1)
{
multiplier = cfgParseSizeQualifier(strArray[chrPos]);
// Remove any letters
strTrunc(valueLower, chrPos);
}
// Convert string to bytes
FUNCTION_TEST_RETURN(cvtZToInt64(strZ(valueLower)) * multiplier);
}
THROW_FMT(FormatError, "value '%s' is not valid", strZ(value));
}
/**********************************************************************************************************************************/
int64_t
cfgParseTime(const String *const value)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(STRING, value);
FUNCTION_TEST_END();
ASSERT(value != NULL);
FUNCTION_TEST_RETURN((int64_t)(cvtZToDouble(strZ(value)) * MSEC_PER_SEC));
}

18
src/config/common.h Normal file
View File

@ -0,0 +1,18 @@
/***********************************************************************************************************************************
Configuration Common
***********************************************************************************************************************************/
#ifndef CONFIG_COMMON_H
#define CONFIG_COMMON_H
#include "common/type/string.h"
/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
// Parse option size, e.g. 23m
int64_t cfgParseSize(const String *value);
// Parse option time, e.g. 900
int64_t cfgParseTime(const String *value);
#endif

View File

@ -114,7 +114,11 @@ cfgExecParam(ConfigCommand commandId, ConfigCommandRole commandRoleId, const Key
else
{
valueList = strLstNew();
strLstAdd(valueList, cfgOptionDisplayVar(value, cfgParseOptionType(optionId)));
strLstAdd(
valueList,
exists ? cfgOptionDisplayVar(value, cfgParseOptionType(optionId)) :
cfgOptionIdxDisplay(optionId, optionIdx));
}
// Output options and values

View File

@ -16,12 +16,12 @@ static const StringPub parseRuleValueStr[] =
PARSE_RULE_STRPUB("/var/log/pgbackrest"),
PARSE_RULE_STRPUB("/var/spool/pgbackrest"),
PARSE_RULE_STRPUB("1"),
PARSE_RULE_STRPUB("1048576"),
PARSE_RULE_STRPUB("1073741824"),
PARSE_RULE_STRPUB("134217728"),
PARSE_RULE_STRPUB("128MiB"),
PARSE_RULE_STRPUB("15"),
PARSE_RULE_STRPUB("1800"),
PARSE_RULE_STRPUB("1830"),
PARSE_RULE_STRPUB("1GiB"),
PARSE_RULE_STRPUB("1MiB"),
PARSE_RULE_STRPUB("2"),
PARSE_RULE_STRPUB("3"),
PARSE_RULE_STRPUB("443"),
@ -63,12 +63,12 @@ typedef enum
parseRuleValStrQT_FS_var_FS_log_FS_pgbackrest_QT,
parseRuleValStrQT_FS_var_FS_spool_FS_pgbackrest_QT,
parseRuleValStrQT_1_QT,
parseRuleValStrQT_1048576_QT,
parseRuleValStrQT_1073741824_QT,
parseRuleValStrQT_134217728_QT,
parseRuleValStrQT_128MiB_QT,
parseRuleValStrQT_15_QT,
parseRuleValStrQT_1800_QT,
parseRuleValStrQT_1830_QT,
parseRuleValStrQT_1GiB_QT,
parseRuleValStrQT_1MiB_QT,
parseRuleValStrQT_2_QT,
parseRuleValStrQT_3_QT,
parseRuleValStrQT_443_QT,
@ -848,7 +848,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] =
PARSE_RULE_OPTIONAL_DEFAULT
(
PARSE_RULE_VAL_INT(parseRuleValInt134217728),
PARSE_RULE_VAL_STR(parseRuleValStrQT_134217728_QT),
PARSE_RULE_VAL_STR(parseRuleValStrQT_128MiB_QT),
),
),
),
@ -1138,7 +1138,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] =
PARSE_RULE_OPTIONAL_DEFAULT
(
PARSE_RULE_VAL_INT(parseRuleValInt1048576),
PARSE_RULE_VAL_STR(parseRuleValStrQT_1048576_QT),
PARSE_RULE_VAL_STR(parseRuleValStrQT_1MiB_QT),
),
),
),
@ -2896,7 +2896,7 @@ static const ParseRuleOption parseRuleOption[CFG_OPTION_TOTAL] =
PARSE_RULE_OPTIONAL_DEFAULT
(
PARSE_RULE_VAL_INT(parseRuleValInt1073741824),
PARSE_RULE_VAL_STR(parseRuleValStrQT_1073741824_QT),
PARSE_RULE_VAL_STR(parseRuleValStrQT_1GiB_QT),
),
),
),

View File

@ -16,6 +16,7 @@ Command and Option Parse
#include "common/macro.h"
#include "common/memContext.h"
#include "common/regExp.h"
#include "config/common.h"
#include "config/config.intern.h"
#include "config/parse.h"
#include "version.h"
@ -1142,104 +1143,6 @@ cfgParseOptionValid(ConfigCommand commandId, ConfigCommandRole commandRoleId, Co
FUNCTION_TEST_RETURN(parseRuleOption[optionId].commandRoleValid[commandRoleId] & ((uint32_t)1 << commandId));
}
/***********************************************************************************************************************************
Generate multiplier based on character
***********************************************************************************************************************************/
static uint64_t
sizeQualifierToMultiplier(char qualifier)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(CHAR, qualifier);
FUNCTION_TEST_END();
uint64_t result;
switch (qualifier)
{
case 'b':
result = 1;
break;
case 'k':
result = 1024;
break;
case 'm':
result = 1024 * 1024;
break;
case 'g':
result = 1024 * 1024 * 1024;
break;
case 't':
result = 1024LL * 1024LL * 1024LL * 1024LL;
break;
case 'p':
result = 1024LL * 1024LL * 1024LL * 1024LL * 1024LL;
break;
default:
THROW_FMT(AssertError, "'%c' is not a valid size qualifier", qualifier);
}
FUNCTION_TEST_RETURN(result);
}
static uint64_t
convertToByte(const String *value)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(STRING, value);
FUNCTION_TEST_END();
ASSERT(value != NULL);
// Lowercase the value
String *valueLower = strLower(strDup(value));
// Match the value against possible values
if (regExpMatchOne(STRDEF("^[0-9]+(kb|k|mb|m|gb|g|tb|t|pb|p|b)*$"), valueLower))
{
// Get the character array and size
const char *strArray = strZ(valueLower);
size_t size = strSize(valueLower);
int chrPos = -1;
// If there is a 'b' on the end, then see if the previous character is a number
if (strArray[size - 1] == 'b')
{
// If the previous character is a number, then the letter to look at is 'b' which is the last position else it is in the
// next to last position (e.g. kb - so the 'k' is the position of interest). Only need to test for <= 9 since the regex
// enforces the format.
if (strArray[size - 2] <= '9')
chrPos = (int)(size - 1);
else
chrPos = (int)(size - 2);
}
// else if there is no 'b' at the end but the last position is not a number then it must be one of the letters, e.g. 'k'
else if (strArray[size - 1] > '9')
chrPos = (int)(size - 1);
uint64_t multiplier = 1;
// If a letter was found calculate multiplier, else do nothing since assumed value is already in bytes
if (chrPos != -1)
{
multiplier = sizeQualifierToMultiplier(strArray[chrPos]);
// Remove any letters
strTrunc(valueLower, chrPos);
}
// Convert string to bytes
FUNCTION_TEST_RETURN(cvtZToUInt64(strZ(valueLower)) * multiplier);
}
else
THROW_FMT(FormatError, "value '%s' is not valid", strZ(value));
}
/***********************************************************************************************************************************
Load the configuration file(s)
@ -2240,16 +2143,14 @@ configParse(const Storage *storage, unsigned int argListSize, const char *argLis
break;
case cfgOptTypeSize:
configOptionValue->value.integer = (int64_t)convertToByte(value);
valueAllow = varStrForce(VARINT64(configOptionValue->value.integer));
configOptionValue->value.integer = cfgParseSize(value);
break;
default:
{
ASSERT(optionType == cfgOptTypeTime);
configOptionValue->value.integer = (int64_t)(cvtZToDouble(
strZ(value)) * MSEC_PER_SEC);
configOptionValue->value.integer = cfgParseTime(value);
break;
}
}

View File

@ -386,6 +386,7 @@ unit:
depend:
- command/backup/pageChecksum
- common/lock
- config/common
- config/config
- config/parse
- config/exec
@ -483,6 +484,7 @@ unit:
total: 6
coverage:
- config/common
- config/config
- config/parse
- config/parse.auto: noCode
@ -770,7 +772,7 @@ unit:
# ----------------------------------------------------------------------------------------------------------------------------
- name: help
total: 5
total: 4
coverage:
- command/help/help

View File

@ -119,17 +119,6 @@ testRun(void)
"two paragraphs, indent first, internal");
}
// *****************************************************************************************************************************
if (testBegin("helpRenderValue()"))
{
TEST_RESULT_STR_Z(helpRenderValue(varNewBool(true), cfgOptTypeBoolean), "y", "boolean y");
TEST_RESULT_STR_Z(helpRenderValue(varNewBool(false), cfgOptTypeBoolean), "n", "boolean n");
TEST_RESULT_STR_Z(helpRenderValue(varNewStrZ("test-string"), cfgOptTypeString), "test-string", "string");
TEST_RESULT_STR_Z(helpRenderValue(varNewInt64(1234), cfgOptTypeInteger), "1234", "int");
TEST_RESULT_STR_Z(helpRenderValue(varNewInt64(1234000), cfgOptTypeTime), "1234", "time");
TEST_RESULT_STR_Z(helpRenderValue(NULL, cfgOptTypeString), NULL, "null");
}
// *****************************************************************************************************************************
if (testBegin("helpRender()"))
{
@ -222,7 +211,7 @@ testRun(void)
"General Options:\n"
"\n"
" --buffer-size buffer size for I/O operations\n"
" [current=32768, default=1048576]\n"
" [current=32768, default=1MiB]\n"
" --cmd pgBackRest command\n"
" [default=/path/to/pgbackrest]\n"
" --cmd-ssh SSH client command [default=ssh]\n"
@ -372,12 +361,13 @@ testRun(void)
"of buffers used depends on options and each operation may use additional\n"
"memory, e.g. gz compression may use an additional 256KiB of memory.\n"
"\n"
"Size can be entered in bytes (default) or KB, MB, GB, TB, or PB where the\n"
"multiplier is a power of 1024. For example, the case-insensitive value 32k (or\n"
"32KB) can be used instead of 32768.\n"
"Size can be entered in bytes (default) or KiB, MiB, GiB, TiB, or PiB where the\n"
"multiplier is a power of 1024. For example, the case-insensitive value 5GiB (or\n"
"5GB, 5g) can be used instead of 5368709120. Fractional values such as 2.5GiB\n"
"are not allowed, use 2560MiB instead.\n"
"\n"
"Allowed values, in bytes, are 16384, 32768, 65536, 131072, 262144, 524288,\n"
"1048576, 2097152, 4194304, 8388608, and 16777216.\n",
"Allowed values are 16KiB, 32KiB, 64KiB, 128KiB, 256KiB, 512KiB, 1MiB, 2MiB,\n"
"4MiB, 8MiB, and 16MiB.\n",
helpVersion));
argList = strLstNew();
@ -386,13 +376,13 @@ testRun(void)
strLstAddZ(argList, "archive-push");
strLstAddZ(argList, "buffer-size");
TEST_RESULT_VOID(testCfgLoad(argList), "help for archive-push command, buffer-size option");
TEST_RESULT_STR(helpRender(helpData), strNewFmt("%s\ndefault: 1048576\n", optionHelp), "check text");
TEST_RESULT_STR(helpRender(helpData), strNewFmt("%s\ndefault: 1MiB\n", optionHelp), "check text");
// Set a current value
hrnCfgArgRawZ(argList, cfgOptBufferSize, "32768");
hrnCfgArgRawZ(argList, cfgOptBufferSize, "32k");
TEST_RESULT_VOID(testCfgLoad(argList), "help for archive-push command, buffer-size option");
TEST_RESULT_STR(
helpRender(helpData), strNewFmt("%s\ncurrent: 32768\ndefault: 1048576\n", optionHelp), "check text, current value");
helpRender(helpData), strNewFmt("%s\ncurrent: 32k\ndefault: 1MiB\n", optionHelp), "check text, current value");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("deprecated host option names");

View File

@ -18,6 +18,7 @@ testRun(void)
StringList *argList = strLstNew();
hrnCfgArgRawZ(argList, cfgOptStanza, "test1");
hrnCfgArgRawZ(argList, cfgOptArchiveTimeout, "5");
hrnCfgArgRawZ(argList, cfgOptBufferSize, "64KiB");
hrnCfgArgRawZ(argList, cfgOptRepoPath, TEST_PATH "/repo");
hrnCfgArgKeyRawZ(argList, cfgOptPgPath, 1, TEST_PATH "/db path");
hrnCfgArgKeyRawZ(argList, cfgOptPgPath, 2, "/db2");
@ -34,14 +35,14 @@ testRun(void)
TEST_RESULT_STRLST_Z(
cfgExecParam(cfgCmdArchiveGet, cfgCmdRoleAsync, NULL, false, true),
"--archive-async\n--no-config\n--exec-id=1-test\n--log-subprocess\n--reset-neutral-umask\n"
"--archive-async\n--buffer-size=64KiB\n--no-config\n--exec-id=1-test\n--log-subprocess\n--reset-neutral-umask\n"
"--pg1-path=\"" TEST_PATH "/db path\"\n--pg2-path=/db2\n--repo1-path=" TEST_PATH "/repo\n--stanza=test1\n"
"archive-get:async\n",
"exec archive-get -> archive-get:async");
TEST_RESULT_STRLST_Z(
cfgExecParam(cfgCmdBackup, cfgCmdRoleMain, NULL, false, false),
"--archive-timeout=5\n--no-config\n--exec-id=1-test\n--log-subprocess\n--reset-neutral-umask\n"
"--archive-timeout=5\n--buffer-size=64KiB\n--no-config\n--exec-id=1-test\n--log-subprocess\n--reset-neutral-umask\n"
"--pg1-path=" TEST_PATH "/db path\n--pg2-path=/db2\n--repo1-path=" TEST_PATH "/repo\n--stanza=test1\nbackup\n",
"exec archive-get -> backup");

View File

@ -593,14 +593,15 @@ testRun(void)
// *****************************************************************************************************************************
if (testBegin("convertToByte()"))
{
TEST_ERROR(sizeQualifierToMultiplier('w'), AssertError, "'w' is not a valid size qualifier");
TEST_RESULT_UINT(convertToByte(STRDEF("10B")), 10, "10B");
TEST_RESULT_UINT(convertToByte(STRDEF("1k")), 1024, "1k");
TEST_RESULT_UINT(convertToByte(STRDEF("5G")), (uint64_t)5 * 1024 * 1024 * 1024, "5G");
TEST_RESULT_UINT(convertToByte(STRDEF("3Tb")), (uint64_t)3 * 1024 * 1024 * 1024 * 1024, "3Tb");
TEST_RESULT_UINT(convertToByte(STRDEF("11")), 11, "11 - no qualifier, default bytes");
TEST_RESULT_UINT(convertToByte(STRDEF("4pB")), 4503599627370496, "4pB");
TEST_RESULT_UINT(convertToByte(STRDEF("15MB")), (uint64_t)15 * 1024 * 1024, "15MB");
TEST_ERROR(cfgParseSizeQualifier('w'), AssertError, "'w' is not a valid size qualifier");
TEST_RESULT_INT(cfgParseSize(STRDEF("10B")), 10, "10B");
TEST_RESULT_INT(cfgParseSize(STRDEF("1k")), 1024, "1k");
TEST_RESULT_INT(cfgParseSize(STRDEF("1KiB")), 1024, "1KiB");
TEST_RESULT_INT(cfgParseSize(STRDEF("5G")), (uint64_t)5 * 1024 * 1024 * 1024, "5G");
TEST_RESULT_INT(cfgParseSize(STRDEF("3Tb")), (uint64_t)3 * 1024 * 1024 * 1024 * 1024, "3Tb");
TEST_RESULT_INT(cfgParseSize(STRDEF("11")), 11, "11 - no qualifier, default bytes");
TEST_RESULT_INT(cfgParseSize(STRDEF("4pB")), 4503599627370496, "4pB");
TEST_RESULT_INT(cfgParseSize(STRDEF("15MB")), (uint64_t)15 * 1024 * 1024, "15MB");
}
// *****************************************************************************************************************************
@ -958,10 +959,10 @@ testRun(void)
strLstAddZ(argList, TEST_BACKREST_EXE);
strLstAddZ(argList, TEST_COMMAND_BACKUP);
hrnCfgArgRawZ(argList, cfgOptStanza, "db");
hrnCfgArgRawZ(argList, cfgOptManifestSaveThreshold, "9999999999999999999p");
hrnCfgArgRawZ(argList, cfgOptManifestSaveThreshold, "999999999999999999p");
TEST_ERROR(
configParse(storageTest, strLstSize(argList), strLstPtr(argList), false), OptionInvalidValueError,
"'9999999999999999999p' is out of range for 'manifest-save-threshold' option");
"'999999999999999999p' is out of range for 'manifest-save-threshold' option");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("value missing");