1 | /*------------------------------------------------------------------------- |
2 | * |
3 | * spgxlog.h |
4 | * xlog declarations for SP-GiST access method. |
5 | * |
6 | * Portions Copyright (c) 1996-2019, 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 | |