1 /*-------------------------------------------------------------------------
4 * POSTGRES heap access XLOG definitions.
7 * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
10 * src/include/access/heapam_xlog.h
12 *-------------------------------------------------------------------------
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"
27 * WAL record definitions for heapam.c's WAL operations
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.
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
41 #define XLOG_HEAP_OPMASK 0x70
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
46 #define XLOG_HEAP_INIT_PAGE 0x80
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
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
63 * xl_heap_insert/xl_heap_multi_insert flag values, 8 bits are available.
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)
72 * xl_heap_update flag values, 8 bits are available.
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)
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)
89 * xl_heap_delete flag values, 8 bits are available.
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)
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)
101 /* This is what we need to know about delete */
102 typedef struct xl_heap_delete
104 TransactionId xmax; /* xmax of the deleted tuple */
105 OffsetNumber offnum; /* deleted tuple's offset */
106 uint8 infobits_set; /* infomask bits */
110 #define SizeOfHeapDelete (offsetof(xl_heap_delete, flags) + sizeof(uint8))
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 * NOTE: t_hoff could be recomputed, but we may as well store it because
118 * it will come for free due to alignment considerations.
120 typedef struct xl_heap_header
127 #define SizeOfHeapHeader (offsetof(xl_heap_header, t_hoff) + sizeof(uint8))
129 /* This is what we need to know about insert */
130 typedef struct xl_heap_insert
132 OffsetNumber offnum; /* inserted tuple's offset */
135 /* xl_heap_header & TUPLE DATA in backup block 0 */
138 #define SizeOfHeapInsert (offsetof(xl_heap_insert, flags) + sizeof(uint8))
141 * This is what we need to know about a multi-insert.
143 * The main data of the record consists of this xl_heap_multi_insert header.
144 * 'offsets' array is omitted if the whole page is reinitialized
145 * (XLOG_HEAP_INIT_PAGE).
147 * In block 0's data portion, there is an xl_multi_insert_tuple struct,
148 * followed by the tuple data for each tuple. There is padding to align
149 * each xl_multi_insert struct.
151 typedef struct xl_heap_multi_insert
155 OffsetNumber offsets[FLEXIBLE_ARRAY_MEMBER];
156 } xl_heap_multi_insert;
158 #define SizeOfHeapMultiInsert offsetof(xl_heap_multi_insert, offsets)
160 typedef struct xl_multi_insert_tuple
162 uint16 datalen; /* size of tuple data that follows */
166 /* TUPLE DATA FOLLOWS AT END OF STRUCT */
167 } xl_multi_insert_tuple;
169 #define SizeOfMultiInsertTuple (offsetof(xl_multi_insert_tuple, t_hoff) + sizeof(uint8))
172 * This is what we need to know about update|hot_update
174 * Backup blk 0: new page
176 * If XLOG_HEAP_PREFIX_FROM_OLD or XLOG_HEAP_SUFFIX_FROM_OLD flags are set,
177 * the prefix and/or suffix come first, as one or two uint16s.
179 * After that, xl_heap_header and new tuple data follow. The new tuple
180 * data doesn't include the prefix and suffix, which are copied from the
181 * old tuple on replay.
183 * If HEAP_CONTAINS_NEW_TUPLE_DATA flag is given, the tuple data is
184 * included even if a full-page image was taken.
186 * Backup blk 1: old page, if different. (no data, just a reference to the blk)
188 typedef struct xl_heap_update
190 TransactionId old_xmax; /* xmax of the old tuple */
191 OffsetNumber old_offnum; /* old tuple's offset */
192 uint8 old_infobits_set; /* infomask bits to set on old tuple */
194 TransactionId new_xmax; /* xmax of the new tuple */
195 OffsetNumber new_offnum; /* new tuple's offset */
198 * If XLOG_HEAP_CONTAINS_OLD_TUPLE or XLOG_HEAP_CONTAINS_OLD_KEY flags are
199 * set, a xl_heap_header struct and tuple data for the old tuple follows.
203 #define SizeOfHeapUpdate (offsetof(xl_heap_update, new_offnum) + sizeof(OffsetNumber))
206 * This is what we need to know about vacuum page cleanup/redirect
208 * The array of OffsetNumbers following the fixed part of the record contains:
209 * * for each redirected item: the item offset, then the offset redirected to
210 * * for each now-dead item: the item offset
211 * * for each now-unused item: the item offset
212 * The total number of OffsetNumbers is therefore 2*nredirected+ndead+nunused.
213 * Note that nunused is not explicitly stored, but may be found by reference
214 * to the total record length.
216 typedef struct xl_heap_clean
218 TransactionId latestRemovedXid;
221 /* OFFSET NUMBERS are in the block reference 0 */
224 #define SizeOfHeapClean (offsetof(xl_heap_clean, ndead) + sizeof(uint16))
227 * Cleanup_info is required in some cases during a lazy VACUUM.
228 * Used for reporting the results of HeapTupleHeaderAdvanceLatestRemovedXid()
229 * see vacuumlazy.c for full explanation
231 typedef struct xl_heap_cleanup_info
234 TransactionId latestRemovedXid;
235 } xl_heap_cleanup_info;
237 #define SizeOfHeapCleanupInfo (sizeof(xl_heap_cleanup_info))
239 /* flags for infobits_set */
240 #define XLHL_XMAX_IS_MULTI 0x01
241 #define XLHL_XMAX_LOCK_ONLY 0x02
242 #define XLHL_XMAX_EXCL_LOCK 0x04
243 #define XLHL_XMAX_KEYSHR_LOCK 0x08
244 #define XLHL_KEYS_UPDATED 0x10
246 /* flag bits for xl_heap_lock / xl_heap_lock_updated's flag field */
247 #define XLH_LOCK_ALL_FROZEN_CLEARED 0x01
249 /* This is what we need to know about lock */
250 typedef struct xl_heap_lock
252 TransactionId locking_xid; /* might be a MultiXactId not xid */
253 OffsetNumber offnum; /* locked tuple's offset on page */
254 int8 infobits_set; /* infomask and infomask2 bits to set */
255 uint8 flags; /* XLH_LOCK_* flag bits */
258 #define SizeOfHeapLock (offsetof(xl_heap_lock, flags) + sizeof(int8))
260 /* This is what we need to know about locking an updated version of a row */
261 typedef struct xl_heap_lock_updated
267 } xl_heap_lock_updated;
269 #define SizeOfHeapLockUpdated (offsetof(xl_heap_lock_updated, flags) + sizeof(uint8))
271 /* This is what we need to know about confirmation of speculative insertion */
272 typedef struct xl_heap_confirm
274 OffsetNumber offnum; /* confirmed tuple's offset on page */
277 #define SizeOfHeapConfirm (offsetof(xl_heap_confirm, offnum) + sizeof(OffsetNumber))
279 /* This is what we need to know about in-place update */
280 typedef struct xl_heap_inplace
282 OffsetNumber offnum; /* updated tuple's offset on page */
283 /* TUPLE DATA FOLLOWS AT END OF STRUCT */
286 #define SizeOfHeapInplace (offsetof(xl_heap_inplace, offnum) + sizeof(OffsetNumber))
289 * This struct represents a 'freeze plan', which is what we need to know about
290 * a single tuple being frozen during vacuum.
292 /* 0x01 was XLH_FREEZE_XMIN */
293 #define XLH_FREEZE_XVAC 0x02
294 #define XLH_INVALID_XVAC 0x04
296 typedef struct xl_heap_freeze_tuple
303 } xl_heap_freeze_tuple;
306 * This is what we need to know about a block being frozen during vacuum
308 * Backup block 0's data contains an array of xl_heap_freeze_tuple structs,
309 * one for each tuple.
311 typedef struct xl_heap_freeze_page
313 TransactionId cutoff_xid;
315 } xl_heap_freeze_page;
317 #define SizeOfHeapFreezePage (offsetof(xl_heap_freeze_page, ntuples) + sizeof(uint16))
320 * This is what we need to know about setting a visibility map bit
322 * Backup blk 0: visibility map buffer
323 * Backup blk 1: heap buffer
325 typedef struct xl_heap_visible
327 TransactionId cutoff_xid;
331 #define SizeOfHeapVisible (offsetof(xl_heap_visible, flags) + sizeof(uint8))
333 typedef struct xl_heap_new_cid
336 * store toplevel xid so we don't have to merge cids from different
339 TransactionId top_xid;
344 * don't really need the combocid since we have the actual values right in
345 * this struct, but the padding makes it free and its useful for
351 * Store the relfilenode/ctid pair to facilitate lookups.
353 RelFileNode target_node;
354 ItemPointerData target_tid;
357 #define SizeOfHeapNewCid (offsetof(xl_heap_new_cid, target_tid) + sizeof(ItemPointerData))
359 /* logical rewrite xlog record header */
360 typedef struct xl_heap_rewrite_mapping
362 TransactionId mapped_xid; /* xid that might need to see the row */
363 Oid mapped_db; /* DbOid or InvalidOid for shared rels */
364 Oid mapped_rel; /* Oid of the mapped relation */
365 off_t offset; /* How far have we written so far */
366 uint32 num_mappings; /* Number of in-memory mappings */
367 XLogRecPtr start_lsn; /* Insert LSN at begin of rewrite */
368 } xl_heap_rewrite_mapping;
370 extern void HeapTupleHeaderAdvanceLatestRemovedXid(HeapTupleHeader tuple,
371 TransactionId *latestRemovedXid);
373 extern void heap_redo(XLogReaderState *record);
374 extern void heap_desc(StringInfo buf, XLogReaderState *record);
375 extern const char *heap_identify(uint8 info);
376 extern void heap_mask(char *pagedata, BlockNumber blkno);
377 extern void heap2_redo(XLogReaderState *record);
378 extern void heap2_desc(StringInfo buf, XLogReaderState *record);
379 extern const char *heap2_identify(uint8 info);
380 extern void heap_xlog_logical_rewrite(XLogReaderState *r);
382 extern XLogRecPtr log_heap_cleanup_info(RelFileNode rnode,
383 TransactionId latestRemovedXid);
384 extern XLogRecPtr log_heap_clean(Relation reln, Buffer buffer,
385 OffsetNumber *redirected, int nredirected,
386 OffsetNumber *nowdead, int ndead,
387 OffsetNumber *nowunused, int nunused,
388 TransactionId latestRemovedXid);
389 extern XLogRecPtr log_heap_freeze(Relation reln, Buffer buffer,
390 TransactionId cutoff_xid, xl_heap_freeze_tuple *tuples,
392 extern bool heap_prepare_freeze_tuple(HeapTupleHeader tuple,
393 TransactionId cutoff_xid,
394 TransactionId cutoff_multi,
395 xl_heap_freeze_tuple *frz,
396 bool *totally_frozen);
397 extern void heap_execute_freeze_tuple(HeapTupleHeader tuple,
398 xl_heap_freeze_tuple *xlrec_tp);
399 extern XLogRecPtr log_heap_visible(RelFileNode rnode, Buffer heap_buffer,
400 Buffer vm_buffer, TransactionId cutoff_xid, uint8 flags);
402 #endif /* HEAPAM_XLOG_H */