summaryrefslogtreecommitdiffstats
path: root/src/include/access/ginxlog.h
blob: 37095e5f17cea036b84f952746fd25f723d9e24b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/*--------------------------------------------------------------------------
 * ginxlog.h
 *	  header file for postgres inverted index xlog implementation.
 *
 *	Copyright (c) 2006-2023, PostgreSQL Global Development Group
 *
 *	src/include/access/ginxlog.h
 *--------------------------------------------------------------------------
 */
#ifndef GINXLOG_H
#define GINXLOG_H

#include "access/ginblock.h"
#include "access/itup.h"
#include "access/xlogreader.h"
#include "lib/stringinfo.h"
#include "storage/off.h"

#define XLOG_GIN_CREATE_PTREE  0x10

typedef struct ginxlogCreatePostingTree
{
	uint32		size;
	/* A compressed posting list follows */
} ginxlogCreatePostingTree;

/*
 * The format of the insertion record varies depending on the page type.
 * ginxlogInsert is the common part between all variants.
 *
 * Backup Blk 0: target page
 * Backup Blk 1: left child, if this insertion finishes an incomplete split
 */

#define XLOG_GIN_INSERT  0x20

typedef struct
{
	uint16		flags;			/* GIN_INSERT_ISLEAF and/or GIN_INSERT_ISDATA */

	/*
	 * FOLLOWS:
	 *
	 * 1. if not leaf page, block numbers of the left and right child pages
	 * whose split this insertion finishes, as BlockIdData[2] (beware of
	 * adding fields in this struct that would make them not 16-bit aligned)
	 *
	 * 2. a ginxlogInsertEntry or ginxlogRecompressDataLeaf struct, depending
	 * on tree type.
	 *
	 * NB: the below structs are only 16-bit aligned when appended to a
	 * ginxlogInsert struct! Beware of adding fields to them that require
	 * stricter alignment.
	 */
} ginxlogInsert;

typedef struct
{
	OffsetNumber offset;
	bool		isDelete;
	IndexTupleData tuple;		/* variable length */
} ginxlogInsertEntry;


typedef struct
{
	uint16		nactions;

	/* Variable number of 'actions' follow */
} ginxlogRecompressDataLeaf;

/*
 * Note: this struct is currently not used in code, and only acts as
 * documentation. The WAL record format is as specified here, but the code
 * uses straight access through a Pointer and memcpy to read/write these.
 */
typedef struct
{
	uint8		segno;			/* segment this action applies to */
	char		type;			/* action type (see below) */

	/*
	 * Action-specific data follows. For INSERT and REPLACE actions that is a
	 * GinPostingList struct. For ADDITEMS, a uint16 for the number of items
	 * added, followed by the items themselves as ItemPointers. DELETE actions
	 * have no further data.
	 */
}			ginxlogSegmentAction;

/* Action types */
#define GIN_SEGMENT_UNMODIFIED	0	/* no action (not used in WAL records) */
#define GIN_SEGMENT_DELETE		1	/* a whole segment is removed */
#define GIN_SEGMENT_INSERT		2	/* a whole segment is added */
#define GIN_SEGMENT_REPLACE		3	/* a segment is replaced */
#define GIN_SEGMENT_ADDITEMS	4	/* items are added to existing segment */

typedef struct
{
	OffsetNumber offset;
	PostingItem newitem;
} ginxlogInsertDataInternal;

/*
 * Backup Blk 0: new left page (= original page, if not root split)
 * Backup Blk 1: new right page
 * Backup Blk 2: original page / new root page, if root split
 * Backup Blk 3: left child, if this insertion completes an earlier split
 */
#define XLOG_GIN_SPLIT	0x30

typedef struct ginxlogSplit
{
	RelFileLocator locator;
	BlockNumber rrlink;			/* right link, or root's blocknumber if root
								 * split */
	BlockNumber leftChildBlkno; /* valid on a non-leaf split */
	BlockNumber rightChildBlkno;
	uint16		flags;			/* see below */
} ginxlogSplit;

/*
 * Flags used in ginxlogInsert and ginxlogSplit records
 */
#define GIN_INSERT_ISDATA	0x01	/* for both insert and split records */
#define GIN_INSERT_ISLEAF	0x02	/* ditto */
#define GIN_SPLIT_ROOT		0x04	/* only for split records */

/*
 * Vacuum simply WAL-logs the whole page, when anything is modified. This
 * is functionally identical to XLOG_FPI records, but is kept separate for
 * debugging purposes. (When inspecting the WAL stream, it's easier to see
 * what's going on when GIN vacuum records are marked as such, not as heap
 * records.) This is currently only used for entry tree leaf pages.
 */
#define XLOG_GIN_VACUUM_PAGE	0x40

/*
 * Vacuuming posting tree leaf page is WAL-logged like recompression caused
 * by insertion.
 */
#define XLOG_GIN_VACUUM_DATA_LEAF_PAGE	0x90

typedef struct ginxlogVacuumDataLeafPage
{
	ginxlogRecompressDataLeaf data;
} ginxlogVacuumDataLeafPage;

/*
 * Backup Blk 0: deleted page
 * Backup Blk 1: parent
 * Backup Blk 2: left sibling
 */
#define XLOG_GIN_DELETE_PAGE	0x50

typedef struct ginxlogDeletePage
{
	OffsetNumber parentOffset;
	BlockNumber rightLink;
	TransactionId deleteXid;	/* last Xid which could see this page in scan */
} ginxlogDeletePage;

#define XLOG_GIN_UPDATE_META_PAGE 0x60

/*
 * Backup Blk 0: metapage
 * Backup Blk 1: tail page
 */
typedef struct ginxlogUpdateMeta
{
	RelFileLocator locator;
	GinMetaPageData metadata;
	BlockNumber prevTail;
	BlockNumber newRightlink;
	int32		ntuples;		/* if ntuples > 0 then metadata.tail was
								 * updated with that many tuples; else new sub
								 * list was inserted */
	/* array of inserted tuples follows */
} ginxlogUpdateMeta;

#define XLOG_GIN_INSERT_LISTPAGE  0x70

typedef struct ginxlogInsertListPage
{
	BlockNumber rightlink;
	int32		ntuples;
	/* array of inserted tuples follows */
} ginxlogInsertListPage;

/*
 * Backup Blk 0: metapage
 * Backup Blk 1 to (ndeleted + 1): deleted pages
 */

#define XLOG_GIN_DELETE_LISTPAGE  0x80

/*
 * The WAL record for deleting list pages must contain a block reference to
 * all the deleted pages, so the number of pages that can be deleted in one
 * record is limited by XLR_MAX_BLOCK_ID. (block_id 0 is used for the
 * metapage.)
 */
#define GIN_NDELETE_AT_ONCE Min(16, XLR_MAX_BLOCK_ID - 1)
typedef struct ginxlogDeleteListPages
{
	GinMetaPageData metadata;
	int32		ndeleted;
} ginxlogDeleteListPages;

extern void gin_redo(XLogReaderState *record);
extern void gin_desc(StringInfo buf, XLogReaderState *record);
extern const char *gin_identify(uint8 info);
extern void gin_xlog_startup(void);
extern void gin_xlog_cleanup(void);
extern void gin_mask(char *pagedata, BlockNumber blkno);

#endif							/* GINXLOG_H */