Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * heapdesc.c
4 : * rmgr descriptor routines for access/heap/heapam.c
5 : *
6 : * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/access/rmgrdesc/heapdesc.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : #include "postgres.h"
16 :
17 : #include "access/heapam_xlog.h"
18 : #include "access/rmgrdesc_utils.h"
19 :
20 : /*
21 : * NOTE: "keyname" argument cannot have trailing spaces or punctuation
22 : * characters
23 : */
24 : static void
25 124246 : infobits_desc(StringInfo buf, uint8 infobits, const char *keyname)
26 : {
27 124246 : appendStringInfo(buf, "%s: [", keyname);
28 :
29 : Assert(buf->data[buf->len - 1] != ' ');
30 :
31 124246 : if (infobits & XLHL_XMAX_IS_MULTI)
32 0 : appendStringInfoString(buf, "IS_MULTI, ");
33 124246 : if (infobits & XLHL_XMAX_LOCK_ONLY)
34 60980 : appendStringInfoString(buf, "LOCK_ONLY, ");
35 124246 : if (infobits & XLHL_XMAX_EXCL_LOCK)
36 60980 : appendStringInfoString(buf, "EXCL_LOCK, ");
37 124246 : if (infobits & XLHL_XMAX_KEYSHR_LOCK)
38 0 : appendStringInfoString(buf, "KEYSHR_LOCK, ");
39 124246 : if (infobits & XLHL_KEYS_UPDATED)
40 630 : appendStringInfoString(buf, "KEYS_UPDATED, ");
41 :
42 124246 : if (buf->data[buf->len - 1] == ' ')
43 : {
44 : /* Truncate-away final unneeded ", " */
45 : Assert(buf->data[buf->len - 2] == ',');
46 61610 : buf->len -= 2;
47 61610 : buf->data[buf->len] = '\0';
48 : }
49 :
50 124246 : appendStringInfoChar(buf, ']');
51 124246 : }
52 :
53 : static void
54 12 : truncate_flags_desc(StringInfo buf, uint8 flags)
55 : {
56 12 : appendStringInfoString(buf, "flags: [");
57 :
58 12 : if (flags & XLH_TRUNCATE_CASCADE)
59 0 : appendStringInfoString(buf, "CASCADE, ");
60 12 : if (flags & XLH_TRUNCATE_RESTART_SEQS)
61 0 : appendStringInfoString(buf, "RESTART_SEQS, ");
62 :
63 12 : if (buf->data[buf->len - 1] == ' ')
64 : {
65 : /* Truncate-away final unneeded ", " */
66 : Assert(buf->data[buf->len - 2] == ',');
67 0 : buf->len -= 2;
68 0 : buf->data[buf->len] = '\0';
69 : }
70 :
71 12 : appendStringInfoChar(buf, ']');
72 12 : }
73 :
74 : static void
75 1192 : plan_elem_desc(StringInfo buf, void *plan, void *data)
76 : {
77 1192 : xl_heap_freeze_plan *new_plan = (xl_heap_freeze_plan *) plan;
78 1192 : OffsetNumber **offsets = data;
79 :
80 1192 : appendStringInfo(buf, "{ xmax: %u, infomask: %u, infomask2: %u, ntuples: %u",
81 : new_plan->xmax,
82 1192 : new_plan->t_infomask, new_plan->t_infomask2,
83 1192 : new_plan->ntuples);
84 :
85 1192 : appendStringInfoString(buf, ", offsets:");
86 1192 : array_desc(buf, *offsets, sizeof(OffsetNumber), new_plan->ntuples,
87 : &offset_elem_desc, NULL);
88 :
89 1192 : *offsets += new_plan->ntuples;
90 :
91 1192 : appendStringInfoString(buf, " }");
92 1192 : }
93 :
94 : void
95 270430 : heap_desc(StringInfo buf, XLogReaderState *record)
96 : {
97 270430 : char *rec = XLogRecGetData(record);
98 270430 : uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
99 :
100 270430 : info &= XLOG_HEAP_OPMASK;
101 270430 : if (info == XLOG_HEAP_INSERT)
102 : {
103 143526 : xl_heap_insert *xlrec = (xl_heap_insert *) rec;
104 :
105 143526 : appendStringInfo(buf, "off: %u, flags: 0x%02X",
106 143526 : xlrec->offnum,
107 143526 : xlrec->flags);
108 : }
109 126904 : else if (info == XLOG_HEAP_DELETE)
110 : {
111 630 : xl_heap_delete *xlrec = (xl_heap_delete *) rec;
112 :
113 630 : appendStringInfo(buf, "xmax: %u, off: %u, ",
114 630 : xlrec->xmax, xlrec->offnum);
115 630 : infobits_desc(buf, xlrec->infobits_set, "infobits");
116 630 : appendStringInfo(buf, ", flags: 0x%02X", xlrec->flags);
117 : }
118 126274 : else if (info == XLOG_HEAP_UPDATE)
119 : {
120 61040 : xl_heap_update *xlrec = (xl_heap_update *) rec;
121 :
122 61040 : appendStringInfo(buf, "old_xmax: %u, old_off: %u, ",
123 61040 : xlrec->old_xmax, xlrec->old_offnum);
124 61040 : infobits_desc(buf, xlrec->old_infobits_set, "old_infobits");
125 61040 : appendStringInfo(buf, ", flags: 0x%02X, new_xmax: %u, new_off: %u",
126 61040 : xlrec->flags, xlrec->new_xmax, xlrec->new_offnum);
127 : }
128 65234 : else if (info == XLOG_HEAP_HOT_UPDATE)
129 : {
130 1596 : xl_heap_update *xlrec = (xl_heap_update *) rec;
131 :
132 1596 : appendStringInfo(buf, "old_xmax: %u, old_off: %u, ",
133 1596 : xlrec->old_xmax, xlrec->old_offnum);
134 1596 : infobits_desc(buf, xlrec->old_infobits_set, "old_infobits");
135 1596 : appendStringInfo(buf, ", flags: 0x%02X, new_xmax: %u, new_off: %u",
136 1596 : xlrec->flags, xlrec->new_xmax, xlrec->new_offnum);
137 : }
138 63638 : else if (info == XLOG_HEAP_TRUNCATE)
139 : {
140 12 : xl_heap_truncate *xlrec = (xl_heap_truncate *) rec;
141 :
142 12 : truncate_flags_desc(buf, xlrec->flags);
143 12 : appendStringInfo(buf, ", nrelids: %u", xlrec->nrelids);
144 12 : appendStringInfoString(buf, ", relids:");
145 12 : array_desc(buf, xlrec->relids, sizeof(Oid), xlrec->nrelids,
146 : &oid_elem_desc, NULL);
147 : }
148 63626 : else if (info == XLOG_HEAP_CONFIRM)
149 : {
150 0 : xl_heap_confirm *xlrec = (xl_heap_confirm *) rec;
151 :
152 0 : appendStringInfo(buf, "off: %u", xlrec->offnum);
153 : }
154 63626 : else if (info == XLOG_HEAP_LOCK)
155 : {
156 60980 : xl_heap_lock *xlrec = (xl_heap_lock *) rec;
157 :
158 60980 : appendStringInfo(buf, "xmax: %u, off: %u, ",
159 60980 : xlrec->xmax, xlrec->offnum);
160 60980 : infobits_desc(buf, xlrec->infobits_set, "infobits");
161 60980 : appendStringInfo(buf, ", flags: 0x%02X", xlrec->flags);
162 : }
163 2646 : else if (info == XLOG_HEAP_INPLACE)
164 : {
165 2646 : xl_heap_inplace *xlrec = (xl_heap_inplace *) rec;
166 :
167 2646 : appendStringInfo(buf, "off: %u", xlrec->offnum);
168 : }
169 270430 : }
170 :
171 : void
172 17598 : heap2_desc(StringInfo buf, XLogReaderState *record)
173 : {
174 17598 : char *rec = XLogRecGetData(record);
175 17598 : uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
176 :
177 17598 : info &= XLOG_HEAP_OPMASK;
178 17598 : if (info == XLOG_HEAP2_PRUNE)
179 : {
180 1482 : xl_heap_prune *xlrec = (xl_heap_prune *) rec;
181 :
182 1482 : appendStringInfo(buf, "snapshotConflictHorizon: %u, nredirected: %u, ndead: %u",
183 : xlrec->snapshotConflictHorizon,
184 1482 : xlrec->nredirected,
185 1482 : xlrec->ndead);
186 :
187 1482 : if (XLogRecHasBlockData(record, 0))
188 : {
189 : OffsetNumber *end;
190 : OffsetNumber *redirected;
191 : OffsetNumber *nowdead;
192 : OffsetNumber *nowunused;
193 : int nredirected;
194 : int nunused;
195 : Size datalen;
196 :
197 1468 : redirected = (OffsetNumber *) XLogRecGetBlockData(record, 0,
198 : &datalen);
199 :
200 1468 : nredirected = xlrec->nredirected;
201 1468 : end = (OffsetNumber *) ((char *) redirected + datalen);
202 1468 : nowdead = redirected + (nredirected * 2);
203 1468 : nowunused = nowdead + xlrec->ndead;
204 1468 : nunused = (end - nowunused);
205 : Assert(nunused >= 0);
206 :
207 1468 : appendStringInfo(buf, ", nunused: %d", nunused);
208 :
209 1468 : appendStringInfoString(buf, ", redirected:");
210 1468 : array_desc(buf, redirected, sizeof(OffsetNumber) * 2,
211 : nredirected, &redirect_elem_desc, NULL);
212 1468 : appendStringInfoString(buf, ", dead:");
213 1468 : array_desc(buf, nowdead, sizeof(OffsetNumber), xlrec->ndead,
214 : &offset_elem_desc, NULL);
215 1468 : appendStringInfoString(buf, ", unused:");
216 1468 : array_desc(buf, nowunused, sizeof(OffsetNumber), nunused,
217 : &offset_elem_desc, NULL);
218 : }
219 : }
220 16116 : else if (info == XLOG_HEAP2_VACUUM)
221 : {
222 564 : xl_heap_vacuum *xlrec = (xl_heap_vacuum *) rec;
223 :
224 564 : appendStringInfo(buf, "nunused: %u", xlrec->nunused);
225 :
226 564 : if (XLogRecHasBlockData(record, 0))
227 : {
228 : OffsetNumber *nowunused;
229 :
230 564 : nowunused = (OffsetNumber *) XLogRecGetBlockData(record, 0, NULL);
231 :
232 564 : appendStringInfoString(buf, ", unused:");
233 564 : array_desc(buf, nowunused, sizeof(OffsetNumber), xlrec->nunused,
234 : &offset_elem_desc, NULL);
235 : }
236 : }
237 15552 : else if (info == XLOG_HEAP2_FREEZE_PAGE)
238 : {
239 988 : xl_heap_freeze_page *xlrec = (xl_heap_freeze_page *) rec;
240 :
241 988 : appendStringInfo(buf, "snapshotConflictHorizon: %u, nplans: %u",
242 988 : xlrec->snapshotConflictHorizon, xlrec->nplans);
243 :
244 988 : if (XLogRecHasBlockData(record, 0))
245 : {
246 : xl_heap_freeze_plan *plans;
247 : OffsetNumber *offsets;
248 :
249 988 : plans = (xl_heap_freeze_plan *) XLogRecGetBlockData(record, 0, NULL);
250 988 : offsets = (OffsetNumber *) ((char *) plans +
251 988 : (xlrec->nplans *
252 : sizeof(xl_heap_freeze_plan)));
253 988 : appendStringInfoString(buf, ", plans:");
254 988 : array_desc(buf, plans, sizeof(xl_heap_freeze_plan), xlrec->nplans,
255 : &plan_elem_desc, &offsets);
256 : }
257 : }
258 14564 : else if (info == XLOG_HEAP2_VISIBLE)
259 : {
260 3112 : xl_heap_visible *xlrec = (xl_heap_visible *) rec;
261 :
262 3112 : appendStringInfo(buf, "snapshotConflictHorizon: %u, flags: 0x%02X",
263 3112 : xlrec->snapshotConflictHorizon, xlrec->flags);
264 : }
265 11452 : else if (info == XLOG_HEAP2_MULTI_INSERT)
266 : {
267 7694 : xl_heap_multi_insert *xlrec = (xl_heap_multi_insert *) rec;
268 7694 : bool isinit = (XLogRecGetInfo(record) & XLOG_HEAP_INIT_PAGE) != 0;
269 :
270 7694 : appendStringInfo(buf, "ntuples: %d, flags: 0x%02X", xlrec->ntuples,
271 7694 : xlrec->flags);
272 :
273 7694 : if (XLogRecHasBlockData(record, 0) && !isinit)
274 : {
275 7384 : appendStringInfoString(buf, ", offsets:");
276 7384 : array_desc(buf, xlrec->offsets, sizeof(OffsetNumber),
277 7384 : xlrec->ntuples, &offset_elem_desc, NULL);
278 : }
279 : }
280 3758 : else if (info == XLOG_HEAP2_LOCK_UPDATED)
281 : {
282 0 : xl_heap_lock_updated *xlrec = (xl_heap_lock_updated *) rec;
283 :
284 0 : appendStringInfo(buf, "xmax: %u, off: %u, ",
285 0 : xlrec->xmax, xlrec->offnum);
286 0 : infobits_desc(buf, xlrec->infobits_set, "infobits");
287 0 : appendStringInfo(buf, ", flags: 0x%02X", xlrec->flags);
288 : }
289 3758 : else if (info == XLOG_HEAP2_NEW_CID)
290 : {
291 3758 : xl_heap_new_cid *xlrec = (xl_heap_new_cid *) rec;
292 :
293 3758 : appendStringInfo(buf, "rel: %u/%u/%u, tid: %u/%u",
294 : xlrec->target_locator.spcOid,
295 : xlrec->target_locator.dbOid,
296 : xlrec->target_locator.relNumber,
297 3758 : ItemPointerGetBlockNumber(&(xlrec->target_tid)),
298 3758 : ItemPointerGetOffsetNumber(&(xlrec->target_tid)));
299 3758 : appendStringInfo(buf, ", cmin: %u, cmax: %u, combo: %u",
300 : xlrec->cmin, xlrec->cmax, xlrec->combocid);
301 : }
302 17598 : }
303 :
304 : const char *
305 270448 : heap_identify(uint8 info)
306 : {
307 270448 : const char *id = NULL;
308 :
309 270448 : switch (info & ~XLR_INFO_MASK)
310 : {
311 142114 : case XLOG_HEAP_INSERT:
312 142114 : id = "INSERT";
313 142114 : break;
314 1416 : case XLOG_HEAP_INSERT | XLOG_HEAP_INIT_PAGE:
315 1416 : id = "INSERT+INIT";
316 1416 : break;
317 632 : case XLOG_HEAP_DELETE:
318 632 : id = "DELETE";
319 632 : break;
320 60606 : case XLOG_HEAP_UPDATE:
321 60606 : id = "UPDATE";
322 60606 : break;
323 438 : case XLOG_HEAP_UPDATE | XLOG_HEAP_INIT_PAGE:
324 438 : id = "UPDATE+INIT";
325 438 : break;
326 1598 : case XLOG_HEAP_HOT_UPDATE:
327 1598 : id = "HOT_UPDATE";
328 1598 : break;
329 0 : case XLOG_HEAP_HOT_UPDATE | XLOG_HEAP_INIT_PAGE:
330 0 : id = "HOT_UPDATE+INIT";
331 0 : break;
332 14 : case XLOG_HEAP_TRUNCATE:
333 14 : id = "TRUNCATE";
334 14 : break;
335 0 : case XLOG_HEAP_CONFIRM:
336 0 : id = "HEAP_CONFIRM";
337 0 : break;
338 60982 : case XLOG_HEAP_LOCK:
339 60982 : id = "LOCK";
340 60982 : break;
341 2648 : case XLOG_HEAP_INPLACE:
342 2648 : id = "INPLACE";
343 2648 : break;
344 : }
345 :
346 270448 : return id;
347 : }
348 :
349 : const char *
350 17610 : heap2_identify(uint8 info)
351 : {
352 17610 : const char *id = NULL;
353 :
354 17610 : switch (info & ~XLR_INFO_MASK)
355 : {
356 1484 : case XLOG_HEAP2_PRUNE:
357 1484 : id = "PRUNE";
358 1484 : break;
359 566 : case XLOG_HEAP2_VACUUM:
360 566 : id = "VACUUM";
361 566 : break;
362 988 : case XLOG_HEAP2_FREEZE_PAGE:
363 988 : id = "FREEZE_PAGE";
364 988 : break;
365 3114 : case XLOG_HEAP2_VISIBLE:
366 3114 : id = "VISIBLE";
367 3114 : break;
368 7464 : case XLOG_HEAP2_MULTI_INSERT:
369 7464 : id = "MULTI_INSERT";
370 7464 : break;
371 234 : case XLOG_HEAP2_MULTI_INSERT | XLOG_HEAP_INIT_PAGE:
372 234 : id = "MULTI_INSERT+INIT";
373 234 : break;
374 0 : case XLOG_HEAP2_LOCK_UPDATED:
375 0 : id = "LOCK_UPDATED";
376 0 : break;
377 3760 : case XLOG_HEAP2_NEW_CID:
378 3760 : id = "NEW_CID";
379 3760 : break;
380 0 : case XLOG_HEAP2_REWRITE:
381 0 : id = "REWRITE";
382 0 : break;
383 : }
384 :
385 17610 : return id;
386 : }
|