60#define MAX_ERRORMSG_LEN 1000
66#define DEFAULT_DECODE_BUFFER_SIZE (64 * 1024)
83 state->errormsg_deferred =
true;
96 state->decode_buffer = buffer;
97 state->decode_buffer_size = size;
98 state->decode_buffer_tail = buffer;
99 state->decode_buffer_head = buffer;
120 state->routine = *routine;
142 state->private_data = private_data;
146 if (!
state->errormsg_buf)
152 state->errormsg_buf[0] =
'\0';
165 if (
state->seg.ws_file != -1)
168 if (
state->decode_buffer &&
state->free_decode_buffer)
172 if (
state->readRecordBuf)
199 if (
state->readRecordBuf)
210 int segsize,
const char *
waldir)
263 record =
state->record;
270 if (
state->decode_queue_tail == record)
282 Assert(
state->decode_buffer_head == (
char *) record);
289 record = record->next;
290 while (
unlikely(record && record->oversized))
291 record = record->next;
296 state->decode_buffer_head = (
char *) record;
306 state->decode_buffer_head =
state->decode_buffer;
307 state->decode_buffer_tail =
state->decode_buffer;
335 if (
state->errormsg_deferred)
337 if (
state->errormsg_buf[0] !=
'\0')
338 *errormsg =
state->errormsg_buf;
339 state->errormsg_deferred =
false;
371 return state->record;
448 if (
state->decode_buffer_size == 0)
451 state->decode_buffer_head =
state->decode_buffer;
452 state->decode_buffer_tail =
state->decode_buffer;
453 state->free_decode_buffer =
true;
457 if (
state->decode_buffer_tail >=
state->decode_buffer_head)
461 state->decode_buffer_size -
462 (
state->decode_buffer_tail -
state->decode_buffer))
479 state->decode_buffer_head -
state->decode_buffer)
500 state->decode_buffer_head -
state->decode_buffer_tail)
554 state->errormsg_buf[0] =
'\0';
587 state->nonblocking = nonblocking;
671 "invalid record length at %X/%08X: expected at least %u, got %u",
719 buffer =
state->readRecordBuf +
len;
761 "there is no contrecord flag at %X/%08X",
774 "invalid contrecord length %u (expected %lld) at %X/%08X",
776 ((
long long) total_len) -
gotlen,
828 if (total_len >
state->readRecordBufSize)
843 }
while (
gotlen < total_len);
881 state->NextRecPtr +=
state->segcxt.ws_segsize - 1;
920 if (
state->decode_queue_tail)
923 if (!
state->decode_queue_head)
948 state->errormsg_deferred =
true;
982 if (
state->errormsg_deferred)
989 return state->decode_queue_tail;
1027 return state->readLen;
1127 state->seg.ws_segno = 0;
1146 "invalid record length at %X/%08X: expected at least %u, got %u",
1154 "invalid resource manager ID %u at %X/%08X",
1167 "record with incorrect prev-link %X/%08X at %X/%08X",
1180 if (record->
xl_prev != PrevRecPtr)
1183 "record with incorrect prev-link %X/%08X at %X/%08X",
1221 "incorrect resource manager data checksum in record at %X/%08X",
1255 "invalid magic number %04X in WAL segment %s, LSN %X/%08X, offset %u",
1270 "invalid info bits %04X in WAL segment %s, LSN %X/%08X, offset %u",
1282 if (
state->system_identifier &&
1286 "WAL file is from different database system: WAL file database system identifier is %" PRIu64 ", pg_control database system identifier is %" PRIu64,
1288 state->system_identifier);
1291 else if (
longhdr->xlp_seg_size !=
state->segcxt.ws_segsize)
1294 "WAL file is from different database system: incorrect segment size in page header");
1300 "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header");
1304 else if (offset == 0)
1312 "invalid info bits %04X in WAL segment %s, LSN %X/%08X, offset %u",
1332 "unexpected pageaddr %X/%08X in WAL segment %s, LSN %X/%08X, offset %u",
1358 "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%08X, offset %u",
1360 state->latestPageTLI,
1379 state->errormsg_buf[0] =
'\0';
1380 state->errormsg_deferred =
false;
1405 state->nonblocking =
false;
1491 found =
state->ReadRecPtr;
1543 if (
state->seg.ws_file < 0 ||
1545 tli !=
state->seg.ws_tli)
1549 if (
state->seg.ws_file >= 0)
1559 state->seg.ws_tli = tli;
1621 while ((r =
state->decode_queue_head) !=
NULL)
1632 state->decode_buffer_tail =
state->decode_buffer;
1633 state->decode_buffer_head =
state->decode_buffer;
1636 state->errormsg_buf[0] =
'\0';
1637 state->errormsg_deferred =
false;
1692#define COPY_HEADER_FIELD(_dst, _size) \
1694 if (remaining < _size) \
1695 goto shortdata_err; \
1696 memcpy(_dst, ptr, _size); \
1698 remaining -= _size; \
1716 ptr = (
char *) record;
1729 uint8 main_data_len;
1733 decoded->main_data_len = main_data_len;
1744 decoded->main_data_len = main_data_len;
1770 "out-of-order block_id %u at %X/%08X",
1779 blk->apply_image =
false;
1783 blk->flags = fork_flags;
1791 if (
blk->has_data &&
blk->data_len == 0)
1794 "BKPBLOCK_HAS_DATA set, but no data included at %X/%08X",
1798 if (!
blk->has_data &&
blk->data_len != 0)
1801 "BKPBLOCK_HAS_DATA not set, but data length is %d at %X/%08X",
1821 blk->hole_length = 0;
1832 (
blk->hole_offset == 0 ||
1833 blk->hole_length == 0 ||
1837 "BKPIMAGE_HAS_HOLE set, but hole offset %d length %d block image length %d at %X/%08X",
1850 (
blk->hole_offset != 0 ||
blk->hole_length != 0))
1853 "BKPIMAGE_HAS_HOLE not set, but hole offset %d length %d at %X/%08X",
1867 "BKPIMAGE_COMPRESSED set, but block image length %d at %X/%08X",
1882 "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image length is %d at %X/%08X",
1891 rlocator = &
blk->rlocator;
1895 if (rlocator ==
NULL)
1898 "BKPBLOCK_SAME_REL set but no previous rel at %X/%08X",
1903 blk->rlocator = *rlocator;
1910 "invalid block_id %u at %X/%08X",
1943 blk->bkp_image = out;
1945 ptr +=
blk->bimg_len;
1946 out +=
blk->bimg_len;
1953 ptr +=
blk->data_len;
1954 out +=
blk->data_len;
1959 if (
decoded->main_data_len > 0)
1964 ptr +=
decoded->main_data_len;
1965 out +=
decoded->main_data_len;
1977 "record with invalid length at %X/%08X",
1980 *errormsg =
state->errormsg_buf;
2000 elog(
ERROR,
"could not locate backup block with ID %d in WAL record",
2003 pg_fatal(
"could not locate backup block with ID %d in WAL record",
2030 *rlocator =
bkpb->rlocator;
2032 *forknum =
bkpb->forknum;
2035 if (prefetch_buffer)
2036 *prefetch_buffer =
bkpb->prefetch_buffer;
2056 if (!
bkpb->has_data)
2087 "could not restore image at %X/%08X with invalid block %d specified",
2121 report_invalid_record(record,
"could not restore image at %X/%08X compressed with %s not supported by build, block %d",
2133 ptr,
bkpb->bimg_len);
2138 report_invalid_record(record,
"could not restore image at %X/%08X compressed with %s not supported by build, block %d",
2147 report_invalid_record(record,
"could not restore image at %X/%08X compressed with unknown method, block %d",
2165 if (
bkpb->hole_length == 0)
2175 ptr +
bkpb->hole_offset,
#define Assert(condition)
#define pg_attribute_printf(f, a)
#define MemSet(start, val, len)
void err(int eval, const char *fmt,...)
#define MCXT_ALLOC_NO_OOM
void pfree(void *pointer)
void * palloc_extended(Size size, int flags)
#define AmStartupProcess()
#define InvalidReplOriginId
#define COMP_CRC32C(crc, data, len)
#define EQ_CRC32C(c1, c2)
int32 pglz_decompress(const char *source, int32 slen, char *dest, int32 rawsize, bool check_complete)
static char buf[DEFAULT_XLOG_SEG_SIZE]
instr_time pgstat_prepare_io_time(bool track_io_guc)
void pgstat_count_io_op_time(IOObject io_object, IOContext io_context, IOOp io_op, instr_time start_time, uint32 cnt, uint64 bytes)
#define RmgrIdIsValid(rmid)
struct DecodedXLogRecord * next
DecodedBkpBlock blocks[FLEXIBLE_ARRAY_MEMBER]
FullTransactionId nextXid
DecodedXLogRecord * record
#define InvalidTransactionId
static FullTransactionId FullTransactionIdFromAllowableAt(FullTransactionId nextFullXid, TransactionId xid)
TransamVariablesData * TransamVariables
static void pgstat_report_wait_start(uint32 wait_event_info)
static void pgstat_report_wait_end(void)
#define XLP_FIRST_IS_CONTRECORD
XLogLongPageHeaderData * XLogLongPageHeader
#define XLP_FIRST_IS_OVERWRITE_CONTRECORD
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
XLogPageHeaderData * XLogPageHeader
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)
#define XRecOffIsValid(xlrp)
#define SizeOfXLogShortPHD
static void XLogFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)
#define XLogPageHeaderSize(hdr)
#define XLByteInSeg(xlrp, logSegNo, wal_segsz_bytes)
#define XLogRecPtrIsValid(r)
#define LSN_FORMAT_ARGS(lsn)
#define InvalidXLogRecPtr
bool XLogRecGetBlockTagExtended(XLogReaderState *record, uint8 block_id, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum, Buffer *prefetch_buffer)
static XLogPageReadResult XLogDecodeNextRecord(XLogReaderState *state, bool nonblocking)
XLogReaderState * XLogReaderAllocate(int wal_segment_size, const char *waldir, XLogReaderRoutine *routine, void *private_data)
void XLogReaderSetDecodeBuffer(XLogReaderState *state, void *buffer, size_t size)
DecodedXLogRecord * XLogReadAhead(XLogReaderState *state, bool nonblocking)
static void WALOpenSegmentInit(WALOpenSegment *seg, WALSegmentContext *segcxt, int segsize, const char *waldir)
char * XLogRecGetBlockData(XLogReaderState *record, uint8 block_id, Size *len)
static int ReadPageInternal(XLogReaderState *state, XLogRecPtr pageptr, int reqLen)
DecodedXLogRecord * XLogNextRecord(XLogReaderState *state, char **errormsg)
static void report_invalid_record(XLogReaderState *state, const char *fmt,...) pg_attribute_printf(2
static void static void allocate_recordbuf(XLogReaderState *state, uint32 reclength)
bool WALRead(XLogReaderState *state, char *buf, XLogRecPtr startptr, Size count, TimeLineID tli, WALReadError *errinfo)
XLogRecord * XLogReadRecord(XLogReaderState *state, char **errormsg)
void XLogReaderResetError(XLogReaderState *state)
static void XLogReaderInvalReadState(XLogReaderState *state)
#define COPY_HEADER_FIELD(_dst, _size)
bool XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr, char *phdr)
FullTransactionId XLogRecGetFullXid(XLogReaderState *record)
void XLogReaderFree(XLogReaderState *state)
void XLogRecGetBlockTag(XLogReaderState *record, uint8 block_id, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum)
static void ResetDecoder(XLogReaderState *state)
bool DecodeXLogRecord(XLogReaderState *state, DecodedXLogRecord *decoded, XLogRecord *record, XLogRecPtr lsn, char **errormsg)
static bool ValidXLogRecord(XLogReaderState *state, XLogRecord *record, XLogRecPtr recptr)
#define DEFAULT_DECODE_BUFFER_SIZE
size_t DecodeXLogRecordRequiredSpace(size_t xl_tot_len)
static DecodedXLogRecord * XLogReadRecordAlloc(XLogReaderState *state, size_t xl_tot_len, bool allow_oversized)
XLogRecPtr XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr)
void XLogBeginRead(XLogReaderState *state, XLogRecPtr RecPtr)
bool RestoreBlockImage(XLogReaderState *record, uint8 block_id, char *page)
XLogRecPtr XLogReleasePreviousRecord(XLogReaderState *state)
static bool ValidXLogRecordHeader(XLogReaderState *state, XLogRecPtr RecPtr, XLogRecPtr PrevRecPtr, XLogRecord *record, bool randAccess)
static bool XLogReaderHasQueuedRecordOrError(XLogReaderState *state)
#define XLogRecGetXid(decoder)
#define XLogRecHasBlockRef(decoder, block_id)
#define BKPIMAGE_COMPRESS_ZSTD
#define BKPBLOCK_FORK_MASK
#define BKPBLOCK_HAS_DATA
#define BKPIMAGE_HAS_HOLE
#define XLR_BLOCK_ID_DATA_LONG
#define BKPIMAGE_COMPRESS_LZ4
#define BKPIMAGE_COMPRESSED(info)
#define XLR_BLOCK_ID_TOPLEVEL_XID
#define XLR_BLOCK_ID_DATA_SHORT
#define BKPBLOCK_SAME_REL
#define BKPIMAGE_COMPRESS_PGLZ
#define XLR_BLOCK_ID_ORIGIN
#define BKPBLOCK_HAS_IMAGE