Age Owner Branch data TLA Line data Source code
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 : : void
3433 heikki.linnakangas@i 37 :CBC 7140 : xlog_desc(StringInfo buf, XLogReaderState *record)
38 : : {
3592 39 : 7140 : char *rec = XLogRecGetData(record);
3433 40 : 7140 : uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
41 : :
4155 alvherre@alvh.no-ip. 42 [ + + + + ]: 7140 : if (info == XLOG_CHECKPOINT_SHUTDOWN ||
43 : : info == XLOG_CHECKPOINT_ONLINE)
44 : 23 : {
45 : 23 : CheckPoint *checkpoint = (CheckPoint *) rec;
46 : :
3495 andres@anarazel.de 47 [ + + ]: 46 : appendStringInfo(buf, "redo %X/%X; "
48 : : "tli %u; prev tli %u; fpw %s; xid %u:%u; oid %u; multi %u; offset %u; "
49 : : "oldest xid %u in DB %u; oldest multi %u in DB %u; "
50 : : "oldest/newest commit timestamp xid: %u/%u; "
51 : : "oldest running xid %u; %s",
1146 peter@eisentraut.org 52 : 23 : LSN_FORMAT_ARGS(checkpoint->redo),
53 : : checkpoint->ThisTimeLineID,
54 : : checkpoint->PrevTimeLineID,
4155 alvherre@alvh.no-ip. 55 : 23 : checkpoint->fullPageWrites ? "true" : "false",
1342 andres@anarazel.de 56 : 23 : EpochFromFullTransactionId(checkpoint->nextXid),
57 [ + + ]: 23 : XidFromFullTransactionId(checkpoint->nextXid),
58 : : checkpoint->nextOid,
59 : : checkpoint->nextMulti,
60 : : checkpoint->nextMultiOffset,
61 : : checkpoint->oldestXid,
62 : : checkpoint->oldestXidDB,
63 : : checkpoint->oldestMulti,
64 : : checkpoint->oldestMultiDB,
65 : : checkpoint->oldestCommitTsXid,
66 : : checkpoint->newestCommitTsXid,
67 : : checkpoint->oldestActiveXid,
68 : : (info == XLOG_CHECKPOINT_SHUTDOWN) ? "shutdown" : "online");
69 : : }
4155 alvherre@alvh.no-ip. 70 [ + + ]: 7117 : else if (info == XLOG_NEXTOID)
71 : : {
72 : : Oid nextOid;
73 : :
74 : 13 : memcpy(&nextOid, rec, sizeof(Oid));
3495 andres@anarazel.de 75 : 13 : appendStringInfo(buf, "%u", nextOid);
76 : : }
4155 alvherre@alvh.no-ip. 77 [ - + ]: 7104 : else if (info == XLOG_RESTORE_POINT)
78 : : {
4155 alvherre@alvh.no-ip. 79 :UBC 0 : xl_restore_point *xlrec = (xl_restore_point *) rec;
80 : :
3261 peter_e@gmx.net 81 : 0 : appendStringInfoString(buf, xlrec->rp_name);
82 : : }
3429 heikki.linnakangas@i 83 [ + + + + ]:CBC 7104 : else if (info == XLOG_FPI || info == XLOG_FPI_FOR_HINT)
84 : : {
85 : : /* no further information to print */
86 : : }
4155 alvherre@alvh.no-ip. 87 [ + + ]: 33 : else if (info == XLOG_BACKUP_END)
88 : : {
89 : : XLogRecPtr startpoint;
90 : :
91 : 4 : memcpy(&startpoint, rec, sizeof(XLogRecPtr));
1146 peter@eisentraut.org 92 : 4 : appendStringInfo(buf, "%X/%X", LSN_FORMAT_ARGS(startpoint));
93 : : }
4155 alvherre@alvh.no-ip. 94 [ + + ]: 29 : else if (info == XLOG_PARAMETER_CHANGE)
95 : : {
96 : : xl_parameter_change xlrec;
97 : : const char *wal_level_str;
98 : : const struct config_enum_entry *entry;
99 : :
100 : 8 : memcpy(&xlrec, rec, sizeof(xl_parameter_change));
101 : :
102 : : /* Find a string representation for wal_level */
103 : 8 : wal_level_str = "?";
104 [ + - ]: 20 : for (entry = wal_level_options; entry->name; entry++)
105 : : {
106 [ + + ]: 20 : if (entry->val == xlrec.wal_level)
107 : : {
108 : 8 : wal_level_str = entry->name;
109 : 8 : break;
110 : : }
111 : : }
112 : :
3418 heikki.linnakangas@i 113 :UBC 0 : appendStringInfo(buf, "max_connections=%d max_worker_processes=%d "
114 : : "max_wal_senders=%d max_prepared_xacts=%d "
115 : : "max_locks_per_xact=%d wal_level=%s "
116 : : "wal_log_hints=%s track_commit_timestamp=%s",
117 : : xlrec.MaxConnections,
118 : : xlrec.max_worker_processes,
119 : : xlrec.max_wal_senders,
120 : : xlrec.max_prepared_xacts,
121 : : xlrec.max_locks_per_xact,
122 : : wal_level_str,
3418 heikki.linnakangas@i 123 [ + + ]:CBC 8 : xlrec.wal_log_hints ? "on" : "off",
124 [ - + ]: 8 : xlrec.track_commit_timestamp ? "on" : "off");
125 : : }
4155 alvherre@alvh.no-ip. 126 [ - + ]: 21 : else if (info == XLOG_FPW_CHANGE)
127 : : {
128 : : bool fpw;
129 : :
4155 alvherre@alvh.no-ip. 130 :UBC 0 : memcpy(&fpw, rec, sizeof(bool));
3261 peter_e@gmx.net 131 [ # # ]: 0 : appendStringInfoString(buf, fpw ? "true" : "false");
132 : : }
4093 simon@2ndQuadrant.co 133 [ - + ]:CBC 21 : else if (info == XLOG_END_OF_RECOVERY)
134 : : {
135 : : xl_end_of_recovery xlrec;
136 : :
4093 simon@2ndQuadrant.co 137 :UBC 0 : memcpy(&xlrec, rec, sizeof(xl_end_of_recovery));
3495 andres@anarazel.de 138 : 0 : appendStringInfo(buf, "tli %u; prev tli %u; time %s",
139 : : xlrec.ThisTimeLineID, xlrec.PrevTimeLineID,
140 : : timestamptz_to_str(xlrec.end_time));
141 : : }
928 alvherre@alvh.no-ip. 142 [ + + ]:CBC 21 : else if (info == XLOG_OVERWRITE_CONTRECORD)
143 : : {
144 : : xl_overwrite_contrecord xlrec;
145 : :
146 : 1 : memcpy(&xlrec, rec, sizeof(xl_overwrite_contrecord));
147 : 1 : appendStringInfo(buf, "lsn %X/%X; time %s",
148 : 1 : LSN_FORMAT_ARGS(xlrec.overwritten_lsn),
149 : : timestamptz_to_str(xlrec.overwrite_time));
150 : : }
151 : : else if (info == XLOG_CHECKPOINT_REDO)
152 : : {
153 : : /* No details to write out */
154 : : }
3495 andres@anarazel.de 155 : 7140 : }
156 : :
157 : : const char *
158 : 7144 : xlog_identify(uint8 info)
159 : : {
160 : 7144 : const char *id = NULL;
161 : :
3492 162 [ + + - + : 7144 : switch (info & ~XLR_INFO_MASK)
+ + + - -
- + + + +
- ]
163 : : {
3495 164 : 9 : case XLOG_CHECKPOINT_SHUTDOWN:
165 : 9 : id = "CHECKPOINT_SHUTDOWN";
166 : 9 : break;
3495 andres@anarazel.de 167 :GBC 15 : case XLOG_CHECKPOINT_ONLINE:
168 : 15 : id = "CHECKPOINT_ONLINE";
169 : 15 : break;
3495 andres@anarazel.de 170 :UBC 0 : case XLOG_NOOP:
171 : 0 : id = "NOOP";
172 : 0 : break;
3495 andres@anarazel.de 173 :CBC 14 : case XLOG_NEXTOID:
174 : 14 : id = "NEXTOID";
175 : 14 : break;
176 : 5 : case XLOG_SWITCH:
177 : 5 : id = "SWITCH";
178 : 5 : break;
179 : 4 : case XLOG_BACKUP_END:
180 : 4 : id = "BACKUP_END";
181 : 4 : break;
182 : 8 : case XLOG_PARAMETER_CHANGE:
183 : 8 : id = "PARAMETER_CHANGE";
184 : 8 : break;
3495 andres@anarazel.de 185 :UBC 0 : case XLOG_RESTORE_POINT:
186 : 0 : id = "RESTORE_POINT";
187 : 0 : break;
188 : 0 : case XLOG_FPW_CHANGE:
189 : 0 : id = "FPW_CHANGE";
190 : 0 : break;
191 : 0 : case XLOG_END_OF_RECOVERY:
192 : 0 : id = "END_OF_RECOVERY";
193 : 0 : break;
928 alvherre@alvh.no-ip. 194 :CBC 1 : case XLOG_OVERWRITE_CONTRECORD:
195 : 1 : id = "OVERWRITE_CONTRECORD";
196 : 1 : break;
3495 andres@anarazel.de 197 : 7062 : case XLOG_FPI:
198 : 7062 : id = "FPI";
199 : 7062 : break;
3429 heikki.linnakangas@i 200 : 10 : case XLOG_FPI_FOR_HINT:
201 : 10 : id = "FPI_FOR_HINT";
202 : 10 : break;
178 rhaas@postgresql.org 203 :GNC 16 : case XLOG_CHECKPOINT_REDO:
204 : 16 : id = "CHECKPOINT_REDO";
205 : 16 : break;
206 : : }
207 : :
3495 andres@anarazel.de 208 :CBC 7144 : return id;
209 : : }
210 : :
211 : : /*
212 : : * Returns a string giving information about all the blocks in an
213 : : * XLogRecord.
214 : : */
215 : : void
737 jdavis@postgresql.or 216 : 294694 : XLogRecGetBlockRefInfo(XLogReaderState *record, bool pretty,
217 : : bool detailed_format, StringInfo buf,
218 : : uint32 *fpi_len)
219 : : {
220 : : int block_id;
221 : :
222 [ - + ]: 294694 : Assert(record != NULL);
223 : :
224 [ + + - + ]: 294694 : if (detailed_format && pretty)
737 jdavis@postgresql.or 225 :UBC 0 : appendStringInfoChar(buf, '\n');
226 : :
737 jdavis@postgresql.or 227 [ + + ]:CBC 618939 : for (block_id = 0; block_id <= XLogRecMaxBlockId(record); block_id++)
228 : : {
229 : : RelFileLocator rlocator;
230 : : ForkNumber forknum;
231 : : BlockNumber blk;
232 : :
734 tgl@sss.pgh.pa.us 233 [ + + ]: 324245 : if (!XLogRecGetBlockTagExtended(record, block_id,
234 : : &rlocator, &forknum, &blk, NULL))
737 jdavis@postgresql.or 235 : 92 : continue;
236 : :
237 [ + + ]: 324153 : if (detailed_format)
238 : : {
239 : : /* Get block references in detailed format. */
240 : :
241 [ - + ]: 36331 : if (pretty)
737 jdavis@postgresql.or 242 :UBC 0 : appendStringInfoChar(buf, '\t');
737 jdavis@postgresql.or 243 [ + + ]:CBC 36331 : else if (block_id > 0)
244 : 2012 : appendStringInfoChar(buf, ' ');
245 : :
246 : 36331 : appendStringInfo(buf,
247 : : "blkref #%d: rel %u/%u/%u fork %s blk %u",
248 : : block_id,
249 : : rlocator.spcOid, rlocator.dbOid, rlocator.relNumber,
250 : 36331 : forkNames[forknum],
251 : : blk);
252 : :
253 [ + + ]: 36331 : if (XLogRecHasBlockImage(record, block_id))
254 : : {
255 : 5260 : uint8 bimg_info = XLogRecGetBlock(record, block_id)->bimg_info;
256 : :
257 : : /* Calculate the amount of FPI data in the record. */
258 [ + - ]: 5260 : if (fpi_len)
259 : 5260 : *fpi_len += XLogRecGetBlock(record, block_id)->bimg_len;
260 : :
261 [ - + ]: 5260 : if (BKPIMAGE_COMPRESSED(bimg_info))
262 : : {
263 : : const char *method;
264 : :
737 jdavis@postgresql.or 265 [ # # ]:UBC 0 : if ((bimg_info & BKPIMAGE_COMPRESS_PGLZ) != 0)
266 : 0 : method = "pglz";
267 [ # # ]: 0 : else if ((bimg_info & BKPIMAGE_COMPRESS_LZ4) != 0)
268 : 0 : method = "lz4";
269 [ # # ]: 0 : else if ((bimg_info & BKPIMAGE_COMPRESS_ZSTD) != 0)
270 : 0 : method = "zstd";
271 : : else
272 : 0 : method = "unknown";
273 : :
274 : 0 : appendStringInfo(buf,
275 : : " (FPW%s); hole: offset: %u, length: %u, "
276 : : "compression saved: %u, method: %s",
277 : 0 : XLogRecBlockImageApply(record, block_id) ?
278 : : "" : " for WAL verification",
279 : 0 : XLogRecGetBlock(record, block_id)->hole_offset,
280 : 0 : XLogRecGetBlock(record, block_id)->hole_length,
281 : : BLCKSZ -
282 : 0 : XLogRecGetBlock(record, block_id)->hole_length -
283 [ # # ]: 0 : XLogRecGetBlock(record, block_id)->bimg_len,
284 : : method);
285 : : }
286 : : else
287 : : {
737 jdavis@postgresql.or 288 :CBC 5260 : appendStringInfo(buf,
289 : : " (FPW%s); hole: offset: %u, length: %u",
290 : 5260 : XLogRecBlockImageApply(record, block_id) ?
291 : : "" : " for WAL verification",
292 : 5260 : XLogRecGetBlock(record, block_id)->hole_offset,
293 [ + + ]: 5260 : XLogRecGetBlock(record, block_id)->hole_length);
294 : : }
295 : : }
296 : :
297 [ - + ]: 36331 : if (pretty)
737 jdavis@postgresql.or 298 :UBC 0 : appendStringInfoChar(buf, '\n');
299 : : }
300 : : else
301 : : {
302 : : /* Get block references in short format. */
303 : :
737 jdavis@postgresql.or 304 [ + + ]:GBC 287822 : if (forknum != MAIN_FORKNUM)
305 : : {
306 : 2616 : appendStringInfo(buf,
307 : : ", blkref #%d: rel %u/%u/%u fork %s blk %u",
308 : : block_id,
309 : : rlocator.spcOid, rlocator.dbOid, rlocator.relNumber,
310 : 2616 : forkNames[forknum],
311 : : blk);
312 : : }
313 : : else
314 : : {
315 : 285206 : appendStringInfo(buf,
316 : : ", blkref #%d: rel %u/%u/%u blk %u",
317 : : block_id,
318 : : rlocator.spcOid, rlocator.dbOid, rlocator.relNumber,
319 : : blk);
320 : : }
321 : :
322 [ + + ]: 287822 : if (XLogRecHasBlockImage(record, block_id))
323 : : {
324 : : /* Calculate the amount of FPI data in the record. */
325 [ - + ]: 8248 : if (fpi_len)
737 jdavis@postgresql.or 326 :UBC 0 : *fpi_len += XLogRecGetBlock(record, block_id)->bimg_len;
327 : :
737 jdavis@postgresql.or 328 [ + - ]:GBC 8248 : if (XLogRecBlockImageApply(record, block_id))
586 drowley@postgresql.o 329 : 8248 : appendStringInfoString(buf, " FPW");
330 : : else
586 drowley@postgresql.o 331 :UBC 0 : appendStringInfoString(buf, " FPW for WAL verification");
332 : : }
333 : : }
334 : : }
335 : :
737 jdavis@postgresql.or 336 [ + + + - ]:CBC 294694 : if (!detailed_format && pretty)
737 jdavis@postgresql.or 337 :GBC 260375 : appendStringInfoChar(buf, '\n');
737 jdavis@postgresql.or 338 :CBC 294694 : }
|