#ifndef XLOGREADER_H
#define XLOGREADER_H
#ifndef FRONTEND
#include "access/transam.h"
#endif
#include "access/xlogrecord.h"
#include "storage/buf.h"
typedef struct WALOpenSegment
{
int ws_file;
XLogSegNo ws_segno;
TimeLineID ws_tli;
} WALOpenSegment;
typedef struct WALSegmentContext
{
char ws_dir[MAXPGPATH];
int ws_segsize;
} WALSegmentContext;
typedef struct XLogReaderState XLogReaderState;
typedef int (*XLogPageReadCB) (XLogReaderState *xlogreader,
XLogRecPtr targetPagePtr,
int reqLen,
XLogRecPtr targetRecPtr,
char *readBuf);
typedef void (*WALSegmentOpenCB) (XLogReaderState *xlogreader,
XLogSegNo nextSegNo,
TimeLineID *tli_p);
typedef void (*WALSegmentCloseCB) (XLogReaderState *xlogreader);
typedef struct XLogReaderRoutine
{
XLogPageReadCB page_read;
WALSegmentOpenCB segment_open;
WALSegmentCloseCB segment_close;
} XLogReaderRoutine;
#define XL_ROUTINE(...) &(XLogReaderRoutine){__VA_ARGS__}
typedef struct
{
bool in_use;
RelFileLocator rlocator;
ForkNumber forknum;
BlockNumber blkno;
Buffer prefetch_buffer;
uint8 flags;
bool has_image;
bool apply_image;
char *bkp_image;
uint16 hole_offset;
uint16 hole_length;
uint16 bimg_len;
uint8 bimg_info;
bool has_data;
char *data;
uint16 data_len;
uint16 data_bufsz;
} DecodedBkpBlock;
typedef struct DecodedXLogRecord
{
size_t size;
bool oversized;
struct DecodedXLogRecord *next;
XLogRecPtr lsn;
XLogRecPtr next_lsn;
XLogRecord header;
RepOriginId record_origin;
TransactionId toplevel_xid;
char *main_data;
uint32 main_data_len;
int max_block_id;
DecodedBkpBlock blocks[FLEXIBLE_ARRAY_MEMBER];
} DecodedXLogRecord;
struct XLogReaderState
{
XLogReaderRoutine routine;
uint64 system_identifier;
void *private_data;
XLogRecPtr ReadRecPtr;
XLogRecPtr EndRecPtr;
XLogRecPtr abortedRecPtr;
XLogRecPtr missingContrecPtr;
XLogRecPtr overwrittenRecPtr;
XLogRecPtr DecodeRecPtr;
XLogRecPtr NextRecPtr;
XLogRecPtr PrevRecPtr;
DecodedXLogRecord *record;
char *decode_buffer;
size_t decode_buffer_size;
bool free_decode_buffer;
char *decode_buffer_head;
char *decode_buffer_tail;
DecodedXLogRecord *decode_queue_head;
DecodedXLogRecord *decode_queue_tail;
char *readBuf;
uint32 readLen;
WALSegmentContext segcxt;
WALOpenSegment seg;
uint32 segoff;
XLogRecPtr latestPagePtr;
TimeLineID latestPageTLI;
XLogRecPtr currRecPtr;
TimeLineID currTLI;
XLogRecPtr currTLIValidUntil;
TimeLineID nextTLI;
char *readRecordBuf;
uint32 readRecordBufSize;
char *errormsg_buf;
bool errormsg_deferred;
bool nonblocking;
};
static inline bool
XLogReaderHasQueuedRecordOrError(XLogReaderState *state)
{
return (state->decode_queue_head != NULL) || state->errormsg_deferred;
}
extern XLogReaderState *XLogReaderAllocate(int wal_segment_size,
const char *waldir,
XLogReaderRoutine *routine,
void *private_data);
extern void XLogReaderFree(XLogReaderState *state);
extern void XLogReaderSetDecodeBuffer(XLogReaderState *state,
void *buffer,
size_t size);
extern void XLogBeginRead(XLogReaderState *state, XLogRecPtr RecPtr);
extern XLogRecPtr XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr);
typedef enum XLogPageReadResult
{
XLREAD_SUCCESS = 0,
XLREAD_FAIL = -1,
XLREAD_WOULDBLOCK = -2,
} XLogPageReadResult;
extern struct XLogRecord *XLogReadRecord(XLogReaderState *state,
char **errormsg);
extern DecodedXLogRecord *XLogNextRecord(XLogReaderState *state,
char **errormsg);
extern XLogRecPtr XLogReleasePreviousRecord(XLogReaderState *state);
extern DecodedXLogRecord *XLogReadAhead(XLogReaderState *state,
bool nonblocking);
extern bool XLogReaderValidatePageHeader(XLogReaderState *state,
XLogRecPtr recptr, char *phdr);
extern void XLogReaderResetError(XLogReaderState *state);
typedef struct WALReadError
{
int wre_errno;
int wre_off;
int wre_req;
int wre_read;
WALOpenSegment wre_seg;
} WALReadError;
extern bool WALRead(XLogReaderState *state,
char *buf, XLogRecPtr startptr, Size count,
TimeLineID tli, WALReadError *errinfo);
extern size_t DecodeXLogRecordRequiredSpace(size_t xl_tot_len);
extern bool DecodeXLogRecord(XLogReaderState *state,
DecodedXLogRecord *decoded,
XLogRecord *record,
XLogRecPtr lsn,
char **errormsg);
#define XLogRecGetTotalLen(decoder) ((decoder)->record->header.xl_tot_len)
#define XLogRecGetPrev(decoder) ((decoder)->record->header.xl_prev)
#define XLogRecGetInfo(decoder) ((decoder)->record->header.xl_info)
#define XLogRecGetRmid(decoder) ((decoder)->record->header.xl_rmid)
#define XLogRecGetXid(decoder) ((decoder)->record->header.xl_xid)
#define XLogRecGetOrigin(decoder) ((decoder)->record->record_origin)
#define XLogRecGetTopXid(decoder) ((decoder)->record->toplevel_xid)
#define XLogRecGetData(decoder) ((decoder)->record->main_data)
#define XLogRecGetDataLen(decoder) ((decoder)->record->main_data_len)
#define XLogRecHasAnyBlockRefs(decoder) ((decoder)->record->max_block_id >= 0)
#define XLogRecMaxBlockId(decoder) ((decoder)->record->max_block_id)
#define XLogRecGetBlock(decoder, i) (&(decoder)->record->blocks[(i)])
#define XLogRecHasBlockRef(decoder, block_id) \
(((decoder)->record->max_block_id >= (block_id)) && \
((decoder)->record->blocks[block_id].in_use))
#define XLogRecHasBlockImage(decoder, block_id) \
((decoder)->record->blocks[block_id].has_image)
#define XLogRecBlockImageApply(decoder, block_id) \
((decoder)->record->blocks[block_id].apply_image)
#define XLogRecHasBlockData(decoder, block_id) \
((decoder)->record->blocks[block_id].has_data)
#ifndef FRONTEND
extern FullTransactionId XLogRecGetFullXid(XLogReaderState *record);
#endif
extern bool RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page);
extern char *XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len);
extern void XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id,
RelFileLocator *rlocator, ForkNumber *forknum,
BlockNumber *blknum);
extern bool XLogRecGetBlockTagExtended(XLogReaderState *record, uint8 block_id,
RelFileLocator *rlocator, ForkNumber *forknum,
BlockNumber *blknum,
Buffer *prefetch_buffer);
#endif