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