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
19static void
20out_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
34void
35heap_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}
117void
118heap2_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
180const char *
181heap_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
225const char *
226heap2_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