1 | /*------------------------------------------------------------------------- |
2 | * |
3 | * heapdesc.c |
4 | * rmgr descriptor routines for access/heap/heapam.c |
5 | * |
6 | * Portions Copyright (c) 1996-2019, 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 | |
19 | static void |
20 | out_infobits(StringInfo buf, uint8 infobits) |
21 | { |
22 | if (infobits & XLHL_XMAX_IS_MULTI) |
23 | appendStringInfoString(buf, "IS_MULTI " ); |
24 | if (infobits & XLHL_XMAX_LOCK_ONLY) |
25 | appendStringInfoString(buf, "LOCK_ONLY " ); |
26 | if (infobits & XLHL_XMAX_EXCL_LOCK) |
27 | appendStringInfoString(buf, "EXCL_LOCK " ); |
28 | if (infobits & XLHL_XMAX_KEYSHR_LOCK) |
29 | appendStringInfoString(buf, "KEYSHR_LOCK " ); |
30 | if (infobits & XLHL_KEYS_UPDATED) |
31 | appendStringInfoString(buf, "KEYS_UPDATED " ); |
32 | } |
33 | |
34 | void |
35 | heap_desc(StringInfo buf, XLogReaderState *record) |
36 | { |
37 | char *rec = XLogRecGetData(record); |
38 | uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; |
39 | |
40 | info &= XLOG_HEAP_OPMASK; |
41 | if (info == XLOG_HEAP_INSERT) |
42 | { |
43 | xl_heap_insert *xlrec = (xl_heap_insert *) rec; |
44 | |
45 | appendStringInfo(buf, "off %u flags 0x%02X" , xlrec->offnum, |
46 | xlrec->flags); |
47 | } |
48 | else if (info == XLOG_HEAP_DELETE) |
49 | { |
50 | xl_heap_delete *xlrec = (xl_heap_delete *) rec; |
51 | |
52 | appendStringInfo(buf, "off %u flags 0x%02X " , |
53 | xlrec->offnum, |
54 | xlrec->flags); |
55 | out_infobits(buf, xlrec->infobits_set); |
56 | } |
57 | else if (info == XLOG_HEAP_UPDATE) |
58 | { |
59 | xl_heap_update *xlrec = (xl_heap_update *) rec; |
60 | |
61 | appendStringInfo(buf, "off %u xmax %u flags 0x%02X " , |
62 | xlrec->old_offnum, |
63 | xlrec->old_xmax, |
64 | xlrec->flags); |
65 | out_infobits(buf, xlrec->old_infobits_set); |
66 | appendStringInfo(buf, "; new off %u xmax %u" , |
67 | xlrec->new_offnum, |
68 | xlrec->new_xmax); |
69 | } |
70 | else if (info == XLOG_HEAP_HOT_UPDATE) |
71 | { |
72 | xl_heap_update *xlrec = (xl_heap_update *) rec; |
73 | |
74 | appendStringInfo(buf, "off %u xmax %u flags 0x%02X " , |
75 | xlrec->old_offnum, |
76 | xlrec->old_xmax, |
77 | xlrec->flags); |
78 | out_infobits(buf, xlrec->old_infobits_set); |
79 | appendStringInfo(buf, "; new off %u xmax %u" , |
80 | xlrec->new_offnum, |
81 | xlrec->new_xmax); |
82 | } |
83 | else if (info == XLOG_HEAP_TRUNCATE) |
84 | { |
85 | xl_heap_truncate *xlrec = (xl_heap_truncate *) rec; |
86 | int i; |
87 | |
88 | if (xlrec->flags & XLH_TRUNCATE_CASCADE) |
89 | appendStringInfo(buf, "cascade " ); |
90 | if (xlrec->flags & XLH_TRUNCATE_RESTART_SEQS) |
91 | appendStringInfo(buf, "restart_seqs " ); |
92 | appendStringInfo(buf, "nrelids %u relids" , xlrec->nrelids); |
93 | for (i = 0; i < xlrec->nrelids; i++) |
94 | appendStringInfo(buf, " %u" , xlrec->relids[i]); |
95 | } |
96 | else if (info == XLOG_HEAP_CONFIRM) |
97 | { |
98 | xl_heap_confirm *xlrec = (xl_heap_confirm *) rec; |
99 | |
100 | appendStringInfo(buf, "off %u" , xlrec->offnum); |
101 | } |
102 | else if (info == XLOG_HEAP_LOCK) |
103 | { |
104 | xl_heap_lock *xlrec = (xl_heap_lock *) rec; |
105 | |
106 | appendStringInfo(buf, "off %u: xid %u: flags 0x%02X " , |
107 | xlrec->offnum, xlrec->locking_xid, xlrec->flags); |
108 | out_infobits(buf, xlrec->infobits_set); |
109 | } |
110 | else if (info == XLOG_HEAP_INPLACE) |
111 | { |
112 | xl_heap_inplace *xlrec = (xl_heap_inplace *) rec; |
113 | |
114 | appendStringInfo(buf, "off %u" , xlrec->offnum); |
115 | } |
116 | } |
117 | void |
118 | heap2_desc(StringInfo buf, XLogReaderState *record) |
119 | { |
120 | char *rec = XLogRecGetData(record); |
121 | uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK; |
122 | |
123 | info &= XLOG_HEAP_OPMASK; |
124 | if (info == XLOG_HEAP2_CLEAN) |
125 | { |
126 | xl_heap_clean *xlrec = (xl_heap_clean *) rec; |
127 | |
128 | appendStringInfo(buf, "remxid %u" , xlrec->latestRemovedXid); |
129 | } |
130 | else if (info == XLOG_HEAP2_FREEZE_PAGE) |
131 | { |
132 | xl_heap_freeze_page *xlrec = (xl_heap_freeze_page *) rec; |
133 | |
134 | appendStringInfo(buf, "cutoff xid %u ntuples %u" , |
135 | xlrec->cutoff_xid, xlrec->ntuples); |
136 | } |
137 | else if (info == XLOG_HEAP2_CLEANUP_INFO) |
138 | { |
139 | xl_heap_cleanup_info *xlrec = (xl_heap_cleanup_info *) rec; |
140 | |
141 | appendStringInfo(buf, "remxid %u" , xlrec->latestRemovedXid); |
142 | } |
143 | else if (info == XLOG_HEAP2_VISIBLE) |
144 | { |
145 | xl_heap_visible *xlrec = (xl_heap_visible *) rec; |
146 | |
147 | appendStringInfo(buf, "cutoff xid %u flags 0x%02X" , |
148 | xlrec->cutoff_xid, xlrec->flags); |
149 | } |
150 | else if (info == XLOG_HEAP2_MULTI_INSERT) |
151 | { |
152 | xl_heap_multi_insert *xlrec = (xl_heap_multi_insert *) rec; |
153 | |
154 | appendStringInfo(buf, "%d tuples flags 0x%02X" , xlrec->ntuples, |
155 | xlrec->flags); |
156 | } |
157 | else if (info == XLOG_HEAP2_LOCK_UPDATED) |
158 | { |
159 | xl_heap_lock_updated *xlrec = (xl_heap_lock_updated *) rec; |
160 | |
161 | appendStringInfo(buf, "off %u: xmax %u: flags 0x%02X " , |
162 | xlrec->offnum, xlrec->xmax, xlrec->flags); |
163 | out_infobits(buf, xlrec->infobits_set); |
164 | } |
165 | else if (info == XLOG_HEAP2_NEW_CID) |
166 | { |
167 | xl_heap_new_cid *xlrec = (xl_heap_new_cid *) rec; |
168 | |
169 | appendStringInfo(buf, "rel %u/%u/%u; tid %u/%u" , |
170 | xlrec->target_node.spcNode, |
171 | xlrec->target_node.dbNode, |
172 | xlrec->target_node.relNode, |
173 | ItemPointerGetBlockNumber(&(xlrec->target_tid)), |
174 | ItemPointerGetOffsetNumber(&(xlrec->target_tid))); |
175 | appendStringInfo(buf, "; cmin: %u, cmax: %u, combo: %u" , |
176 | xlrec->cmin, xlrec->cmax, xlrec->combocid); |
177 | } |
178 | } |
179 | |
180 | const char * |
181 | heap_identify(uint8 info) |
182 | { |
183 | const char *id = NULL; |
184 | |
185 | switch (info & ~XLR_INFO_MASK) |
186 | { |
187 | case XLOG_HEAP_INSERT: |
188 | id = "INSERT" ; |
189 | break; |
190 | case XLOG_HEAP_INSERT | XLOG_HEAP_INIT_PAGE: |
191 | id = "INSERT+INIT" ; |
192 | break; |
193 | case XLOG_HEAP_DELETE: |
194 | id = "DELETE" ; |
195 | break; |
196 | case XLOG_HEAP_UPDATE: |
197 | id = "UPDATE" ; |
198 | break; |
199 | case XLOG_HEAP_UPDATE | XLOG_HEAP_INIT_PAGE: |
200 | id = "UPDATE+INIT" ; |
201 | break; |
202 | case XLOG_HEAP_HOT_UPDATE: |
203 | id = "HOT_UPDATE" ; |
204 | break; |
205 | case XLOG_HEAP_HOT_UPDATE | XLOG_HEAP_INIT_PAGE: |
206 | id = "HOT_UPDATE+INIT" ; |
207 | break; |
208 | case XLOG_HEAP_TRUNCATE: |
209 | id = "TRUNCATE" ; |
210 | break; |
211 | case XLOG_HEAP_CONFIRM: |
212 | id = "HEAP_CONFIRM" ; |
213 | break; |
214 | case XLOG_HEAP_LOCK: |
215 | id = "LOCK" ; |
216 | break; |
217 | case XLOG_HEAP_INPLACE: |
218 | id = "INPLACE" ; |
219 | break; |
220 | } |
221 | |
222 | return id; |
223 | } |
224 | |
225 | const char * |
226 | heap2_identify(uint8 info) |
227 | { |
228 | const char *id = NULL; |
229 | |
230 | switch (info & ~XLR_INFO_MASK) |
231 | { |
232 | case XLOG_HEAP2_CLEAN: |
233 | id = "CLEAN" ; |
234 | break; |
235 | case XLOG_HEAP2_FREEZE_PAGE: |
236 | id = "FREEZE_PAGE" ; |
237 | break; |
238 | case XLOG_HEAP2_CLEANUP_INFO: |
239 | id = "CLEANUP_INFO" ; |
240 | break; |
241 | case XLOG_HEAP2_VISIBLE: |
242 | id = "VISIBLE" ; |
243 | break; |
244 | case XLOG_HEAP2_MULTI_INSERT: |
245 | id = "MULTI_INSERT" ; |
246 | break; |
247 | case XLOG_HEAP2_MULTI_INSERT | XLOG_HEAP_INIT_PAGE: |
248 | id = "MULTI_INSERT+INIT" ; |
249 | break; |
250 | case XLOG_HEAP2_LOCK_UPDATED: |
251 | id = "LOCK_UPDATED" ; |
252 | break; |
253 | case XLOG_HEAP2_NEW_CID: |
254 | id = "NEW_CID" ; |
255 | break; |
256 | case XLOG_HEAP2_REWRITE: |
257 | id = "REWRITE" ; |
258 | break; |
259 | } |
260 | |
261 | return id; |
262 | } |
263 | |