1 /*-------------------------------------------------------------------------
2  *
3  * spgxlog.h
4  *	  xlog declarations for SP-GiST access method.
5  *
6  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * src/include/access/spgxlog.h
10  *
11  *-------------------------------------------------------------------------
12  */
13 #ifndef SPGXLOG_H
14 #define SPGXLOG_H
15 
16 #include "access/xlogreader.h"
17 #include "lib/stringinfo.h"
18 #include "storage/off.h"
19 
20 /* XLOG record types for SPGiST */
21  /* #define XLOG_SPGIST_CREATE_INDEX       0x00 */	/* not used anymore */
22 #define XLOG_SPGIST_ADD_LEAF		0x10
23 #define XLOG_SPGIST_MOVE_LEAFS		0x20
24 #define XLOG_SPGIST_ADD_NODE		0x30
25 #define XLOG_SPGIST_SPLIT_TUPLE		0x40
26 #define XLOG_SPGIST_PICKSPLIT		0x50
27 #define XLOG_SPGIST_VACUUM_LEAF		0x60
28 #define XLOG_SPGIST_VACUUM_ROOT		0x70
29 #define XLOG_SPGIST_VACUUM_REDIRECT 0x80
30 
31 /*
32  * Some redo functions need an SpGistState, although only a few of its fields
33  * need to be valid.  spgxlogState carries the required info in xlog records.
34  * (See fillFakeState in spgxlog.c for more comments.)
35  */
36 typedef struct spgxlogState
37 {
38 	TransactionId myXid;
39 	bool		isBuild;
40 } spgxlogState;
41 
42 /*
43  * Backup Blk 0: destination page for leaf tuple
44  * Backup Blk 1: parent page (if any)
45  */
46 typedef struct spgxlogAddLeaf
47 {
48 	bool		newPage;		/* init dest page? */
49 	bool		storesNulls;	/* page is in the nulls tree? */
50 	OffsetNumber offnumLeaf;	/* offset where leaf tuple gets placed */
51 	OffsetNumber offnumHeadLeaf;	/* offset of head tuple in chain, if any */
52 
53 	OffsetNumber offnumParent;	/* where the parent downlink is, if any */
54 	uint16		nodeI;
55 
56 	/* new leaf tuple follows (unaligned!) */
57 } spgxlogAddLeaf;
58 
59 /*
60  * Backup Blk 0: source leaf page
61  * Backup Blk 1: destination leaf page
62  * Backup Blk 2: parent page
63  */
64 typedef struct spgxlogMoveLeafs
65 {
66 	uint16		nMoves;			/* number of tuples moved from source page */
67 	bool		newPage;		/* init dest page? */
68 	bool		replaceDead;	/* are we replacing a DEAD source tuple? */
69 	bool		storesNulls;	/* pages are in the nulls tree? */
70 
71 	/* where the parent downlink is */
72 	OffsetNumber offnumParent;
73 	uint16		nodeI;
74 
75 	spgxlogState stateSrc;
76 
77 	/*----------
78 	 * data follows:
79 	 *		array of deleted tuple numbers, length nMoves
80 	 *		array of inserted tuple numbers, length nMoves + 1 or 1
81 	 *		list of leaf tuples, length nMoves + 1 or 1 (unaligned!)
82 	 *
83 	 * Note: if replaceDead is true then there is only one inserted tuple
84 	 * number and only one leaf tuple in the data, because we are not copying
85 	 * the dead tuple from the source
86 	 *----------
87 	 */
88 	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
89 } spgxlogMoveLeafs;
90 
91 #define SizeOfSpgxlogMoveLeafs	offsetof(spgxlogMoveLeafs, offsets)
92 
93 /*
94  * Backup Blk 0: original page
95  * Backup Blk 1: where new tuple goes, if not same place
96  * Backup Blk 2: where parent downlink is, if updated and different from
97  *				 the old and new
98  */
99 typedef struct spgxlogAddNode
100 {
101 	/*
102 	 * Offset of the original inner tuple, in the original page (on backup
103 	 * block 0).
104 	 */
105 	OffsetNumber offnum;
106 
107 	/*
108 	 * Offset of the new tuple, on the new page (on backup block 1). Invalid,
109 	 * if we overwrote the old tuple in the original page).
110 	 */
111 	OffsetNumber offnumNew;
112 	bool		newPage;		/* init new page? */
113 
114 	/*----
115 	 * Where is the parent downlink? parentBlk indicates which page it's on,
116 	 * and offnumParent is the offset within the page. The possible values for
117 	 * parentBlk are:
118 	 *
119 	 * 0: parent == original page
120 	 * 1: parent == new page
121 	 * 2: parent == different page (blk ref 2)
122 	 * -1: parent not updated
123 	 *----
124 	 */
125 	int8		parentBlk;
126 	OffsetNumber offnumParent;	/* offset within the parent page */
127 
128 	uint16		nodeI;
129 
130 	spgxlogState stateSrc;
131 
132 	/*
133 	 * updated inner tuple follows (unaligned!)
134 	 */
135 } spgxlogAddNode;
136 
137 /*
138  * Backup Blk 0: where the prefix tuple goes
139  * Backup Blk 1: where the postfix tuple goes (if different page)
140  */
141 typedef struct spgxlogSplitTuple
142 {
143 	/* where the prefix tuple goes */
144 	OffsetNumber offnumPrefix;
145 
146 	/* where the postfix tuple goes */
147 	OffsetNumber offnumPostfix;
148 	bool		newPage;		/* need to init that page? */
149 	bool		postfixBlkSame; /* was postfix tuple put on same page as
150 								 * prefix? */
151 
152 	/*
153 	 * new prefix inner tuple follows, then new postfix inner tuple (both are
154 	 * unaligned!)
155 	 */
156 } spgxlogSplitTuple;
157 
158 /*
159  * Buffer references in the rdata array are:
160  * Backup Blk 0: Src page (only if not root)
161  * Backup Blk 1: Dest page (if used)
162  * Backup Blk 2: Inner page
163  * Backup Blk 3: Parent page (if any, and different from Inner)
164  */
165 typedef struct spgxlogPickSplit
166 {
167 	bool		isRootSplit;
168 
169 	uint16		nDelete;		/* n to delete from Src */
170 	uint16		nInsert;		/* n to insert on Src and/or Dest */
171 	bool		initSrc;		/* re-init the Src page? */
172 	bool		initDest;		/* re-init the Dest page? */
173 
174 	/* where to put new inner tuple */
175 	OffsetNumber offnumInner;
176 	bool		initInner;		/* re-init the Inner page? */
177 
178 	bool		storesNulls;	/* pages are in the nulls tree? */
179 
180 	/* where the parent downlink is, if any */
181 	bool		innerIsParent;	/* is parent the same as inner page? */
182 	OffsetNumber offnumParent;
183 	uint16		nodeI;
184 
185 	spgxlogState stateSrc;
186 
187 	/*----------
188 	 * data follows:
189 	 *		array of deleted tuple numbers, length nDelete
190 	 *		array of inserted tuple numbers, length nInsert
191 	 *		array of page selector bytes for inserted tuples, length nInsert
192 	 *		new inner tuple (unaligned!)
193 	 *		list of leaf tuples, length nInsert (unaligned!)
194 	 *----------
195 	 */
196 	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
197 } spgxlogPickSplit;
198 
199 #define SizeOfSpgxlogPickSplit offsetof(spgxlogPickSplit, offsets)
200 
201 typedef struct spgxlogVacuumLeaf
202 {
203 	uint16		nDead;			/* number of tuples to become DEAD */
204 	uint16		nPlaceholder;	/* number of tuples to become PLACEHOLDER */
205 	uint16		nMove;			/* number of tuples to move */
206 	uint16		nChain;			/* number of tuples to re-chain */
207 
208 	spgxlogState stateSrc;
209 
210 	/*----------
211 	 * data follows:
212 	 *		tuple numbers to become DEAD
213 	 *		tuple numbers to become PLACEHOLDER
214 	 *		tuple numbers to move from (and replace with PLACEHOLDER)
215 	 *		tuple numbers to move to (replacing what is there)
216 	 *		tuple numbers to update nextOffset links of
217 	 *		tuple numbers to insert in nextOffset links
218 	 *----------
219 	 */
220 	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
221 } spgxlogVacuumLeaf;
222 
223 #define SizeOfSpgxlogVacuumLeaf offsetof(spgxlogVacuumLeaf, offsets)
224 
225 typedef struct spgxlogVacuumRoot
226 {
227 	/* vacuum a root page when it is also a leaf */
228 	uint16		nDelete;		/* number of tuples to delete */
229 
230 	spgxlogState stateSrc;
231 
232 	/* offsets of tuples to delete follow */
233 	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
234 } spgxlogVacuumRoot;
235 
236 #define SizeOfSpgxlogVacuumRoot offsetof(spgxlogVacuumRoot, offsets)
237 
238 typedef struct spgxlogVacuumRedirect
239 {
240 	uint16		nToPlaceholder; /* number of redirects to make placeholders */
241 	OffsetNumber firstPlaceholder;	/* first placeholder tuple to remove */
242 	TransactionId newestRedirectXid;	/* newest XID of removed redirects */
243 
244 	/* offsets of redirect tuples to make placeholders follow */
245 	OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
246 } spgxlogVacuumRedirect;
247 
248 #define SizeOfSpgxlogVacuumRedirect offsetof(spgxlogVacuumRedirect, offsets)
249 
250 extern void spg_redo(XLogReaderState *record);
251 extern void spg_desc(StringInfo buf, XLogReaderState *record);
252 extern const char *spg_identify(uint8 info);
253 extern void spg_xlog_startup(void);
254 extern void spg_xlog_cleanup(void);
255 extern void spg_mask(char *pagedata, BlockNumber blkno);
256 
257 #endif							/* SPGXLOG_H */
258