Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * nbtdesc.c
4 : * rmgr descriptor routines for access/nbtree/nbtxlog.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/nbtdesc.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 : #include "postgres.h"
16 :
17 : #include "access/nbtxlog.h"
18 : #include "access/rmgrdesc_utils.h"
19 :
20 : static void delvacuum_desc(StringInfo buf, char *block_data,
21 : uint16 ndeleted, uint16 nupdated);
22 :
23 : void
24 72040 : btree_desc(StringInfo buf, XLogReaderState *record)
25 : {
26 72040 : char *rec = XLogRecGetData(record);
27 72040 : uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
28 :
29 72040 : switch (info)
30 : {
31 71088 : case XLOG_BTREE_INSERT_LEAF:
32 : case XLOG_BTREE_INSERT_UPPER:
33 : case XLOG_BTREE_INSERT_META:
34 : case XLOG_BTREE_INSERT_POST:
35 : {
36 71088 : xl_btree_insert *xlrec = (xl_btree_insert *) rec;
37 :
38 71088 : appendStringInfo(buf, "off: %u", xlrec->offnum);
39 71088 : break;
40 : }
41 240 : case XLOG_BTREE_SPLIT_L:
42 : case XLOG_BTREE_SPLIT_R:
43 : {
44 240 : xl_btree_split *xlrec = (xl_btree_split *) rec;
45 :
46 240 : appendStringInfo(buf, "level: %u, firstrightoff: %d, newitemoff: %d, postingoff: %d",
47 240 : xlrec->level, xlrec->firstrightoff,
48 240 : xlrec->newitemoff, xlrec->postingoff);
49 240 : break;
50 : }
51 212 : case XLOG_BTREE_DEDUP:
52 : {
53 212 : xl_btree_dedup *xlrec = (xl_btree_dedup *) rec;
54 :
55 212 : appendStringInfo(buf, "nintervals: %u", xlrec->nintervals);
56 212 : break;
57 : }
58 256 : case XLOG_BTREE_VACUUM:
59 : {
60 256 : xl_btree_vacuum *xlrec = (xl_btree_vacuum *) rec;
61 :
62 256 : appendStringInfo(buf, "ndeleted: %u, nupdated: %u",
63 256 : xlrec->ndeleted, xlrec->nupdated);
64 :
65 256 : if (XLogRecHasBlockData(record, 0))
66 256 : delvacuum_desc(buf, XLogRecGetBlockData(record, 0, NULL),
67 256 : xlrec->ndeleted, xlrec->nupdated);
68 256 : break;
69 : }
70 24 : case XLOG_BTREE_DELETE:
71 : {
72 24 : xl_btree_delete *xlrec = (xl_btree_delete *) rec;
73 :
74 24 : appendStringInfo(buf, "snapshotConflictHorizon: %u, ndeleted: %u, nupdated: %u, isCatalogRel: %c",
75 : xlrec->snapshotConflictHorizon,
76 24 : xlrec->ndeleted, xlrec->nupdated,
77 24 : xlrec->isCatalogRel ? 'T' : 'F');
78 :
79 24 : if (XLogRecHasBlockData(record, 0))
80 24 : delvacuum_desc(buf, XLogRecGetBlockData(record, 0, NULL),
81 24 : xlrec->ndeleted, xlrec->nupdated);
82 24 : break;
83 : }
84 0 : case XLOG_BTREE_MARK_PAGE_HALFDEAD:
85 : {
86 0 : xl_btree_mark_page_halfdead *xlrec = (xl_btree_mark_page_halfdead *) rec;
87 :
88 0 : appendStringInfo(buf, "topparent: %u, leaf: %u, left: %u, right: %u",
89 : xlrec->topparent, xlrec->leafblk, xlrec->leftblk, xlrec->rightblk);
90 0 : break;
91 : }
92 0 : case XLOG_BTREE_UNLINK_PAGE_META:
93 : case XLOG_BTREE_UNLINK_PAGE:
94 : {
95 0 : xl_btree_unlink_page *xlrec = (xl_btree_unlink_page *) rec;
96 :
97 0 : appendStringInfo(buf, "left: %u, right: %u, level: %u, safexid: %u:%u, ",
98 : xlrec->leftsib, xlrec->rightsib, xlrec->level,
99 0 : EpochFromFullTransactionId(xlrec->safexid),
100 0 : XidFromFullTransactionId(xlrec->safexid));
101 0 : appendStringInfo(buf, "leafleft: %u, leafright: %u, leaftopparent: %u",
102 : xlrec->leafleftsib, xlrec->leafrightsib,
103 : xlrec->leaftopparent);
104 0 : break;
105 : }
106 220 : case XLOG_BTREE_NEWROOT:
107 : {
108 220 : xl_btree_newroot *xlrec = (xl_btree_newroot *) rec;
109 :
110 220 : appendStringInfo(buf, "level: %u", xlrec->level);
111 220 : break;
112 : }
113 0 : case XLOG_BTREE_REUSE_PAGE:
114 : {
115 0 : xl_btree_reuse_page *xlrec = (xl_btree_reuse_page *) rec;
116 :
117 0 : appendStringInfo(buf, "rel: %u/%u/%u, snapshotConflictHorizon: %u:%u, isCatalogRel: %c",
118 : xlrec->locator.spcOid, xlrec->locator.dbOid,
119 : xlrec->locator.relNumber,
120 0 : EpochFromFullTransactionId(xlrec->snapshotConflictHorizon),
121 0 : XidFromFullTransactionId(xlrec->snapshotConflictHorizon),
122 0 : xlrec->isCatalogRel ? 'T' : 'F');
123 0 : break;
124 : }
125 0 : case XLOG_BTREE_META_CLEANUP:
126 : {
127 : xl_btree_metadata *xlrec;
128 :
129 0 : xlrec = (xl_btree_metadata *) XLogRecGetBlockData(record, 0,
130 : NULL);
131 0 : appendStringInfo(buf, "last_cleanup_num_delpages: %u",
132 : xlrec->last_cleanup_num_delpages);
133 0 : break;
134 : }
135 : }
136 72040 : }
137 :
138 : const char *
139 72052 : btree_identify(uint8 info)
140 : {
141 72052 : const char *id = NULL;
142 :
143 72052 : switch (info & ~XLR_INFO_MASK)
144 : {
145 70902 : case XLOG_BTREE_INSERT_LEAF:
146 70902 : id = "INSERT_LEAF";
147 70902 : break;
148 190 : case XLOG_BTREE_INSERT_UPPER:
149 190 : id = "INSERT_UPPER";
150 190 : break;
151 0 : case XLOG_BTREE_INSERT_META:
152 0 : id = "INSERT_META";
153 0 : break;
154 70 : case XLOG_BTREE_SPLIT_L:
155 70 : id = "SPLIT_L";
156 70 : break;
157 174 : case XLOG_BTREE_SPLIT_R:
158 174 : id = "SPLIT_R";
159 174 : break;
160 0 : case XLOG_BTREE_INSERT_POST:
161 0 : id = "INSERT_POST";
162 0 : break;
163 212 : case XLOG_BTREE_DEDUP:
164 212 : id = "DEDUP";
165 212 : break;
166 258 : case XLOG_BTREE_VACUUM:
167 258 : id = "VACUUM";
168 258 : break;
169 24 : case XLOG_BTREE_DELETE:
170 24 : id = "DELETE";
171 24 : break;
172 0 : case XLOG_BTREE_MARK_PAGE_HALFDEAD:
173 0 : id = "MARK_PAGE_HALFDEAD";
174 0 : break;
175 0 : case XLOG_BTREE_UNLINK_PAGE:
176 0 : id = "UNLINK_PAGE";
177 0 : break;
178 0 : case XLOG_BTREE_UNLINK_PAGE_META:
179 0 : id = "UNLINK_PAGE_META";
180 0 : break;
181 222 : case XLOG_BTREE_NEWROOT:
182 222 : id = "NEWROOT";
183 222 : break;
184 0 : case XLOG_BTREE_REUSE_PAGE:
185 0 : id = "REUSE_PAGE";
186 0 : break;
187 0 : case XLOG_BTREE_META_CLEANUP:
188 0 : id = "META_CLEANUP";
189 0 : break;
190 : }
191 :
192 72052 : return id;
193 : }
194 :
195 : static void
196 280 : delvacuum_desc(StringInfo buf, char *block_data,
197 : uint16 ndeleted, uint16 nupdated)
198 : {
199 : OffsetNumber *deletedoffsets;
200 : OffsetNumber *updatedoffsets;
201 : xl_btree_update *updates;
202 :
203 : /* Output deleted page offset number array */
204 280 : appendStringInfoString(buf, ", deleted:");
205 280 : deletedoffsets = (OffsetNumber *) block_data;
206 280 : array_desc(buf, deletedoffsets, sizeof(OffsetNumber), ndeleted,
207 : &offset_elem_desc, NULL);
208 :
209 : /*
210 : * Output updates as an array of "update objects", where each element
211 : * contains a page offset number from updated array. (This is not the
212 : * most literal representation of the underlying physical data structure
213 : * that we could use. Readability seems more important here.)
214 : */
215 280 : appendStringInfoString(buf, ", updated: [");
216 280 : updatedoffsets = (OffsetNumber *) (block_data + ndeleted *
217 : sizeof(OffsetNumber));
218 280 : updates = (xl_btree_update *) ((char *) updatedoffsets +
219 280 : nupdated *
220 : sizeof(OffsetNumber));
221 1216 : for (int i = 0; i < nupdated; i++)
222 : {
223 936 : OffsetNumber off = updatedoffsets[i];
224 :
225 : Assert(OffsetNumberIsValid(off));
226 : Assert(updates->ndeletedtids > 0);
227 :
228 : /*
229 : * "ptid" is the symbol name used when building each xl_btree_update's
230 : * array of offsets into a posting list tuple's ItemPointerData array.
231 : * xl_btree_update describes a subset of the existing TIDs to delete.
232 : */
233 936 : appendStringInfo(buf, "{ off: %u, nptids: %u, ptids: [",
234 936 : off, updates->ndeletedtids);
235 2180 : for (int p = 0; p < updates->ndeletedtids; p++)
236 : {
237 : uint16 *ptid;
238 :
239 1244 : ptid = (uint16 *) ((char *) updates + SizeOfBtreeUpdate) + p;
240 1244 : appendStringInfo(buf, "%u", *ptid);
241 :
242 1244 : if (p < updates->ndeletedtids - 1)
243 308 : appendStringInfoString(buf, ", ");
244 : }
245 936 : appendStringInfoString(buf, "] }");
246 936 : if (i < nupdated - 1)
247 896 : appendStringInfoString(buf, ", ");
248 :
249 936 : updates = (xl_btree_update *)
250 936 : ((char *) updates + SizeOfBtreeUpdate +
251 936 : updates->ndeletedtids * sizeof(uint16));
252 : }
253 280 : appendStringInfoChar(buf, ']');
254 280 : }
|