1 /*--------------------------------------------------------------------------
2  * ginxlog.h
3  *	  header file for postgres inverted index xlog implementation.
4  *
5  *	Copyright (c) 2006-2021, PostgreSQL Global Development Group
6  *
7  *	src/include/access/ginxlog.h
8  *--------------------------------------------------------------------------
9  */
10 #ifndef GINXLOG_H
11 #define GINXLOG_H
12 
13 #include "access/ginblock.h"
14 #include "access/itup.h"
15 #include "access/xlogreader.h"
16 #include "lib/stringinfo.h"
17 #include "storage/off.h"
18 
19 #define XLOG_GIN_CREATE_PTREE  0x10
20 
21 typedef struct ginxlogCreatePostingTree
22 {
23 	uint32		size;
24 	/* A compressed posting list follows */
25 } ginxlogCreatePostingTree;
26 
27 /*
28  * The format of the insertion record varies depending on the page type.
29  * ginxlogInsert is the common part between all variants.
30  *
31  * Backup Blk 0: target page
32  * Backup Blk 1: left child, if this insertion finishes an incomplete split
33  */
34 
35 #define XLOG_GIN_INSERT  0x20
36 
37 typedef struct
38 {
39 	uint16		flags;			/* GIN_INSERT_ISLEAF and/or GIN_INSERT_ISDATA */
40 
41 	/*
42 	 * FOLLOWS:
43 	 *
44 	 * 1. if not leaf page, block numbers of the left and right child pages
45 	 * whose split this insertion finishes, as BlockIdData[2] (beware of
46 	 * adding fields in this struct that would make them not 16-bit aligned)
47 	 *
48 	 * 2. a ginxlogInsertEntry or ginxlogRecompressDataLeaf struct, depending
49 	 * on tree type.
50 	 *
51 	 * NB: the below structs are only 16-bit aligned when appended to a
52 	 * ginxlogInsert struct! Beware of adding fields to them that require
53 	 * stricter alignment.
54 	 */
55 } ginxlogInsert;
56 
57 typedef struct
58 {
59 	OffsetNumber offset;
60 	bool		isDelete;
61 	IndexTupleData tuple;		/* variable length */
62 } ginxlogInsertEntry;
63 
64 
65 typedef struct
66 {
67 	uint16		nactions;
68 
69 	/* Variable number of 'actions' follow */
70 } ginxlogRecompressDataLeaf;
71 
72 /*
73  * Note: this struct is currently not used in code, and only acts as
74  * documentation. The WAL record format is as specified here, but the code
75  * uses straight access through a Pointer and memcpy to read/write these.
76  */
77 typedef struct
78 {
79 	uint8		segno;			/* segment this action applies to */
80 	char		type;			/* action type (see below) */
81 
82 	/*
83 	 * Action-specific data follows. For INSERT and REPLACE actions that is a
84 	 * GinPostingList struct. For ADDITEMS, a uint16 for the number of items
85 	 * added, followed by the items themselves as ItemPointers. DELETE actions
86 	 * have no further data.
87 	 */
88 }			ginxlogSegmentAction;
89 
90 /* Action types */
91 #define GIN_SEGMENT_UNMODIFIED	0	/* no action (not used in WAL records) */
92 #define GIN_SEGMENT_DELETE		1	/* a whole segment is removed */
93 #define GIN_SEGMENT_INSERT		2	/* a whole segment is added */
94 #define GIN_SEGMENT_REPLACE		3	/* a segment is replaced */
95 #define GIN_SEGMENT_ADDITEMS	4	/* items are added to existing segment */
96 
97 typedef struct
98 {
99 	OffsetNumber offset;
100 	PostingItem newitem;
101 } ginxlogInsertDataInternal;
102 
103 /*
104  * Backup Blk 0: new left page (= original page, if not root split)
105  * Backup Blk 1: new right page
106  * Backup Blk 2: original page / new root page, if root split
107  * Backup Blk 3: left child, if this insertion completes an earlier split
108  */
109 #define XLOG_GIN_SPLIT	0x30
110 
111 typedef struct ginxlogSplit
112 {
113 	RelFileNode node;
114 	BlockNumber rrlink;			/* right link, or root's blocknumber if root
115 								 * split */
116 	BlockNumber leftChildBlkno; /* valid on a non-leaf split */
117 	BlockNumber rightChildBlkno;
118 	uint16		flags;			/* see below */
119 } ginxlogSplit;
120 
121 /*
122  * Flags used in ginxlogInsert and ginxlogSplit records
123  */
124 #define GIN_INSERT_ISDATA	0x01	/* for both insert and split records */
125 #define GIN_INSERT_ISLEAF	0x02	/* ditto */
126 #define GIN_SPLIT_ROOT		0x04	/* only for split records */
127 
128 /*
129  * Vacuum simply WAL-logs the whole page, when anything is modified. This
130  * is functionally identical to XLOG_FPI records, but is kept separate for
131  * debugging purposes. (When inspecting the WAL stream, it's easier to see
132  * what's going on when GIN vacuum records are marked as such, not as heap
133  * records.) This is currently only used for entry tree leaf pages.
134  */
135 #define XLOG_GIN_VACUUM_PAGE	0x40
136 
137 /*
138  * Vacuuming posting tree leaf page is WAL-logged like recompression caused
139  * by insertion.
140  */
141 #define XLOG_GIN_VACUUM_DATA_LEAF_PAGE	0x90
142 
143 typedef struct ginxlogVacuumDataLeafPage
144 {
145 	ginxlogRecompressDataLeaf data;
146 } ginxlogVacuumDataLeafPage;
147 
148 /*
149  * Backup Blk 0: deleted page
150  * Backup Blk 1: parent
151  * Backup Blk 2: left sibling
152  */
153 #define XLOG_GIN_DELETE_PAGE	0x50
154 
155 typedef struct ginxlogDeletePage
156 {
157 	OffsetNumber parentOffset;
158 	BlockNumber rightLink;
159 	TransactionId deleteXid;	/* last Xid which could see this page in scan */
160 } ginxlogDeletePage;
161 
162 #define XLOG_GIN_UPDATE_META_PAGE 0x60
163 
164 /*
165  * Backup Blk 0: metapage
166  * Backup Blk 1: tail page
167  */
168 typedef struct ginxlogUpdateMeta
169 {
170 	RelFileNode node;
171 	GinMetaPageData metadata;
172 	BlockNumber prevTail;
173 	BlockNumber newRightlink;
174 	int32		ntuples;		/* if ntuples > 0 then metadata.tail was
175 								 * updated with that many tuples; else new sub
176 								 * list was inserted */
177 	/* array of inserted tuples follows */
178 } ginxlogUpdateMeta;
179 
180 #define XLOG_GIN_INSERT_LISTPAGE  0x70
181 
182 typedef struct ginxlogInsertListPage
183 {
184 	BlockNumber rightlink;
185 	int32		ntuples;
186 	/* array of inserted tuples follows */
187 } ginxlogInsertListPage;
188 
189 /*
190  * Backup Blk 0: metapage
191  * Backup Blk 1 to (ndeleted + 1): deleted pages
192  */
193 
194 #define XLOG_GIN_DELETE_LISTPAGE  0x80
195 
196 /*
197  * The WAL record for deleting list pages must contain a block reference to
198  * all the deleted pages, so the number of pages that can be deleted in one
199  * record is limited by XLR_MAX_BLOCK_ID. (block_id 0 is used for the
200  * metapage.)
201  */
202 #define GIN_NDELETE_AT_ONCE Min(16, XLR_MAX_BLOCK_ID - 1)
203 typedef struct ginxlogDeleteListPages
204 {
205 	GinMetaPageData metadata;
206 	int32		ndeleted;
207 } ginxlogDeleteListPages;
208 
209 extern void gin_redo(XLogReaderState *record);
210 extern void gin_desc(StringInfo buf, XLogReaderState *record);
211 extern const char *gin_identify(uint8 info);
212 extern void gin_xlog_startup(void);
213 extern void gin_xlog_cleanup(void);
214 extern void gin_mask(char *pagedata, BlockNumber blkno);
215 
216 #endif							/* GINXLOG_H */
217