1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-07-30 19:23:04 +03:00

Add pgLsnRangeToWalSegmentList() to convert lsn range to wal segments.

This commit is contained in:
David Steele
2019-12-12 16:43:34 -05:00
parent 81295fd388
commit 8acfb6adf4
3 changed files with 101 additions and 1 deletions

View File

@ -622,6 +622,66 @@ pgLsnToWalSegment(uint32_t timeline, uint64_t lsn, unsigned int walSegmentSize)
strNewFmt("%08X%08X%08X", timeline, (unsigned int)(lsn >> 32), (unsigned int)(lsn & 0xFFFFFFFF) / walSegmentSize));
}
/**********************************************************************************************************************************/
StringList *
pgLsnRangeToWalSegmentList(
unsigned int pgVersion, uint32_t timeline, uint64_t lsnStart, uint64_t lsnStop, unsigned int walSegmentSize)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(UINT, pgVersion);
FUNCTION_TEST_PARAM(UINT, timeline);
FUNCTION_TEST_PARAM(UINT64, lsnStart);
FUNCTION_TEST_PARAM(UINT64, lsnStop);
FUNCTION_TEST_PARAM(UINT, walSegmentSize);
FUNCTION_TEST_END();
ASSERT(pgVersion != 0);
ASSERT(timeline != 0);
ASSERT(lsnStart <= lsnStop);
ASSERT(walSegmentSize != 0);
ASSERT(pgVersion > PG_VERSION_92 || walSegmentSize == PG_WAL_SEGMENT_SIZE_DEFAULT);
StringList *result = NULL;
MEM_CONTEXT_TEMP_BEGIN()
{
result = strLstNew();
// Skip the FF segment when PostgreSQL <= 9.2 (in this case segment size should always be 16MB)
bool skipFF = pgVersion <= PG_VERSION_92;
// Calculate the start and stop segments
unsigned int startMajor = (unsigned int)(lsnStart >> 32);
unsigned int startMinor = (unsigned int)(lsnStart & 0xFFFFFFFF) / walSegmentSize;
unsigned int stopMajor = (unsigned int)(lsnStop >> 32);
unsigned int stopMinor = (unsigned int)(lsnStop & 0xFFFFFFFF) / walSegmentSize;
unsigned int minorPerMajor = 0xFFFFFFFF / walSegmentSize;
// Create list
strLstAdd(result, strNewFmt("%08X%08X%08X", timeline, startMajor, startMinor));
while (!(startMajor == stopMajor && startMinor == stopMinor))
{
startMinor++;
if ((skipFF && startMinor == 0xFF) || (!skipFF && startMinor > minorPerMajor))
{
startMajor++;
startMinor = 0;
}
strLstAdd(result, strNewFmt("%08X%08X%08X", timeline, startMajor, startMinor));
}
strLstMove(result, MEM_CONTEXT_OLD());
}
MEM_CONTEXT_TEMP_END();
FUNCTION_TEST_RETURN(result);
}
/**********************************************************************************************************************************/
const String *
pgLsnName(unsigned int pgVersion)

View File

@ -132,6 +132,10 @@ String *pgLsnToStr(uint64_t lsn);
// Convert a timeline and lsn to a wal segment
String *pgLsnToWalSegment(uint32_t timeline, uint64_t lsn, unsigned int walSegmentSize);
// Convert a timeline and lsn range to a list of wal segments
StringList *pgLsnRangeToWalSegmentList(
unsigned int pgVersion, uint32_t timeline, uint64_t lsnStart, uint64_t lsnStop, unsigned int walSegmentSize);
// Get name used for lsn in functions (this was changed in PostgreSQL 10 for consistency since lots of names were changing)
const String *pgLsnName(unsigned int pgVersion);

View File

@ -102,7 +102,7 @@ testRun(void)
}
// *****************************************************************************************************************************
if (testBegin("pgLsnFromStr(), pgLsnToStr(), and pgLsnToWalSegment()"))
if (testBegin("pgLsnFromStr(), pgLsnToStr(), pgLsnToWalSegment(), and pgLsnRangeToWalSegmentList()"))
{
TEST_RESULT_UINT(pgLsnFromStr(STRDEF("1/1")), 0x0000000100000001, "lsn to string");
TEST_RESULT_UINT(pgLsnFromStr(STRDEF("ffffffff/ffffffff")), 0xFFFFFFFFFFFFFFFF, "lsn to string");
@ -115,6 +115,42 @@ testRun(void)
TEST_RESULT_STR_Z(pgLsnToWalSegment(1, 0xFFFFFFFFAAAAAAAA, 0x1000000), "00000001FFFFFFFF000000AA", "lsn to wal segment");
TEST_RESULT_STR_Z(pgLsnToWalSegment(1, 0xFFFFFFFFAAAAAAAA, 0x40000000), "00000001FFFFFFFF00000002", "lsn to wal segment");
TEST_RESULT_STR_Z(pgLsnToWalSegment(1, 0xFFFFFFFF40000000, 0x40000000), "00000001FFFFFFFF00000001", "lsn to wal segment");
TEST_RESULT_STR_Z(
strLstJoin(
pgLsnRangeToWalSegmentList(
PG_VERSION_92, 1, pgLsnFromStr(STRDEF("1/60")), pgLsnFromStr(STRDEF("1/60")), 16 * 1024 * 1024),
", "),
"000000010000000100000000", "get single");
TEST_RESULT_STR_Z(
strLstJoin(
pgLsnRangeToWalSegmentList(
PG_VERSION_92, 2, pgLsnFromStr(STRDEF("1/FD000000")), pgLsnFromStr(STRDEF("2/1000000")), 16 * 1024 * 1024),
", "),
"0000000200000001000000FD, 0000000200000001000000FE, 000000020000000200000000, 000000020000000200000001",
"get range <= 9.2");
TEST_RESULT_STR_Z(
strLstJoin(
pgLsnRangeToWalSegmentList(
PG_VERSION_93, 2, pgLsnFromStr(STRDEF("1/FD000000")), pgLsnFromStr(STRDEF("2/60")), 16 * 1024 * 1024),
", "),
"0000000200000001000000FD, 0000000200000001000000FE, 0000000200000001000000FF, 000000020000000200000000",
"get range > 9.2");
TEST_RESULT_STR_Z(
strLstJoin(
pgLsnRangeToWalSegmentList(
PG_VERSION_11, 2, pgLsnFromStr(STRDEF("A/800")), pgLsnFromStr(STRDEF("B/C0000000")), 1024 * 1024 * 1024),
", "),
"000000020000000A00000000, 000000020000000A00000001, 000000020000000A00000002, 000000020000000A00000003"
", 000000020000000B00000000, 000000020000000B00000001, 000000020000000B00000002, 000000020000000B00000003",
"get range >= 11/1GB");
TEST_RESULT_STR_Z(
strLstJoin(
pgLsnRangeToWalSegmentList(
PG_VERSION_11, 3, pgLsnFromStr(STRDEF("7/FFEFFFFF")), pgLsnFromStr(STRDEF("8/001AAAAA")), 1024 * 1024),
", "),
"000000030000000700000FFE, 000000030000000700000FFF, 000000030000000800000000, 000000030000000800000001",
"get range >= 11/1MB");
}
// *****************************************************************************************************************************