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/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_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_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 bool IsFutureLSN (XLogRecPtr lsn, XLogRecPtr *curr_lsn)
 
static XLogReaderStateInitXLogReaderState (XLogRecPtr lsn)
 
static XLogRecordReadNextXLogRecord (XLogReaderState *xlogreader)
 
static void GetWALRecordInfo (XLogReaderState *record, Datum *values, bool *nulls, uint32 ncols)
 
static XLogRecPtr ValidateInputLSNs (bool till_end_of_wal, XLogRecPtr start_lsn, XLogRecPtr end_lsn)
 
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)
 
Datum pg_get_wal_record_info (PG_FUNCTION_ARGS)
 
Datum pg_get_wal_records_info (PG_FUNCTION_ARGS)
 
Datum pg_get_wal_records_info_till_end_of_wal (PG_FUNCTION_ARGS)
 
Datum pg_get_wal_stats (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_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 402 of file pg_walinspect.c.

408 {
409  double n_pct,
410  rec_len_pct,
411  fpi_len_pct,
412  tot_len_pct;
413  int i = 0;
414 
415  n_pct = 0;
416  if (total_count != 0)
417  n_pct = 100 * (double) n / total_count;
418 
419  rec_len_pct = 0;
420  if (total_rec_len != 0)
421  rec_len_pct = 100 * (double) rec_len / total_rec_len;
422 
423  fpi_len_pct = 0;
424  if (total_fpi_len != 0)
425  fpi_len_pct = 100 * (double) fpi_len / total_fpi_len;
426 
427  tot_len_pct = 0;
428  if (total_len != 0)
429  tot_len_pct = 100 * (double) tot_len / total_len;
430 
432  values[i++] = Int64GetDatum(n);
433  values[i++] = Float8GetDatum(n_pct);
434  values[i++] = Int64GetDatum(rec_len);
435  values[i++] = Float8GetDatum(rec_len_pct);
436  values[i++] = Int64GetDatum(fpi_len);
437  values[i++] = Float8GetDatum(fpi_len_pct);
438  values[i++] = Int64GetDatum(tot_len);
439  values[i++] = Float8GetDatum(tot_len_pct);
440 
441  Assert(i == ncols);
442 }
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define CStringGetTextDatum(s)
Definition: builtins.h:85
const char * name
Definition: encode.c:561
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1683
Datum Float8GetDatum(float8 X)
Definition: fmgr.c:1692
int i
Definition: isn.c:73
Assert(fmt[strlen(fmt) - 1] !='\n')

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

Referenced by GetXLogSummaryStats().

◆ GetWALRecordInfo()

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

Definition at line 179 of file pg_walinspect.c.

181 {
182  const char *id;
183  RmgrData desc;
184  uint32 fpi_len = 0;
185  StringInfoData rec_desc;
186  StringInfoData rec_blk_ref;
187  uint32 main_data_len;
188  int i = 0;
189 
190  desc = GetRmgr(XLogRecGetRmid(record));
191  id = desc.rm_identify(XLogRecGetInfo(record));
192 
193  if (id == NULL)
194  id = psprintf("UNKNOWN (%x)", XLogRecGetInfo(record) & ~XLR_INFO_MASK);
195 
196  initStringInfo(&rec_desc);
197  desc.rm_desc(&rec_desc, record);
198 
199  /* Block references. */
200  initStringInfo(&rec_blk_ref);
201  XLogRecGetBlockRefInfo(record, false, true, &rec_blk_ref, &fpi_len);
202 
203  main_data_len = XLogRecGetDataLen(record);
204 
205  values[i++] = LSNGetDatum(record->ReadRecPtr);
206  values[i++] = LSNGetDatum(record->EndRecPtr);
207  values[i++] = LSNGetDatum(XLogRecGetPrev(record));
209  values[i++] = CStringGetTextDatum(desc.rm_name);
210  values[i++] = CStringGetTextDatum(id);
212  values[i++] = UInt32GetDatum(main_data_len);
213  values[i++] = UInt32GetDatum(fpi_len);
214  values[i++] = CStringGetTextDatum(rec_desc.data);
215  values[i++] = CStringGetTextDatum(rec_blk_ref.data);
216 
217  Assert(i == ncols);
218 }
unsigned int uint32
Definition: c.h:442
static Datum LSNGetDatum(XLogRecPtr X)
Definition: pg_lsn.h:28
static Datum TransactionIdGetDatum(TransactionId X)
Definition: postgres.h:620
static Datum UInt32GetDatum(uint32 X)
Definition: postgres.h:580
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
XLogRecPtr ReadRecPtr
Definition: xlogreader.h:206
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:417
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:411
#define XLogRecGetRmid(decoder)
Definition: xlogreader.h:412
#define XLogRecGetTotalLen(decoder)
Definition: xlogreader.h:409
#define XLogRecGetXid(decoder)
Definition: xlogreader.h:413
#define XLogRecGetPrev(decoder)
Definition: xlogreader.h:410
#define XLR_INFO_MASK
Definition: xlogrecord.h:62

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

Referenced by pg_get_wal_record_info().

◆ GetWALRecordsInfo()

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

Definition at line 324 of file pg_walinspect.c.

326 {
327 #define PG_GET_WAL_RECORDS_INFO_COLS 11
329  ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
331  bool nulls[PG_GET_WAL_RECORDS_INFO_COLS] = {0};
332 
333  InitMaterializedSRF(fcinfo, 0);
334 
335  xlogreader = InitXLogReaderState(start_lsn);
336 
337  while (ReadNextXLogRecord(xlogreader) &&
338  xlogreader->EndRecPtr <= end_lsn)
339  {
342 
343  tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
344  values, nulls);
345 
347  }
348 
351 
352 #undef PG_GET_WAL_RECORDS_INFO_COLS
353 }
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition: funcapi.c:76
void pfree(void *pointer)
Definition: mcxt.c:1306
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121
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:87
uintptr_t Datum
Definition: postgres.h:412
fmNodePtr resultinfo
Definition: fmgr.h:89
void * private_data
Definition: xlogreader.h:196
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, Datum *values, bool *isnull)
Definition: tuplestore.c:750
void XLogReaderFree(XLogReaderState *state)
Definition: xlogreader.c:170
static XLogReaderState * xlogreader
Definition: xlogrecovery.c:188

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

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 541 of file pg_walinspect.c.

543 {
544 #define PG_GET_WAL_STATS_COLS 9
546  XLogStats stats = {0};
547  ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
549  bool nulls[PG_GET_WAL_STATS_COLS] = {0};
550 
551  InitMaterializedSRF(fcinfo, 0);
552 
553  xlogreader = InitXLogReaderState(start_lsn);
554 
555  while (ReadNextXLogRecord(xlogreader) &&
556  xlogreader->EndRecPtr <= end_lsn)
557  {
558  XLogRecStoreStats(&stats, xlogreader);
559 
561  }
562 
565 
566  GetXLogSummaryStats(&stats, rsinfo, values, nulls,
568  stats_per_record);
569 
570 #undef PG_GET_WAL_STATS_COLS
571 }
#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 448 of file pg_walinspect.c.

451 {
452  uint64 total_count = 0;
453  uint64 total_rec_len = 0;
454  uint64 total_fpi_len = 0;
455  uint64 total_len = 0;
456  int ri;
457 
458  /*
459  * Each row shows its percentages of the total, so make a first pass to
460  * calculate column totals.
461  */
462  for (ri = 0; ri <= RM_MAX_ID; ri++)
463  {
464  if (!RmgrIdIsValid(ri))
465  continue;
466 
467  total_count += stats->rmgr_stats[ri].count;
468  total_rec_len += stats->rmgr_stats[ri].rec_len;
469  total_fpi_len += stats->rmgr_stats[ri].fpi_len;
470  }
471  total_len = total_rec_len + total_fpi_len;
472 
473  for (ri = 0; ri <= RM_MAX_ID; ri++)
474  {
475  uint64 count;
476  uint64 rec_len;
477  uint64 fpi_len;
478  uint64 tot_len;
479  RmgrData desc;
480 
481  if (!RmgrIdIsValid(ri))
482  continue;
483 
484  if (!RmgrIdExists(ri))
485  continue;
486 
487  desc = GetRmgr(ri);
488 
489  if (stats_per_record)
490  {
491  int rj;
492 
493  for (rj = 0; rj < MAX_XLINFO_TYPES; rj++)
494  {
495  const char *id;
496 
497  count = stats->record_stats[ri][rj].count;
498  rec_len = stats->record_stats[ri][rj].rec_len;
499  fpi_len = stats->record_stats[ri][rj].fpi_len;
500  tot_len = rec_len + fpi_len;
501 
502  /* Skip undefined combinations and ones that didn't occur */
503  if (count == 0)
504  continue;
505 
506  /* the upper four bits in xl_info are the rmgr's */
507  id = desc.rm_identify(rj << 4);
508  if (id == NULL)
509  id = psprintf("UNKNOWN (%x)", rj << 4);
510 
511  FillXLogStatsRow(psprintf("%s/%s", desc.rm_name, id), count,
512  total_count, rec_len, total_rec_len, fpi_len,
513  total_fpi_len, tot_len, total_len,
514  values, nulls, ncols);
515 
516  tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
517  values, nulls);
518  }
519  }
520  else
521  {
522  count = stats->rmgr_stats[ri].count;
523  rec_len = stats->rmgr_stats[ri].rec_len;
524  fpi_len = stats->rmgr_stats[ri].fpi_len;
525  tot_len = rec_len + fpi_len;
526 
527  FillXLogStatsRow(desc.rm_name, count, total_count, rec_len,
528  total_rec_len, fpi_len, total_fpi_len, tot_len,
529  total_len, values, nulls, ncols);
530 
531  tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
532  values, nulls);
533  }
534  }
535 }
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
TupleDesc setDesc
Definition: execnodes.h:332
Tuplestorestate * setResult
Definition: execnodes.h:331
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 XLogRecStats::count, FillXLogStatsRow(), XLogRecStats::fpi_len, GetRmgr(), MAX_XLINFO_TYPES, 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 87 of file pg_walinspect.c.

88 {
90  ReadLocalXLogPageNoWaitPrivate *private_data;
91  XLogRecPtr first_valid_record;
92 
93  /*
94  * Reading WAL below the first page of the first segments isn't allowed.
95  * This is a bootstrap WAL page and the page_read callback fails to read
96  * it.
97  */
98  if (lsn < XLOG_BLCKSZ)
99  ereport(ERROR,
100  (errmsg("could not read WAL at LSN %X/%X",
101  LSN_FORMAT_ARGS(lsn))));
102 
103  private_data = (ReadLocalXLogPageNoWaitPrivate *)
105 
108  .segment_open = &wal_segment_open,
109  .segment_close = &wal_segment_close),
110  private_data);
111 
112  if (xlogreader == NULL)
113  ereport(ERROR,
114  (errcode(ERRCODE_OUT_OF_MEMORY),
115  errmsg("out of memory"),
116  errdetail("Failed while allocating a WAL reading processor.")));
117 
118  /* first find a valid recptr to start from */
119  first_valid_record = XLogFindNextRecord(xlogreader, lsn);
120 
121  if (XLogRecPtrIsInvalid(first_valid_record))
122  ereport(ERROR,
123  (errmsg("could not find a valid record after %X/%X",
124  LSN_FORMAT_ARGS(lsn))));
125 
126  return xlogreader;
127 }
int errdetail(const char *fmt,...)
Definition: elog.c:1039
int errcode(int sqlerrcode)
Definition: elog.c:695
int errmsg(const char *fmt,...)
Definition: elog.c:906
#define ERROR
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:145
void * palloc0(Size size)
Definition: mcxt.c:1230
int wal_segment_size
Definition: xlog.c:146
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
uint64 XLogRecPtr
Definition: xlogdefs.h:21
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:1369
#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 pg_get_wal_record_info().

◆ IsFutureLSN()

static bool IsFutureLSN ( XLogRecPtr  lsn,
XLogRecPtr curr_lsn 
)
static

Definition at line 64 of file pg_walinspect.c.

65 {
66  /*
67  * We determine the current LSN of the server similar to how page_read
68  * callback read_local_xlog_page_no_wait does.
69  */
70  if (!RecoveryInProgress())
71  *curr_lsn = GetFlushRecPtr(NULL);
72  else
73  *curr_lsn = GetXLogReplayRecPtr(NULL);
74 
75  Assert(!XLogRecPtrIsInvalid(*curr_lsn));
76 
77  if (lsn >= *curr_lsn)
78  return true;
79 
80  return false;
81 }
bool RecoveryInProgress(void)
Definition: xlog.c:5912
XLogRecPtr GetFlushRecPtr(TimeLineID *insertTLI)
Definition: xlog.c:6077
XLogRecPtr GetXLogReplayRecPtr(TimeLineID *replayTLI)

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

Referenced by pg_get_wal_record_info(), and ValidateInputLSNs().

◆ PG_FUNCTION_INFO_V1() [1/5]

PG_FUNCTION_INFO_V1 ( pg_get_wal_record_info  )

◆ PG_FUNCTION_INFO_V1() [2/5]

PG_FUNCTION_INFO_V1 ( pg_get_wal_records_info  )

◆ PG_FUNCTION_INFO_V1() [3/5]

PG_FUNCTION_INFO_V1 ( pg_get_wal_records_info_till_end_of_wal  )

◆ PG_FUNCTION_INFO_V1() [4/5]

PG_FUNCTION_INFO_V1 ( pg_get_wal_stats  )

◆ PG_FUNCTION_INFO_V1() [5/5]

PG_FUNCTION_INFO_V1 ( pg_get_wal_stats_till_end_of_wal  )

◆ pg_get_wal_record_info()

Datum pg_get_wal_record_info ( PG_FUNCTION_ARGS  )

Definition at line 227 of file pg_walinspect.c.

228 {
229 #define PG_GET_WAL_RECORD_INFO_COLS 11
230  Datum result;
232  bool nulls[PG_GET_WAL_RECORD_INFO_COLS] = {0};
233  XLogRecPtr lsn;
234  XLogRecPtr curr_lsn;
236  TupleDesc tupdesc;
237  HeapTuple tuple;
238 
239  lsn = PG_GETARG_LSN(0);
240 
241  if (IsFutureLSN(lsn, &curr_lsn))
242  {
243  /*
244  * GetFlushRecPtr or GetXLogReplayRecPtr gives "end+1" LSN of the last
245  * record flushed or replayed respectively. But let's use the LSN up
246  * to "end" in user facing message.
247  */
248  ereport(ERROR,
249  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
250  errmsg("cannot accept future input LSN"),
251  errdetail("Last known WAL LSN on the database system is at %X/%X.",
252  LSN_FORMAT_ARGS(curr_lsn))));
253  }
254 
255  /* Build a tuple descriptor for our result type. */
256  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
257  elog(ERROR, "return type must be a row type");
258 
260 
262  ereport(ERROR,
263  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
264  errmsg("could not read WAL at %X/%X",
266 
268 
271 
272  tuple = heap_form_tuple(tupdesc, values, nulls);
273  result = HeapTupleGetDatum(tuple);
274 
275  PG_RETURN_DATUM(result);
276 #undef PG_GET_WAL_RECORD_INFO_COLS
277 }
#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_GETARG_LSN(n)
Definition: pg_lsn.h:33
#define PG_GET_WAL_RECORD_INFO_COLS
static bool IsFutureLSN(XLogRecPtr lsn, XLogRecPtr *curr_lsn)
Definition: pg_walinspect.c:64

References elog(), XLogReaderState::EndRecPtr, ereport, errcode(), errdetail(), errmsg(), ERROR, get_call_result_type(), GetWALRecordInfo(), heap_form_tuple(), HeapTupleGetDatum(), InitXLogReaderState(), IsFutureLSN(), 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 362 of file pg_walinspect.c.

363 {
364  XLogRecPtr start_lsn;
365  XLogRecPtr end_lsn;
366 
367  start_lsn = PG_GETARG_LSN(0);
368  end_lsn = PG_GETARG_LSN(1);
369 
370  end_lsn = ValidateInputLSNs(false, start_lsn, end_lsn);
371 
372  GetWALRecordsInfo(fcinfo, start_lsn, end_lsn);
373 
374  PG_RETURN_VOID();
375 }
#define PG_RETURN_VOID()
Definition: fmgr.h:349
static void GetWALRecordsInfo(FunctionCallInfo fcinfo, XLogRecPtr start_lsn, XLogRecPtr end_lsn)
static XLogRecPtr ValidateInputLSNs(bool till_end_of_wal, 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 384 of file pg_walinspect.c.

385 {
386  XLogRecPtr start_lsn;
387  XLogRecPtr end_lsn = InvalidXLogRecPtr;
388 
389  start_lsn = PG_GETARG_LSN(0);
390 
391  end_lsn = ValidateInputLSNs(true, start_lsn, end_lsn);
392 
393  GetWALRecordsInfo(fcinfo, start_lsn, end_lsn);
394 
395  PG_RETURN_VOID();
396 }
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28

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

◆ pg_get_wal_stats()

Datum pg_get_wal_stats ( PG_FUNCTION_ARGS  )

Definition at line 580 of file pg_walinspect.c.

581 {
582  XLogRecPtr start_lsn;
583  XLogRecPtr end_lsn;
584  bool stats_per_record;
585 
586  start_lsn = PG_GETARG_LSN(0);
587  end_lsn = PG_GETARG_LSN(1);
588  stats_per_record = PG_GETARG_BOOL(2);
589 
590  end_lsn = ValidateInputLSNs(false, start_lsn, end_lsn);
591 
592  GetWalStats(fcinfo, start_lsn, end_lsn, stats_per_record);
593 
594  PG_RETURN_VOID();
595 }
#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 604 of file pg_walinspect.c.

605 {
606  XLogRecPtr start_lsn;
607  XLogRecPtr end_lsn = InvalidXLogRecPtr;
608  bool stats_per_record;
609 
610  start_lsn = PG_GETARG_LSN(0);
611  stats_per_record = PG_GETARG_BOOL(1);
612 
613  end_lsn = ValidateInputLSNs(true, start_lsn, end_lsn);
614 
615  GetWalStats(fcinfo, start_lsn, end_lsn, stats_per_record);
616 
617  PG_RETURN_VOID();
618 }

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

◆ ReadNextXLogRecord()

static XLogRecord * ReadNextXLogRecord ( XLogReaderState xlogreader)
static

Definition at line 142 of file pg_walinspect.c.

143 {
144  XLogRecord *record;
145  char *errormsg;
146 
147  record = XLogReadRecord(xlogreader, &errormsg);
148 
149  if (record == NULL)
150  {
151  ReadLocalXLogPageNoWaitPrivate *private_data;
152 
153  /* return NULL, if end of WAL is reached */
154  private_data = (ReadLocalXLogPageNoWaitPrivate *)
156 
157  if (private_data->end_of_wal)
158  return NULL;
159 
160  if (errormsg)
161  ereport(ERROR,
163  errmsg("could not read WAL at %X/%X: %s",
164  LSN_FORMAT_ARGS(xlogreader->EndRecPtr), errormsg)));
165  else
166  ereport(ERROR,
168  errmsg("could not read WAL at %X/%X",
170  }
171 
172  return record;
173 }
int errcode_for_file_access(void)
Definition: elog.c:718
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
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 pg_get_wal_record_info().

◆ ValidateInputLSNs()

static XLogRecPtr ValidateInputLSNs ( bool  till_end_of_wal,
XLogRecPtr  start_lsn,
XLogRecPtr  end_lsn 
)
static

Definition at line 283 of file pg_walinspect.c.

285 {
286  XLogRecPtr curr_lsn;
287 
288  if (IsFutureLSN(start_lsn, &curr_lsn))
289  {
290  /*
291  * GetFlushRecPtr or GetXLogReplayRecPtr gives "end+1" LSN of the last
292  * record flushed or replayed respectively. But let's use the LSN up
293  * to "end" in user facing message.
294  */
295  ereport(ERROR,
296  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
297  errmsg("cannot accept future start LSN"),
298  errdetail("Last known WAL LSN on the database system is at %X/%X.",
299  LSN_FORMAT_ARGS(curr_lsn))));
300  }
301 
302  if (till_end_of_wal)
303  end_lsn = curr_lsn;
304 
305  if (end_lsn > curr_lsn)
306  ereport(ERROR,
307  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
308  errmsg("cannot accept future end LSN"),
309  errdetail("Last known WAL LSN on the database system is at %X/%X.",
310  LSN_FORMAT_ARGS(curr_lsn))));
311 
312  if (start_lsn >= end_lsn)
313  ereport(ERROR,
314  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
315  errmsg("WAL start LSN must be less than end LSN")));
316 
317  return end_lsn;
318 }

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

Referenced by pg_get_wal_records_info(), pg_get_wal_records_info_till_end_of_wal(), pg_get_wal_stats(), and pg_get_wal_stats_till_end_of_wal().

Variable Documentation

◆ PG_MODULE_MAGIC

PG_MODULE_MAGIC

Definition at line 31 of file pg_walinspect.c.