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