PostgreSQL Source Code  git master
xlogdesc.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * xlogdesc.c
4  * rmgr descriptor routines for access/transam/xlog.c
5  *
6  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/access/rmgrdesc/xlogdesc.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include "access/transam.h"
18 #include "access/xlog.h"
19 #include "access/xlog_internal.h"
20 #include "catalog/pg_control.h"
21 #include "utils/guc.h"
22 #include "utils/timestamp.h"
23 
24 /*
25  * GUC support
26  */
27 const struct config_enum_entry wal_level_options[] = {
28  {"minimal", WAL_LEVEL_MINIMAL, false},
29  {"replica", WAL_LEVEL_REPLICA, false},
30  {"archive", WAL_LEVEL_REPLICA, true}, /* deprecated */
31  {"hot_standby", WAL_LEVEL_REPLICA, true}, /* deprecated */
32  {"logical", WAL_LEVEL_LOGICAL, false},
33  {NULL, 0, false}
34 };
35 
36 /*
37  * Find a string representation for wal_level
38  */
39 static const char *
41 {
42  const struct config_enum_entry *entry;
43  const char *wal_level_str = "?";
44 
45  for (entry = wal_level_options; entry->name; entry++)
46  {
47  if (entry->val == wal_level)
48  {
49  wal_level_str = entry->name;
50  break;
51  }
52  }
53 
54  return wal_level_str;
55 }
56 
57 void
59 {
60  char *rec = XLogRecGetData(record);
61  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
62 
63  if (info == XLOG_CHECKPOINT_SHUTDOWN ||
64  info == XLOG_CHECKPOINT_ONLINE)
65  {
66  CheckPoint *checkpoint = (CheckPoint *) rec;
67 
68  appendStringInfo(buf, "redo %X/%X; "
69  "tli %u; prev tli %u; fpw %s; wal_level %s; xid %u:%u; oid %u; multi %u; offset %u; "
70  "oldest xid %u in DB %u; oldest multi %u in DB %u; "
71  "oldest/newest commit timestamp xid: %u/%u; "
72  "oldest running xid %u; %s",
73  LSN_FORMAT_ARGS(checkpoint->redo),
74  checkpoint->ThisTimeLineID,
75  checkpoint->PrevTimeLineID,
76  checkpoint->fullPageWrites ? "true" : "false",
77  get_wal_level_string(checkpoint->wal_level),
79  XidFromFullTransactionId(checkpoint->nextXid),
80  checkpoint->nextOid,
81  checkpoint->nextMulti,
82  checkpoint->nextMultiOffset,
83  checkpoint->oldestXid,
84  checkpoint->oldestXidDB,
85  checkpoint->oldestMulti,
86  checkpoint->oldestMultiDB,
87  checkpoint->oldestCommitTsXid,
88  checkpoint->newestCommitTsXid,
89  checkpoint->oldestActiveXid,
90  (info == XLOG_CHECKPOINT_SHUTDOWN) ? "shutdown" : "online");
91  }
92  else if (info == XLOG_NEXTOID)
93  {
94  Oid nextOid;
95 
96  memcpy(&nextOid, rec, sizeof(Oid));
97  appendStringInfo(buf, "%u", nextOid);
98  }
99  else if (info == XLOG_RESTORE_POINT)
100  {
101  xl_restore_point *xlrec = (xl_restore_point *) rec;
102 
104  }
105  else if (info == XLOG_FPI || info == XLOG_FPI_FOR_HINT)
106  {
107  /* no further information to print */
108  }
109  else if (info == XLOG_BACKUP_END)
110  {
111  XLogRecPtr startpoint;
112 
113  memcpy(&startpoint, rec, sizeof(XLogRecPtr));
114  appendStringInfo(buf, "%X/%X", LSN_FORMAT_ARGS(startpoint));
115  }
116  else if (info == XLOG_PARAMETER_CHANGE)
117  {
118  xl_parameter_change xlrec;
119  const char *wal_level_str;
120 
121  memcpy(&xlrec, rec, sizeof(xl_parameter_change));
123 
124  appendStringInfo(buf, "max_connections=%d max_worker_processes=%d "
125  "max_wal_senders=%d max_prepared_xacts=%d "
126  "max_locks_per_xact=%d wal_level=%s "
127  "wal_log_hints=%s track_commit_timestamp=%s",
128  xlrec.MaxConnections,
129  xlrec.max_worker_processes,
130  xlrec.max_wal_senders,
131  xlrec.max_prepared_xacts,
132  xlrec.max_locks_per_xact,
134  xlrec.wal_log_hints ? "on" : "off",
135  xlrec.track_commit_timestamp ? "on" : "off");
136  }
137  else if (info == XLOG_FPW_CHANGE)
138  {
139  bool fpw;
140 
141  memcpy(&fpw, rec, sizeof(bool));
142  appendStringInfoString(buf, fpw ? "true" : "false");
143  }
144  else if (info == XLOG_END_OF_RECOVERY)
145  {
146  xl_end_of_recovery xlrec;
147 
148  memcpy(&xlrec, rec, sizeof(xl_end_of_recovery));
149  appendStringInfo(buf, "tli %u; prev tli %u; time %s; wal_level %s",
150  xlrec.ThisTimeLineID, xlrec.PrevTimeLineID,
153  }
154  else if (info == XLOG_OVERWRITE_CONTRECORD)
155  {
157 
158  memcpy(&xlrec, rec, sizeof(xl_overwrite_contrecord));
159  appendStringInfo(buf, "lsn %X/%X; time %s",
162  }
163  else if (info == XLOG_CHECKPOINT_REDO)
164  {
165  int wal_level;
166 
167  memcpy(&wal_level, rec, sizeof(int));
169  }
170 }
171 
172 const char *
174 {
175  const char *id = NULL;
176 
177  switch (info & ~XLR_INFO_MASK)
178  {
180  id = "CHECKPOINT_SHUTDOWN";
181  break;
183  id = "CHECKPOINT_ONLINE";
184  break;
185  case XLOG_NOOP:
186  id = "NOOP";
187  break;
188  case XLOG_NEXTOID:
189  id = "NEXTOID";
190  break;
191  case XLOG_SWITCH:
192  id = "SWITCH";
193  break;
194  case XLOG_BACKUP_END:
195  id = "BACKUP_END";
196  break;
198  id = "PARAMETER_CHANGE";
199  break;
200  case XLOG_RESTORE_POINT:
201  id = "RESTORE_POINT";
202  break;
203  case XLOG_FPW_CHANGE:
204  id = "FPW_CHANGE";
205  break;
207  id = "END_OF_RECOVERY";
208  break;
210  id = "OVERWRITE_CONTRECORD";
211  break;
212  case XLOG_FPI:
213  id = "FPI";
214  break;
215  case XLOG_FPI_FOR_HINT:
216  id = "FPI_FOR_HINT";
217  break;
219  id = "CHECKPOINT_REDO";
220  break;
221  }
222 
223  return id;
224 }
225 
226 /*
227  * Returns a string giving information about all the blocks in an
228  * XLogRecord.
229  */
230 void
232  bool detailed_format, StringInfo buf,
233  uint32 *fpi_len)
234 {
235  int block_id;
236 
237  Assert(record != NULL);
238 
239  if (detailed_format && pretty)
240  appendStringInfoChar(buf, '\n');
241 
242  for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++)
243  {
244  RelFileLocator rlocator;
245  ForkNumber forknum;
246  BlockNumber blk;
247 
248  if (!XLogRecGetBlockTagExtended(record, block_id,
249  &rlocator, &forknum, &blk, NULL))
250  continue;
251 
252  if (detailed_format)
253  {
254  /* Get block references in detailed format. */
255 
256  if (pretty)
257  appendStringInfoChar(buf, '\t');
258  else if (block_id > 0)
260 
262  "blkref #%d: rel %u/%u/%u fork %s blk %u",
263  block_id,
264  rlocator.spcOid, rlocator.dbOid, rlocator.relNumber,
265  forkNames[forknum],
266  blk);
267 
268  if (XLogRecHasBlockImage(record, block_id))
269  {
270  uint8 bimg_info = XLogRecGetBlock(record, block_id)->bimg_info;
271 
272  /* Calculate the amount of FPI data in the record. */
273  if (fpi_len)
274  *fpi_len += XLogRecGetBlock(record, block_id)->bimg_len;
275 
276  if (BKPIMAGE_COMPRESSED(bimg_info))
277  {
278  const char *method;
279 
280  if ((bimg_info & BKPIMAGE_COMPRESS_PGLZ) != 0)
281  method = "pglz";
282  else if ((bimg_info & BKPIMAGE_COMPRESS_LZ4) != 0)
283  method = "lz4";
284  else if ((bimg_info & BKPIMAGE_COMPRESS_ZSTD) != 0)
285  method = "zstd";
286  else
287  method = "unknown";
288 
290  " (FPW%s); hole: offset: %u, length: %u, "
291  "compression saved: %u, method: %s",
292  XLogRecBlockImageApply(record, block_id) ?
293  "" : " for WAL verification",
294  XLogRecGetBlock(record, block_id)->hole_offset,
295  XLogRecGetBlock(record, block_id)->hole_length,
296  BLCKSZ -
297  XLogRecGetBlock(record, block_id)->hole_length -
298  XLogRecGetBlock(record, block_id)->bimg_len,
299  method);
300  }
301  else
302  {
304  " (FPW%s); hole: offset: %u, length: %u",
305  XLogRecBlockImageApply(record, block_id) ?
306  "" : " for WAL verification",
307  XLogRecGetBlock(record, block_id)->hole_offset,
308  XLogRecGetBlock(record, block_id)->hole_length);
309  }
310  }
311 
312  if (pretty)
313  appendStringInfoChar(buf, '\n');
314  }
315  else
316  {
317  /* Get block references in short format. */
318 
319  if (forknum != MAIN_FORKNUM)
320  {
322  ", blkref #%d: rel %u/%u/%u fork %s blk %u",
323  block_id,
324  rlocator.spcOid, rlocator.dbOid, rlocator.relNumber,
325  forkNames[forknum],
326  blk);
327  }
328  else
329  {
331  ", blkref #%d: rel %u/%u/%u blk %u",
332  block_id,
333  rlocator.spcOid, rlocator.dbOid, rlocator.relNumber,
334  blk);
335  }
336 
337  if (XLogRecHasBlockImage(record, block_id))
338  {
339  /* Calculate the amount of FPI data in the record. */
340  if (fpi_len)
341  *fpi_len += XLogRecGetBlock(record, block_id)->bimg_len;
342 
343  if (XLogRecBlockImageApply(record, block_id))
344  appendStringInfoString(buf, " FPW");
345  else
346  appendStringInfoString(buf, " FPW for WAL verification");
347  }
348  }
349  }
350 
351  if (!detailed_format && pretty)
352  appendStringInfoChar(buf, '\n');
353 }
const char * timestamptz_to_str(TimestampTz t)
Definition: timestamp.c:1854
static const char * wal_level_str(WalLevel wal_level)
uint32 BlockNumber
Definition: block.h:31
unsigned int uint32
Definition: c.h:506
#define Assert(condition)
Definition: c.h:858
unsigned char uint8
Definition: c.h:504
#define XLOG_RESTORE_POINT
Definition: pg_control.h:75
#define XLOG_FPW_CHANGE
Definition: pg_control.h:76
#define XLOG_CHECKPOINT_REDO
Definition: pg_control.h:82
#define XLOG_OVERWRITE_CONTRECORD
Definition: pg_control.h:81
#define XLOG_FPI
Definition: pg_control.h:79
#define XLOG_FPI_FOR_HINT
Definition: pg_control.h:78
#define XLOG_NEXTOID
Definition: pg_control.h:71
#define XLOG_NOOP
Definition: pg_control.h:70
#define XLOG_CHECKPOINT_SHUTDOWN
Definition: pg_control.h:68
#define XLOG_SWITCH
Definition: pg_control.h:72
#define XLOG_BACKUP_END
Definition: pg_control.h:73
#define XLOG_PARAMETER_CHANGE
Definition: pg_control.h:74
#define XLOG_CHECKPOINT_ONLINE
Definition: pg_control.h:69
#define XLOG_END_OF_RECOVERY
Definition: pg_control.h:77
static char * buf
Definition: pg_test_fsync.c:73
unsigned int Oid
Definition: postgres_ext.h:31
const char *const forkNames[]
Definition: relpath.c:33
ForkNumber
Definition: relpath.h:48
@ MAIN_FORKNUM
Definition: relpath.h:50
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:97
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:182
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:194
Oid oldestMultiDB
Definition: pg_control.h:51
MultiXactId oldestMulti
Definition: pg_control.h:50
MultiXactOffset nextMultiOffset
Definition: pg_control.h:47
TransactionId newestCommitTsXid
Definition: pg_control.h:55
TransactionId oldestXid
Definition: pg_control.h:48
TimeLineID PrevTimeLineID
Definition: pg_control.h:40
TimeLineID ThisTimeLineID
Definition: pg_control.h:39
Oid nextOid
Definition: pg_control.h:45
TransactionId oldestActiveXid
Definition: pg_control.h:64
bool fullPageWrites
Definition: pg_control.h:42
MultiXactId nextMulti
Definition: pg_control.h:46
FullTransactionId nextXid
Definition: pg_control.h:44
TransactionId oldestCommitTsXid
Definition: pg_control.h:53
int wal_level
Definition: pg_control.h:43
XLogRecPtr redo
Definition: pg_control.h:37
Oid oldestXidDB
Definition: pg_control.h:49
RelFileNumber relNumber
Definition: guc.h:170
const char * name
Definition: guc.h:171
int val
Definition: guc.h:172
TimeLineID PrevTimeLineID
TimestampTz end_time
TimeLineID ThisTimeLineID
char rp_name[MAXFNAMELEN]
#define EpochFromFullTransactionId(x)
Definition: transam.h:47
#define XidFromFullTransactionId(x)
Definition: transam.h:48
int wal_level
Definition: xlog.c:129
@ WAL_LEVEL_REPLICA
Definition: xlog.h:75
@ WAL_LEVEL_LOGICAL
Definition: xlog.h:76
@ WAL_LEVEL_MINIMAL
Definition: xlog.h:74
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
uint64 XLogRecPtr
Definition: xlogdefs.h:21
void xlog_desc(StringInfo buf, XLogReaderState *record)
Definition: xlogdesc.c:58
void XLogRecGetBlockRefInfo(XLogReaderState *record, bool pretty, bool detailed_format, StringInfo buf, uint32 *fpi_len)
Definition: xlogdesc.c:231
static const char * get_wal_level_string(int wal_level)
Definition: xlogdesc.c:40
const char * xlog_identify(uint8 info)
Definition: xlogdesc.c:173
const struct config_enum_entry wal_level_options[]
Definition: xlogdesc.c:27
bool XLogRecGetBlockTagExtended(XLogReaderState *record, uint8 block_id, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum, Buffer *prefetch_buffer)
Definition: xlogreader.c:1997
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:410
#define XLogRecBlockImageApply(decoder, block_id)
Definition: xlogreader.h:425
#define XLogRecGetData(decoder)
Definition: xlogreader.h:415
#define XLogRecGetBlock(decoder, i)
Definition: xlogreader.h:419
#define XLogRecMaxBlockId(decoder)
Definition: xlogreader.h:418
#define XLogRecHasBlockImage(decoder, block_id)
Definition: xlogreader.h:423
#define BKPIMAGE_COMPRESS_ZSTD
Definition: xlogrecord.h:162
#define BKPIMAGE_COMPRESS_LZ4
Definition: xlogrecord.h:161
#define BKPIMAGE_COMPRESSED(info)
Definition: xlogrecord.h:164
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
#define BKPIMAGE_COMPRESS_PGLZ
Definition: xlogrecord.h:160