1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-07-15 01:04:37 +02:00

Use designated initializers to initialize structs.

Previously memNew() used memset() to initialize all struct members to 0, NULL, false, etc.  While this appears to work in practice, it is a violation of the C specification.  For instance, NULL == 0 must be true but neither NULL nor 0 must be represented with all zero bits.

Instead use designated initializers to initialize structs.  These guarantee that struct members will be properly initialized even if they are not specified in the initializer.  Note that due to a quirk in the C99 specification at least one member must be explicitly initialized even if it needs to be the default value.

Since pre-zeroed memory is no longer required, adjust memAllocInternal()/memReallocInternal() to return raw memory and update dependent functions accordingly.  All instances of memset() have been removed except in debug/test code where needed.

Add memMewPtrArray() to allocate an array of pointers and automatically set all pointers to NULL.

Rename memGrowRaw() to the more logical memResize().
This commit is contained in:
David Steele
2020-01-23 14:15:58 -07:00
parent cf2024beaf
commit b134175fc7
77 changed files with 1049 additions and 716 deletions

View File

@ -220,14 +220,16 @@ pageChecksumNew(unsigned int segmentNo, unsigned int segmentPageTotal, size_t pa
MEM_CONTEXT_NEW_BEGIN("PageChecksum")
{
PageChecksum *driver = memNew(sizeof(PageChecksum));
driver->memContext = memContextCurrent();
driver->pageNoOffset = segmentNo * segmentPageTotal;
driver->pageSize = pageSize;
driver->lsnLimit = lsnLimit;
driver->valid = true;
driver->align = true;
*driver = (PageChecksum)
{
.memContext = memContextCurrent(),
.pageNoOffset = segmentNo * segmentPageTotal,
.pageSize = pageSize,
.lsnLimit = lsnLimit,
.valid = true,
.align = true,
};
// Create param list
VariantList *paramList = varLstNew();

View File

@ -779,8 +779,12 @@ restoreCleanBuild(Manifest *manifest)
{
RestoreCleanCallbackData *cleanData = &cleanDataList[targetIdx];
cleanData->manifest = manifest;
cleanData->target = manifestTarget(manifest, targetIdx);
*cleanData = (RestoreCleanCallbackData)
{
.manifest = manifest,
.target = manifestTarget(manifest, targetIdx),
};
cleanData->targetName = cleanData->target->name;
cleanData->targetPath = manifestTargetPath(manifest, cleanData->target);
cleanData->basePath = strEq(cleanData->targetName, MANIFEST_TARGET_PGDATA_STR);

View File

@ -28,7 +28,7 @@ Object type
typedef struct GzipCompress
{
MemContext *memContext; // Context to store data
z_stream *stream; // Compression stream state
z_stream stream; // Compression stream state
bool inputSame; // Is the same input required on the next process call?
bool flush; // Is input complete and flushing in progress?
@ -43,7 +43,7 @@ gzipCompressToLog(const GzipCompress *this)
{
return strNewFmt(
"{inputSame: %s, done: %s, flushing: %s, availIn: %u}", cvtBoolToConstZ(this->inputSame), cvtBoolToConstZ(this->done),
cvtBoolToConstZ(this->done), this->stream->avail_in);
cvtBoolToConstZ(this->done), this->stream.avail_in);
}
#define FUNCTION_LOG_GZIP_COMPRESS_TYPE \
@ -61,7 +61,7 @@ Free deflate stream
***********************************************************************************************************************************/
OBJECT_DEFINE_FREE_RESOURCE_BEGIN(GZIP_COMPRESS, LOG, logLevelTrace)
{
deflateEnd(this->stream);
deflateEnd(&this->stream);
}
OBJECT_DEFINE_FREE_RESOURCE_END(LOG);
@ -81,15 +81,14 @@ gzipCompressProcess(THIS_VOID, const Buffer *uncompressed, Buffer *compressed)
ASSERT(this != NULL);
ASSERT(!this->done);
ASSERT(this->stream != NULL);
ASSERT(compressed != NULL);
ASSERT(!this->flush || uncompressed == NULL);
ASSERT(this->flush || (!this->inputSame || this->stream->avail_in != 0));
ASSERT(this->flush || (!this->inputSame || this->stream.avail_in != 0));
// Flushing
if (uncompressed == NULL)
{
this->stream->avail_in = 0;
this->stream.avail_in = 0;
this->flush = true;
}
// More input
@ -98,27 +97,27 @@ gzipCompressProcess(THIS_VOID, const Buffer *uncompressed, Buffer *compressed)
// Is new input allowed?
if (!this->inputSame)
{
this->stream->avail_in = (unsigned int)bufUsed(uncompressed);
this->stream->next_in = bufPtr(uncompressed);
this->stream.avail_in = (unsigned int)bufUsed(uncompressed);
this->stream.next_in = bufPtr(uncompressed);
}
}
// Initialize compressed output buffer
this->stream->avail_out = (unsigned int)bufRemains(compressed);
this->stream->next_out = bufPtr(compressed) + bufUsed(compressed);
this->stream.avail_out = (unsigned int)bufRemains(compressed);
this->stream.next_out = bufPtr(compressed) + bufUsed(compressed);
// Perform compression
gzipError(deflate(this->stream, this->flush ? Z_FINISH : Z_NO_FLUSH));
gzipError(deflate(&this->stream, this->flush ? Z_FINISH : Z_NO_FLUSH));
// Set buffer used space
bufUsedSet(compressed, bufSize(compressed) - (size_t)this->stream->avail_out);
bufUsedSet(compressed, bufSize(compressed) - (size_t)this->stream.avail_out);
// Is compression done?
if (this->flush && this->stream->avail_out > 0)
if (this->flush && this->stream.avail_out > 0)
this->done = true;
// Can more input be provided on the next call?
this->inputSame = this->flush ? !this->done : this->stream->avail_in != 0;
this->inputSame = this->flush ? !this->done : this->stream.avail_in != 0;
FUNCTION_LOG_RETURN_VOID();
}
@ -175,11 +174,15 @@ gzipCompressNew(int level, bool raw)
MEM_CONTEXT_NEW_BEGIN("GzipCompress")
{
GzipCompress *driver = memNew(sizeof(GzipCompress));
driver->memContext = MEM_CONTEXT_NEW();
*driver = (GzipCompress)
{
.memContext = MEM_CONTEXT_NEW(),
.stream = {.zalloc = NULL},
};
// Create gzip stream
driver->stream = memNew(sizeof(z_stream));
gzipError(deflateInit2(driver->stream, level, Z_DEFLATED, gzipWindowBits(raw), MEM_LEVEL, Z_DEFAULT_STRATEGY));
gzipError(deflateInit2(&driver->stream, level, Z_DEFLATED, gzipWindowBits(raw), MEM_LEVEL, Z_DEFAULT_STRATEGY));
// Set free callback to ensure gzip context is freed
memContextCallbackSet(driver->memContext, gzipCompressFreeResource, driver);

View File

@ -28,7 +28,7 @@ Object type
typedef struct GzipDecompress
{
MemContext *memContext; // Context to store data
z_stream *stream; // Decompression stream state
z_stream stream; // Decompression stream state
int result; // Result of last operation
bool inputSame; // Is the same input required on the next process call?
@ -43,7 +43,7 @@ gzipDecompressToLog(const GzipDecompress *this)
{
return strNewFmt(
"{inputSame: %s, done: %s, availIn: %u}", cvtBoolToConstZ(this->inputSame), cvtBoolToConstZ(this->done),
this->stream->avail_in);
this->stream.avail_in);
}
#define FUNCTION_LOG_GZIP_DECOMPRESS_TYPE \
@ -56,7 +56,7 @@ Free inflate stream
***********************************************************************************************************************************/
OBJECT_DEFINE_FREE_RESOURCE_BEGIN(GZIP_DECOMPRESS, LOG, logLevelTrace)
{
inflateEnd(this->stream);
inflateEnd(&this->stream);
}
OBJECT_DEFINE_FREE_RESOURCE_END(LOG);
@ -75,7 +75,6 @@ gzipDecompressProcess(THIS_VOID, const Buffer *compressed, Buffer *uncompressed)
FUNCTION_LOG_END();
ASSERT(this != NULL);
ASSERT(this->stream != NULL);
ASSERT(uncompressed != NULL);
// There should never be a flush because in a valid compressed stream the end of data can be determined and done will be set.
@ -85,23 +84,23 @@ gzipDecompressProcess(THIS_VOID, const Buffer *compressed, Buffer *uncompressed)
if (!this->inputSame)
{
this->stream->avail_in = (unsigned int)bufUsed(compressed);
this->stream->next_in = bufPtr(compressed);
this->stream.avail_in = (unsigned int)bufUsed(compressed);
this->stream.next_in = bufPtr(compressed);
}
this->stream->avail_out = (unsigned int)bufRemains(uncompressed);
this->stream->next_out = bufPtr(uncompressed) + bufUsed(uncompressed);
this->stream.avail_out = (unsigned int)bufRemains(uncompressed);
this->stream.next_out = bufPtr(uncompressed) + bufUsed(uncompressed);
this->result = gzipError(inflate(this->stream, Z_NO_FLUSH));
this->result = gzipError(inflate(&this->stream, Z_NO_FLUSH));
// Set buffer used space
bufUsedSet(uncompressed, bufSize(uncompressed) - (size_t)this->stream->avail_out);
bufUsedSet(uncompressed, bufSize(uncompressed) - (size_t)this->stream.avail_out);
// Is decompression done?
this->done = this->result == Z_STREAM_END;
// Is the same input expected on the next call?
this->inputSame = this->done ? false : this->stream->avail_in != 0;
this->inputSame = this->done ? false : this->stream.avail_in != 0;
FUNCTION_LOG_RETURN_VOID();
}
@ -156,11 +155,15 @@ gzipDecompressNew(bool raw)
{
// Allocate state and set context
GzipDecompress *driver = memNew(sizeof(GzipDecompress));
driver->memContext = MEM_CONTEXT_NEW();
*driver = (GzipDecompress)
{
.memContext = MEM_CONTEXT_NEW(),
.stream = {.zalloc = NULL},
};
// Create gzip stream
driver->stream = memNew(sizeof(z_stream));
gzipError(driver->result = inflateInit2(driver->stream, gzipWindowBits(raw)));
gzipError(driver->result = inflateInit2(&driver->stream, gzipWindowBits(raw)));
// Set free callback to ensure gzip context is freed
memContextCallbackSet(driver->memContext, gzipDecompressFreeResource, driver);

View File

@ -420,18 +420,18 @@ cipherBlockNew(CipherMode mode, CipherType cipherType, const Buffer *pass, const
MEM_CONTEXT_NEW_BEGIN("CipherBlock")
{
CipherBlock *driver = memNew(sizeof(CipherBlock));
driver->memContext = MEM_CONTEXT_NEW();
// Set mode, encrypt or decrypt
driver->mode = mode;
// Set cipher and digest
driver->cipher = cipher;
driver->digest = digest;
*driver = (CipherBlock)
{
.memContext = MEM_CONTEXT_NEW(),
.mode = mode,
.cipher = cipher,
.digest = digest,
.passSize = bufUsed(pass),
};
// Store the passphrase
driver->passSize = bufUsed(pass);
driver->pass = memNewRaw(driver->passSize);
driver->pass = memNew(driver->passSize);
memcpy(driver->pass, bufPtr(pass), driver->passSize);
// Create param list

View File

@ -154,7 +154,11 @@ cryptoHashNew(const String *type)
MEM_CONTEXT_NEW_BEGIN("CryptoHash")
{
CryptoHash *driver = memNew(sizeof(CryptoHash));
driver->memContext = MEM_CONTEXT_NEW();
*driver = (CryptoHash)
{
.memContext = MEM_CONTEXT_NEW(),
};
// Lookup digest
if ((driver->hashType = EVP_get_digestbyname(strPtr(type))) == NULL)

View File

@ -127,21 +127,20 @@ execNew(const String *command, const StringList *param, const String *name, Time
MEM_CONTEXT_NEW_BEGIN("Exec")
{
this = memNew(sizeof(Exec));
this->memContext = MEM_CONTEXT_NEW();
this->command = strDup(command);
*this = (Exec)
{
.memContext = MEM_CONTEXT_NEW(),
.command = strDup(command),
.name = strDup(name),
.timeout = timeout,
// Parameter list is optional but if not specified we need to build one with the command
if (param == NULL)
this->param = strLstNew();
else
this->param = strLstDup(param);
.param = param == NULL ? strLstNew() : strLstDup(param),
};
// The first parameter must be the command
strLstInsert(this->param, 0, this->command);
this->name = strDup(name);
this->timeout = timeout;
}
MEM_CONTEXT_NEW_END();

View File

@ -38,12 +38,13 @@ iniNew(void)
MEM_CONTEXT_NEW_BEGIN("Ini")
{
// Create object
this = memNew(sizeof(Ini));
this->memContext = MEM_CONTEXT_NEW();
// Allocate key value store
this->store = kvNew();
*this = (Ini)
{
.memContext = MEM_CONTEXT_NEW(),
.store = kvNew(),
};
}
MEM_CONTEXT_NEW_END();

View File

@ -101,8 +101,12 @@ ioBufferReadNew(const Buffer *buffer)
MEM_CONTEXT_NEW_BEGIN("IoBufferRead")
{
IoBufferRead *driver = memNew(sizeof(IoBufferRead));
driver->memContext = memContextCurrent();
driver->read = buffer;
*driver = (IoBufferRead)
{
.memContext = MEM_CONTEXT_NEW(),
.read = buffer,
};
this = ioReadNewP(driver, .eof = ioBufferReadEof, .read = ioBufferRead);
}

View File

@ -65,8 +65,12 @@ ioBufferWriteNew(Buffer *buffer)
MEM_CONTEXT_NEW_BEGIN("IoBufferWrite")
{
IoBufferWrite *driver = memNew(sizeof(IoBufferWrite));
driver->memContext = memContextCurrent();
driver->write = buffer;
*driver = (IoBufferWrite)
{
.memContext = memContextCurrent(),
.write = buffer,
};
this = ioWriteNewP(driver, .write = ioBufferWrite);
}

View File

@ -119,7 +119,11 @@ ioBufferNew(void)
MEM_CONTEXT_NEW_BEGIN("IoBuffer")
{
IoBuffer *driver = memNew(sizeof(IoBuffer));
driver->memContext = memContextCurrent();
*driver = (IoBuffer)
{
.memContext = memContextCurrent(),
};
this = ioFilterNewP(BUFFER_FILTER_TYPE_STR, driver, NULL, .inOut = ioBufferProcess, .inputSame = ioBufferInputSame);
}

View File

@ -51,11 +51,15 @@ ioFilterNew(const String *type, void *driver, VariantList *paramList, IoFilterIn
ASSERT(interface.in == NULL || (interface.result != NULL && interface.done == NULL && interface.inputSame == NULL));
IoFilter *this = memNew(sizeof(IoFilter));
this->memContext = memContextCurrent();
this->type = type;
this->driver = driver;
this->paramList = paramList;
this->interface = interface;
*this = (IoFilter)
{
.memContext = memContextCurrent(),
.type = type,
.driver = driver,
.paramList = paramList,
.interface = interface,
};
FUNCTION_LOG_RETURN(IO_FILTER, this);
}

View File

@ -68,9 +68,13 @@ ioFilterGroupNew(void)
MEM_CONTEXT_NEW_BEGIN("IoFilterGroup")
{
this = memNew(sizeof(IoFilterGroup));
this->memContext = memContextCurrent();
this->done = false;
this->filterList = lstNew(sizeof(IoFilterData));
*this = (IoFilterGroup)
{
.memContext = memContextCurrent(),
.done = false,
.filterList = lstNew(sizeof(IoFilterData)),
};
}
MEM_CONTEXT_NEW_END();

View File

@ -65,7 +65,11 @@ ioSinkNew(void)
MEM_CONTEXT_NEW_BEGIN("IoSink")
{
IoSink *driver = memNew(sizeof(IoSink));
driver->memContext = memContextCurrent();
*driver = (IoSink)
{
.memContext = memContextCurrent(),
};
this = ioFilterNewP(SINK_FILTER_TYPE_STR, driver, NULL, .inOut = ioSinkProcess);
}

View File

@ -92,7 +92,11 @@ ioSizeNew(void)
MEM_CONTEXT_NEW_BEGIN("IoSize")
{
IoSize *driver = memNew(sizeof(IoSize));
driver->memContext = memContextCurrent();
*driver = (IoSize)
{
.memContext = memContextCurrent(),
};
this = ioFilterNewP(SIZE_FILTER_TYPE_STR, driver, NULL, .in = ioSizeProcess, .result = ioSizeResult);
}

View File

@ -147,10 +147,14 @@ ioHandleReadNew(const String *name, int handle, TimeMSec timeout)
MEM_CONTEXT_NEW_BEGIN("IoHandleRead")
{
IoHandleRead *driver = memNew(sizeof(IoHandleRead));
driver->memContext = memContextCurrent();
driver->name = strDup(name);
driver->handle = handle;
driver->timeout = timeout;
*driver = (IoHandleRead)
{
.memContext = memContextCurrent(),
.name = strDup(name),
.handle = handle,
.timeout = timeout,
};
this = ioReadNewP(driver, .block = true, .eof = ioHandleReadEof, .handle = ioHandleReadHandle, .read = ioHandleRead);
}

View File

@ -84,9 +84,13 @@ ioHandleWriteNew(const String *name, int handle)
MEM_CONTEXT_NEW_BEGIN("IoHandleWrite")
{
IoHandleWrite *driver = memNew(sizeof(IoHandleWrite));
driver->memContext = memContextCurrent();
driver->name = strDup(name);
driver->handle = handle;
*driver = (IoHandleWrite)
{
.memContext = memContextCurrent(),
.name = strDup(name),
.handle = handle,
};
this = ioWriteNewP(driver, .handle = ioHandleWriteHandle, .write = ioHandleWrite);
}

View File

@ -52,16 +52,18 @@ httpClientCacheNew(
{
// Allocate state and set context
this = memNew(sizeof(HttpClientCache));
this->memContext = MEM_CONTEXT_NEW();
this->host = strDup(host);
this->port = port;
this->timeout = timeout;
this->verifyPeer = verifyPeer;
this->caFile = strDup(caFile);
this->caPath = strDup(caPath);
this->clientList = lstNew(sizeof(HttpClient *));
*this = (HttpClientCache)
{
.memContext = MEM_CONTEXT_NEW(),
.host = strDup(host),
.port = port,
.timeout = timeout,
.verifyPeer = verifyPeer,
.caFile = strDup(caFile),
.caPath = strDup(caPath),
.clientList = lstNew(sizeof(HttpClient *)),
};
}
MEM_CONTEXT_NEW_END();

View File

@ -194,12 +194,14 @@ httpClientNew(
MEM_CONTEXT_NEW_BEGIN("HttpClient")
{
// Allocate state and set context
this = memNew(sizeof(HttpClient));
this->memContext = MEM_CONTEXT_NEW();
this->timeout = timeout;
this->tls = tlsClientNew(host, port, timeout, verifyPeer, caFile, caPath);
*this = (HttpClient)
{
.memContext = MEM_CONTEXT_NEW(),
.timeout = timeout,
.tls = tlsClientNew(host, port, timeout, verifyPeer, caFile, caPath),
};
httpClientStatLocal.object++;
}

View File

@ -36,10 +36,13 @@ httpHeaderNew(const StringList *redactList)
{
// Allocate state and set context
this = memNew(sizeof(HttpHeader));
this->memContext = MEM_CONTEXT_NEW();
this->redactList = strLstDup(redactList);
this->kv = kvNew();
*this = (HttpHeader)
{
.memContext = MEM_CONTEXT_NEW(),
.redactList = strLstDup(redactList),
.kv = kvNew(),
};
}
MEM_CONTEXT_NEW_END();
@ -61,15 +64,17 @@ httpHeaderDup(const HttpHeader *header, const StringList *redactList)
if (header != NULL)
{
MEM_CONTEXT_NEW_BEGIN("HttpHeader")
{
// Allocate state and set context
this = memNew(sizeof(HttpHeader));
this->memContext = MEM_CONTEXT_NEW();
this->redactList = redactList == NULL ? strLstDup(header->redactList) : strLstDup(redactList);
this->kv = kvDup(header->kv);
*this = (HttpHeader)
{
.memContext = MEM_CONTEXT_NEW(),
.redactList = redactList == NULL ? strLstDup(header->redactList) : strLstDup(redactList),
.kv = kvDup(header->kv),
};
}
MEM_CONTEXT_NEW_END();
}

View File

@ -36,8 +36,12 @@ httpQueryNew(void)
{
// Allocate state and set context
this = memNew(sizeof(HttpQuery));
this->memContext = MEM_CONTEXT_NEW();
this->kv = kvNew();
*this = (HttpQuery)
{
.memContext = MEM_CONTEXT_NEW(),
.kv = kvNew(),
};
}
MEM_CONTEXT_NEW_END();

View File

@ -53,11 +53,15 @@ ioReadNew(void *driver, IoReadInterface interface)
MEM_CONTEXT_NEW_BEGIN("IoRead")
{
this = memNew(sizeof(IoRead));
this->memContext = memContextCurrent();
this->driver = driver;
this->interface = interface;
this->filterGroup = ioFilterGroupNew();
this->input = bufNew(ioBufferSize());
*this = (IoRead)
{
.memContext = memContextCurrent(),
.driver = driver,
.interface = interface,
.filterGroup = ioFilterGroupNew(),
.input = bufNew(ioBufferSize()),
};
}
MEM_CONTEXT_NEW_END();

View File

@ -143,15 +143,18 @@ tlsClientNew(
MEM_CONTEXT_NEW_BEGIN("TlsClient")
{
this = memNew(sizeof(TlsClient));
this->memContext = MEM_CONTEXT_NEW();
this->host = strDup(host);
this->port = port;
this->timeout = timeout;
this->verifyPeer = verifyPeer;
*this = (TlsClient)
{
.memContext = MEM_CONTEXT_NEW(),
.host = strDup(host),
.port = port,
.timeout = timeout,
.verifyPeer = verifyPeer,
// Initialize socket to -1 so we know when it is disconnected
this->socket = -1;
.socket = -1,
};
// Setup TLS context
// -------------------------------------------------------------------------------------------------------------------------
@ -573,12 +576,12 @@ tlsClientOpen(TlsClient *this)
TRY_BEGIN()
{
// Set hits that narrow the type of address we are looking for -- we'll take ipv4 or ipv6
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
struct addrinfo hints = (struct addrinfo)
{
.ai_family = AF_UNSPEC,
.ai_socktype = SOCK_STREAM,
.ai_protocol = IPPROTO_TCP,
};
// Convert the port to a zero-terminated string for use with getaddrinfo()
char port[CVT_BASE10_BUFFER_SIZE];

View File

@ -51,11 +51,15 @@ ioWriteNew(void *driver, IoWriteInterface interface)
MEM_CONTEXT_NEW_BEGIN("IoWrite")
{
this = memNew(sizeof(IoWrite));
this->memContext = memContextCurrent();
this->driver = driver;
this->interface = interface;
this->filterGroup = ioFilterGroupNew();
this->output = bufNew(ioBufferSize());
*this = (IoWrite)
{
.memContext = memContextCurrent(),
.driver = driver,
.interface = interface,
.filterGroup = ioFilterGroupNew(),
.output = bufNew(ioBufferSize()),
};
}
MEM_CONTEXT_NEW_END();

View File

@ -64,14 +64,13 @@ All memory allocations will be done from the current context. Initialized to to
MemContext *contextCurrent = &contextTop;
/***********************************************************************************************************************************
Wrapper around malloc()
Wrapper around malloc() with error handling
***********************************************************************************************************************************/
static void *
memAllocInternal(size_t size, bool zero)
memAllocInternal(size_t size)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(SIZE, size);
FUNCTION_TEST_PARAM(BOOL, zero);
FUNCTION_TEST_END();
// Allocate memory
@ -81,25 +80,40 @@ memAllocInternal(size_t size, bool zero)
if (buffer == NULL)
THROW_FMT(MemoryError, "unable to allocate %zu bytes", size);
// Zero the memory when requested
if (zero)
memset(buffer, 0, size);
// Return the buffer
FUNCTION_TEST_RETURN(buffer);
}
/***********************************************************************************************************************************
Allocate an array of pointers and set all entries to NULL
***********************************************************************************************************************************/
static void *
memAllocPtrArrayInternal(size_t size)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(SIZE, size);
FUNCTION_TEST_END();
// Allocate memory
void **buffer = memAllocInternal(size * sizeof(void *));
// Set all pointers to NULL
for (size_t ptrIdx = 0; ptrIdx < size; ptrIdx++)
buffer[ptrIdx] = NULL;
// Return the buffer
FUNCTION_TEST_RETURN(buffer);
}
/***********************************************************************************************************************************
Wrapper around realloc()
Wrapper around realloc() with error handling
***********************************************************************************************************************************/
static void *
memReAllocInternal(void *bufferOld, size_t sizeOld, size_t sizeNew, bool zeroNew)
memReAllocInternal(void *bufferOld, size_t sizeNew)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM_P(VOID, bufferOld);
FUNCTION_TEST_PARAM(SIZE, sizeOld);
FUNCTION_TEST_PARAM(SIZE, sizeNew);
FUNCTION_TEST_PARAM(BOOL, zeroNew);
FUNCTION_TEST_END();
ASSERT(bufferOld != NULL);
@ -111,9 +125,28 @@ memReAllocInternal(void *bufferOld, size_t sizeOld, size_t sizeNew, bool zeroNew
if (bufferNew == NULL)
THROW_FMT(MemoryError, "unable to reallocate %zu bytes", sizeNew);
// Zero the new memory when requested - old memory is left untouched else why bother with a realloc?
if (zeroNew)
memset((unsigned char *)bufferNew + sizeOld, 0, sizeNew - sizeOld);
// Return the buffer
FUNCTION_TEST_RETURN(bufferNew);
}
/***********************************************************************************************************************************
Wrapper around realloc() with error handling
***********************************************************************************************************************************/
static void *
memReAllocPtrArrayInternal(void *bufferOld, size_t sizeOld, size_t sizeNew)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM_P(VOID, bufferOld);
FUNCTION_TEST_PARAM(SIZE, sizeOld);
FUNCTION_TEST_PARAM(SIZE, sizeNew);
FUNCTION_TEST_END();
// Allocate memory
void **bufferNew = memReAllocInternal(bufferOld, sizeNew * sizeof(void *));
// Set all new pointers to NULL
for (size_t ptrIdx = sizeOld; ptrIdx < sizeNew; ptrIdx++)
bufferNew[ptrIdx] = NULL;
// Return the buffer
FUNCTION_TEST_RETURN(bufferNew);
@ -166,7 +199,7 @@ memContextNewIndex(MemContext *memContext, bool allowFree)
if (memContext->contextChildListSize == 0)
{
// Allocate memory before modifying anything else in case there is an error
memContext->contextChildList = memAllocInternal(sizeof(MemContext *) * MEM_CONTEXT_INITIAL_SIZE, true);
memContext->contextChildList = memAllocPtrArrayInternal(MEM_CONTEXT_INITIAL_SIZE);
// Set new list size
memContext->contextChildListSize = MEM_CONTEXT_INITIAL_SIZE;
@ -178,9 +211,8 @@ memContextNewIndex(MemContext *memContext, bool allowFree)
unsigned int contextChildListSizeNew = memContext->contextChildListSize * 2;
// ReAllocate memory before modifying anything else in case there is an error
memContext->contextChildList = memReAllocInternal(
memContext->contextChildList, sizeof(MemContext *) * memContext->contextChildListSize,
sizeof(MemContext *) * contextChildListSizeNew, true);
memContext->contextChildList = memReAllocPtrArrayInternal(
memContext->contextChildList, memContext->contextChildListSize, contextChildListSizeNew);
// Set new list size
memContext->contextChildListSize = contextChildListSizeNew;
@ -209,25 +241,32 @@ memContextNew(const char *name)
unsigned int contextIdx = memContextNewIndex(contextCurrent, true);
// If the context has not been allocated yet
if (!contextCurrent->contextChildList[contextIdx])
contextCurrent->contextChildList[contextIdx] = memAllocInternal(sizeof(MemContext), true);
if (contextCurrent->contextChildList[contextIdx] == NULL)
contextCurrent->contextChildList[contextIdx] = memAllocInternal(sizeof(MemContext));
// Get the context
MemContext *this = contextCurrent->contextChildList[contextIdx];
*this = (MemContext)
{
// Create initial space for allocations
this->allocList = memAllocInternal(sizeof(MemContextAlloc) * MEM_CONTEXT_ALLOC_INITIAL_SIZE, true);
this->allocListSize = MEM_CONTEXT_ALLOC_INITIAL_SIZE;
.allocList = memAllocInternal(sizeof(MemContextAlloc) * MEM_CONTEXT_ALLOC_INITIAL_SIZE),
.allocListSize = MEM_CONTEXT_ALLOC_INITIAL_SIZE,
// Set the context name
this->name = name;
.name = name,
// Set new context active
this->state = memContextStateActive;
.state = memContextStateActive,
// Set current context as the parent
this->contextParent = contextCurrent;
this->contextParentIdx = contextIdx;
.contextParent = contextCurrent,
.contextParentIdx = contextIdx,
};
// Initialize allocation list
for (unsigned int allocIdx = 0; allocIdx < MEM_CONTEXT_ALLOC_INITIAL_SIZE; allocIdx++)
this->allocList[allocIdx] = (MemContextAlloc){.active = false};
// Possible free context must be in the next position
contextCurrent->contextChildFreeIdx++;
@ -297,15 +336,12 @@ memContextCallbackClear(MemContext *this)
}
/***********************************************************************************************************************************
Allocate memory in the memory context and optionally zero it.
Find an available allocation in the memory context
***********************************************************************************************************************************/
static void *
memContextAlloc(size_t size, bool zero)
static MemContextAlloc *
memContextAllocFind(void)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(SIZE, size);
FUNCTION_TEST_PARAM(BOOL, zero);
FUNCTION_TEST_END();
FUNCTION_TEST_VOID();
// Find space for the new allocation
for (; contextCurrent->allocFreeIdx < contextCurrent->allocListSize; contextCurrent->allocFreeIdx++)
@ -319,7 +355,11 @@ memContextAlloc(size_t size, bool zero)
if (contextCurrent->allocListSize == 0)
{
// Allocate memory before modifying anything else in case there is an error
contextCurrent->allocList = memAllocInternal(sizeof(MemContextAlloc) * MEM_CONTEXT_ALLOC_INITIAL_SIZE, true);
contextCurrent->allocList = memAllocInternal(sizeof(MemContextAlloc) * MEM_CONTEXT_ALLOC_INITIAL_SIZE);
// Initialize allocations in list
for (unsigned int allocIdx = 0; allocIdx < MEM_CONTEXT_ALLOC_INITIAL_SIZE; allocIdx++)
contextCurrent->allocList[allocIdx] = (MemContextAlloc){.active = false};
// Set new size
contextCurrent->allocListSize = MEM_CONTEXT_ALLOC_INITIAL_SIZE;
@ -331,23 +371,21 @@ memContextAlloc(size_t size, bool zero)
unsigned int allocListSizeNew = contextCurrent->allocListSize * 2;
// ReAllocate memory before modifying anything else in case there is an error
contextCurrent->allocList = memReAllocInternal(
contextCurrent->allocList, sizeof(MemContextAlloc) * contextCurrent->allocListSize,
sizeof(MemContextAlloc) * allocListSizeNew, true);
contextCurrent->allocList = memReAllocInternal(contextCurrent->allocList, sizeof(MemContextAlloc) * allocListSizeNew);
// Initialize new allocations in list
for (unsigned int allocIdx = contextCurrent->allocListSize; allocIdx < allocListSizeNew; allocIdx++)
contextCurrent->allocList[allocIdx] = (MemContextAlloc){.active = false};
// Set new size
contextCurrent->allocListSize = allocListSizeNew;
}
}
// Allocate the memory
contextCurrent->allocList[contextCurrent->allocFreeIdx].active = true;
contextCurrent->allocList[contextCurrent->allocFreeIdx].size = (unsigned int)size;
contextCurrent->allocList[contextCurrent->allocFreeIdx].buffer = memAllocInternal(size, zero);
contextCurrent->allocFreeIdx++;
// Return buffer
FUNCTION_TEST_RETURN(contextCurrent->allocList[contextCurrent->allocFreeIdx - 1].buffer);
FUNCTION_TEST_RETURN(&contextCurrent->allocList[contextCurrent->allocFreeIdx - 1]);
}
/***********************************************************************************************************************************
@ -376,9 +414,7 @@ memFind(const void *buffer)
FUNCTION_TEST_RETURN(allocIdx);
}
/***********************************************************************************************************************************
Allocate zeroed memory in the memory context
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
void *
memNew(size_t size)
{
@ -386,14 +422,41 @@ memNew(size_t size)
FUNCTION_TEST_PARAM(SIZE, size);
FUNCTION_TEST_END();
FUNCTION_TEST_RETURN(memContextAlloc(size, true));
MemContextAlloc *alloc = memContextAllocFind();
*alloc = (MemContextAlloc)
{
.active = true,
.size = (unsigned int)size,
.buffer = memAllocInternal(size),
};
FUNCTION_TEST_RETURN(alloc->buffer);
}
/***********************************************************************************************************************************
Grow allocated memory without initializing the new portion
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
void *
memGrowRaw(const void *buffer, size_t size)
memNewPtrArray(size_t size)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(SIZE, size);
FUNCTION_TEST_END();
MemContextAlloc *alloc = memContextAllocFind();
*alloc = (MemContextAlloc)
{
.active = true,
.size = (unsigned int)(size * sizeof(void *)),
.buffer = memAllocPtrArrayInternal(size),
};
FUNCTION_TEST_RETURN(alloc->buffer);
}
/**********************************************************************************************************************************/
void *
memResize(const void *buffer, size_t size)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM_P(VOID, buffer);
@ -406,28 +469,13 @@ memGrowRaw(const void *buffer, size_t size)
MemContextAlloc *alloc = &(contextCurrent->allocList[memFind(buffer)]);
// Grow the buffer
alloc->buffer = memReAllocInternal(alloc->buffer, alloc->size, size, false);
alloc->buffer = memReAllocInternal(alloc->buffer, size);
alloc->size = (unsigned int)size;
FUNCTION_TEST_RETURN(alloc->buffer);
}
/***********************************************************************************************************************************
Allocate memory in the memory context without initializing it
***********************************************************************************************************************************/
void *
memNewRaw(size_t size)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(SIZE, size);
FUNCTION_TEST_END();
FUNCTION_TEST_RETURN(memContextAlloc(size, false));
}
/***********************************************************************************************************************************
Free a memory allocation in the context
***********************************************************************************************************************************/
/**********************************************************************************************************************************/
void
memFree(void *buffer)
{
@ -645,7 +693,7 @@ memContextFree(MemContext *this)
this->state = memContextStateActive;
// Else reset the memory context so it can be reused
else
memset(this, 0, sizeof(MemContext));
*this = (MemContext){.state = memContextStateFree};
// Rethrow the error that was caught in the callback
if (rethrow)

View File

@ -68,13 +68,20 @@ MemContext *memContextTop(void);
const char *memContextName(MemContext *this);
/***********************************************************************************************************************************
Memory management
Memory management functions
These functions always new/free within the current memory context.
All these functions operate in the current memory context, including memResize() and memFree().
***********************************************************************************************************************************/
// Allocate memory in the current memory context
void *memNew(size_t size);
void *memNewRaw(size_t size);
void *memGrowRaw(const void *buffer, size_t size);
// Allocate requested number of pointers and initialize them to NULL
void *memNewPtrArray(size_t size);
// Reallocate to the new size. Original buffer pointer is undefined on return.
void *memResize(const void *buffer, size_t size);
// Free memory allocation
void memFree(void *buffer);
/***********************************************************************************************************************************

View File

@ -70,7 +70,11 @@ regExpNew(const String *expression)
MEM_CONTEXT_NEW_BEGIN("RegExp")
{
this = memNew(sizeof(RegExp));
this->memContext = MEM_CONTEXT_NEW();
*this = (RegExp)
{
.memContext = MEM_CONTEXT_NEW(),
};
// Compile the regexp and process errors
int result = 0;

View File

@ -124,14 +124,15 @@ stackTracePush(const char *fileName, const char *functionName, LogLevel function
backtrace_full(backTraceState, 2, backTraceCallback, backTraceCallbackError, NULL);
#endif
// This struct could be holding old trace data so init to zero
StackTraceData *data = &stackTrace[stackSize];
memset(data, 0, sizeof(StackTraceData));
// Set function info
data->fileName = fileName;
data->functionName = functionName;
data->tryDepth = errorTryDepth();
StackTraceData *data = &stackTrace[stackSize];
*data = (StackTraceData)
{
.fileName = fileName,
.functionName = functionName,
.tryDepth = errorTryDepth(),
};
// Set param pointer
if (stackSize == 0)

View File

@ -53,13 +53,16 @@ bufNew(size_t size)
{
// Create object
this = memNew(sizeof(Buffer));
this->memContext = MEM_CONTEXT_NEW();
this->size = size;
this->used = 0;
*this = (Buffer)
{
.memContext = MEM_CONTEXT_NEW(),
.size = size,
};
// Allocate buffer
if (size > 0)
this->buffer = memNewRaw(this->size);
this->buffer = memNew(this->size);
}
MEM_CONTEXT_NEW_END();
@ -291,7 +294,7 @@ bufResize(Buffer *this, size_t size)
if (this->buffer == NULL)
this->buffer = memNew(size);
else
this->buffer = memGrowRaw(this->buffer, size);
this->buffer = memResize(this->buffer, size);
}
MEM_CONTEXT_END();

View File

@ -53,11 +53,13 @@ kvNew(void)
{
// Allocate state and set context
this = memNew(sizeof(KeyValue));
this->memContext = MEM_CONTEXT_NEW();
// Initialize list
this->list = lstNew(sizeof(KeyValuePair));
this->keyList = varLstNew();
*this = (KeyValue)
{
.memContext = MEM_CONTEXT_NEW(),
.list = lstNew(sizeof(KeyValuePair)),
.keyList = varLstNew(),
};
}
MEM_CONTEXT_NEW_END();

View File

@ -56,10 +56,14 @@ lstNewParam(size_t itemSize, ListParam param)
{
// Create object
this = memNew(sizeof(List));
this->memContext = MEM_CONTEXT_NEW();
this->itemSize = itemSize;
this->sortOrder = param.sortOrder;
this->comparator = param.comparator;
*this = (List)
{
.memContext = MEM_CONTEXT_NEW(),
.itemSize = itemSize,
.sortOrder = param.sortOrder,
.comparator = param.comparator,
};
}
MEM_CONTEXT_NEW_END();
@ -292,13 +296,13 @@ lstInsert(List *this, unsigned int listIdx, const void *item)
if (this->listSizeMax == 0)
{
this->listSizeMax = LIST_INITIAL_SIZE;
this->list = memNewRaw(this->listSizeMax * this->itemSize);
this->list = memNew(this->listSizeMax * this->itemSize);
}
// Else the list needs to be extended
else
{
this->listSizeMax *= 2;
this->list = memGrowRaw(this->list, this->listSizeMax * this->itemSize);
this->list = memResize(this->list, this->listSizeMax * this->itemSize);
}
}
MEM_CONTEXT_END();

View File

@ -39,8 +39,12 @@ mcvNew(void)
MEM_CONTEXT_NEW_BEGIN("MostCommonValue")
{
this = memNew(sizeof(MostCommonValue));
this->memContext = MEM_CONTEXT_NEW();
this->list = lstNew(sizeof(MostCommonValueEntry));
*this = (MostCommonValue)
{
.memContext = MEM_CONTEXT_NEW(),
.list = lstNew(sizeof(MostCommonValueEntry)),
};
}
MEM_CONTEXT_NEW_END();

View File

@ -77,11 +77,15 @@ strNew(const char *string)
// Create object
String *this = memNew(sizeof(String));
this->memContext = memContextCurrent();
this->size = (unsigned int)stringSize;
*this = (String)
{
.memContext = memContextCurrent(),
.size = (unsigned int)stringSize,
};
// Allocate and assign string
this->buffer = memNewRaw(this->size + 1);
this->buffer = memNew(this->size + 1);
strcpy(this->buffer, string);
FUNCTION_TEST_RETURN(this);
@ -107,11 +111,15 @@ strNewBuf(const Buffer *buffer)
// Create object
String *this = memNew(sizeof(String));
this->memContext = memContextCurrent();
this->size = (unsigned int)bufUsed(buffer);
*this = (String)
{
.memContext = memContextCurrent(),
.size = (unsigned int)bufUsed(buffer),
};
// Allocate and assign string
this->buffer = memNewRaw(this->size + 1);
this->buffer = memNew(this->size + 1);
memcpy(this->buffer, (char *)bufPtr(buffer), this->size);
this->buffer[this->size] = 0;
@ -132,7 +140,11 @@ strNewFmt(const char *format, ...)
// Create object
String *this = memNew(sizeof(String));
this->memContext = memContextCurrent();
*this = (String)
{
.memContext = memContextCurrent(),
};
// Determine how long the allocated string needs to be
va_list argumentList;
@ -145,7 +157,7 @@ strNewFmt(const char *format, ...)
// Allocate and assign string
this->size = (unsigned int)formatSize;
this->buffer = memNewRaw(this->size + 1);
this->buffer = memNew(this->size + 1);
va_start(argumentList, format);
vsnprintf(this->buffer, this->size + 1, format, argumentList);
va_end(argumentList);
@ -173,11 +185,15 @@ strNewN(const char *string, size_t size)
// Create object
String *this = memNew(sizeof(String));
this->memContext = memContextCurrent();
this->size = (unsigned int)size;
*this = (String)
{
.memContext = memContextCurrent(),
.size = (unsigned int)size,
};
// Allocate and assign string
this->buffer = memNewRaw(this->size + 1);
this->buffer = memNew(this->size + 1);
strncpy(this->buffer, string, this->size);
this->buffer[this->size] = 0;
@ -263,7 +279,7 @@ strResize(String *this, size_t requested)
MEM_CONTEXT_BEGIN(this->memContext)
{
this->buffer = memGrowRaw(this->buffer, this->size + this->extra + 1);
this->buffer = memResize(this->buffer, this->size + this->extra + 1);
}
MEM_CONTEXT_END();
}
@ -854,7 +870,7 @@ strTrim(String *this)
MEM_CONTEXT_BEGIN(this->memContext)
{
// Resize the buffer
this->buffer = memGrowRaw(this->buffer, this->size + 1);
this->buffer = memResize(this->buffer, this->size + 1);
}
MEM_CONTEXT_END();
}
@ -912,7 +928,7 @@ strTrunc(String *this, int idx)
MEM_CONTEXT_BEGIN(this->memContext)
{
// Resize the buffer
this->buffer = memGrowRaw(this->buffer, this->size + 1);
this->buffer = memResize(this->buffer, this->size + 1);
}
MEM_CONTEXT_END();
}

View File

@ -156,9 +156,13 @@ varDup(const Variant *this)
case varTypeKeyValue:
{
VariantKeyValue *keyValue = memNew(sizeof(VariantKeyValue));
keyValue->memContext = memContextCurrent();
keyValue->type = varTypeKeyValue;
keyValue->data = kvDup(varKv(this));
*keyValue = (VariantKeyValue)
{
.memContext = memContextCurrent(),
.type = varTypeKeyValue,
.data = kvDup(varKv(this)),
};
result = (Variant *)keyValue;
break;
@ -295,9 +299,13 @@ varNewBool(bool data)
// Allocate memory for the variant and set the type and data
VariantBool *this = memNew(sizeof(VariantBool));
this->memContext = memContextCurrent();
this->type = varTypeBool;
this->data = data;
*this = (VariantBool)
{
.memContext = memContextCurrent(),
.type = varTypeBool,
.data = data,
};
FUNCTION_TEST_RETURN((Variant *)this);
}
@ -400,9 +408,13 @@ varNewDbl(double data)
// Allocate memory for the variant and set the type and data
VariantDouble *this = memNew(sizeof(VariantDouble));
this->memContext = memContextCurrent();
this->type = varTypeDouble;
this->data = data;
*this = (VariantDouble)
{
.memContext = memContextCurrent(),
.type = varTypeDouble,
.data = data,
};
FUNCTION_TEST_RETURN((Variant *)this);
}
@ -500,9 +512,13 @@ varNewInt(int data)
// Allocate memory for the variant and set the type and data
VariantInt *this = memNew(sizeof(VariantInt));
this->memContext = memContextCurrent();
this->type = varTypeInt;
this->data = data;
*this = (VariantInt)
{
.memContext = memContextCurrent(),
.type = varTypeInt,
.data = data,
};
FUNCTION_TEST_RETURN((Variant *)this);
}
@ -618,9 +634,13 @@ varNewInt64(int64_t data)
// Allocate memory for the variant and set the type and data
VariantInt64 *this = memNew(sizeof(VariantInt64));
this->memContext = memContextCurrent();
this->type = varTypeInt64;
this->data = data;
*this = (VariantInt64)
{
.memContext = memContextCurrent(),
.type = varTypeInt64,
.data = data,
};
FUNCTION_TEST_RETURN((Variant *)this);
}
@ -724,9 +744,13 @@ varNewUInt(unsigned int data)
// Allocate memory for the variant and set the type and data
VariantUInt *this = memNew(sizeof(VariantUInt));
this->memContext = memContextCurrent();
this->type = varTypeUInt;
this->data = data;
*this = (VariantUInt)
{
.memContext = memContextCurrent(),
.type = varTypeUInt,
.data = data,
};
FUNCTION_TEST_RETURN((Variant *)this);
}
@ -851,9 +875,13 @@ varNewUInt64(uint64_t data)
// Allocate memory for the variant and set the type and data
VariantUInt64 *this = memNew(sizeof(VariantUInt64));
this->memContext = memContextCurrent();
this->type = varTypeUInt64;
this->data = data;
*this = (VariantUInt64)
{
.memContext = memContextCurrent(),
.type = varTypeUInt64,
.data = data,
};
FUNCTION_TEST_RETURN((Variant *)this);
}
@ -969,8 +997,12 @@ varNewKv(KeyValue *data)
// Allocate memory for the variant and set the type and data
VariantKeyValue *this = memNew(sizeof(VariantKeyValue));
this->memContext = memContextCurrent();
this->type = varTypeKeyValue;
*this = (VariantKeyValue)
{
.memContext = memContextCurrent(),
.type = varTypeKeyValue,
};
if (data != NULL)
this->data = kvMove(data, memContextCurrent());
@ -1011,9 +1043,13 @@ varNewStr(const String *data)
// Allocate memory for the variant and set the type and data
VariantString *this = memNew(sizeof(VariantString));
this->memContext = memContextCurrent();
this->type = varTypeString;
this->data = strDup(data);
*this = (VariantString)
{
.memContext = memContextCurrent(),
.type = varTypeString,
.data = strDup(data),
};
FUNCTION_TEST_RETURN((Variant *)this);
}
@ -1144,8 +1180,12 @@ varNewVarLst(const VariantList *data)
// Allocate memory for the variant and set the type and data
VariantVariantList *this = memNew(sizeof(VariantVariantList));
this->memContext = memContextCurrent();
this->type = varTypeVariantList;
*this = (VariantVariantList)
{
.memContext = memContextCurrent(),
.type = varTypeVariantList,
};
if (data != NULL)
this->data = varLstDup(data);

View File

@ -148,7 +148,11 @@ xmlNodeNew(xmlNodePtr node)
ASSERT(node != NULL);
XmlNode *this = memNew(sizeof(XmlNode));
this->node = node;
*this = (XmlNode)
{
.node = node,
};
FUNCTION_TEST_RETURN(this);
}
@ -409,9 +413,12 @@ xmlDocumentNew(const String *rootName)
MEM_CONTEXT_NEW_BEGIN("XmlDocument")
{
this = memNew(sizeof(XmlDocument));
this->memContext = MEM_CONTEXT_NEW();
this->xml = xmlNewDoc(BAD_CAST "1.0");
*this = (XmlDocument)
{
.memContext = MEM_CONTEXT_NEW(),
.xml = xmlNewDoc(BAD_CAST "1.0"),
};
// Set callback to ensure xml document is freed
memContextCallbackSet(this->memContext, xmlDocumentFreeResource, this);
@ -446,7 +453,11 @@ xmlDocumentNewC(const unsigned char *buffer, size_t bufferSize)
MEM_CONTEXT_NEW_BEGIN("XmlDocument")
{
this = memNew(sizeof(XmlDocument));
this->memContext = MEM_CONTEXT_NEW();
*this = (XmlDocument)
{
.memContext = MEM_CONTEXT_NEW(),
};
if ((this->xml = xmlReadMemory((const char *)buffer, (int)bufferSize, "noname.xml", NULL, 0)) == NULL)
THROW_FMT(FormatError, "invalid xml");

View File

@ -42,10 +42,12 @@ waitNew(TimeMSec waitTime)
{
// Create object
this = memNew(sizeof(Wait));
this->memContext = MEM_CONTEXT_NEW();
// Store time
this->waitTime = waitTime;
*this = (Wait)
{
.memContext = MEM_CONTEXT_NEW(),
.waitTime = waitTime,
};
// Calculate first sleep time -- start with 1/10th of a second for anything >= 1 second
if (this->waitTime >= MSEC_PER_SEC)

View File

@ -81,48 +81,32 @@ Include the automatically generated configuration data
#include "config/config.auto.c"
/***********************************************************************************************************************************
Store the config memory context
Static data for the currently loaded configuration
***********************************************************************************************************************************/
static MemContext *configMemContext = NULL;
/***********************************************************************************************************************************
Store the current command
This is generally set by the command parser but can also be set by during execute to change commands, i.e. backup -> expire.
***********************************************************************************************************************************/
static ConfigCommand command = cfgCmdNone;
static ConfigCommandRole commandRole = cfgCmdRoleDefault;
/***********************************************************************************************************************************
Store the location of the executable
***********************************************************************************************************************************/
static String *exe = NULL;
/***********************************************************************************************************************************
Was help requested for the command?
***********************************************************************************************************************************/
static bool help = false;
/***********************************************************************************************************************************
Store the list of parameters passed to the command
***********************************************************************************************************************************/
static StringList *paramList = NULL;
/***********************************************************************************************************************************
Map options names and indexes to option definitions.
***********************************************************************************************************************************/
typedef struct ConfigOptionValue
static struct ConfigStatic
{
bool valid:1;
bool negate:1;
bool reset:1;
unsigned int source:2;
MemContext *memContext; // Mem context for config data (child of top context)
Variant *value;
Variant *defaultValue;
} ConfigOptionValue;
// Generally set by the command parser but can also be set by during execute to change commands, i.e. backup -> expire
ConfigCommand command; // Current command
ConfigCommandRole commandRole; // Current command role
static ConfigOptionValue configOptionValue[CFG_OPTION_TOTAL];
String *exe; // Location of the executable
bool help; // Was help requested for the command?
StringList *paramList; // Parameters passed to the command (if any)
// Map options names and indexes to option definitions
struct
{
bool valid:1; // Is option valid for current command?
bool negate:1; // Is the option negated?
bool reset:1; // Is the option reset?
unsigned int source:2; // Where the option came from, i.e. ConfigSource enum
Variant *value; // Value
Variant *defaultValue; // Default value
} option[CFG_OPTION_TOTAL];
} configStatic;
/***********************************************************************************************************************************
Initialize or reinitialize the configuration data
@ -132,27 +116,19 @@ cfgInit(void)
{
FUNCTION_TEST_VOID();
// Reset configuration
command = cfgCmdNone;
commandRole = cfgCmdRoleDefault;
exe = NULL;
help = false;
paramList = NULL;
memset(&configOptionValue, 0, sizeof(configOptionValue));
// Free the old context
if (configMemContext != NULL)
{
memContextFree(configMemContext);
configMemContext = NULL;
}
if (configStatic.memContext != NULL)
memContextFree(configStatic.memContext);
// Initialize config data
configStatic = (struct ConfigStatic){.command = cfgCmdNone};
// Allocate configuration context as a child of the top context
MEM_CONTEXT_BEGIN(memContextTop())
{
MEM_CONTEXT_NEW_BEGIN("configuration")
{
configMemContext = MEM_CONTEXT_NEW();
configStatic.memContext = MEM_CONTEXT_NEW();
}
MEM_CONTEXT_NEW_END();
}
@ -168,14 +144,14 @@ ConfigCommand
cfgCommand(void)
{
FUNCTION_TEST_VOID();
FUNCTION_TEST_RETURN(command);
FUNCTION_TEST_RETURN(configStatic.command);
}
ConfigCommandRole
cfgCommandRole(void)
{
FUNCTION_TEST_VOID();
FUNCTION_TEST_RETURN(commandRole);
FUNCTION_TEST_RETURN(configStatic.commandRole);
}
void
@ -188,8 +164,8 @@ cfgCommandSet(ConfigCommand commandId, ConfigCommandRole commandRoleId)
ASSERT(commandId <= cfgCmdNone);
command = commandId;
commandRole = commandRoleId;
configStatic.command = commandId;
configStatic.commandRole = commandRoleId;
FUNCTION_TEST_RETURN_VOID();
}
@ -201,17 +177,17 @@ bool
cfgCommandHelp(void)
{
FUNCTION_TEST_VOID();
FUNCTION_TEST_RETURN(help);
FUNCTION_TEST_RETURN(configStatic.help);
}
void
cfgCommandHelpSet(bool helpParam)
cfgCommandHelpSet(bool help)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(BOOL, helpParam);
FUNCTION_TEST_PARAM(BOOL, help);
FUNCTION_TEST_END();
help = helpParam;
configStatic.help = help;
FUNCTION_TEST_RETURN_VOID();
}
@ -305,16 +281,16 @@ cfgCommandParam(void)
{
FUNCTION_TEST_VOID();
if (paramList == NULL)
if (configStatic.paramList == NULL)
{
MEM_CONTEXT_BEGIN(configMemContext)
MEM_CONTEXT_BEGIN(configStatic.memContext)
{
paramList = strLstNew();
configStatic.paramList = strLstNew();
}
MEM_CONTEXT_END();
}
FUNCTION_TEST_RETURN(paramList);
FUNCTION_TEST_RETURN(configStatic.paramList);
}
void
@ -326,9 +302,9 @@ cfgCommandParamSet(const StringList *param)
ASSERT(param != NULL);
MEM_CONTEXT_BEGIN(configMemContext)
MEM_CONTEXT_BEGIN(configStatic.memContext)
{
paramList = strLstDup(param);
configStatic.paramList = strLstDup(param);
}
MEM_CONTEXT_END();
@ -402,21 +378,21 @@ const String *
cfgExe(void)
{
FUNCTION_TEST_VOID();
FUNCTION_TEST_RETURN(exe);
FUNCTION_TEST_RETURN(configStatic.exe);
}
void
cfgExeSet(const String *exeParam)
cfgExeSet(const String *exe)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(STRING, exeParam);
FUNCTION_TEST_PARAM(STRING, exe);
FUNCTION_TEST_END();
ASSERT(exeParam != NULL);
ASSERT(exe != NULL);
MEM_CONTEXT_BEGIN(configMemContext)
MEM_CONTEXT_BEGIN(configStatic.memContext)
{
exe = strDup(exeParam);
configStatic.exe = strDup(exe);
}
MEM_CONTEXT_END();
@ -446,7 +422,7 @@ cfgLockRequired(void)
{
FUNCTION_TEST_VOID();
ASSERT(command != cfgCmdNone);
ASSERT(configStatic.command != cfgCmdNone);
// Local roles never take a lock and the remote role has special logic for locking
FUNCTION_TEST_RETURN(
@ -475,7 +451,7 @@ cfgLockType(void)
{
FUNCTION_TEST_VOID();
ASSERT(command != cfgCmdNone);
ASSERT(configStatic.command != cfgCmdNone);
FUNCTION_TEST_RETURN((LockType)configCommandData[cfgCommand()].lockType);
}
@ -488,7 +464,7 @@ cfgLogFile(void)
{
FUNCTION_TEST_VOID();
ASSERT(command != cfgCmdNone);
ASSERT(configStatic.command != cfgCmdNone);
FUNCTION_TEST_RETURN(
// If the command always logs to a file
@ -507,7 +483,7 @@ cfgLogLevelDefault(void)
{
FUNCTION_TEST_VOID();
ASSERT(command != cfgCmdNone);
ASSERT(configStatic.command != cfgCmdNone);
FUNCTION_TEST_RETURN((LogLevel)configCommandData[cfgCommand()].logLevelDefault);
}
@ -520,7 +496,7 @@ cfgParameterAllowed(void)
{
FUNCTION_TEST_VOID();
ASSERT(command != cfgCmdNone);
ASSERT(configStatic.command != cfgCmdNone);
FUNCTION_TEST_RETURN(configCommandData[cfgCommand()].parameterAllowed);
}
@ -600,21 +576,21 @@ cfgOptionDefault(ConfigOption optionId)
ASSERT(optionId < CFG_OPTION_TOTAL);
if (configOptionValue[optionId].defaultValue == NULL)
if (configStatic.option[optionId].defaultValue == NULL)
{
ConfigDefineOption optionDefId = cfgOptionDefIdFromId(optionId);
if (cfgDefOptionDefault(cfgCommandDefIdFromId(cfgCommand()), optionDefId) != NULL)
{
MEM_CONTEXT_BEGIN(configMemContext)
MEM_CONTEXT_BEGIN(configStatic.memContext)
{
configOptionValue[optionId].defaultValue = cfgOptionDefaultValue(optionDefId);
configStatic.option[optionId].defaultValue = cfgOptionDefaultValue(optionDefId);
}
MEM_CONTEXT_END();
}
}
FUNCTION_TEST_RETURN(configOptionValue[optionId].defaultValue);
FUNCTION_TEST_RETURN(configStatic.option[optionId].defaultValue);
}
void
@ -627,19 +603,19 @@ cfgOptionDefaultSet(ConfigOption optionId, const Variant *defaultValue)
ASSERT(optionId < CFG_OPTION_TOTAL);
MEM_CONTEXT_BEGIN(configMemContext)
MEM_CONTEXT_BEGIN(configStatic.memContext)
{
if (configOptionValue[optionId].defaultValue != NULL)
varFree(configOptionValue[optionId].defaultValue);
if (configStatic.option[optionId].defaultValue != NULL)
varFree(configStatic.option[optionId].defaultValue);
configOptionValue[optionId].defaultValue = varDup(defaultValue);
configStatic.option[optionId].defaultValue = varDup(defaultValue);
if (configOptionValue[optionId].source == cfgSourceDefault)
if (configStatic.option[optionId].source == cfgSourceDefault)
{
if (configOptionValue[optionId].value != NULL)
varFree(configOptionValue[optionId].value);
if (configStatic.option[optionId].value != NULL)
varFree(configStatic.option[optionId].value);
configOptionValue[optionId].value = varDup(defaultValue);
configStatic.option[optionId].value = varDup(defaultValue);
}
}
MEM_CONTEXT_END();
@ -831,7 +807,7 @@ cfgOptionNegate(ConfigOption optionId)
ASSERT(optionId < CFG_OPTION_TOTAL);
FUNCTION_TEST_RETURN(configOptionValue[optionId].negate);
FUNCTION_TEST_RETURN(configStatic.option[optionId].negate);
}
void
@ -844,7 +820,7 @@ cfgOptionNegateSet(ConfigOption optionId, bool negate)
ASSERT(optionId < CFG_OPTION_TOTAL);
configOptionValue[optionId].negate = negate;
configStatic.option[optionId].negate = negate;
FUNCTION_TEST_RETURN_VOID();
}
@ -861,7 +837,7 @@ cfgOptionReset(ConfigOption optionId)
ASSERT(optionId < CFG_OPTION_TOTAL);
FUNCTION_TEST_RETURN(configOptionValue[optionId].reset);
FUNCTION_TEST_RETURN(configStatic.option[optionId].reset);
}
void
@ -874,7 +850,7 @@ cfgOptionResetSet(ConfigOption optionId, bool reset)
ASSERT(optionId < CFG_OPTION_TOTAL);
configOptionValue[optionId].reset = reset;
configStatic.option[optionId].reset = reset;
FUNCTION_TEST_RETURN_VOID();
}
@ -891,7 +867,7 @@ cfgOption(ConfigOption optionId)
ASSERT(optionId < CFG_OPTION_TOTAL);
FUNCTION_TEST_RETURN(configOptionValue[optionId].value);
FUNCTION_TEST_RETURN(configStatic.option[optionId].value);
}
bool
@ -902,9 +878,9 @@ cfgOptionBool(ConfigOption optionId)
FUNCTION_LOG_END();
ASSERT(optionId < CFG_OPTION_TOTAL);
ASSERT(varType(configOptionValue[optionId].value) == varTypeBool);
ASSERT(varType(configStatic.option[optionId].value) == varTypeBool);
FUNCTION_LOG_RETURN(BOOL, varBool(configOptionValue[optionId].value));
FUNCTION_LOG_RETURN(BOOL, varBool(configStatic.option[optionId].value));
}
double
@ -915,9 +891,9 @@ cfgOptionDbl(ConfigOption optionId)
FUNCTION_LOG_END();
ASSERT(optionId < CFG_OPTION_TOTAL);
ASSERT(varType(configOptionValue[optionId].value) == varTypeDouble);
ASSERT(varType(configStatic.option[optionId].value) == varTypeDouble);
FUNCTION_LOG_RETURN(DOUBLE, varDbl(configOptionValue[optionId].value));
FUNCTION_LOG_RETURN(DOUBLE, varDbl(configStatic.option[optionId].value));
}
int
@ -928,9 +904,9 @@ cfgOptionInt(ConfigOption optionId)
FUNCTION_LOG_END();
ASSERT(optionId < CFG_OPTION_TOTAL);
ASSERT(varType(configOptionValue[optionId].value) == varTypeInt64);
ASSERT(varType(configStatic.option[optionId].value) == varTypeInt64);
FUNCTION_LOG_RETURN(INT, varIntForce(configOptionValue[optionId].value));
FUNCTION_LOG_RETURN(INT, varIntForce(configStatic.option[optionId].value));
}
int64_t
@ -941,9 +917,9 @@ cfgOptionInt64(ConfigOption optionId)
FUNCTION_LOG_END();
ASSERT(optionId < CFG_OPTION_TOTAL);
ASSERT(varType(configOptionValue[optionId].value) == varTypeInt64);
ASSERT(varType(configStatic.option[optionId].value) == varTypeInt64);
FUNCTION_LOG_RETURN(INT64, varInt64(configOptionValue[optionId].value));
FUNCTION_LOG_RETURN(INT64, varInt64(configStatic.option[optionId].value));
}
unsigned int
@ -954,9 +930,9 @@ cfgOptionUInt(ConfigOption optionId)
FUNCTION_LOG_END();
ASSERT(optionId < CFG_OPTION_TOTAL);
ASSERT(varType(configOptionValue[optionId].value) == varTypeInt64);
ASSERT(varType(configStatic.option[optionId].value) == varTypeInt64);
FUNCTION_LOG_RETURN(UINT, varUIntForce(configOptionValue[optionId].value));
FUNCTION_LOG_RETURN(UINT, varUIntForce(configStatic.option[optionId].value));
}
uint64_t
@ -967,9 +943,9 @@ cfgOptionUInt64(ConfigOption optionId)
FUNCTION_LOG_END();
ASSERT(optionId < CFG_OPTION_TOTAL);
ASSERT(varType(configOptionValue[optionId].value) == varTypeInt64);
ASSERT(varType(configStatic.option[optionId].value) == varTypeInt64);
FUNCTION_LOG_RETURN(UINT64, varUInt64Force(configOptionValue[optionId].value));
FUNCTION_LOG_RETURN(UINT64, varUInt64Force(configStatic.option[optionId].value));
}
const KeyValue *
@ -980,9 +956,9 @@ cfgOptionKv(ConfigOption optionId)
FUNCTION_LOG_END();
ASSERT(optionId < CFG_OPTION_TOTAL);
ASSERT(varType(configOptionValue[optionId].value) == varTypeKeyValue);
ASSERT(varType(configStatic.option[optionId].value) == varTypeKeyValue);
FUNCTION_LOG_RETURN(KEY_VALUE, varKv(configOptionValue[optionId].value));
FUNCTION_LOG_RETURN(KEY_VALUE, varKv(configStatic.option[optionId].value));
}
const VariantList *
@ -993,18 +969,18 @@ cfgOptionLst(ConfigOption optionId)
FUNCTION_LOG_END();
ASSERT(optionId < CFG_OPTION_TOTAL);
ASSERT(configOptionValue[optionId].value == NULL || varType(configOptionValue[optionId].value) == varTypeVariantList);
ASSERT(configStatic.option[optionId].value == NULL || varType(configStatic.option[optionId].value) == varTypeVariantList);
if (configOptionValue[optionId].value == NULL)
if (configStatic.option[optionId].value == NULL)
{
MEM_CONTEXT_BEGIN(configMemContext)
MEM_CONTEXT_BEGIN(configStatic.memContext)
{
configOptionValue[optionId].value = varNewVarLst(varLstNew());
configStatic.option[optionId].value = varNewVarLst(varLstNew());
}
MEM_CONTEXT_END();
}
FUNCTION_LOG_RETURN(VARIANT_LIST, varVarLst(configOptionValue[optionId].value));
FUNCTION_LOG_RETURN(VARIANT_LIST, varVarLst(configStatic.option[optionId].value));
}
const String *
@ -1015,12 +991,12 @@ cfgOptionStr(ConfigOption optionId)
FUNCTION_LOG_END();
ASSERT(optionId < CFG_OPTION_TOTAL);
ASSERT(configOptionValue[optionId].value == NULL || varType(configOptionValue[optionId].value) == varTypeString);
ASSERT(configStatic.option[optionId].value == NULL || varType(configStatic.option[optionId].value) == varTypeString);
const String *result = NULL;
if (configOptionValue[optionId].value != NULL)
result = varStr(configOptionValue[optionId].value);
if (configStatic.option[optionId].value != NULL)
result = varStr(configStatic.option[optionId].value);
FUNCTION_LOG_RETURN_CONST(STRING, result);
}
@ -1036,13 +1012,13 @@ cfgOptionSet(ConfigOption optionId, ConfigSource source, const Variant *value)
ASSERT(optionId < CFG_OPTION_TOTAL);
MEM_CONTEXT_BEGIN(configMemContext)
MEM_CONTEXT_BEGIN(configStatic.memContext)
{
// Set the source
configOptionValue[optionId].source = source;
configStatic.option[optionId].source = source;
// Store old value
Variant *valueOld = configOptionValue[optionId].value;
Variant *valueOld = configStatic.option[optionId].value;
// Only set value if it is not null
if (value != NULL)
@ -1052,9 +1028,9 @@ cfgOptionSet(ConfigOption optionId, ConfigSource source, const Variant *value)
case cfgDefOptTypeBoolean:
{
if (varType(value) == varTypeBool)
configOptionValue[optionId].value = varDup(value);
configStatic.option[optionId].value = varDup(value);
else
configOptionValue[optionId].value = varNewBool(varBoolForce(value));
configStatic.option[optionId].value = varNewBool(varBoolForce(value));
break;
}
@ -1062,9 +1038,9 @@ cfgOptionSet(ConfigOption optionId, ConfigSource source, const Variant *value)
case cfgDefOptTypeFloat:
{
if (varType(value) == varTypeDouble)
configOptionValue[optionId].value = varDup(value);
configStatic.option[optionId].value = varDup(value);
else
configOptionValue[optionId].value = varNewDbl(varDblForce(value));
configStatic.option[optionId].value = varNewDbl(varDblForce(value));
break;
}
@ -1073,9 +1049,9 @@ cfgOptionSet(ConfigOption optionId, ConfigSource source, const Variant *value)
case cfgDefOptTypeSize:
{
if (varType(value) == varTypeInt64)
configOptionValue[optionId].value = varDup(value);
configStatic.option[optionId].value = varDup(value);
else
configOptionValue[optionId].value = varNewInt64(varInt64Force(value));
configStatic.option[optionId].value = varNewInt64(varInt64Force(value));
break;
}
@ -1083,7 +1059,7 @@ cfgOptionSet(ConfigOption optionId, ConfigSource source, const Variant *value)
case cfgDefOptTypeHash:
{
if (varType(value) == varTypeKeyValue)
configOptionValue[optionId].value = varDup(value);
configStatic.option[optionId].value = varDup(value);
else
THROW_FMT(AssertError, "option '%s' must be set with KeyValue variant", cfgOptionName(optionId));
@ -1093,7 +1069,7 @@ cfgOptionSet(ConfigOption optionId, ConfigSource source, const Variant *value)
case cfgDefOptTypeList:
{
if (varType(value) == varTypeVariantList)
configOptionValue[optionId].value = varDup(value);
configStatic.option[optionId].value = varDup(value);
else
THROW_FMT(AssertError, "option '%s' must be set with VariantList variant", cfgOptionName(optionId));
@ -1104,7 +1080,7 @@ cfgOptionSet(ConfigOption optionId, ConfigSource source, const Variant *value)
case cfgDefOptTypeString:
{
if (varType(value) == varTypeString)
configOptionValue[optionId].value = varDup(value);
configStatic.option[optionId].value = varDup(value);
else
THROW_FMT(AssertError, "option '%s' must be set with String variant", cfgOptionName(optionId));
@ -1113,7 +1089,7 @@ cfgOptionSet(ConfigOption optionId, ConfigSource source, const Variant *value)
}
}
else
configOptionValue[optionId].value = NULL;
configStatic.option[optionId].value = NULL;
// Free old value
if (valueOld != NULL)
@ -1136,7 +1112,7 @@ cfgOptionSource(ConfigOption optionId)
ASSERT(optionId < CFG_OPTION_TOTAL);
FUNCTION_TEST_RETURN(configOptionValue[optionId].source);
FUNCTION_TEST_RETURN(configStatic.option[optionId].source);
}
/***********************************************************************************************************************************
@ -1151,7 +1127,7 @@ cfgOptionTest(ConfigOption optionId)
ASSERT(optionId < CFG_OPTION_TOTAL);
FUNCTION_TEST_RETURN(cfgOptionValid(optionId) && configOptionValue[optionId].value != NULL);
FUNCTION_TEST_RETURN(cfgOptionValid(optionId) && configStatic.option[optionId].value != NULL);
}
/***********************************************************************************************************************************
@ -1166,7 +1142,7 @@ cfgOptionValid(ConfigOption optionId)
ASSERT(optionId < CFG_OPTION_TOTAL);
FUNCTION_TEST_RETURN(configOptionValue[optionId].valid);
FUNCTION_TEST_RETURN(configStatic.option[optionId].valid);
}
void
@ -1179,7 +1155,7 @@ cfgOptionValidSet(ConfigOption optionId, bool valid)
ASSERT(optionId < CFG_OPTION_TOTAL);
configOptionValue[optionId].valid = valid;
configStatic.option[optionId].valid = valid;
FUNCTION_TEST_RETURN_VOID();
}

View File

@ -23,7 +23,7 @@ what it is supposed to do.
typedef enum
{
// Called directly by the user. This is the main part of the command that may or may not spawn other command roles.
cfgCmdRoleDefault,
cfgCmdRoleDefault = 0,
// Async worker that is spawned so the main process can return a result while work continues. An async worker may spawn local
// or remote workers.
@ -124,7 +124,7 @@ void cfgInit(void);
ConfigDefineCommand cfgCommandDefIdFromId(ConfigCommand commandId);
bool cfgCommandHelp(void);
void cfgCommandHelpSet(bool helpParam);
void cfgCommandHelpSet(bool help);
// Get command id by name. If error is true then assert when the command does not exist.
ConfigCommand cfgCommandId(const char *commandName, bool error);
@ -140,7 +140,7 @@ ConfigCommandRole cfgCommandRoleEnum(const String *commandRole);
const String *cfgCommandRoleStr(ConfigCommandRole commandRole);
const String *cfgExe(void);
void cfgExeSet(const String *exeParam);
void cfgExeSet(const String *exe);
const Variant *cfgOptionDefault(ConfigOption optionId);
void cfgOptionDefaultSet(ConfigOption optionId, const Variant *defaultValue);

View File

@ -445,8 +445,7 @@ configParse(unsigned int argListSize, const char *argList[], bool resetLogLevel)
opterr = false;
// List of parsed options
ParseOption parseOptionList[CFG_OPTION_TOTAL];
memset(&parseOptionList, 0, sizeof(parseOptionList));
ParseOption parseOptionList[CFG_OPTION_TOTAL] = {{.found = false}};
// Only the first non-option parameter should be treated as a command so track if the command has been set
bool commandSet = false;

View File

@ -72,11 +72,14 @@ dbNew(PgClient *client, ProtocolClient *remoteClient, const String *applicationN
MEM_CONTEXT_NEW_BEGIN("Db")
{
this = memNew(sizeof(Db));
this->memContext = memContextCurrent();
this->client = pgClientMove(client, this->memContext);
this->remoteClient = remoteClient;
this->applicationName = strDup(applicationName);
*this = (Db)
{
.memContext = memContextCurrent(),
.client = pgClientMove(client, memContextCurrent()),
.remoteClient = remoteClient,
.applicationName = strDup(applicationName),
};
}
MEM_CONTEXT_NEW_END();

View File

@ -118,7 +118,11 @@ infoNewInternal(void)
FUNCTION_TEST_VOID();
Info *this = memNew(sizeof(Info));
this->memContext = memContextCurrent();
*this = (Info)
{
.memContext = memContextCurrent(),
};
FUNCTION_TEST_RETURN(this);
}

View File

@ -46,7 +46,11 @@ infoArchiveNewInternal(void)
FUNCTION_TEST_VOID();
InfoArchive *this = memNew(sizeof(InfoArchive));
this->memContext = memContextCurrent();
*this = (InfoArchive)
{
.memContext = memContextCurrent(),
};
FUNCTION_TEST_RETURN(this);
}

View File

@ -75,8 +75,12 @@ infoBackupNewInternal(void)
FUNCTION_TEST_VOID();
InfoBackup *this = memNew(sizeof(InfoBackup));
this->memContext = memContextCurrent();
this->backup = lstNewP(sizeof(InfoBackupData), .comparator = lstComparatorStr);
*this = (InfoBackup)
{
.memContext = memContextCurrent(),
.backup = lstNewP(sizeof(InfoBackupData), .comparator = lstComparatorStr),
};
FUNCTION_TEST_RETURN(this);
}

View File

@ -59,9 +59,13 @@ infoPgNewInternal(InfoPgType type)
FUNCTION_TEST_END();
InfoPg *this = memNew(sizeof(InfoPg));
this->memContext = memContextCurrent();
this->type = type;
this->history = lstNew(sizeof(InfoPgData));
*this = (InfoPg)
{
.memContext = memContextCurrent(),
.type = type,
.history = lstNew(sizeof(InfoPgData)),
};
FUNCTION_TEST_RETURN(this);
}

View File

@ -370,7 +370,7 @@ manifestNewInternal(void)
{
FUNCTION_TEST_VOID();
Manifest *this = memNewRaw(sizeof(Manifest));
Manifest *this = memNew(sizeof(Manifest));
*this = (Manifest)
{

View File

@ -62,13 +62,16 @@ pgClientNew(const String *host, const unsigned int port, const String *database,
MEM_CONTEXT_NEW_BEGIN("PgClient")
{
this = memNew(sizeof(PgClient));
this->memContext = memContextCurrent();
this->host = strDup(host);
this->port = port;
this->database = strDup(database);
this->user = strDup(user);
this->queryTimeout = queryTimeout;
*this = (PgClient)
{
.memContext = MEM_CONTEXT_NEW(),
.host = strDup(host),
.port = port,
.database = strDup(database),
.user = strDup(user),
.queryTimeout = queryTimeout,
};
}
MEM_CONTEXT_NEW_END();

View File

@ -124,12 +124,15 @@ Create a pg_control file for testing
{ \
ASSERT(buffer != NULL); \
\
((ControlFileData *)buffer)->system_identifier = pgControl.systemId; \
((ControlFileData *)buffer)->pg_control_version = PG_CONTROL_VERSION; \
((ControlFileData *)buffer)->catalog_version_no = CATALOG_VERSION_NO; \
((ControlFileData *)buffer)->blcksz = pgControl.pageSize; \
((ControlFileData *)buffer)->xlog_seg_size = pgControl.walSegmentSize; \
((ControlFileData *)buffer)->data_checksum_version = pgControl.pageChecksum; \
*(ControlFileData *)buffer = (ControlFileData) \
{ \
.system_identifier = pgControl.systemId, \
.pg_control_version = PG_CONTROL_VERSION, \
.catalog_version_no = CATALOG_VERSION_NO, \
.blcksz = pgControl.pageSize, \
.xlog_seg_size = pgControl.walSegmentSize, \
.data_checksum_version = pgControl.pageChecksum, \
}; \
}
#elif PG_VERSION >= PG_VERSION_83
@ -141,11 +144,14 @@ Create a pg_control file for testing
ASSERT(buffer != NULL); \
ASSERT(!pgControl.pageChecksum); \
\
((ControlFileData *)buffer)->system_identifier = pgControl.systemId; \
((ControlFileData *)buffer)->pg_control_version = PG_CONTROL_VERSION; \
((ControlFileData *)buffer)->catalog_version_no = CATALOG_VERSION_NO; \
((ControlFileData *)buffer)->blcksz = pgControl.pageSize; \
((ControlFileData *)buffer)->xlog_seg_size = pgControl.walSegmentSize; \
*(ControlFileData *)buffer = (ControlFileData) \
{ \
.system_identifier = pgControl.systemId, \
.pg_control_version = PG_CONTROL_VERSION, \
.catalog_version_no = CATALOG_VERSION_NO, \
.blcksz = pgControl.pageSize, \
.xlog_seg_size = pgControl.walSegmentSize, \
}; \
}
#endif

View File

@ -80,13 +80,16 @@ protocolClientNew(const String *name, const String *service, IoRead *read, IoWri
MEM_CONTEXT_NEW_BEGIN("ProtocolClient")
{
this = memNew(sizeof(ProtocolClient));
this->memContext = memContextCurrent();
this->name = strDup(name);
this->errorPrefix = strNewFmt("raised from %s", strPtr(this->name));
this->read = read;
this->write = write;
this->keepAliveTime = timeMSec();
*this = (ProtocolClient)
{
.memContext = memContextCurrent(),
.name = strDup(name),
.errorPrefix = strNewFmt("raised from %s", strPtr(name)),
.read = read,
.write = write,
.keepAliveTime = timeMSec(),
};
// Read, parse, and check the protocol greeting
MEM_CONTEXT_TEMP_BEGIN()

View File

@ -47,9 +47,12 @@ protocolCommandNew(const String *command)
MEM_CONTEXT_NEW_BEGIN("ProtocolCommand")
{
this = memNew(sizeof(ProtocolCommand));
this->memContext = memContextCurrent();
this->command = strDup(command);
*this = (ProtocolCommand)
{
.memContext = memContextCurrent(),
.command = strDup(command),
};
}
MEM_CONTEXT_NEW_END();

View File

@ -174,8 +174,10 @@ protocolLocalGet(ProtocolStorageType protocolStorageType, unsigned int hostId, u
MEM_CONTEXT_BEGIN(protocolHelper.memContext)
{
protocolHelper.clientLocalSize = cfgOptionUInt(cfgOptProcessMax) + 1;
protocolHelper.clientLocal = (ProtocolHelperClient *)memNew(
protocolHelper.clientLocalSize * sizeof(ProtocolHelperClient));
protocolHelper.clientLocal = memNew(protocolHelper.clientLocalSize * sizeof(ProtocolHelperClient));
for (unsigned int clientIdx = 0; clientIdx < protocolHelper.clientLocalSize; clientIdx++)
protocolHelper.clientLocal[clientIdx] = (ProtocolHelperClient){.exec = NULL};
}
MEM_CONTEXT_END();
}
@ -401,8 +403,10 @@ protocolRemoteGet(ProtocolStorageType protocolStorageType, unsigned int hostId)
ASSERT(cfgDefOptionIndexTotal(cfgDefOptPgPath) >= cfgDefOptionIndexTotal(cfgDefOptRepoPath));
protocolHelper.clientRemoteSize = cfgDefOptionIndexTotal(cfgDefOptPgPath) + 1;
protocolHelper.clientRemote = (ProtocolHelperClient *)memNew(
protocolHelper.clientRemoteSize * sizeof(ProtocolHelperClient));
protocolHelper.clientRemote = memNew(protocolHelper.clientRemoteSize * sizeof(ProtocolHelperClient));
for (unsigned int clientIdx = 0; clientIdx < protocolHelper.clientRemoteSize; clientIdx++)
protocolHelper.clientRemote[clientIdx] = (ProtocolHelperClient){.exec = NULL};
}
MEM_CONTEXT_END();
}
@ -576,8 +580,7 @@ protocolFree(void)
protocolClientFree(protocolHelperClient->client);
execFree(protocolHelperClient->exec);
protocolHelperClient->client = NULL;
protocolHelperClient->exec = NULL;
*protocolHelperClient = (ProtocolHelperClient){.exec = NULL};
}
}
}

View File

@ -56,15 +56,17 @@ protocolParallelNew(TimeMSec timeout, ParallelJobCallback *callbackFunction, voi
MEM_CONTEXT_NEW_BEGIN("ProtocolParallel")
{
this = memNew(sizeof(ProtocolParallel));
this->memContext = memContextCurrent();
this->timeout = timeout;
this->callbackFunction = callbackFunction;
this->callbackData = callbackData;
this->clientList = lstNew(sizeof(ProtocolClient *));
this->jobList = lstNew(sizeof(ProtocolParallelJob *));
this->state = protocolParallelJobStatePending;
*this = (ProtocolParallel)
{
.memContext = MEM_CONTEXT_NEW(),
.timeout = timeout,
.callbackFunction = callbackFunction,
.callbackData = callbackData,
.clientList = lstNew(sizeof(ProtocolClient *)),
.jobList = lstNew(sizeof(ProtocolParallelJob *)),
.state = protocolParallelJobStatePending,
};
}
MEM_CONTEXT_NEW_END();
@ -114,7 +116,7 @@ protocolParallelProcess(ProtocolParallel *this)
{
MEM_CONTEXT_BEGIN(this->memContext)
{
this->clientJobList = (ProtocolParallelJob **)memNew(sizeof(ProtocolParallelJob *) * lstSize(this->clientList));
this->clientJobList = memNewPtrArray(lstSize(this->clientList));
}
MEM_CONTEXT_END();

View File

@ -46,11 +46,14 @@ protocolParallelJobNew(const Variant *key, ProtocolCommand *command)
MEM_CONTEXT_NEW_BEGIN("ProtocolParallelJob")
{
this = memNew(sizeof(ProtocolParallelJob));
this->memContext = memContextCurrent();
this->state = protocolParallelJobStatePending;
this->key = varDup(key);
this->command = protocolCommandMove(command, memContextCurrent());
*this = (ProtocolParallelJob)
{
.memContext = memContextCurrent(),
.state = protocolParallelJobStatePending,
.key = varDup(key),
.command = protocolCommandMove(command, memContextCurrent()),
};
}
MEM_CONTEXT_NEW_END();

View File

@ -56,13 +56,15 @@ protocolServerNew(const String *name, const String *service, IoRead *read, IoWri
MEM_CONTEXT_NEW_BEGIN("ProtocolServer")
{
this = memNew(sizeof(ProtocolServer));
this->memContext = memContextCurrent();
this->name = strDup(name);
this->read = read;
this->write = write;
this->handlerList = lstNew(sizeof(ProtocolServerProcessHandler));
*this = (ProtocolServer)
{
.memContext = memContextCurrent(),
.name = strDup(name),
.read = read,
.write = write,
.handlerList = lstNew(sizeof(ProtocolServerProcessHandler)),
};
// Send the protocol greeting
MEM_CONTEXT_TEMP_BEGIN()

View File

@ -32,7 +32,7 @@ STRING_EXTERN(STORAGE_PATH_BACKUP_STR, STORAGE_PATH
/***********************************************************************************************************************************
Local variables
***********************************************************************************************************************************/
static struct
static struct StorageHelper
{
MemContext *memContext; // Mem context for storage helper
@ -193,7 +193,7 @@ storagePgId(unsigned int hostId)
MEM_CONTEXT_BEGIN(storageHelper.memContext)
{
if (storageHelper.storagePg == NULL)
storageHelper.storagePg = memNew(sizeof(Storage *) * cfgDefOptionIndexTotal(cfgDefOptPgPath));
storageHelper.storagePg = memNewPtrArray(cfgDefOptionIndexTotal(cfgDefOptPgPath));
storageHelper.storagePg[hostId - 1] = storagePgGet(hostId, false);
}
@ -230,7 +230,7 @@ storagePgIdWrite(unsigned int hostId)
MEM_CONTEXT_BEGIN(storageHelper.memContext)
{
if (storageHelper.storagePgWrite == NULL)
storageHelper.storagePgWrite = memNew(sizeof(Storage *) * cfgDefOptionIndexTotal(cfgDefOptPgPath));
storageHelper.storagePgWrite = memNewPtrArray(cfgDefOptionIndexTotal(cfgDefOptPgPath));
storageHelper.storagePgWrite[hostId - 1] = storagePgGet(hostId, true);
}
@ -534,7 +534,7 @@ storageHelperFree(void)
if (storageHelper.memContext != NULL)
memContextFree(storageHelper.memContext);
memset(&storageHelper, 0, sizeof(storageHelper));
storageHelper = (struct StorageHelper){.memContext = NULL};
FUNCTION_TEST_RETURN_VOID();
}

View File

@ -205,9 +205,14 @@ storageReadPosixNew(StoragePosix *storage, const String *name, bool ignoreMissin
MEM_CONTEXT_NEW_BEGIN("StorageReadPosix")
{
StorageReadPosix *driver = memNew(sizeof(StorageReadPosix));
driver->memContext = MEM_CONTEXT_NEW();
driver->interface = (StorageReadInterface)
*driver = (StorageReadPosix)
{
.memContext = MEM_CONTEXT_NEW(),
.storage = storage,
.handle = -1,
.interface = (StorageReadInterface)
{
.type = STORAGE_POSIX_TYPE_STR,
.name = strDup(name),
@ -221,11 +226,9 @@ storageReadPosixNew(StoragePosix *storage, const String *name, bool ignoreMissin
.open = storageReadPosixOpen,
.read = storageReadPosix,
},
},
};
driver->storage = storage;
driver->handle = -1;
this = storageReadNew(driver, &driver->interface);
}
MEM_CONTEXT_NEW_END();

View File

@ -677,8 +677,12 @@ storagePosixNewInternal(
MEM_CONTEXT_NEW_BEGIN("StoragePosix")
{
StoragePosix *driver = memNew(sizeof(StoragePosix));
driver->memContext = MEM_CONTEXT_NEW();
driver->interface = storageInterfacePosix;
*driver = (StoragePosix)
{
.memContext = MEM_CONTEXT_NEW(),
.interface = storageInterfacePosix,
};
// Disable path sync when not supported
if (!pathSync)

View File

@ -248,9 +248,15 @@ storageWritePosixNew(
MEM_CONTEXT_NEW_BEGIN("StorageWritePosix")
{
StorageWritePosix *driver = memNew(sizeof(StorageWritePosix));
driver->memContext = MEM_CONTEXT_NEW();
driver->interface = (StorageWriteInterface)
*driver = (StorageWritePosix)
{
.memContext = MEM_CONTEXT_NEW(),
.storage = storage,
.path = strPath(name),
.handle = -1,
.interface = (StorageWriteInterface)
{
.type = STORAGE_POSIX_TYPE_STR,
.name = strDup(name),
@ -271,12 +277,11 @@ storageWritePosixNew(
.open = storageWritePosixOpen,
.write = storageWritePosix,
},
},
};
driver->storage = storage;
// Create temp file name
driver->nameTmp = atomic ? strNewFmt("%s." STORAGE_FILE_TEMP_EXT, strPtr(name)) : driver->interface.name;
driver->path = strPath(name);
driver->handle = -1;
this = storageWriteNew(driver, &driver->interface);
}

View File

@ -48,11 +48,14 @@ storageReadNew(void *driver, const StorageReadInterface *interface)
StorageRead *this = NULL;
this = memNew(sizeof(StorageRead));
this->memContext = memContextCurrent();
this->driver = driver;
this->interface = interface;
this->io = ioReadNew(driver, interface->ioInterface);
*this = (StorageRead)
{
.memContext = memContextCurrent(),
.driver = driver,
.interface = interface,
.io = ioReadNew(driver, interface->ioInterface),
};
FUNCTION_LOG_RETURN(STORAGE_READ, this);
}

View File

@ -199,9 +199,14 @@ storageReadRemoteNew(
MEM_CONTEXT_NEW_BEGIN("StorageReadRemote")
{
this = memNew(sizeof(StorageReadRemote));
this->memContext = MEM_CONTEXT_NEW();
this->interface = (StorageReadInterface)
*this = (StorageReadRemote)
{
.memContext = MEM_CONTEXT_NEW(),
.storage = storage,
.client = client,
.interface = (StorageReadInterface)
{
.type = STORAGE_REMOTE_TYPE_STR,
.name = strDup(name),
@ -215,11 +220,9 @@ storageReadRemoteNew(
.open = storageReadRemoteOpen,
.read = storageReadRemote,
},
},
};
this->storage = storage;
this->client = client;
this->read = storageReadNew(this, &this->interface);
}
MEM_CONTEXT_NEW_END();

View File

@ -485,10 +485,14 @@ storageRemoteNew(
MEM_CONTEXT_NEW_BEGIN("StorageRemote")
{
StorageRemote *driver = memNew(sizeof(StorageRemote));
driver->memContext = MEM_CONTEXT_NEW();
driver->client = client;
driver->compressLevel = compressLevel;
driver->interface = storageInterfaceRemote;
*driver = (StorageRemote)
{
.memContext = MEM_CONTEXT_NEW(),
.client = client,
.compressLevel = compressLevel,
.interface = storageInterfaceRemote,
};
const String *path = NULL;

View File

@ -196,9 +196,14 @@ storageWriteRemoteNew(
MEM_CONTEXT_NEW_BEGIN("StorageWriteRemote")
{
this = memNew(sizeof(StorageWriteRemote));
this->memContext = MEM_CONTEXT_NEW();
this->interface = (StorageWriteInterface)
*this = (StorageWriteRemote)
{
.memContext = MEM_CONTEXT_NEW(),
.storage = storage,
.client = client,
.interface = (StorageWriteInterface)
{
.type = STORAGE_REMOTE_TYPE_STR,
.name = strDup(name),
@ -220,11 +225,9 @@ storageWriteRemoteNew(
.open = storageWriteRemoteOpen,
.write = storageWriteRemote,
},
},
};
this->storage = storage;
this->client = client;
this->write = storageWriteNew(this, &this->interface);
}
MEM_CONTEXT_NEW_END();

View File

@ -160,9 +160,13 @@ storageReadS3New(StorageS3 *storage, const String *name, bool ignoreMissing)
MEM_CONTEXT_NEW_BEGIN("StorageReadS3")
{
StorageReadS3 *driver = memNew(sizeof(StorageReadS3));
driver->memContext = MEM_CONTEXT_NEW();
driver->interface = (StorageReadInterface)
*driver = (StorageReadS3)
{
.memContext = MEM_CONTEXT_NEW(),
.storage = storage,
.interface = (StorageReadInterface)
{
.type = STORAGE_S3_TYPE_STR,
.name = strDup(name),
@ -175,10 +179,9 @@ storageReadS3New(StorageS3 *storage, const String *name, bool ignoreMissing)
.open = storageReadS3Open,
.read = storageReadS3,
},
},
};
driver->storage = storage;
this = storageReadNew(driver, &driver->interface);
}
MEM_CONTEXT_NEW_END();

View File

@ -960,23 +960,26 @@ storageS3New(
MEM_CONTEXT_NEW_BEGIN("StorageS3")
{
StorageS3 *driver = memNew(sizeof(StorageS3));
driver->memContext = MEM_CONTEXT_NEW();
driver->interface = storageInterfaceS3;
driver->bucket = strDup(bucket);
driver->region = strDup(region);
driver->accessKey = strDup(accessKey);
driver->secretAccessKey = strDup(secretAccessKey);
driver->securityToken = strDup(securityToken);
driver->partSize = partSize;
driver->deleteMax = deleteMax;
driver->uriStyle = uriStyle;
driver->bucketEndpoint = uriStyle == storageS3UriStyleHost ?
strNewFmt("%s.%s", strPtr(bucket), strPtr(endPoint)) : strDup(endPoint);
driver->port = port;
*driver = (StorageS3)
{
.memContext = MEM_CONTEXT_NEW(),
.interface = storageInterfaceS3,
.bucket = strDup(bucket),
.region = strDup(region),
.accessKey = strDup(accessKey),
.secretAccessKey = strDup(secretAccessKey),
.securityToken = strDup(securityToken),
.partSize = partSize,
.deleteMax = deleteMax,
.uriStyle = uriStyle,
.bucketEndpoint = uriStyle == storageS3UriStyleHost ?
strNewFmt("%s.%s", strPtr(bucket), strPtr(endPoint)) : strDup(endPoint),
.port = port,
// Force the signing key to be generated on the first run
driver->signingKeyDate = YYYYMMDD_STR;
.signingKeyDate = YYYYMMDD_STR,
};
// Create the http client cache used to service requests
driver->httpClientCache = httpClientCacheNew(

View File

@ -245,9 +245,14 @@ storageWriteS3New(StorageS3 *storage, const String *name, size_t partSize)
MEM_CONTEXT_NEW_BEGIN("StorageWriteS3")
{
StorageWriteS3 *driver = memNew(sizeof(StorageWriteS3));
driver->memContext = MEM_CONTEXT_NEW();
driver->interface = (StorageWriteInterface)
*driver = (StorageWriteS3)
{
.memContext = MEM_CONTEXT_NEW(),
.storage = storage,
.partSize = partSize,
.interface = (StorageWriteInterface)
{
.type = STORAGE_S3_TYPE_STR,
.name = strDup(name),
@ -262,11 +267,9 @@ storageWriteS3New(StorageS3 *storage, const String *name, size_t partSize)
.open = storageWriteS3Open,
.write = storageWriteS3,
},
},
};
driver->storage = storage;
driver->partSize = partSize;
this = storageWriteNew(driver, &driver->interface);
}
MEM_CONTEXT_NEW_END();

View File

@ -64,18 +64,20 @@ storageNew(
ASSERT(interface.pathRemove != NULL);
ASSERT(interface.remove != NULL);
Storage *this = NULL;
this = (Storage *)memNew(sizeof(Storage));
this->memContext = memContextCurrent();
this->driver = driver;
this->interface = interface;
this->type = type;
Storage *this = (Storage *)memNew(sizeof(Storage));
this->path = strDup(path);
this->modeFile = modeFile;
this->modePath = modePath;
this->write = write;
this->pathExpressionFunction = pathExpressionFunction;
*this = (Storage)
{
.memContext = memContextCurrent(),
.driver = driver,
.interface = interface,
.type = type,
.path = strDup(path),
.modeFile = modeFile,
.modePath = modePath,
.write = write,
.pathExpressionFunction = pathExpressionFunction,
};
// If path sync feature is enabled then path feature must be enabled
CHECK(!storageFeature(this, storageFeaturePathSync) || storageFeature(this, storageFeaturePath));

View File

@ -49,12 +49,14 @@ storageWriteNew(void *driver, const StorageWriteInterface *interface)
ASSERT(interface != NULL);
StorageWrite *this = memNew(sizeof(StorageWrite));
this->memContext = memContextCurrent();
this->driver = driver;
this->interface = interface;
this->io = ioWriteNew(driver, interface->ioInterface);
*this = (StorageWrite)
{
.memContext = memContextCurrent(),
.driver = driver,
.interface = interface,
.io = ioWriteNew(driver, interface->ioInterface),
};
FUNCTION_LOG_RETURN(STORAGE_WRITE, this);
}

View File

@ -126,6 +126,9 @@ testRun(void)
Buffer *bufferOut = bufNew(0);
bufUsedSet(buffer, bufSize(buffer));
memset(bufPtr(buffer), 0, bufSize(buffer));
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x00)) = (PageHeaderData){.pd_upper = 0};
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x01)) = (PageHeaderData){.pd_upper = 0};
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x02)) = (PageHeaderData){.pd_upper = 0};
IoWrite *write = ioBufferWriteNew(bufferOut);
ioFilterGroupAdd(ioWriteFilterGroup(write), pageChecksumNew(0, PG_SEGMENT_PAGE_DEFAULT, PG_PAGE_SIZE_DEFAULT, 0));
@ -144,9 +147,15 @@ testRun(void)
memset(bufPtr(buffer), 0, bufSize(buffer));
// Page 0 has bogus checksum
((PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x00)))->pd_upper = 0x01;
((PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x00)))->pd_lsn.walid = 0xF0F0F0F0;
((PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x00)))->pd_lsn.xrecoff = 0xF0F0F0F0;
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x00)) = (PageHeaderData)
{
.pd_upper = 0x01,
.pd_lsn = (PageWalRecPtr)
{
.walid = 0xF0F0F0F0,
.xrecoff = 0xF0F0F0F0,
},
};
write = ioBufferWriteNew(bufferOut);
@ -171,34 +180,79 @@ testRun(void)
memset(bufPtr(buffer), 0, bufSize(buffer));
// Page 0 has bogus checksum
((PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x00)))->pd_upper = 0x01;
((PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x00)))->pd_lsn.walid = 0xF0F0F0F0;
((PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x00)))->pd_lsn.xrecoff = 0xF0F0F0F0;
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x00)) = (PageHeaderData)
{
.pd_upper = 0x01,
.pd_lsn = (PageWalRecPtr)
{
.walid = 0xF0F0F0F0,
.xrecoff = 0xF0F0F0F0,
},
};
// Page 1 has bogus checksum but lsn above the limit
((PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x01)))->pd_upper = 0x01;
((PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x01)))->pd_lsn.walid = 0xFACEFACE;
((PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x01)))->pd_lsn.xrecoff = 0x00000000;
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x01)) = (PageHeaderData)
{
.pd_upper = 0x01,
.pd_lsn = (PageWalRecPtr)
{
.walid = 0xFACEFACE,
.xrecoff = 0x00000000,
},
};
// Page 2 has bogus checksum
((PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x02)))->pd_upper = 0x01;
((PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x02)))->pd_lsn.xrecoff = 0x2;
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x02)) = (PageHeaderData)
{
.pd_upper = 0x01,
.pd_lsn = (PageWalRecPtr)
{
.xrecoff = 0x2,
},
};
// Page 3 has bogus checksum
((PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x03)))->pd_upper = 0x01;
((PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x03)))->pd_lsn.xrecoff = 0x3;
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x03)) = (PageHeaderData)
{
.pd_upper = 0x01,
.pd_lsn = (PageWalRecPtr)
{
.xrecoff = 0x3,
},
};
// Page 4 has bogus checksum
((PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x04)))->pd_upper = 0x01;
((PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x04)))->pd_lsn.xrecoff = 0x4;
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x04)) = (PageHeaderData)
{
.pd_upper = 0x01,
.pd_lsn = (PageWalRecPtr)
{
.xrecoff = 0x4,
},
};
// Page 5 is zero
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x05)) = (PageHeaderData){.pd_upper = 0x00};
// Page 6 has bogus checksum
((PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x06)))->pd_upper = 0x01;
((PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x06)))->pd_lsn.xrecoff = 0x6;
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x06)) = (PageHeaderData)
{
.pd_upper = 0x01,
.pd_lsn = (PageWalRecPtr)
{
.xrecoff = 0x6,
},
};
// Page 7 has bogus checksum (and is misaligned but large enough to test)
((PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x07)))->pd_upper = 0x01;
((PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x07)))->pd_lsn.xrecoff = 0x7;
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x07)) = (PageHeaderData)
{
.pd_upper = 0x01,
.pd_lsn = (PageWalRecPtr)
{
.xrecoff = 0x7,
},
};
write = ioBufferWriteNew(bufferOut);
ioFilterGroupAdd(
@ -217,6 +271,8 @@ testRun(void)
bufUsedSet(buffer, bufSize(buffer));
memset(bufPtr(buffer), 0, bufSize(buffer));
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x00)) = (PageHeaderData){.pd_upper = 0};
write = ioBufferWriteNew(bufferOut);
ioFilterGroupAdd(
ioWriteFilterGroup(write), pageChecksumNew(0, PG_SEGMENT_PAGE_DEFAULT, PG_PAGE_SIZE_DEFAULT, 0xFACEFACE00000000));
@ -234,6 +290,8 @@ testRun(void)
bufUsedSet(buffer, bufSize(buffer));
memset(bufPtr(buffer), 0, bufSize(buffer));
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x00)) = (PageHeaderData){.pd_upper = 0};
write = ioBufferWriteNew(bufferOut);
ioFilterGroupAdd(
ioWriteFilterGroup(write), pageChecksumNew(0, PG_SEGMENT_PAGE_DEFAULT, PG_PAGE_SIZE_DEFAULT, 0xFACEFACE00000000));

View File

@ -2043,6 +2043,8 @@ testRun(void)
memset(bufPtr(relation), 0, bufSize(relation));
bufUsedSet(relation, bufSize(relation));
*(PageHeaderData *)(bufPtr(relation) + (PG_PAGE_SIZE_DEFAULT * 0x00)) = (PageHeaderData){.pd_upper = 0};
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF(PG_PATH_BASE "/1/1"), .timeModified = backupTimeStart), relation);
// Zeroed file which will fail on alignment
@ -2050,14 +2052,17 @@ testRun(void)
memset(bufPtr(relation), 0, bufSize(relation));
bufUsedSet(relation, bufSize(relation));
*(PageHeaderData *)(bufPtr(relation) + (PG_PAGE_SIZE_DEFAULT * 0x00)) = (PageHeaderData){.pd_upper = 0};
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF(PG_PATH_BASE "/1/2"), .timeModified = backupTimeStart), relation);
// File with bad page checksums
relation = bufNew(PG_PAGE_SIZE_DEFAULT * 4);
memset(bufPtr(relation), 0, bufSize(relation));
((PageHeaderData *)(bufPtr(relation) + PG_PAGE_SIZE_DEFAULT * 0))->pd_upper = 0xFF;
((PageHeaderData *)(bufPtr(relation) + PG_PAGE_SIZE_DEFAULT * 2))->pd_upper = 0xFE;
((PageHeaderData *)(bufPtr(relation) + PG_PAGE_SIZE_DEFAULT * 3))->pd_upper = 0xEF;
*(PageHeaderData *)(bufPtr(relation) + (PG_PAGE_SIZE_DEFAULT * 0x00)) = (PageHeaderData){.pd_upper = 0xFF};
*(PageHeaderData *)(bufPtr(relation) + (PG_PAGE_SIZE_DEFAULT * 0x01)) = (PageHeaderData){.pd_upper = 0x00};
*(PageHeaderData *)(bufPtr(relation) + (PG_PAGE_SIZE_DEFAULT * 0x02)) = (PageHeaderData){.pd_upper = 0xFE};
*(PageHeaderData *)(bufPtr(relation) + (PG_PAGE_SIZE_DEFAULT * 0x03)) = (PageHeaderData){.pd_upper = 0xEF};
bufUsedSet(relation, bufSize(relation));
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF(PG_PATH_BASE "/1/3"), .timeModified = backupTimeStart), relation);
@ -2065,7 +2070,9 @@ testRun(void)
// File with bad page checksum
relation = bufNew(PG_PAGE_SIZE_DEFAULT * 3);
memset(bufPtr(relation), 0, bufSize(relation));
((PageHeaderData *)(bufPtr(relation) + PG_PAGE_SIZE_DEFAULT * 1))->pd_upper = 0x08;
*(PageHeaderData *)(bufPtr(relation) + (PG_PAGE_SIZE_DEFAULT * 0x00)) = (PageHeaderData){.pd_upper = 0x00};
*(PageHeaderData *)(bufPtr(relation) + (PG_PAGE_SIZE_DEFAULT * 0x01)) = (PageHeaderData){.pd_upper = 0x08};
*(PageHeaderData *)(bufPtr(relation) + (PG_PAGE_SIZE_DEFAULT * 0x02)) = (PageHeaderData){.pd_upper = 0x00};
bufUsedSet(relation, bufSize(relation));
storagePutP(storageNewWriteP(storagePgWrite(), STRDEF(PG_PATH_BASE "/1/4"), .timeModified = backupTimeStart), relation);

View File

@ -56,17 +56,17 @@ testRun(void)
// Test if the buffer was overrun
// -------------------------------------------------------------------------------------------------------------------------
size_t bufferSize = 256;
unsigned char *buffer = memNew(bufferSize + 1);
unsigned char buffer[256] = {0};
cryptoRandomBytes(buffer, bufferSize);
TEST_RESULT_BOOL(buffer[bufferSize] == 0, true, "check that buffer did not overrun (though random byte could be 0)");
cryptoRandomBytes(buffer, sizeof(buffer) - 1);
TEST_RESULT_BOOL(
buffer[sizeof(buffer) - 1] == 0, true, "check that buffer did not overrun (though random byte could be 0)");
// Count bytes that are not zero (there shouldn't be all zeroes)
// -------------------------------------------------------------------------------------------------------------------------
int nonZeroTotal = 0;
for (unsigned int charIdx = 0; charIdx < bufferSize; charIdx++)
for (unsigned int charIdx = 0; charIdx < sizeof(buffer) - 1; charIdx++)
if (buffer[charIdx] != 0) // {uncoverable_branch - ok if there are no zeros}
nonZeroTotal++;

View File

@ -27,6 +27,8 @@ testRun(void)
// *****************************************************************************************************************************
if (testBegin("exitInit() and exitOnSignal()"))
{
cfgInit();
HARNESS_FORK_BEGIN()
{
HARNESS_FORK_CHILD_BEGIN(errorTypeCode(&TermError), false)

View File

@ -111,7 +111,11 @@ ioTestFilterSizeNew(const char *type)
MEM_CONTEXT_NEW_BEGIN("IoTestFilterSize")
{
IoTestFilterSize *driver = memNew(sizeof(IoTestFilterSize));
driver->memContext = MEM_CONTEXT_NEW();
*driver = (IoTestFilterSize)
{
.memContext = MEM_CONTEXT_NEW(),
};
this = ioFilterNewP(strNew(type), driver, NULL, .in = ioTestFilterSizeProcess, .result = ioTestFilterSizeResult);
}
@ -212,11 +216,15 @@ ioTestFilterMultiplyNew(const char *type, unsigned int multiplier, unsigned int
MEM_CONTEXT_NEW_BEGIN("IoTestFilterMultiply")
{
IoTestFilterMultiply *driver = memNew(sizeof(IoTestFilterMultiply));
driver->memContext = MEM_CONTEXT_NEW();
driver->bufferFilter = ioBufferNew();
driver->multiplier = multiplier;
driver->flushTotal = flushTotal;
driver->flushChar = flushChar;
*driver = (IoTestFilterMultiply)
{
.memContext = MEM_CONTEXT_NEW(),
.bufferFilter = ioBufferNew(),
.multiplier = multiplier,
.flushTotal = flushTotal,
.flushChar = flushChar,
};
VariantList *paramList = varLstNew();
varLstAdd(paramList, varNewStrZ(type));

View File

@ -43,49 +43,31 @@ testRun(void)
// valgrind will accept
if (TEST_64BIT())
{
TEST_ERROR(memAllocInternal((size_t)5629499534213120, false), MemoryError, "unable to allocate 5629499534213120 bytes");
TEST_ERROR(memAllocInternal((size_t)5629499534213120), MemoryError, "unable to allocate 5629499534213120 bytes");
TEST_ERROR(memFreeInternal(NULL), AssertError, "assertion 'buffer != NULL' failed");
// Check that bad realloc is caught
void *buffer = memAllocInternal(sizeof(size_t), false);
void *buffer = memAllocInternal(sizeof(size_t));
TEST_ERROR(
memReAllocInternal(buffer, sizeof(size_t), (size_t)5629499534213120, false), MemoryError,
memReAllocInternal(buffer, (size_t)5629499534213120), MemoryError,
"unable to reallocate 5629499534213120 bytes");
memFreeInternal(buffer);
}
// Normal memory allocation
void *buffer = memAllocInternal(sizeof(size_t), false);
buffer = memReAllocInternal(buffer, sizeof(size_t), sizeof(size_t) * 2, false);
memFreeInternal(buffer);
// Memory allocation
void *buffer = memAllocInternal(sizeof(size_t));
// Memory reallocation
memset(buffer, 0xC7, sizeof(size_t));
unsigned char *buffer2 = memReAllocInternal(buffer, sizeof(size_t) * 2);
// Zeroed memory allocation
unsigned char *buffer2 = memAllocInternal(sizeof(size_t), true);
int expectedTotal = 0;
for (unsigned int charIdx = 0; charIdx < sizeof(size_t); charIdx++)
expectedTotal += buffer2[charIdx] == 0;
TEST_RESULT_INT(expectedTotal, sizeof(size_t), "all bytes are 0");
// Zeroed memory reallocation
memset(buffer2, 0xC7, sizeof(size_t));
buffer2 = memReAllocInternal(buffer2, sizeof(size_t), sizeof(size_t) * 2, true);
expectedTotal = 0;
for (unsigned int charIdx = 0; charIdx < sizeof(size_t); charIdx++)
expectedTotal += buffer2[charIdx] == 0xC7;
TEST_RESULT_INT(expectedTotal, sizeof(size_t), "all old bytes are filled");
expectedTotal = 0;
for (unsigned int charIdx = 0; charIdx < sizeof(size_t); charIdx++)
expectedTotal += (buffer2 + sizeof(size_t))[charIdx] == 0;
TEST_RESULT_INT(expectedTotal, sizeof(size_t), "all new bytes are 0");
memFreeInternal(buffer2);
}
@ -175,22 +157,14 @@ testRun(void)
if (testBegin("memContextAlloc(), memNew*(), memGrow(), and memFree()"))
{
memContextSwitch(memContextTop());
memNew(sizeof(size_t));
memNewPtrArray(1);
MemContext *memContext = memContextNew("test-alloc");
memContextSwitch(memContext);
for (int allocIdx = 0; allocIdx <= MEM_CONTEXT_ALLOC_INITIAL_SIZE; allocIdx++)
{
unsigned char *buffer = memNew(sizeof(size_t));
// Check that the buffer is zeroed
int expectedTotal = 0;
for (unsigned int charIdx = 0; charIdx < sizeof(size_t); charIdx++)
expectedTotal += buffer[charIdx] == 0;
TEST_RESULT_INT(expectedTotal, sizeof(size_t), "all bytes are 0");
memNew(sizeof(size_t));
TEST_RESULT_INT(
memContextCurrent()->allocListSize,
@ -198,12 +172,11 @@ testRun(void)
"allocation list size");
}
unsigned char *buffer = memNewRaw(sizeof(size_t));
unsigned char *buffer = memNew(sizeof(size_t));
// Grow memory
memset(buffer, 0xFE, sizeof(size_t));
buffer = memGrowRaw(buffer, sizeof(size_t) * 2);
buffer = memResize(buffer, sizeof(size_t) * 2);
// Check that original portion of the buffer is preserved
int expectedTotal = 0;

View File

@ -58,7 +58,11 @@ testObjectNew(void)
MEM_CONTEXT_NEW_BEGIN(STRINGIFY(TestObject))
{
this = memNew(sizeof(TestObject));
this->memContext = memContextCurrent();
*this = (TestObject)
{
.memContext = MEM_CONTEXT_NEW(),
};
memContextCallbackSet(this->memContext, testObjectFreeResource, (void *)1);
}

View File

@ -153,10 +153,10 @@ testRun(void)
TEST_RESULT_INT(cfgOptionSource(cfgOptOnline), cfgSourceParam, "online source is set");
TEST_ERROR(
cfgOptionDbl(cfgOptOnline), AssertError,
"assertion 'varType(configOptionValue[optionId].value) == varTypeDouble' failed");
"assertion 'varType(configStatic.option[optionId].value) == varTypeDouble' failed");
TEST_ERROR(
cfgOptionInt64(cfgOptOnline), AssertError,
"assertion 'varType(configOptionValue[optionId].value) == varTypeInt64' failed");
"assertion 'varType(configStatic.option[optionId].value) == varTypeInt64' failed");
TEST_RESULT_VOID(cfgOptionSet(cfgOptCompressLevel, cfgSourceParam, varNewInt64(1)), "set compress-level");
TEST_RESULT_INT(cfgOptionInt(cfgOptCompressLevel), 1, "compress-level is set");
@ -165,7 +165,7 @@ testRun(void)
TEST_RESULT_INT(cfgOptionSource(cfgOptCompressLevel), cfgSourceDefault, "compress source is set");
TEST_ERROR(
cfgOptionBool(cfgOptCompressLevel), AssertError,
"assertion 'varType(configOptionValue[optionId].value) == varTypeBool' failed");
"assertion 'varType(configStatic.option[optionId].value) == varTypeBool' failed");
TEST_RESULT_VOID(
cfgOptionSet(cfgOptArchivePushQueueMax, cfgSourceParam, varNewInt64(999999999999)), "set archive-push-queue-max");
@ -179,7 +179,7 @@ testRun(void)
TEST_RESULT_INT(cfgOptionSource(cfgOptProtocolTimeout), cfgSourceConfig, "protocol-timeout source is set");
TEST_ERROR(
cfgOptionKv(cfgOptProtocolTimeout), AssertError,
"assertion 'varType(configOptionValue[optionId].value) == varTypeKeyValue' failed");
"assertion 'varType(configStatic.option[optionId].value) == varTypeKeyValue' failed");
TEST_RESULT_VOID(cfgOptionSet(cfgOptProtocolTimeout, cfgSourceConfig, NULL), "set protocol-timeout to NULL");
TEST_RESULT_PTR(cfgOption(cfgOptProtocolTimeout), NULL, "protocol-timeout is not set");
@ -191,8 +191,8 @@ testRun(void)
TEST_RESULT_INT(varLstSize(kvKeyList(cfgOptionKv(cfgOptRecoveryOption))), 0, "recovery-option is set");
TEST_ERROR(
cfgOptionLst(cfgOptRecoveryOption), AssertError,
"assertion 'configOptionValue[optionId].value == NULL"
" || varType(configOptionValue[optionId].value) == varTypeVariantList' failed");
"assertion 'configStatic.option[optionId].value == NULL"
" || varType(configStatic.option[optionId].value) == varTypeVariantList' failed");
TEST_RESULT_INT(varLstSize(cfgOptionLst(cfgOptDbInclude)), 0, "db-include defaults to empty");
TEST_ERROR(
@ -202,8 +202,8 @@ testRun(void)
TEST_RESULT_INT(varLstSize(cfgOptionLst(cfgOptDbInclude)), 0, "db-include is set");
TEST_ERROR(
cfgOptionStr(cfgOptDbInclude), AssertError,
"assertion 'configOptionValue[optionId].value == NULL"
" || varType(configOptionValue[optionId].value) == varTypeString' failed");
"assertion 'configStatic.option[optionId].value == NULL"
" || varType(configStatic.option[optionId].value) == varTypeString' failed");
TEST_RESULT_PTR(cfgOptionStr(cfgOptStanza), NULL, "stanza defaults to null");
TEST_ERROR(
@ -213,7 +213,7 @@ testRun(void)
TEST_RESULT_STR_Z(cfgOptionStr(cfgOptStanza), "db", "stanza is set");
TEST_ERROR(
cfgOptionInt(cfgOptStanza), AssertError,
"assertion 'varType(configOptionValue[optionId].value) == varTypeInt64' failed");
"assertion 'varType(configStatic.option[optionId].value) == varTypeInt64' failed");
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_VOID(cfgInit(), "config init resets value");

View File

@ -145,8 +145,7 @@ testRun(void)
String *oldConfigDefault = strNewFmt("%s%s", testPath(), PGBACKREST_CONFIG_ORIG_PATH_FILE);
// Create the option structure and initialize with 0
ParseOption parseOptionList[CFG_OPTION_TOTAL];
memset(&parseOptionList, 0, sizeof(parseOptionList));
ParseOption parseOptionList[CFG_OPTION_TOTAL] = {{.found = false}};
StringList *value = strLstNew();
strLstAdd(value, configFile);

View File

@ -56,8 +56,12 @@ testRun(void)
Buffer *result = bufNew(PG_CONTROL_SIZE);
memset(bufPtr(result), 0, bufSize(result));
bufUsedSet(result, bufSize(result));
((PgControlCommon *)bufPtr(result))->controlVersion = 501;
((PgControlCommon *)bufPtr(result))->catalogVersion = 19780101;
*(PgControlCommon *)bufPtr(result) = (PgControlCommon)
{
.controlVersion = 501,
.catalogVersion = 19780101,
};
TEST_ERROR(
pgControlFromBuffer(result), VersionNotSupportedError,
@ -184,7 +188,8 @@ testRun(void)
Buffer *result = bufNew((size_t)16 * 1024 * 1024);
memset(bufPtr(result), 0, bufSize(result));
bufUsedSet(result, bufSize(result));
((PgWalCommon *)bufPtr(result))->magic = 777;
*(PgWalCommon *)bufPtr(result) = (PgWalCommon){.magic = 777};
TEST_ERROR(pgWalFromBuffer(result), FormatError, "first page header in WAL file is expected to be in long format");

View File

@ -47,19 +47,21 @@ testRun(void)
// Zero the pages
memset(testPage(0), 0, TEST_PAGE_TOTAL * TEST_PAGE_SIZE);
for (unsigned int pageIdx = 0; pageIdx < TEST_PAGE_TOTAL; pageIdx++)
*(PageHeader)testPage(pageIdx) = (PageHeaderData){.pd_upper = 0x0};
// Pages with pd_upper = 0 should always return true no matter the block no
TEST_RESULT_BOOL(pageChecksumTest(testPage(0), 0, TEST_PAGE_SIZE, 0, 0), true, "pd_upper is 0, block 0");
TEST_RESULT_BOOL(pageChecksumTest(testPage(1), 999, TEST_PAGE_SIZE, 0, 0), true, "pd_upper is 0, block 999");
// Partial pages are always invalid
((PageHeader)testPage(0))->pd_upper = 0x00FF;
*(PageHeader)testPage(0) = (PageHeaderData){.pd_upper = 0x00FF};
((PageHeader)testPage(0))->pd_checksum = pageChecksum(testPage(0), 0, TEST_PAGE_SIZE);
TEST_RESULT_BOOL(pageChecksumTest(testPage(0), 0, TEST_PAGE_SIZE, 1, 1), true, "valid page");
TEST_RESULT_BOOL(pageChecksumTest(testPage(0), 0, TEST_PAGE_SIZE / 2, 1, 1), false, "invalid partial page");
// Update pd_upper and check for failure no matter the block no
((PageHeader)testPage(0))->pd_upper = 0x00FF;
((PageHeader)testPage(0))->pd_checksum = 0;
*(PageHeader)testPage(0) = (PageHeaderData){.pd_upper = 0x00FF, .pd_checksum = 0};
TEST_RESULT_BOOL(pageChecksumTest(testPage(0), 0, TEST_PAGE_SIZE, 0xFFFF, 0xFFFF), false, "badchecksum, page 0");
TEST_RESULT_BOOL(
pageChecksumTest(testPage(0), 9999, TEST_PAGE_SIZE, 0xFFFF, 0xFFFF), false, "badchecksum, page 9999");