You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-06-18 23:57:33 +02:00
Add stack trace macros to all functions.
Low-level functions only include stack trace in test builds while higher-level functions ship with stack trace built-in. Stack traces include all parameters passed to the function but production builds only create the parameter list when the log level is set high enough, i.e. debug or trace depending on the function.
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
/***********************************************************************************************************************************
|
||||
PostgreSQL Info
|
||||
***********************************************************************************************************************************/
|
||||
#include "common/debug.h"
|
||||
#include "common/memContext.h"
|
||||
#include "postgres/info.h"
|
||||
#include "postgres/type.h"
|
||||
@ -13,6 +14,11 @@ Map control/catalog version to PostgreSQL version
|
||||
static uint
|
||||
pgVersionMap(uint32_t controlVersion, uint32_t catalogVersion)
|
||||
{
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(UINT32, controlVersion);
|
||||
FUNCTION_TEST_PARAM(UINT32, catalogVersion);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
uint result = 0;
|
||||
|
||||
if (controlVersion == 1002 && catalogVersion == 201707211)
|
||||
@ -44,7 +50,7 @@ pgVersionMap(uint32_t controlVersion, uint32_t catalogVersion)
|
||||
controlVersion, catalogVersion);
|
||||
}
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(UINT, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -53,6 +59,12 @@ Get info from pg_control
|
||||
PgControlInfo
|
||||
pgControlInfo(const String *pgPath)
|
||||
{
|
||||
FUNCTION_DEBUG_BEGIN(logLevelDebug);
|
||||
FUNCTION_DEBUG_PARAM(STRING, pgPath);
|
||||
|
||||
FUNCTION_TEST_ASSERT(pgPath != NULL);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
PgControlInfo result = {0};
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
@ -73,5 +85,5 @@ pgControlInfo(const String *pgPath)
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
FUNCTION_DEBUG_RESULT(PG_CONTROL_INFO, result);
|
||||
}
|
||||
|
@ -25,4 +25,12 @@ Functions
|
||||
***********************************************************************************************************************************/
|
||||
PgControlInfo pgControlInfo(const String *pgPath);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Macros for function logging
|
||||
***********************************************************************************************************************************/
|
||||
#define FUNCTION_DEBUG_PG_CONTROL_INFO_TYPE \
|
||||
PgControlInfo
|
||||
#define FUNCTION_DEBUG_PG_CONTROL_INFO_FORMAT(value, buffer, bufferSize) \
|
||||
objToLog(&value, "PgControlInfo", buffer, bufferSize)
|
||||
|
||||
#endif
|
||||
|
@ -65,6 +65,7 @@ minimize register spilling. For less sophisticated compilers it might be benefic
|
||||
#include <string.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/error.h"
|
||||
#include "postgres/pageChecksum.h"
|
||||
#include "postgres/type.h"
|
||||
@ -134,10 +135,15 @@ do { \
|
||||
} while (0)
|
||||
|
||||
static uint32_t
|
||||
pageChecksumBlock(const unsigned char *page, uint32_t pageSize)
|
||||
pageChecksumBlock(const unsigned char *page, unsigned int pageSize)
|
||||
{
|
||||
ASSERT_DEBUG(page != NULL);
|
||||
ASSERT_DEBUG(pageSize == PG_PAGE_SIZE);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(UCHARP, page);
|
||||
FUNCTION_TEST_PARAM(UINT, pageSize);
|
||||
|
||||
FUNCTION_TEST_ASSERT(page != NULL);
|
||||
FUNCTION_TEST_ASSERT(pageSize == PG_PAGE_SIZE);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
uint32_t sums[N_SUMS];
|
||||
uint32_t (*dataArray)[N_SUMS] = (uint32_t (*)[N_SUMS])page;
|
||||
@ -161,7 +167,7 @@ pageChecksumBlock(const unsigned char *page, uint32_t pageSize)
|
||||
for (i = 0; i < N_SUMS; i++)
|
||||
result ^= sums[i];
|
||||
|
||||
return result;
|
||||
FUNCTION_TEST_RESULT(UINT32, result);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -173,7 +179,14 @@ The checksum includes the block number (to detect the case where a page is someh
|
||||
uint16_t
|
||||
pageChecksum(const unsigned char *page, unsigned int blockNo, unsigned int pageSize)
|
||||
{
|
||||
ASSERT_DEBUG(page != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(UCHARP, page);
|
||||
FUNCTION_TEST_PARAM(UINT, blockNo);
|
||||
FUNCTION_TEST_PARAM(UINT, pageSize);
|
||||
|
||||
FUNCTION_TEST_ASSERT(page != NULL);
|
||||
FUNCTION_TEST_ASSERT(pageSize == PG_PAGE_SIZE);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
// Save pd_checksum and temporarily set it to zero, so that the checksum calculation isn't affected by the old checksum stored
|
||||
// on the page. Restore it after, because actually updating the checksum is NOT part of the API of this function.
|
||||
@ -188,7 +201,7 @@ pageChecksum(const unsigned char *page, unsigned int blockNo, unsigned int pageS
|
||||
checksum ^= blockNo;
|
||||
|
||||
// Reduce to a uint16 with an offset of one. That avoids checksums of zero, which seems like a good idea.
|
||||
return (uint16_t)((checksum % 65535) + 1);
|
||||
FUNCTION_TEST_RESULT(UINT16, (uint16_t)(checksum % 65535 + 1));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -198,15 +211,25 @@ bool
|
||||
pageChecksumTest(
|
||||
const unsigned char *page, unsigned int blockNo, unsigned int pageSize, uint32_t ignoreWalId, uint32_t ignoreWalOffset)
|
||||
{
|
||||
ASSERT_DEBUG(page != NULL);
|
||||
FUNCTION_TEST_BEGIN();
|
||||
FUNCTION_TEST_PARAM(UCHARP, page);
|
||||
FUNCTION_TEST_PARAM(UINT, blockNo);
|
||||
FUNCTION_TEST_PARAM(UINT, pageSize);
|
||||
FUNCTION_TEST_PARAM(UINT32, ignoreWalId);
|
||||
FUNCTION_TEST_PARAM(UINT32, ignoreWalOffset);
|
||||
|
||||
return
|
||||
FUNCTION_TEST_ASSERT(page != NULL);
|
||||
FUNCTION_TEST_ASSERT(pageSize == PG_PAGE_SIZE);
|
||||
FUNCTION_TEST_END();
|
||||
|
||||
FUNCTION_TEST_RESULT(
|
||||
BOOL,
|
||||
// This is a new page so don't test checksum
|
||||
((PageHeader)page)->pd_upper == 0 ||
|
||||
// LSN is after the backup started so checksum is not tested because pages may be torn
|
||||
(((PageHeader)page)->pd_lsn.walid >= ignoreWalId && ((PageHeader)page)->pd_lsn.xrecoff >= ignoreWalOffset) ||
|
||||
// Checksum is valid
|
||||
((PageHeader)page)->pd_checksum == pageChecksum(page, blockNo, pageSize);
|
||||
((PageHeader)page)->pd_checksum == pageChecksum(page, blockNo, pageSize));
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -217,13 +240,21 @@ pageChecksumBufferTest(
|
||||
const unsigned char *pageBuffer, unsigned int pageBufferSize, unsigned int blockNoBegin, unsigned int pageSize,
|
||||
uint32_t ignoreWalId, uint32_t ignoreWalOffset)
|
||||
{
|
||||
ASSERT_DEBUG(pageBuffer != NULL);
|
||||
ASSERT_DEBUG(pageBufferSize > 0);
|
||||
ASSERT_DEBUG(pageSize == PG_PAGE_SIZE);
|
||||
FUNCTION_DEBUG_BEGIN(logLevelTrace);
|
||||
FUNCTION_DEBUG_PARAM(UCHARP, pageBuffer);
|
||||
FUNCTION_DEBUG_PARAM(UINT, pageBufferSize);
|
||||
FUNCTION_DEBUG_PARAM(UINT, blockNoBegin);
|
||||
FUNCTION_DEBUG_PARAM(UINT, pageSize);
|
||||
FUNCTION_DEBUG_PARAM(UINT32, ignoreWalId);
|
||||
FUNCTION_DEBUG_PARAM(UINT32, ignoreWalOffset);
|
||||
|
||||
// If the buffer does not represent an even number of pages then error
|
||||
if (pageBufferSize % pageSize != 0)
|
||||
THROW_FMT(AssertError, "buffer size %u, page size %u are not divisible", pageBufferSize, pageSize);
|
||||
FUNCTION_TEST_ASSERT(pageBuffer != NULL);
|
||||
FUNCTION_DEBUG_ASSERT(pageBufferSize > 0);
|
||||
FUNCTION_DEBUG_ASSERT(pageSize == PG_PAGE_SIZE);
|
||||
FUNCTION_DEBUG_ASSERT(pageBufferSize % pageSize == 0);
|
||||
FUNCTION_DEBUG_END();
|
||||
|
||||
bool result = true;
|
||||
|
||||
// Loop through all pages in the buffer
|
||||
for (unsigned int pageIdx = 0; pageIdx < pageBufferSize / pageSize; pageIdx++)
|
||||
@ -232,9 +263,11 @@ pageChecksumBufferTest(
|
||||
|
||||
// Return false if the checksums do not match
|
||||
if (!pageChecksumTest(page, blockNoBegin + pageIdx, pageSize, ignoreWalId, ignoreWalOffset))
|
||||
return false;
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// All checksums match
|
||||
return true;
|
||||
FUNCTION_DEBUG_RESULT(BOOL, result);
|
||||
}
|
||||
|
Reference in New Issue
Block a user