TLA 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 : static void
21 GIC 41 : out_infobits(StringInfo buf, uint8 infobits)
22 ECB : {
23 GNC 41 : if ((infobits & XLHL_XMAX_IS_MULTI) == 0 &&
24 41 : (infobits & XLHL_XMAX_LOCK_ONLY) == 0 &&
25 30 : (infobits & XLHL_XMAX_EXCL_LOCK) == 0 &&
26 30 : (infobits & XLHL_XMAX_KEYSHR_LOCK) == 0 &&
27 30 : (infobits & XLHL_KEYS_UPDATED) == 0)
28 22 : return;
29 :
30 19 : appendStringInfoString(buf, ", infobits: [");
31 :
32 GIC 19 : if (infobits & XLHL_XMAX_IS_MULTI)
33 UNC 0 : appendStringInfoString(buf, " IS_MULTI");
34 CBC 19 : if (infobits & XLHL_XMAX_LOCK_ONLY)
35 GNC 11 : appendStringInfoString(buf, ", LOCK_ONLY");
36 CBC 19 : if (infobits & XLHL_XMAX_EXCL_LOCK)
37 GNC 11 : appendStringInfoString(buf, ", EXCL_LOCK");
38 CBC 19 : if (infobits & XLHL_XMAX_KEYSHR_LOCK)
39 UNC 0 : appendStringInfoString(buf, ", KEYSHR_LOCK");
40 CBC 19 : if (infobits & XLHL_KEYS_UPDATED)
41 GNC 8 : appendStringInfoString(buf, ", KEYS_UPDATED");
42 :
43 19 : appendStringInfoString(buf, " ]");
44 : }
45 :
46 : static void
47 UNC 0 : plan_elem_desc(StringInfo buf, void *plan, void *data)
48 : {
49 0 : xl_heap_freeze_plan *new_plan = (xl_heap_freeze_plan *) plan;
50 0 : OffsetNumber **offsets = data;
51 :
52 0 : appendStringInfo(buf, "{ xmax: %u, infomask: %u, infomask2: %u, ntuples: %u",
53 : new_plan->xmax,
54 0 : new_plan->t_infomask, new_plan->t_infomask2,
55 0 : new_plan->ntuples);
56 :
57 0 : appendStringInfoString(buf, ", offsets:");
58 0 : array_desc(buf, *offsets, sizeof(OffsetNumber), new_plan->ntuples,
59 : &offset_elem_desc, NULL);
60 :
61 0 : *offsets += new_plan->ntuples;
62 :
63 0 : appendStringInfo(buf, " }");
64 LBC 0 : }
65 EUB :
66 ECB : void
67 CBC 30937 : heap_desc(StringInfo buf, XLogReaderState *record)
68 ECB : {
69 CBC 30937 : char *rec = XLogRecGetData(record);
70 30937 : uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
71 EUB :
72 CBC 30937 : info &= XLOG_HEAP_OPMASK;
73 30937 : if (info == XLOG_HEAP_INSERT)
74 : {
75 30896 : xl_heap_insert *xlrec = (xl_heap_insert *) rec;
76 :
77 GNC 30896 : appendStringInfo(buf, "off: %u, flags: 0x%02X",
78 30896 : xlrec->offnum,
79 GIC 30896 : xlrec->flags);
80 EUB : }
81 GIC 41 : else if (info == XLOG_HEAP_DELETE)
82 EUB : {
83 GBC 8 : xl_heap_delete *xlrec = (xl_heap_delete *) rec;
84 :
85 GNC 8 : appendStringInfo(buf, "off: %u, flags: 0x%02X",
86 GIC 8 : xlrec->offnum,
87 GBC 8 : xlrec->flags);
88 8 : out_infobits(buf, xlrec->infobits_set);
89 : }
90 33 : else if (info == XLOG_HEAP_UPDATE)
91 EUB : {
92 GIC 10 : xl_heap_update *xlrec = (xl_heap_update *) rec;
93 :
94 GNC 10 : appendStringInfo(buf, "off: %u, xmax: %u, flags: 0x%02X",
95 GIC 10 : xlrec->old_offnum,
96 EUB : xlrec->old_xmax,
97 GBC 10 : xlrec->flags);
98 GIC 10 : out_infobits(buf, xlrec->old_infobits_set);
99 GNC 10 : appendStringInfo(buf, ", new off: %u, xmax %u",
100 CBC 10 : xlrec->new_offnum,
101 : xlrec->new_xmax);
102 ECB : }
103 CBC 23 : else if (info == XLOG_HEAP_HOT_UPDATE)
104 : {
105 12 : xl_heap_update *xlrec = (xl_heap_update *) rec;
106 ECB :
107 GNC 12 : appendStringInfo(buf, "off: %u, xmax: %u, flags: 0x%02X",
108 CBC 12 : xlrec->old_offnum,
109 : xlrec->old_xmax,
110 12 : xlrec->flags);
111 12 : out_infobits(buf, xlrec->old_infobits_set);
112 GNC 12 : appendStringInfo(buf, ", new off: %u, xmax: %u",
113 GIC 12 : xlrec->new_offnum,
114 ECB : xlrec->new_xmax);
115 : }
116 CBC 11 : else if (info == XLOG_HEAP_TRUNCATE)
117 : {
118 LBC 0 : xl_heap_truncate *xlrec = (xl_heap_truncate *) rec;
119 ECB :
120 UNC 0 : appendStringInfoString(buf, "flags: [");
121 LBC 0 : if (xlrec->flags & XLH_TRUNCATE_CASCADE)
122 UNC 0 : appendStringInfoString(buf, " CASCADE");
123 LBC 0 : if (xlrec->flags & XLH_TRUNCATE_RESTART_SEQS)
124 UNC 0 : appendStringInfoString(buf, ", RESTART_SEQS");
125 0 : appendStringInfoString(buf, " ]");
126 :
127 0 : appendStringInfo(buf, ", nrelids: %u", xlrec->nrelids);
128 0 : appendStringInfoString(buf, ", relids:");
129 0 : array_desc(buf, xlrec->relids, sizeof(Oid), xlrec->nrelids,
130 : &relid_desc, NULL);
131 ECB : }
132 GIC 11 : else if (info == XLOG_HEAP_CONFIRM)
133 ECB : {
134 LBC 0 : xl_heap_confirm *xlrec = (xl_heap_confirm *) rec;
135 ECB :
136 UNC 0 : appendStringInfo(buf, "off: %u", xlrec->offnum);
137 : }
138 GIC 11 : else if (info == XLOG_HEAP_LOCK)
139 ECB : {
140 GIC 11 : xl_heap_lock *xlrec = (xl_heap_lock *) rec;
141 ECB :
142 GNC 11 : appendStringInfo(buf, "off: %u, xid: %u, flags: 0x%02X",
143 CBC 11 : xlrec->offnum, xlrec->locking_xid, xlrec->flags);
144 11 : out_infobits(buf, xlrec->infobits_set);
145 : }
146 LBC 0 : else if (info == XLOG_HEAP_INPLACE)
147 ECB : {
148 LBC 0 : xl_heap_inplace *xlrec = (xl_heap_inplace *) rec;
149 ECB :
150 UNC 0 : appendStringInfo(buf, "off: %u", xlrec->offnum);
151 : }
152 CBC 30937 : }
153 :
154 : void
155 GBC 63 : heap2_desc(StringInfo buf, XLogReaderState *record)
156 : {
157 63 : char *rec = XLogRecGetData(record);
158 63 : uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
159 EUB :
160 GBC 63 : info &= XLOG_HEAP_OPMASK;
161 63 : if (info == XLOG_HEAP2_PRUNE)
162 EUB : {
163 GIC 47 : xl_heap_prune *xlrec = (xl_heap_prune *) rec;
164 EUB :
165 GNC 47 : appendStringInfo(buf, "snapshotConflictHorizon: %u, nredirected: %u, ndead: %u",
166 : xlrec->snapshotConflictHorizon,
167 GIC 47 : xlrec->nredirected,
168 47 : xlrec->ndead);
169 :
170 GNC 47 : if (!XLogRecHasBlockImage(record, 0))
171 : {
172 : OffsetNumber *end;
173 : OffsetNumber *redirected;
174 : OffsetNumber *nowdead;
175 : OffsetNumber *nowunused;
176 : int nredirected;
177 : int nunused;
178 : Size datalen;
179 :
180 47 : redirected = (OffsetNumber *) XLogRecGetBlockData(record, 0,
181 : &datalen);
182 :
183 47 : nredirected = xlrec->nredirected;
184 47 : end = (OffsetNumber *) ((char *) redirected + datalen);
185 47 : nowdead = redirected + (nredirected * 2);
186 47 : nowunused = nowdead + xlrec->ndead;
187 47 : nunused = (end - nowunused);
188 47 : Assert(nunused >= 0);
189 :
190 47 : appendStringInfo(buf, ", nunused: %u", nunused);
191 :
192 47 : appendStringInfoString(buf, ", redirected:");
193 47 : array_desc(buf, redirected, sizeof(OffsetNumber) * 2,
194 : nredirected, &redirect_elem_desc, NULL);
195 47 : appendStringInfoString(buf, ", dead:");
196 47 : array_desc(buf, nowdead, sizeof(OffsetNumber), xlrec->ndead,
197 : &offset_elem_desc, NULL);
198 47 : appendStringInfoString(buf, ", unused:");
199 47 : array_desc(buf, nowunused, sizeof(OffsetNumber), nunused,
200 : &offset_elem_desc, NULL);
201 : }
202 ECB : }
203 GIC 16 : else if (info == XLOG_HEAP2_VACUUM)
204 EUB : {
205 UIC 0 : xl_heap_vacuum *xlrec = (xl_heap_vacuum *) rec;
206 EUB :
207 UNC 0 : appendStringInfo(buf, "nunused: %u", xlrec->nunused);
208 :
209 0 : if (!XLogRecHasBlockImage(record, 0))
210 : {
211 : OffsetNumber *nowunused;
212 :
213 0 : nowunused = (OffsetNumber *) XLogRecGetBlockData(record, 0, NULL);
214 :
215 0 : appendStringInfoString(buf, ", unused:");
216 0 : array_desc(buf, nowunused, sizeof(OffsetNumber), xlrec->nunused,
217 : &offset_elem_desc, NULL);
218 : }
219 ECB : }
220 GIC 16 : else if (info == XLOG_HEAP2_FREEZE_PAGE)
221 ECB : {
222 UIC 0 : xl_heap_freeze_page *xlrec = (xl_heap_freeze_page *) rec;
223 ECB :
224 UNC 0 : appendStringInfo(buf, "snapshotConflictHorizon: %u, nplans: %u",
225 0 : xlrec->snapshotConflictHorizon, xlrec->nplans);
226 :
227 0 : if (!XLogRecHasBlockImage(record, 0))
228 : {
229 : xl_heap_freeze_plan *plans;
230 : OffsetNumber *offsets;
231 :
232 0 : plans = (xl_heap_freeze_plan *) XLogRecGetBlockData(record, 0, NULL);
233 0 : offsets = (OffsetNumber *) &plans[xlrec->nplans];
234 0 : appendStringInfoString(buf, ", plans:");
235 0 : array_desc(buf, plans, sizeof(xl_heap_freeze_plan), xlrec->nplans,
236 : &plan_elem_desc, &offsets);
237 : }
238 : }
239 GBC 16 : else if (info == XLOG_HEAP2_VISIBLE)
240 : {
241 UBC 0 : xl_heap_visible *xlrec = (xl_heap_visible *) rec;
242 :
243 UNC 0 : appendStringInfo(buf, "snapshotConflictHorizon: %u, flags: 0x%02X",
244 0 : xlrec->snapshotConflictHorizon, xlrec->flags);
245 ECB : }
246 GIC 16 : else if (info == XLOG_HEAP2_MULTI_INSERT)
247 : {
248 CBC 16 : xl_heap_multi_insert *xlrec = (xl_heap_multi_insert *) rec;
249 GNC 16 : bool isinit = (XLogRecGetInfo(record) & XLOG_HEAP_INIT_PAGE) != 0;
250 :
251 16 : appendStringInfo(buf, "ntuples: %d, flags: 0x%02X", xlrec->ntuples,
252 CBC 16 : xlrec->flags);
253 :
254 GNC 16 : appendStringInfoString(buf, ", offsets:");
255 16 : if (!XLogRecHasBlockImage(record, 0) && !isinit)
256 13 : array_desc(buf, xlrec->offsets, sizeof(OffsetNumber),
257 13 : xlrec->ntuples, &offset_elem_desc, NULL);
258 : }
259 LBC 0 : else if (info == XLOG_HEAP2_LOCK_UPDATED)
260 ECB : {
261 UIC 0 : xl_heap_lock_updated *xlrec = (xl_heap_lock_updated *) rec;
262 ECB :
263 UNC 0 : appendStringInfo(buf, "off: %u, xmax: %u, flags: 0x%02X",
264 LBC 0 : xlrec->offnum, xlrec->xmax, xlrec->flags);
265 UIC 0 : out_infobits(buf, xlrec->infobits_set);
266 ECB : }
267 LBC 0 : else if (info == XLOG_HEAP2_NEW_CID)
268 : {
269 0 : xl_heap_new_cid *xlrec = (xl_heap_new_cid *) rec;
270 :
271 UNC 0 : appendStringInfo(buf, "rel: %u/%u/%u, tid: %u/%u",
272 : xlrec->target_locator.spcOid,
273 : xlrec->target_locator.dbOid,
274 : xlrec->target_locator.relNumber,
275 UIC 0 : ItemPointerGetBlockNumber(&(xlrec->target_tid)),
276 0 : ItemPointerGetOffsetNumber(&(xlrec->target_tid)));
277 UNC 0 : appendStringInfo(buf, ", cmin: %u, cmax: %u, combo: %u",
278 : xlrec->cmin, xlrec->cmax, xlrec->combocid);
279 ECB : }
280 GIC 63 : }
281 :
282 ECB : const char *
283 CBC 30937 : heap_identify(uint8 info)
284 ECB : {
285 CBC 30937 : const char *id = NULL;
286 ECB :
287 CBC 30937 : switch (info & ~XLR_INFO_MASK)
288 : {
289 29486 : case XLOG_HEAP_INSERT:
290 GIC 29486 : id = "INSERT";
291 CBC 29486 : break;
292 1410 : case XLOG_HEAP_INSERT | XLOG_HEAP_INIT_PAGE:
293 GIC 1410 : id = "INSERT+INIT";
294 CBC 1410 : break;
295 8 : case XLOG_HEAP_DELETE:
296 GIC 8 : id = "DELETE";
297 CBC 8 : break;
298 9 : case XLOG_HEAP_UPDATE:
299 GIC 9 : id = "UPDATE";
300 9 : break;
301 1 : case XLOG_HEAP_UPDATE | XLOG_HEAP_INIT_PAGE:
302 CBC 1 : id = "UPDATE+INIT";
303 GIC 1 : break;
304 GBC 12 : case XLOG_HEAP_HOT_UPDATE:
305 GIC 12 : id = "HOT_UPDATE";
306 GBC 12 : break;
307 UIC 0 : case XLOG_HEAP_HOT_UPDATE | XLOG_HEAP_INIT_PAGE:
308 UBC 0 : id = "HOT_UPDATE+INIT";
309 UIC 0 : break;
310 0 : case XLOG_HEAP_TRUNCATE:
311 0 : id = "TRUNCATE";
312 UBC 0 : break;
313 UIC 0 : case XLOG_HEAP_CONFIRM:
314 UBC 0 : id = "HEAP_CONFIRM";
315 0 : break;
316 GIC 11 : case XLOG_HEAP_LOCK:
317 11 : id = "LOCK";
318 11 : break;
319 LBC 0 : case XLOG_HEAP_INPLACE:
320 UIC 0 : id = "INPLACE";
321 UBC 0 : break;
322 : }
323 EUB :
324 GBC 30937 : return id;
325 : }
326 EUB :
327 : const char *
328 GIC 63 : heap2_identify(uint8 info)
329 : {
330 63 : const char *id = NULL;
331 EUB :
332 GBC 63 : switch (info & ~XLR_INFO_MASK)
333 EUB : {
334 GBC 47 : case XLOG_HEAP2_PRUNE:
335 GIC 47 : id = "PRUNE";
336 47 : break;
337 UIC 0 : case XLOG_HEAP2_VACUUM:
338 LBC 0 : id = "VACUUM";
339 UIC 0 : break;
340 UBC 0 : case XLOG_HEAP2_FREEZE_PAGE:
341 UIC 0 : id = "FREEZE_PAGE";
342 UBC 0 : break;
343 0 : case XLOG_HEAP2_VISIBLE:
344 UIC 0 : id = "VISIBLE";
345 LBC 0 : break;
346 GIC 16 : case XLOG_HEAP2_MULTI_INSERT:
347 CBC 16 : id = "MULTI_INSERT";
348 16 : break;
349 UIC 0 : case XLOG_HEAP2_MULTI_INSERT | XLOG_HEAP_INIT_PAGE:
350 LBC 0 : id = "MULTI_INSERT+INIT";
351 0 : break;
352 UIC 0 : case XLOG_HEAP2_LOCK_UPDATED:
353 LBC 0 : id = "LOCK_UPDATED";
354 0 : break;
355 0 : case XLOG_HEAP2_NEW_CID:
356 0 : id = "NEW_CID";
357 UIC 0 : break;
358 UBC 0 : case XLOG_HEAP2_REWRITE:
359 UIC 0 : id = "REWRITE";
360 UBC 0 : break;
361 : }
362 EUB :
363 GBC 63 : return id;
364 EUB : }
|