mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-03-05 15:05:48 +02:00
Exclude mem context name from production builds.
The mem context name is used to produce clearer debug errors but it has no purpose in production builds. Also remove memContextName() and access the struct directly since the name is only used within the common/memContext module. Note that a few errors that were thrown in production builds (and required the name) are now only thrown in debug builds. In practice we have not seen these errors in production builds due to extensive coverage so it does not seem worth modifying the error to work without the context name. This saves some memory, which is worthwhile, but the goal is to refactor Strings and Variants to have their own mem contexts and this change will prevent them from using more memory than they are now, along with other changes that will be coming later.
This commit is contained in:
parent
0055fa40fe
commit
eb435becb3
@ -49,7 +49,9 @@ Contains information about the memory context
|
||||
***********************************************************************************************************************************/
|
||||
struct MemContext
|
||||
{
|
||||
#ifdef DEBUG
|
||||
const char *name; // Indicates what the context is being used for
|
||||
#endif
|
||||
MemContextState state:1; // Current state of the context
|
||||
size_t allocExtra:16; // Size of extra allocation (1kB max)
|
||||
|
||||
@ -74,7 +76,13 @@ Top context
|
||||
The top context always exists and can never be freed. All other contexts are children of the top context. The top context is
|
||||
generally used to allocate memory that exists for the life of the program.
|
||||
***********************************************************************************************************************************/
|
||||
static MemContext contextTop = {.state = memContextStateActive, .name = "TOP"};
|
||||
static MemContext contextTop =
|
||||
{
|
||||
.state = memContextStateActive,
|
||||
#ifdef DEBUG
|
||||
.name = "TOP",
|
||||
#endif
|
||||
};
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Memory context stack types
|
||||
@ -257,7 +265,11 @@ memContextNewIndex(MemContext *memContext)
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
MemContext *
|
||||
memContextNew(const char *const name, const MemContextNewParam param)
|
||||
memContextNew(
|
||||
#ifdef DEBUG
|
||||
const char *const name,
|
||||
#endif
|
||||
const MemContextNewParam param)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(STRINGZ, name);
|
||||
@ -280,8 +292,10 @@ memContextNew(const char *const name, const MemContextNewParam param)
|
||||
|
||||
*this = (MemContext)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// Set the context name
|
||||
.name = name,
|
||||
#endif
|
||||
|
||||
// Set extra allocation
|
||||
.allocExtra = param.allocExtra,
|
||||
@ -373,9 +387,11 @@ memContextCallbackSet(MemContext *this, void (*callbackFunction)(void *), void *
|
||||
if (this == &contextTop)
|
||||
THROW(AssertError, "top context may not have a callback");
|
||||
|
||||
#ifdef DEBUG
|
||||
// Error if callback has already been set - there may be valid use cases for this but error until one is found
|
||||
if (this->callbackFunction)
|
||||
THROW_FMT(AssertError, "callback is already set for context '%s'", this->name);
|
||||
#endif
|
||||
|
||||
// Set callback function and argument
|
||||
this->callbackFunction = callbackFunction;
|
||||
@ -629,7 +645,7 @@ memContextSwitchBack(void)
|
||||
{
|
||||
THROW_FMT(
|
||||
AssertError, "current context expected but new context '%s' found",
|
||||
memContextName(memContextStack[memContextMaxStackIdx].memContext));
|
||||
memContextStack[memContextMaxStackIdx].memContext->name);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -658,7 +674,7 @@ memContextKeep(void)
|
||||
{
|
||||
THROW_FMT(
|
||||
AssertError, "new context expected but current context '%s' found",
|
||||
memContextName(memContextStack[memContextMaxStackIdx].memContext));
|
||||
memContextStack[memContextMaxStackIdx].memContext->name);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -679,7 +695,7 @@ memContextDiscard(void)
|
||||
{
|
||||
THROW_FMT(
|
||||
AssertError, "new context expected but current context '%s' found",
|
||||
memContextName(memContextStack[memContextMaxStackIdx].memContext));
|
||||
memContextStack[memContextMaxStackIdx].memContext->name);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -718,23 +734,6 @@ memContextFreeing(const MemContext *const this)
|
||||
FUNCTION_TEST_RETURN(BOOL, this->state == memContextStateFreeing);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
const char *
|
||||
memContextName(const MemContext *const this)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(MEM_CONTEXT, this);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
ASSERT(this != NULL);
|
||||
|
||||
// Error if context is not active
|
||||
if (this->state != memContextStateActive)
|
||||
THROW(AssertError, "cannot get name for inactive context");
|
||||
|
||||
FUNCTION_TEST_RETURN_CONST(STRINGZ, this->name);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
MemContext *
|
||||
memContextPrior(void)
|
||||
@ -827,9 +826,11 @@ memContextFree(MemContext *this)
|
||||
// If context is already freeing then return if memContextFree() is called again - this can happen in callbacks
|
||||
if (this->state != memContextStateFreeing)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
// Current context cannot be freed unless it is top (top is never really freed, just the stuff under it)
|
||||
if (this == memContextStack[memContextCurrentStackIdx].memContext && this != &contextTop)
|
||||
THROW_FMT(AssertError, "cannot free current context '%s'", this->name);
|
||||
#endif
|
||||
|
||||
// Free child contexts
|
||||
for (unsigned int contextIdx = 0; contextIdx < this->contextChildListSize; contextIdx++)
|
||||
|
@ -207,10 +207,19 @@ typedef struct MemContextNewParam
|
||||
uint16_t allocExtra; // Extra memory to allocate with the context
|
||||
} MemContextNewParam;
|
||||
|
||||
#define memContextNewP(name, ...) \
|
||||
memContextNew(name, (MemContextNewParam){VAR_PARAM_INIT, __VA_ARGS__})
|
||||
#ifdef DEBUG
|
||||
#define memContextNewP(name, ...) \
|
||||
memContextNew(name, (MemContextNewParam){VAR_PARAM_INIT, __VA_ARGS__})
|
||||
#else
|
||||
#define memContextNewP(name, ...) \
|
||||
memContextNew((MemContextNewParam){VAR_PARAM_INIT, __VA_ARGS__})
|
||||
#endif
|
||||
|
||||
MemContext *memContextNew(const char *name, MemContextNewParam param);
|
||||
MemContext *memContextNew(
|
||||
#ifdef DEBUG
|
||||
const char *name,
|
||||
#endif
|
||||
MemContextNewParam param);
|
||||
|
||||
// Switch to a context making it the current mem context
|
||||
void memContextSwitch(MemContext *this);
|
||||
@ -268,9 +277,6 @@ MemContext *memContextPrior(void);
|
||||
// good place to put long-lived mem contexts since they won't be automatically freed until the program exits.
|
||||
MemContext *memContextTop(void);
|
||||
|
||||
// Mem context name
|
||||
const char *memContextName(const MemContext *this);
|
||||
|
||||
// Get total size of mem context and all children
|
||||
size_t memContextSize(const MemContext *this);
|
||||
|
||||
|
@ -18,9 +18,7 @@ testFree(void *thisVoid)
|
||||
TEST_RESULT_INT(this->state, memContextStateFreeing, "state should still be freeing after memContextFree() in callback");
|
||||
|
||||
TEST_ERROR(memContextCallbackSet(this, testFree, this), AssertError, "cannot assign callback to inactive context");
|
||||
|
||||
TEST_ERROR(memContextSwitch(this), AssertError, "cannot switch to inactive context");
|
||||
TEST_ERROR(memContextName(this), AssertError, "cannot get name for inactive context");
|
||||
|
||||
memContextCallbackArgument = this;
|
||||
|
||||
@ -80,7 +78,7 @@ testRun(void)
|
||||
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
// Make sure top context was created
|
||||
TEST_RESULT_Z(memContextName(memContextTop()), "TOP", "top context should exist");
|
||||
TEST_RESULT_Z(memContextTop()->name, "TOP", "top context should exist");
|
||||
TEST_RESULT_INT(memContextTop()->contextChildListSize, 0, "top context should init with zero children");
|
||||
TEST_RESULT_PTR(memContextTop()->contextChildList, NULL, "top context child list empty");
|
||||
|
||||
@ -92,7 +90,7 @@ testRun(void)
|
||||
|
||||
MemContext *memContext = memContextNewP("test1");
|
||||
memContextKeep();
|
||||
TEST_RESULT_Z(memContextName(memContext), "test1", "test1 context name");
|
||||
TEST_RESULT_Z(memContext->name, "test1", "test1 context name");
|
||||
TEST_RESULT_PTR(memContext->contextParent, memContextTop(), "test1 context parent is top");
|
||||
TEST_RESULT_INT(memContextTop()->contextChildListSize, MEM_CONTEXT_INITIAL_SIZE, "initial top context child list size");
|
||||
|
||||
@ -110,7 +108,7 @@ testRun(void)
|
||||
memContextKeep();
|
||||
TEST_RESULT_BOOL(
|
||||
memContextTop()->contextChildList[contextIdx]->state == memContextStateActive, true, "new context is active");
|
||||
TEST_RESULT_Z(memContextName(memContextTop()->contextChildList[contextIdx]), "test-filler", "new context name");
|
||||
TEST_RESULT_Z(memContextTop()->contextChildList[contextIdx]->name, "test-filler", "new context name");
|
||||
}
|
||||
|
||||
// This forces the child context array to grow
|
||||
@ -134,7 +132,7 @@ testRun(void)
|
||||
TEST_RESULT_BOOL(
|
||||
memContextTop()->contextChildList[1]->state == memContextStateActive,
|
||||
true, "new context in same index as freed context is active");
|
||||
TEST_RESULT_Z(memContextName(memContextTop()->contextChildList[1]), "test-reuse", "new context name");
|
||||
TEST_RESULT_Z(memContextTop()->contextChildList[1]->name, "test-reuse", "new context name");
|
||||
TEST_RESULT_UINT(memContextTop()->contextChildFreeIdx, 2, "check context free idx");
|
||||
|
||||
// Next context will be at the end
|
||||
@ -287,23 +285,23 @@ testRun(void)
|
||||
// Check normal block
|
||||
MEM_CONTEXT_BEGIN(memContext)
|
||||
{
|
||||
TEST_RESULT_Z(memContextName(memContextCurrent()), "test-block", "context is now test-block");
|
||||
TEST_RESULT_Z(memContextCurrent()->name, "test-block", "context is now test-block");
|
||||
}
|
||||
MEM_CONTEXT_END();
|
||||
|
||||
TEST_RESULT_Z(memContextName(memContextCurrent()), "TOP", "context is now top");
|
||||
TEST_RESULT_Z(memContextCurrent()->name, "TOP", "context is now top");
|
||||
|
||||
// Check block that errors
|
||||
TEST_ERROR(
|
||||
MEM_CONTEXT_BEGIN(memContext)
|
||||
{
|
||||
TEST_RESULT_Z(memContextName(memContextCurrent()), "test-block", "context is now test-block");
|
||||
TEST_RESULT_Z(memContextCurrent()->name, "test-block", "context is now test-block");
|
||||
THROW(AssertError, "error in test block");
|
||||
}
|
||||
MEM_CONTEXT_END(),
|
||||
AssertError, "error in test block");
|
||||
|
||||
TEST_RESULT_Z(memContextName(memContextCurrent()), "TOP", "context is now top");
|
||||
TEST_RESULT_Z(memContextCurrent()->name, "TOP", "context is now top");
|
||||
|
||||
// Reset temp mem context after a single interaction
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
@ -333,11 +331,11 @@ testRun(void)
|
||||
{
|
||||
memContext = MEM_CONTEXT_NEW();
|
||||
TEST_RESULT_PTR(memContext, memContextCurrent(), "new mem context is current");
|
||||
TEST_RESULT_Z(memContextName(memContext), memContextTestName, "check context name");
|
||||
TEST_RESULT_Z(memContext->name, memContextTestName, "check context name");
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
||||
TEST_RESULT_Z(memContextName(memContextCurrent()), "TOP", "context name is now 'TOP'");
|
||||
TEST_RESULT_Z(memContextCurrent()->name, "TOP", "context name is now 'TOP'");
|
||||
TEST_RESULT_PTR(memContextCurrent(), memContextTop(), "context is now 'TOP'");
|
||||
TEST_RESULT_BOOL(memContext->state == memContextStateActive, true, "new mem context is still active");
|
||||
memContextFree(memContext);
|
||||
@ -352,7 +350,7 @@ testRun(void)
|
||||
MEM_CONTEXT_NEW_BEGIN(memContextTestName)
|
||||
{
|
||||
memContext = MEM_CONTEXT_NEW();
|
||||
TEST_RESULT_Z(memContextName(memContext), memContextTestName, "check mem context name");
|
||||
TEST_RESULT_Z(memContext->name, memContextTestName, "check mem context name");
|
||||
THROW(AssertError, "create failed");
|
||||
}
|
||||
MEM_CONTEXT_NEW_END();
|
||||
|
Loading…
x
Reference in New Issue
Block a user