PostgreSQL Source Code: src/backend/access/transam/xlogreader.c File Reference (original) (raw)

Go to the source code of this file.

Macros
#define MAX_ERRORMSG_LEN 1000
#define DEFAULT_DECODE_BUFFER_SIZE (64 * 1024)
#define COPY_HEADER_FIELD(_dst, _size)
Functions
static void report_invalid_record (XLogReaderState *state, const char *fmt,...) pg_attribute_printf(2
static void static void allocate_recordbuf (XLogReaderState *state, uint32 reclength)
static int ReadPageInternal (XLogReaderState *state, XLogRecPtr pageptr, int reqLen)
static void XLogReaderInvalReadState (XLogReaderState *state)
static XLogPageReadResult XLogDecodeNextRecord (XLogReaderState *state, bool nonblocking)
static bool ValidXLogRecordHeader (XLogReaderState *state, XLogRecPtr RecPtr, XLogRecPtr PrevRecPtr, XLogRecord *record, bool randAccess)
static bool ValidXLogRecord (XLogReaderState *state, XLogRecord *record, XLogRecPtr recptr)
static void ResetDecoder (XLogReaderState *state)
static void WALOpenSegmentInit (WALOpenSegment *seg, WALSegmentContext *segcxt, int segsize, const char *waldir)
void XLogReaderSetDecodeBuffer (XLogReaderState *state, void *buffer, size_t size)
XLogReaderState * XLogReaderAllocate (int wal_segment_size, const char *waldir, XLogReaderRoutine *routine, void *private_data)
void XLogReaderFree (XLogReaderState *state)
void XLogBeginRead (XLogReaderState *state, XLogRecPtr RecPtr)
XLogRecPtr XLogReleasePreviousRecord (XLogReaderState *state)
DecodedXLogRecord * XLogNextRecord (XLogReaderState *state, char **errormsg)
XLogRecord * XLogReadRecord (XLogReaderState *state, char **errormsg)
static DecodedXLogRecord * XLogReadRecordAlloc (XLogReaderState *state, size_t xl_tot_len, bool allow_oversized)
DecodedXLogRecord * XLogReadAhead (XLogReaderState *state, bool nonblocking)
bool XLogReaderValidatePageHeader (XLogReaderState *state, XLogRecPtr recptr, char *phdr)
void XLogReaderResetError (XLogReaderState *state)
XLogRecPtr XLogFindNextRecord (XLogReaderState *state, XLogRecPtr RecPtr)
bool WALRead (XLogReaderState *state, char *buf, XLogRecPtr startptr, Size count, TimeLineID tli, WALReadError *errinfo)
size_t DecodeXLogRecordRequiredSpace (size_t xl_tot_len)
bool DecodeXLogRecord (XLogReaderState *state, DecodedXLogRecord *decoded, XLogRecord *record, XLogRecPtr lsn, char **errormsg)
void XLogRecGetBlockTag (XLogReaderState *record, uint8 block_id, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum)
bool XLogRecGetBlockTagExtended (XLogReaderState *record, uint8 block_id, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum, Buffer *prefetch_buffer)
char * XLogRecGetBlockData (XLogReaderState *record, uint8 block_id, Size *len)
bool RestoreBlockImage (XLogReaderState *record, uint8 block_id, char *page)
FullTransactionId XLogRecGetFullXid (XLogReaderState *record)

COPY_HEADER_FIELD

| #define COPY_HEADER_FIELD | ( | | _dst, | | --------------------------- | - | | ------ | | | _size | | | | | ) | | | |

Value:

do { \

goto shortdata_err; \

memcpy(_dst, ptr, _size); \

ptr += _size; \

remaining -= _size; \

} while(0)

DEFAULT_DECODE_BUFFER_SIZE

#define DEFAULT_DECODE_BUFFER_SIZE (64 * 1024)

MAX_ERRORMSG_LEN

#define MAX_ERRORMSG_LEN 1000

allocate_recordbuf()

DecodeXLogRecord()

Definition at line 1682 of file xlogreader.c.

1687{

1688

1689

1690

1691#define COPY_HEADER_FIELD(_dst, _size) \

1692 do { \

1693 if (remaining < _size) \

1694 goto shortdata_err; \

1695 memcpy(_dst, ptr, _size); \

1696 ptr += _size; \

1697 remaining -= _size; \

1698 } while(0)

1699

1700 char *ptr;

1701 char *out;

1706

1707 decoded->header = *record;

1708 decoded->lsn = lsn;

1709 decoded->next = NULL;

1715 ptr = (char *) record;

1718

1719

1720 datatotal = 0;

1722 {

1724

1726 {

1727

1728 uint8 main_data_len;

1729

1731

1733 datatotal += main_data_len;

1734 break;

1735

1736 }

1738 {

1739

1740 uint32 main_data_len;

1741

1744 datatotal += main_data_len;

1745 break;

1746

1747 }

1749 {

1751 }

1753 {

1755 }

1757 {

1758

1760 uint8 fork_flags;

1761

1762

1763 for (int i = decoded->max_block_id + 1; i < block_id; ++i)

1765

1766 if (block_id <= decoded->max_block_id)

1767 {

1769 "out-of-order block_id %u at %X/%08X",

1770 block_id,

1772 goto err;

1773 }

1775

1776 blk = &decoded->blocks[block_id];

1779

1782 blk->flags = fork_flags;

1785

1787

1789

1791 {

1793 "BKPBLOCK_HAS_DATA set, but no data included at %X/%08X",

1795 goto err;

1796 }

1798 {

1800 "BKPBLOCK_HAS_DATA not set, but data length is %d at %X/%08X",

1803 goto err;

1804 }

1806

1808 {

1812

1814

1816 {

1819 else

1821 }

1822 else

1825

1826

1827

1828

1829

1834 {

1836 "BKPIMAGE_HAS_HOLE set, but hole offset %d length %d block image length %d at %X/%08X",

1841 goto err;

1842 }

1843

1844

1845

1846

1847

1850 {

1852 "BKPIMAGE_HAS_HOLE not set, but hole offset %d length %d at %X/%08X",

1856 goto err;

1857 }

1858

1859

1860

1861

1864 {

1866 "BKPIMAGE_COMPRESSED set, but block image length %d at %X/%08X",

1869 goto err;

1870 }

1871

1872

1873

1874

1875

1879 {

1881 "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_COMPRESSED set, but block image length is %d at %X/%08X",

1884 goto err;

1885 }

1886 }

1888 {

1891 }

1892 else

1893 {

1894 if (rlocator == NULL)

1895 {

1897 "BKPBLOCK_SAME_REL set but no previous rel at %X/%08X",

1899 goto err;

1900 }

1901

1903 }

1905 }

1906 else

1907 {

1909 "invalid block_id %u at %X/%08X",

1911 goto err;

1912 }

1913 }

1914

1916 goto shortdata_err;

1917

1918

1919

1920

1921

1922

1923

1924

1925 out = ((char *) decoded) +

1928

1929

1930 for (block_id = 0; block_id <= decoded->max_block_id; block_id++)

1931 {

1933

1935 continue;

1936

1938

1940 {

1941

1943 memcpy(out, ptr, blk->bimg_len);

1946 }

1948 {

1949 out = (char *) MAXALIGN(out);

1950 blk->data = out;

1954 }

1955 }

1956

1957

1959 {

1960 out = (char *) MAXALIGN(out);

1965 }

1966

1967

1968 decoded->size = MAXALIGN(out - (char *) decoded);

1970 decoded->size);

1971

1972 return true;

1973

1974shortdata_err:

1976 "record with invalid length at %X/%08X",

1979 *errormsg = state->errormsg_buf;

1980

1981 return false;

1982}

void err(int eval, const char *fmt,...)

Assert(PointerIsAligned(start, uint64))

#define InvalidRepOriginId

struct DecodedXLogRecord * next

TransactionId toplevel_xid

RepOriginId record_origin

DecodedBkpBlock blocks[FLEXIBLE_ARRAY_MEMBER]

#define InvalidTransactionId

#define LSN_FORMAT_ARGS(lsn)

static void report_invalid_record(XLogReaderState *state, const char *fmt,...) pg_attribute_printf(2

#define COPY_HEADER_FIELD(_dst, _size)

size_t DecodeXLogRecordRequiredSpace(size_t xl_tot_len)

#define BKPBLOCK_FORK_MASK

#define BKPBLOCK_HAS_DATA

#define BKPIMAGE_HAS_HOLE

#define XLR_BLOCK_ID_DATA_LONG

#define BKPIMAGE_COMPRESSED(info)

#define XLR_BLOCK_ID_TOPLEVEL_XID

#define XLR_BLOCK_ID_DATA_SHORT

#define BKPBLOCK_SAME_REL

#define XLR_BLOCK_ID_ORIGIN

#define BKPBLOCK_HAS_IMAGE

References DecodedBkpBlock::apply_image, Assert(), DecodedBkpBlock::bimg_info, DecodedBkpBlock::bimg_len, DecodedBkpBlock::bkp_image, BKPBLOCK_FORK_MASK, BKPBLOCK_HAS_DATA, BKPBLOCK_HAS_IMAGE, BKPBLOCK_SAME_REL, BKPIMAGE_APPLY, BKPIMAGE_COMPRESSED, BKPIMAGE_HAS_HOLE, DecodedBkpBlock::blkno, DecodedXLogRecord::blocks, COPY_HEADER_FIELD, DecodedBkpBlock::data, DecodedBkpBlock::data_len, DecodeXLogRecordRequiredSpace(), err(), DecodedBkpBlock::flags, DecodedBkpBlock::forknum, DecodedBkpBlock::has_data, DecodedBkpBlock::has_image, DecodedXLogRecord::header, DecodedBkpBlock::hole_length, DecodedBkpBlock::hole_offset, i, DecodedBkpBlock::in_use, InvalidBuffer, InvalidRepOriginId, InvalidTransactionId, DecodedXLogRecord::lsn, LSN_FORMAT_ARGS, DecodedXLogRecord::main_data, DecodedXLogRecord::main_data_len, DecodedXLogRecord::max_block_id, MAXALIGN, DecodedXLogRecord::next, DecodedBkpBlock::prefetch_buffer, DecodedXLogRecord::record_origin, remaining, report_invalid_record(), DecodedBkpBlock::rlocator, DecodedXLogRecord::size, SizeOfXLogRecord, DecodedXLogRecord::toplevel_xid, XLogRecord::xl_tot_len, XLR_BLOCK_ID_DATA_LONG, XLR_BLOCK_ID_DATA_SHORT, XLR_BLOCK_ID_ORIGIN, XLR_BLOCK_ID_TOPLEVEL_XID, and XLR_MAX_BLOCK_ID.

Referenced by XLogDecodeNextRecord(), and XLogInsertRecord().

DecodeXLogRecordRequiredSpace()

size_t DecodeXLogRecordRequiredSpace ( size_t xl_tot_len )

ReadPageInternal()

Definition at line 1011 of file xlogreader.c.

1012{

1014 uint32 targetPageOff;

1017

1018 Assert((pageptr % XLOG_BLCKSZ) == 0);

1019

1020 XLByteToSeg(pageptr, targetSegNo, state->segcxt.ws_segsize);

1022

1023

1024 if (targetSegNo == state->seg.ws_segno &&

1025 targetPageOff == state->segoff && reqLen <= state->readLen)

1026 return state->readLen;

1027

1028

1029

1030

1031

1032

1033 state->readLen = 0;

1034

1035

1036

1037

1038

1039

1040

1041

1042

1043

1044

1045

1046

1047 if (targetSegNo != state->seg.ws_segno && targetPageOff != 0)

1048 {

1049 XLogRecPtr targetSegmentPtr = pageptr - targetPageOff;

1050

1051 readLen = state->routine.page_read(state, targetSegmentPtr, XLOG_BLCKSZ,

1052 state->currRecPtr,

1053 state->readBuf);

1057 goto err;

1058

1059

1061

1063 state->readBuf))

1064 goto err;

1065 }

1066

1067

1068

1069

1070

1072 state->currRecPtr,

1073 state->readBuf);

1077 goto err;

1078

1080

1081

1083 goto err;

1084

1086

1088

1089

1091 {

1093 state->currRecPtr,

1094 state->readBuf);

1098 goto err;

1099 }

1100

1101

1102

1103

1105 goto err;

1106

1107

1108 state->seg.ws_segno = targetSegNo;

1109 state->segoff = targetPageOff;

1111

1113

1116

1118}

if(TABLE==NULL||TABLE_index==NULL)

#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)

XLogPageHeaderData * XLogPageHeader

#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)

#define SizeOfXLogShortPHD

#define XLogPageHeaderSize(hdr)

static void XLogReaderInvalReadState(XLogReaderState *state)

bool XLogReaderValidatePageHeader(XLogReaderState *state, XLogRecPtr recptr, char *phdr)

References Assert(), err(), if(), Max, readLen, SizeOfXLogShortPHD, XLByteToSeg, XLogPageHeaderSize, XLogReaderInvalReadState(), XLogReaderValidatePageHeader(), XLogSegmentOffset, XLREAD_FAIL, and XLREAD_WOULDBLOCK.

Referenced by XLogDecodeNextRecord(), and XLogFindNextRecord().

report_invalid_record()

static void report_invalid_record ( XLogReaderState * state, const char * fmt, ... ) static

ResetDecoder()

RestoreBlockImage()

Definition at line 2076 of file xlogreader.c.

2077{

2079 char *ptr;

2081

2084 {

2086 "could not restore image at %X/%08X with invalid block %d specified",

2088 block_id);

2089 return false;

2090 }

2092 {

2093 report_invalid_record(record, "could not restore image at %X/%08X with invalid state, block %d",

2095 block_id);

2096 return false;

2097 }

2098

2101

2103 {

2104

2105 bool decomp_success = true;

2106

2108 {

2111 decomp_success = false;

2112 }

2114 {

2115#ifdef USE_LZ4

2116 if (LZ4_decompress_safe(ptr, tmp.data,

2118 decomp_success = false;

2119#else

2120 report_invalid_record(record, "could not restore image at %X/%08X compressed with %s not supported by build, block %d",

2122 "LZ4",

2123 block_id);

2124 return false;

2125#endif

2126 }

2128 {

2129#ifdef USE_ZSTD

2130 size_t decomp_result = ZSTD_decompress(tmp.data,

2133

2134 if (ZSTD_isError(decomp_result))

2135 decomp_success = false;

2136#else

2137 report_invalid_record(record, "could not restore image at %X/%08X compressed with %s not supported by build, block %d",

2139 "zstd",

2140 block_id);

2141 return false;

2142#endif

2143 }

2144 else

2145 {

2146 report_invalid_record(record, "could not restore image at %X/%08X compressed with unknown method, block %d",

2148 block_id);

2149 return false;

2150 }

2151

2152 if (!decomp_success)

2153 {

2154 report_invalid_record(record, "could not decompress image at %X/%08X, block %d",

2156 block_id);

2157 return false;

2158 }

2159

2160 ptr = tmp.data;

2161 }

2162

2163

2165 {

2166 memcpy(page, ptr, BLCKSZ);

2167 }

2168 else

2169 {

2171

2176 }

2177

2178 return true;

2179}

#define MemSet(start, val, len)

int32 pglz_decompress(const char *source, int32 slen, char *dest, int32 rawsize, bool check_complete)

DecodedXLogRecord * record

#define BKPIMAGE_COMPRESS_ZSTD

#define BKPIMAGE_COMPRESS_LZ4

#define BKPIMAGE_COMPRESS_PGLZ

References DecodedBkpBlock::bimg_info, DecodedBkpBlock::bimg_len, DecodedBkpBlock::bkp_image, BKPIMAGE_COMPRESS_LZ4, BKPIMAGE_COMPRESS_PGLZ, BKPIMAGE_COMPRESS_ZSTD, BKPIMAGE_COMPRESSED, DecodedXLogRecord::blocks, PGAlignedBlock::data, DecodedBkpBlock::has_image, DecodedBkpBlock::hole_length, DecodedBkpBlock::hole_offset, DecodedBkpBlock::in_use, LSN_FORMAT_ARGS, DecodedXLogRecord::max_block_id, MemSet, pglz_decompress(), XLogReaderState::ReadRecPtr, XLogReaderState::record, and report_invalid_record().

Referenced by GetWALBlockInfo(), verifyBackupPageConsistency(), XLogReadBufferForRedoExtended(), and XLogRecordSaveFPWs().

ValidXLogRecord()

Definition at line 1204 of file xlogreader.c.

1205{

1207

1209

1210

1213

1216

1218 {

1220 "incorrect resource manager data checksum in record at %X/%08X",

1222 return false;

1223 }

1224

1225 return true;

1226}

#define COMP_CRC32C(crc, data, len)

#define EQ_CRC32C(c1, c2)

References Assert(), COMP_CRC32C, crc, EQ_CRC32C, FIN_CRC32C, INIT_CRC32C, LSN_FORMAT_ARGS, report_invalid_record(), SizeOfXLogRecord, XLogRecord::xl_crc, and XLogRecord::xl_tot_len.

Referenced by XLogDecodeNextRecord().

ValidXLogRecordHeader()

Definition at line 1138 of file xlogreader.c.

1141{

1143 {

1145 "invalid record length at %X/%08X: expected at least %u, got %u",

1148 return false;

1149 }

1151 {

1153 "invalid resource manager ID %u at %X/%08X",

1155 return false;

1156 }

1157 if (randAccess)

1158 {

1159

1160

1161

1162

1163 if (!(record->xl_prev < RecPtr))

1164 {

1166 "record with incorrect prev-link %X/%08X at %X/%08X",

1169 return false;

1170 }

1171 }

1172 else

1173 {

1174

1175

1176

1177

1178

1179 if (record->xl_prev != PrevRecPtr)

1180 {

1182 "record with incorrect prev-link %X/%08X at %X/%08X",

1185 return false;

1186 }

1187 }

1188

1189 return true;

1190}

#define RmgrIdIsValid(rmid)

References LSN_FORMAT_ARGS, report_invalid_record(), RmgrIdIsValid, SizeOfXLogRecord, XLogRecord::xl_prev, XLogRecord::xl_rmid, and XLogRecord::xl_tot_len.

Referenced by XLogDecodeNextRecord().

WALOpenSegmentInit()

WALRead()

Definition at line 1514 of file xlogreader.c.

1517{

1518 char *p;

1520 Size nbytes;

1521#ifndef FRONTEND

1523#endif

1524

1525 p = buf;

1526 recptr = startptr;

1527 nbytes = count;

1528

1529 while (nbytes > 0)

1530 {

1532 int segbytes;

1533 int readbytes;

1534

1536

1537

1538

1539

1540

1541

1542 if (state->seg.ws_file < 0 ||

1544 tli != state->seg.ws_tli)

1545 {

1547

1548 if (state->seg.ws_file >= 0)

1549 state->routine.segment_close(state);

1550

1552 state->routine.segment_open(state, nextSegNo, &tli);

1553

1554

1556

1557

1558 state->seg.ws_tli = tli;

1559 state->seg.ws_segno = nextSegNo;

1560 }

1561

1562

1563 if (nbytes > (state->segcxt.ws_segsize - startoff))

1564 segbytes = state->segcxt.ws_segsize - startoff;

1565 else

1566 segbytes = nbytes;

1567

1568#ifndef FRONTEND

1569

1571

1573#endif

1574

1575

1576 errno = 0;

1578

1579#ifndef FRONTEND

1581

1583 io_start, 1, readbytes);

1584#endif

1585

1586 if (readbytes <= 0)

1587 {

1589 errinfo->wre_req = segbytes;

1590 errinfo->wre_read = readbytes;

1591 errinfo->wre_off = startoff;

1593 return false;

1594 }

1595

1596

1597 recptr += readbytes;

1598 nbytes -= readbytes;

1599 p += readbytes;

1600 }

1601

1602 return true;

1603}

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)

static void pgstat_report_wait_start(uint32 wait_event_info)

static void pgstat_report_wait_end(void)

#define XLByteInSeg(xlrp, logSegNo, wal_segsz_bytes)

References Assert(), buf, IOCONTEXT_NORMAL, IOOBJECT_WAL, IOOP_READ, pg_pread, pgstat_count_io_op_time(), pgstat_prepare_io_time(), pgstat_report_wait_end(), pgstat_report_wait_start(), track_wal_io_timing, WALReadError::wre_errno, WALReadError::wre_off, WALReadError::wre_read, WALReadError::wre_req, WALReadError::wre_seg, XLByteInSeg, XLByteToSeg, and XLogSegmentOffset.

Referenced by logical_read_xlog_page(), read_local_xlog_page_guts(), summarizer_read_local_xlog_page(), WALDumpReadPage(), and XLogSendPhysical().

XLogBeginRead()

Definition at line 232 of file xlogreader.c.

233{

235

237

238

239 state->EndRecPtr = RecPtr;

240 state->NextRecPtr = RecPtr;

243}

#define XLogRecPtrIsValid(r)

#define InvalidXLogRecPtr

static void ResetDecoder(XLogReaderState *state)

References Assert(), InvalidXLogRecPtr, ResetDecoder(), and XLogRecPtrIsValid.

Referenced by DecodingContextFindStartpoint(), extractPageMap(), findLastCheckpoint(), LogicalReplicationSlotHasPendingWal(), LogicalSlotAdvanceAndCheckSnapState(), pg_logical_slot_get_changes_guts(), readOneRecord(), StartLogicalReplication(), SummarizeWAL(), XLogFindNextRecord(), XLogPrefetcherBeginRead(), and XlogReadTwoPhaseData().

XLogDecodeNextRecord()

Definition at line 529 of file xlogreader.c.

530{

534 bool randAccess;

536 total_len;

538 uint32 pageHeaderSize;

539 bool assembled;

540 bool gotheader;

543 char *errormsg;

544

545

546

547

548

549

550 randAccess = false;

551

552

553 state->errormsg_buf[0] = '\0';

554 decoded = NULL;

555

558

559 RecPtr = state->NextRecPtr;

560

562 {

563

564

565

566

567

568

569

570

571 }

572 else

573 {

574

575

576

577

578

579

580

582 randAccess = true;

583 }

584

585restart:

586 state->nonblocking = nonblocking;

587 state->currRecPtr = RecPtr;

588 assembled = false;

589

590 targetPagePtr = RecPtr - (RecPtr % XLOG_BLCKSZ);

591 targetRecOff = RecPtr % XLOG_BLCKSZ;

592

593

594

595

596

597

603 goto err;

604

605

606

607

608

610 if (targetRecOff == 0)

611 {

612

613

614

615 RecPtr += pageHeaderSize;

616 targetRecOff = pageHeaderSize;

617 }

618 else if (targetRecOff < pageHeaderSize)

619 {

622 pageHeaderSize, targetRecOff);

623 goto err;

624 }

625

627 targetRecOff == pageHeaderSize)

628 {

631 goto err;

632 }

633

634

636

637

638

639

640

641

642

643

644

645

646 record = (XLogRecord *) (state->readBuf + RecPtr % XLOG_BLCKSZ);

648

649

650

651

652

653

654

655

656

658 {

660 randAccess))

661 goto err;

662 gotheader = true;

663 }

664 else

665 {

666

668 {

670 "invalid record length at %X/%08X: expected at least %u, got %u",

673 goto err;

674 }

675

676 gotheader = false;

677 }

678

679

680

681

682

683

685 total_len,

686 false );

687 if (decoded == NULL && nonblocking)

688 {

689

690

691

692

693

695 }

696

697 len = XLOG_BLCKSZ - RecPtr % XLOG_BLCKSZ;

698 if (total_len > len)

699 {

700

701 char *contdata;

703 char *buffer;

705

706 assembled = true;

707

708

709

710

711

712 Assert(state->readRecordBufSize >= XLOG_BLCKSZ * 2);

714

715

716 memcpy(state->readRecordBuf,

717 state->readBuf + RecPtr % XLOG_BLCKSZ, len);

718 buffer = state->readRecordBuf + len;

719 gotlen = len;

720

721 do

722 {

723

724 targetPagePtr += XLOG_BLCKSZ;

725

726

727

728

729

730

735 goto err;

736

738

740

741

742

743

744

745

746

747

748

750 {

751 state->overwrittenRecPtr = RecPtr;

752 RecPtr = targetPagePtr;

753 goto restart;

754 }

755

756

758 {

760 "there is no contrecord flag at %X/%08X",

762 goto err;

763 }

764

765

766

767

768

770 total_len != (pageHeader->xlp_rem_len + gotlen))

771 {

773 "invalid contrecord length %u (expected %lld) at %X/%08X",

775 ((long long) total_len) - gotlen,

777 goto err;

778 }

779

780

783 XLOG_BLCKSZ));

787 goto err;

788

789

791

792 if (readOff < pageHeaderSize)

794 pageHeaderSize);

795

797

798 contdata = (char *) state->readBuf + pageHeaderSize;

799 len = XLOG_BLCKSZ - pageHeaderSize;

802

805 pageHeaderSize + len);

806

807 memcpy(buffer, contdata, len);

808 buffer += len;

809 gotlen += len;

810

811

812 if (!gotheader)

813 {

816 record, randAccess))

817 goto err;

818 gotheader = true;

819 }

820

821

822

823

824

825

826

827 if (total_len > state->readRecordBufSize)

828 {

829 char save_copy[XLOG_BLCKSZ * 2];

830

831

832

833

834

836 Assert(gotlen <= state->readRecordBufSize);

837 memcpy(save_copy, state->readRecordBuf, gotlen);

839 memcpy(state->readRecordBuf, save_copy, gotlen);

840 buffer = state->readRecordBuf + gotlen;

841 }

842 } while (gotlen < total_len);

844

847 goto err;

848

850 state->DecodeRecPtr = RecPtr;

851 state->NextRecPtr = targetPagePtr + pageHeaderSize

853 }

854 else

855 {

856

858 Min(targetRecOff + total_len, XLOG_BLCKSZ));

862 goto err;

863

864

866 goto err;

867

868 state->NextRecPtr = RecPtr + MAXALIGN(total_len);

869

870 state->DecodeRecPtr = RecPtr;

871 }

872

873

874

875

876 if (record->xl_rmid == RM_XLOG_ID &&

878 {

879

880 state->NextRecPtr += state->segcxt.ws_segsize - 1;

882 }

883

884

885

886

887

888 if (decoded == NULL)

889 {

890 Assert(!nonblocking);

892 total_len,

893 true );

894

895 Assert(decoded != NULL);

896 }

897

899 {

900

902

903

904

905

906

908 {

909

911 if ((char *) decoded == state->decode_buffer)

912 state->decode_buffer_tail = state->decode_buffer + decoded->size;

913 else

914 state->decode_buffer_tail += decoded->size;

915 }

916

917

918 Assert(state->decode_queue_tail != decoded);

919 if (state->decode_queue_tail)

920 state->decode_queue_tail->next = decoded;

921 state->decode_queue_tail = decoded;

922 if (state->decode_queue_head)

923 state->decode_queue_head = decoded;

925 }

926

928 if (assembled)

929 {

930

931

932

933

934

935

936

937

938

939 state->abortedRecPtr = RecPtr;

940 state->missingContrecPtr = targetPagePtr;

941

942

943

944

945

946

947 state->errormsg_deferred = true;

948 }

949

950 if (decoded && decoded->oversized)

952

953

954

955

956

958

959

960

961

962

963

964

966}

#define XLP_FIRST_IS_CONTRECORD

#define XLP_FIRST_IS_OVERWRITE_CONTRECORD

#define XRecOffIsValid(xlrp)

static int ReadPageInternal(XLogReaderState *state, XLogRecPtr pageptr, int reqLen)

static void static void allocate_recordbuf(XLogReaderState *state, uint32 reclength)

bool DecodeXLogRecord(XLogReaderState *state, DecodedXLogRecord *decoded, XLogRecord *record, XLogRecPtr lsn, char **errormsg)

static bool ValidXLogRecord(XLogReaderState *state, XLogRecord *record, XLogRecPtr recptr)

static DecodedXLogRecord * XLogReadRecordAlloc(XLogReaderState *state, size_t xl_tot_len, bool allow_oversized)

static bool ValidXLogRecordHeader(XLogReaderState *state, XLogRecPtr RecPtr, XLogRecPtr PrevRecPtr, XLogRecord *record, bool randAccess)

References allocate_recordbuf(), Assert(), DecodeXLogRecord(), err(), if(), InvalidXLogRecPtr, len, lengthof, LSN_FORMAT_ARGS, MAXALIGN, Min, state::next, DecodedXLogRecord::next_lsn, DecodedXLogRecord::oversized, pfree(), readOff, ReadPageInternal(), report_invalid_record(), DecodedXLogRecord::size, SizeOfXLogRecord, SizeOfXLogShortPHD, ValidXLogRecord(), ValidXLogRecordHeader(), XLogRecord::xl_info, XLogRecord::xl_rmid, XLogRecord::xl_tot_len, XLOG_SWITCH, XLogPageHeaderSize, XLogReaderInvalReadState(), XLogReadRecordAlloc(), XLogRecPtrIsValid, XLogSegmentOffset, XLP_FIRST_IS_CONTRECORD, XLP_FIRST_IS_OVERWRITE_CONTRECORD, XLogPageHeaderData::xlp_info, XLogPageHeaderData::xlp_rem_len, XLR_INFO_MASK, XLREAD_FAIL, XLREAD_SUCCESS, XLREAD_WOULDBLOCK, and XRecOffIsValid.

Referenced by XLogReadAhead().

XLogFindNextRecord()

Definition at line 1394 of file xlogreader.c.

1395{

1399 char *errormsg;

1400

1402

1403

1404 state->nonblocking = false;

1405

1406

1407

1408

1409

1410 tmpRecPtr = RecPtr;

1411 while (true)

1412 {

1414 int targetRecOff;

1415 uint32 pageHeaderSize;

1417

1418

1419

1420

1421

1422

1423

1424

1425

1426

1427 targetRecOff = tmpRecPtr % XLOG_BLCKSZ;

1428

1429

1430 targetPagePtr = tmpRecPtr - targetRecOff;

1431

1432

1435 goto err;

1436

1438

1440

1441

1444 goto err;

1445

1446

1448 {

1449

1450

1451

1452

1453

1454

1455

1456

1457

1459 tmpRecPtr = targetPagePtr + XLOG_BLCKSZ;

1460 else

1461 {

1462

1463

1464

1465

1466 tmpRecPtr = targetPagePtr + pageHeaderSize

1468 break;

1469 }

1470 }

1471 else

1472 {

1473 tmpRecPtr = targetPagePtr + pageHeaderSize;

1474 break;

1475 }

1476 }

1477

1478

1479

1480

1481

1482

1485 {

1486

1487 if (RecPtr <= state->ReadRecPtr)

1488 {

1489

1490 found = state->ReadRecPtr;

1492 return found;

1493 }

1494 }

1495

1498

1500}

XLogRecord * XLogReadRecord(XLogReaderState *state, char **errormsg)

void XLogBeginRead(XLogReaderState *state, XLogRecPtr RecPtr)

References Assert(), err(), InvalidXLogRecPtr, MAXALIGN, readLen, ReadPageInternal(), XLogBeginRead(), XLogPageHeaderSize, XLogReaderInvalReadState(), XLogReadRecord(), XLogRecPtrIsValid, XLP_FIRST_IS_CONTRECORD, XLogPageHeaderData::xlp_info, and XLogPageHeaderData::xlp_rem_len.

Referenced by InitXLogReaderState(), main(), and SummarizeWAL().

XLogNextRecord()

XLogReadAhead()

XLogReaderAllocate()

Definition at line 107 of file xlogreader.c.

109{

111

116 return NULL;

117

118

119 state->routine = *routine;

120

121

122

123

124

125

126

127

130 if (state->readBuf)

131 {

133 return NULL;

134 }

135

136

138 waldir);

139

140

141 state->private_data = private_data;

142

145 if (state->errormsg_buf)

146 {

149 return NULL;

150 }

151 state->errormsg_buf[0] = '\0';

152

153

154

155

156

159}

#define MCXT_ALLOC_NO_OOM

void * palloc_extended(Size size, int flags)

static void WALOpenSegmentInit(WALOpenSegment *seg, WALSegmentContext *segcxt, int segsize, const char *waldir)

References allocate_recordbuf(), MAX_ERRORMSG_LEN, MCXT_ALLOC_NO_OOM, MCXT_ALLOC_ZERO, palloc_extended(), pfree(), wal_segment_size, and WALOpenSegmentInit().

Referenced by extractPageMap(), findLastCheckpoint(), InitWalRecovery(), InitXLogReaderState(), main(), readOneRecord(), StartReplication(), StartupDecodingContext(), SummarizeWAL(), XLogInsertRecord(), and XlogReadTwoPhaseData().

XLogReaderFree()

Definition at line 162 of file xlogreader.c.

163{

164 if (state->seg.ws_file != -1)

166

167 if (state->decode_buffer && state->free_decode_buffer)

169

171 if (state->readRecordBuf)

175}

References pfree().

Referenced by extractPageMap(), findLastCheckpoint(), FreeDecodingContext(), GetWALRecordsInfo(), main(), pg_get_wal_block_info(), pg_get_wal_record_info(), readOneRecord(), ShutdownWalRecovery(), SummarizeWAL(), and XlogReadTwoPhaseData().

XLogReaderInvalReadState()

XLogReaderResetError()

XLogReaderSetDecodeBuffer()

void XLogReaderSetDecodeBuffer ( XLogReaderState * state,
void * buffer,
size_t size
)

XLogReaderValidatePageHeader()

Definition at line 1235 of file xlogreader.c.

1237{

1241

1242 Assert((recptr % XLOG_BLCKSZ) == 0);

1243

1246

1248 {

1250

1252

1254 "invalid magic number %04X in WAL segment %s, LSN %X/%08X, offset %u",

1256 fname,

1258 offset);

1259 return false;

1260 }

1261

1263 {

1265

1267

1269 "invalid info bits %04X in WAL segment %s, LSN %X/%08X, offset %u",

1271 fname,

1273 offset);

1274 return false;

1275 }

1276

1278 {

1280

1281 if (state->system_identifier &&

1283 {

1285 "WAL file is from different database system: WAL file database system identifier is %" PRIu64 ", pg_control database system identifier is %" PRIu64,

1287 state->system_identifier);

1288 return false;

1289 }

1291 {

1293 "WAL file is from different database system: incorrect segment size in page header");

1294 return false;

1295 }

1297 {

1299 "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header");

1300 return false;

1301 }

1302 }

1303 else if (offset == 0)

1304 {

1306

1308

1309

1311 "invalid info bits %04X in WAL segment %s, LSN %X/%08X, offset %u",

1313 fname,

1315 offset);

1316 return false;

1317 }

1318

1319

1320

1321

1322

1323

1325 {

1327

1329

1331 "unexpected pageaddr %X/%08X in WAL segment %s, LSN %X/%08X, offset %u",

1333 fname,

1335 offset);

1336 return false;

1337 }

1338

1339

1340

1341

1342

1343

1344

1345

1346

1347

1348 if (recptr > state->latestPagePtr)

1349 {

1351 {

1353

1355

1357 "out-of-sequence timeline ID %u (after %u) in WAL segment %s, LSN %X/%08X, offset %u",

1359 state->latestPageTLI,

1360 fname,

1362 offset);

1363 return false;

1364 }

1365 }

1366 state->latestPagePtr = recptr;

1368

1369 return true;

1370}

XLogLongPageHeaderData * XLogLongPageHeader

static void XLogFileName(char *fname, TimeLineID tli, XLogSegNo logSegNo, int wal_segsz_bytes)

References Assert(), LSN_FORMAT_ARGS, MAXFNAMELEN, report_invalid_record(), XLByteToSeg, XLOG_PAGE_MAGIC, XLogFileName(), XLogSegmentOffset, XLP_ALL_FLAGS, XLogPageHeaderData::xlp_info, XLP_LONG_HEADER, XLogPageHeaderData::xlp_magic, XLogPageHeaderData::xlp_pageaddr, XLogLongPageHeaderData::xlp_seg_size, XLogLongPageHeaderData::xlp_sysid, XLogPageHeaderData::xlp_tli, and XLogLongPageHeaderData::xlp_xlog_blcksz.

Referenced by ReadPageInternal(), and XLogPageRead().

XLogReadRecord()

Definition at line 390 of file xlogreader.c.

391{

393

394

395

396

397

399

400

401

402

403

406

407

409 if (decoded)

410 {

411

412

413

414

415

416

418 return &decoded->header;

419 }

420

421 return NULL;

422}

DecodedXLogRecord * XLogReadAhead(XLogReaderState *state, bool nonblocking)

DecodedXLogRecord * XLogNextRecord(XLogReaderState *state, char **errormsg)

static bool XLogReaderHasQueuedRecordOrError(XLogReaderState *state)

References Assert(), DecodedXLogRecord::header, XLogNextRecord(), XLogReadAhead(), XLogReaderHasQueuedRecordOrError(), and XLogReleasePreviousRecord().

Referenced by DecodingContextFindStartpoint(), extractPageMap(), findLastCheckpoint(), LogicalReplicationSlotHasPendingWal(), LogicalSlotAdvanceAndCheckSnapState(), main(), pg_logical_slot_get_changes_guts(), ReadNextXLogRecord(), readOneRecord(), SummarizeWAL(), XLogFindNextRecord(), XlogReadTwoPhaseData(), and XLogSendLogical().

XLogReadRecordAlloc()

Definition at line 439 of file xlogreader.c.

440{

443

444

446 {

447 if (state->decode_buffer_size == 0)

450 state->decode_buffer_head = state->decode_buffer;

451 state->decode_buffer_tail = state->decode_buffer;

452 state->free_decode_buffer = true;

453 }

454

455

456 if (state->decode_buffer_tail >= state->decode_buffer_head)

457 {

458

459 if (required_space <=

460 state->decode_buffer_size -

461 (state->decode_buffer_tail - state->decode_buffer))

462 {

463

464

465

466

467

468

469

470

471

472

475 return decoded;

476 }

477 else if (required_space <

478 state->decode_buffer_head - state->decode_buffer)

479 {

480

481

482

483

484

485

486

487

488

489

492 return decoded;

493 }

494 }

495 else

496 {

497

498 if (required_space <

499 state->decode_buffer_head - state->decode_buffer_tail)

500 {

501

502

503

504

505

506

507

508

509

510

513 return decoded;

514 }

515 }

516

517

518 if (allow_oversized)

519 {

520 decoded = palloc(required_space);

522 return decoded;

523 }

524

525 return NULL;

526}

#define DEFAULT_DECODE_BUFFER_SIZE

References DecodeXLogRecordRequiredSpace(), DEFAULT_DECODE_BUFFER_SIZE, DecodedXLogRecord::oversized, palloc(), and unlikely.

Referenced by XLogDecodeNextRecord().

XLogRecGetBlockData()

Definition at line 2045 of file xlogreader.c.

2046{

2048

2051 return NULL;

2052

2054

2056 {

2057 if (len)

2058 *len = 0;

2059 return NULL;

2060 }

2061 else

2062 {

2063 if (len)

2065 return bkpb->data;

2066 }

2067}

References DecodedXLogRecord::blocks, DecodedBkpBlock::data, DecodedBkpBlock::data_len, DecodedBkpBlock::has_data, DecodedBkpBlock::in_use, len, DecodedXLogRecord::max_block_id, and XLogReaderState::record.

Referenced by _bt_restore_meta(), brin_xlog_insert_update(), brin_xlog_samepage_update(), btree_desc(), btree_xlog_dedup(), btree_xlog_delete(), btree_xlog_insert(), btree_xlog_newroot(), btree_xlog_split(), btree_xlog_vacuum(), DecodeInsert(), DecodeMultiInsert(), DecodeUpdate(), generic_redo(), gin_desc(), ginRedoInsert(), ginRedoInsertListPage(), ginRedoUpdateMetapage(), ginRedoVacuumDataLeafPage(), gistRedoPageSplitRecord(), gistRedoPageUpdateRecord(), hash_xlog_add_ovfl_page(), hash_xlog_delete(), hash_xlog_insert(), hash_xlog_move_page_contents(), hash_xlog_split_allocate_page(), hash_xlog_squeeze_page(), heap2_desc(), heap_xlog_inplace(), heap_xlog_insert(), heap_xlog_multi_insert(), heap_xlog_prune_freeze(), and heap_xlog_update().

XLogRecGetBlockTag()

Definition at line 1991 of file xlogreader.c.

1994{

1996 blknum, NULL))

1997 {

1998#ifndef FRONTEND

1999 elog(ERROR, "could not locate backup block with ID %d in WAL record",

2000 block_id);

2001#else

2002 pg_fatal("could not locate backup block with ID %d in WAL record",

2003 block_id);

2004#endif

2005 }

2006}

bool XLogRecGetBlockTagExtended(XLogReaderState *record, uint8 block_id, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum, Buffer *prefetch_buffer)

References elog, ERROR, pg_fatal, and XLogRecGetBlockTagExtended().

Referenced by brin_xlog_revmap_extend(), btree_xlog_delete(), btree_xlog_split(), DecodeDelete(), DecodeInsert(), DecodeMultiInsert(), DecodeSpecConfirm(), DecodeUpdate(), gistRedoDeleteRecord(), gistRedoPageSplitRecord(), hash_xlog_add_ovfl_page(), hash_xlog_init_bitmap_page(), hash_xlog_init_meta_page(), hash_xlog_vacuum_one_page(), heap_xlog_delete(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_multi_insert(), heap_xlog_prune_freeze(), heap_xlog_update(), heap_xlog_visible(), spgRedoAddLeaf(), spgRedoAddNode(), spgRedoMoveLeafs(), spgRedoPickSplit(), and spgRedoVacuumRedirect().

XLogRecGetBlockTagExtended()

Definition at line 2017 of file xlogreader.c.

2021{

2023

2025 return false;

2026

2028 if (rlocator)

2030 if (forknum)

2031 *forknum = bkpb->forknum;

2032 if (blknum)

2033 *blknum = bkpb->blkno;

2034 if (prefetch_buffer)

2036 return true;

2037}

#define XLogRecHasBlockRef(decoder, block_id)

References DecodedBkpBlock::blkno, DecodedXLogRecord::blocks, DecodedBkpBlock::forknum, DecodedBkpBlock::prefetch_buffer, XLogReaderState::record, DecodedBkpBlock::rlocator, and XLogRecHasBlockRef.

Referenced by btree_xlog_split(), extractPageInfo(), GetWALBlockInfo(), heap_xlog_update(), SummarizeWAL(), verifyBackupPageConsistency(), xlog_block_info(), XLogReadBufferForRedoExtended(), XLogRecGetBlockRefInfo(), XLogRecGetBlockTag(), XLogRecordMatchesRelationBlock(), and XLogRecordSaveFPWs().

XLogRecGetFullXid()

XLogReleasePreviousRecord()