codekingpro/portable-devtools
115k
1/*-------------------------------------------------------------------------2 *3 * xlogreader.h4 * Definitions for the generic XLog reading facility5 *6 * Portions Copyright (c) 2013-2023, PostgreSQL Global Development Group7 *8 * IDENTIFICATION9 * src/include/access/xlogreader.h10 *11 * NOTES12 * See the definition of the XLogReaderState struct for instructions on13 * how to use the XLogReader infrastructure.14 *15 * The basic idea is to allocate an XLogReaderState via16 * XLogReaderAllocate(), position the reader to the first record with17 * XLogBeginRead() or XLogFindNextRecord(), and call XLogReadRecord()18 * until it returns NULL.19 *20 * Callers supply a page_read callback if they want to call21 * XLogReadRecord or XLogFindNextRecord; it can be passed in as NULL22 * otherwise. The WALRead function can be used as a helper to write23 * page_read callbacks, but it is not mandatory; callers that use it,24 * must supply segment_open callbacks. The segment_close callback25 * must always be supplied.26 *27 * After reading a record with XLogReadRecord(), it's decomposed into28 * the per-block and main data parts, and the parts can be accessed29 * with the XLogRec* macros and functions. You can also decode a30 * record that's already constructed in memory, without reading from31 * disk, by calling the DecodeXLogRecord() function.32 *-------------------------------------------------------------------------33 */34#ifndef XLOGREADER_H35#define XLOGREADER_H36 37#ifndef FRONTEND38#include "access/transam.h"39#endif40 41#include "access/xlogrecord.h"42#include "storage/buf.h"43 44/* WALOpenSegment represents a WAL segment being read. */45typedef struct WALOpenSegment46{47 int ws_file; /* segment file descriptor */48 XLogSegNo ws_segno; /* segment number */49 TimeLineID ws_tli; /* timeline ID of the currently open file */50} WALOpenSegment;51 52/* WALSegmentContext carries context information about WAL segments to read */53typedef struct WALSegmentContext54{55 char ws_dir[MAXPGPATH];56 int ws_segsize;57} WALSegmentContext;58 59typedef struct XLogReaderState XLogReaderState;60 61/* Function type definitions for various xlogreader interactions */62typedef int (*XLogPageReadCB) (XLogReaderState *xlogreader,63 XLogRecPtr targetPagePtr,64 int reqLen,65 XLogRecPtr targetRecPtr,66 char *readBuf);67typedef void (*WALSegmentOpenCB) (XLogReaderState *xlogreader,68 XLogSegNo nextSegNo,69 TimeLineID *tli_p);70typedef void (*WALSegmentCloseCB) (XLogReaderState *xlogreader);71 72typedef struct XLogReaderRoutine73{74 /*75 * Data input callback76 *77 * This callback shall read at least reqLen valid bytes of the xlog page78 * starting at targetPagePtr, and store them in readBuf. The callback79 * shall return the number of bytes read (never more than XLOG_BLCKSZ), or80 * -1 on failure. The callback shall sleep, if necessary, to wait for the81 * requested bytes to become available. The callback will not be invoked82 * again for the same page unless more than the returned number of bytes83 * are needed.84 *85 * targetRecPtr is the position of the WAL record we're reading. Usually86 * it is equal to targetPagePtr + reqLen, but sometimes xlogreader needs87 * to read and verify the page or segment header, before it reads the88 * actual WAL record it's interested in. In that case, targetRecPtr can89 * be used to determine which timeline to read the page from.90 *91 * The callback shall set ->seg.ws_tli to the TLI of the file the page was92 * read from.93 */94 XLogPageReadCB page_read;95 96 /*97 * Callback to open the specified WAL segment for reading. ->seg.ws_file98 * shall be set to the file descriptor of the opened segment. In case of99 * failure, an error shall be raised by the callback and it shall not100 * return.101 *102 * "nextSegNo" is the number of the segment to be opened.103 *104 * "tli_p" is an input/output argument. WALRead() uses it to pass the105 * timeline in which the new segment should be found, but the callback can106 * use it to return the TLI that it actually opened.107 */108 WALSegmentOpenCB segment_open;109 110 /*111 * WAL segment close callback. ->seg.ws_file shall be set to a negative112 * number.113 */114 WALSegmentCloseCB segment_close;115} XLogReaderRoutine;116 117#define XL_ROUTINE(...) &(XLogReaderRoutine){__VA_ARGS__}118 119typedef struct120{121 /* Is this block ref in use? */122 bool in_use;123 124 /* Identify the block this refers to */125 RelFileLocator rlocator;126 ForkNumber forknum;127 BlockNumber blkno;128 129 /* Prefetching workspace. */130 Buffer prefetch_buffer;131 132 /* copy of the fork_flags field from the XLogRecordBlockHeader */133 uint8 flags;134 135 /* Information on full-page image, if any */136 bool has_image; /* has image, even for consistency checking */137 bool apply_image; /* has image that should be restored */138 char *bkp_image;139 uint16 hole_offset;140 uint16 hole_length;141 uint16 bimg_len;142 uint8 bimg_info;143 144 /* Buffer holding the rmgr-specific data associated with this block */145 bool has_data;146 char *data;147 uint16 data_len;148 uint16 data_bufsz;149} DecodedBkpBlock;150 151/*152 * The decoded contents of a record. This occupies a contiguous region of153 * memory, with main_data and blocks[n].data pointing to memory after the154 * members declared here.155 */156typedef struct DecodedXLogRecord157{158 /* Private member used for resource management. */159 size_t size; /* total size of decoded record */160 bool oversized; /* outside the regular decode buffer? */161 struct DecodedXLogRecord *next; /* decoded record queue link */162 163 /* Public members. */164 XLogRecPtr lsn; /* location */165 XLogRecPtr next_lsn; /* location of next record */166 XLogRecord header; /* header */167 RepOriginId record_origin;168 TransactionId toplevel_xid; /* XID of top-level transaction */169 char *main_data; /* record's main data portion */170 uint32 main_data_len; /* main data portion's length */171 int max_block_id; /* highest block_id in use (-1 if none) */172 DecodedBkpBlock blocks[FLEXIBLE_ARRAY_MEMBER];173} DecodedXLogRecord;174 175struct XLogReaderState176{177 /*178 * Operational callbacks179 */180 XLogReaderRoutine routine;181 182 /* ----------------------------------------183 * Public parameters184 * ----------------------------------------185 */186 187 /*188 * System identifier of the xlog files we're about to read. Set to zero189 * (the default value) if unknown or unimportant.190 */191 uint64 system_identifier;192 193 /*194 * Opaque data for callbacks to use. Not used by XLogReader.195 */196 void *private_data;197 198 /*199 * Start and end point of last record read. EndRecPtr is also used as the200 * position to read next. Calling XLogBeginRead() sets EndRecPtr to the201 * starting position and ReadRecPtr to invalid.202 *203 * Start and end point of last record returned by XLogReadRecord(). These204 * are also available as record->lsn and record->next_lsn.205 */206 XLogRecPtr ReadRecPtr; /* start of last record read */207 XLogRecPtr EndRecPtr; /* end+1 of last record read */208 209 /*210 * Set at the end of recovery: the start point of a partial record at the211 * end of WAL (InvalidXLogRecPtr if there wasn't one), and the start212 * location of its first contrecord that went missing.213 */214 XLogRecPtr abortedRecPtr;215 XLogRecPtr missingContrecPtr;216 /* Set when XLP_FIRST_IS_OVERWRITE_CONTRECORD is found */217 XLogRecPtr overwrittenRecPtr;218 219 220 /* ----------------------------------------221 * Decoded representation of current record222 *223 * Use XLogRecGet* functions to investigate the record; these fields224 * should not be accessed directly.225 * ----------------------------------------226 * Start and end point of the last record read and decoded by227 * XLogReadRecordInternal(). NextRecPtr is also used as the position to228 * decode next. Calling XLogBeginRead() sets NextRecPtr and EndRecPtr to229 * the requested starting position.230 */231 XLogRecPtr DecodeRecPtr; /* start of last record decoded */232 XLogRecPtr NextRecPtr; /* end+1 of last record decoded */233 XLogRecPtr PrevRecPtr; /* start of previous record decoded */234 235 /* Last record returned by XLogReadRecord(). */236 DecodedXLogRecord *record;237 238 /* ----------------------------------------239 * private/internal state240 * ----------------------------------------241 */242 243 /*244 * Buffer for decoded records. This is a circular buffer, though245 * individual records can't be split in the middle, so some space is often246 * wasted at the end. Oversized records that don't fit in this space are247 * allocated separately.248 */249 char *decode_buffer;250 size_t decode_buffer_size;251 bool free_decode_buffer; /* need to free? */252 char *decode_buffer_head; /* data is read from the head */253 char *decode_buffer_tail; /* new data is written at the tail */254 255 /*256 * Queue of records that have been decoded. This is a linked list that257 * usually consists of consecutive records in decode_buffer, but may also258 * contain oversized records allocated with palloc().259 */260 DecodedXLogRecord *decode_queue_head; /* oldest decoded record */261 DecodedXLogRecord *decode_queue_tail; /* newest decoded record */262 263 /*264 * Buffer for currently read page (XLOG_BLCKSZ bytes, valid up to at least265 * readLen bytes)266 */267 char *readBuf;268 uint32 readLen;269 270 /* last read XLOG position for data currently in readBuf */271 WALSegmentContext segcxt;272 WALOpenSegment seg;273 uint32 segoff;274 275 /*276 * beginning of prior page read, and its TLI. Doesn't necessarily277 * correspond to what's in readBuf; used for timeline sanity checks.278 */279 XLogRecPtr latestPagePtr;280 TimeLineID latestPageTLI;281 282 /* beginning of the WAL record being read. */283 XLogRecPtr currRecPtr;284 /* timeline to read it from, 0 if a lookup is required */285 TimeLineID currTLI;286 287 /*288 * Safe point to read to in currTLI if current TLI is historical289 * (tliSwitchPoint) or InvalidXLogRecPtr if on current timeline.290 *291 * Actually set to the start of the segment containing the timeline switch292 * that ends currTLI's validity, not the LSN of the switch its self, since293 * we can't assume the old segment will be present.294 */295 XLogRecPtr currTLIValidUntil;296 297 /*298 * If currTLI is not the most recent known timeline, the next timeline to299 * read from when currTLIValidUntil is reached.300 */301 TimeLineID nextTLI;302 303 /*304 * Buffer for current ReadRecord result (expandable), used when a record305 * crosses a page boundary.306 */307 char *readRecordBuf;308 uint32 readRecordBufSize;309 310 /* Buffer to hold error message */311 char *errormsg_buf;312 bool errormsg_deferred;313 314 /*315 * Flag to indicate to XLogPageReadCB that it should not block waiting for316 * data.317 */318 bool nonblocking;319};320 321/*322 * Check if XLogNextRecord() has any more queued records or an error to return.323 */324static inline bool325XLogReaderHasQueuedRecordOrError(XLogReaderState *state)326{327 return (state->decode_queue_head != NULL) || state->errormsg_deferred;328}329 330/* Get a new XLogReader */331extern XLogReaderState *XLogReaderAllocate(int wal_segment_size,332 const char *waldir,333 XLogReaderRoutine *routine,334 void *private_data);335 336/* Free an XLogReader */337extern void XLogReaderFree(XLogReaderState *state);338 339/* Optionally provide a circular decoding buffer to allow readahead. */340extern void XLogReaderSetDecodeBuffer(XLogReaderState *state,341 void *buffer,342 size_t size);343 344/* Position the XLogReader to given record */345extern void XLogBeginRead(XLogReaderState *state, XLogRecPtr RecPtr);346extern XLogRecPtr XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr);347 348/* Return values from XLogPageReadCB. */349typedef enum XLogPageReadResult350{351 XLREAD_SUCCESS = 0, /* record is successfully read */352 XLREAD_FAIL = -1, /* failed during reading a record */353 XLREAD_WOULDBLOCK = -2 /* nonblocking mode only, no data */354} XLogPageReadResult;355 356/* Read the next XLog record. Returns NULL on end-of-WAL or failure */357extern struct XLogRecord *XLogReadRecord(XLogReaderState *state,358 char **errormsg);359 360/* Consume the next record or error. */361extern DecodedXLogRecord *XLogNextRecord(XLogReaderState *state,362 char **errormsg);363 364/* Release the previously returned record, if necessary. */365extern XLogRecPtr XLogReleasePreviousRecord(XLogReaderState *state);366 367/* Try to read ahead, if there is data and space. */368extern DecodedXLogRecord *XLogReadAhead(XLogReaderState *state,369 bool nonblocking);370 371/* Validate a page */372extern bool XLogReaderValidatePageHeader(XLogReaderState *state,373 XLogRecPtr recptr, char *phdr);374 375/* Forget error produced by XLogReaderValidatePageHeader(). */376extern void XLogReaderResetError(XLogReaderState *state);377 378/*379 * Error information from WALRead that both backend and frontend caller can380 * process. Currently only errors from pg_pread can be reported.381 */382typedef struct WALReadError383{384 int wre_errno; /* errno set by the last pg_pread() */385 int wre_off; /* Offset we tried to read from. */386 int wre_req; /* Bytes requested to be read. */387 int wre_read; /* Bytes read by the last read(). */388 WALOpenSegment wre_seg; /* Segment we tried to read from. */389} WALReadError;390 391extern bool WALRead(XLogReaderState *state,392 char *buf, XLogRecPtr startptr, Size count,393 TimeLineID tli, WALReadError *errinfo);394 395/* Functions for decoding an XLogRecord */396 397extern size_t DecodeXLogRecordRequiredSpace(size_t xl_tot_len);398extern bool DecodeXLogRecord(XLogReaderState *state,399 DecodedXLogRecord *decoded,400 XLogRecord *record,401 XLogRecPtr lsn,402 char **errormsg);403 404/*405 * Macros that provide access to parts of the record most recently returned by406 * XLogReadRecord() or XLogNextRecord().407 */408#define XLogRecGetTotalLen(decoder) ((decoder)->record->header.xl_tot_len)409#define XLogRecGetPrev(decoder) ((decoder)->record->header.xl_prev)410#define XLogRecGetInfo(decoder) ((decoder)->record->header.xl_info)411#define XLogRecGetRmid(decoder) ((decoder)->record->header.xl_rmid)412#define XLogRecGetXid(decoder) ((decoder)->record->header.xl_xid)413#define XLogRecGetOrigin(decoder) ((decoder)->record->record_origin)414#define XLogRecGetTopXid(decoder) ((decoder)->record->toplevel_xid)415#define XLogRecGetData(decoder) ((decoder)->record->main_data)416#define XLogRecGetDataLen(decoder) ((decoder)->record->main_data_len)417#define XLogRecHasAnyBlockRefs(decoder) ((decoder)->record->max_block_id >= 0)418#define XLogRecMaxBlockId(decoder) ((decoder)->record->max_block_id)419#define XLogRecGetBlock(decoder, i) (&(decoder)->record->blocks[(i)])420#define XLogRecHasBlockRef(decoder, block_id) \421 (((decoder)->record->max_block_id >= (block_id)) && \422 ((decoder)->record->blocks[block_id].in_use))423#define XLogRecHasBlockImage(decoder, block_id) \424 ((decoder)->record->blocks[block_id].has_image)425#define XLogRecBlockImageApply(decoder, block_id) \426 ((decoder)->record->blocks[block_id].apply_image)427#define XLogRecHasBlockData(decoder, block_id) \428 ((decoder)->record->blocks[block_id].has_data)429 430#ifndef FRONTEND431extern FullTransactionId XLogRecGetFullXid(XLogReaderState *record);432#endif433 434extern bool RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page);435extern char *XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len);436extern void XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id,437 RelFileLocator *rlocator, ForkNumber *forknum,438 BlockNumber *blknum);439extern bool XLogRecGetBlockTagExtended(XLogReaderState *record, uint8 block_id,440 RelFileLocator *rlocator, ForkNumber *forknum,441 BlockNumber *blknum,442 Buffer *prefetch_buffer);443 444#endif /* XLOGREADER_H */445 