PostgreSQL Source Code  git master
pg_walinspect.c File Reference
#include "postgres.h"
#include "access/xlog.h"
#include "access/xlog_internal.h"
#include "access/xlogreader.h"
#include "access/xlogrecovery.h"
#include "access/xlogstats.h"
#include "access/xlogutils.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/pg_lsn.h"
Include dependency graph for pg_walinspect.c:

Go to the source code of this file.

Macros

#define PG_GET_WAL_BLOCK_INFO_COLS   11
 
#define PG_GET_WAL_RECORD_INFO_COLS   11
 
#define PG_GET_WAL_RECORDS_INFO_COLS   11
 
#define PG_GET_WAL_STATS_COLS   9
 

Functions

 PG_FUNCTION_INFO_V1 (pg_get_wal_block_info)
 
 PG_FUNCTION_INFO_V1 (pg_get_wal_record_info)
 
 PG_FUNCTION_INFO_V1 (pg_get_wal_records_info)
 
 PG_FUNCTION_INFO_V1 (pg_get_wal_records_info_till_end_of_wal)
 
 PG_FUNCTION_INFO_V1 (pg_get_wal_stats)
 
 PG_FUNCTION_INFO_V1 (pg_get_wal_stats_till_end_of_wal)
 
static void ValidateInputLSNs (XLogRecPtr start_lsn, XLogRecPtr *end_lsn)
 
static XLogRecPtr GetCurrentLSN (void)
 
static XLogReaderStateInitXLogReaderState (XLogRecPtr lsn)
 
static XLogRecordReadNextXLogRecord (XLogReaderState *xlogreader)
 
static void GetWALRecordInfo (XLogReaderState *record, Datum *values, bool *nulls, uint32 ncols)
 
static void GetWALRecordsInfo (FunctionCallInfo fcinfo, XLogRecPtr start_lsn, XLogRecPtr end_lsn)
 
static void GetXLogSummaryStats (XLogStats *stats, ReturnSetInfo *rsinfo, Datum *values, bool *nulls, uint32 ncols, bool stats_per_record)
 
static void FillXLogStatsRow (const char *name, uint64 n, uint64 total_count, uint64 rec_len, uint64 total_rec_len, uint64 fpi_len, uint64 total_fpi_len, uint64 tot_len, uint64 total_len, Datum *values, bool *nulls, uint32 ncols)
 
static void GetWalStats (FunctionCallInfo fcinfo, XLogRecPtr start_lsn, XLogRecPtr end_lsn, bool stats_per_record)
 
static void GetWALBlockInfo (FunctionCallInfo fcinfo, XLogReaderState *record)
 
Datum pg_get_wal_block_info (PG_FUNCTION_ARGS)
 
Datum pg_get_wal_record_info (PG_FUNCTION_ARGS)
 
Datum pg_get_wal_records_info (PG_FUNCTION_ARGS)
 
Datum pg_get_wal_stats (PG_FUNCTION_ARGS)
 
Datum pg_get_wal_records_info_till_end_of_wal (PG_FUNCTION_ARGS)
 
Datum pg_get_wal_stats_till_end_of_wal (PG_FUNCTION_ARGS)
 

Variables

 PG_MODULE_MAGIC
 

Macro Definition Documentation

◆ PG_GET_WAL_BLOCK_INFO_COLS

#define PG_GET_WAL_BLOCK_INFO_COLS   11

◆ PG_GET_WAL_RECORD_INFO_COLS

#define PG_GET_WAL_RECORD_INFO_COLS   11

◆ PG_GET_WAL_RECORDS_INFO_COLS

#define PG_GET_WAL_RECORDS_INFO_COLS   11

◆ PG_GET_WAL_STATS_COLS

#define PG_GET_WAL_STATS_COLS   9

Function Documentation

◆ FillXLogStatsRow()

static void FillXLogStatsRow ( const char *  name,
uint64  n,
uint64  total_count,
uint64  rec_len,
uint64  total_rec_len,
uint64  fpi_len,
uint64  total_fpi_len,
uint64  tot_len,
uint64  total_len,
Datum values,
bool nulls,
uint32  ncols 
)
static

Definition at line 557 of file pg_walinspect.c.

563 {
564  double n_pct,
565  rec_len_pct,
566  fpi_len_pct,
567  tot_len_pct;
568  int i = 0;
569 
570  n_pct = 0;
571  if (total_count != 0)
572  n_pct = 100 * (double) n / total_count;
573 
574  rec_len_pct = 0;
575  if (total_rec_len != 0)
576  rec_len_pct = 100 * (double) rec_len / total_rec_len;
577 
578  fpi_len_pct = 0;
579  if (total_fpi_len != 0)
580  fpi_len_pct = 100 * (double) fpi_len / total_fpi_len;
581 
582  tot_len_pct = 0;
583  if (total_len != 0)
584  tot_len_pct = 100 * (double) tot_len / total_len;
585 
587  values[i++] = Int64GetDatum(n);
588  values[i++] = Float8GetDatum(n_pct);
589  values[i++] = Int64GetDatum(rec_len);
590  values[i++] = Float8GetDatum(rec_len_pct);
591  values[i++] = Int64GetDatum(fpi_len);
592  values[i++] = Float8GetDatum(fpi_len_pct);
593  values[i++] = Int64GetDatum(tot_len);
594  values[i++] = Float8GetDatum(tot_len_pct);
595 
596  Assert(i == ncols);
597 }
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define CStringGetTextDatum(s)
Definition: builtins.h:94
const char * name
Definition: encode.c:571
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1779
Datum Float8GetDatum(float8 X)
Definition: fmgr.c:1788
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')

References Assert(), CStringGetTextDatum, Float8GetDatum(), i, Int64GetDatum(), name, and values.

Referenced by GetXLogSummaryStats().

◆ GetCurrentLSN()

static XLogRecPtr GetCurrentLSN ( void  )
static

Definition at line 68 of file pg_walinspect.c.

69 {
70  XLogRecPtr curr_lsn;
71 
72  /*
73  * We determine the current LSN of the server similar to how page_read
74  * callback read_local_xlog_page_no_wait does.
75  */
76  if (!RecoveryInProgress())
77  curr_lsn = GetFlushRecPtr(NULL);
78  else
79  curr_lsn = GetXLogReplayRecPtr(NULL);
80 
81  Assert(!XLogRecPtrIsInvalid(curr_lsn));
82 
83  return curr_lsn;
84 }
bool RecoveryInProgress(void)
Definition: xlog.c:5908
XLogRecPtr GetFlushRecPtr(TimeLineID *insertTLI)
Definition: xlog.c:6073
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
uint64 XLogRecPtr
Definition: xlogdefs.h:21
XLogRecPtr GetXLogReplayRecPtr(TimeLineID *replayTLI)

References Assert(), GetFlushRecPtr(), GetXLogReplayRecPtr(), RecoveryInProgress(), and XLogRecPtrIsInvalid.

Referenced by pg_get_wal_record_info(), pg_get_wal_records_info_till_end_of_wal(), pg_get_wal_stats_till_end_of_wal(), and ValidateInputLSNs().

◆ GetWALBlockInfo()

static void GetWALBlockInfo ( FunctionCallInfo  fcinfo,
XLogReaderState record 
)
static

Definition at line 236 of file pg_walinspect.c.

237 {
238 #define PG_GET_WAL_BLOCK_INFO_COLS 11
239  int block_id;
240  ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
241 
242  for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++)
243  {
244  DecodedBkpBlock *blk;
245  BlockNumber blkno;
246  RelFileLocator rnode;
247  ForkNumber fork;
249  bool nulls[PG_GET_WAL_BLOCK_INFO_COLS] = {0};
250  int i = 0;
251 
252  if (!XLogRecHasBlockRef(record, block_id))
253  continue;
254 
255  blk = XLogRecGetBlock(record, block_id);
256 
257  (void) XLogRecGetBlockTagExtended(record, block_id,
258  &rnode, &fork, &blkno, NULL);
259 
260  values[i++] = LSNGetDatum(record->ReadRecPtr);
261  values[i++] = Int16GetDatum(block_id);
265  values[i++] = Int64GetDatum((int64) blkno);
266 
267  if (fork >= 0 && fork <= MAX_FORKNUM)
269  else
270  ereport(ERROR,
271  (errcode(ERRCODE_INTERNAL_ERROR),
272  errmsg_internal("invalid fork number: %u", fork)));
273 
274  /* Block data */
275  if (blk->has_data)
276  {
277  bytea *raw_data;
278 
279  /* Initialize bytea buffer to copy the data to */
280  raw_data = (bytea *) palloc(blk->data_len + VARHDRSZ);
281  SET_VARSIZE(raw_data, blk->data_len + VARHDRSZ);
282 
283  /* Copy the data */
284  memcpy(VARDATA(raw_data), blk->data, blk->data_len);
285  values[i++] = PointerGetDatum(raw_data);
286  }
287  else
288  {
289  /* No data, so set this field to NULL */
290  nulls[i++] = true;
291  }
292 
293  if (blk->has_image)
294  {
296  Page page;
297  bytea *raw_page;
298  int bitcnt;
299  int cnt = 0;
300  Datum *flags;
301  ArrayType *a;
302 
303  page = (Page) buf.data;
304 
305  /* Full page image exists, so let's save it */
306  if (!RestoreBlockImage(record, block_id, page))
307  ereport(ERROR,
308  (errcode(ERRCODE_INTERNAL_ERROR),
309  errmsg_internal("%s", record->errormsg_buf)));
310 
311  /* Initialize bytea buffer to copy the FPI to */
312  raw_page = (bytea *) palloc(BLCKSZ + VARHDRSZ);
313  SET_VARSIZE(raw_page, BLCKSZ + VARHDRSZ);
314 
315  /* Take a verbatim copy of the FPI */
316  memcpy(VARDATA(raw_page), page, BLCKSZ);
317 
318  values[i++] = PointerGetDatum(raw_page);
319  values[i++] = UInt32GetDatum(blk->bimg_len);
320 
321  /* FPI flags */
322  bitcnt = pg_popcount((const char *) &blk->bimg_info,
323  sizeof(uint8));
324  /* Build set of raw flags */
325  flags = (Datum *) palloc0(sizeof(Datum) * bitcnt);
326 
327  if ((blk->bimg_info & BKPIMAGE_HAS_HOLE) != 0)
328  flags[cnt++] = CStringGetTextDatum("HAS_HOLE");
329  if (blk->apply_image)
330  flags[cnt++] = CStringGetTextDatum("APPLY");
331  if ((blk->bimg_info & BKPIMAGE_COMPRESS_PGLZ) != 0)
332  flags[cnt++] = CStringGetTextDatum("COMPRESS_PGLZ");
333  if ((blk->bimg_info & BKPIMAGE_COMPRESS_LZ4) != 0)
334  flags[cnt++] = CStringGetTextDatum("COMPRESS_LZ4");
335  if ((blk->bimg_info & BKPIMAGE_COMPRESS_ZSTD) != 0)
336  flags[cnt++] = CStringGetTextDatum("COMPRESS_ZSTD");
337 
338  Assert(cnt <= bitcnt);
339  a = construct_array_builtin(flags, cnt, TEXTOID);
340  values[i++] = PointerGetDatum(a);
341  }
342  else
343  {
344  /* No full page image, so store NULLs for all its fields */
345  memset(&nulls[i], true, 3 * sizeof(bool));
346  i += 3;
347  }
348 
350 
351  tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
352  values, nulls);
353  }
354 
355 #undef PG_GET_WAL_FPI_BLOCK_COLS
356 }
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
Definition: arrayfuncs.c:3361
uint32 BlockNumber
Definition: block.h:31
Pointer Page
Definition: bufpage.h:78
#define VARHDRSZ
Definition: c.h:676
unsigned char uint8
Definition: c.h:488
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1156
int errcode(int sqlerrcode)
Definition: elog.c:858
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
int a
Definition: isn.c:69
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
void * palloc0(Size size)
Definition: mcxt.c:1241
void * palloc(Size size)
Definition: mcxt.c:1210
uint64 pg_popcount(const char *buf, int bytes)
Definition: pg_bitutils.c:296
static Datum LSNGetDatum(XLogRecPtr X)
Definition: pg_lsn.h:28
static char * buf
Definition: pg_test_fsync.c:67
#define PG_GET_WAL_BLOCK_INFO_COLS
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
uintptr_t Datum
Definition: postgres.h:64
static Datum Int16GetDatum(int16 X)
Definition: postgres.h:172
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Datum UInt32GetDatum(uint32 X)
Definition: postgres.h:232
const char *const forkNames[]
Definition: relpath.c:33
ForkNumber
Definition: relpath.h:48
#define MAX_FORKNUM
Definition: relpath.h:62
RelFileLocator rlocator
Definition: xlogreader.h:125
fmNodePtr resultinfo
Definition: fmgr.h:89
RelFileNumber relNumber
TupleDesc setDesc
Definition: execnodes.h:334
Tuplestorestate * setResult
Definition: execnodes.h:333
char * errormsg_buf
Definition: xlogreader.h:311
XLogRecPtr ReadRecPtr
Definition: xlogreader.h:206
Definition: c.h:671
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, Datum *values, bool *isnull)
Definition: tuplestore.c:750
#define VARDATA(PTR)
Definition: varatt.h:278
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305
bool XLogRecGetBlockTagExtended(XLogReaderState *record, uint8 block_id, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum, Buffer *prefetch_buffer)
Definition: xlogreader.c:1987
bool RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
Definition: xlogreader.c:2046
#define XLogRecGetBlock(decoder, i)
Definition: xlogreader.h:418
#define XLogRecMaxBlockId(decoder)
Definition: xlogreader.h:417
#define XLogRecHasBlockRef(decoder, block_id)
Definition: xlogreader.h:419
#define BKPIMAGE_COMPRESS_ZSTD
Definition: xlogrecord.h:151
#define BKPIMAGE_HAS_HOLE
Definition: xlogrecord.h:146
#define BKPIMAGE_COMPRESS_LZ4
Definition: xlogrecord.h:150
#define BKPIMAGE_COMPRESS_PGLZ
Definition: xlogrecord.h:149

References a, DecodedBkpBlock::apply_image, Assert(), DecodedBkpBlock::bimg_info, DecodedBkpBlock::bimg_len, BKPIMAGE_COMPRESS_LZ4, BKPIMAGE_COMPRESS_PGLZ, BKPIMAGE_COMPRESS_ZSTD, BKPIMAGE_HAS_HOLE, buf, construct_array_builtin(), CStringGetTextDatum, DecodedBkpBlock::data, DecodedBkpBlock::data_len, RelFileLocator::dbOid, ereport, errcode(), errmsg_internal(), ERROR, XLogReaderState::errormsg_buf, forkNames, DecodedBkpBlock::has_data, DecodedBkpBlock::has_image, i, if(), Int16GetDatum(), Int64GetDatum(), LSNGetDatum(), MAX_FORKNUM, ObjectIdGetDatum(), palloc(), palloc0(), PG_GET_WAL_BLOCK_INFO_COLS, pg_popcount(), PointerGetDatum(), XLogReaderState::ReadRecPtr, RelFileLocator::relNumber, RestoreBlockImage(), FunctionCallInfoBaseData::resultinfo, DecodedBkpBlock::rlocator, SET_VARSIZE, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, RelFileLocator::spcOid, tuplestore_putvalues(), UInt32GetDatum(), values, VARDATA, VARHDRSZ, XLogRecGetBlock, XLogRecGetBlockTagExtended(), XLogRecHasBlockRef, and XLogRecMaxBlockId.

Referenced by pg_get_wal_block_info().

◆ GetWALRecordInfo()

static void GetWALRecordInfo ( XLogReaderState record,
Datum values,
bool nulls,
uint32  ncols 
)
static

Definition at line 182 of file pg_walinspect.c.

184 {
185  const char *id;
186  RmgrData desc;
187  uint32 fpi_len = 0;
188  StringInfoData rec_desc;
189  StringInfoData rec_blk_ref;
190  int i = 0;
191 
192  desc = GetRmgr(XLogRecGetRmid(record));
193  id = desc.rm_identify(XLogRecGetInfo(record));
194 
195  if (id == NULL)
196  id = psprintf("UNKNOWN (%x)", XLogRecGetInfo(record) & ~XLR_INFO_MASK);
197 
198  initStringInfo(&rec_desc);
199  desc.rm_desc(&rec_desc, record);
200 
201  if (XLogRecHasAnyBlockRefs(record))
202  {
203  initStringInfo(&rec_blk_ref);
204  XLogRecGetBlockRefInfo(record, false, true, &rec_blk_ref, &fpi_len);
205  }
206 
207  values[i++] = LSNGetDatum(record->ReadRecPtr);
208  values[i++] = LSNGetDatum(record->EndRecPtr);
209  values[i++] = LSNGetDatum(XLogRecGetPrev(record));
211  values[i++] = CStringGetTextDatum(desc.rm_name);
212  values[i++] = CStringGetTextDatum(id);
215  values[i++] = UInt32GetDatum(fpi_len);
216 
217  if (rec_desc.len > 0)
218  values[i++] = CStringGetTextDatum(rec_desc.data);
219  else
220  nulls[i++] = true;
221 
222  if (XLogRecHasAnyBlockRefs(record))
223  values[i++] = CStringGetTextDatum(rec_blk_ref.data);
224  else
225  nulls[i++] = true;
226 
227  Assert(i == ncols);
228 }
unsigned int uint32
Definition: c.h:490
static Datum TransactionIdGetDatum(TransactionId X)
Definition: postgres.h:272
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
const char *(* rm_identify)(uint8 info)
const char * rm_name
void(* rm_desc)(StringInfo buf, XLogReaderState *record)
XLogRecPtr EndRecPtr
Definition: xlogreader.h:207
static RmgrData GetRmgr(RmgrId rmid)
void XLogRecGetBlockRefInfo(XLogReaderState *record, bool pretty, bool detailed_format, StringInfo buf, uint32 *fpi_len)
Definition: xlogdesc.c:209
#define XLogRecGetDataLen(decoder)
Definition: xlogreader.h:415
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:409
#define XLogRecGetRmid(decoder)
Definition: xlogreader.h:410
#define XLogRecGetTotalLen(decoder)
Definition: xlogreader.h:407
#define XLogRecGetXid(decoder)
Definition: xlogreader.h:411
#define XLogRecGetPrev(decoder)
Definition: xlogreader.h:408
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:416
#define XLR_INFO_MASK
Definition: xlogrecord.h:62

References Assert(), CStringGetTextDatum, StringInfoData::data, XLogReaderState::EndRecPtr, GetRmgr(), i, initStringInfo(), StringInfoData::len, LSNGetDatum(), psprintf(), XLogReaderState::ReadRecPtr, RmgrData::rm_desc, RmgrData::rm_identify, RmgrData::rm_name, TransactionIdGetDatum(), UInt32GetDatum(), values, XLogRecGetBlockRefInfo(), XLogRecGetDataLen, XLogRecGetInfo, XLogRecGetPrev, XLogRecGetRmid, XLogRecGetTotalLen, XLogRecGetXid, XLogRecHasAnyBlockRefs, and XLR_INFO_MASK.

Referenced by GetWALRecordsInfo(), and pg_get_wal_record_info().

◆ GetWALRecordsInfo()

static void GetWALRecordsInfo ( FunctionCallInfo  fcinfo,
XLogRecPtr  start_lsn,
XLogRecPtr  end_lsn 
)
static

Definition at line 490 of file pg_walinspect.c.

492 {
493 #define PG_GET_WAL_RECORDS_INFO_COLS 11
495  ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
496  MemoryContext old_cxt;
497  MemoryContext tmp_cxt;
498 
499  Assert(start_lsn <= end_lsn);
500 
501  InitMaterializedSRF(fcinfo, 0);
502 
503  xlogreader = InitXLogReaderState(start_lsn);
504 
506  "GetWALRecordsInfo temporary cxt",
508 
509  while (ReadNextXLogRecord(xlogreader) &&
510  xlogreader->EndRecPtr <= end_lsn)
511  {
513  bool nulls[PG_GET_WAL_RECORDS_INFO_COLS] = {0};
514 
515  /* Use the tmp context so we can clean up after each tuple is done */
516  old_cxt = MemoryContextSwitchTo(tmp_cxt);
517 
520 
521  tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
522  values, nulls);
523 
524  /* clean up and switch back */
525  MemoryContextSwitchTo(old_cxt);
526  MemoryContextReset(tmp_cxt);
527 
529  }
530 
531  MemoryContextDelete(tmp_cxt);
534 
535 #undef PG_GET_WAL_RECORDS_INFO_COLS
536 }
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition: funcapi.c:76
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:314
void pfree(void *pointer)
Definition: mcxt.c:1436
MemoryContext CurrentMemoryContext
Definition: mcxt.c:135
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:387
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:153
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:138
static void GetWALRecordInfo(XLogReaderState *record, Datum *values, bool *nulls, uint32 ncols)
#define PG_GET_WAL_RECORDS_INFO_COLS
static XLogRecord * ReadNextXLogRecord(XLogReaderState *xlogreader)
static XLogReaderState * InitXLogReaderState(XLogRecPtr lsn)
Definition: pg_walinspect.c:90
void * private_data
Definition: xlogreader.h:196
void XLogReaderFree(XLogReaderState *state)
Definition: xlogreader.c:170
static XLogReaderState * xlogreader
Definition: xlogrecovery.c:188

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert(), CHECK_FOR_INTERRUPTS, CurrentMemoryContext, XLogReaderState::EndRecPtr, GetWALRecordInfo(), InitMaterializedSRF(), InitXLogReaderState(), MemoryContextDelete(), MemoryContextReset(), MemoryContextSwitchTo(), pfree(), PG_GET_WAL_RECORDS_INFO_COLS, XLogReaderState::private_data, ReadNextXLogRecord(), FunctionCallInfoBaseData::resultinfo, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, tuplestore_putvalues(), values, xlogreader, and XLogReaderFree().

Referenced by pg_get_wal_records_info(), and pg_get_wal_records_info_till_end_of_wal().

◆ GetWalStats()

static void GetWalStats ( FunctionCallInfo  fcinfo,
XLogRecPtr  start_lsn,
XLogRecPtr  end_lsn,
bool  stats_per_record 
)
static

Definition at line 716 of file pg_walinspect.c.

718 {
719 #define PG_GET_WAL_STATS_COLS 9
721  XLogStats stats = {0};
722  ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
724  bool nulls[PG_GET_WAL_STATS_COLS] = {0};
725 
726  Assert(start_lsn <= end_lsn);
727 
728  InitMaterializedSRF(fcinfo, 0);
729 
730  xlogreader = InitXLogReaderState(start_lsn);
731 
732  while (ReadNextXLogRecord(xlogreader) &&
733  xlogreader->EndRecPtr <= end_lsn)
734  {
735  XLogRecStoreStats(&stats, xlogreader);
736 
738  }
739 
742 
743  GetXLogSummaryStats(&stats, rsinfo, values, nulls,
745  stats_per_record);
746 
747 #undef PG_GET_WAL_STATS_COLS
748 }
#define PG_GET_WAL_STATS_COLS
static void GetXLogSummaryStats(XLogStats *stats, ReturnSetInfo *rsinfo, Datum *values, bool *nulls, uint32 ncols, bool stats_per_record)
void XLogRecStoreStats(XLogStats *stats, XLogReaderState *record)
Definition: xlogstats.c:54

References PG_GET_WAL_STATS_COLS, FunctionCallInfoBaseData::resultinfo, values, and xlogreader.

Referenced by pg_get_wal_stats(), and pg_get_wal_stats_till_end_of_wal().

◆ GetXLogSummaryStats()

static void GetXLogSummaryStats ( XLogStats stats,
ReturnSetInfo rsinfo,
Datum values,
bool nulls,
uint32  ncols,
bool  stats_per_record 
)
static

Definition at line 603 of file pg_walinspect.c.

606 {
607  MemoryContext old_cxt;
608  MemoryContext tmp_cxt;
609  uint64 total_count = 0;
610  uint64 total_rec_len = 0;
611  uint64 total_fpi_len = 0;
612  uint64 total_len = 0;
613  int ri;
614 
615  /*
616  * Each row shows its percentages of the total, so make a first pass to
617  * calculate column totals.
618  */
619  for (ri = 0; ri <= RM_MAX_ID; ri++)
620  {
621  if (!RmgrIdIsValid(ri))
622  continue;
623 
624  total_count += stats->rmgr_stats[ri].count;
625  total_rec_len += stats->rmgr_stats[ri].rec_len;
626  total_fpi_len += stats->rmgr_stats[ri].fpi_len;
627  }
628  total_len = total_rec_len + total_fpi_len;
629 
631  "GetXLogSummaryStats temporary cxt",
633 
634  for (ri = 0; ri <= RM_MAX_ID; ri++)
635  {
636  uint64 count;
637  uint64 rec_len;
638  uint64 fpi_len;
639  uint64 tot_len;
640  RmgrData desc;
641 
642  if (!RmgrIdIsValid(ri))
643  continue;
644 
645  if (!RmgrIdExists(ri))
646  continue;
647 
648  desc = GetRmgr(ri);
649 
650  if (stats_per_record)
651  {
652  int rj;
653 
654  for (rj = 0; rj < MAX_XLINFO_TYPES; rj++)
655  {
656  const char *id;
657 
658  count = stats->record_stats[ri][rj].count;
659  rec_len = stats->record_stats[ri][rj].rec_len;
660  fpi_len = stats->record_stats[ri][rj].fpi_len;
661  tot_len = rec_len + fpi_len;
662 
663  /* Skip undefined combinations and ones that didn't occur */
664  if (count == 0)
665  continue;
666 
667  old_cxt = MemoryContextSwitchTo(tmp_cxt);
668 
669  /* the upper four bits in xl_info are the rmgr's */
670  id = desc.rm_identify(rj << 4);
671  if (id == NULL)
672  id = psprintf("UNKNOWN (%x)", rj << 4);
673 
674  FillXLogStatsRow(psprintf("%s/%s", desc.rm_name, id), count,
675  total_count, rec_len, total_rec_len, fpi_len,
676  total_fpi_len, tot_len, total_len,
677  values, nulls, ncols);
678 
679  tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
680  values, nulls);
681 
682  /* clean up and switch back */
683  MemoryContextSwitchTo(old_cxt);
684  MemoryContextReset(tmp_cxt);
685  }
686  }
687  else
688  {
689  count = stats->rmgr_stats[ri].count;
690  rec_len = stats->rmgr_stats[ri].rec_len;
691  fpi_len = stats->rmgr_stats[ri].fpi_len;
692  tot_len = rec_len + fpi_len;
693 
694  old_cxt = MemoryContextSwitchTo(tmp_cxt);
695 
696  FillXLogStatsRow(desc.rm_name, count, total_count, rec_len,
697  total_rec_len, fpi_len, total_fpi_len, tot_len,
698  total_len, values, nulls, ncols);
699 
700  tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
701  values, nulls);
702 
703  /* clean up and switch back */
704  MemoryContextSwitchTo(old_cxt);
705  MemoryContextReset(tmp_cxt);
706  }
707  }
708 
709  MemoryContextDelete(tmp_cxt);
710 }
static void FillXLogStatsRow(const char *name, uint64 n, uint64 total_count, uint64 rec_len, uint64 total_rec_len, uint64 fpi_len, uint64 total_fpi_len, uint64 tot_len, uint64 total_len, Datum *values, bool *nulls, uint32 ncols)
#define RmgrIdIsValid(rmid)
Definition: rmgr.h:53
#define RM_MAX_ID
Definition: rmgr.h:33
uint64 count
Definition: xlogstats.h:23
uint64 fpi_len
Definition: xlogstats.h:25
uint64 rec_len
Definition: xlogstats.h:24
XLogRecStats record_stats[RM_MAX_ID+1][MAX_XLINFO_TYPES]
Definition: xlogstats.h:36
XLogRecStats rmgr_stats[RM_MAX_ID+1]
Definition: xlogstats.h:35
static bool RmgrIdExists(RmgrId rmid)
#define MAX_XLINFO_TYPES
Definition: xlogstats.h:19

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, XLogRecStats::count, CurrentMemoryContext, FillXLogStatsRow(), XLogRecStats::fpi_len, GetRmgr(), MAX_XLINFO_TYPES, MemoryContextDelete(), MemoryContextReset(), MemoryContextSwitchTo(), psprintf(), XLogRecStats::rec_len, XLogStats::record_stats, RmgrData::rm_identify, RM_MAX_ID, RmgrData::rm_name, XLogStats::rmgr_stats, RmgrIdExists(), RmgrIdIsValid, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, tuplestore_putvalues(), and values.

◆ InitXLogReaderState()

static XLogReaderState * InitXLogReaderState ( XLogRecPtr  lsn)
static

Definition at line 90 of file pg_walinspect.c.

91 {
93  ReadLocalXLogPageNoWaitPrivate *private_data;
94  XLogRecPtr first_valid_record;
95 
96  /*
97  * Reading WAL below the first page of the first segments isn't allowed.
98  * This is a bootstrap WAL page and the page_read callback fails to read
99  * it.
100  */
101  if (lsn < XLOG_BLCKSZ)
102  ereport(ERROR,
103  (errmsg("could not read WAL at LSN %X/%X",
104  LSN_FORMAT_ARGS(lsn))));
105 
106  private_data = (ReadLocalXLogPageNoWaitPrivate *)
108 
111  .segment_open = &wal_segment_open,
112  .segment_close = &wal_segment_close),
113  private_data);
114 
115  if (xlogreader == NULL)
116  ereport(ERROR,
117  (errcode(ERRCODE_OUT_OF_MEMORY),
118  errmsg("out of memory"),
119  errdetail("Failed while allocating a WAL reading processor.")));
120 
121  /* first find a valid recptr to start from */
122  first_valid_record = XLogFindNextRecord(xlogreader, lsn);
123 
124  if (XLogRecPtrIsInvalid(first_valid_record))
125  ereport(ERROR,
126  (errmsg("could not find a valid record after %X/%X",
127  LSN_FORMAT_ARGS(lsn))));
128 
129  return xlogreader;
130 }
int errdetail(const char *fmt,...)
Definition: elog.c:1202
int errmsg(const char *fmt,...)
Definition: elog.c:1069
int wal_segment_size
Definition: xlog.c:146
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
XLogReaderState * XLogReaderAllocate(int wal_segment_size, const char *waldir, XLogReaderRoutine *routine, void *private_data)
Definition: xlogreader.c:108
XLogRecPtr XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr)
Definition: xlogreader.c:1370
#define XL_ROUTINE(...)
Definition: xlogreader.h:117
void wal_segment_close(XLogReaderState *state)
Definition: xlogutils.c:859
void wal_segment_open(XLogReaderState *state, XLogSegNo nextSegNo, TimeLineID *tli_p)
Definition: xlogutils.c:834
int read_local_xlog_page_no_wait(XLogReaderState *state, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *cur_page)
Definition: xlogutils.c:890

References ereport, errcode(), errdetail(), errmsg(), ERROR, LSN_FORMAT_ARGS, palloc0(), read_local_xlog_page_no_wait(), wal_segment_close(), wal_segment_open(), wal_segment_size, XL_ROUTINE, XLogFindNextRecord(), xlogreader, XLogReaderAllocate(), and XLogRecPtrIsInvalid.

Referenced by GetWALRecordsInfo(), pg_get_wal_block_info(), and pg_get_wal_record_info().

◆ PG_FUNCTION_INFO_V1() [1/6]

PG_FUNCTION_INFO_V1 ( pg_get_wal_block_info  )

◆ PG_FUNCTION_INFO_V1() [2/6]

PG_FUNCTION_INFO_V1 ( pg_get_wal_record_info  )

◆ PG_FUNCTION_INFO_V1() [3/6]

PG_FUNCTION_INFO_V1 ( pg_get_wal_records_info  )

◆ PG_FUNCTION_INFO_V1() [4/6]

PG_FUNCTION_INFO_V1 ( pg_get_wal_records_info_till_end_of_wal  )

◆ PG_FUNCTION_INFO_V1() [5/6]

PG_FUNCTION_INFO_V1 ( pg_get_wal_stats  )

◆ PG_FUNCTION_INFO_V1() [6/6]

PG_FUNCTION_INFO_V1 ( pg_get_wal_stats_till_end_of_wal  )

◆ pg_get_wal_block_info()

Datum pg_get_wal_block_info ( PG_FUNCTION_ARGS  )

Definition at line 366 of file pg_walinspect.c.

367 {
368  XLogRecPtr start_lsn = PG_GETARG_LSN(0);
369  XLogRecPtr end_lsn = PG_GETARG_LSN(1);
371  MemoryContext old_cxt;
372  MemoryContext tmp_cxt;
373 
374  ValidateInputLSNs(start_lsn, &end_lsn);
375 
376  InitMaterializedSRF(fcinfo, 0);
377 
378  xlogreader = InitXLogReaderState(start_lsn);
379 
381  "pg_get_wal_block_info temporary cxt",
383 
384  while (ReadNextXLogRecord(xlogreader) &&
385  xlogreader->EndRecPtr <= end_lsn)
386  {
388 
390  continue;
391 
392  /* Use the tmp context so we can clean up after each tuple is done */
393  old_cxt = MemoryContextSwitchTo(tmp_cxt);
394 
395  GetWALBlockInfo(fcinfo, xlogreader);
396 
397  /* clean up and switch back */
398  MemoryContextSwitchTo(old_cxt);
399  MemoryContextReset(tmp_cxt);
400  }
401 
402  MemoryContextDelete(tmp_cxt);
405 
406  PG_RETURN_VOID();
407 }
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define PG_GETARG_LSN(n)
Definition: pg_lsn.h:33
static void GetWALBlockInfo(FunctionCallInfo fcinfo, XLogReaderState *record)
static void ValidateInputLSNs(XLogRecPtr start_lsn, XLogRecPtr *end_lsn)

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, CHECK_FOR_INTERRUPTS, CurrentMemoryContext, XLogReaderState::EndRecPtr, GetWALBlockInfo(), InitMaterializedSRF(), InitXLogReaderState(), MemoryContextDelete(), MemoryContextReset(), MemoryContextSwitchTo(), pfree(), PG_GETARG_LSN, PG_RETURN_VOID, XLogReaderState::private_data, ReadNextXLogRecord(), ValidateInputLSNs(), xlogreader, XLogReaderFree(), and XLogRecHasAnyBlockRefs.

◆ pg_get_wal_record_info()

Datum pg_get_wal_record_info ( PG_FUNCTION_ARGS  )

Definition at line 413 of file pg_walinspect.c.

414 {
415 #define PG_GET_WAL_RECORD_INFO_COLS 11
416  Datum result;
418  bool nulls[PG_GET_WAL_RECORD_INFO_COLS] = {0};
419  XLogRecPtr lsn;
420  XLogRecPtr curr_lsn;
422  TupleDesc tupdesc;
423  HeapTuple tuple;
424 
425  lsn = PG_GETARG_LSN(0);
426  curr_lsn = GetCurrentLSN();
427 
428  if (lsn > curr_lsn)
429  ereport(ERROR,
430  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
431  errmsg("WAL input LSN must be less than current LSN"),
432  errdetail("Current WAL LSN on the database system is at %X/%X.",
433  LSN_FORMAT_ARGS(curr_lsn))));
434 
435  /* Build a tuple descriptor for our result type. */
436  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
437  elog(ERROR, "return type must be a row type");
438 
440 
442  ereport(ERROR,
443  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
444  errmsg("could not read WAL at %X/%X",
446 
448 
451 
452  tuple = heap_form_tuple(tupdesc, values, nulls);
453  result = HeapTupleGetDatum(tuple);
454 
455  PG_RETURN_DATUM(result);
456 #undef PG_GET_WAL_RECORD_INFO_COLS
457 }
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:276
@ TYPEFUNC_COMPOSITE
Definition: funcapi.h:149
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
Definition: funcapi.h:230
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
#define PG_GET_WAL_RECORD_INFO_COLS
static XLogRecPtr GetCurrentLSN(void)
Definition: pg_walinspect.c:68

References elog(), XLogReaderState::EndRecPtr, ereport, errcode(), errdetail(), errmsg(), ERROR, get_call_result_type(), GetCurrentLSN(), GetWALRecordInfo(), heap_form_tuple(), HeapTupleGetDatum(), InitXLogReaderState(), LSN_FORMAT_ARGS, pfree(), PG_GET_WAL_RECORD_INFO_COLS, PG_GETARG_LSN, PG_RETURN_DATUM, XLogReaderState::private_data, ReadNextXLogRecord(), TYPEFUNC_COMPOSITE, values, xlogreader, and XLogReaderFree().

◆ pg_get_wal_records_info()

Datum pg_get_wal_records_info ( PG_FUNCTION_ARGS  )

Definition at line 542 of file pg_walinspect.c.

543 {
544  XLogRecPtr start_lsn = PG_GETARG_LSN(0);
545  XLogRecPtr end_lsn = PG_GETARG_LSN(1);
546 
547  ValidateInputLSNs(start_lsn, &end_lsn);
548  GetWALRecordsInfo(fcinfo, start_lsn, end_lsn);
549 
550  PG_RETURN_VOID();
551 }
static void GetWALRecordsInfo(FunctionCallInfo fcinfo, XLogRecPtr start_lsn, XLogRecPtr end_lsn)

References GetWALRecordsInfo(), PG_GETARG_LSN, PG_RETURN_VOID, and ValidateInputLSNs().

◆ pg_get_wal_records_info_till_end_of_wal()

Datum pg_get_wal_records_info_till_end_of_wal ( PG_FUNCTION_ARGS  )

Definition at line 771 of file pg_walinspect.c.

772 {
773  XLogRecPtr start_lsn = PG_GETARG_LSN(0);
774  XLogRecPtr end_lsn = GetCurrentLSN();
775 
776  if (start_lsn > end_lsn)
777  ereport(ERROR,
778  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
779  errmsg("WAL start LSN must be less than current LSN"),
780  errdetail("Current WAL LSN on the database system is at %X/%X.",
781  LSN_FORMAT_ARGS(end_lsn))));
782 
783  GetWALRecordsInfo(fcinfo, start_lsn, end_lsn);
784 
785  PG_RETURN_VOID();
786 }

References ereport, errcode(), errdetail(), errmsg(), ERROR, GetCurrentLSN(), GetWALRecordsInfo(), LSN_FORMAT_ARGS, PG_GETARG_LSN, and PG_RETURN_VOID.

◆ pg_get_wal_stats()

Datum pg_get_wal_stats ( PG_FUNCTION_ARGS  )

Definition at line 754 of file pg_walinspect.c.

755 {
756  XLogRecPtr start_lsn = PG_GETARG_LSN(0);
757  XLogRecPtr end_lsn = PG_GETARG_LSN(1);
758  bool stats_per_record = PG_GETARG_BOOL(2);
759 
760  ValidateInputLSNs(start_lsn, &end_lsn);
761  GetWalStats(fcinfo, start_lsn, end_lsn, stats_per_record);
762 
763  PG_RETURN_VOID();
764 }
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
static void GetWalStats(FunctionCallInfo fcinfo, XLogRecPtr start_lsn, XLogRecPtr end_lsn, bool stats_per_record)

References GetWalStats(), PG_GETARG_BOOL, PG_GETARG_LSN, PG_RETURN_VOID, and ValidateInputLSNs().

◆ pg_get_wal_stats_till_end_of_wal()

Datum pg_get_wal_stats_till_end_of_wal ( PG_FUNCTION_ARGS  )

Definition at line 789 of file pg_walinspect.c.

790 {
791  XLogRecPtr start_lsn = PG_GETARG_LSN(0);
792  XLogRecPtr end_lsn = GetCurrentLSN();
793  bool stats_per_record = PG_GETARG_BOOL(1);
794 
795  if (start_lsn > end_lsn)
796  ereport(ERROR,
797  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
798  errmsg("WAL start LSN must be less than current LSN"),
799  errdetail("Current WAL LSN on the database system is at %X/%X.",
800  LSN_FORMAT_ARGS(end_lsn))));
801 
802  GetWalStats(fcinfo, start_lsn, end_lsn, stats_per_record);
803 
804  PG_RETURN_VOID();
805 }

References ereport, errcode(), errdetail(), errmsg(), ERROR, GetCurrentLSN(), GetWalStats(), LSN_FORMAT_ARGS, PG_GETARG_BOOL, PG_GETARG_LSN, and PG_RETURN_VOID.

◆ ReadNextXLogRecord()

static XLogRecord * ReadNextXLogRecord ( XLogReaderState xlogreader)
static

Definition at line 145 of file pg_walinspect.c.

146 {
147  XLogRecord *record;
148  char *errormsg;
149 
150  record = XLogReadRecord(xlogreader, &errormsg);
151 
152  if (record == NULL)
153  {
154  ReadLocalXLogPageNoWaitPrivate *private_data;
155 
156  /* return NULL, if end of WAL is reached */
157  private_data = (ReadLocalXLogPageNoWaitPrivate *)
159 
160  if (private_data->end_of_wal)
161  return NULL;
162 
163  if (errormsg)
164  ereport(ERROR,
166  errmsg("could not read WAL at %X/%X: %s",
167  LSN_FORMAT_ARGS(xlogreader->EndRecPtr), errormsg)));
168  else
169  ereport(ERROR,
171  errmsg("could not read WAL at %X/%X",
173  }
174 
175  return record;
176 }
int errcode_for_file_access(void)
Definition: elog.c:881
XLogRecord * XLogReadRecord(XLogReaderState *state, char **errormsg)
Definition: xlogreader.c:422

References ReadLocalXLogPageNoWaitPrivate::end_of_wal, XLogReaderState::EndRecPtr, ereport, errcode_for_file_access(), errmsg(), ERROR, if(), LSN_FORMAT_ARGS, XLogReaderState::private_data, xlogreader, and XLogReadRecord().

Referenced by GetWALRecordsInfo(), pg_get_wal_block_info(), and pg_get_wal_record_info().

◆ ValidateInputLSNs()

static void ValidateInputLSNs ( XLogRecPtr  start_lsn,
XLogRecPtr end_lsn 
)
static

Definition at line 466 of file pg_walinspect.c.

467 {
468  XLogRecPtr curr_lsn = GetCurrentLSN();
469 
470  if (start_lsn > curr_lsn)
471  ereport(ERROR,
472  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
473  errmsg("WAL start LSN must be less than current LSN"),
474  errdetail("Current WAL LSN on the database system is at %X/%X.",
475  LSN_FORMAT_ARGS(curr_lsn))));
476 
477  if (start_lsn > *end_lsn)
478  ereport(ERROR,
479  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
480  errmsg("WAL start LSN must be less than end LSN")));
481 
482  if (*end_lsn > curr_lsn)
483  *end_lsn = curr_lsn;
484 }

References ereport, errcode(), errdetail(), errmsg(), ERROR, GetCurrentLSN(), and LSN_FORMAT_ARGS.

Referenced by pg_get_wal_block_info(), pg_get_wal_records_info(), and pg_get_wal_stats().

Variable Documentation

◆ PG_MODULE_MAGIC

PG_MODULE_MAGIC

Definition at line 32 of file pg_walinspect.c.