mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-01-30 05:39:12 +02:00
Add walSegmentNext() and walSegmentRange().
This commit is contained in:
parent
be02c67503
commit
321a28f6b0
@ -90,6 +90,10 @@
|
||||
<p>Add <code>pgControlInfo()</code> to read <file>pg_control</file> and determine the <postgres/> version.</p>
|
||||
</release-item>
|
||||
|
||||
<release-item>
|
||||
<p>Add <code>walSegmentNext()</code> and <code>walSegmentRange()</code>.</p>
|
||||
</release-item>
|
||||
|
||||
<release-item>
|
||||
<p>Add <code>THROWP_</code>* macro variants for error handling. These macros allow an <code>ErrorType</code> pointer to be passed and are required for functions that may return different errors based on a parameter.</p>
|
||||
</release-item>
|
||||
|
@ -1,12 +1,16 @@
|
||||
/***********************************************************************************************************************************
|
||||
Archive Push Command
|
||||
***********************************************************************************************************************************/
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "command/archive/common.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/log.h"
|
||||
#include "common/memContext.h"
|
||||
#include "common/wait.h"
|
||||
#include "postgres/version.h"
|
||||
#include "storage/helper.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
@ -94,3 +98,82 @@ archiveAsyncStatus(const String *walSegment, bool confessOnError)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Get the next WAL segment given a WAL segment and WAL segment size
|
||||
***********************************************************************************************************************************/
|
||||
String *
|
||||
walSegmentNext(const String *walSegment, size_t walSegmentSize, uint pgVersion)
|
||||
{
|
||||
ASSERT_DEBUG(walSegment != NULL);
|
||||
ASSERT_DEBUG(strSize(walSegment) == 24);
|
||||
ASSERT_DEBUG(UINT32_MAX % walSegmentSize == walSegmentSize - 1);
|
||||
ASSERT_DEBUG(pgVersion >= PG_VERSION_11 || walSegmentSize == 16 * 1024 * 1024);
|
||||
|
||||
// Extract WAL parts
|
||||
uint32_t timeline = 0;
|
||||
uint32_t major = 0;
|
||||
uint32_t minor = 0;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
timeline = (uint32_t)strtol(strPtr(strSubN(walSegment, 0, 8)), NULL, 16);
|
||||
major = (uint32_t)strtol(strPtr(strSubN(walSegment, 8, 8)), NULL, 16);
|
||||
minor = (uint32_t)strtol(strPtr(strSubN(walSegment, 16, 8)), NULL, 16);
|
||||
|
||||
// Increment minor and adjust major dir on overflow
|
||||
minor++;
|
||||
|
||||
if (minor > UINT32_MAX / walSegmentSize)
|
||||
{
|
||||
major++;
|
||||
minor = 0;
|
||||
}
|
||||
|
||||
// Special hack for PostgreSQL < 9.3 which skipped minor FF
|
||||
if (minor == 0xFF && pgVersion < PG_VERSION_93)
|
||||
{
|
||||
major++;
|
||||
minor = 0;
|
||||
}
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return strNewFmt("%08X%08X%08X", timeline, major, minor);
|
||||
}
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Build a list of WAL segments based on a beginning WAL and number of WAL in the range (inclusive)
|
||||
***********************************************************************************************************************************/
|
||||
StringList *
|
||||
walSegmentRange(const String *walSegmentBegin, size_t walSegmentSize, uint pgVersion, uint range)
|
||||
{
|
||||
ASSERT_DEBUG(range > 0);
|
||||
|
||||
StringList *result = NULL;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
result = strLstAdd(strLstNew(), walSegmentBegin);
|
||||
|
||||
if (range > 1)
|
||||
{
|
||||
String *current = strDup(walSegmentBegin);
|
||||
|
||||
for (uint rangeIdx = 0; rangeIdx < range - 1; rangeIdx++)
|
||||
{
|
||||
String *next = walSegmentNext(current, walSegmentSize, pgVersion);
|
||||
|
||||
strLstAdd(result, next);
|
||||
|
||||
strFree(current);
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
|
||||
strLstMove(result, MEM_CONTEXT_OLD());
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -4,11 +4,15 @@ Archive Common
|
||||
#ifndef COMMAND_ARCHIVE_COMMON_H
|
||||
#define COMMAND_ARCHIVE_COMMON_H
|
||||
|
||||
#include "common/type/string.h"
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "common/type/stringList.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
***********************************************************************************************************************************/
|
||||
bool archiveAsyncStatus(const String *walSegment, bool confessOnError);
|
||||
String *walSegmentNext(const String *walSegment, size_t walSegmentSize, uint pgVersion);
|
||||
StringList *walSegmentRange(const String *walSegmentBegin, size_t walSegmentSize, uint pgVersion, uint range);
|
||||
|
||||
#endif
|
||||
|
@ -506,7 +506,7 @@ unit:
|
||||
test:
|
||||
# ----------------------------------------------------------------------------------------------------------------------------
|
||||
- name: common
|
||||
total: 1
|
||||
total: 3
|
||||
|
||||
coverage:
|
||||
command/archive/common: full
|
||||
|
@ -87,4 +87,52 @@ testRun()
|
||||
|
||||
unlink(strPtr(storagePathNP(storageSpool(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.error", strPtr(segment)))));
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("walSegmentNext()"))
|
||||
{
|
||||
TEST_RESULT_STR(
|
||||
strPtr(walSegmentNext(strNew("000000010000000100000001"), 16 * 1024 * 1024, PG_VERSION_10)),
|
||||
"000000010000000100000002", "get next");
|
||||
TEST_RESULT_STR(
|
||||
strPtr(walSegmentNext(strNew("0000000100000001000000FE"), 16 * 1024 * 1024, PG_VERSION_93)),
|
||||
"0000000100000001000000FF", "get next");
|
||||
TEST_RESULT_STR(
|
||||
strPtr(walSegmentNext(strNew("0000009900000001000000FF"), 16 * 1024 * 1024, PG_VERSION_93)),
|
||||
"000000990000000200000000", "get next overflow >= 9.3");
|
||||
TEST_RESULT_STR(
|
||||
strPtr(walSegmentNext(strNew("0000000100000001000000FE"), 16 * 1024 * 1024, PG_VERSION_92)),
|
||||
"000000010000000200000000", "get next overflow < 9.3");
|
||||
TEST_RESULT_STR(
|
||||
strPtr(walSegmentNext(strNew("000000010000000100000003"), 1024 * 1024 * 1024, PG_VERSION_11)),
|
||||
"000000010000000200000000", "get next overflow >= 11/1GB");
|
||||
TEST_RESULT_STR(
|
||||
strPtr(walSegmentNext(strNew("000000010000006700000FFF"), 1024 * 1024, PG_VERSION_11)),
|
||||
"000000010000006800000000", "get next overflow >= 11/1MB");
|
||||
}
|
||||
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("walSegmentRange()"))
|
||||
{
|
||||
TEST_RESULT_STR(
|
||||
strPtr(strLstJoin(walSegmentRange(strNew("000000010000000100000000"), 16 * 1024 * 1024, PG_VERSION_92, 1), "|")),
|
||||
"000000010000000100000000", "get single");
|
||||
TEST_RESULT_STR(
|
||||
strPtr(strLstJoin(walSegmentRange(strNew("0000000100000001000000FD"), 16 * 1024 * 1024, PG_VERSION_92, 4), "|")),
|
||||
"0000000100000001000000FD|0000000100000001000000FE|000000010000000200000000|000000010000000200000001",
|
||||
"get range < 9.3");
|
||||
TEST_RESULT_STR(
|
||||
strPtr(strLstJoin(walSegmentRange(strNew("0000000100000001000000FD"), 16 * 1024 * 1024, PG_VERSION_93, 4), "|")),
|
||||
"0000000100000001000000FD|0000000100000001000000FE|0000000100000001000000FF|000000010000000200000000",
|
||||
"get range >= 9.3");
|
||||
TEST_RESULT_STR(
|
||||
strPtr(strLstJoin(walSegmentRange(strNew("000000080000000A00000000"), 1024 * 1024 * 1024, PG_VERSION_11, 8), "|")),
|
||||
"000000080000000A00000000|000000080000000A00000001|000000080000000A00000002|000000080000000A00000003|"
|
||||
"000000080000000B00000000|000000080000000B00000001|000000080000000B00000002|000000080000000B00000003",
|
||||
"get range >= 11/1GB");
|
||||
TEST_RESULT_STR(
|
||||
strPtr(strLstJoin(walSegmentRange(strNew("000000070000000700000FFE"), 1024 * 1024, PG_VERSION_11, 4), "|")),
|
||||
"000000070000000700000FFE|000000070000000700000FFF|000000070000000800000000|000000070000000800000001",
|
||||
"get range >= 11/1MB");
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user