PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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   20
 
#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, bool show_data)
 
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   20

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

610{
611 double n_pct,
612 rec_len_pct,
613 fpi_len_pct,
614 tot_len_pct;
615 int i = 0;
616
617 n_pct = 0;
618 if (total_count != 0)
619 n_pct = 100 * (double) n / total_count;
620
621 rec_len_pct = 0;
622 if (total_rec_len != 0)
623 rec_len_pct = 100 * (double) rec_len / total_rec_len;
624
625 fpi_len_pct = 0;
626 if (total_fpi_len != 0)
627 fpi_len_pct = 100 * (double) fpi_len / total_fpi_len;
628
629 tot_len_pct = 0;
630 if (total_len != 0)
631 tot_len_pct = 100 * (double) tot_len / total_len;
632
634 values[i++] = Int64GetDatum(n);
635 values[i++] = Float8GetDatum(n_pct);
636 values[i++] = Int64GetDatum(rec_len);
637 values[i++] = Float8GetDatum(rec_len_pct);
638 values[i++] = Int64GetDatum(fpi_len);
639 values[i++] = Float8GetDatum(fpi_len_pct);
640 values[i++] = Int64GetDatum(tot_len);
641 values[i++] = Float8GetDatum(tot_len_pct);
642
643 Assert(i == ncols);
644}
static Datum values[MAXATTR]
Definition: bootstrap.c:151
#define CStringGetTextDatum(s)
Definition: builtins.h:97
#define Assert(condition)
Definition: c.h:812
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1807
Datum Float8GetDatum(float8 X)
Definition: fmgr.c:1816
int i
Definition: isn.c:72
const char * name

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

Referenced by GetXLogSummaryStats().

◆ GetCurrentLSN()

static XLogRecPtr GetCurrentLSN ( void  )
static

Definition at line 69 of file pg_walinspect.c.

70{
71 XLogRecPtr curr_lsn;
72
73 /*
74 * We determine the current LSN of the server similar to how page_read
75 * callback read_local_xlog_page_no_wait does.
76 */
77 if (!RecoveryInProgress())
78 curr_lsn = GetFlushRecPtr(NULL);
79 else
80 curr_lsn = GetXLogReplayRecPtr(NULL);
81
82 Assert(!XLogRecPtrIsInvalid(curr_lsn));
83
84 return curr_lsn;
85}
bool RecoveryInProgress(void)
Definition: xlog.c:6334
XLogRecPtr GetFlushRecPtr(TimeLineID *insertTLI)
Definition: xlog.c:6499
#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,
bool  show_data 
)
static

Definition at line 249 of file pg_walinspect.c.

251{
252#define PG_GET_WAL_BLOCK_INFO_COLS 20
253 int block_id;
254 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
255 RmgrData desc;
256 const char *record_type;
257 StringInfoData rec_desc;
258
260
261 desc = GetRmgr(XLogRecGetRmid(record));
262 record_type = desc.rm_identify(XLogRecGetInfo(record));
263
264 if (record_type == NULL)
265 record_type = psprintf("UNKNOWN (%x)",
266 XLogRecGetInfo(record) & ~XLR_INFO_MASK);
267
268 initStringInfo(&rec_desc);
269 desc.rm_desc(&rec_desc, record);
270
271 for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++)
272 {
273 DecodedBkpBlock *blk;
274 BlockNumber blkno;
275 RelFileLocator rnode;
276 ForkNumber forknum;
278 bool nulls[PG_GET_WAL_BLOCK_INFO_COLS] = {0};
279 uint32 block_data_len = 0,
280 block_fpi_len = 0;
281 ArrayType *block_fpi_info = NULL;
282 int i = 0;
283
284 if (!XLogRecHasBlockRef(record, block_id))
285 continue;
286
287 blk = XLogRecGetBlock(record, block_id);
288
289 (void) XLogRecGetBlockTagExtended(record, block_id,
290 &rnode, &forknum, &blkno, NULL);
291
292 /* Save block_data_len */
293 if (blk->has_data)
294 block_data_len = blk->data_len;
295
296 if (blk->has_image)
297 {
298 /* Block reference has an FPI, so prepare relevant output */
299 int bitcnt;
300 int cnt = 0;
301 Datum *flags;
302
303 /* Save block_fpi_len */
304 block_fpi_len = blk->bimg_len;
305
306 /* Construct and save block_fpi_info */
307 bitcnt = pg_popcount((const char *) &blk->bimg_info,
308 sizeof(uint8));
309 flags = (Datum *) palloc0(sizeof(Datum) * bitcnt);
310 if ((blk->bimg_info & BKPIMAGE_HAS_HOLE) != 0)
311 flags[cnt++] = CStringGetTextDatum("HAS_HOLE");
312 if (blk->apply_image)
313 flags[cnt++] = CStringGetTextDatum("APPLY");
314 if ((blk->bimg_info & BKPIMAGE_COMPRESS_PGLZ) != 0)
315 flags[cnt++] = CStringGetTextDatum("COMPRESS_PGLZ");
316 if ((blk->bimg_info & BKPIMAGE_COMPRESS_LZ4) != 0)
317 flags[cnt++] = CStringGetTextDatum("COMPRESS_LZ4");
318 if ((blk->bimg_info & BKPIMAGE_COMPRESS_ZSTD) != 0)
319 flags[cnt++] = CStringGetTextDatum("COMPRESS_ZSTD");
320
321 Assert(cnt <= bitcnt);
322 block_fpi_info = construct_array_builtin(flags, cnt, TEXTOID);
323 }
324
325 /* start_lsn, end_lsn, prev_lsn, and blockid outputs */
326 values[i++] = LSNGetDatum(record->ReadRecPtr);
327 values[i++] = LSNGetDatum(record->EndRecPtr);
328 values[i++] = LSNGetDatum(XLogRecGetPrev(record));
329 values[i++] = Int16GetDatum(block_id);
330
331 /* relfile and block related outputs */
335 values[i++] = Int16GetDatum(forknum);
336 values[i++] = Int64GetDatum((int64) blkno);
337
338 /* xid, resource_manager, and record_type outputs */
340 values[i++] = CStringGetTextDatum(desc.rm_name);
341 values[i++] = CStringGetTextDatum(record_type);
342
343 /*
344 * record_length, main_data_length, block_data_len, and
345 * block_fpi_length outputs
346 */
349 values[i++] = UInt32GetDatum(block_data_len);
350 values[i++] = UInt32GetDatum(block_fpi_len);
351
352 /* block_fpi_info (text array) output */
353 if (block_fpi_info)
354 values[i++] = PointerGetDatum(block_fpi_info);
355 else
356 nulls[i++] = true;
357
358 /* description output (describes WAL record) */
359 if (rec_desc.len > 0)
360 values[i++] = CStringGetTextDatum(rec_desc.data);
361 else
362 nulls[i++] = true;
363
364 /* block_data output */
365 if (blk->has_data && show_data)
366 {
367 bytea *block_data;
368
369 block_data = (bytea *) palloc(block_data_len + VARHDRSZ);
370 SET_VARSIZE(block_data, block_data_len + VARHDRSZ);
371 memcpy(VARDATA(block_data), blk->data, block_data_len);
372 values[i++] = PointerGetDatum(block_data);
373 }
374 else
375 nulls[i++] = true;
376
377 /* block_fpi_data output */
378 if (blk->has_image && show_data)
379 {
381 Page page;
382 bytea *block_fpi_data;
383
384 page = (Page) buf.data;
385 if (!RestoreBlockImage(record, block_id, page))
387 (errcode(ERRCODE_INTERNAL_ERROR),
388 errmsg_internal("%s", record->errormsg_buf)));
389
390 block_fpi_data = (bytea *) palloc(BLCKSZ + VARHDRSZ);
391 SET_VARSIZE(block_fpi_data, BLCKSZ + VARHDRSZ);
392 memcpy(VARDATA(block_fpi_data), page, BLCKSZ);
393 values[i++] = PointerGetDatum(block_fpi_data);
394 }
395 else
396 nulls[i++] = true;
397
399
400 /* Store a tuple for this block reference */
401 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
402 values, nulls);
403 }
404
405#undef PG_GET_WAL_BLOCK_INFO_COLS
406}
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
Definition: arrayfuncs.c:3381
uint32 BlockNumber
Definition: block.h:31
Pointer Page
Definition: bufpage.h:81
uint8_t uint8
Definition: c.h:483
#define VARHDRSZ
Definition: c.h:646
int64_t int64
Definition: c.h:482
uint32_t uint32
Definition: c.h:485
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1157
int errcode(int sqlerrcode)
Definition: elog.c:853
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:76
void * palloc0(Size size)
Definition: mcxt.c:1347
void * palloc(Size size)
Definition: mcxt.c:1317
static uint64 pg_popcount(const char *buf, int bytes)
Definition: pg_bitutils.h:339
static Datum LSNGetDatum(XLogRecPtr X)
Definition: pg_lsn.h:28
static char * buf
Definition: pg_test_fsync.c:72
#define PG_GET_WAL_BLOCK_INFO_COLS
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
static Datum TransactionIdGetDatum(TransactionId X)
Definition: postgres.h:272
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
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43
ForkNumber
Definition: relpath.h:56
void initStringInfo(StringInfo str)
Definition: stringinfo.c:56
RelFileLocator rlocator
Definition: xlogreader.h:125
fmNodePtr resultinfo
Definition: fmgr.h:89
RelFileNumber relNumber
TupleDesc setDesc
Definition: execnodes.h:343
Tuplestorestate * setResult
Definition: execnodes.h:342
char * errormsg_buf
Definition: xlogreader.h:311
XLogRecPtr EndRecPtr
Definition: xlogreader.h:207
XLogRecPtr ReadRecPtr
Definition: xlogreader.h:206
Definition: c.h:641
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition: tuplestore.c:784
#define VARDATA(PTR)
Definition: varatt.h:278
#define SET_VARSIZE(PTR, len)
Definition: varatt.h:305
static RmgrData GetRmgr(RmgrId rmid)
bool XLogRecGetBlockTagExtended(XLogReaderState *record, uint8 block_id, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum, Buffer *prefetch_buffer)
Definition: xlogreader.c:1997
bool RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
Definition: xlogreader.c:2056
#define XLogRecGetDataLen(decoder)
Definition: xlogreader.h:416
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:410
#define XLogRecGetRmid(decoder)
Definition: xlogreader.h:411
#define XLogRecGetTotalLen(decoder)
Definition: xlogreader.h:408
#define XLogRecGetXid(decoder)
Definition: xlogreader.h:412
#define XLogRecGetBlock(decoder, i)
Definition: xlogreader.h:419
#define XLogRecMaxBlockId(decoder)
Definition: xlogreader.h:418
#define XLogRecHasBlockRef(decoder, block_id)
Definition: xlogreader.h:420
#define XLogRecGetPrev(decoder)
Definition: xlogreader.h:409
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:417
#define BKPIMAGE_COMPRESS_ZSTD
Definition: xlogrecord.h:162
#define BKPIMAGE_HAS_HOLE
Definition: xlogrecord.h:157
#define BKPIMAGE_COMPRESS_LZ4
Definition: xlogrecord.h:161
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
#define BKPIMAGE_COMPRESS_PGLZ
Definition: xlogrecord.h:160

References 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, XLogReaderState::EndRecPtr, ereport, errcode(), errmsg_internal(), ERROR, XLogReaderState::errormsg_buf, GetRmgr(), DecodedBkpBlock::has_data, DecodedBkpBlock::has_image, i, if(), initStringInfo(), Int16GetDatum(), Int64GetDatum(), LSNGetDatum(), ObjectIdGetDatum(), palloc(), palloc0(), PG_GET_WAL_BLOCK_INFO_COLS, pg_popcount(), PointerGetDatum(), psprintf(), XLogReaderState::ReadRecPtr, RelFileLocator::relNumber, RestoreBlockImage(), FunctionCallInfoBaseData::resultinfo, DecodedBkpBlock::rlocator, SET_VARSIZE, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, RelFileLocator::spcOid, TransactionIdGetDatum(), tuplestore_putvalues(), UInt32GetDatum(), values, VARDATA, VARHDRSZ, XLogRecGetBlock, XLogRecGetBlockTagExtended(), XLogRecGetDataLen, XLogRecGetInfo, XLogRecGetPrev, XLogRecGetRmid, XLogRecGetTotalLen, XLogRecGetXid, XLogRecHasAnyBlockRefs, XLogRecHasBlockRef, XLogRecMaxBlockId, and XLR_INFO_MASK.

Referenced by pg_get_wal_block_info().

◆ GetWALRecordInfo()

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

Definition at line 189 of file pg_walinspect.c.

191{
192 const char *record_type;
193 RmgrData desc;
194 uint32 fpi_len = 0;
195 StringInfoData rec_desc;
196 StringInfoData rec_blk_ref;
197 int i = 0;
198
199 desc = GetRmgr(XLogRecGetRmid(record));
200 record_type = desc.rm_identify(XLogRecGetInfo(record));
201
202 if (record_type == NULL)
203 record_type = psprintf("UNKNOWN (%x)", XLogRecGetInfo(record) & ~XLR_INFO_MASK);
204
205 initStringInfo(&rec_desc);
206 desc.rm_desc(&rec_desc, record);
207
208 if (XLogRecHasAnyBlockRefs(record))
209 {
210 initStringInfo(&rec_blk_ref);
211 XLogRecGetBlockRefInfo(record, false, true, &rec_blk_ref, &fpi_len);
212 }
213
214 values[i++] = LSNGetDatum(record->ReadRecPtr);
215 values[i++] = LSNGetDatum(record->EndRecPtr);
216 values[i++] = LSNGetDatum(XLogRecGetPrev(record));
219 values[i++] = CStringGetTextDatum(record_type);
222 values[i++] = UInt32GetDatum(fpi_len);
223
224 if (rec_desc.len > 0)
225 values[i++] = CStringGetTextDatum(rec_desc.data);
226 else
227 nulls[i++] = true;
228
229 if (XLogRecHasAnyBlockRefs(record))
230 values[i++] = CStringGetTextDatum(rec_blk_ref.data);
231 else
232 nulls[i++] = true;
233
234 Assert(i == ncols);
235}
const char *(* rm_identify)(uint8 info)
const char * rm_name
void(* rm_desc)(StringInfo buf, XLogReaderState *record)
void XLogRecGetBlockRefInfo(XLogReaderState *record, bool pretty, bool detailed_format, StringInfo buf, uint32 *fpi_len)
Definition: xlogdesc.c:231

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

539{
540#define PG_GET_WAL_RECORDS_INFO_COLS 11
542 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
543 MemoryContext old_cxt;
544 MemoryContext tmp_cxt;
545
546 Assert(start_lsn <= end_lsn);
547
548 InitMaterializedSRF(fcinfo, 0);
549
550 xlogreader = InitXLogReaderState(start_lsn);
551
553 "GetWALRecordsInfo temporary cxt",
555
557 xlogreader->EndRecPtr <= end_lsn)
558 {
560 bool nulls[PG_GET_WAL_RECORDS_INFO_COLS] = {0};
561
562 /* Use the tmp context so we can clean up after each tuple is done */
563 old_cxt = MemoryContextSwitchTo(tmp_cxt);
564
567
568 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
569 values, nulls);
570
571 /* clean up and switch back */
572 MemoryContextSwitchTo(old_cxt);
573 MemoryContextReset(tmp_cxt);
574
576 }
577
578 MemoryContextDelete(tmp_cxt);
581
582#undef PG_GET_WAL_RECORDS_INFO_COLS
583}
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition: funcapi.c:76
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:383
void pfree(void *pointer)
Definition: mcxt.c:1521
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:454
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
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:91
void * private_data
Definition: xlogreader.h:196
void XLogReaderFree(XLogReaderState *state)
Definition: xlogreader.c:161
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 763 of file pg_walinspect.c.

765{
766#define PG_GET_WAL_STATS_COLS 9
768 XLogStats stats = {0};
769 ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
771 bool nulls[PG_GET_WAL_STATS_COLS] = {0};
772
773 Assert(start_lsn <= end_lsn);
774
775 InitMaterializedSRF(fcinfo, 0);
776
777 xlogreader = InitXLogReaderState(start_lsn);
778
780 xlogreader->EndRecPtr <= end_lsn)
781 {
783
785 }
786
789
790 GetXLogSummaryStats(&stats, rsinfo, values, nulls,
792 stats_per_record);
793
794#undef PG_GET_WAL_STATS_COLS
795}
#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 650 of file pg_walinspect.c.

653{
654 MemoryContext old_cxt;
655 MemoryContext tmp_cxt;
656 uint64 total_count = 0;
657 uint64 total_rec_len = 0;
658 uint64 total_fpi_len = 0;
659 uint64 total_len = 0;
660 int ri;
661
662 /*
663 * Each row shows its percentages of the total, so make a first pass to
664 * calculate column totals.
665 */
666 for (ri = 0; ri <= RM_MAX_ID; ri++)
667 {
668 if (!RmgrIdIsValid(ri))
669 continue;
670
671 total_count += stats->rmgr_stats[ri].count;
672 total_rec_len += stats->rmgr_stats[ri].rec_len;
673 total_fpi_len += stats->rmgr_stats[ri].fpi_len;
674 }
675 total_len = total_rec_len + total_fpi_len;
676
678 "GetXLogSummaryStats temporary cxt",
680
681 for (ri = 0; ri <= RM_MAX_ID; ri++)
682 {
683 uint64 count;
684 uint64 rec_len;
685 uint64 fpi_len;
686 uint64 tot_len;
687 RmgrData desc;
688
689 if (!RmgrIdIsValid(ri))
690 continue;
691
692 if (!RmgrIdExists(ri))
693 continue;
694
695 desc = GetRmgr(ri);
696
697 if (stats_per_record)
698 {
699 int rj;
700
701 for (rj = 0; rj < MAX_XLINFO_TYPES; rj++)
702 {
703 const char *id;
704
705 count = stats->record_stats[ri][rj].count;
706 rec_len = stats->record_stats[ri][rj].rec_len;
707 fpi_len = stats->record_stats[ri][rj].fpi_len;
708 tot_len = rec_len + fpi_len;
709
710 /* Skip undefined combinations and ones that didn't occur */
711 if (count == 0)
712 continue;
713
714 old_cxt = MemoryContextSwitchTo(tmp_cxt);
715
716 /* the upper four bits in xl_info are the rmgr's */
717 id = desc.rm_identify(rj << 4);
718 if (id == NULL)
719 id = psprintf("UNKNOWN (%x)", rj << 4);
720
721 FillXLogStatsRow(psprintf("%s/%s", desc.rm_name, id), count,
722 total_count, rec_len, total_rec_len, fpi_len,
723 total_fpi_len, tot_len, total_len,
724 values, nulls, ncols);
725
726 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
727 values, nulls);
728
729 /* clean up and switch back */
730 MemoryContextSwitchTo(old_cxt);
731 MemoryContextReset(tmp_cxt);
732 }
733 }
734 else
735 {
736 count = stats->rmgr_stats[ri].count;
737 rec_len = stats->rmgr_stats[ri].rec_len;
738 fpi_len = stats->rmgr_stats[ri].fpi_len;
739 tot_len = rec_len + fpi_len;
740
741 old_cxt = MemoryContextSwitchTo(tmp_cxt);
742
743 FillXLogStatsRow(desc.rm_name, count, total_count, rec_len,
744 total_rec_len, fpi_len, total_fpi_len, tot_len,
745 total_len, values, nulls, ncols);
746
747 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
748 values, nulls);
749
750 /* clean up and switch back */
751 MemoryContextSwitchTo(old_cxt);
752 MemoryContextReset(tmp_cxt);
753 }
754 }
755
756 MemoryContextDelete(tmp_cxt);
757}
uint64_t uint64
Definition: c.h:486
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 91 of file pg_walinspect.c.

92{
95 XLogRecPtr first_valid_record;
96
97 /*
98 * Reading WAL below the first page of the first segments isn't allowed.
99 * This is a bootstrap WAL page and the page_read callback fails to read
100 * it.
101 */
102 if (lsn < XLOG_BLCKSZ)
104 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
105 errmsg("could not read WAL at LSN %X/%X",
106 LSN_FORMAT_ARGS(lsn))));
107
108 private_data = (ReadLocalXLogPageNoWaitPrivate *)
110
113 .segment_open = &wal_segment_open,
114 .segment_close = &wal_segment_close),
115 private_data);
116
117 if (xlogreader == NULL)
119 (errcode(ERRCODE_OUT_OF_MEMORY),
120 errmsg("out of memory"),
121 errdetail("Failed while allocating a WAL reading processor.")));
122
123 /* first find a valid recptr to start from */
124 first_valid_record = XLogFindNextRecord(xlogreader, lsn);
125
126 if (XLogRecPtrIsInvalid(first_valid_record))
128 (errmsg("could not find a valid record after %X/%X",
129 LSN_FORMAT_ARGS(lsn))));
130
131 return xlogreader;
132}
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errmsg(const char *fmt,...)
Definition: elog.c:1070
int wal_segment_size
Definition: xlog.c:143
#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:106
XLogRecPtr XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr)
Definition: xlogreader.c:1383
#define XL_ROUTINE(...)
Definition: xlogreader.h:117
void wal_segment_close(XLogReaderState *state)
Definition: xlogutils.c:842
void wal_segment_open(XLogReaderState *state, XLogSegNo nextSegNo, TimeLineID *tli_p)
Definition: xlogutils.c:817
int read_local_xlog_page_no_wait(XLogReaderState *state, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *cur_page)
Definition: xlogutils.c:873

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

413{
414 XLogRecPtr start_lsn = PG_GETARG_LSN(0);
415 XLogRecPtr end_lsn = PG_GETARG_LSN(1);
416 bool show_data = PG_GETARG_BOOL(2);
418 MemoryContext old_cxt;
419 MemoryContext tmp_cxt;
420
421 ValidateInputLSNs(start_lsn, &end_lsn);
422
423 InitMaterializedSRF(fcinfo, 0);
424
425 xlogreader = InitXLogReaderState(start_lsn);
426
428 "pg_get_wal_block_info temporary cxt",
430
432 xlogreader->EndRecPtr <= end_lsn)
433 {
435
437 continue;
438
439 /* Use the tmp context so we can clean up after each tuple is done */
440 old_cxt = MemoryContextSwitchTo(tmp_cxt);
441
442 GetWALBlockInfo(fcinfo, xlogreader, show_data);
443
444 /* clean up and switch back */
445 MemoryContextSwitchTo(old_cxt);
446 MemoryContextReset(tmp_cxt);
447 }
448
449 MemoryContextDelete(tmp_cxt);
452
454}
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define PG_GETARG_LSN(n)
Definition: pg_lsn.h:33
static void GetWALBlockInfo(FunctionCallInfo fcinfo, XLogReaderState *record, bool show_data)
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_BOOL, 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 460 of file pg_walinspect.c.

461{
462#define PG_GET_WAL_RECORD_INFO_COLS 11
463 Datum result;
465 bool nulls[PG_GET_WAL_RECORD_INFO_COLS] = {0};
466 XLogRecPtr lsn;
467 XLogRecPtr curr_lsn;
469 TupleDesc tupdesc;
470 HeapTuple tuple;
471
472 lsn = PG_GETARG_LSN(0);
473 curr_lsn = GetCurrentLSN();
474
475 if (lsn > curr_lsn)
477 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
478 errmsg("WAL input LSN must be less than current LSN"),
479 errdetail("Current WAL LSN on the database system is at %X/%X.",
480 LSN_FORMAT_ARGS(curr_lsn))));
481
482 /* Build a tuple descriptor for our result type. */
483 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
484 elog(ERROR, "return type must be a row type");
485
487
490 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
491 errmsg("could not read WAL at %X/%X",
493
495
498
499 tuple = heap_form_tuple(tupdesc, values, nulls);
500 result = HeapTupleGetDatum(tuple);
501
502 PG_RETURN_DATUM(result);
503#undef PG_GET_WAL_RECORD_INFO_COLS
504}
#define elog(elevel,...)
Definition: elog.h:225
#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, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1117
#define PG_GET_WAL_RECORD_INFO_COLS
static XLogRecPtr GetCurrentLSN(void)
Definition: pg_walinspect.c:69

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

590{
591 XLogRecPtr start_lsn = PG_GETARG_LSN(0);
592 XLogRecPtr end_lsn = PG_GETARG_LSN(1);
593
594 ValidateInputLSNs(start_lsn, &end_lsn);
595 GetWALRecordsInfo(fcinfo, start_lsn, end_lsn);
596
598}
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 818 of file pg_walinspect.c.

819{
820 XLogRecPtr start_lsn = PG_GETARG_LSN(0);
821 XLogRecPtr end_lsn = GetCurrentLSN();
822
823 if (start_lsn > end_lsn)
825 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
826 errmsg("WAL start LSN must be less than current LSN"),
827 errdetail("Current WAL LSN on the database system is at %X/%X.",
828 LSN_FORMAT_ARGS(end_lsn))));
829
830 GetWALRecordsInfo(fcinfo, start_lsn, end_lsn);
831
833}

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

802{
803 XLogRecPtr start_lsn = PG_GETARG_LSN(0);
804 XLogRecPtr end_lsn = PG_GETARG_LSN(1);
805 bool stats_per_record = PG_GETARG_BOOL(2);
806
807 ValidateInputLSNs(start_lsn, &end_lsn);
808 GetWalStats(fcinfo, start_lsn, end_lsn, stats_per_record);
809
811}
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 836 of file pg_walinspect.c.

837{
838 XLogRecPtr start_lsn = PG_GETARG_LSN(0);
839 XLogRecPtr end_lsn = GetCurrentLSN();
840 bool stats_per_record = PG_GETARG_BOOL(1);
841
842 if (start_lsn > end_lsn)
844 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
845 errmsg("WAL start LSN must be less than current LSN"),
846 errdetail("Current WAL LSN on the database system is at %X/%X.",
847 LSN_FORMAT_ARGS(end_lsn))));
848
849 GetWalStats(fcinfo, start_lsn, end_lsn, stats_per_record);
850
852}

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

148{
149 XLogRecord *record;
150 char *errormsg;
151
152 record = XLogReadRecord(xlogreader, &errormsg);
153
154 if (record == NULL)
155 {
156 ReadLocalXLogPageNoWaitPrivate *private_data;
157
158 /* return NULL, if end of WAL is reached */
159 private_data = (ReadLocalXLogPageNoWaitPrivate *)
161
162 if (private_data->end_of_wal)
163 return NULL;
164
165 if (errormsg)
168 errmsg("could not read WAL at %X/%X: %s",
169 LSN_FORMAT_ARGS(xlogreader->EndRecPtr), errormsg)));
170 else
173 errmsg("could not read WAL at %X/%X",
175 }
176
177 return record;
178}
int errcode_for_file_access(void)
Definition: elog.c:876
XLogRecord * XLogReadRecord(XLogReaderState *state, char **errormsg)
Definition: xlogreader.c:389

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

514{
515 XLogRecPtr curr_lsn = GetCurrentLSN();
516
517 if (start_lsn > curr_lsn)
519 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
520 errmsg("WAL start LSN must be less than current LSN"),
521 errdetail("Current WAL LSN on the database system is at %X/%X.",
522 LSN_FORMAT_ARGS(curr_lsn))));
523
524 if (start_lsn > *end_lsn)
526 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
527 errmsg("WAL start LSN must be less than end LSN")));
528
529 if (*end_lsn > curr_lsn)
530 *end_lsn = curr_lsn;
531}

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.