1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-07-05 00:28:52 +02:00

Add pg-version-force option for fork integration.

Forks may update pg_control version or WAL magic without affecting the structures that pgBackRest depends on.

This option forces pgBackRest to treat a cluster as the specified version when it cannot be automatically identified.
This commit is contained in:
Stefan Fercot
2023-03-09 02:23:15 +01:00
committed by GitHub
parent 2fa7e53c5d
commit 740c2258e3
21 changed files with 438 additions and 72 deletions

View File

@ -111,7 +111,13 @@ pgInterfaceVersion(unsigned int pgVersion)
// If the version was not found then error
if (result == NULL)
THROW_FMT(AssertError, "invalid " PG_NAME " version %u", pgVersion);
{
THROW_FMT(
VersionNotSupportedError,
"invalid " PG_NAME " version %u\n"
"HINT: is this version of PostgreSQL supported?",
pgVersion);
}
FUNCTION_TEST_RETURN_TYPE_CONST_P(PgInterface, result);
}
@ -172,10 +178,11 @@ pgWalSegmentSizeCheck(unsigned int pgVersion, unsigned int walSegmentSize)
/**********************************************************************************************************************************/
static PgControl
pgControlFromBuffer(const Buffer *controlFile)
pgControlFromBuffer(const Buffer *controlFile, const String *const pgVersionForce)
{
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(BUFFER, controlFile);
FUNCTION_LOG_PARAM(STRING, pgVersionForce);
FUNCTION_LOG_END();
ASSERT(controlFile != NULL);
@ -183,28 +190,35 @@ pgControlFromBuffer(const Buffer *controlFile)
// Search for the version of PostgreSQL that uses this control file
const PgInterface *interface = NULL;
for (unsigned int interfaceIdx = 0; interfaceIdx < LENGTH_OF(pgInterface); interfaceIdx++)
if (pgVersionForce != NULL)
interface = pgInterfaceVersion(pgVersionFromStr(pgVersionForce));
else
{
if (pgInterface[interfaceIdx].controlIs(bufPtrConst(controlFile)))
for (unsigned int interfaceIdx = 0; interfaceIdx < LENGTH_OF(pgInterface); interfaceIdx++)
{
interface = &pgInterface[interfaceIdx];
break;
if (pgInterface[interfaceIdx].controlIs(bufPtrConst(controlFile)))
{
interface = &pgInterface[interfaceIdx];
break;
}
}
// If the version was not found then error with the control and catalog version that were found
if (interface == NULL)
{
const PgControlCommon *controlCommon = (const PgControlCommon *)bufPtrConst(controlFile);
THROW_FMT(
VersionNotSupportedError,
"unexpected control version = %u and catalog version = %u\n"
"HINT: is this version of PostgreSQL supported?",
controlCommon->controlVersion, controlCommon->catalogVersion);
}
}
// If the version was not found then error with the control and catalog version that were found
if (interface == NULL)
{
const PgControlCommon *controlCommon = (const PgControlCommon *)bufPtrConst(controlFile);
THROW_FMT(
VersionNotSupportedError,
"unexpected control version = %u and catalog version = %u\n"
"HINT: is this version of PostgreSQL supported?",
controlCommon->controlVersion, controlCommon->catalogVersion);
}
// Get info from the control file
ASSERT(pgVersionForce != NULL || interface->controlIs(bufPtrConst(controlFile)));
PgControl result = interface->control(bufPtrConst(controlFile));
result.version = interface->version;
@ -219,10 +233,11 @@ pgControlFromBuffer(const Buffer *controlFile)
}
FN_EXTERN PgControl
pgControlFromFile(const Storage *storage)
pgControlFromFile(const Storage *storage, const String *const pgVersionForce)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STORAGE, storage);
FUNCTION_LOG_PARAM(STRING, pgVersionForce);
FUNCTION_LOG_END();
ASSERT(storage != NULL);
@ -235,7 +250,7 @@ pgControlFromFile(const Storage *storage)
Buffer *controlFile = storageGetP(
storageNewReadP(storage, STRDEF(PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL)), .exactSize = PG_CONTROL_DATA_SIZE);
result = pgControlFromBuffer(controlFile);
result = pgControlFromBuffer(controlFile, pgVersionForce);
}
MEM_CONTEXT_TEMP_END();
@ -267,10 +282,11 @@ typedef struct PgWalCommon
/**********************************************************************************************************************************/
FN_EXTERN PgWal
pgWalFromBuffer(const Buffer *walBuffer)
pgWalFromBuffer(const Buffer *walBuffer, const String *const pgVersionForce)
{
FUNCTION_LOG_BEGIN(logLevelTrace);
FUNCTION_LOG_PARAM(BUFFER, walBuffer);
FUNCTION_LOG_PARAM(STRING, pgVersionForce);
FUNCTION_LOG_END();
ASSERT(walBuffer != NULL);
@ -282,26 +298,33 @@ pgWalFromBuffer(const Buffer *walBuffer)
// Search for the version of PostgreSQL that uses this WAL magic
const PgInterface *interface = NULL;
for (unsigned int interfaceIdx = 0; interfaceIdx < LENGTH_OF(pgInterface); interfaceIdx++)
if (pgVersionForce != NULL)
interface = pgInterfaceVersion(pgVersionFromStr(pgVersionForce));
else
{
if (pgInterface[interfaceIdx].walIs(bufPtrConst(walBuffer)))
for (unsigned int interfaceIdx = 0; interfaceIdx < LENGTH_OF(pgInterface); interfaceIdx++)
{
interface = &pgInterface[interfaceIdx];
break;
if (pgInterface[interfaceIdx].walIs(bufPtrConst(walBuffer)))
{
interface = &pgInterface[interfaceIdx];
break;
}
}
// If the version was not found then error with the magic that was found
if (interface == NULL)
{
THROW_FMT(
VersionNotSupportedError,
"unexpected WAL magic %u\n"
"HINT: is this version of PostgreSQL supported?",
((const PgWalCommon *)bufPtrConst(walBuffer))->magic);
}
}
// If the version was not found then error with the magic that was found
if (interface == NULL)
{
THROW_FMT(
VersionNotSupportedError,
"unexpected WAL magic %u\n"
"HINT: is this version of PostgreSQL supported?",
((const PgWalCommon *)bufPtrConst(walBuffer))->magic);
}
// Get info from the control file
ASSERT(pgVersionForce != NULL || interface->walIs(bufPtrConst(walBuffer)));
PgWal result = interface->wal(bufPtrConst(walBuffer));
result.version = interface->version;
@ -312,10 +335,11 @@ pgWalFromBuffer(const Buffer *walBuffer)
}
FN_EXTERN PgWal
pgWalFromFile(const String *walFile, const Storage *storage)
pgWalFromFile(const String *walFile, const Storage *storage, const String *const pgVersionForce)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STRING, walFile);
FUNCTION_LOG_PARAM(STRING, pgVersionForce);
FUNCTION_LOG_END();
ASSERT(walFile != NULL);
@ -327,7 +351,7 @@ pgWalFromFile(const String *walFile, const Storage *storage)
// Read WAL segment header
Buffer *walBuffer = storageGetP(storageNewReadP(storage, walFile), .exactSize = PG_WAL_HEADER_SIZE);
result = pgWalFromBuffer(walBuffer);
result = pgWalFromBuffer(walBuffer, pgVersionForce);
}
MEM_CONTEXT_TEMP_END();

View File

@ -130,7 +130,7 @@ FN_EXTERN bool pgDbIsSystem(const String *name);
FN_EXTERN bool pgDbIsSystemId(unsigned int id);
// Get info from pg_control
FN_EXTERN PgControl pgControlFromFile(const Storage *storage);
FN_EXTERN PgControl pgControlFromFile(const Storage *storage, const String *pgVersionForce);
// Get the control version for a PostgreSQL version
FN_EXTERN uint32_t pgControlVersion(unsigned int pgVersion);
@ -140,8 +140,8 @@ FN_EXTERN unsigned int pgVersionFromStr(const String *version);
FN_EXTERN String *pgVersionToStr(unsigned int version);
// Get info from WAL header
FN_EXTERN PgWal pgWalFromFile(const String *walFile, const Storage *storage);
FN_EXTERN PgWal pgWalFromBuffer(const Buffer *walBuffer);
FN_EXTERN PgWal pgWalFromFile(const String *walFile, const Storage *storage, const String *pgVersionForce);
FN_EXTERN PgWal pgWalFromBuffer(const Buffer *walBuffer, const String *pgVersionForce);
// Get the tablespace identifier used to distinguish versions in a tablespace directory, e.g. PG_15_202209061
FN_EXTERN String *pgTablespaceId(unsigned int pgVersion, unsigned int pgCatalogVersion);

View File

@ -61,7 +61,6 @@ Read the version specific pg_control into a general data structure
pgInterfaceControl##version(const unsigned char *controlFile) \
{ \
ASSERT(controlFile != NULL); \
ASSERT(pgInterfaceControlIs##version(controlFile)); \
\
return (PgControl) \
{ \
@ -123,7 +122,6 @@ Read the version specific WAL header into a general data structure
pgInterfaceWal##version(const unsigned char *walFile) \
{ \
ASSERT(walFile != NULL); \
ASSERT(pgInterfaceWalIs##version(walFile)); \
\
return (PgWal) \
{ \