PostgreSQL Source Code git master
Loading...
Searching...
No Matches
pg_walinspect.c File Reference
#include "postgres.h"
#include "access/htup_details.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 "port/pg_bitutils.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/pg_lsn.h"
#include "utils/tuplestore.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_MODULE_MAGIC_EXT (.name="pg_walinspect",.version=PG_VERSION)
 
 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)
 

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

623{
624 double n_pct,
628 int i = 0;
629
630 n_pct = 0;
631 if (total_count != 0)
632 n_pct = 100 * (double) n / total_count;
633
634 rec_len_pct = 0;
635 if (total_rec_len != 0)
636 rec_len_pct = 100 * (double) rec_len / total_rec_len;
637
638 fpi_len_pct = 0;
639 if (total_fpi_len != 0)
640 fpi_len_pct = 100 * (double) fpi_len / total_fpi_len;
641
642 tot_len_pct = 0;
643 if (total_len != 0)
644 tot_len_pct = 100 * (double) tot_len / total_len;
645
647 values[i++] = Int64GetDatum(n);
649 values[i++] = Int64GetDatum(rec_len);
651 values[i++] = Int64GetDatum(fpi_len);
655
656 Assert(i == ncols);
657}
static Datum values[MAXATTR]
Definition bootstrap.c:188
#define CStringGetTextDatum(s)
Definition builtins.h:98
#define Assert(condition)
Definition c.h:943
int i
Definition isn.c:77
static Datum Int64GetDatum(int64 X)
Definition postgres.h:413
static Datum Float8GetDatum(float8 X)
Definition postgres.h:502
static int fb(int x)
const char * name

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

Referenced by GetXLogSummaryStats().

◆ GetCurrentLSN()

static XLogRecPtr GetCurrentLSN ( void  )
static

Definition at line 75 of file pg_walinspect.c.

76{
78
79 /*
80 * We determine the current LSN of the server similar to how page_read
81 * callback read_local_xlog_page_no_wait does.
82 */
83 if (!RecoveryInProgress())
85 else
87
89
90 return curr_lsn;
91}
bool RecoveryInProgress(void)
Definition xlog.c:6444
XLogRecPtr GetFlushRecPtr(TimeLineID *insertTLI)
Definition xlog.c:6609
#define XLogRecPtrIsValid(r)
Definition xlogdefs.h:29
uint64 XLogRecPtr
Definition xlogdefs.h:21
XLogRecPtr GetXLogReplayRecPtr(TimeLineID *replayTLI)

References Assert, fb(), GetFlushRecPtr(), GetXLogReplayRecPtr(), RecoveryInProgress(), and XLogRecPtrIsValid.

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

264{
265#define PG_GET_WAL_BLOCK_INFO_COLS 20
266 int block_id;
268 RmgrData desc;
269 const char *record_type;
271
273
274 desc = GetRmgr(XLogRecGetRmid(record));
275 record_type = desc.rm_identify(XLogRecGetInfo(record));
276
277 if (record_type == NULL)
278 record_type = psprintf("UNKNOWN (%x)",
279 XLogRecGetInfo(record) & ~XLR_INFO_MASK);
280
282 desc.rm_desc(&rec_desc, record);
283
284 for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++)
285 {
287 BlockNumber blkno;
289 ForkNumber forknum;
291 bool nulls[PG_GET_WAL_BLOCK_INFO_COLS] = {0};
293 block_fpi_len = 0;
295 int i = 0;
296
297 if (!XLogRecHasBlockRef(record, block_id))
298 continue;
299
300 blk = XLogRecGetBlock(record, block_id);
301
303 &rnode, &forknum, &blkno, NULL);
304
305 /* Save block_data_len */
306 if (blk->has_data)
307 block_data_len = blk->data_len;
308
309 if (blk->has_image)
310 {
311 /* Block reference has an FPI, so prepare relevant output */
312 int bitcnt;
313 int cnt = 0;
314 Datum *flags;
315
316 /* Save block_fpi_len */
317 block_fpi_len = blk->bimg_len;
318
319 /* Construct and save block_fpi_info */
320 bitcnt = pg_popcount((const char *) &blk->bimg_info,
321 sizeof(uint8));
322 flags = palloc0_array(Datum, bitcnt);
323 if ((blk->bimg_info & BKPIMAGE_HAS_HOLE) != 0)
324 flags[cnt++] = CStringGetTextDatum("HAS_HOLE");
325 if (blk->apply_image)
326 flags[cnt++] = CStringGetTextDatum("APPLY");
327 if ((blk->bimg_info & BKPIMAGE_COMPRESS_PGLZ) != 0)
328 flags[cnt++] = CStringGetTextDatum("COMPRESS_PGLZ");
329 if ((blk->bimg_info & BKPIMAGE_COMPRESS_LZ4) != 0)
330 flags[cnt++] = CStringGetTextDatum("COMPRESS_LZ4");
331 if ((blk->bimg_info & BKPIMAGE_COMPRESS_ZSTD) != 0)
332 flags[cnt++] = CStringGetTextDatum("COMPRESS_ZSTD");
333
334 Assert(cnt <= bitcnt);
336 }
337
338 /* start_lsn, end_lsn, prev_lsn, and blockid outputs */
339 values[i++] = LSNGetDatum(record->ReadRecPtr);
340 values[i++] = LSNGetDatum(record->EndRecPtr);
341 values[i++] = LSNGetDatum(XLogRecGetPrev(record));
343
344 /* relfile and block related outputs */
345 values[i++] = ObjectIdGetDatum(blk->rlocator.spcOid);
346 values[i++] = ObjectIdGetDatum(blk->rlocator.dbOid);
347 values[i++] = ObjectIdGetDatum(blk->rlocator.relNumber);
348 values[i++] = Int16GetDatum(forknum);
349 values[i++] = Int64GetDatum((int64) blkno);
350
351 /* xid, resource_manager, and record_type outputs */
354 values[i++] = CStringGetTextDatum(record_type);
355
356 /*
357 * record_length, main_data_length, block_data_len, and
358 * block_fpi_length outputs
359 */
364
365 /* block_fpi_info (text array) output */
366 if (block_fpi_info)
368 else
369 nulls[i++] = true;
370
371 /* description output (describes WAL record) */
372 if (rec_desc.len > 0)
374 else
375 nulls[i++] = true;
376
377 /* block_data output */
378 if (blk->has_data && show_data)
379 {
381
386 }
387 else
388 nulls[i++] = true;
389
390 /* block_fpi_data output */
391 if (blk->has_image && show_data)
392 {
394 Page page;
396
397 page = (Page) buf.data;
398 if (!RestoreBlockImage(record, block_id, page))
401 errmsg_internal("%s", record->errormsg_buf)));
402
407 }
408 else
409 nulls[i++] = true;
410
412
413 /* Store a tuple for this block reference */
414 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
415 values, nulls);
416 }
417
418#undef PG_GET_WAL_BLOCK_INFO_COLS
419}
ArrayType * construct_array_builtin(Datum *elems, int nelems, Oid elmtype)
uint32 BlockNumber
Definition block.h:31
PageData * Page
Definition bufpage.h:81
uint8_t uint8
Definition c.h:622
#define VARHDRSZ
Definition c.h:781
int64_t int64
Definition c.h:621
uint32_t uint32
Definition c.h:624
int errcode(int sqlerrcode)
Definition elog.c:874
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
#define ERROR
Definition elog.h:39
#define ereport(elevel,...)
Definition elog.h:151
#define palloc0_array(type, count)
Definition fe_memutils.h:77
void * palloc(Size size)
Definition mcxt.c:1387
static uint64 pg_popcount(const char *buf, int bytes)
static Datum LSNGetDatum(XLogRecPtr X)
Definition pg_lsn.h:31
static char buf[DEFAULT_XLOG_SEG_SIZE]
#define PG_GET_WAL_BLOCK_INFO_COLS
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
static Datum TransactionIdGetDatum(TransactionId X)
Definition postgres.h:292
static Datum Int16GetDatum(int16 X)
Definition postgres.h:172
static Datum ObjectIdGetDatum(Oid X)
Definition postgres.h:252
uint64_t Datum
Definition postgres.h:70
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:97
const char *(* rm_identify)(uint8 info)
const char * rm_name
void(* rm_desc)(StringInfo buf, XLogReaderState *record)
char * errormsg_buf
Definition xlogreader.h:310
XLogRecPtr EndRecPtr
Definition xlogreader.h:206
XLogRecPtr ReadRecPtr
Definition xlogreader.h:205
Definition c.h:776
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, const Datum *values, const bool *isnull)
Definition tuplestore.c:785
static char * VARDATA(const void *PTR)
Definition varatt.h:305
static void SET_VARSIZE(void *PTR, Size len)
Definition varatt.h:432
static RmgrData GetRmgr(RmgrId rmid)
bool XLogRecGetBlockTagExtended(XLogReaderState *record, uint8 block_id, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum, Buffer *prefetch_buffer)
bool RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
#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 Assert, BKPIMAGE_COMPRESS_LZ4, BKPIMAGE_COMPRESS_PGLZ, BKPIMAGE_COMPRESS_ZSTD, BKPIMAGE_HAS_HOLE, buf, construct_array_builtin(), CStringGetTextDatum, XLogReaderState::EndRecPtr, ereport, errcode(), errmsg_internal(), ERROR, XLogReaderState::errormsg_buf, fb(), GetRmgr(), i, initStringInfo(), Int16GetDatum(), Int64GetDatum(), LSNGetDatum(), ObjectIdGetDatum(), palloc(), palloc0_array, PG_GET_WAL_BLOCK_INFO_COLS, pg_popcount(), PointerGetDatum(), psprintf(), XLogReaderState::ReadRecPtr, RestoreBlockImage(), FunctionCallInfoBaseData::resultinfo, RmgrData::rm_desc, RmgrData::rm_identify, RmgrData::rm_name, SET_VARSIZE(), 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 202 of file pg_walinspect.c.

204{
205 const char *record_type;
206 RmgrData desc;
207 uint32 fpi_len = 0;
210 int i = 0;
211
212 desc = GetRmgr(XLogRecGetRmid(record));
213 record_type = desc.rm_identify(XLogRecGetInfo(record));
214
215 if (record_type == NULL)
216 record_type = psprintf("UNKNOWN (%x)", XLogRecGetInfo(record) & ~XLR_INFO_MASK);
217
219 desc.rm_desc(&rec_desc, record);
220
221 if (XLogRecHasAnyBlockRefs(record))
222 {
224 XLogRecGetBlockRefInfo(record, false, true, &rec_blk_ref, &fpi_len);
225 }
226
227 values[i++] = LSNGetDatum(record->ReadRecPtr);
228 values[i++] = LSNGetDatum(record->EndRecPtr);
229 values[i++] = LSNGetDatum(XLogRecGetPrev(record));
232 values[i++] = CStringGetTextDatum(record_type);
235 values[i++] = UInt32GetDatum(fpi_len);
236
237 if (rec_desc.len > 0)
239 else
240 nulls[i++] = true;
241
242 if (XLogRecHasAnyBlockRefs(record))
244 else
245 nulls[i++] = true;
246
247 Assert(i == ncols);
248}
void XLogRecGetBlockRefInfo(XLogReaderState *record, bool pretty, bool detailed_format, StringInfo buf, uint32 *fpi_len)
Definition xlogdesc.c:249

References Assert, CStringGetTextDatum, XLogReaderState::EndRecPtr, fb(), 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, 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 550 of file pg_walinspect.c.

552{
553#define PG_GET_WAL_RECORDS_INFO_COLS 11
557 MemoryContext tmp_cxt;
558
559 Assert(start_lsn <= end_lsn);
560
561 InitMaterializedSRF(fcinfo, 0);
562
563 xlogreader = InitXLogReaderState(start_lsn);
564
566 "GetWALRecordsInfo temporary cxt",
568
570 xlogreader->EndRecPtr <= end_lsn)
571 {
573 bool nulls[PG_GET_WAL_RECORDS_INFO_COLS] = {0};
574
575 /* Use the tmp context so we can clean up after each tuple is done */
577
580
581 tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc,
582 values, nulls);
583
584 /* clean up and switch back */
586 MemoryContextReset(tmp_cxt);
587
589 }
590
591 MemoryContextDelete(tmp_cxt);
594
595#undef PG_GET_WAL_RECORDS_INFO_COLS
596}
void InitMaterializedSRF(FunctionCallInfo fcinfo, uint32 flags)
Definition funcapi.c:76
void MemoryContextReset(MemoryContext context)
Definition mcxt.c:403
void pfree(void *pointer)
Definition mcxt.c:1616
MemoryContext CurrentMemoryContext
Definition mcxt.c:160
void MemoryContextDelete(MemoryContext context)
Definition mcxt.c:472
#define AllocSetContextCreate
Definition memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition memutils.h:160
#define CHECK_FOR_INTERRUPTS()
Definition miscadmin.h:123
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)
void * private_data
Definition xlogreader.h:195
void XLogReaderFree(XLogReaderState *state)
Definition xlogreader.c:163
static XLogReaderState * xlogreader

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, CHECK_FOR_INTERRUPTS, CurrentMemoryContext, XLogReaderState::EndRecPtr, fb(), GetWALRecordInfo(), InitMaterializedSRF(), InitXLogReaderState(), MemoryContextDelete(), MemoryContextReset(), MemoryContextSwitchTo(), pfree(), PG_GET_WAL_RECORDS_INFO_COLS, XLogReaderState::private_data, ReadNextXLogRecord(), FunctionCallInfoBaseData::resultinfo, 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 776 of file pg_walinspect.c.

778{
779#define PG_GET_WAL_STATS_COLS 9
781 XLogStats stats = {0};
784 bool nulls[PG_GET_WAL_STATS_COLS] = {0};
785
786 Assert(start_lsn <= end_lsn);
787
788 InitMaterializedSRF(fcinfo, 0);
789
790 xlogreader = InitXLogReaderState(start_lsn);
791
793 xlogreader->EndRecPtr <= end_lsn)
794 {
796
798 }
799
802
803 GetXLogSummaryStats(&stats, rsinfo, values, nulls,
805 stats_per_record);
806
807#undef PG_GET_WAL_STATS_COLS
808}
#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 Assert, CHECK_FOR_INTERRUPTS, XLogReaderState::EndRecPtr, fb(), GetXLogSummaryStats(), InitMaterializedSRF(), InitXLogReaderState(), pfree(), PG_GET_WAL_STATS_COLS, XLogReaderState::private_data, ReadNextXLogRecord(), FunctionCallInfoBaseData::resultinfo, values, xlogreader, XLogReaderFree(), and XLogRecStoreStats().

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

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

Referenced by GetWalStats().

◆ InitXLogReaderState()

static XLogReaderState * InitXLogReaderState ( XLogRecPtr  lsn)
static

Definition at line 97 of file pg_walinspect.c.

98{
100 ReadLocalXLogPageNoWaitPrivate *private_data;
102 char *errormsg;
103
104 /*
105 * Reading WAL below the first page of the first segments isn't allowed.
106 * This is a bootstrap WAL page and the page_read callback fails to read
107 * it.
108 */
109 if (lsn < XLOG_BLCKSZ)
112 errmsg("could not read WAL at LSN %X/%08X",
113 LSN_FORMAT_ARGS(lsn))));
114
116
119 .segment_open = &wal_segment_open,
120 .segment_close = &wal_segment_close),
121 private_data);
122
123 if (xlogreader == NULL)
126 errmsg("out of memory"),
127 errdetail("Failed while allocating a WAL reading processor.")));
128
129 /* first find a valid recptr to start from */
131
133 {
134 if (errormsg)
136 errmsg("could not find a valid record after %X/%08X: %s",
137 LSN_FORMAT_ARGS(lsn), errormsg));
138 else
140 errmsg("could not find a valid record after %X/%08X",
141 LSN_FORMAT_ARGS(lsn)));
142 }
143
144 return xlogreader;
145}
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define palloc0_object(type)
Definition fe_memutils.h:75
static char * errmsg
int wal_segment_size
Definition xlog.c:147
#define LSN_FORMAT_ARGS(lsn)
Definition xlogdefs.h:47
XLogReaderState * XLogReaderAllocate(int wal_segment_size, const char *waldir, XLogReaderRoutine *routine, void *private_data)
Definition xlogreader.c:108
XLogRecPtr XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
#define XL_ROUTINE(...)
Definition xlogreader.h:117
void wal_segment_close(XLogReaderState *state)
Definition xlogutils.c:831
void wal_segment_open(XLogReaderState *state, XLogSegNo nextSegNo, TimeLineID *tli_p)
Definition xlogutils.c:806
int read_local_xlog_page_no_wait(XLogReaderState *state, XLogRecPtr targetPagePtr, int reqLen, XLogRecPtr targetRecPtr, char *cur_page)
Definition xlogutils.c:857

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

Referenced by GetWALRecordsInfo(), GetWalStats(), 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 425 of file pg_walinspect.c.

426{
427 XLogRecPtr start_lsn = PG_GETARG_LSN(0);
428 XLogRecPtr end_lsn = PG_GETARG_LSN(1);
429 bool show_data = PG_GETARG_BOOL(2);
432 MemoryContext tmp_cxt;
433
434 ValidateInputLSNs(start_lsn, &end_lsn);
435
436 InitMaterializedSRF(fcinfo, 0);
437
438 xlogreader = InitXLogReaderState(start_lsn);
439
441 "pg_get_wal_block_info temporary cxt",
443
445 xlogreader->EndRecPtr <= end_lsn)
446 {
448
450 continue;
451
452 /* Use the tmp context so we can clean up after each tuple is done */
454
456
457 /* clean up and switch back */
459 MemoryContextReset(tmp_cxt);
460 }
461
462 MemoryContextDelete(tmp_cxt);
465
467}
#define PG_RETURN_VOID()
Definition fmgr.h:350
#define PG_GETARG_BOOL(n)
Definition fmgr.h:274
#define PG_GETARG_LSN(n)
Definition pg_lsn.h:36
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, fb(), 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 473 of file pg_walinspect.c.

474{
475#define PG_GET_WAL_RECORD_INFO_COLS 11
476 Datum result;
478 bool nulls[PG_GET_WAL_RECORD_INFO_COLS] = {0};
479 XLogRecPtr lsn;
482 TupleDesc tupdesc;
483 HeapTuple tuple;
484
485 lsn = PG_GETARG_LSN(0);
487
488 if (lsn > curr_lsn)
491 errmsg("WAL input LSN must be less than current LSN"),
492 errdetail("Current WAL LSN on the database system is at %X/%08X.",
494
495 /* Build a tuple descriptor for our result type. */
496 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
497 elog(ERROR, "return type must be a row type");
498
500
504 errmsg("could not read WAL at %X/%08X",
506
508
511
512 tuple = heap_form_tuple(tupdesc, values, nulls);
513 result = HeapTupleGetDatum(tuple);
514
515 PG_RETURN_DATUM(result);
516#undef PG_GET_WAL_RECORD_INFO_COLS
517}
#define elog(elevel,...)
Definition elog.h:227
#define PG_RETURN_DATUM(x)
Definition fmgr.h:354
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:1025
#define PG_GET_WAL_RECORD_INFO_COLS
static XLogRecPtr GetCurrentLSN(void)

References elog, XLogReaderState::EndRecPtr, ereport, errcode(), errdetail(), errmsg, ERROR, fb(), 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 602 of file pg_walinspect.c.

603{
604 XLogRecPtr start_lsn = PG_GETARG_LSN(0);
605 XLogRecPtr end_lsn = PG_GETARG_LSN(1);
606
607 ValidateInputLSNs(start_lsn, &end_lsn);
608 GetWALRecordsInfo(fcinfo, start_lsn, end_lsn);
609
611}
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 831 of file pg_walinspect.c.

832{
833 XLogRecPtr start_lsn = PG_GETARG_LSN(0);
834 XLogRecPtr end_lsn = GetCurrentLSN();
835
836 if (start_lsn > end_lsn)
839 errmsg("WAL start LSN must be less than current LSN"),
840 errdetail("Current WAL LSN on the database system is at %X/%08X.",
841 LSN_FORMAT_ARGS(end_lsn))));
842
843 GetWALRecordsInfo(fcinfo, start_lsn, end_lsn);
844
846}

References ereport, errcode(), errdetail(), errmsg, ERROR, fb(), 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 814 of file pg_walinspect.c.

815{
816 XLogRecPtr start_lsn = PG_GETARG_LSN(0);
817 XLogRecPtr end_lsn = PG_GETARG_LSN(1);
818 bool stats_per_record = PG_GETARG_BOOL(2);
819
820 ValidateInputLSNs(start_lsn, &end_lsn);
821 GetWalStats(fcinfo, start_lsn, end_lsn, stats_per_record);
822
824}
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 849 of file pg_walinspect.c.

850{
851 XLogRecPtr start_lsn = PG_GETARG_LSN(0);
852 XLogRecPtr end_lsn = GetCurrentLSN();
853 bool stats_per_record = PG_GETARG_BOOL(1);
854
855 if (start_lsn > end_lsn)
858 errmsg("WAL start LSN must be less than current LSN"),
859 errdetail("Current WAL LSN on the database system is at %X/%08X.",
860 LSN_FORMAT_ARGS(end_lsn))));
861
862 GetWalStats(fcinfo, start_lsn, end_lsn, stats_per_record);
863
865}

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

◆ PG_MODULE_MAGIC_EXT()

PG_MODULE_MAGIC_EXT ( name = "pg_walinspect",
version = PG_VERSION 
)

◆ ReadNextXLogRecord()

static XLogRecord * ReadNextXLogRecord ( XLogReaderState xlogreader)
static

Definition at line 160 of file pg_walinspect.c.

161{
162 XLogRecord *record;
163 char *errormsg;
164
165 record = XLogReadRecord(xlogreader, &errormsg);
166
167 if (record == NULL)
168 {
169 ReadLocalXLogPageNoWaitPrivate *private_data;
170
171 /* return NULL, if end of WAL is reached */
172 private_data = (ReadLocalXLogPageNoWaitPrivate *)
174
175 if (private_data->end_of_wal)
176 return NULL;
177
178 if (errormsg)
181 errmsg("could not read WAL at %X/%08X: %s",
182 LSN_FORMAT_ARGS(xlogreader->EndRecPtr), errormsg)));
183 else
186 errmsg("could not read WAL at %X/%08X",
188 }
189
190 return record;
191}
int errcode_for_file_access(void)
Definition elog.c:897
XLogRecord * XLogReadRecord(XLogReaderState *state, char **errormsg)
Definition xlogreader.c:391

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

Referenced by GetWALRecordsInfo(), GetWalStats(), 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 526 of file pg_walinspect.c.

527{
529
530 if (start_lsn > curr_lsn)
533 errmsg("WAL start LSN must be less than current LSN"),
534 errdetail("Current WAL LSN on the database system is at %X/%08X.",
536
537 if (start_lsn > *end_lsn)
540 errmsg("WAL start LSN must be less than end LSN")));
541
542 if (*end_lsn > curr_lsn)
543 *end_lsn = curr_lsn;
544}

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

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