| 1 | /*-------------------------------------------------------------------------- |
| 2 | * ginxlog.h |
| 3 | * header file for postgres inverted index xlog implementation. |
| 4 | * |
| 5 | * Copyright (c) 2006-2019, 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 heap_newpage 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 | |