diff options
Diffstat (limited to 'src/include/access/xlogrecord.h')
-rw-r--r-- | src/include/access/xlogrecord.h | 160 |
1 files changed, 120 insertions, 40 deletions
diff --git a/src/include/access/xlogrecord.h b/src/include/access/xlogrecord.h index ab0fb1c5004..11ddfac9c7f 100644 --- a/src/include/access/xlogrecord.h +++ b/src/include/access/xlogrecord.h @@ -20,81 +20,161 @@ /* * The overall layout of an XLOG record is: * Fixed-size header (XLogRecord struct) - * rmgr-specific data - * BkpBlock - * backup block data - * BkpBlock - * backup block data + * XLogRecordBlockHeader struct + * XLogRecordBlockHeader struct * ... + * XLogRecordDataHeader[Short|Long] struct + * block data + * block data + * ... + * main data * - * where there can be zero to four backup blocks (as signaled by xl_info flag - * bits). XLogRecord structs always start on MAXALIGN boundaries in the WAL - * files, and we round up SizeOfXLogRecord so that the rmgr data is also - * guaranteed to begin on a MAXALIGN boundary. However, no padding is added - * to align BkpBlock structs or backup block data. + * There can be zero or more XLogRecordBlockHeaders, and 0 or more bytes of + * rmgr-specific data not associated with a block. XLogRecord structs + * always start on MAXALIGN boundaries in the WAL files, but the rest of + * the fields are not aligned. * - * NOTE: xl_len counts only the rmgr data, not the XLogRecord header, - * and also not any backup blocks. xl_tot_len counts everything. Neither - * length field is rounded up to an alignment boundary. + * The XLogRecordBlockHeader, XLogRecordDataHeaderShort and + * XLogRecordDataHeaderLong structs all begin with a single 'id' byte. It's + * used to distinguish between block references, and the main data structs. */ typedef struct XLogRecord { uint32 xl_tot_len; /* total len of entire record */ TransactionId xl_xid; /* xact id */ - uint32 xl_len; /* total len of rmgr data */ + XLogRecPtr xl_prev; /* ptr to previous record in log */ uint8 xl_info; /* flag bits, see below */ RmgrId xl_rmid; /* resource manager for this record */ /* 2 bytes of padding here, initialize to zero */ - XLogRecPtr xl_prev; /* ptr to previous record in log */ pg_crc32 xl_crc; /* CRC for this record */ - /* If MAXALIGN==8, there are 4 wasted bytes here */ - - /* ACTUAL LOG DATA FOLLOWS AT END OF STRUCT */ + /* XLogRecordBlockHeaders and XLogRecordDataHeader follow, no padding */ } XLogRecord; -#define SizeOfXLogRecord MAXALIGN(sizeof(XLogRecord)) - -#define XLogRecGetData(record) ((char*) (record) + SizeOfXLogRecord) +#define SizeOfXLogRecord (offsetof(XLogRecord, xl_crc) + sizeof(pg_crc32)) /* - * XLOG uses only low 4 bits of xl_info. High 4 bits may be used by rmgr. + * The high 4 bits in xl_info may be used freely by rmgr. The + * XLR_SPECIAL_REL_UPDATE bit can be passed by XLogInsert caller. The rest + * are set internally by XLogInsert. */ #define XLR_INFO_MASK 0x0F +#define XLR_RMGR_INFO_MASK 0xF0 /* - * If we backed up any disk blocks with the XLOG record, we use flag bits in - * xl_info to signal it. We support backup of up to 4 disk blocks per XLOG - * record. + * If a WAL record modifies any relation files, in ways not covered by the + * usual block references, this flag is set. This is not used for anything + * by PostgreSQL itself, but it allows external tools that read WAL and keep + * track of modified blocks to recognize such special record types. + */ +#define XLR_SPECIAL_REL_UPDATE 0x01 + +/* + * Header info for block data appended to an XLOG record. + * + * Note that we don't attempt to align the XLogRecordBlockHeader struct! + * So, the struct must be copied to aligned local storage before use. + * 'data_length' is the length of the payload data associated with this, + * and includes the possible full-page image, and rmgr-specific data. It + * does not include the XLogRecordBlockHeader struct itself. */ -#define XLR_BKP_BLOCK_MASK 0x0F /* all info bits used for bkp blocks */ -#define XLR_MAX_BKP_BLOCKS 4 -#define XLR_BKP_BLOCK(iblk) (0x08 >> (iblk)) /* iblk in 0..3 */ +typedef struct XLogRecordBlockHeader +{ + uint8 id; /* block reference ID */ + uint8 fork_flags; /* fork within the relation, and flags */ + uint16 data_length; /* number of payload bytes (not including page + * image) */ + + /* If BKPBLOCK_HAS_IMAGE, an XLogRecordBlockImageHeader struct follows */ + /* If !BKPBLOCK_SAME_REL is not set, a RelFileNode follows */ + /* BlockNumber follows */ +} XLogRecordBlockHeader; + +#define SizeOfXLogRecordBlockHeader (offsetof(XLogRecordBlockHeader, data_length) + sizeof(uint16)) /* - * Header info for a backup block appended to an XLOG record. + * Additional header information when a full-page image is included + * (i.e. when BKPBLOCK_HAS_IMAGE is set). * * As a trivial form of data compression, the XLOG code is aware that * PG data pages usually contain an unused "hole" in the middle, which * contains only zero bytes. If hole_length > 0 then we have removed * such a "hole" from the stored data (and it's not counted in the * XLOG record's CRC, either). Hence, the amount of block data actually - * present following the BkpBlock struct is BLCKSZ - hole_length bytes. - * - * Note that we don't attempt to align either the BkpBlock struct or the - * block's data. So, the struct must be copied to aligned local storage - * before use. + * present is BLCKSZ - hole_length bytes. */ -typedef struct BkpBlock +typedef struct XLogRecordBlockImageHeader { - RelFileNode node; /* relation containing block */ - ForkNumber fork; /* fork within the relation */ - BlockNumber block; /* block number */ uint16 hole_offset; /* number of bytes before "hole" */ uint16 hole_length; /* number of bytes in "hole" */ +} XLogRecordBlockImageHeader; + +#define SizeOfXLogRecordBlockImageHeader sizeof(XLogRecordBlockImageHeader) + +/* + * Maximum size of the header for a block reference. This is used to size a + * temporary buffer for constructing the header. + */ +#define MaxSizeOfXLogRecordBlockHeader \ + (SizeOfXLogRecordBlockHeader + \ + SizeOfXLogRecordBlockImageHeader + \ + sizeof(RelFileNode) + \ + sizeof(BlockNumber)) + +/* + * The fork number fits in the lower 4 bits in the fork_flags field. The upper + * bits are used for flags. + */ +#define BKPBLOCK_FORK_MASK 0x0F +#define BKPBLOCK_FLAG_MASK 0xF0 +#define BKPBLOCK_HAS_IMAGE 0x10 /* block data is an XLogRecordBlockImage */ +#define BKPBLOCK_HAS_DATA 0x20 +#define BKPBLOCK_WILL_INIT 0x40 /* redo will re-init the page */ +#define BKPBLOCK_SAME_REL 0x80 /* RelFileNode omitted, same as previous */ + +/* + * XLogRecordDataHeaderShort/Long are used for the "main data" portion of + * the record. If the length of the data is less than 256 bytes, the short + * form is used, with a single byte to hold the length. Otherwise the long + * form is used. + * + * (These structs are currently not used in the code, they are here just for + * documentation purposes). + */ +typedef struct XLogRecordDataHeaderShort +{ + uint8 id; /* XLR_BLOCK_ID_DATA_SHORT */ + uint8 data_length; /* number of payload bytes */ +} XLogRecordDataHeaderShort; + +#define SizeOfXLogRecordDataHeaderShort (sizeof(uint8) * 2) + +typedef struct XLogRecordDataHeaderLong +{ + uint8 id; /* XLR_BLOCK_ID_DATA_LONG */ + /* followed by uint32 data_length, unaligned */ +} XLogRecordDataHeaderLong; + +#define SizeOfXLogRecordDataHeaderLong (sizeof(uint8) + sizeof(uint32)) + +/* + * Block IDs used to distinguish different kinds of record fragments. Block + * references are numbered from 0 to XLR_MAX_BLOCK_ID. A rmgr is free to use + * any ID number in that range (although you should stick to small numbers, + * because the WAL machinery is optimized for that case). A couple of ID + * numbers are reserved to denote the "main" data portion of the record. + * + * The maximum is currently set at 32, quite arbitrarily. Most records only + * need a handful of block references, but there are a few exceptions that + * need more. + */ +#define XLR_MAX_BLOCK_ID 32 + +#define XLR_BLOCK_ID_DATA_SHORT 255 +#define XLR_BLOCK_ID_DATA_LONG 254 + +#define SizeOfXLogRecordDataHeaderLong (sizeof(uint8) + sizeof(uint32)) - /* ACTUAL BLOCK DATA FOLLOWS AT END OF STRUCT */ -} BkpBlock; #endif /* XLOGRECORD_H */ |