TLA 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 btree_del_desc(StringInfo buf, char *block_data, uint16 ndeleted,
21 : uint16 nupdated);
22 : static void btree_update_elem_desc(StringInfo buf, void *update, void *data);
23 :
24 : static void
25 UNC 0 : btree_del_desc(StringInfo buf, char *block_data, uint16 ndeleted,
26 : uint16 nupdated)
27 : {
28 : OffsetNumber *updatedoffsets;
29 : xl_btree_update *updates;
30 0 : OffsetNumber *data = (OffsetNumber *) block_data;
31 :
32 0 : appendStringInfoString(buf, ", deleted:");
33 0 : array_desc(buf, data, sizeof(OffsetNumber), ndeleted,
34 : &offset_elem_desc, NULL);
35 :
36 0 : appendStringInfoString(buf, ", updated:");
37 0 : array_desc(buf, data, sizeof(OffsetNumber), nupdated,
38 : &offset_elem_desc, NULL);
39 :
40 0 : if (nupdated <= 0)
41 0 : return;
42 :
43 0 : updatedoffsets = (OffsetNumber *)
44 0 : ((char *) data + ndeleted * sizeof(OffsetNumber));
45 0 : updates = (xl_btree_update *) ((char *) updatedoffsets +
46 0 : nupdated *
47 : sizeof(OffsetNumber));
48 :
49 0 : appendStringInfoString(buf, ", updates:");
50 0 : array_desc(buf, updates, sizeof(xl_btree_update),
51 : nupdated, &btree_update_elem_desc,
52 : &updatedoffsets);
53 : }
54 :
55 : static void
56 0 : btree_update_elem_desc(StringInfo buf, void *update, void *data)
57 : {
58 0 : xl_btree_update *new_update = (xl_btree_update *) update;
59 0 : OffsetNumber *updated_offset = *((OffsetNumber **) data);
60 :
61 0 : appendStringInfo(buf, "{ updated offset: %u, ndeleted tids: %u",
62 0 : *updated_offset, new_update->ndeletedtids);
63 :
64 0 : appendStringInfoString(buf, ", deleted tids:");
65 :
66 0 : array_desc(buf, (char *) new_update + SizeOfBtreeUpdate, sizeof(uint16),
67 0 : new_update->ndeletedtids, &uint16_elem_desc, NULL);
68 :
69 0 : updated_offset++;
70 :
71 0 : appendStringInfo(buf, " }");
72 0 : }
73 :
74 : void
75 GIC 81 : btree_desc(StringInfo buf, XLogReaderState *record)
76 : {
77 81 : char *rec = XLogRecGetData(record);
78 81 : uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
79 :
80 GBC 81 : switch (info)
81 : {
82 GIC 79 : case XLOG_BTREE_INSERT_LEAF:
83 : case XLOG_BTREE_INSERT_UPPER:
84 : case XLOG_BTREE_INSERT_META:
85 EUB : case XLOG_BTREE_INSERT_POST:
86 : {
87 GBC 79 : xl_btree_insert *xlrec = (xl_btree_insert *) rec;
88 EUB :
89 GNC 79 : appendStringInfo(buf, "off: %u", xlrec->offnum);
90 GIC 79 : break;
91 EUB : }
92 UBC 0 : case XLOG_BTREE_SPLIT_L:
93 : case XLOG_BTREE_SPLIT_R:
94 : {
95 0 : xl_btree_split *xlrec = (xl_btree_split *) rec;
96 EUB :
97 UNC 0 : appendStringInfo(buf, "level: %u, firstrightoff: %d, newitemoff: %d, postingoff: %d",
98 UBC 0 : xlrec->level, xlrec->firstrightoff,
99 0 : xlrec->newitemoff, xlrec->postingoff);
100 0 : break;
101 EUB : }
102 GIC 2 : case XLOG_BTREE_DEDUP:
103 : {
104 GBC 2 : xl_btree_dedup *xlrec = (xl_btree_dedup *) rec;
105 EUB :
106 GNC 2 : appendStringInfo(buf, "nintervals: %u", xlrec->nintervals);
107 GIC 2 : break;
108 : }
109 UIC 0 : case XLOG_BTREE_VACUUM:
110 : {
111 UBC 0 : xl_btree_vacuum *xlrec = (xl_btree_vacuum *) rec;
112 :
113 UNC 0 : appendStringInfo(buf, "ndeleted: %u, nupdated: %u",
114 UBC 0 : xlrec->ndeleted, xlrec->nupdated);
115 :
116 UNC 0 : if (!XLogRecHasBlockImage(record, 0))
117 0 : btree_del_desc(buf, XLogRecGetBlockData(record, 0, NULL),
118 0 : xlrec->ndeleted, xlrec->nupdated);
119 :
120 UIC 0 : break;
121 EUB : }
122 UBC 0 : case XLOG_BTREE_DELETE:
123 : {
124 0 : xl_btree_delete *xlrec = (xl_btree_delete *) rec;
125 :
126 UNC 0 : appendStringInfo(buf, "snapshotConflictHorizon: %u, ndeleted: %u, nupdated: %u",
127 : xlrec->snapshotConflictHorizon,
128 0 : xlrec->ndeleted, xlrec->nupdated);
129 :
130 0 : if (!XLogRecHasBlockImage(record, 0))
131 0 : btree_del_desc(buf, XLogRecGetBlockData(record, 0, NULL),
132 0 : xlrec->ndeleted, xlrec->nupdated);
133 :
134 UIC 0 : break;
135 EUB : }
136 UIC 0 : case XLOG_BTREE_MARK_PAGE_HALFDEAD:
137 EUB : {
138 UBC 0 : xl_btree_mark_page_halfdead *xlrec = (xl_btree_mark_page_halfdead *) rec;
139 :
140 UNC 0 : appendStringInfo(buf, "topparent: %u; leaf: %u; left: %u; right: %u",
141 ECB : xlrec->topparent, xlrec->leafblk, xlrec->leftblk, xlrec->rightblk);
142 UIC 0 : break;
143 ECB : }
144 LBC 0 : case XLOG_BTREE_UNLINK_PAGE_META:
145 : case XLOG_BTREE_UNLINK_PAGE:
146 ECB : {
147 UIC 0 : xl_btree_unlink_page *xlrec = (xl_btree_unlink_page *) rec;
148 ECB :
149 UNC 0 : appendStringInfo(buf, "left: %u; right: %u; level: %u; safexid: %u:%u; ",
150 : xlrec->leftsib, xlrec->rightsib, xlrec->level,
151 UIC 0 : EpochFromFullTransactionId(xlrec->safexid),
152 0 : XidFromFullTransactionId(xlrec->safexid));
153 UNC 0 : appendStringInfo(buf, "leafleft: %u; leafright: %u; leaftopparent: %u",
154 : xlrec->leafleftsib, xlrec->leafrightsib,
155 ECB : xlrec->leaftopparent);
156 LBC 0 : break;
157 : }
158 UBC 0 : case XLOG_BTREE_NEWROOT:
159 : {
160 UIC 0 : xl_btree_newroot *xlrec = (xl_btree_newroot *) rec;
161 EUB :
162 UNC 0 : appendStringInfo(buf, "lev: %u", xlrec->level);
163 UBC 0 : break;
164 EUB : }
165 UBC 0 : case XLOG_BTREE_REUSE_PAGE:
166 EUB : {
167 UIC 0 : xl_btree_reuse_page *xlrec = (xl_btree_reuse_page *) rec;
168 ECB :
169 UNC 0 : appendStringInfo(buf, "rel: %u/%u/%u, snapshotConflictHorizon: %u:%u",
170 : xlrec->locator.spcOid, xlrec->locator.dbOid,
171 : xlrec->locator.relNumber,
172 0 : EpochFromFullTransactionId(xlrec->snapshotConflictHorizon),
173 0 : XidFromFullTransactionId(xlrec->snapshotConflictHorizon));
174 UIC 0 : break;
175 EUB : }
176 UIC 0 : case XLOG_BTREE_META_CLEANUP:
177 EUB : {
178 : xl_btree_metadata *xlrec;
179 :
180 UBC 0 : xlrec = (xl_btree_metadata *) XLogRecGetBlockData(record, 0,
181 : NULL);
182 UNC 0 : appendStringInfo(buf, "last_cleanup_num_delpages: %u",
183 EUB : xlrec->last_cleanup_num_delpages);
184 UBC 0 : break;
185 : }
186 EUB : }
187 GIC 81 : }
188 EUB :
189 : const char *
190 GBC 81 : btree_identify(uint8 info)
191 : {
192 81 : const char *id = NULL;
193 :
194 81 : switch (info & ~XLR_INFO_MASK)
195 : {
196 78 : case XLOG_BTREE_INSERT_LEAF:
197 78 : id = "INSERT_LEAF";
198 78 : break;
199 GIC 1 : case XLOG_BTREE_INSERT_UPPER:
200 GBC 1 : id = "INSERT_UPPER";
201 GIC 1 : break;
202 UBC 0 : case XLOG_BTREE_INSERT_META:
203 UIC 0 : id = "INSERT_META";
204 UBC 0 : break;
205 UIC 0 : case XLOG_BTREE_SPLIT_L:
206 UBC 0 : id = "SPLIT_L";
207 UIC 0 : break;
208 UBC 0 : case XLOG_BTREE_SPLIT_R:
209 UIC 0 : id = "SPLIT_R";
210 UBC 0 : break;
211 UIC 0 : case XLOG_BTREE_INSERT_POST:
212 0 : id = "INSERT_POST";
213 UBC 0 : break;
214 GIC 2 : case XLOG_BTREE_DEDUP:
215 GBC 2 : id = "DEDUP";
216 GIC 2 : break;
217 UBC 0 : case XLOG_BTREE_VACUUM:
218 0 : id = "VACUUM";
219 0 : break;
220 UIC 0 : case XLOG_BTREE_DELETE:
221 0 : id = "DELETE";
222 UBC 0 : break;
223 UIC 0 : case XLOG_BTREE_MARK_PAGE_HALFDEAD:
224 UBC 0 : id = "MARK_PAGE_HALFDEAD";
225 UIC 0 : break;
226 UBC 0 : case XLOG_BTREE_UNLINK_PAGE:
227 UIC 0 : id = "UNLINK_PAGE";
228 UBC 0 : break;
229 0 : case XLOG_BTREE_UNLINK_PAGE_META:
230 UIC 0 : id = "UNLINK_PAGE_META";
231 UBC 0 : break;
232 UIC 0 : case XLOG_BTREE_NEWROOT:
233 UBC 0 : id = "NEWROOT";
234 UIC 0 : break;
235 UBC 0 : case XLOG_BTREE_REUSE_PAGE:
236 UIC 0 : id = "REUSE_PAGE";
237 0 : break;
238 UBC 0 : case XLOG_BTREE_META_CLEANUP:
239 0 : id = "META_CLEANUP";
240 0 : break;
241 : }
242 EUB :
243 GIC 81 : return id;
244 : }
|