mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2026-06-20 01:17:49 +02:00
Allow NULL stanza in storage helper.
Some commands (e.g. info) do not take a stanza or the stanza is optional. In that case it is the job of the command to construct the repository path with a stanza as needed. Update helper functions to omit the stanza from the constructed path when it is NULL. Contributed by Cynthia Shang.
This commit is contained in:
committed by
David Steele
parent
cbf514e191
commit
4f539db8d9
@@ -99,6 +99,14 @@
|
|||||||
<p>Improve JSON to <code>Variant</code> conversion and add <code>Variant</code> to JSON conversion.</p>
|
<p>Improve JSON to <code>Variant</code> conversion and add <code>Variant</code> to JSON conversion.</p>
|
||||||
</release-item>
|
</release-item>
|
||||||
|
|
||||||
|
<release-item>
|
||||||
|
<release-item-contributor-list>
|
||||||
|
<release-item-contributor id="cynthia.shang"/>
|
||||||
|
</release-item-contributor-list>
|
||||||
|
|
||||||
|
<p>Allow <code>NULL</code> stanza in storage helper.</p>
|
||||||
|
</release-item>
|
||||||
|
|
||||||
<release-item>
|
<release-item>
|
||||||
<p>Allow I/O read interface to explicitly request blocking reads.</p>
|
<p>Allow I/O read interface to explicitly request blocking reads.</p>
|
||||||
</release-item>
|
</release-item>
|
||||||
|
|||||||
+27
-12
@@ -17,6 +17,8 @@ Storage path constants
|
|||||||
STRING_EXTERN(STORAGE_SPOOL_ARCHIVE_IN_STR, STORAGE_SPOOL_ARCHIVE_IN);
|
STRING_EXTERN(STORAGE_SPOOL_ARCHIVE_IN_STR, STORAGE_SPOOL_ARCHIVE_IN);
|
||||||
STRING_EXTERN(STORAGE_SPOOL_ARCHIVE_OUT_STR, STORAGE_SPOOL_ARCHIVE_OUT);
|
STRING_EXTERN(STORAGE_SPOOL_ARCHIVE_OUT_STR, STORAGE_SPOOL_ARCHIVE_OUT);
|
||||||
|
|
||||||
|
#define STORAGE_PATH_ARCHIVE "archive"
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Local variables
|
Local variables
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
@@ -31,6 +33,7 @@ static struct
|
|||||||
Storage *storageSpoolWrite; // Spool write storage
|
Storage *storageSpoolWrite; // Spool write storage
|
||||||
|
|
||||||
String *stanza; // Stanza for storage
|
String *stanza; // Stanza for storage
|
||||||
|
bool stanzaInit; // Has the stanza been initialized?
|
||||||
RegExp *walRegExp; // Regular expression for identifying wal files
|
RegExp *walRegExp; // Regular expression for identifying wal files
|
||||||
} storageHelper;
|
} storageHelper;
|
||||||
|
|
||||||
@@ -58,19 +61,25 @@ storageHelperInit(void)
|
|||||||
Initialize the stanza and error if it changes
|
Initialize the stanza and error if it changes
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
static void
|
static void
|
||||||
storageHelperStanzaInit(void)
|
storageHelperStanzaInit(const bool stanzaRequired)
|
||||||
{
|
{
|
||||||
FUNCTION_TEST_VOID();
|
FUNCTION_TEST_VOID();
|
||||||
|
|
||||||
if (storageHelper.stanza == NULL)
|
// If the stanza is NULL and the storage has not already been initialized then initialize the stanza
|
||||||
|
if (storageHelper.stanza == NULL && !storageHelper.stanzaInit)
|
||||||
{
|
{
|
||||||
|
if (stanzaRequired && cfgOptionStr(cfgOptStanza) == NULL)
|
||||||
|
THROW(AssertError, "stanza cannot be NULL for this storage object");
|
||||||
|
|
||||||
MEM_CONTEXT_BEGIN(storageHelper.memContext)
|
MEM_CONTEXT_BEGIN(storageHelper.memContext)
|
||||||
{
|
{
|
||||||
storageHelper.stanza = strDup(cfgOptionStr(cfgOptStanza));
|
storageHelper.stanza = strDup(cfgOptionStr(cfgOptStanza));
|
||||||
|
storageHelper.stanzaInit = true;
|
||||||
}
|
}
|
||||||
MEM_CONTEXT_END();
|
MEM_CONTEXT_END();
|
||||||
}
|
}
|
||||||
else if (!strEq(storageHelper.stanza, cfgOptionStr(cfgOptStanza)))
|
else if ((storageHelper.stanza == NULL && cfgOptionStr(cfgOptStanza) != NULL) ||
|
||||||
|
(cfgOptionStr(cfgOptStanza) != NULL && !strEq(storageHelper.stanza, cfgOptionStr(cfgOptStanza))))
|
||||||
{
|
{
|
||||||
THROW_FMT(
|
THROW_FMT(
|
||||||
AssertError, "stanza has changed from '%s' to '%s'", strPtr(storageHelper.stanza), strPtr(cfgOptionStr(cfgOptStanza)));
|
AssertError, "stanza has changed from '%s' to '%s'", strPtr(storageHelper.stanza), strPtr(cfgOptionStr(cfgOptStanza)));
|
||||||
@@ -130,7 +139,7 @@ storageLocalWrite(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Get a spool storage object
|
Construct a repo path from an expression and path
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
static String *
|
static String *
|
||||||
storageRepoPathExpression(const String *expression, const String *path)
|
storageRepoPathExpression(const String *expression, const String *path)
|
||||||
@@ -146,8 +155,13 @@ storageRepoPathExpression(const String *expression, const String *path)
|
|||||||
|
|
||||||
if (strEqZ(expression, STORAGE_REPO_ARCHIVE))
|
if (strEqZ(expression, STORAGE_REPO_ARCHIVE))
|
||||||
{
|
{
|
||||||
result = strNewFmt("archive/%s", strPtr(storageHelper.stanza));
|
// Contruct the base path
|
||||||
|
if (storageHelper.stanza != NULL)
|
||||||
|
result = strNewFmt(STORAGE_PATH_ARCHIVE "/%s", strPtr(storageHelper.stanza));
|
||||||
|
else
|
||||||
|
result = strNew(STORAGE_PATH_ARCHIVE);
|
||||||
|
|
||||||
|
// If a subpath should be appended, determine if it is WAL path, else just append the subpath
|
||||||
if (path != NULL)
|
if (path != NULL)
|
||||||
{
|
{
|
||||||
StringList *pathSplit = strLstNewSplitZ(path, "/");
|
StringList *pathSplit = strLstNewSplitZ(path, "/");
|
||||||
@@ -219,7 +233,7 @@ storageRepo(void)
|
|||||||
if (storageHelper.storageRepo == NULL)
|
if (storageHelper.storageRepo == NULL)
|
||||||
{
|
{
|
||||||
storageHelperInit();
|
storageHelperInit();
|
||||||
storageHelperStanzaInit();
|
storageHelperStanzaInit(false);
|
||||||
|
|
||||||
MEM_CONTEXT_BEGIN(storageHelper.memContext)
|
MEM_CONTEXT_BEGIN(storageHelper.memContext)
|
||||||
{
|
{
|
||||||
@@ -243,6 +257,7 @@ storageSpoolPathExpression(const String *expression, const String *path)
|
|||||||
FUNCTION_TEST_PARAM(STRING, path);
|
FUNCTION_TEST_PARAM(STRING, path);
|
||||||
|
|
||||||
FUNCTION_TEST_ASSERT(expression != NULL);
|
FUNCTION_TEST_ASSERT(expression != NULL);
|
||||||
|
FUNCTION_TEST_ASSERT(storageHelper.stanza != NULL);
|
||||||
FUNCTION_TEST_END();
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
String *result = NULL;
|
String *result = NULL;
|
||||||
@@ -250,16 +265,16 @@ storageSpoolPathExpression(const String *expression, const String *path)
|
|||||||
if (strEqZ(expression, STORAGE_SPOOL_ARCHIVE_IN))
|
if (strEqZ(expression, STORAGE_SPOOL_ARCHIVE_IN))
|
||||||
{
|
{
|
||||||
if (path == NULL)
|
if (path == NULL)
|
||||||
result = strNewFmt("archive/%s/in", strPtr(storageHelper.stanza));
|
result = strNewFmt(STORAGE_PATH_ARCHIVE "/%s/in", strPtr(storageHelper.stanza));
|
||||||
else
|
else
|
||||||
result = strNewFmt("archive/%s/in/%s", strPtr(storageHelper.stanza), strPtr(path));
|
result = strNewFmt(STORAGE_PATH_ARCHIVE "/%s/in/%s", strPtr(storageHelper.stanza), strPtr(path));
|
||||||
}
|
}
|
||||||
else if (strEqZ(expression, STORAGE_SPOOL_ARCHIVE_OUT))
|
else if (strEqZ(expression, STORAGE_SPOOL_ARCHIVE_OUT))
|
||||||
{
|
{
|
||||||
if (path == NULL)
|
if (path == NULL)
|
||||||
result = strNewFmt("archive/%s/out", strPtr(storageHelper.stanza));
|
result = strNewFmt(STORAGE_PATH_ARCHIVE "/%s/out", strPtr(storageHelper.stanza));
|
||||||
else
|
else
|
||||||
result = strNewFmt("archive/%s/out/%s", strPtr(storageHelper.stanza), strPtr(path));
|
result = strNewFmt(STORAGE_PATH_ARCHIVE "/%s/out/%s", strPtr(storageHelper.stanza), strPtr(path));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
THROW_FMT(AssertError, "invalid expression '%s'", strPtr(expression));
|
THROW_FMT(AssertError, "invalid expression '%s'", strPtr(expression));
|
||||||
@@ -278,7 +293,7 @@ storageSpool(void)
|
|||||||
if (storageHelper.storageSpool == NULL)
|
if (storageHelper.storageSpool == NULL)
|
||||||
{
|
{
|
||||||
storageHelperInit();
|
storageHelperInit();
|
||||||
storageHelperStanzaInit();
|
storageHelperStanzaInit(true);
|
||||||
|
|
||||||
MEM_CONTEXT_BEGIN(storageHelper.memContext)
|
MEM_CONTEXT_BEGIN(storageHelper.memContext)
|
||||||
{
|
{
|
||||||
@@ -304,7 +319,7 @@ storageSpoolWrite(void)
|
|||||||
if (storageHelper.storageSpoolWrite == NULL)
|
if (storageHelper.storageSpoolWrite == NULL)
|
||||||
{
|
{
|
||||||
storageHelperInit();
|
storageHelperInit();
|
||||||
storageHelperStanzaInit();
|
storageHelperStanzaInit(true);
|
||||||
|
|
||||||
MEM_CONTEXT_BEGIN(storageHelper.memContext)
|
MEM_CONTEXT_BEGIN(storageHelper.memContext)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -961,7 +961,7 @@ testRun(void)
|
|||||||
TEST_RESULT_STR(
|
TEST_RESULT_STR(
|
||||||
strPtr(storagePathNP(storage, strNew(STORAGE_REPO_ARCHIVE "/9.4-1/000000010000014C0000001A.00000028.backup"))),
|
strPtr(storagePathNP(storage, strNew(STORAGE_REPO_ARCHIVE "/9.4-1/000000010000014C0000001A.00000028.backup"))),
|
||||||
strPtr(strNewFmt("%s/archive/db/9.4-1/000000010000014C/000000010000014C0000001A.00000028.backup", testPath())),
|
strPtr(strNewFmt("%s/archive/db/9.4-1/000000010000014C/000000010000014C0000001A.00000028.backup", testPath())),
|
||||||
"check backup path");
|
"check archive backup path");
|
||||||
|
|
||||||
// Change the stanza name and make sure helper fails
|
// Change the stanza name and make sure helper fails
|
||||||
// -------------------------------------------------------------------------------------------------------------------------
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
@@ -975,6 +975,46 @@ testRun(void)
|
|||||||
harnessCfgLoad(strLstSize(argList), strLstPtr(argList));
|
harnessCfgLoad(strLstSize(argList), strLstPtr(argList));
|
||||||
|
|
||||||
TEST_ERROR(storageRepo(), AssertError, "stanza has changed from 'db' to 'other'");
|
TEST_ERROR(storageRepo(), AssertError, "stanza has changed from 'db' to 'other'");
|
||||||
|
|
||||||
|
// Change the stanza to NULL with the stanzaInit flag still true and make sure helper fails
|
||||||
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
|
storageHelper.storageRepo = NULL;
|
||||||
|
storageHelper.stanza = NULL;
|
||||||
|
TEST_RESULT_BOOL(storageHelper.stanzaInit, true, "stanza initialized");
|
||||||
|
|
||||||
|
argList = strLstNew();
|
||||||
|
strLstAddZ(argList, "pgbackrest");
|
||||||
|
strLstAddZ(argList, "--stanza=other");
|
||||||
|
strLstAdd(argList, strNewFmt("--repo-path=%s", testPath()));
|
||||||
|
strLstAddZ(argList, "archive-get");
|
||||||
|
harnessCfgLoad(strLstSize(argList), strLstPtr(argList));
|
||||||
|
|
||||||
|
TEST_ERROR(storageRepo(), AssertError, "stanza has changed from '(null)' to 'other'");
|
||||||
|
|
||||||
|
// Change the stanza to NULL with the stanzaInit flag still true, make sure helper does not fail when stanza option not set
|
||||||
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
|
storageHelper.storageRepo = NULL;
|
||||||
|
storageHelper.stanza = NULL;
|
||||||
|
TEST_RESULT_BOOL(storageHelper.stanzaInit, true, "stanza initialized");
|
||||||
|
|
||||||
|
argList = strLstNew();
|
||||||
|
strLstAddZ(argList, "pgbackrest");
|
||||||
|
strLstAdd(argList, strNewFmt("--repo-path=%s", testPath()));
|
||||||
|
strLstAddZ(argList, "info");
|
||||||
|
harnessCfgLoad(strLstSize(argList), strLstPtr(argList));
|
||||||
|
|
||||||
|
TEST_ASSIGN(storage, storageRepo(), "new repo storage no stanza");
|
||||||
|
TEST_RESULT_PTR(storageHelper.stanza, NULL, "stanza NULL");
|
||||||
|
|
||||||
|
TEST_RESULT_STR(
|
||||||
|
strPtr(storagePathNP(storage, strNew(STORAGE_REPO_ARCHIVE))), strPtr(strNewFmt("%s/archive", testPath())),
|
||||||
|
"check archive path - NULL stanza");
|
||||||
|
TEST_RESULT_STR(
|
||||||
|
strPtr(storagePathNP(storage, strNew(STORAGE_REPO_ARCHIVE "/simple"))),
|
||||||
|
strPtr(strNewFmt("%s/archive/simple", testPath())), "check simple archive path - NULL stanza");
|
||||||
|
|
||||||
|
// Reset init flag
|
||||||
|
storageHelper.stanzaInit = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// *****************************************************************************************************************************
|
// *****************************************************************************************************************************
|
||||||
@@ -1023,6 +1063,22 @@ testRun(void)
|
|||||||
TEST_RESULT_PTR(storageSpoolWrite(), storage, "get cached storage");
|
TEST_RESULT_PTR(storageSpoolWrite(), storage, "get cached storage");
|
||||||
|
|
||||||
TEST_RESULT_VOID(storageNewWriteNP(storage, writeFile), "writes are allowed");
|
TEST_RESULT_VOID(storageNewWriteNP(storage, writeFile), "writes are allowed");
|
||||||
|
|
||||||
|
// Change the stanza to NULL, stanzaInit flag to false and make sure helper fails because stanza is required
|
||||||
|
// -------------------------------------------------------------------------------------------------------------------------
|
||||||
|
storageHelper.storageSpool = NULL;
|
||||||
|
storageHelper.storageSpoolWrite = NULL;
|
||||||
|
storageHelper.stanzaInit = false;
|
||||||
|
storageHelper.stanza = NULL;
|
||||||
|
|
||||||
|
argList = strLstNew();
|
||||||
|
strLstAddZ(argList, "pgbackrest");
|
||||||
|
strLstAdd(argList, strNewFmt("--repo-path=%s", testPath()));
|
||||||
|
strLstAddZ(argList, "info");
|
||||||
|
harnessCfgLoad(strLstSize(argList), strLstPtr(argList));
|
||||||
|
|
||||||
|
TEST_ERROR(storageSpool(), AssertError, "stanza cannot be NULL for this storage object");
|
||||||
|
TEST_ERROR(storageSpoolWrite(), AssertError, "stanza cannot be NULL for this storage object");
|
||||||
}
|
}
|
||||||
|
|
||||||
FUNCTION_HARNESS_RESULT_VOID();
|
FUNCTION_HARNESS_RESULT_VOID();
|
||||||
|
|||||||
Reference in New Issue
Block a user