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

Merge protocol storage helper into storage helper.

These are separated the same way in the Perl code where the remote storage driver is located in the Protocol module. However, in the C code the intention is to implement the remote storage driver as a regular driver in the storage layer rather than making a special case out of it.

So, merge the storage helpers. This also has the benefit of making the code a bit simpler.

Also separate storageSpool() and storageSpoolWrite() to make it clearer which operations require write access and to maintain consistency with the other storage helper functions.
This commit is contained in:
David Steele 2018-09-16 14:12:53 -04:00
parent 3014b05dab
commit 84ab787b1a
15 changed files with 283 additions and 303 deletions

View File

@ -53,7 +53,7 @@
</release-item>
<release-item>
<p>Storage refactoring. Posix file functions now differentiate between open and missing errors. Don't use negations in objects below Storage. Rename posix driver files/functions for consistency. Full abstraction of storage driver interface.</p>
<p>Storage refactoring. Posix file functions now differentiate between open and missing errors. Don't use negations in objects below Storage. Rename posix driver files/functions for consistency. Full abstraction of storage driver interface. Merge protocol storage helper into storage helper.</p>
</release-item>
<release-item>

View File

@ -112,7 +112,6 @@ SRCS = \
perl/exec.c \
postgres/info.c \
postgres/pageChecksum.c \
protocol/storage/helper.c \
storage/driver/posix/storage.c \
storage/driver/posix/common.c \
storage/driver/posix/fileRead.c \
@ -142,13 +141,13 @@ install: pgbackrest
####################################################################################################################################
# Compile rules
####################################################################################################################################
command/archive/common.o: command/archive/common.c command/archive/common.h common/assert.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/log.h common/logLevel.h common/memContext.h common/regExp.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h common/wait.h postgres/version.h protocol/storage/helper.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
command/archive/common.o: command/archive/common.c command/archive/common.h common/assert.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/log.h common/logLevel.h common/memContext.h common/regExp.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h common/wait.h postgres/version.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
$(CC) $(CFLAGS) -c command/archive/common.c -o command/archive/common.o
command/archive/get/file.o: command/archive/get/file.c command/archive/common.h command/archive/get/file.h command/control/control.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h compress/gzip.h compress/gzipDecompress.h config/config.auto.h config/config.h config/define.auto.h config/define.h info/infoArchive.h info/infoPg.h postgres/info.h protocol/storage/helper.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
command/archive/get/file.o: command/archive/get/file.c command/archive/common.h command/archive/get/file.h command/control/control.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h compress/gzip.h compress/gzipDecompress.h config/config.auto.h config/config.h config/define.auto.h config/define.h info/infoArchive.h info/infoPg.h postgres/info.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
$(CC) $(CFLAGS) -c command/archive/get/file.c -o command/archive/get/file.o
command/archive/get/get.o: command/archive/get/get.c command/archive/common.h command/archive/get/file.h command/command.h common/assert.h common/debug.h common/error.auto.h common/error.h common/fork.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/regExp.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h common/wait.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/load.h perl/exec.h postgres/info.h protocol/storage/helper.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
command/archive/get/get.o: command/archive/get/get.c command/archive/common.h command/archive/get/file.h command/command.h common/assert.h common/debug.h common/error.auto.h common/error.h common/fork.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/regExp.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h common/wait.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/load.h perl/exec.h postgres/info.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
$(CC) $(CFLAGS) -c command/archive/get/get.c -o command/archive/get/get.o
command/archive/push/push.o: command/archive/push/push.c command/archive/common.h command/command.h common/debug.h common/error.auto.h common/error.h common/fork.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h common/wait.h config/config.auto.h config/config.h config/define.auto.h config/define.h config/load.h perl/exec.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h
@ -319,9 +318,6 @@ postgres/info.o: postgres/info.c common/debug.h common/error.auto.h common/error
postgres/pageChecksum.o: postgres/pageChecksum.c common/assert.h common/debug.h common/error.auto.h common/error.h common/log.h common/logLevel.h common/stackTrace.h common/type/convert.h postgres/pageChecksum.h postgres/type.h
$(CC) $(CFLAGS) -funroll-loops -ftree-vectorize -c postgres/pageChecksum.c -o postgres/pageChecksum.o
protocol/storage/helper.o: protocol/storage/helper.c common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/regExp.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h protocol/storage/helper.h storage/driver/posix/fileRead.h storage/driver/posix/fileWrite.h storage/driver/posix/storage.h storage/fileRead.h storage/fileWrite.h storage/info.h storage/storage.h storage/storage.intern.h
$(CC) $(CFLAGS) -c protocol/storage/helper.c -o protocol/storage/helper.o
storage/driver/posix/common.o: storage/driver/posix/common.c common/assert.h common/debug.h common/error.auto.h common/error.h common/logLevel.h common/memContext.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/string.h storage/driver/posix/common.h
$(CC) $(CFLAGS) -c storage/driver/posix/common.c -o storage/driver/posix/common.o
@ -340,7 +336,7 @@ storage/fileRead.o: storage/fileRead.c common/assert.h common/debug.h common/err
storage/fileWrite.o: storage/fileWrite.c common/assert.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/write.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/variant.h common/type/variantList.h storage/fileWrite.h storage/fileWrite.intern.h version.h
$(CC) $(CFLAGS) -c storage/fileWrite.c -o storage/fileWrite.o
storage/helper.o: storage/helper.c common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h storage/driver/posix/fileRead.h storage/driver/posix/fileWrite.h storage/driver/posix/storage.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h storage/storage.intern.h
storage/helper.o: storage/helper.c common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/read.h common/io/write.h common/lock.h common/log.h common/logLevel.h common/memContext.h common/regExp.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h config/config.auto.h config/config.h config/define.auto.h config/define.h storage/driver/posix/fileRead.h storage/driver/posix/fileWrite.h storage/driver/posix/storage.h storage/fileRead.h storage/fileWrite.h storage/helper.h storage/info.h storage/storage.h storage/storage.intern.h
$(CC) $(CFLAGS) -c storage/helper.c -o storage/helper.o
storage/storage.o: storage/storage.c common/assert.h common/debug.h common/error.auto.h common/error.h common/io/filter/filter.h common/io/filter/group.h common/io/io.h common/io/read.h common/io/write.h common/log.h common/logLevel.h common/memContext.h common/stackTrace.h common/type/buffer.h common/type/convert.h common/type/keyValue.h common/type/string.h common/type/stringList.h common/type/variant.h common/type/variantList.h common/wait.h storage/fileRead.h storage/fileWrite.h storage/info.h storage/storage.h storage/storage.intern.h

View File

@ -13,7 +13,7 @@ Archive Push Command
#include "common/regExp.h"
#include "common/wait.h"
#include "postgres/version.h"
#include "protocol/storage/helper.h"
#include "storage/helper.h"
#include "storage/helper.h"
/***********************************************************************************************************************************

View File

@ -12,7 +12,7 @@ Archive Get File
#include "config/config.h"
#include "info/infoArchive.h"
#include "postgres/info.h"
#include "protocol/storage/helper.h"
#include "storage/helper.h"
#include "storage/helper.h"
/***********************************************************************************************************************************

View File

@ -18,7 +18,7 @@ Archive Get Command
#include "config/load.h"
#include "perl/exec.h"
#include "postgres/info.h"
#include "protocol/storage/helper.h"
#include "storage/helper.h"
#include "storage/helper.h"
/***********************************************************************************************************************************
@ -78,7 +78,7 @@ queueNeed(const String *walSegment, bool found, size_t queueSize, size_t walSegm
// Else delete it
else
storageRemoveNP(storageSpool(), strNewFmt(STORAGE_SPOOL_ARCHIVE_IN "/%s", strPtr(file)));
storageRemoveNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_IN "/%s", strPtr(file)));
}
// Generate a list of the WAL that are needed by removing kept WAL from the ideal queue
@ -150,7 +150,8 @@ cmdArchiveGet(void)
if (archiveAsyncStatus(archiveModeGet, walSegment, confessOnError))
{
storageRemoveP(
storageSpool(), strNewFmt(STORAGE_SPOOL_ARCHIVE_IN "/%s.ok", strPtr(walSegment)), .errorOnMissing = true);
storageSpoolWrite(),
strNewFmt(STORAGE_SPOOL_ARCHIVE_IN "/%s.ok", strPtr(walSegment)), .errorOnMissing = true);
break;
}
@ -176,7 +177,7 @@ cmdArchiveGet(void)
.noAtomic = true);
// Move (or copy if required) the file
storageMoveNP(storageSpool(), source, destination);
storageMoveNP(storageSpoolWrite(), source, destination);
// Return success
result = 0;
@ -226,7 +227,7 @@ cmdArchiveGet(void)
unsigned int walSegmentSize = WAL_SEGMENT_DEFAULT_SIZE;
// Create the queue
storagePathCreateNP(storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_IN));
storagePathCreateNP(storageSpoolWrite(), strNew(STORAGE_SPOOL_ARCHIVE_IN));
// Clean the current queue using the list of WAL that we ideally want in the queue. queueNeed()
// will return the list of WAL needed to fill the queue and this will be passed to the async process.

View File

@ -1,106 +0,0 @@
/***********************************************************************************************************************************
Protocol Storage Helper
***********************************************************************************************************************************/
#include <string.h>
#include "common/debug.h"
#include "common/memContext.h"
#include "common/regExp.h"
#include "config/config.h"
#include "protocol/storage/helper.h"
#include "storage/driver/posix/storage.h"
#include "storage/storage.intern.h"
/***********************************************************************************************************************************
Local variables
***********************************************************************************************************************************/
struct
{
MemContext *memContext; // Mem context for protocol storage
Storage *storageRepo; // Repository read-only storage
String *stanza; // Stanza for storage
RegExp *walRegExp; // Regular expression for identifying wal files
} protocolStorageHelper;
/***********************************************************************************************************************************
Create the storage helper memory context
***********************************************************************************************************************************/
static void
protocolStorageHelperInit(void)
{
FUNCTION_TEST_VOID();
if (protocolStorageHelper.memContext == NULL)
{
MEM_CONTEXT_BEGIN(memContextTop())
{
protocolStorageHelper.memContext = memContextNew("protocolStorageHelper");
}
MEM_CONTEXT_END();
}
FUNCTION_TEST_RESULT_VOID();
}
/***********************************************************************************************************************************
Get a spool storage object
***********************************************************************************************************************************/
static String *
storageRepoPathExpression(const String *expression, const String *path)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(STRING, expression);
FUNCTION_TEST_PARAM(STRING, path);
FUNCTION_TEST_ASSERT(expression != NULL);
FUNCTION_TEST_END();
String *result = NULL;
if (strEqZ(expression, STORAGE_REPO_ARCHIVE))
{
result = strNewFmt("archive/%s", strPtr(protocolStorageHelper.stanza));
if (path != NULL)
{
StringList *pathSplit = strLstNewSplitZ(path, "/");
String *file = strLstSize(pathSplit) == 2 ? strLstGet(pathSplit, 1) : NULL;
if (file != NULL && regExpMatch(protocolStorageHelper.walRegExp, file))
strCatFmt(result, "/%s/%s/%s", strPtr(strLstGet(pathSplit, 0)), strPtr(strSubN(file, 0, 16)), strPtr(file));
else
strCatFmt(result, "/%s", strPtr(path));
}
}
else
THROW_FMT(AssertError, "invalid expression '%s'", strPtr(expression));
FUNCTION_TEST_RESULT(STRING, result);
}
/***********************************************************************************************************************************
Get a read-only repository storage object
***********************************************************************************************************************************/
const Storage *
storageRepo(void)
{
FUNCTION_TEST_VOID();
if (protocolStorageHelper.storageRepo == NULL)
{
protocolStorageHelperInit();
MEM_CONTEXT_BEGIN(protocolStorageHelper.memContext)
{
protocolStorageHelper.stanza = strDup(cfgOptionStr(cfgOptStanza));
protocolStorageHelper.walRegExp = regExpNew(strNew("^[0-F]{24}"));
protocolStorageHelper.storageRepo = storageDriverPosixInterface(
storageDriverPosixNew(
cfgOptionStr(cfgOptRepoPath), STORAGE_MODE_FILE_DEFAULT, STORAGE_MODE_PATH_DEFAULT, false,
storageRepoPathExpression));
}
MEM_CONTEXT_END();
}
FUNCTION_TEST_RESULT(STORAGE, protocolStorageHelper.storageRepo);
}

View File

@ -1,26 +0,0 @@
/***********************************************************************************************************************************
Protocol Storage Helper
***********************************************************************************************************************************/
#ifndef PROTOCOL_STORAGE_HELPER_H
#define PROTOCOL_STORAGE_HELPER_H
#include "storage/storage.h"
/***********************************************************************************************************************************
Repo storage path constants
***********************************************************************************************************************************/
#define STORAGE_REPO_ARCHIVE "<REPO:ARCHIVE>"
/***********************************************************************************************************************************
Repository storage types
***********************************************************************************************************************************/
#define STORAGE_TYPE_CIFS "cifs"
#define STORAGE_TYPE_POSIX "posix"
#define STORAGE_TYPE_S3 "s3"
/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
const Storage *storageRepo(void);
#endif

View File

@ -5,26 +5,27 @@ Storage Helper
#include "common/debug.h"
#include "common/memContext.h"
#include "common/regExp.h"
#include "config/config.h"
#include "storage/driver/posix/storage.h"
#include "storage/helper.h"
/***********************************************************************************************************************************
Mem context for storage helper
Local variables
***********************************************************************************************************************************/
static MemContext *memContextStorageHelper = NULL;
static struct
{
MemContext *memContext; // Mem context for storage helper
/***********************************************************************************************************************************
Cache for local storage
***********************************************************************************************************************************/
static Storage *storageLocalData = NULL;
static Storage *storageLocalWriteData = NULL;
Storage *storageLocal; // Local read-only storage
Storage *storageLocalWrite; // Local write storage
Storage *storageRepo; // Repository read-only storage
Storage *storageSpool; // Spool read-only storage
Storage *storageSpoolWrite; // Spool write storage
/***********************************************************************************************************************************
Cache for spool storage
***********************************************************************************************************************************/
static Storage *storageSpoolData = NULL;
static const String *storageSpoolStanza = NULL;
String *stanza; // Stanza for storage
RegExp *walRegExp; // Regular expression for identifying wal files
} storageHelper;
/***********************************************************************************************************************************
Create the storage helper memory context
@ -34,11 +35,11 @@ storageHelperInit(void)
{
FUNCTION_TEST_VOID();
if (memContextStorageHelper == NULL)
if (storageHelper.memContext == NULL)
{
MEM_CONTEXT_BEGIN(memContextTop())
{
memContextStorageHelper = memContextNew("storageHelper");
storageHelper.memContext = memContextNew("storageHelper");
}
MEM_CONTEXT_END();
}
@ -46,6 +47,31 @@ storageHelperInit(void)
FUNCTION_TEST_RESULT_VOID();
}
/***********************************************************************************************************************************
Initialize the stanza and error if it changes
***********************************************************************************************************************************/
static void
storageHelperStanzaInit(void)
{
FUNCTION_TEST_VOID();
if (storageHelper.stanza == NULL)
{
MEM_CONTEXT_BEGIN(storageHelper.memContext)
{
storageHelper.stanza = strDup(cfgOptionStr(cfgOptStanza));
}
MEM_CONTEXT_END();
}
else if (!strEq(storageHelper.stanza, cfgOptionStr(cfgOptStanza)))
{
THROW_FMT(
AssertError, "stanza has changed from '%s' to '%s'", strPtr(storageHelper.stanza), strPtr(cfgOptionStr(cfgOptStanza)));
}
FUNCTION_TEST_RESULT_VOID();
}
/***********************************************************************************************************************************
Get a local storage object
***********************************************************************************************************************************/
@ -54,20 +80,20 @@ storageLocal(void)
{
FUNCTION_TEST_VOID();
if (storageLocalData == NULL)
if (storageHelper.storageLocal == NULL)
{
storageHelperInit();
MEM_CONTEXT_BEGIN(memContextStorageHelper)
MEM_CONTEXT_BEGIN(storageHelper.memContext)
{
storageLocalData = storageDriverPosixInterface(
storageHelper.storageLocal = storageDriverPosixInterface(
storageDriverPosixNew(
strNew("/"), STORAGE_MODE_FILE_DEFAULT, STORAGE_MODE_PATH_DEFAULT, false, NULL));
}
MEM_CONTEXT_END();
}
FUNCTION_TEST_RESULT(STORAGE, storageLocalData);
FUNCTION_TEST_RESULT(STORAGE, storageHelper.storageLocal);
}
/***********************************************************************************************************************************
@ -80,20 +106,84 @@ storageLocalWrite(void)
{
FUNCTION_TEST_VOID();
if (storageLocalWriteData == NULL)
if (storageHelper.storageLocalWrite == NULL)
{
storageHelperInit();
MEM_CONTEXT_BEGIN(memContextStorageHelper)
MEM_CONTEXT_BEGIN(storageHelper.memContext)
{
storageLocalWriteData = storageDriverPosixInterface(
storageHelper.storageLocalWrite = storageDriverPosixInterface(
storageDriverPosixNew(
strNew("/"), STORAGE_MODE_FILE_DEFAULT, STORAGE_MODE_PATH_DEFAULT, true, NULL));
}
MEM_CONTEXT_END();
}
FUNCTION_TEST_RESULT(STORAGE, storageLocalWriteData);
FUNCTION_TEST_RESULT(STORAGE, storageHelper.storageLocalWrite);
}
/***********************************************************************************************************************************
Get a spool storage object
***********************************************************************************************************************************/
static String *
storageRepoPathExpression(const String *expression, const String *path)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(STRING, expression);
FUNCTION_TEST_PARAM(STRING, path);
FUNCTION_TEST_ASSERT(expression != NULL);
FUNCTION_TEST_END();
String *result = NULL;
if (strEqZ(expression, STORAGE_REPO_ARCHIVE))
{
result = strNewFmt("archive/%s", strPtr(storageHelper.stanza));
if (path != NULL)
{
StringList *pathSplit = strLstNewSplitZ(path, "/");
String *file = strLstSize(pathSplit) == 2 ? strLstGet(pathSplit, 1) : NULL;
if (file != NULL && regExpMatch(storageHelper.walRegExp, file))
strCatFmt(result, "/%s/%s/%s", strPtr(strLstGet(pathSplit, 0)), strPtr(strSubN(file, 0, 16)), strPtr(file));
else
strCatFmt(result, "/%s", strPtr(path));
}
}
else
THROW_FMT(AssertError, "invalid expression '%s'", strPtr(expression));
FUNCTION_TEST_RESULT(STRING, result);
}
/***********************************************************************************************************************************
Get a read-only repository storage object
***********************************************************************************************************************************/
const Storage *
storageRepo(void)
{
FUNCTION_TEST_VOID();
if (storageHelper.storageRepo == NULL)
{
storageHelperInit();
storageHelperStanzaInit();
MEM_CONTEXT_BEGIN(storageHelper.memContext)
{
storageHelper.walRegExp = regExpNew(strNew("^[0-F]{24}"));
storageHelper.storageRepo = storageDriverPosixInterface(
storageDriverPosixNew(
cfgOptionStr(cfgOptRepoPath), STORAGE_MODE_FILE_DEFAULT, STORAGE_MODE_PATH_DEFAULT, false,
storageRepoPathExpression));
}
MEM_CONTEXT_END();
}
FUNCTION_TEST_RESULT(STORAGE, storageHelper.storageRepo);
}
/***********************************************************************************************************************************
@ -114,16 +204,16 @@ storageSpoolPathExpression(const String *expression, const String *path)
if (strEqZ(expression, STORAGE_SPOOL_ARCHIVE_IN))
{
if (path == NULL)
result = strNewFmt("archive/%s/in", strPtr(storageSpoolStanza));
result = strNewFmt("archive/%s/in", strPtr(storageHelper.stanza));
else
result = strNewFmt("archive/%s/in/%s", strPtr(storageSpoolStanza), strPtr(path));
result = strNewFmt("archive/%s/in/%s", strPtr(storageHelper.stanza), strPtr(path));
}
else if (strEqZ(expression, STORAGE_SPOOL_ARCHIVE_OUT))
{
if (path == NULL)
result = strNewFmt("archive/%s/out", strPtr(storageSpoolStanza));
result = strNewFmt("archive/%s/out", strPtr(storageHelper.stanza));
else
result = strNewFmt("archive/%s/out/%s", strPtr(storageSpoolStanza), strPtr(path));
result = strNewFmt("archive/%s/out/%s", strPtr(storageHelper.stanza), strPtr(path));
}
else
THROW_FMT(AssertError, "invalid expression '%s'", strPtr(expression));
@ -132,21 +222,47 @@ storageSpoolPathExpression(const String *expression, const String *path)
}
/***********************************************************************************************************************************
Get a spool storage object
Get a read-only spool storage object
***********************************************************************************************************************************/
const Storage *
storageSpool(void)
{
FUNCTION_TEST_VOID();
if (storageSpoolData == NULL)
if (storageHelper.storageSpool == NULL)
{
storageHelperInit();
storageHelperStanzaInit();
MEM_CONTEXT_BEGIN(memContextStorageHelper)
MEM_CONTEXT_BEGIN(storageHelper.memContext)
{
storageSpoolStanza = strDup(cfgOptionStr(cfgOptStanza));
storageSpoolData = storageDriverPosixInterface(
storageHelper.storageSpool = storageDriverPosixInterface(
storageDriverPosixNew(
cfgOptionStr(cfgOptSpoolPath), STORAGE_MODE_FILE_DEFAULT, STORAGE_MODE_PATH_DEFAULT, false,
storageSpoolPathExpression));
}
MEM_CONTEXT_END();
}
FUNCTION_TEST_RESULT(STORAGE, storageHelper.storageSpool);
}
/***********************************************************************************************************************************
Get a writable spool storage object
***********************************************************************************************************************************/
const Storage *
storageSpoolWrite(void)
{
FUNCTION_TEST_VOID();
if (storageHelper.storageSpoolWrite == NULL)
{
storageHelperInit();
storageHelperStanzaInit();
MEM_CONTEXT_BEGIN(storageHelper.memContext)
{
storageHelper.storageSpoolWrite = storageDriverPosixInterface(
storageDriverPosixNew(
cfgOptionStr(cfgOptSpoolPath), STORAGE_MODE_FILE_DEFAULT, STORAGE_MODE_PATH_DEFAULT, true,
storageSpoolPathExpression));
@ -154,5 +270,5 @@ storageSpool(void)
MEM_CONTEXT_END();
}
FUNCTION_TEST_RESULT(STORAGE, storageSpoolData);
FUNCTION_TEST_RESULT(STORAGE, storageHelper.storageSpoolWrite);
}

View File

@ -7,17 +7,27 @@ Storage Helper
#include "storage/storage.h"
/***********************************************************************************************************************************
Spool storage path constants
Storage path constants
***********************************************************************************************************************************/
#define STORAGE_SPOOL_ARCHIVE_IN "<SPOOL:ARCHIVE:IN>"
#define STORAGE_SPOOL_ARCHIVE_OUT "<SPOOL:ARCHIVE:OUT>"
#define STORAGE_REPO_ARCHIVE "<REPO:ARCHIVE>"
/***********************************************************************************************************************************
Repository storage types
***********************************************************************************************************************************/
#define STORAGE_TYPE_CIFS "cifs"
#define STORAGE_TYPE_POSIX "posix"
#define STORAGE_TYPE_S3 "s3"
/***********************************************************************************************************************************
Functions
***********************************************************************************************************************************/
const Storage *storageLocal(void);
const Storage *storageLocalWrite(void);
const Storage *storageRepo(void);
const Storage *storageSpool(void);
const Storage *storageSpoolWrite(void);
#endif

View File

@ -530,13 +530,6 @@ unit:
coverage:
Protocol/Base/Minion: partial
# ----------------------------------------------------------------------------------------------------------------------------
- name: storage-helper
total: 2
coverage:
protocol/storage/helper: full
# ----------------------------------------------------------------------------------------------------------------------------
- name: helper-perl
total: 2

View File

@ -3,7 +3,7 @@ Test Archive Common
***********************************************************************************************************************************/
#include <unistd.h>
#include "protocol/storage/helper.h"
#include "storage/helper.h"
#include "storage/driver/posix/storage.h"
#include "common/harnessConfig.h"
@ -47,34 +47,34 @@ testRun(void)
// -------------------------------------------------------------------------------------------------------------------------
storagePutNP(
storageNewWriteNP(storageSpool(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))),
storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))),
bufNewStr(strNew(BOGUS_STR)));
TEST_ERROR(
archiveAsyncStatus(archiveModePush, segment, false), FormatError,
"000000010000000100000001.ok content must have at least two lines");
storagePutNP(
storageNewWriteNP(storageSpool(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))),
storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))),
bufNewStr(strNew(BOGUS_STR "\n")));
TEST_ERROR(
archiveAsyncStatus(archiveModePush, segment, false), FormatError, "000000010000000100000001.ok message must be > 0");
storagePutNP(
storageNewWriteNP(storageSpool(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))),
storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))),
bufNewStr(strNew(BOGUS_STR "\nmessage")));
TEST_ERROR(archiveAsyncStatus(archiveModePush, segment, false), FormatError, "unable to convert string 'BOGUS' to int");
storagePutNP(storageNewWriteNP(storageSpool(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))), NULL);
storagePutNP(storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))), NULL);
TEST_RESULT_BOOL(archiveAsyncStatus(archiveModePush, segment, false), true, "ok file");
storagePutNP(
storageNewWriteNP(storageSpool(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))),
storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))),
bufNewStr(strNew("0\nwarning")));
TEST_RESULT_BOOL(archiveAsyncStatus(archiveModePush, segment, false), true, "ok file with warning");
harnessLogResult("P00 WARN: warning");
storagePutNP(
storageNewWriteNP(storageSpool(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))),
storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strPtr(segment))),
bufNewStr(strNew("25\nerror")));
TEST_RESULT_BOOL(archiveAsyncStatus(archiveModePush, segment, false), true, "error status renamed to ok");
harnessLogResult(
@ -82,7 +82,7 @@ testRun(void)
// -------------------------------------------------------------------------------------------------------------------------
storagePutNP(
storageNewWriteNP(storageSpool(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.error", strPtr(segment))),
storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.error", strPtr(segment))),
bufNewStr(strNew("")));
TEST_ERROR(
archiveAsyncStatus(archiveModePush, segment, false), AssertError,
@ -96,7 +96,7 @@ testRun(void)
"status file '000000010000000100000001.error' has no content");
storagePutNP(
storageNewWriteNP(storageSpool(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.error", strPtr(segment))),
storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.error", strPtr(segment))),
bufNewStr(strNew("25\nmessage")));
TEST_ERROR(archiveAsyncStatus(archiveModePush, segment, true), AssertError, "message");

View File

@ -213,7 +213,7 @@ testRun(void)
{
StringList *argList = strLstNew();
strLstAddZ(argList, "pgbackrest");
strLstAddZ(argList, "--stanza=db");
strLstAddZ(argList, "--stanza=test1");
strLstAddZ(argList, "--archive-async");
strLstAdd(argList, strNewFmt("--spool-path=%s/spool", testPath()));
strLstAddZ(argList, "archive-get");
@ -224,10 +224,10 @@ testRun(void)
TEST_ERROR_FMT(
queueNeed(strNew("000000010000000100000001"), false, queueSize, walSegmentSize, PG_VERSION_92),
PathOpenError, "unable to open path '%s/spool/archive/db/in' for read: [2] No such file or directory", testPath());
PathOpenError, "unable to open path '%s/spool/archive/test1/in' for read: [2] No such file or directory", testPath());
// -------------------------------------------------------------------------------------------------------------------------
storagePathCreateNP(storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_IN));
storagePathCreateNP(storageSpoolWrite(), strNew(STORAGE_SPOOL_ARCHIVE_IN));
TEST_RESULT_STR(
strPtr(strLstJoin(queueNeed(strNew("000000010000000100000001"), false, queueSize, walSegmentSize, PG_VERSION_92), "|")),
@ -246,30 +246,30 @@ testRun(void)
storagePutNP(
storageNewWriteNP(
storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_IN "/0000000100000001000000FE")), walSegmentBuffer);
storageSpoolWrite(), strNew(STORAGE_SPOOL_ARCHIVE_IN "/0000000100000001000000FE")), walSegmentBuffer);
storagePutNP(
storageNewWriteNP(
storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_IN "/0000000100000001000000FF")), walSegmentBuffer);
storageSpoolWrite(), strNew(STORAGE_SPOOL_ARCHIVE_IN "/0000000100000001000000FF")), walSegmentBuffer);
TEST_RESULT_STR(
strPtr(strLstJoin(queueNeed(strNew("0000000100000001000000FE"), false, queueSize, walSegmentSize, PG_VERSION_92), "|")),
"000000010000000200000000|000000010000000200000001", "queue has wal < 9.3");
TEST_RESULT_STR(
strPtr(strLstJoin(storageListNP(storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_IN)), "|")),
strPtr(strLstJoin(storageListNP(storageSpoolWrite(), strNew(STORAGE_SPOOL_ARCHIVE_IN)), "|")),
"0000000100000001000000FE", "check queue");
// -------------------------------------------------------------------------------------------------------------------------
walSegmentSize = 1024 * 1024;
queueSize = walSegmentSize * 5;
storagePutNP(storageNewWriteNP(storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_IN "/junk")), bufNewStr(strNew("JUNK")));
storagePutNP(storageNewWriteNP(storageSpoolWrite(), strNew(STORAGE_SPOOL_ARCHIVE_IN "/junk")), bufNewStr(strNew("JUNK")));
storagePutNP(
storageNewWriteNP(
storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_IN "/000000010000000A00000FFE")), walSegmentBuffer);
storageSpoolWrite(), strNew(STORAGE_SPOOL_ARCHIVE_IN "/000000010000000A00000FFE")), walSegmentBuffer);
storagePutNP(
storageNewWriteNP(
storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_IN "/000000010000000A00000FFF")), walSegmentBuffer);
storageSpoolWrite(), strNew(STORAGE_SPOOL_ARCHIVE_IN "/000000010000000A00000FFF")), walSegmentBuffer);
TEST_RESULT_STR(
strPtr(strLstJoin(queueNeed(strNew("000000010000000A00000FFD"), true, queueSize, walSegmentSize, PG_VERSION_11), "|")),
@ -279,7 +279,7 @@ testRun(void)
strPtr(strLstJoin(strLstSort(storageListNP(storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_IN)), sortOrderAsc), "|")),
"000000010000000A00000FFE|000000010000000A00000FFF", "check queue");
storagePathRemoveP(storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_IN), .recurse = true);
storagePathRemoveP(storageSpoolWrite(), strNew(STORAGE_SPOOL_ARCHIVE_IN), .recurse = true);
}
// *****************************************************************************************************************************
@ -378,7 +378,7 @@ testRun(void)
harnessCfgLoad(strLstSize(argList), strLstPtr(argList));
storagePutNP(
storageNewWriteNP(storageSpool(), strNewFmt(STORAGE_SPOOL_ARCHIVE_IN "/%s.ok", strPtr(walSegment))), NULL);
storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_IN "/%s.ok", strPtr(walSegment))), NULL);
TEST_RESULT_VOID(cmdArchiveGet(), "successful get of missing WAL");
harnessLogResult("P00 INFO: unable to find 000000010000000100000001 in the archive");
@ -390,7 +390,7 @@ testRun(void)
// Write out a WAL segment for success
// -------------------------------------------------------------------------------------------------------------------------
storagePutNP(
storageNewWriteNP(storageSpool(), strNewFmt(STORAGE_SPOOL_ARCHIVE_IN "/%s", strPtr(walSegment))),
storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_IN "/%s", strPtr(walSegment))),
bufNewStr(strNew("SHOULD-BE-A-REAL-WAL-FILE")));
TEST_RESULT_VOID(cmdArchiveGet(), "successful get");
@ -407,10 +407,10 @@ testRun(void)
String *walSegment2 = strNew("000000010000000100000002");
storagePutNP(
storageNewWriteNP(storageSpool(), strNewFmt(STORAGE_SPOOL_ARCHIVE_IN "/%s", strPtr(walSegment))),
storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_IN "/%s", strPtr(walSegment))),
bufNewStr(strNew("SHOULD-BE-A-REAL-WAL-FILE")));
storagePutNP(
storageNewWriteNP(storageSpool(), strNewFmt(STORAGE_SPOOL_ARCHIVE_IN "/%s", strPtr(walSegment2))),
storageNewWriteNP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_IN "/%s", strPtr(walSegment2))),
bufNewStr(strNew("SHOULD-BE-A-REAL-WAL-FILE")));
TEST_RESULT_VOID(cmdArchiveGet(), "successful get");

View File

@ -60,7 +60,7 @@ testRun(void)
storagePathRemoveNP(storageTest, strNewFmt("%s/db/archive_status", testPath()));
String *errorFile = storagePathNP(storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.error"));
storagePutNP(storageNewWriteNP(storageSpool(), errorFile), bufNewStr(strNew("25\n" BOGUS_STR)));
storagePutNP(storageNewWriteNP(storageSpoolWrite(), errorFile), bufNewStr(strNew("25\n" BOGUS_STR)));
TEST_ERROR(cmdArchivePush(), AssertError, BOGUS_STR);
@ -69,13 +69,14 @@ testRun(void)
// Write out a valid ok file and test for success
// -------------------------------------------------------------------------------------------------------------------------
storagePutNP(
storageNewWriteNP(storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.ok")),
storageNewWriteNP(storageSpoolWrite(), strNew(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.ok")),
bufNewStr(strNew("")));
TEST_RESULT_VOID(cmdArchivePush(), "successful push");
harnessLogResult("P00 INFO: pushed WAL segment 000000010000000100000001 asynchronously");
storageRemoveP(storageSpool(), strNew(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.ok"), .errorOnMissing = true);
storageRemoveP(
storageSpoolWrite(), strNew(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.ok"), .errorOnMissing = true);
// Make sure the process times out when there is nothing to archive and it can't get a lock. This test MUST go last since
// the lock is lost and cannot be closed by the main process.

View File

@ -1,67 +0,0 @@
/***********************************************************************************************************************************
Test Protocol Storage Helper
***********************************************************************************************************************************/
#include "common/harnessConfig.h"
/***********************************************************************************************************************************
Test Run
***********************************************************************************************************************************/
void
testRun(void)
{
FUNCTION_HARNESS_VOID();
String *writeFile = strNewFmt("%s/writefile", testPath());
// *****************************************************************************************************************************
if (testBegin("protocolStorageHelperInit()"))
{
TEST_RESULT_PTR(protocolStorageHelper.memContext, NULL, "mem context not created");
TEST_RESULT_VOID(protocolStorageHelperInit(), "create mem context");
TEST_RESULT_BOOL(protocolStorageHelper.memContext != NULL, true, "mem context created");
TEST_RESULT_VOID(protocolStorageHelperInit(), "reinit does nothing");
}
// *****************************************************************************************************************************
if (testBegin("storageRepo()"))
{
const Storage *storage = NULL;
// Load configuration to set repo-path and stanza
StringList *argList = strLstNew();
strLstAddZ(argList, "pgbackrest");
strLstAddZ(argList, "--stanza=db");
strLstAdd(argList, strNewFmt("--repo-path=%s", testPath()));
strLstAddZ(argList, "archive-get");
harnessCfgLoad(strLstSize(argList), strLstPtr(argList));
TEST_RESULT_PTR(protocolStorageHelper.storageRepo, NULL, "repo storage not cached");
TEST_ASSIGN(storage, storageRepo(), "new storage");
TEST_RESULT_PTR(protocolStorageHelper.storageRepo, storage, "repo storage cached");
TEST_RESULT_PTR(storageRepo(), storage, "get cached storage");
// -------------------------------------------------------------------------------------------------------------------------
TEST_ERROR(storagePathNP(storage, strNew("<BOGUS>/path")), AssertError, "invalid expression '<BOGUS>'");
TEST_ERROR(storageNewWriteNP(storage, writeFile), AssertError, "function debug assertion 'this->write' failed");
TEST_RESULT_STR(strPtr(storagePathNP(storage, NULL)), testPath(), "check base path");
TEST_RESULT_STR(
strPtr(storagePathNP(storage, strNew(STORAGE_REPO_ARCHIVE))), strPtr(strNewFmt("%s/archive/db", testPath())),
"check archive path");
TEST_RESULT_STR(
strPtr(storagePathNP(storage, strNew(STORAGE_REPO_ARCHIVE "/simple"))),
strPtr(strNewFmt("%s/archive/db/simple", testPath())), "check simple path");
TEST_RESULT_STR(
strPtr(storagePathNP(storage, strNew(STORAGE_REPO_ARCHIVE "/9.4-1/700000007000000070000000"))),
strPtr(strNewFmt("%s/archive/db/9.4-1/7000000070000000/700000007000000070000000", testPath())), "check segment path");
TEST_RESULT_STR(
strPtr(storagePathNP(storage, strNew(STORAGE_REPO_ARCHIVE "/9.4-1/00000008.history"))),
strPtr(strNewFmt("%s/archive/db/9.4-1/00000008.history", testPath())), "check history path");
TEST_RESULT_STR(
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())),
"check backup path");
}
FUNCTION_HARNESS_RESULT_VOID();
}

View File

@ -1,6 +1,7 @@
/***********************************************************************************************************************************
Test Storage Helper
***********************************************************************************************************************************/
#include "common/harnessConfig.h"
/***********************************************************************************************************************************
Test Run
@ -12,29 +13,24 @@ testRun(void)
String *writeFile = strNewFmt("%s/writefile", testPath());
// -----------------------------------------------------------------------------------------------------------------------------
if (testBegin("storageLocal()"))
// *****************************************************************************************************************************
if (testBegin("storageLocal() and storageLocalWrite()"))
{
const Storage *storage = NULL;
TEST_RESULT_PTR(storageLocalData, NULL, "local storage not cached");
TEST_RESULT_PTR(storageHelper.storageLocal, NULL, "local storage not cached");
TEST_ASSIGN(storage, storageLocal(), "new storage");
TEST_RESULT_PTR(storageLocalData, storage, "local storage cached");
TEST_RESULT_PTR(storageHelper.storageLocal, storage, "local storage cached");
TEST_RESULT_PTR(storageLocal(), storage, "get cached storage");
TEST_RESULT_STR(strPtr(storagePathNP(storage, NULL)), "/", "check base path");
TEST_ERROR(storageNewWriteNP(storage, writeFile), AssertError, "function debug assertion 'this->write' failed");
}
// -----------------------------------------------------------------------------------------------------------------------------
if (testBegin("storageLocalWrite()"))
{
const Storage *storage = NULL;
TEST_RESULT_PTR(storageLocalWriteData, NULL, "local storage not cached");
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_PTR(storageHelper.storageLocalWrite, NULL, "local storage not cached");
TEST_ASSIGN(storage, storageLocalWrite(), "new storage");
TEST_RESULT_PTR(storageLocalWriteData, storage, "local storage cached");
TEST_RESULT_PTR(storageHelper.storageLocalWrite, storage, "local storage cached");
TEST_RESULT_PTR(storageLocalWrite(), storage, "get cached storage");
TEST_RESULT_STR(strPtr(storagePathNP(storage, NULL)), "/", "check base path");
@ -42,22 +38,80 @@ testRun(void)
TEST_RESULT_VOID(storageNewWriteNP(storage, writeFile), "writes are allowed");
}
// -----------------------------------------------------------------------------------------------------------------------------
if (testBegin("storageSpool()"))
// *****************************************************************************************************************************
if (testBegin("storageRepo()"))
{
const Storage *storage = NULL;
// Initialize config
cfgInit();
cfgOptionSet(cfgOptSpoolPath, cfgSourceConfig, varNewStr(strNew(testPath())));
cfgOptionSet(cfgOptBufferSize, cfgSourceConfig, varNewInt(65536));
cfgOptionSet(cfgOptStanza, cfgSourceConfig, varNewStr(strNew("db")));
// Load configuration to set repo-path and stanza
StringList *argList = strLstNew();
strLstAddZ(argList, "pgbackrest");
strLstAddZ(argList, "--stanza=db");
strLstAdd(argList, strNewFmt("--repo-path=%s", testPath()));
strLstAddZ(argList, "archive-get");
harnessCfgLoad(strLstSize(argList), strLstPtr(argList));
TEST_RESULT_PTR(storageSpoolData, NULL, "storage not cached");
TEST_RESULT_PTR(storageHelper.storageRepo, NULL, "repo storage not cached");
TEST_ASSIGN(storage, storageRepo(), "new storage");
TEST_RESULT_PTR(storageHelper.storageRepo, storage, "repo storage cached");
TEST_RESULT_PTR(storageRepo(), storage, "get cached storage");
// -------------------------------------------------------------------------------------------------------------------------
TEST_ERROR(storagePathNP(storage, strNew("<BOGUS>/path")), AssertError, "invalid expression '<BOGUS>'");
TEST_ERROR(storageNewWriteNP(storage, writeFile), AssertError, "function debug assertion 'this->write' failed");
TEST_RESULT_STR(strPtr(storagePathNP(storage, NULL)), testPath(), "check base path");
TEST_RESULT_STR(
strPtr(storagePathNP(storage, strNew(STORAGE_REPO_ARCHIVE))), strPtr(strNewFmt("%s/archive/db", testPath())),
"check archive path");
TEST_RESULT_STR(
strPtr(storagePathNP(storage, strNew(STORAGE_REPO_ARCHIVE "/simple"))),
strPtr(strNewFmt("%s/archive/db/simple", testPath())), "check simple path");
TEST_RESULT_STR(
strPtr(storagePathNP(storage, strNew(STORAGE_REPO_ARCHIVE "/9.4-1/700000007000000070000000"))),
strPtr(strNewFmt("%s/archive/db/9.4-1/7000000070000000/700000007000000070000000", testPath())), "check segment path");
TEST_RESULT_STR(
strPtr(storagePathNP(storage, strNew(STORAGE_REPO_ARCHIVE "/9.4-1/00000008.history"))),
strPtr(strNewFmt("%s/archive/db/9.4-1/00000008.history", testPath())), "check history path");
TEST_RESULT_STR(
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())),
"check backup path");
// Change the stanza name and make sure helper fails
// -------------------------------------------------------------------------------------------------------------------------
storageHelper.storageRepo = NULL;
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 'db' to 'other'");
}
// *****************************************************************************************************************************
if (testBegin("storageSpool() and storageSpoolWrite()"))
{
const Storage *storage = NULL;
// Load configuration to set spool-path and stanza
StringList *argList = strLstNew();
strLstAddZ(argList, "pgbackrest");
strLstAddZ(argList, "--stanza=db");
strLstAddZ(argList, "--archive-async");
strLstAdd(argList, strNewFmt("--spool-path=%s", testPath()));
strLstAddZ(argList, "archive-get");
harnessCfgLoad(strLstSize(argList), strLstPtr(argList));
TEST_RESULT_PTR(storageHelper.storageSpool, NULL, "storage not cached");
TEST_ASSIGN(storage, storageSpool(), "new storage");
TEST_RESULT_PTR(storageSpoolData, storage, "storage cached");
TEST_RESULT_PTR(storageHelper.storageSpool, storage, "storage cached");
TEST_RESULT_PTR(storageSpool(), storage, "get cached storage");
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_STR(strPtr(storagePathNP(storage, NULL)), testPath(), "check base path");
TEST_RESULT_STR(
strPtr(storagePathNP(storage, strNew(STORAGE_SPOOL_ARCHIVE_OUT))), strPtr(strNewFmt("%s/archive/db/out", testPath())),
@ -75,6 +129,14 @@ testRun(void)
TEST_ERROR(storagePathNP(storage, strNew("<" BOGUS_STR ">")), AssertError, "invalid expression '<BOGUS>'");
TEST_ERROR(storageNewWriteNP(storage, writeFile), AssertError, "function debug assertion 'this->write' failed");
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_PTR(storageHelper.storageSpoolWrite, NULL, "storage not cached");
TEST_ASSIGN(storage, storageSpoolWrite(), "new storage");
TEST_RESULT_PTR(storageHelper.storageSpoolWrite, storage, "storage cached");
TEST_RESULT_PTR(storageSpoolWrite(), storage, "get cached storage");
TEST_RESULT_VOID(storageNewWriteNP(storage, writeFile), "writes are allowed");
}