mirror of
https://github.com/postgres/postgres.git
synced 2025-11-28 11:44:57 +03:00
Add contrib/pg_walinspect.
Provides similar functionality to pg_waldump, but from a SQL interface rather than a separate utility. Author: Bharath Rupireddy Reviewed-by: Greg Stark, Kyotaro Horiguchi, Andres Freund, Ashutosh Sharma, Nitin Jadhav, RKN Sai Krishna Discussion: https://postgr.es/m/CALj2ACUGUYXsEQdKhEdsBzhGEyF3xggvLdD8C0VT72TNEfOiog%40mail.gmail.com
This commit is contained in:
@@ -34,6 +34,7 @@ OBJS = \
|
||||
xlogprefetcher.o \
|
||||
xlogreader.o \
|
||||
xlogrecovery.o \
|
||||
xlogstats.o \
|
||||
xlogutils.o
|
||||
|
||||
include $(top_srcdir)/src/backend/common.mk
|
||||
|
||||
@@ -1320,13 +1320,6 @@ XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr,
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef FRONTEND
|
||||
/*
|
||||
* Functions that are currently not needed in the backend, but are better
|
||||
* implemented inside xlogreader.c because of the internal facilities available
|
||||
* here.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Find the first record with an lsn >= RecPtr.
|
||||
*
|
||||
@@ -1447,8 +1440,6 @@ err:
|
||||
return InvalidXLogRecPtr;
|
||||
}
|
||||
|
||||
#endif /* FRONTEND */
|
||||
|
||||
/*
|
||||
* Helper function to ease writing of XLogRoutine->page_read callbacks.
|
||||
* If this function is used, caller must supply a segment_open callback in
|
||||
|
||||
93
src/backend/access/transam/xlogstats.c
Normal file
93
src/backend/access/transam/xlogstats.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*-------------------------------------------------------------------------
|
||||
*
|
||||
* xlogstats.c
|
||||
* Functions for WAL Statitstics
|
||||
*
|
||||
* Copyright (c) 2022, PostgreSQL Global Development Group
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* src/backend/access/transam/xlogstats.c
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
#include "postgres.h"
|
||||
|
||||
#include "access/xlogreader.h"
|
||||
#include "access/xlogstats.h"
|
||||
|
||||
/*
|
||||
* Calculate the size of a record, split into !FPI and FPI parts.
|
||||
*/
|
||||
void
|
||||
XLogRecGetLen(XLogReaderState *record, uint32 *rec_len,
|
||||
uint32 *fpi_len)
|
||||
{
|
||||
int block_id;
|
||||
|
||||
/*
|
||||
* Calculate the amount of FPI data in the record.
|
||||
*
|
||||
* XXX: We peek into xlogreader's private decoded backup blocks for the
|
||||
* bimg_len indicating the length of FPI data.
|
||||
*/
|
||||
*fpi_len = 0;
|
||||
for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++)
|
||||
{
|
||||
if (XLogRecHasBlockImage(record, block_id))
|
||||
*fpi_len += XLogRecGetBlock(record, block_id)->bimg_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the length of the record as the total length - the length of
|
||||
* all the block images.
|
||||
*/
|
||||
*rec_len = XLogRecGetTotalLen(record) - *fpi_len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Store per-rmgr and per-record statistics for a given record.
|
||||
*/
|
||||
void
|
||||
XLogRecStoreStats(XLogStats *stats, XLogReaderState *record)
|
||||
{
|
||||
RmgrId rmid;
|
||||
uint8 recid;
|
||||
uint32 rec_len;
|
||||
uint32 fpi_len;
|
||||
|
||||
Assert(stats != NULL && record != NULL);
|
||||
|
||||
stats->count++;
|
||||
|
||||
rmid = XLogRecGetRmid(record);
|
||||
|
||||
XLogRecGetLen(record, &rec_len, &fpi_len);
|
||||
|
||||
/* Update per-rmgr statistics */
|
||||
|
||||
stats->rmgr_stats[rmid].count++;
|
||||
stats->rmgr_stats[rmid].rec_len += rec_len;
|
||||
stats->rmgr_stats[rmid].fpi_len += fpi_len;
|
||||
|
||||
/*
|
||||
* Update per-record statistics, where the record is identified by a
|
||||
* combination of the RmgrId and the four bits of the xl_info field that
|
||||
* are the rmgr's domain (resulting in sixteen possible entries per
|
||||
* RmgrId).
|
||||
*/
|
||||
|
||||
recid = XLogRecGetInfo(record) >> 4;
|
||||
|
||||
/*
|
||||
* XACT records need to be handled differently. Those records use the
|
||||
* first bit of those four bits for an optional flag variable and the
|
||||
* following three bits for the opcode. We filter opcode out of xl_info
|
||||
* and use it as the identifier of the record.
|
||||
*/
|
||||
if (rmid == RM_XACT_ID)
|
||||
recid &= 0x07;
|
||||
|
||||
stats->record_stats[rmid][recid].count++;
|
||||
stats->record_stats[rmid][recid].rec_len += rec_len;
|
||||
stats->record_stats[rmid][recid].fpi_len += fpi_len;
|
||||
}
|
||||
@@ -80,6 +80,10 @@ typedef struct xl_invalid_page
|
||||
|
||||
static HTAB *invalid_page_tab = NULL;
|
||||
|
||||
static int
|
||||
read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
|
||||
int reqLen, XLogRecPtr targetRecPtr,
|
||||
char *cur_page, bool wait_for_wal);
|
||||
|
||||
/* Report a reference to an invalid page */
|
||||
static void
|
||||
@@ -870,6 +874,31 @@ wal_segment_close(XLogReaderState *state)
|
||||
int
|
||||
read_local_xlog_page(XLogReaderState *state, XLogRecPtr targetPagePtr,
|
||||
int reqLen, XLogRecPtr targetRecPtr, char *cur_page)
|
||||
{
|
||||
return read_local_xlog_page_guts(state, targetPagePtr, reqLen,
|
||||
targetRecPtr, cur_page, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Same as read_local_xlog_page except that it doesn't wait for future WAL
|
||||
* to be available.
|
||||
*/
|
||||
int
|
||||
read_local_xlog_page_no_wait(XLogReaderState *state, XLogRecPtr targetPagePtr,
|
||||
int reqLen, XLogRecPtr targetRecPtr,
|
||||
char *cur_page)
|
||||
{
|
||||
return read_local_xlog_page_guts(state, targetPagePtr, reqLen,
|
||||
targetRecPtr, cur_page, false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Implementation of read_local_xlog_page and its no wait version.
|
||||
*/
|
||||
static int
|
||||
read_local_xlog_page_guts(XLogReaderState *state, XLogRecPtr targetPagePtr,
|
||||
int reqLen, XLogRecPtr targetRecPtr,
|
||||
char *cur_page, bool wait_for_wal)
|
||||
{
|
||||
XLogRecPtr read_upto,
|
||||
loc;
|
||||
@@ -925,6 +954,10 @@ read_local_xlog_page(XLogReaderState *state, XLogRecPtr targetPagePtr,
|
||||
if (loc <= read_upto)
|
||||
break;
|
||||
|
||||
/* If asked, let's not wait for future WAL. */
|
||||
if (!wait_for_wal)
|
||||
break;
|
||||
|
||||
CHECK_FOR_INTERRUPTS();
|
||||
pg_usleep(1000L);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user