1 /*------------------------------------------------------------------------- 2 * 3 * heapam_xlog.h 4 * POSTGRES heap access XLOG definitions. 5 * 6 * 7 * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group 8 * Portions Copyright (c) 1994, Regents of the University of California 9 * 10 * src/include/access/heapam_xlog.h 11 * 12 *------------------------------------------------------------------------- 13 */ 14 #ifndef HEAPAM_XLOG_H 15 #define HEAPAM_XLOG_H 16 17 #include "access/htup.h" 18 #include "access/xlogreader.h" 19 #include "lib/stringinfo.h" 20 #include "storage/buf.h" 21 #include "storage/bufpage.h" 22 #include "storage/relfilenode.h" 23 #include "utils/relcache.h" 24 25 26 /* 27 * WAL record definitions for heapam.c's WAL operations 28 * 29 * XLOG allows to store some information in high 4 bits of log 30 * record xl_info field. We use 3 for opcode and one for init bit. 31 */ 32 #define XLOG_HEAP_INSERT 0x00 33 #define XLOG_HEAP_DELETE 0x10 34 #define XLOG_HEAP_UPDATE 0x20 35 /* 0x030 is free, was XLOG_HEAP_MOVE */ 36 #define XLOG_HEAP_HOT_UPDATE 0x40 37 #define XLOG_HEAP_CONFIRM 0x50 38 #define XLOG_HEAP_LOCK 0x60 39 #define XLOG_HEAP_INPLACE 0x70 40 41 #define XLOG_HEAP_OPMASK 0x70 42 /* 43 * When we insert 1st item on new page in INSERT, UPDATE, HOT_UPDATE, 44 * or MULTI_INSERT, we can (and we do) restore entire page in redo 45 */ 46 #define XLOG_HEAP_INIT_PAGE 0x80 47 /* 48 * We ran out of opcodes, so heapam.c now has a second RmgrId. These opcodes 49 * are associated with RM_HEAP2_ID, but are not logically different from 50 * the ones above associated with RM_HEAP_ID. XLOG_HEAP_OPMASK applies to 51 * these, too. 52 */ 53 #define XLOG_HEAP2_REWRITE 0x00 54 #define XLOG_HEAP2_CLEAN 0x10 55 #define XLOG_HEAP2_FREEZE_PAGE 0x20 56 #define XLOG_HEAP2_CLEANUP_INFO 0x30 57 #define XLOG_HEAP2_VISIBLE 0x40 58 #define XLOG_HEAP2_MULTI_INSERT 0x50 59 #define XLOG_HEAP2_LOCK_UPDATED 0x60 60 #define XLOG_HEAP2_NEW_CID 0x70 61 62 /* 63 * xl_heap_insert/xl_heap_multi_insert flag values, 8 bits are available. 64 */ 65 /* PD_ALL_VISIBLE was cleared */ 66 #define XLH_INSERT_ALL_VISIBLE_CLEARED (1<<0) 67 #define XLH_INSERT_LAST_IN_MULTI (1<<1) 68 #define XLH_INSERT_IS_SPECULATIVE (1<<2) 69 #define XLH_INSERT_CONTAINS_NEW_TUPLE (1<<3) 70 71 /* 72 * xl_heap_update flag values, 8 bits are available. 73 */ 74 /* PD_ALL_VISIBLE was cleared */ 75 #define XLH_UPDATE_OLD_ALL_VISIBLE_CLEARED (1<<0) 76 /* PD_ALL_VISIBLE was cleared in the 2nd page */ 77 #define XLH_UPDATE_NEW_ALL_VISIBLE_CLEARED (1<<1) 78 #define XLH_UPDATE_CONTAINS_OLD_TUPLE (1<<2) 79 #define XLH_UPDATE_CONTAINS_OLD_KEY (1<<3) 80 #define XLH_UPDATE_CONTAINS_NEW_TUPLE (1<<4) 81 #define XLH_UPDATE_PREFIX_FROM_OLD (1<<5) 82 #define XLH_UPDATE_SUFFIX_FROM_OLD (1<<6) 83 84 /* convenience macro for checking whether any form of old tuple was logged */ 85 #define XLH_UPDATE_CONTAINS_OLD \ 86 (XLH_UPDATE_CONTAINS_OLD_TUPLE | XLH_UPDATE_CONTAINS_OLD_KEY) 87 88 /* 89 * xl_heap_delete flag values, 8 bits are available. 90 */ 91 /* PD_ALL_VISIBLE was cleared */ 92 #define XLH_DELETE_ALL_VISIBLE_CLEARED (1<<0) 93 #define XLH_DELETE_CONTAINS_OLD_TUPLE (1<<1) 94 #define XLH_DELETE_CONTAINS_OLD_KEY (1<<2) 95 #define XLH_DELETE_IS_SUPER (1<<3) 96 97 /* convenience macro for checking whether any form of old tuple was logged */ 98 #define XLH_DELETE_CONTAINS_OLD \ 99 (XLH_DELETE_CONTAINS_OLD_TUPLE | XLH_DELETE_CONTAINS_OLD_KEY) 100 101 /* This is what we need to know about delete */ 102 typedef struct xl_heap_delete 103 { 104 TransactionId xmax; /* xmax of the deleted tuple */ 105 OffsetNumber offnum; /* deleted tuple's offset */ 106 uint8 infobits_set; /* infomask bits */ 107 uint8 flags; 108 } xl_heap_delete; 109 110 #define SizeOfHeapDelete (offsetof(xl_heap_delete, flags) + sizeof(uint8)) 111 112 /* 113 * We don't store the whole fixed part (HeapTupleHeaderData) of an inserted 114 * or updated tuple in WAL; we can save a few bytes by reconstructing the 115 * fields that are available elsewhere in the WAL record, or perhaps just 116 * plain needn't be reconstructed. These are the fields we must store. 117 */ 118 typedef struct xl_heap_header 119 { 120 uint16 t_infomask2; 121 uint16 t_infomask; 122 uint8 t_hoff; 123 } xl_heap_header; 124 125 #define SizeOfHeapHeader (offsetof(xl_heap_header, t_hoff) + sizeof(uint8)) 126 127 /* This is what we need to know about insert */ 128 typedef struct xl_heap_insert 129 { 130 OffsetNumber offnum; /* inserted tuple's offset */ 131 uint8 flags; 132 133 /* xl_heap_header & TUPLE DATA in backup block 0 */ 134 } xl_heap_insert; 135 136 #define SizeOfHeapInsert (offsetof(xl_heap_insert, flags) + sizeof(uint8)) 137 138 /* 139 * This is what we need to know about a multi-insert. 140 * 141 * The main data of the record consists of this xl_heap_multi_insert header. 142 * 'offsets' array is omitted if the whole page is reinitialized 143 * (XLOG_HEAP_INIT_PAGE). 144 * 145 * In block 0's data portion, there is an xl_multi_insert_tuple struct, 146 * followed by the tuple data for each tuple. There is padding to align 147 * each xl_multi_insert struct. 148 */ 149 typedef struct xl_heap_multi_insert 150 { 151 uint8 flags; 152 uint16 ntuples; 153 OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER]; 154 } xl_heap_multi_insert; 155 156 #define SizeOfHeapMultiInsert offsetof(xl_heap_multi_insert, offsets) 157 158 typedef struct xl_multi_insert_tuple 159 { 160 uint16 datalen; /* size of tuple data that follows */ 161 uint16 t_infomask2; 162 uint16 t_infomask; 163 uint8 t_hoff; 164 /* TUPLE DATA FOLLOWS AT END OF STRUCT */ 165 } xl_multi_insert_tuple; 166 167 #define SizeOfMultiInsertTuple (offsetof(xl_multi_insert_tuple, t_hoff) + sizeof(uint8)) 168 169 /* 170 * This is what we need to know about update|hot_update 171 * 172 * Backup blk 0: new page 173 * 174 * If XLOG_HEAP_PREFIX_FROM_OLD or XLOG_HEAP_SUFFIX_FROM_OLD flags are set, 175 * the prefix and/or suffix come first, as one or two uint16s. 176 * 177 * After that, xl_heap_header and new tuple data follow. The new tuple 178 * data doesn't include the prefix and suffix, which are copied from the 179 * old tuple on replay. 180 * 181 * If HEAP_CONTAINS_NEW_TUPLE_DATA flag is given, the tuple data is 182 * included even if a full-page image was taken. 183 * 184 * Backup blk 1: old page, if different. (no data, just a reference to the blk) 185 */ 186 typedef struct xl_heap_update 187 { 188 TransactionId old_xmax; /* xmax of the old tuple */ 189 OffsetNumber old_offnum; /* old tuple's offset */ 190 uint8 old_infobits_set; /* infomask bits to set on old tuple */ 191 uint8 flags; 192 TransactionId new_xmax; /* xmax of the new tuple */ 193 OffsetNumber new_offnum; /* new tuple's offset */ 194 195 /* 196 * If XLOG_HEAP_CONTAINS_OLD_TUPLE or XLOG_HEAP_CONTAINS_OLD_KEY flags are 197 * set, a xl_heap_header struct and tuple data for the old tuple follows. 198 */ 199 } xl_heap_update; 200 201 #define SizeOfHeapUpdate (offsetof(xl_heap_update, new_offnum) + sizeof(OffsetNumber)) 202 203 /* 204 * This is what we need to know about vacuum page cleanup/redirect 205 * 206 * The array of OffsetNumbers following the fixed part of the record contains: 207 * * for each redirected item: the item offset, then the offset redirected to 208 * * for each now-dead item: the item offset 209 * * for each now-unused item: the item offset 210 * The total number of OffsetNumbers is therefore 2*nredirected+ndead+nunused. 211 * Note that nunused is not explicitly stored, but may be found by reference 212 * to the total record length. 213 */ 214 typedef struct xl_heap_clean 215 { 216 TransactionId latestRemovedXid; 217 uint16 nredirected; 218 uint16 ndead; 219 /* OFFSET NUMBERS are in the block reference 0 */ 220 } xl_heap_clean; 221 222 #define SizeOfHeapClean (offsetof(xl_heap_clean, ndead) + sizeof(uint16)) 223 224 /* 225 * Cleanup_info is required in some cases during a lazy VACUUM. 226 * Used for reporting the results of HeapTupleHeaderAdvanceLatestRemovedXid() 227 * see vacuumlazy.c for full explanation 228 */ 229 typedef struct xl_heap_cleanup_info 230 { 231 RelFileNode node; 232 TransactionId latestRemovedXid; 233 } xl_heap_cleanup_info; 234 235 #define SizeOfHeapCleanupInfo (sizeof(xl_heap_cleanup_info)) 236 237 /* flags for infobits_set */ 238 #define XLHL_XMAX_IS_MULTI 0x01 239 #define XLHL_XMAX_LOCK_ONLY 0x02 240 #define XLHL_XMAX_EXCL_LOCK 0x04 241 #define XLHL_XMAX_KEYSHR_LOCK 0x08 242 #define XLHL_KEYS_UPDATED 0x10 243 244 /* flag bits for xl_heap_lock / xl_heap_lock_updated's flag field */ 245 #define XLH_LOCK_ALL_FROZEN_CLEARED 0x01 246 247 /* This is what we need to know about lock */ 248 typedef struct xl_heap_lock 249 { 250 TransactionId locking_xid; /* might be a MultiXactId not xid */ 251 OffsetNumber offnum; /* locked tuple's offset on page */ 252 int8 infobits_set; /* infomask and infomask2 bits to set */ 253 uint8 flags; /* XLH_LOCK_* flag bits */ 254 } xl_heap_lock; 255 256 #define SizeOfHeapLock (offsetof(xl_heap_lock, flags) + sizeof(int8)) 257 258 /* This is what we need to know about locking an updated version of a row */ 259 typedef struct xl_heap_lock_updated 260 { 261 TransactionId xmax; 262 OffsetNumber offnum; 263 uint8 infobits_set; 264 uint8 flags; 265 } xl_heap_lock_updated; 266 267 #define SizeOfHeapLockUpdated (offsetof(xl_heap_lock_updated, flags) + sizeof(uint8)) 268 269 /* This is what we need to know about confirmation of speculative insertion */ 270 typedef struct xl_heap_confirm 271 { 272 OffsetNumber offnum; /* confirmed tuple's offset on page */ 273 } xl_heap_confirm; 274 275 #define SizeOfHeapConfirm (offsetof(xl_heap_confirm, offnum) + sizeof(OffsetNumber)) 276 277 /* This is what we need to know about in-place update */ 278 typedef struct xl_heap_inplace 279 { 280 OffsetNumber offnum; /* updated tuple's offset on page */ 281 /* TUPLE DATA FOLLOWS AT END OF STRUCT */ 282 } xl_heap_inplace; 283 284 #define SizeOfHeapInplace (offsetof(xl_heap_inplace, offnum) + sizeof(OffsetNumber)) 285 286 /* 287 * This struct represents a 'freeze plan', which is what we need to know about 288 * a single tuple being frozen during vacuum. 289 */ 290 /* 0x01 was XLH_FREEZE_XMIN */ 291 #define XLH_FREEZE_XVAC 0x02 292 #define XLH_INVALID_XVAC 0x04 293 294 typedef struct xl_heap_freeze_tuple 295 { 296 TransactionId xmax; 297 OffsetNumber offset; 298 uint16 t_infomask2; 299 uint16 t_infomask; 300 uint8 frzflags; 301 } xl_heap_freeze_tuple; 302 303 /* 304 * This is what we need to know about a block being frozen during vacuum 305 * 306 * Backup block 0's data contains an array of xl_heap_freeze_tuple structs, 307 * one for each tuple. 308 */ 309 typedef struct xl_heap_freeze_page 310 { 311 TransactionId cutoff_xid; 312 uint16 ntuples; 313 } xl_heap_freeze_page; 314 315 #define SizeOfHeapFreezePage (offsetof(xl_heap_freeze_page, ntuples) + sizeof(uint16)) 316 317 /* 318 * This is what we need to know about setting a visibility map bit 319 * 320 * Backup blk 0: visibility map buffer 321 * Backup blk 1: heap buffer 322 */ 323 typedef struct xl_heap_visible 324 { 325 TransactionId cutoff_xid; 326 uint8 flags; 327 } xl_heap_visible; 328 329 #define SizeOfHeapVisible (offsetof(xl_heap_visible, flags) + sizeof(uint8)) 330 331 typedef struct xl_heap_new_cid 332 { 333 /* 334 * store toplevel xid so we don't have to merge cids from different 335 * transactions 336 */ 337 TransactionId top_xid; 338 CommandId cmin; 339 CommandId cmax; 340 CommandId combocid; /* just for debugging */ 341 342 /* 343 * Store the relfilenode/ctid pair to facilitate lookups. 344 */ 345 RelFileNode target_node; 346 ItemPointerData target_tid; 347 } xl_heap_new_cid; 348 349 #define SizeOfHeapNewCid (offsetof(xl_heap_new_cid, target_tid) + sizeof(ItemPointerData)) 350 351 /* logical rewrite xlog record header */ 352 typedef struct xl_heap_rewrite_mapping 353 { 354 TransactionId mapped_xid; /* xid that might need to see the row */ 355 Oid mapped_db; /* DbOid or InvalidOid for shared rels */ 356 Oid mapped_rel; /* Oid of the mapped relation */ 357 off_t offset; /* How far have we written so far */ 358 uint32 num_mappings; /* Number of in-memory mappings */ 359 XLogRecPtr start_lsn; /* Insert LSN at begin of rewrite */ 360 } xl_heap_rewrite_mapping; 361 362 extern void HeapTupleHeaderAdvanceLatestRemovedXid(HeapTupleHeader tuple, 363 TransactionId *latestRemovedXid); 364 365 extern void heap_redo(XLogReaderState *record); 366 extern void heap_desc(StringInfo buf, XLogReaderState *record); 367 extern const char *heap_identify(uint8 info); 368 extern void heap_mask(char *pagedata, BlockNumber blkno); 369 extern void heap2_redo(XLogReaderState *record); 370 extern void heap2_desc(StringInfo buf, XLogReaderState *record); 371 extern const char *heap2_identify(uint8 info); 372 extern void heap_xlog_logical_rewrite(XLogReaderState *r); 373 374 extern XLogRecPtr log_heap_cleanup_info(RelFileNode rnode, 375 TransactionId latestRemovedXid); 376 extern XLogRecPtr log_heap_clean(Relation reln, Buffer buffer, 377 OffsetNumber *redirected, int nredirected, 378 OffsetNumber *nowdead, int ndead, 379 OffsetNumber *nowunused, int nunused, 380 TransactionId latestRemovedXid); 381 extern XLogRecPtr log_heap_freeze(Relation reln, Buffer buffer, 382 TransactionId cutoff_xid, xl_heap_freeze_tuple *tuples, 383 int ntuples); 384 extern bool heap_prepare_freeze_tuple(HeapTupleHeader tuple, 385 TransactionId relfrozenxid, 386 TransactionId relminmxid, 387 TransactionId cutoff_xid, 388 TransactionId cutoff_multi, 389 xl_heap_freeze_tuple *frz, 390 bool *totally_frozen); 391 extern void heap_execute_freeze_tuple(HeapTupleHeader tuple, 392 xl_heap_freeze_tuple *xlrec_tp); 393 extern XLogRecPtr log_heap_visible(RelFileNode rnode, Buffer heap_buffer, 394 Buffer vm_buffer, TransactionId cutoff_xid, uint8 flags); 395 396 #endif /* HEAPAM_XLOG_H */ 397