You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-06-16 23:47:38 +02:00
Add WAL info to PostgreSQL interface.
This allows the WAL header to be read for any supported version on PostgreSQL.
This commit is contained in:
@ -57,6 +57,10 @@
|
|||||||
<p>Remove redundant documentation from <postgres/> interface files and clarify ambiguous function names.</p>
|
<p>Remove redundant documentation from <postgres/> interface files and clarify ambiguous function names.</p>
|
||||||
</release-item>
|
</release-item>
|
||||||
|
|
||||||
|
<release-item>
|
||||||
|
<p>Add WAL info to <postgres/> interface.</p>
|
||||||
|
</release-item>
|
||||||
|
|
||||||
<release-item>
|
<release-item>
|
||||||
<p>Move WAL path prefix logic into <code>walPath()</code>.</p>
|
<p>Move WAL path prefix logic into <code>walPath()</code>.</p>
|
||||||
</release-item>
|
</release-item>
|
||||||
|
@ -43,6 +43,12 @@ really old storage with 512-byte sectors. This is true across all versions of P
|
|||||||
#define PG_CONTROL_SIZE ((unsigned int)(8 * 1024))
|
#define PG_CONTROL_SIZE ((unsigned int)(8 * 1024))
|
||||||
#define PG_CONTROL_DATA_SIZE ((unsigned int)(512))
|
#define PG_CONTROL_DATA_SIZE ((unsigned int)(512))
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
WAL header size. It doesn't seem worth tracking the exact size of the WAL header across versions of PostgreSQL so just set it to
|
||||||
|
something far larger needed but <= the minimum read size on just about any system.
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
#define PG_WAL_HEADER_SIZE ((unsigned int)(512))
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
PostgreSQL interface definitions
|
PostgreSQL interface definitions
|
||||||
|
|
||||||
@ -61,9 +67,19 @@ typedef struct PgInterface
|
|||||||
// Convert pg_control to a common data structure
|
// Convert pg_control to a common data structure
|
||||||
PgControl (*control)(const Buffer *);
|
PgControl (*control)(const Buffer *);
|
||||||
|
|
||||||
|
// Does the WAL header match this version of PostgreSQL?
|
||||||
|
bool (*walIs)(const Buffer *);
|
||||||
|
|
||||||
|
// Convert WAL header to a common data structure
|
||||||
|
PgWal (*wal)(const Buffer *);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
// Create pg_control for testing
|
// Create pg_control for testing
|
||||||
void (*controlTest)(PgControl, Buffer *);
|
void (*controlTest)(PgControl, Buffer *);
|
||||||
|
|
||||||
|
// Create WAL header for testing
|
||||||
|
void (*walTest)(PgWal, Buffer *);
|
||||||
#endif
|
#endif
|
||||||
} PgInterface;
|
} PgInterface;
|
||||||
|
|
||||||
@ -75,8 +91,12 @@ static const PgInterface pgInterface[] =
|
|||||||
.controlIs = pgInterfaceControlIs110,
|
.controlIs = pgInterfaceControlIs110,
|
||||||
.control = pgInterfaceControl110,
|
.control = pgInterfaceControl110,
|
||||||
|
|
||||||
|
.walIs = pgInterfaceWalIs110,
|
||||||
|
.wal = pgInterfaceWal110,
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
.controlTest = pgInterfaceControlTest110,
|
.controlTest = pgInterfaceControlTest110,
|
||||||
|
.walTest = pgInterfaceWalTest110,
|
||||||
#endif
|
#endif
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -85,8 +105,12 @@ static const PgInterface pgInterface[] =
|
|||||||
.controlIs = pgInterfaceControlIs100,
|
.controlIs = pgInterfaceControlIs100,
|
||||||
.control = pgInterfaceControl100,
|
.control = pgInterfaceControl100,
|
||||||
|
|
||||||
|
.walIs = pgInterfaceWalIs100,
|
||||||
|
.wal = pgInterfaceWal100,
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
.controlTest = pgInterfaceControlTest100,
|
.controlTest = pgInterfaceControlTest100,
|
||||||
|
.walTest = pgInterfaceWalTest100,
|
||||||
#endif
|
#endif
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -95,8 +119,12 @@ static const PgInterface pgInterface[] =
|
|||||||
.controlIs = pgInterfaceControlIs096,
|
.controlIs = pgInterfaceControlIs096,
|
||||||
.control = pgInterfaceControl096,
|
.control = pgInterfaceControl096,
|
||||||
|
|
||||||
|
.walIs = pgInterfaceWalIs096,
|
||||||
|
.wal = pgInterfaceWal096,
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
.controlTest = pgInterfaceControlTest096,
|
.controlTest = pgInterfaceControlTest096,
|
||||||
|
.walTest = pgInterfaceWalTest096,
|
||||||
#endif
|
#endif
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -105,8 +133,12 @@ static const PgInterface pgInterface[] =
|
|||||||
.controlIs = pgInterfaceControlIs095,
|
.controlIs = pgInterfaceControlIs095,
|
||||||
.control = pgInterfaceControl095,
|
.control = pgInterfaceControl095,
|
||||||
|
|
||||||
|
.walIs = pgInterfaceWalIs095,
|
||||||
|
.wal = pgInterfaceWal095,
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
.controlTest = pgInterfaceControlTest095,
|
.controlTest = pgInterfaceControlTest095,
|
||||||
|
.walTest = pgInterfaceWalTest095,
|
||||||
#endif
|
#endif
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -115,8 +147,12 @@ static const PgInterface pgInterface[] =
|
|||||||
.controlIs = pgInterfaceControlIs094,
|
.controlIs = pgInterfaceControlIs094,
|
||||||
.control = pgInterfaceControl094,
|
.control = pgInterfaceControl094,
|
||||||
|
|
||||||
|
.walIs = pgInterfaceWalIs094,
|
||||||
|
.wal = pgInterfaceWal094,
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
.controlTest = pgInterfaceControlTest094,
|
.controlTest = pgInterfaceControlTest094,
|
||||||
|
.walTest = pgInterfaceWalTest094,
|
||||||
#endif
|
#endif
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -125,8 +161,12 @@ static const PgInterface pgInterface[] =
|
|||||||
.controlIs = pgInterfaceControlIs093,
|
.controlIs = pgInterfaceControlIs093,
|
||||||
.control = pgInterfaceControl093,
|
.control = pgInterfaceControl093,
|
||||||
|
|
||||||
|
.walIs = pgInterfaceWalIs093,
|
||||||
|
.wal = pgInterfaceWal093,
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
.controlTest = pgInterfaceControlTest093,
|
.controlTest = pgInterfaceControlTest093,
|
||||||
|
.walTest = pgInterfaceWalTest093,
|
||||||
#endif
|
#endif
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -135,8 +175,12 @@ static const PgInterface pgInterface[] =
|
|||||||
.controlIs = pgInterfaceControlIs092,
|
.controlIs = pgInterfaceControlIs092,
|
||||||
.control = pgInterfaceControl092,
|
.control = pgInterfaceControl092,
|
||||||
|
|
||||||
|
.walIs = pgInterfaceWalIs092,
|
||||||
|
.wal = pgInterfaceWal092,
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
.controlTest = pgInterfaceControlTest092,
|
.controlTest = pgInterfaceControlTest092,
|
||||||
|
.walTest = pgInterfaceWalTest092,
|
||||||
#endif
|
#endif
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -145,8 +189,12 @@ static const PgInterface pgInterface[] =
|
|||||||
.controlIs = pgInterfaceControlIs091,
|
.controlIs = pgInterfaceControlIs091,
|
||||||
.control = pgInterfaceControl091,
|
.control = pgInterfaceControl091,
|
||||||
|
|
||||||
|
.walIs = pgInterfaceWalIs091,
|
||||||
|
.wal = pgInterfaceWal091,
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
.controlTest = pgInterfaceControlTest091,
|
.controlTest = pgInterfaceControlTest091,
|
||||||
|
.walTest = pgInterfaceWalTest091,
|
||||||
#endif
|
#endif
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -155,8 +203,12 @@ static const PgInterface pgInterface[] =
|
|||||||
.controlIs = pgInterfaceControlIs090,
|
.controlIs = pgInterfaceControlIs090,
|
||||||
.control = pgInterfaceControl090,
|
.control = pgInterfaceControl090,
|
||||||
|
|
||||||
|
.walIs = pgInterfaceWalIs090,
|
||||||
|
.wal = pgInterfaceWal090,
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
.controlTest = pgInterfaceControlTest090,
|
.controlTest = pgInterfaceControlTest090,
|
||||||
|
.walTest = pgInterfaceWalTest090,
|
||||||
#endif
|
#endif
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -165,8 +217,12 @@ static const PgInterface pgInterface[] =
|
|||||||
.controlIs = pgInterfaceControlIs084,
|
.controlIs = pgInterfaceControlIs084,
|
||||||
.control = pgInterfaceControl084,
|
.control = pgInterfaceControl084,
|
||||||
|
|
||||||
|
.walIs = pgInterfaceWalIs084,
|
||||||
|
.wal = pgInterfaceWal084,
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
.controlTest = pgInterfaceControlTest084,
|
.controlTest = pgInterfaceControlTest084,
|
||||||
|
.walTest = pgInterfaceWalTest084,
|
||||||
#endif
|
#endif
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -175,8 +231,12 @@ static const PgInterface pgInterface[] =
|
|||||||
.controlIs = pgInterfaceControlIs083,
|
.controlIs = pgInterfaceControlIs083,
|
||||||
.control = pgInterfaceControl083,
|
.control = pgInterfaceControl083,
|
||||||
|
|
||||||
|
.walIs = pgInterfaceWalIs083,
|
||||||
|
.wal = pgInterfaceWal083,
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
.controlTest = pgInterfaceControlTest083,
|
.controlTest = pgInterfaceControlTest083,
|
||||||
|
.walTest = pgInterfaceWalTest083,
|
||||||
#endif
|
#endif
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -275,6 +335,89 @@ pgControlFromFile(const String *pgPath)
|
|||||||
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
These WAL header fields are common to all versions of PostgreSQL, so we can use them to generate error messages when the WAL magic
|
||||||
|
cannot be found.
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
typedef struct PgWalCommon
|
||||||
|
{
|
||||||
|
uint16_t magic;
|
||||||
|
uint16_t flag;
|
||||||
|
} PgWalCommon;
|
||||||
|
|
||||||
|
#define PG_WAL_LONG_HEADER 0x0002
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Get info from WAL header
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
PgWal
|
||||||
|
pgWalFromBuffer(const Buffer *walBuffer)
|
||||||
|
{
|
||||||
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
||||||
|
FUNCTION_LOG_PARAM(BUFFER, walBuffer);
|
||||||
|
FUNCTION_LOG_END();
|
||||||
|
|
||||||
|
ASSERT(walBuffer != NULL);
|
||||||
|
|
||||||
|
// Check that this is a long format WAL header
|
||||||
|
if (!(((PgWalCommon *)bufPtr(walBuffer))->flag & PG_WAL_LONG_HEADER))
|
||||||
|
THROW_FMT(FormatError, "first page header in WAL file is expected to be in long format");
|
||||||
|
|
||||||
|
// Search for the version of PostgreSQL that uses this WAL magic
|
||||||
|
const PgInterface *interface = NULL;
|
||||||
|
|
||||||
|
for (unsigned int interfaceIdx = 0; interfaceIdx < sizeof(pgInterface) / sizeof(PgInterface); interfaceIdx++)
|
||||||
|
{
|
||||||
|
if (pgInterface[interfaceIdx].walIs(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?",
|
||||||
|
((PgWalCommon *)bufPtr(walBuffer))->magic);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get info from the control file
|
||||||
|
PgWal result = interface->wal(walBuffer);
|
||||||
|
result.version = interface->version;
|
||||||
|
|
||||||
|
FUNCTION_LOG_RETURN(PG_WAL, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Get info from a WAL segment
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
PgWal
|
||||||
|
pgWalFromFile(const String *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_LOG_BEGIN(logLevelDebug);
|
||||||
|
FUNCTION_LOG_PARAM(STRING, walFile);
|
||||||
|
FUNCTION_LOG_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
|
||||||
|
PgWal result = {0};
|
||||||
|
|
||||||
|
MEM_CONTEXT_TEMP_BEGIN()
|
||||||
|
{
|
||||||
|
// Read WAL segment header
|
||||||
|
Buffer *walBuffer = storageGetP(storageNewReadNP(storageLocal(), walFile), .exactSize = PG_WAL_HEADER_SIZE);
|
||||||
|
|
||||||
|
result = pgWalFromBuffer(walBuffer);
|
||||||
|
}
|
||||||
|
MEM_CONTEXT_TEMP_END();
|
||||||
|
|
||||||
|
FUNCTION_LOG_RETURN(PG_WAL, result);
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Create pg_control for testing
|
Create pg_control for testing
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
@ -318,6 +461,38 @@ pgControlTestToBuffer(PgControl pgControl)
|
|||||||
FUNCTION_TEST_RETURN(result);
|
FUNCTION_TEST_RETURN(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pgWalTestToBuffer(PgWal pgWal, Buffer *walBuffer)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(PG_WAL, pgWal);
|
||||||
|
FUNCTION_TEST_PARAM(BUFFER, walBuffer);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
ASSERT(walBuffer != NULL);
|
||||||
|
|
||||||
|
// Find the interface for the version of PostgreSQL
|
||||||
|
const PgInterface *interface = NULL;
|
||||||
|
|
||||||
|
for (unsigned int interfaceIdx = 0; interfaceIdx < sizeof(pgInterface) / sizeof(PgInterface); interfaceIdx++)
|
||||||
|
{
|
||||||
|
if (pgInterface[interfaceIdx].version == pgWal.version)
|
||||||
|
{
|
||||||
|
interface = &pgInterface[interfaceIdx];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the version was not found then error
|
||||||
|
if (interface == NULL)
|
||||||
|
THROW_FMT(AssertError, "invalid version %u", pgWal.version);
|
||||||
|
|
||||||
|
// Generate pg_control
|
||||||
|
interface->walTest(pgWal, walBuffer);
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
@ -387,3 +562,9 @@ pgControlToLog(const PgControl *pgControl)
|
|||||||
"{version: %u, systemId: %" PRIu64 ", walSegmentSize: %u, pageChecksum: %s}", pgControl->version, pgControl->systemId,
|
"{version: %u, systemId: %" PRIu64 ", walSegmentSize: %u, pageChecksum: %s}", pgControl->version, pgControl->systemId,
|
||||||
pgControl->walSegmentSize, cvtBoolToConstZ(pgControl->pageChecksum));
|
pgControl->walSegmentSize, cvtBoolToConstZ(pgControl->pageChecksum));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String *
|
||||||
|
pgWalToLog(const PgWal *pgWal)
|
||||||
|
{
|
||||||
|
return strNewFmt("{version: %u, systemId: %" PRIu64 "}", pgWal->version, pgWal->systemId);
|
||||||
|
}
|
||||||
|
@ -33,6 +33,15 @@ typedef struct PgControl
|
|||||||
bool pageChecksum;
|
bool pageChecksum;
|
||||||
} PgControl;
|
} PgControl;
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
PostgreSQL WAL Info
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
typedef struct PgWal
|
||||||
|
{
|
||||||
|
unsigned int version;
|
||||||
|
uint64_t systemId;
|
||||||
|
} PgWal;
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Functions
|
Functions
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
@ -41,21 +50,31 @@ PgControl pgControlFromBuffer(const Buffer *controlFile);
|
|||||||
unsigned int pgVersionFromStr(const String *version);
|
unsigned int pgVersionFromStr(const String *version);
|
||||||
String *pgVersionToStr(unsigned int version);
|
String *pgVersionToStr(unsigned int version);
|
||||||
|
|
||||||
|
PgWal pgWalFromFile(const String *walFile);
|
||||||
|
PgWal pgWalFromBuffer(const Buffer *walBuffer);
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Test Functions
|
Test Functions
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
Buffer *pgControlTestToBuffer(PgControl pgControl);
|
Buffer *pgControlTestToBuffer(PgControl pgControl);
|
||||||
|
void pgWalTestToBuffer(PgWal pgWal, Buffer *walBuffer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Macros for function logging
|
Macros for function logging
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
String *pgControlToLog(const PgControl *pgControl);
|
String *pgControlToLog(const PgControl *pgControl);
|
||||||
|
String *pgWalToLog(const PgWal *pgWal);
|
||||||
|
|
||||||
#define FUNCTION_LOG_PG_CONTROL_TYPE \
|
#define FUNCTION_LOG_PG_CONTROL_TYPE \
|
||||||
PgControl
|
PgControl
|
||||||
#define FUNCTION_LOG_PG_CONTROL_FORMAT(value, buffer, bufferSize) \
|
#define FUNCTION_LOG_PG_CONTROL_FORMAT(value, buffer, bufferSize) \
|
||||||
FUNCTION_LOG_STRING_OBJECT_FORMAT(&value, pgControlToLog, buffer, bufferSize)
|
FUNCTION_LOG_STRING_OBJECT_FORMAT(&value, pgControlToLog, buffer, bufferSize)
|
||||||
|
|
||||||
|
#define FUNCTION_LOG_PG_WAL_TYPE \
|
||||||
|
PgWal
|
||||||
|
#define FUNCTION_LOG_PG_WAL_FORMAT(value, buffer, bufferSize) \
|
||||||
|
FUNCTION_LOG_STRING_OBJECT_FORMAT(&value, pgWalToLog, buffer, bufferSize)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,6 +6,7 @@ PostgreSQL 8.3 Types
|
|||||||
Types from src/include/c.h
|
Types from src/include/c.h
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
typedef int64_t int64;
|
typedef int64_t int64;
|
||||||
|
typedef uint16_t uint16;
|
||||||
typedef uint32_t uint32;
|
typedef uint32_t uint32;
|
||||||
typedef uint64_t uint64;
|
typedef uint64_t uint64;
|
||||||
|
|
||||||
@ -201,3 +202,35 @@ typedef struct ControlFileData
|
|||||||
/* CRC of all above ... MUST BE LAST! */
|
/* CRC of all above ... MUST BE LAST! */
|
||||||
pg_crc32 crc;
|
pg_crc32 crc;
|
||||||
} ControlFileData;
|
} ControlFileData;
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Types from src/include/access/xlog_internal.h
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
* Each page of XLOG file has a header like this:
|
||||||
|
*/
|
||||||
|
#define XLOG_PAGE_MAGIC 0xD062 /* can be used as WAL version indicator */
|
||||||
|
|
||||||
|
typedef struct XLogPageHeaderData
|
||||||
|
{
|
||||||
|
uint16 xlp_magic; /* magic value for correctness checks */
|
||||||
|
uint16 xlp_info; /* flag bits, see below */
|
||||||
|
TimeLineID xlp_tli; /* TimeLineID of first record on page */
|
||||||
|
XLogRecPtr xlp_pageaddr; /* XLOG address of this page */
|
||||||
|
} XLogPageHeaderData;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When the XLP_LONG_HEADER flag is set, we store additional fields in the
|
||||||
|
* page header. (This is ordinarily done just in the first page of an
|
||||||
|
* XLOG file.) The additional fields serve to identify the file accurately.
|
||||||
|
*/
|
||||||
|
typedef struct XLogLongPageHeaderData
|
||||||
|
{
|
||||||
|
XLogPageHeaderData std; /* standard header fields */
|
||||||
|
uint64 xlp_sysid; /* system identifier from pg_control */
|
||||||
|
uint32 xlp_seg_size; /* just as a cross-check */
|
||||||
|
uint32 xlp_xlog_blcksz; /* just as a cross-check */
|
||||||
|
} XLogLongPageHeaderData;
|
||||||
|
|
||||||
|
/* This flag indicates a "long" page header */
|
||||||
|
#define XLP_LONG_HEADER 0x0002
|
||||||
|
@ -49,6 +49,37 @@ pgInterfaceControl083(const Buffer *controlFile)
|
|||||||
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
bool
|
||||||
|
pgInterfaceWalIs083(const Buffer *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(BUFFER, controlFile);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN(((XLogPageHeaderData *)bufPtr(walFile))->xlp_magic == XLOG_PAGE_MAGIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
PgWal
|
||||||
|
pgInterfaceWal083(const Buffer *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
||||||
|
FUNCTION_LOG_PARAM(BUFFER, walFile);
|
||||||
|
FUNCTION_LOG_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
ASSERT(pgInterfaceWalIs083(walFile));
|
||||||
|
|
||||||
|
PgWal result = {0};
|
||||||
|
|
||||||
|
result.systemId = ((XLogLongPageHeaderData *)bufPtr(walFile))->xlp_sysid;
|
||||||
|
|
||||||
|
FUNCTION_LOG_RETURN(PG_WAL, result);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
/**********************************************************************************************************************************/
|
/**********************************************************************************************************************************/
|
||||||
@ -71,4 +102,20 @@ pgInterfaceControlTest083(PgControl pgControl, Buffer *buffer)
|
|||||||
FUNCTION_TEST_RETURN_VOID();
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
void
|
||||||
|
pgInterfaceWalTest083(PgWal pgWal, Buffer *buffer)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(PG_WAL, pgWal);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
XLogLongPageHeaderData *walData = (XLogLongPageHeaderData *)bufPtr(buffer);
|
||||||
|
|
||||||
|
walData->std.xlp_magic = XLOG_PAGE_MAGIC;
|
||||||
|
walData->xlp_sysid = pgWal.systemId;
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,12 +11,15 @@ Functions
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
bool pgInterfaceControlIs083(const Buffer *controlFile);
|
bool pgInterfaceControlIs083(const Buffer *controlFile);
|
||||||
PgControl pgInterfaceControl083(const Buffer *controlFile);
|
PgControl pgInterfaceControl083(const Buffer *controlFile);
|
||||||
|
bool pgInterfaceWalIs083(const Buffer *walFile);
|
||||||
|
PgWal pgInterfaceWal083(const Buffer *controlFile);
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Test Functions
|
Test Functions
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void pgInterfaceControlTest083(PgControl pgControl, Buffer *buffer);
|
void pgInterfaceControlTest083(PgControl pgControl, Buffer *buffer);
|
||||||
|
void pgInterfaceWalTest083(PgWal pgWal, Buffer *buffer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,6 +6,7 @@ PostgreSQL 8.4 Types
|
|||||||
Types from src/include/c.h
|
Types from src/include/c.h
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
typedef int64_t int64;
|
typedef int64_t int64;
|
||||||
|
typedef uint16_t uint16;
|
||||||
typedef uint32_t uint32;
|
typedef uint32_t uint32;
|
||||||
typedef uint64_t uint64;
|
typedef uint64_t uint64;
|
||||||
|
|
||||||
@ -206,3 +207,35 @@ typedef struct ControlFileData
|
|||||||
/* CRC of all above ... MUST BE LAST! */
|
/* CRC of all above ... MUST BE LAST! */
|
||||||
pg_crc32 crc;
|
pg_crc32 crc;
|
||||||
} ControlFileData;
|
} ControlFileData;
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Types from src/include/access/xlog_internal.h
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
* Each page of XLOG file has a header like this:
|
||||||
|
*/
|
||||||
|
#define XLOG_PAGE_MAGIC 0xD063 /* can be used as WAL version indicator */
|
||||||
|
|
||||||
|
typedef struct XLogPageHeaderData
|
||||||
|
{
|
||||||
|
uint16 xlp_magic; /* magic value for correctness checks */
|
||||||
|
uint16 xlp_info; /* flag bits, see below */
|
||||||
|
TimeLineID xlp_tli; /* TimeLineID of first record on page */
|
||||||
|
XLogRecPtr xlp_pageaddr; /* XLOG address of this page */
|
||||||
|
} XLogPageHeaderData;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When the XLP_LONG_HEADER flag is set, we store additional fields in the
|
||||||
|
* page header. (This is ordinarily done just in the first page of an
|
||||||
|
* XLOG file.) The additional fields serve to identify the file accurately.
|
||||||
|
*/
|
||||||
|
typedef struct XLogLongPageHeaderData
|
||||||
|
{
|
||||||
|
XLogPageHeaderData std; /* standard header fields */
|
||||||
|
uint64 xlp_sysid; /* system identifier from pg_control */
|
||||||
|
uint32 xlp_seg_size; /* just as a cross-check */
|
||||||
|
uint32 xlp_xlog_blcksz; /* just as a cross-check */
|
||||||
|
} XLogLongPageHeaderData;
|
||||||
|
|
||||||
|
/* This flag indicates a "long" page header */
|
||||||
|
#define XLP_LONG_HEADER 0x0002
|
||||||
|
@ -49,6 +49,37 @@ pgInterfaceControl084(const Buffer *controlFile)
|
|||||||
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
bool
|
||||||
|
pgInterfaceWalIs084(const Buffer *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(BUFFER, controlFile);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN(((XLogPageHeaderData *)bufPtr(walFile))->xlp_magic == XLOG_PAGE_MAGIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
PgWal
|
||||||
|
pgInterfaceWal084(const Buffer *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
||||||
|
FUNCTION_LOG_PARAM(BUFFER, walFile);
|
||||||
|
FUNCTION_LOG_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
ASSERT(pgInterfaceWalIs084(walFile));
|
||||||
|
|
||||||
|
PgWal result = {0};
|
||||||
|
|
||||||
|
result.systemId = ((XLogLongPageHeaderData *)bufPtr(walFile))->xlp_sysid;
|
||||||
|
|
||||||
|
FUNCTION_LOG_RETURN(PG_WAL, result);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
/**********************************************************************************************************************************/
|
/**********************************************************************************************************************************/
|
||||||
@ -71,4 +102,20 @@ pgInterfaceControlTest084(PgControl pgControl, Buffer *buffer)
|
|||||||
FUNCTION_TEST_RETURN_VOID();
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
void
|
||||||
|
pgInterfaceWalTest084(PgWal pgWal, Buffer *buffer)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(PG_WAL, pgWal);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
XLogLongPageHeaderData *walData = (XLogLongPageHeaderData *)bufPtr(buffer);
|
||||||
|
|
||||||
|
walData->std.xlp_magic = XLOG_PAGE_MAGIC;
|
||||||
|
walData->xlp_sysid = pgWal.systemId;
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,12 +11,15 @@ Functions
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
bool pgInterfaceControlIs084(const Buffer *controlFile);
|
bool pgInterfaceControlIs084(const Buffer *controlFile);
|
||||||
PgControl pgInterfaceControl084(const Buffer *controlFile);
|
PgControl pgInterfaceControl084(const Buffer *controlFile);
|
||||||
|
bool pgInterfaceWalIs084(const Buffer *walFile);
|
||||||
|
PgWal pgInterfaceWal084(const Buffer *controlFile);
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Test Functions
|
Test Functions
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void pgInterfaceControlTest084(PgControl pgControl, Buffer *buffer);
|
void pgInterfaceControlTest084(PgControl pgControl, Buffer *buffer);
|
||||||
|
void pgInterfaceWalTest084(PgWal pgWal, Buffer *buffer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,6 +6,7 @@ PostgreSQL 9.0 Types
|
|||||||
Types from src/include/c.h
|
Types from src/include/c.h
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
typedef int64_t int64;
|
typedef int64_t int64;
|
||||||
|
typedef uint16_t uint16;
|
||||||
typedef uint32_t uint32;
|
typedef uint32_t uint32;
|
||||||
typedef uint64_t uint64;
|
typedef uint64_t uint64;
|
||||||
|
|
||||||
@ -250,3 +251,35 @@ typedef struct ControlFileData
|
|||||||
/* CRC of all above ... MUST BE LAST! */
|
/* CRC of all above ... MUST BE LAST! */
|
||||||
pg_crc32 crc;
|
pg_crc32 crc;
|
||||||
} ControlFileData;
|
} ControlFileData;
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Types from src/include/access/xlog_internal.h
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
* Each page of XLOG file has a header like this:
|
||||||
|
*/
|
||||||
|
#define XLOG_PAGE_MAGIC 0xD064 /* can be used as WAL version indicator */
|
||||||
|
|
||||||
|
typedef struct XLogPageHeaderData
|
||||||
|
{
|
||||||
|
uint16 xlp_magic; /* magic value for correctness checks */
|
||||||
|
uint16 xlp_info; /* flag bits, see below */
|
||||||
|
TimeLineID xlp_tli; /* TimeLineID of first record on page */
|
||||||
|
XLogRecPtr xlp_pageaddr; /* XLOG address of this page */
|
||||||
|
} XLogPageHeaderData;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When the XLP_LONG_HEADER flag is set, we store additional fields in the
|
||||||
|
* page header. (This is ordinarily done just in the first page of an
|
||||||
|
* XLOG file.) The additional fields serve to identify the file accurately.
|
||||||
|
*/
|
||||||
|
typedef struct XLogLongPageHeaderData
|
||||||
|
{
|
||||||
|
XLogPageHeaderData std; /* standard header fields */
|
||||||
|
uint64 xlp_sysid; /* system identifier from pg_control */
|
||||||
|
uint32 xlp_seg_size; /* just as a cross-check */
|
||||||
|
uint32 xlp_xlog_blcksz; /* just as a cross-check */
|
||||||
|
} XLogLongPageHeaderData;
|
||||||
|
|
||||||
|
/* This flag indicates a "long" page header */
|
||||||
|
#define XLP_LONG_HEADER 0x0002
|
||||||
|
@ -49,6 +49,37 @@ pgInterfaceControl090(const Buffer *controlFile)
|
|||||||
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
bool
|
||||||
|
pgInterfaceWalIs090(const Buffer *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(BUFFER, controlFile);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN(((XLogPageHeaderData *)bufPtr(walFile))->xlp_magic == XLOG_PAGE_MAGIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
PgWal
|
||||||
|
pgInterfaceWal090(const Buffer *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
||||||
|
FUNCTION_LOG_PARAM(BUFFER, walFile);
|
||||||
|
FUNCTION_LOG_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
ASSERT(pgInterfaceWalIs090(walFile));
|
||||||
|
|
||||||
|
PgWal result = {0};
|
||||||
|
|
||||||
|
result.systemId = ((XLogLongPageHeaderData *)bufPtr(walFile))->xlp_sysid;
|
||||||
|
|
||||||
|
FUNCTION_LOG_RETURN(PG_WAL, result);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
/**********************************************************************************************************************************/
|
/**********************************************************************************************************************************/
|
||||||
@ -71,4 +102,20 @@ pgInterfaceControlTest090(PgControl pgControl, Buffer *buffer)
|
|||||||
FUNCTION_TEST_RETURN_VOID();
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
void
|
||||||
|
pgInterfaceWalTest090(PgWal pgWal, Buffer *buffer)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(PG_WAL, pgWal);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
XLogLongPageHeaderData *walData = (XLogLongPageHeaderData *)bufPtr(buffer);
|
||||||
|
|
||||||
|
walData->std.xlp_magic = XLOG_PAGE_MAGIC;
|
||||||
|
walData->xlp_sysid = pgWal.systemId;
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,12 +11,15 @@ Functions
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
bool pgInterfaceControlIs090(const Buffer *controlFile);
|
bool pgInterfaceControlIs090(const Buffer *controlFile);
|
||||||
PgControl pgInterfaceControl090(const Buffer *controlFile);
|
PgControl pgInterfaceControl090(const Buffer *controlFile);
|
||||||
|
bool pgInterfaceWalIs090(const Buffer *walFile);
|
||||||
|
PgWal pgInterfaceWal090(const Buffer *controlFile);
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Test Functions
|
Test Functions
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void pgInterfaceControlTest090(PgControl pgControl, Buffer *buffer);
|
void pgInterfaceControlTest090(PgControl pgControl, Buffer *buffer);
|
||||||
|
void pgInterfaceWalTest090(PgWal pgWal, Buffer *buffer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,6 +6,7 @@ PostgreSQL 9.1 Types
|
|||||||
Types from src/include/c.h
|
Types from src/include/c.h
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
typedef int64_t int64;
|
typedef int64_t int64;
|
||||||
|
typedef uint16_t uint16;
|
||||||
typedef uint32_t uint32;
|
typedef uint32_t uint32;
|
||||||
typedef uint64_t uint64;
|
typedef uint64_t uint64;
|
||||||
|
|
||||||
@ -250,3 +251,35 @@ typedef struct ControlFileData
|
|||||||
/* CRC of all above ... MUST BE LAST! */
|
/* CRC of all above ... MUST BE LAST! */
|
||||||
pg_crc32 crc;
|
pg_crc32 crc;
|
||||||
} ControlFileData;
|
} ControlFileData;
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Types from src/include/access/xlog_internal.h
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
* Each page of XLOG file has a header like this:
|
||||||
|
*/
|
||||||
|
#define XLOG_PAGE_MAGIC 0xD066 /* can be used as WAL version indicator */
|
||||||
|
|
||||||
|
typedef struct XLogPageHeaderData
|
||||||
|
{
|
||||||
|
uint16 xlp_magic; /* magic value for correctness checks */
|
||||||
|
uint16 xlp_info; /* flag bits, see below */
|
||||||
|
TimeLineID xlp_tli; /* TimeLineID of first record on page */
|
||||||
|
XLogRecPtr xlp_pageaddr; /* XLOG address of this page */
|
||||||
|
} XLogPageHeaderData;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When the XLP_LONG_HEADER flag is set, we store additional fields in the
|
||||||
|
* page header. (This is ordinarily done just in the first page of an
|
||||||
|
* XLOG file.) The additional fields serve to identify the file accurately.
|
||||||
|
*/
|
||||||
|
typedef struct XLogLongPageHeaderData
|
||||||
|
{
|
||||||
|
XLogPageHeaderData std; /* standard header fields */
|
||||||
|
uint64 xlp_sysid; /* system identifier from pg_control */
|
||||||
|
uint32 xlp_seg_size; /* just as a cross-check */
|
||||||
|
uint32 xlp_xlog_blcksz; /* just as a cross-check */
|
||||||
|
} XLogLongPageHeaderData;
|
||||||
|
|
||||||
|
/* This flag indicates a "long" page header */
|
||||||
|
#define XLP_LONG_HEADER 0x0002
|
||||||
|
@ -49,6 +49,37 @@ pgInterfaceControl091(const Buffer *controlFile)
|
|||||||
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
bool
|
||||||
|
pgInterfaceWalIs091(const Buffer *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(BUFFER, controlFile);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN(((XLogPageHeaderData *)bufPtr(walFile))->xlp_magic == XLOG_PAGE_MAGIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
PgWal
|
||||||
|
pgInterfaceWal091(const Buffer *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
||||||
|
FUNCTION_LOG_PARAM(BUFFER, walFile);
|
||||||
|
FUNCTION_LOG_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
ASSERT(pgInterfaceWalIs091(walFile));
|
||||||
|
|
||||||
|
PgWal result = {0};
|
||||||
|
|
||||||
|
result.systemId = ((XLogLongPageHeaderData *)bufPtr(walFile))->xlp_sysid;
|
||||||
|
|
||||||
|
FUNCTION_LOG_RETURN(PG_WAL, result);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
/**********************************************************************************************************************************/
|
/**********************************************************************************************************************************/
|
||||||
@ -71,4 +102,20 @@ pgInterfaceControlTest091(PgControl pgControl, Buffer *buffer)
|
|||||||
FUNCTION_TEST_RETURN_VOID();
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
void
|
||||||
|
pgInterfaceWalTest091(PgWal pgWal, Buffer *buffer)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(PG_WAL, pgWal);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
XLogLongPageHeaderData *walData = (XLogLongPageHeaderData *)bufPtr(buffer);
|
||||||
|
|
||||||
|
walData->std.xlp_magic = XLOG_PAGE_MAGIC;
|
||||||
|
walData->xlp_sysid = pgWal.systemId;
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,12 +11,15 @@ Functions
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
bool pgInterfaceControlIs091(const Buffer *controlFile);
|
bool pgInterfaceControlIs091(const Buffer *controlFile);
|
||||||
PgControl pgInterfaceControl091(const Buffer *controlFile);
|
PgControl pgInterfaceControl091(const Buffer *controlFile);
|
||||||
|
bool pgInterfaceWalIs091(const Buffer *walFile);
|
||||||
|
PgWal pgInterfaceWal091(const Buffer *controlFile);
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Test Functions
|
Test Functions
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void pgInterfaceControlTest091(PgControl pgControl, Buffer *buffer);
|
void pgInterfaceControlTest091(PgControl pgControl, Buffer *buffer);
|
||||||
|
void pgInterfaceWalTest091(PgWal pgWal, Buffer *buffer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,6 +6,7 @@ PostgreSQL 9.2 Types
|
|||||||
Types from src/include/c.h
|
Types from src/include/c.h
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
typedef int64_t int64;
|
typedef int64_t int64;
|
||||||
|
typedef uint16_t uint16;
|
||||||
typedef uint32_t uint32;
|
typedef uint32_t uint32;
|
||||||
typedef uint64_t uint64;
|
typedef uint64_t uint64;
|
||||||
|
|
||||||
@ -265,3 +266,35 @@ typedef struct ControlFileData
|
|||||||
/* CRC of all above ... MUST BE LAST! */
|
/* CRC of all above ... MUST BE LAST! */
|
||||||
pg_crc32 crc;
|
pg_crc32 crc;
|
||||||
} ControlFileData;
|
} ControlFileData;
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Types from src/include/access/xlog_internal.h
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
* Each page of XLOG file has a header like this:
|
||||||
|
*/
|
||||||
|
#define XLOG_PAGE_MAGIC 0xD071 /* can be used as WAL version indicator */
|
||||||
|
|
||||||
|
typedef struct XLogPageHeaderData
|
||||||
|
{
|
||||||
|
uint16 xlp_magic; /* magic value for correctness checks */
|
||||||
|
uint16 xlp_info; /* flag bits, see below */
|
||||||
|
TimeLineID xlp_tli; /* TimeLineID of first record on page */
|
||||||
|
XLogRecPtr xlp_pageaddr; /* XLOG address of this page */
|
||||||
|
} XLogPageHeaderData;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When the XLP_LONG_HEADER flag is set, we store additional fields in the
|
||||||
|
* page header. (This is ordinarily done just in the first page of an
|
||||||
|
* XLOG file.) The additional fields serve to identify the file accurately.
|
||||||
|
*/
|
||||||
|
typedef struct XLogLongPageHeaderData
|
||||||
|
{
|
||||||
|
XLogPageHeaderData std; /* standard header fields */
|
||||||
|
uint64 xlp_sysid; /* system identifier from pg_control */
|
||||||
|
uint32 xlp_seg_size; /* just as a cross-check */
|
||||||
|
uint32 xlp_xlog_blcksz; /* just as a cross-check */
|
||||||
|
} XLogLongPageHeaderData;
|
||||||
|
|
||||||
|
/* This flag indicates a "long" page header */
|
||||||
|
#define XLP_LONG_HEADER 0x0002
|
||||||
|
@ -49,6 +49,37 @@ pgInterfaceControl092(const Buffer *controlFile)
|
|||||||
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
bool
|
||||||
|
pgInterfaceWalIs092(const Buffer *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(BUFFER, controlFile);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN(((XLogPageHeaderData *)bufPtr(walFile))->xlp_magic == XLOG_PAGE_MAGIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
PgWal
|
||||||
|
pgInterfaceWal092(const Buffer *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
||||||
|
FUNCTION_LOG_PARAM(BUFFER, walFile);
|
||||||
|
FUNCTION_LOG_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
ASSERT(pgInterfaceWalIs092(walFile));
|
||||||
|
|
||||||
|
PgWal result = {0};
|
||||||
|
|
||||||
|
result.systemId = ((XLogLongPageHeaderData *)bufPtr(walFile))->xlp_sysid;
|
||||||
|
|
||||||
|
FUNCTION_LOG_RETURN(PG_WAL, result);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
/**********************************************************************************************************************************/
|
/**********************************************************************************************************************************/
|
||||||
@ -71,4 +102,20 @@ pgInterfaceControlTest092(PgControl pgControl, Buffer *buffer)
|
|||||||
FUNCTION_TEST_RETURN_VOID();
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
void
|
||||||
|
pgInterfaceWalTest092(PgWal pgWal, Buffer *buffer)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(PG_WAL, pgWal);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
XLogLongPageHeaderData *walData = (XLogLongPageHeaderData *)bufPtr(buffer);
|
||||||
|
|
||||||
|
walData->std.xlp_magic = XLOG_PAGE_MAGIC;
|
||||||
|
walData->xlp_sysid = pgWal.systemId;
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,12 +11,15 @@ Functions
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
bool pgInterfaceControlIs092(const Buffer *controlFile);
|
bool pgInterfaceControlIs092(const Buffer *controlFile);
|
||||||
PgControl pgInterfaceControl092(const Buffer *controlFile);
|
PgControl pgInterfaceControl092(const Buffer *controlFile);
|
||||||
|
bool pgInterfaceWalIs092(const Buffer *walFile);
|
||||||
|
PgWal pgInterfaceWal092(const Buffer *controlFile);
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Test Functions
|
Test Functions
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void pgInterfaceControlTest092(PgControl pgControl, Buffer *buffer);
|
void pgInterfaceControlTest092(PgControl pgControl, Buffer *buffer);
|
||||||
|
void pgInterfaceWalTest092(PgWal pgWal, Buffer *buffer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,6 +6,7 @@ PostgreSQL 9.3 Types
|
|||||||
Types from src/include/c.h
|
Types from src/include/c.h
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
typedef int64_t int64;
|
typedef int64_t int64;
|
||||||
|
typedef uint16_t uint16;
|
||||||
typedef uint32_t uint32;
|
typedef uint32_t uint32;
|
||||||
typedef uint64_t uint64;
|
typedef uint64_t uint64;
|
||||||
|
|
||||||
@ -260,3 +261,46 @@ typedef struct ControlFileData
|
|||||||
/* CRC of all above ... MUST BE LAST! */
|
/* CRC of all above ... MUST BE LAST! */
|
||||||
pg_crc32 crc;
|
pg_crc32 crc;
|
||||||
} ControlFileData;
|
} ControlFileData;
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Types from src/include/access/xlog_internal.h
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
* Each page of XLOG file has a header like this:
|
||||||
|
*/
|
||||||
|
#define XLOG_PAGE_MAGIC 0xD075 /* can be used as WAL version indicator */
|
||||||
|
|
||||||
|
typedef struct XLogPageHeaderData
|
||||||
|
{
|
||||||
|
uint16 xlp_magic; /* magic value for correctness checks */
|
||||||
|
uint16 xlp_info; /* flag bits, see below */
|
||||||
|
TimeLineID xlp_tli; /* TimeLineID of first record on page */
|
||||||
|
XLogRecPtr xlp_pageaddr; /* XLOG address of this page */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When there is not enough space on current page for whole record, we
|
||||||
|
* continue on the next page. xlp_rem_len is the number of bytes
|
||||||
|
* remaining from a previous page.
|
||||||
|
*
|
||||||
|
* Note that xl_rem_len includes backup-block data; that is, it tracks
|
||||||
|
* xl_tot_len not xl_len in the initial header. Also note that the
|
||||||
|
* continuation data isn't necessarily aligned.
|
||||||
|
*/
|
||||||
|
uint32 xlp_rem_len; /* total len of remaining data for record */
|
||||||
|
} XLogPageHeaderData;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When the XLP_LONG_HEADER flag is set, we store additional fields in the
|
||||||
|
* page header. (This is ordinarily done just in the first page of an
|
||||||
|
* XLOG file.) The additional fields serve to identify the file accurately.
|
||||||
|
*/
|
||||||
|
typedef struct XLogLongPageHeaderData
|
||||||
|
{
|
||||||
|
XLogPageHeaderData std; /* standard header fields */
|
||||||
|
uint64 xlp_sysid; /* system identifier from pg_control */
|
||||||
|
uint32 xlp_seg_size; /* just as a cross-check */
|
||||||
|
uint32 xlp_xlog_blcksz; /* just as a cross-check */
|
||||||
|
} XLogLongPageHeaderData;
|
||||||
|
|
||||||
|
/* This flag indicates a "long" page header */
|
||||||
|
#define XLP_LONG_HEADER 0x0002
|
||||||
|
@ -51,6 +51,37 @@ pgInterfaceControl093(const Buffer *controlFile)
|
|||||||
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
bool
|
||||||
|
pgInterfaceWalIs093(const Buffer *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(BUFFER, controlFile);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN(((XLogPageHeaderData *)bufPtr(walFile))->xlp_magic == XLOG_PAGE_MAGIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
PgWal
|
||||||
|
pgInterfaceWal093(const Buffer *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
||||||
|
FUNCTION_LOG_PARAM(BUFFER, walFile);
|
||||||
|
FUNCTION_LOG_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
ASSERT(pgInterfaceWalIs093(walFile));
|
||||||
|
|
||||||
|
PgWal result = {0};
|
||||||
|
|
||||||
|
result.systemId = ((XLogLongPageHeaderData *)bufPtr(walFile))->xlp_sysid;
|
||||||
|
|
||||||
|
FUNCTION_LOG_RETURN(PG_WAL, result);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
/**********************************************************************************************************************************/
|
/**********************************************************************************************************************************/
|
||||||
@ -75,4 +106,20 @@ pgInterfaceControlTest093(PgControl pgControl, Buffer *buffer)
|
|||||||
FUNCTION_TEST_RETURN_VOID();
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
void
|
||||||
|
pgInterfaceWalTest093(PgWal pgWal, Buffer *buffer)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(PG_WAL, pgWal);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
XLogLongPageHeaderData *walData = (XLogLongPageHeaderData *)bufPtr(buffer);
|
||||||
|
|
||||||
|
walData->std.xlp_magic = XLOG_PAGE_MAGIC;
|
||||||
|
walData->xlp_sysid = pgWal.systemId;
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,12 +11,15 @@ Functions
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
bool pgInterfaceControlIs093(const Buffer *controlFile);
|
bool pgInterfaceControlIs093(const Buffer *controlFile);
|
||||||
PgControl pgInterfaceControl093(const Buffer *controlFile);
|
PgControl pgInterfaceControl093(const Buffer *controlFile);
|
||||||
|
bool pgInterfaceWalIs093(const Buffer *walFile);
|
||||||
|
PgWal pgInterfaceWal093(const Buffer *controlFile);
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Test Functions
|
Test Functions
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void pgInterfaceControlTest093(PgControl pgControl, Buffer *buffer);
|
void pgInterfaceControlTest093(PgControl pgControl, Buffer *buffer);
|
||||||
|
void pgInterfaceWalTest093(PgWal pgWal, Buffer *buffer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,6 +6,7 @@ PostgreSQL 9.4 Types
|
|||||||
Types from src/include/c.h
|
Types from src/include/c.h
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
typedef int64_t int64;
|
typedef int64_t int64;
|
||||||
|
typedef uint16_t uint16;
|
||||||
typedef uint32_t uint32;
|
typedef uint32_t uint32;
|
||||||
typedef uint64_t uint64;
|
typedef uint64_t uint64;
|
||||||
|
|
||||||
@ -263,3 +264,46 @@ typedef struct ControlFileData
|
|||||||
/* CRC of all above ... MUST BE LAST! */
|
/* CRC of all above ... MUST BE LAST! */
|
||||||
pg_crc32 crc;
|
pg_crc32 crc;
|
||||||
} ControlFileData;
|
} ControlFileData;
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Types from src/include/access/xlog_internal.h
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
* Each page of XLOG file has a header like this:
|
||||||
|
*/
|
||||||
|
#define XLOG_PAGE_MAGIC 0xD07E /* can be used as WAL version indicator */
|
||||||
|
|
||||||
|
typedef struct XLogPageHeaderData
|
||||||
|
{
|
||||||
|
uint16 xlp_magic; /* magic value for correctness checks */
|
||||||
|
uint16 xlp_info; /* flag bits, see below */
|
||||||
|
TimeLineID xlp_tli; /* TimeLineID of first record on page */
|
||||||
|
XLogRecPtr xlp_pageaddr; /* XLOG address of this page */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When there is not enough space on current page for whole record, we
|
||||||
|
* continue on the next page. xlp_rem_len is the number of bytes
|
||||||
|
* remaining from a previous page.
|
||||||
|
*
|
||||||
|
* Note that xl_rem_len includes backup-block data; that is, it tracks
|
||||||
|
* xl_tot_len not xl_len in the initial header. Also note that the
|
||||||
|
* continuation data isn't necessarily aligned.
|
||||||
|
*/
|
||||||
|
uint32 xlp_rem_len; /* total len of remaining data for record */
|
||||||
|
} XLogPageHeaderData;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When the XLP_LONG_HEADER flag is set, we store additional fields in the
|
||||||
|
* page header. (This is ordinarily done just in the first page of an
|
||||||
|
* XLOG file.) The additional fields serve to identify the file accurately.
|
||||||
|
*/
|
||||||
|
typedef struct XLogLongPageHeaderData
|
||||||
|
{
|
||||||
|
XLogPageHeaderData std; /* standard header fields */
|
||||||
|
uint64 xlp_sysid; /* system identifier from pg_control */
|
||||||
|
uint32 xlp_seg_size; /* just as a cross-check */
|
||||||
|
uint32 xlp_xlog_blcksz; /* just as a cross-check */
|
||||||
|
} XLogLongPageHeaderData;
|
||||||
|
|
||||||
|
/* This flag indicates a "long" page header */
|
||||||
|
#define XLP_LONG_HEADER 0x0002
|
||||||
|
@ -51,6 +51,37 @@ pgInterfaceControl094(const Buffer *controlFile)
|
|||||||
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
bool
|
||||||
|
pgInterfaceWalIs094(const Buffer *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(BUFFER, controlFile);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN(((XLogPageHeaderData *)bufPtr(walFile))->xlp_magic == XLOG_PAGE_MAGIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
PgWal
|
||||||
|
pgInterfaceWal094(const Buffer *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
||||||
|
FUNCTION_LOG_PARAM(BUFFER, walFile);
|
||||||
|
FUNCTION_LOG_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
ASSERT(pgInterfaceWalIs094(walFile));
|
||||||
|
|
||||||
|
PgWal result = {0};
|
||||||
|
|
||||||
|
result.systemId = ((XLogLongPageHeaderData *)bufPtr(walFile))->xlp_sysid;
|
||||||
|
|
||||||
|
FUNCTION_LOG_RETURN(PG_WAL, result);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
/**********************************************************************************************************************************/
|
/**********************************************************************************************************************************/
|
||||||
@ -75,4 +106,20 @@ pgInterfaceControlTest094(PgControl pgControl, Buffer *buffer)
|
|||||||
FUNCTION_TEST_RETURN_VOID();
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
void
|
||||||
|
pgInterfaceWalTest094(PgWal pgWal, Buffer *buffer)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(PG_WAL, pgWal);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
XLogLongPageHeaderData *walData = (XLogLongPageHeaderData *)bufPtr(buffer);
|
||||||
|
|
||||||
|
walData->std.xlp_magic = XLOG_PAGE_MAGIC;
|
||||||
|
walData->xlp_sysid = pgWal.systemId;
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,12 +11,15 @@ Functions
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
bool pgInterfaceControlIs094(const Buffer *controlFile);
|
bool pgInterfaceControlIs094(const Buffer *controlFile);
|
||||||
PgControl pgInterfaceControl094(const Buffer *controlFile);
|
PgControl pgInterfaceControl094(const Buffer *controlFile);
|
||||||
|
bool pgInterfaceWalIs094(const Buffer *walFile);
|
||||||
|
PgWal pgInterfaceWal094(const Buffer *controlFile);
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Test Functions
|
Test Functions
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void pgInterfaceControlTest094(PgControl pgControl, Buffer *buffer);
|
void pgInterfaceControlTest094(PgControl pgControl, Buffer *buffer);
|
||||||
|
void pgInterfaceWalTest094(PgWal pgWal, Buffer *buffer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,6 +6,7 @@ PostgreSQL 9.5 Types
|
|||||||
Types from src/include/c.h
|
Types from src/include/c.h
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
typedef int64_t int64;
|
typedef int64_t int64;
|
||||||
|
typedef uint16_t uint16;
|
||||||
typedef uint32_t uint32;
|
typedef uint32_t uint32;
|
||||||
typedef uint64_t uint64;
|
typedef uint64_t uint64;
|
||||||
|
|
||||||
@ -268,3 +269,46 @@ typedef struct ControlFileData
|
|||||||
/* CRC of all above ... MUST BE LAST! */
|
/* CRC of all above ... MUST BE LAST! */
|
||||||
pg_crc32c crc;
|
pg_crc32c crc;
|
||||||
} ControlFileData;
|
} ControlFileData;
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Types from src/include/access/xlog_internal.h
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
* Each page of XLOG file has a header like this:
|
||||||
|
*/
|
||||||
|
#define XLOG_PAGE_MAGIC 0xD087 /* can be used as WAL version indicator */
|
||||||
|
|
||||||
|
typedef struct XLogPageHeaderData
|
||||||
|
{
|
||||||
|
uint16 xlp_magic; /* magic value for correctness checks */
|
||||||
|
uint16 xlp_info; /* flag bits, see below */
|
||||||
|
TimeLineID xlp_tli; /* TimeLineID of first record on page */
|
||||||
|
XLogRecPtr xlp_pageaddr; /* XLOG address of this page */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When there is not enough space on current page for whole record, we
|
||||||
|
* continue on the next page. xlp_rem_len is the number of bytes
|
||||||
|
* remaining from a previous page.
|
||||||
|
*
|
||||||
|
* Note that xl_rem_len includes backup-block data; that is, it tracks
|
||||||
|
* xl_tot_len not xl_len in the initial header. Also note that the
|
||||||
|
* continuation data isn't necessarily aligned.
|
||||||
|
*/
|
||||||
|
uint32 xlp_rem_len; /* total len of remaining data for record */
|
||||||
|
} XLogPageHeaderData;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When the XLP_LONG_HEADER flag is set, we store additional fields in the
|
||||||
|
* page header. (This is ordinarily done just in the first page of an
|
||||||
|
* XLOG file.) The additional fields serve to identify the file accurately.
|
||||||
|
*/
|
||||||
|
typedef struct XLogLongPageHeaderData
|
||||||
|
{
|
||||||
|
XLogPageHeaderData std; /* standard header fields */
|
||||||
|
uint64 xlp_sysid; /* system identifier from pg_control */
|
||||||
|
uint32 xlp_seg_size; /* just as a cross-check */
|
||||||
|
uint32 xlp_xlog_blcksz; /* just as a cross-check */
|
||||||
|
} XLogLongPageHeaderData;
|
||||||
|
|
||||||
|
/* This flag indicates a "long" page header */
|
||||||
|
#define XLP_LONG_HEADER 0x0002
|
||||||
|
@ -51,6 +51,37 @@ pgInterfaceControl095(const Buffer *controlFile)
|
|||||||
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
bool
|
||||||
|
pgInterfaceWalIs095(const Buffer *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(BUFFER, controlFile);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN(((XLogPageHeaderData *)bufPtr(walFile))->xlp_magic == XLOG_PAGE_MAGIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
PgWal
|
||||||
|
pgInterfaceWal095(const Buffer *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
||||||
|
FUNCTION_LOG_PARAM(BUFFER, walFile);
|
||||||
|
FUNCTION_LOG_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
ASSERT(pgInterfaceWalIs095(walFile));
|
||||||
|
|
||||||
|
PgWal result = {0};
|
||||||
|
|
||||||
|
result.systemId = ((XLogLongPageHeaderData *)bufPtr(walFile))->xlp_sysid;
|
||||||
|
|
||||||
|
FUNCTION_LOG_RETURN(PG_WAL, result);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
/**********************************************************************************************************************************/
|
/**********************************************************************************************************************************/
|
||||||
@ -75,4 +106,20 @@ pgInterfaceControlTest095(PgControl pgControl, Buffer *buffer)
|
|||||||
FUNCTION_TEST_RETURN_VOID();
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
void
|
||||||
|
pgInterfaceWalTest095(PgWal pgWal, Buffer *buffer)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(PG_WAL, pgWal);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
XLogLongPageHeaderData *walData = (XLogLongPageHeaderData *)bufPtr(buffer);
|
||||||
|
|
||||||
|
walData->std.xlp_magic = XLOG_PAGE_MAGIC;
|
||||||
|
walData->xlp_sysid = pgWal.systemId;
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,12 +11,15 @@ Functions
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
bool pgInterfaceControlIs095(const Buffer *controlFile);
|
bool pgInterfaceControlIs095(const Buffer *controlFile);
|
||||||
PgControl pgInterfaceControl095(const Buffer *controlFile);
|
PgControl pgInterfaceControl095(const Buffer *controlFile);
|
||||||
|
bool pgInterfaceWalIs095(const Buffer *walFile);
|
||||||
|
PgWal pgInterfaceWal095(const Buffer *controlFile);
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Test Functions
|
Test Functions
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void pgInterfaceControlTest095(PgControl pgControl, Buffer *buffer);
|
void pgInterfaceControlTest095(PgControl pgControl, Buffer *buffer);
|
||||||
|
void pgInterfaceWalTest095(PgWal pgWal, Buffer *buffer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,6 +6,7 @@ PostgreSQL 9.6 Types
|
|||||||
Types from src/include/c.h
|
Types from src/include/c.h
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
typedef int64_t int64;
|
typedef int64_t int64;
|
||||||
|
typedef uint16_t uint16;
|
||||||
typedef uint32_t uint32;
|
typedef uint32_t uint32;
|
||||||
typedef uint64_t uint64;
|
typedef uint64_t uint64;
|
||||||
|
|
||||||
@ -268,3 +269,46 @@ typedef struct ControlFileData
|
|||||||
/* CRC of all above ... MUST BE LAST! */
|
/* CRC of all above ... MUST BE LAST! */
|
||||||
pg_crc32c crc;
|
pg_crc32c crc;
|
||||||
} ControlFileData;
|
} ControlFileData;
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Types from src/include/access/xlog_internal.h
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
* Each page of XLOG file has a header like this:
|
||||||
|
*/
|
||||||
|
#define XLOG_PAGE_MAGIC 0xD093 /* can be used as WAL version indicator */
|
||||||
|
|
||||||
|
typedef struct XLogPageHeaderData
|
||||||
|
{
|
||||||
|
uint16 xlp_magic; /* magic value for correctness checks */
|
||||||
|
uint16 xlp_info; /* flag bits, see below */
|
||||||
|
TimeLineID xlp_tli; /* TimeLineID of first record on page */
|
||||||
|
XLogRecPtr xlp_pageaddr; /* XLOG address of this page */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When there is not enough space on current page for whole record, we
|
||||||
|
* continue on the next page. xlp_rem_len is the number of bytes
|
||||||
|
* remaining from a previous page.
|
||||||
|
*
|
||||||
|
* Note that xl_rem_len includes backup-block data; that is, it tracks
|
||||||
|
* xl_tot_len not xl_len in the initial header. Also note that the
|
||||||
|
* continuation data isn't necessarily aligned.
|
||||||
|
*/
|
||||||
|
uint32 xlp_rem_len; /* total len of remaining data for record */
|
||||||
|
} XLogPageHeaderData;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When the XLP_LONG_HEADER flag is set, we store additional fields in the
|
||||||
|
* page header. (This is ordinarily done just in the first page of an
|
||||||
|
* XLOG file.) The additional fields serve to identify the file accurately.
|
||||||
|
*/
|
||||||
|
typedef struct XLogLongPageHeaderData
|
||||||
|
{
|
||||||
|
XLogPageHeaderData std; /* standard header fields */
|
||||||
|
uint64 xlp_sysid; /* system identifier from pg_control */
|
||||||
|
uint32 xlp_seg_size; /* just as a cross-check */
|
||||||
|
uint32 xlp_xlog_blcksz; /* just as a cross-check */
|
||||||
|
} XLogLongPageHeaderData;
|
||||||
|
|
||||||
|
/* This flag indicates a "long" page header */
|
||||||
|
#define XLP_LONG_HEADER 0x0002
|
||||||
|
@ -51,6 +51,37 @@ pgInterfaceControl096(const Buffer *controlFile)
|
|||||||
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
bool
|
||||||
|
pgInterfaceWalIs096(const Buffer *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(BUFFER, controlFile);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN(((XLogPageHeaderData *)bufPtr(walFile))->xlp_magic == XLOG_PAGE_MAGIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
PgWal
|
||||||
|
pgInterfaceWal096(const Buffer *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
||||||
|
FUNCTION_LOG_PARAM(BUFFER, walFile);
|
||||||
|
FUNCTION_LOG_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
ASSERT(pgInterfaceWalIs096(walFile));
|
||||||
|
|
||||||
|
PgWal result = {0};
|
||||||
|
|
||||||
|
result.systemId = ((XLogLongPageHeaderData *)bufPtr(walFile))->xlp_sysid;
|
||||||
|
|
||||||
|
FUNCTION_LOG_RETURN(PG_WAL, result);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
/**********************************************************************************************************************************/
|
/**********************************************************************************************************************************/
|
||||||
@ -75,4 +106,20 @@ pgInterfaceControlTest096(PgControl pgControl, Buffer *buffer)
|
|||||||
FUNCTION_TEST_RETURN_VOID();
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
void
|
||||||
|
pgInterfaceWalTest096(PgWal pgWal, Buffer *buffer)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(PG_WAL, pgWal);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
XLogLongPageHeaderData *walData = (XLogLongPageHeaderData *)bufPtr(buffer);
|
||||||
|
|
||||||
|
walData->std.xlp_magic = XLOG_PAGE_MAGIC;
|
||||||
|
walData->xlp_sysid = pgWal.systemId;
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,12 +11,15 @@ Functions
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
bool pgInterfaceControlIs096(const Buffer *controlFile);
|
bool pgInterfaceControlIs096(const Buffer *controlFile);
|
||||||
PgControl pgInterfaceControl096(const Buffer *controlFile);
|
PgControl pgInterfaceControl096(const Buffer *controlFile);
|
||||||
|
bool pgInterfaceWalIs096(const Buffer *walFile);
|
||||||
|
PgWal pgInterfaceWal096(const Buffer *controlFile);
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Test Functions
|
Test Functions
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void pgInterfaceControlTest096(PgControl pgControl, Buffer *buffer);
|
void pgInterfaceControlTest096(PgControl pgControl, Buffer *buffer);
|
||||||
|
void pgInterfaceWalTest096(PgWal pgWal, Buffer *buffer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,6 +6,7 @@ PostgreSQL 10 Types
|
|||||||
Types from src/include/c.h
|
Types from src/include/c.h
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
typedef int64_t int64;
|
typedef int64_t int64;
|
||||||
|
typedef uint16_t uint16;
|
||||||
typedef uint32_t uint32;
|
typedef uint32_t uint32;
|
||||||
typedef uint64_t uint64;
|
typedef uint64_t uint64;
|
||||||
|
|
||||||
@ -271,3 +272,46 @@ typedef struct ControlFileData
|
|||||||
/* CRC of all above ... MUST BE LAST! */
|
/* CRC of all above ... MUST BE LAST! */
|
||||||
pg_crc32c crc;
|
pg_crc32c crc;
|
||||||
} ControlFileData;
|
} ControlFileData;
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Types from src/include/access/xlog_internal.h
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
* Each page of XLOG file has a header like this:
|
||||||
|
*/
|
||||||
|
#define XLOG_PAGE_MAGIC 0xD097 /* can be used as WAL version indicator */
|
||||||
|
|
||||||
|
typedef struct XLogPageHeaderData
|
||||||
|
{
|
||||||
|
uint16 xlp_magic; /* magic value for correctness checks */
|
||||||
|
uint16 xlp_info; /* flag bits, see below */
|
||||||
|
TimeLineID xlp_tli; /* TimeLineID of first record on page */
|
||||||
|
XLogRecPtr xlp_pageaddr; /* XLOG address of this page */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When there is not enough space on current page for whole record, we
|
||||||
|
* continue on the next page. xlp_rem_len is the number of bytes
|
||||||
|
* remaining from a previous page.
|
||||||
|
*
|
||||||
|
* Note that xl_rem_len includes backup-block data; that is, it tracks
|
||||||
|
* xl_tot_len not xl_len in the initial header. Also note that the
|
||||||
|
* continuation data isn't necessarily aligned.
|
||||||
|
*/
|
||||||
|
uint32 xlp_rem_len; /* total len of remaining data for record */
|
||||||
|
} XLogPageHeaderData;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When the XLP_LONG_HEADER flag is set, we store additional fields in the
|
||||||
|
* page header. (This is ordinarily done just in the first page of an
|
||||||
|
* XLOG file.) The additional fields serve to identify the file accurately.
|
||||||
|
*/
|
||||||
|
typedef struct XLogLongPageHeaderData
|
||||||
|
{
|
||||||
|
XLogPageHeaderData std; /* standard header fields */
|
||||||
|
uint64 xlp_sysid; /* system identifier from pg_control */
|
||||||
|
uint32 xlp_seg_size; /* just as a cross-check */
|
||||||
|
uint32 xlp_xlog_blcksz; /* just as a cross-check */
|
||||||
|
} XLogLongPageHeaderData;
|
||||||
|
|
||||||
|
/* This flag indicates a "long" page header */
|
||||||
|
#define XLP_LONG_HEADER 0x0002
|
||||||
|
@ -51,6 +51,37 @@ pgInterfaceControl100(const Buffer *controlFile)
|
|||||||
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
bool
|
||||||
|
pgInterfaceWalIs100(const Buffer *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(BUFFER, controlFile);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN(((XLogPageHeaderData *)bufPtr(walFile))->xlp_magic == XLOG_PAGE_MAGIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
PgWal
|
||||||
|
pgInterfaceWal100(const Buffer *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
||||||
|
FUNCTION_LOG_PARAM(BUFFER, walFile);
|
||||||
|
FUNCTION_LOG_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
ASSERT(pgInterfaceWalIs100(walFile));
|
||||||
|
|
||||||
|
PgWal result = {0};
|
||||||
|
|
||||||
|
result.systemId = ((XLogLongPageHeaderData *)bufPtr(walFile))->xlp_sysid;
|
||||||
|
|
||||||
|
FUNCTION_LOG_RETURN(PG_WAL, result);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
/**********************************************************************************************************************************/
|
/**********************************************************************************************************************************/
|
||||||
@ -75,4 +106,20 @@ pgInterfaceControlTest100(PgControl pgControl, Buffer *buffer)
|
|||||||
FUNCTION_TEST_RETURN_VOID();
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
void
|
||||||
|
pgInterfaceWalTest100(PgWal pgWal, Buffer *buffer)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(PG_WAL, pgWal);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
XLogLongPageHeaderData *walData = (XLogLongPageHeaderData *)bufPtr(buffer);
|
||||||
|
|
||||||
|
walData->std.xlp_magic = XLOG_PAGE_MAGIC;
|
||||||
|
walData->xlp_sysid = pgWal.systemId;
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,12 +11,15 @@ Functions
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
bool pgInterfaceControlIs100(const Buffer *controlFile);
|
bool pgInterfaceControlIs100(const Buffer *controlFile);
|
||||||
PgControl pgInterfaceControl100(const Buffer *controlFile);
|
PgControl pgInterfaceControl100(const Buffer *controlFile);
|
||||||
|
bool pgInterfaceWalIs100(const Buffer *walFile);
|
||||||
|
PgWal pgInterfaceWal100(const Buffer *controlFile);
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Test Functions
|
Test Functions
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void pgInterfaceControlTest100(PgControl pgControl, Buffer *buffer);
|
void pgInterfaceControlTest100(PgControl pgControl, Buffer *buffer);
|
||||||
|
void pgInterfaceWalTest100(PgWal pgWal, Buffer *buffer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -6,6 +6,7 @@ PostgreSQL 11 Types
|
|||||||
Types from src/include/c.h
|
Types from src/include/c.h
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
typedef int64_t int64;
|
typedef int64_t int64;
|
||||||
|
typedef uint16_t uint16;
|
||||||
typedef uint32_t uint32;
|
typedef uint32_t uint32;
|
||||||
typedef uint64_t uint64;
|
typedef uint64_t uint64;
|
||||||
|
|
||||||
@ -270,3 +271,46 @@ typedef struct ControlFileData
|
|||||||
/* CRC of all above ... MUST BE LAST! */
|
/* CRC of all above ... MUST BE LAST! */
|
||||||
pg_crc32c crc;
|
pg_crc32c crc;
|
||||||
} ControlFileData;
|
} ControlFileData;
|
||||||
|
|
||||||
|
/***********************************************************************************************************************************
|
||||||
|
Types from src/include/access/xlog_internal.h
|
||||||
|
***********************************************************************************************************************************/
|
||||||
|
/*
|
||||||
|
* Each page of XLOG file has a header like this:
|
||||||
|
*/
|
||||||
|
#define XLOG_PAGE_MAGIC 0xD098 /* can be used as WAL version indicator */
|
||||||
|
|
||||||
|
typedef struct XLogPageHeaderData
|
||||||
|
{
|
||||||
|
uint16 xlp_magic; /* magic value for correctness checks */
|
||||||
|
uint16 xlp_info; /* flag bits, see below */
|
||||||
|
TimeLineID xlp_tli; /* TimeLineID of first record on page */
|
||||||
|
XLogRecPtr xlp_pageaddr; /* XLOG address of this page */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When there is not enough space on current page for whole record, we
|
||||||
|
* continue on the next page. xlp_rem_len is the number of bytes
|
||||||
|
* remaining from a previous page.
|
||||||
|
*
|
||||||
|
* Note that xl_rem_len includes backup-block data; that is, it tracks
|
||||||
|
* xl_tot_len not xl_len in the initial header. Also note that the
|
||||||
|
* continuation data isn't necessarily aligned.
|
||||||
|
*/
|
||||||
|
uint32 xlp_rem_len; /* total len of remaining data for record */
|
||||||
|
} XLogPageHeaderData;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When the XLP_LONG_HEADER flag is set, we store additional fields in the
|
||||||
|
* page header. (This is ordinarily done just in the first page of an
|
||||||
|
* XLOG file.) The additional fields serve to identify the file accurately.
|
||||||
|
*/
|
||||||
|
typedef struct XLogLongPageHeaderData
|
||||||
|
{
|
||||||
|
XLogPageHeaderData std; /* standard header fields */
|
||||||
|
uint64 xlp_sysid; /* system identifier from pg_control */
|
||||||
|
uint32 xlp_seg_size; /* just as a cross-check */
|
||||||
|
uint32 xlp_xlog_blcksz; /* just as a cross-check */
|
||||||
|
} XLogLongPageHeaderData;
|
||||||
|
|
||||||
|
/* This flag indicates a "long" page header */
|
||||||
|
#define XLP_LONG_HEADER 0x0002
|
||||||
|
@ -51,6 +51,37 @@ pgInterfaceControl110(const Buffer *controlFile)
|
|||||||
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
FUNCTION_LOG_RETURN(PG_CONTROL, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
bool
|
||||||
|
pgInterfaceWalIs110(const Buffer *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(BUFFER, controlFile);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN(((XLogPageHeaderData *)bufPtr(walFile))->xlp_magic == XLOG_PAGE_MAGIC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
PgWal
|
||||||
|
pgInterfaceWal110(const Buffer *walFile)
|
||||||
|
{
|
||||||
|
FUNCTION_LOG_BEGIN(logLevelTrace);
|
||||||
|
FUNCTION_LOG_PARAM(BUFFER, walFile);
|
||||||
|
FUNCTION_LOG_END();
|
||||||
|
|
||||||
|
ASSERT(walFile != NULL);
|
||||||
|
ASSERT(pgInterfaceWalIs110(walFile));
|
||||||
|
|
||||||
|
PgWal result = {0};
|
||||||
|
|
||||||
|
result.systemId = ((XLogLongPageHeaderData *)bufPtr(walFile))->xlp_sysid;
|
||||||
|
|
||||||
|
FUNCTION_LOG_RETURN(PG_WAL, result);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
||||||
/**********************************************************************************************************************************/
|
/**********************************************************************************************************************************/
|
||||||
@ -75,4 +106,20 @@ pgInterfaceControlTest110(PgControl pgControl, Buffer *buffer)
|
|||||||
FUNCTION_TEST_RETURN_VOID();
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************************************************************************/
|
||||||
|
void
|
||||||
|
pgInterfaceWalTest110(PgWal pgWal, Buffer *buffer)
|
||||||
|
{
|
||||||
|
FUNCTION_TEST_BEGIN();
|
||||||
|
FUNCTION_TEST_PARAM(PG_WAL, pgWal);
|
||||||
|
FUNCTION_TEST_END();
|
||||||
|
|
||||||
|
XLogLongPageHeaderData *walData = (XLogLongPageHeaderData *)bufPtr(buffer);
|
||||||
|
|
||||||
|
walData->std.xlp_magic = XLOG_PAGE_MAGIC;
|
||||||
|
walData->xlp_sysid = pgWal.systemId;
|
||||||
|
|
||||||
|
FUNCTION_TEST_RETURN_VOID();
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -11,12 +11,15 @@ Functions
|
|||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
bool pgInterfaceControlIs110(const Buffer *controlFile);
|
bool pgInterfaceControlIs110(const Buffer *controlFile);
|
||||||
PgControl pgInterfaceControl110(const Buffer *controlFile);
|
PgControl pgInterfaceControl110(const Buffer *controlFile);
|
||||||
|
bool pgInterfaceWalIs110(const Buffer *walFile);
|
||||||
|
PgWal pgInterfaceWal110(const Buffer *controlFile);
|
||||||
|
|
||||||
/***********************************************************************************************************************************
|
/***********************************************************************************************************************************
|
||||||
Test Functions
|
Test Functions
|
||||||
***********************************************************************************************************************************/
|
***********************************************************************************************************************************/
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
void pgInterfaceControlTest110(PgControl pgControl, Buffer *buffer);
|
void pgInterfaceControlTest110(PgControl pgControl, Buffer *buffer);
|
||||||
|
void pgInterfaceWalTest110(PgWal pgWal, Buffer *buffer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -330,7 +330,7 @@ unit:
|
|||||||
test:
|
test:
|
||||||
# ----------------------------------------------------------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------------------------------------------------------
|
||||||
- name: interface
|
- name: interface
|
||||||
total: 3
|
total: 5
|
||||||
|
|
||||||
coverage:
|
coverage:
|
||||||
postgres/interface: full
|
postgres/interface: full
|
||||||
|
@ -89,6 +89,50 @@ testRun(void)
|
|||||||
TEST_RESULT_INT(info.version, PG_VERSION_83, " check version");
|
TEST_RESULT_INT(info.version, PG_VERSION_83, " check version");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// *****************************************************************************************************************************
|
||||||
|
if (testBegin("pgWalFromBuffer() and pgWalFromFile()"))
|
||||||
|
{
|
||||||
|
String *walFile = strNewFmt("%s/0000000F0000000F0000000F", testPath());
|
||||||
|
|
||||||
|
// Create a bogus control file, initially not in long format)
|
||||||
|
// --------------------------------------------------------------------------------------------------------------------------
|
||||||
|
Buffer *result = bufNew((size_t)16 * 1024 * 1024);
|
||||||
|
memset(bufPtr(result), 0, bufSize(result));
|
||||||
|
bufUsedSet(result, bufSize(result));
|
||||||
|
((PgWalCommon *)bufPtr(result))->magic = 777;
|
||||||
|
|
||||||
|
TEST_ERROR(pgWalFromBuffer(result), FormatError, "first page header in WAL file is expected to be in long format");
|
||||||
|
|
||||||
|
// Add the long flag so that the version will now error
|
||||||
|
// --------------------------------------------------------------------------------------------------------------------------
|
||||||
|
((PgWalCommon *)bufPtr(result))->flag = PG_WAL_LONG_HEADER;
|
||||||
|
|
||||||
|
TEST_ERROR(
|
||||||
|
pgWalFromBuffer(result), VersionNotSupportedError,
|
||||||
|
"unexpected WAL magic 777\n"
|
||||||
|
"HINT: is this version of PostgreSQL supported?");
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------------------------------
|
||||||
|
TEST_ERROR(pgWalTestToBuffer((PgWal){.version = 0}, result), AssertError, "invalid version 0");
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------------------------------
|
||||||
|
pgWalTestToBuffer((PgWal){.version = PG_VERSION_11, .systemId = 0xECAFECAF}, result);
|
||||||
|
storagePutNP(storageNewWriteNP(storageTest, walFile), result);
|
||||||
|
|
||||||
|
PgWal info = {0};
|
||||||
|
TEST_ASSIGN(info, pgWalFromFile(walFile), "get wal info v11");
|
||||||
|
TEST_RESULT_INT(info.systemId, 0xECAFECAF, " check system id");
|
||||||
|
TEST_RESULT_INT(info.version, PG_VERSION_11, " check version");
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------------------------------
|
||||||
|
pgWalTestToBuffer((PgWal){.version = PG_VERSION_83, .systemId = 0xEAEAEAEA}, result);
|
||||||
|
storagePutNP(storageNewWriteNP(storageTest, walFile), result);
|
||||||
|
|
||||||
|
TEST_ASSIGN(info, pgWalFromFile(walFile), "get wal info v8.3");
|
||||||
|
TEST_RESULT_INT(info.systemId, 0xEAEAEAEA, " check system id");
|
||||||
|
TEST_RESULT_INT(info.version, PG_VERSION_83, " check version");
|
||||||
|
}
|
||||||
|
|
||||||
// *****************************************************************************************************************************
|
// *****************************************************************************************************************************
|
||||||
if (testBegin("pgControlToLog()"))
|
if (testBegin("pgControlToLog()"))
|
||||||
{
|
{
|
||||||
@ -105,5 +149,20 @@ testRun(void)
|
|||||||
"{version: 110000, systemId: 1030522662895, walSegmentSize: 16777216, pageChecksum: true}", "check log");
|
"{version: 110000, systemId: 1030522662895, walSegmentSize: 16777216, pageChecksum: true}", "check log");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// *****************************************************************************************************************************
|
||||||
|
if (testBegin("pgWalToLog()"))
|
||||||
|
{
|
||||||
|
PgWal pgWal =
|
||||||
|
{
|
||||||
|
.version = PG_VERSION_10,
|
||||||
|
.systemId = 0xFEFEFEFEFE
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_RESULT_STR(
|
||||||
|
strPtr(pgWalToLog(&pgWal)),
|
||||||
|
"{version: 100000, systemId: 1095199817470}", "check log");
|
||||||
|
}
|
||||||
|
|
||||||
FUNCTION_HARNESS_RESULT_VOID();
|
FUNCTION_HARNESS_RESULT_VOID();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user