PostgreSQL Source Code  git master
pg_walinspect.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * pg_walinspect.c
4  * Functions to inspect contents of PostgreSQL Write-Ahead Log
5  *
6  * Copyright (c) 2022, PostgreSQL Global Development Group
7  *
8  * IDENTIFICATION
9  * contrib/pg_walinspect/pg_walinspect.c
10  *
11  *-------------------------------------------------------------------------
12  */
13 #include "postgres.h"
14 
15 #include "access/xlog.h"
16 #include "access/xlog_internal.h"
17 #include "access/xlogreader.h"
18 #include "access/xlogrecovery.h"
19 #include "access/xlogstats.h"
20 #include "access/xlogutils.h"
21 #include "funcapi.h"
22 #include "miscadmin.h"
23 #include "utils/builtins.h"
24 #include "utils/pg_lsn.h"
25 
26 /*
27  * NOTE: For any code change or issue fix here, it is highly recommended to
28  * give a thought about doing the same in pg_waldump tool as well.
29  */
30 
32 
38 
39 static bool IsFutureLSN(XLogRecPtr lsn, XLogRecPtr *curr_lsn);
42 static void GetWALRecordInfo(XLogReaderState *record, Datum *values,
43  bool *nulls, uint32 ncols);
44 static XLogRecPtr ValidateInputLSNs(bool till_end_of_wal,
45  XLogRecPtr start_lsn, XLogRecPtr end_lsn);
46 static void GetWALRecordsInfo(FunctionCallInfo fcinfo, XLogRecPtr start_lsn,
47  XLogRecPtr end_lsn);
48 static void GetXLogSummaryStats(XLogStats *stats, ReturnSetInfo *rsinfo,
49  Datum *values, bool *nulls, uint32 ncols,
50  bool stats_per_record);
51 static void FillXLogStatsRow(const char *name, uint64 n, uint64 total_count,
52  uint64 rec_len, uint64 total_rec_len,
53  uint64 fpi_len, uint64 total_fpi_len,
54  uint64 tot_len, uint64 total_len,
55  Datum *values, bool *nulls, uint32 ncols);
56 static void GetWalStats(FunctionCallInfo fcinfo, XLogRecPtr start_lsn,
57  XLogRecPtr end_lsn, bool stats_per_record);
58 
59 /*
60  * Check if the given LSN is in future. Also, return the LSN up to which the
61  * server has WAL.
62  */
63 static bool
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 }
82 
83 /*
84  * Intialize WAL reader and identify first valid LSN.
85  */
86 static XLogReaderState *
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 }
128 
129 /*
130  * Read next WAL record.
131  *
132  * By design, to be less intrusive in a running system, no slot is allocated
133  * to reserve the WAL we're about to read. Therefore this function can
134  * encounter read errors for historical WAL.
135  *
136  * We guard against ordinary errors trying to read WAL that hasn't been
137  * written yet by limiting end_lsn to the flushed WAL, but that can also
138  * encounter errors if the flush pointer falls in the middle of a record. In
139  * that case we'll return NULL.
140  */
141 static XLogRecord *
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 }
174 
175 /*
176  * Get a single WAL record info.
177  */
178 static void
180  bool *nulls, uint32 ncols)
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 }
219 
220 /*
221  * Get WAL record info.
222  *
223  * This function emits an error if a future WAL LSN i.e. WAL LSN the database
224  * system doesn't know about is specified.
225  */
226 Datum
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 }
278 
279 /*
280  * Validate the input LSNs and compute end LSN for till_end_of_wal versions.
281  */
282 static XLogRecPtr
283 ValidateInputLSNs(bool till_end_of_wal, XLogRecPtr start_lsn,
284  XLogRecPtr end_lsn)
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 }
319 
320 /*
321  * Get info and data of all WAL records between start LSN and end LSN.
322  */
323 static void
325  XLogRecPtr end_lsn)
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 }
354 
355 /*
356  * Get info and data of all WAL records between start LSN and end LSN.
357  *
358  * This function emits an error if a future start or end WAL LSN i.e. WAL LSN
359  * the database system doesn't know about is specified.
360  */
361 Datum
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 }
376 
377 /*
378  * Get info and data of all WAL records from start LSN till end of WAL.
379  *
380  * This function emits an error if a future start i.e. WAL LSN the database
381  * system doesn't know about is specified.
382  */
383 Datum
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 }
397 
398 /*
399  * Fill single row of record counts and sizes for an rmgr or record.
400  */
401 static void
402 FillXLogStatsRow(const char *name,
403  uint64 n, uint64 total_count,
404  uint64 rec_len, uint64 total_rec_len,
405  uint64 fpi_len, uint64 total_fpi_len,
406  uint64 tot_len, uint64 total_len,
407  Datum *values, bool *nulls, uint32 ncols)
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 }
443 
444 /*
445  * Get summary statistics about the records seen so far.
446  */
447 static void
449  Datum *values, bool *nulls, uint32 ncols,
450  bool stats_per_record)
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 }
536 
537 /*
538  * Get WAL stats between start LSN and end LSN.
539  */
540 static void
542  XLogRecPtr end_lsn, bool stats_per_record)
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 }
572 
573 /*
574  * Get stats of all WAL records between start LSN and end LSN.
575  *
576  * This function emits an error if a future start or end WAL LSN i.e. WAL LSN
577  * the database system doesn't know about is specified.
578  */
579 Datum
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 }
596 
597 /*
598  * Get stats of all WAL records from start LSN till end of WAL.
599  *
600  * This function emits an error if a future start i.e. WAL LSN the database
601  * system doesn't know about is specified.
602  */
603 Datum
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 }
static Datum values[MAXATTR]
Definition: bootstrap.c:156
#define CStringGetTextDatum(s)
Definition: builtins.h:85
unsigned int uint32
Definition: c.h:442
int errcode_for_file_access(void)
Definition: elog.c:758
int errdetail(const char *fmt,...)
Definition: elog.c:1079
int errcode(int sqlerrcode)
Definition: elog.c:735
int errmsg(const char *fmt,...)
Definition: elog.c:946
#define ERROR
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:145
const char * name
Definition: encode.c:561
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1683
Datum Float8GetDatum(float8 X)
Definition: fmgr.c:1692
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
#define PG_RETURN_DATUM(x)
Definition: fmgr.h:353
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
void InitMaterializedSRF(FunctionCallInfo fcinfo, bits32 flags)
Definition: funcapi.c:76
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
int i
Definition: isn.c:73
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
Assert(fmt[strlen(fmt) - 1] !='\n')
void pfree(void *pointer)
Definition: mcxt.c:1306
void * palloc0(Size size)
Definition: mcxt.c:1230
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121
#define PG_GETARG_LSN(n)
Definition: pg_lsn.h:33
static Datum LSNGetDatum(XLogRecPtr X)
Definition: pg_lsn.h:28
PG_FUNCTION_INFO_V1(pg_get_wal_record_info)
static void GetWALRecordInfo(XLogReaderState *record, Datum *values, bool *nulls, uint32 ncols)
#define PG_GET_WAL_STATS_COLS
Datum pg_get_wal_records_info(PG_FUNCTION_ARGS)
Datum pg_get_wal_stats(PG_FUNCTION_ARGS)
static void GetWalStats(FunctionCallInfo fcinfo, XLogRecPtr start_lsn, XLogRecPtr end_lsn, bool stats_per_record)
#define PG_GET_WAL_RECORDS_INFO_COLS
#define PG_GET_WAL_RECORD_INFO_COLS
static void GetWALRecordsInfo(FunctionCallInfo fcinfo, XLogRecPtr start_lsn, XLogRecPtr end_lsn)
static bool IsFutureLSN(XLogRecPtr lsn, XLogRecPtr *curr_lsn)
Definition: pg_walinspect.c:64
Datum pg_get_wal_records_info_till_end_of_wal(PG_FUNCTION_ARGS)
PG_MODULE_MAGIC
Definition: pg_walinspect.c:31
static XLogRecord * ReadNextXLogRecord(XLogReaderState *xlogreader)
static XLogReaderState * InitXLogReaderState(XLogRecPtr lsn)
Definition: pg_walinspect.c:87
Datum pg_get_wal_stats_till_end_of_wal(PG_FUNCTION_ARGS)
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 XLogRecPtr ValidateInputLSNs(bool till_end_of_wal, XLogRecPtr start_lsn, XLogRecPtr end_lsn)
Datum pg_get_wal_record_info(PG_FUNCTION_ARGS)
static Datum TransactionIdGetDatum(TransactionId X)
Definition: postgres.h:620
uintptr_t Datum
Definition: postgres.h:412
static Datum UInt32GetDatum(uint32 X)
Definition: postgres.h:580
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
#define RmgrIdIsValid(rmid)
Definition: rmgr.h:53
#define RM_MAX_ID
Definition: rmgr.h:33
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
fmNodePtr resultinfo
Definition: fmgr.h:89
TupleDesc setDesc
Definition: execnodes.h:332
Tuplestorestate * setResult
Definition: execnodes.h:331
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
void * private_data
Definition: xlogreader.h:196
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
void tuplestore_putvalues(Tuplestorestate *state, TupleDesc tdesc, Datum *values, bool *isnull)
Definition: tuplestore.c:750
bool RecoveryInProgress(void)
Definition: xlog.c:5912
int wal_segment_size
Definition: xlog.c:146
XLogRecPtr GetFlushRecPtr(TimeLineID *insertTLI)
Definition: xlog.c:6077
static RmgrData GetRmgr(RmgrId rmid)
static bool RmgrIdExists(RmgrId rmid)
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
void XLogRecGetBlockRefInfo(XLogReaderState *record, bool pretty, bool detailed_format, StringInfo buf, uint32 *fpi_len)
Definition: xlogdesc.c:209
XLogRecord * XLogReadRecord(XLogReaderState *state, char **errormsg)
Definition: xlogreader.c:422
void XLogReaderFree(XLogReaderState *state)
Definition: xlogreader.c:170
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 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 XL_ROUTINE(...)
Definition: xlogreader.h:117
#define XLogRecGetPrev(decoder)
Definition: xlogreader.h:410
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
XLogRecPtr GetXLogReplayRecPtr(TimeLineID *replayTLI)
static XLogReaderState * xlogreader
Definition: xlogrecovery.c:188
void XLogRecStoreStats(XLogStats *stats, XLogReaderState *record)
Definition: xlogstats.c:54
#define MAX_XLINFO_TYPES
Definition: xlogstats.h:19
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