PostgreSQL Source Code  git master
xlogreader.h File Reference
#include "access/transam.h"
#include "access/xlogrecord.h"
#include "storage/buf.h"
Include dependency graph for xlogreader.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  WALOpenSegment
 
struct  WALSegmentContext
 
struct  DecodedBkpBlock
 
struct  DecodedXLogRecord
 
struct  XLogReaderState
 
struct  XLogFindNextRecordState
 
struct  WALReadError
 

Macros

#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)
 
#define XLogRecHasBlockImage(decoder, block_id)   ((decoder)->record->blocks[block_id].has_image)
 
#define XLogRecBlockImageApply(decoder, block_id)   ((decoder)->record->blocks[block_id].apply_image)
 

Typedefs

typedef struct WALOpenSegment WALOpenSegment
 
typedef struct WALSegmentContext WALSegmentContext
 
typedef struct XLogReaderState XLogReaderState
 
typedef struct XLogFindNextRecordState XLogFindNextRecordState
 
typedef void(* WALSegmentCleanupCB) (XLogReaderState *xlogreader)
 
typedef void(* WALSegmentOpenCB) (XLogReaderState *xlogreader, XLogSegNo nextSegNo, TimeLineID *tli_p)
 
typedef void(* WALSegmentCloseCB) (XLogReaderState *xlogreader)
 
typedef enum XLogReadRecordResult XLogReadRecordResult
 
typedef enum XLogReadRecordState XLogReadRecordState
 
typedef struct DecodedXLogRecord DecodedXLogRecord
 
typedef struct WALReadError WALReadError
 

Enumerations

enum  XLogReadRecordResult { XLREAD_SUCCESS, XLREAD_NEED_DATA, XLREAD_FULL, XLREAD_FAIL }
 
enum  XLogReadRecordState { XLREAD_NEXT_RECORD, XLREAD_TOT_LEN, XLREAD_FIRST_FRAGMENT, XLREAD_CONTINUATION }
 

Functions

static void XLogReaderSetInputData (XLogReaderState *state, int32 len)
 
XLogReaderStateXLogReaderAllocate (int wal_segment_size, const char *waldir, WALSegmentCleanupCB cleanup_cb)
 
void XLogReaderFree (XLogReaderState *state)
 
void XLogReaderSetDecodeBuffer (XLogReaderState *state, void *buffer, size_t size)
 
void XLogBeginRead (XLogReaderState *state, XLogRecPtr RecPtr)
 
XLogReadRecordResult XLogReadRecord (XLogReaderState *state, XLogRecord **record, char **errormsg)
 
XLogReadRecordResult XLogNextRecord (XLogReaderState *state, DecodedXLogRecord **record, char **errormsg)
 
XLogReadRecordResult XLogReadAhead (XLogReaderState *state, DecodedXLogRecord **record, char **errormsg)
 
bool XLogReaderValidatePageHeader (XLogReaderState *state, XLogRecPtr recptr, char *phdr)
 
bool WALRead (XLogReaderState *state, WALSegmentOpenCB segopenfn, WALSegmentCloseCB sgclosefn, 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 **errmsg)
 
FullTransactionId XLogRecGetFullXid (XLogReaderState *record)
 
bool RestoreBlockImage (XLogReaderState *record, uint8 block_id, char *page)
 
char * XLogRecGetBlockData (XLogReaderState *record, uint8 block_id, Size *len)
 
bool XLogRecGetBlockTag (XLogReaderState *record, uint8 block_id, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum)
 
bool XLogRecGetRecentBuffer (XLogReaderState *record, uint8 block_id, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum, Buffer *recent_buffer)
 

Macro Definition Documentation

◆ XLogRecBlockImageApply

#define XLogRecBlockImageApply (   decoder,
  block_id 
)    ((decoder)->record->blocks[block_id].apply_image)

◆ XLogRecGetBlock

#define XLogRecGetBlock (   decoder,
  i 
)    (&(decoder)->record->blocks[(i)])

Definition at line 386 of file xlogreader.h.

◆ XLogRecGetData

#define XLogRecGetData (   decoder)    ((decoder)->record->main_data)

Definition at line 382 of file xlogreader.h.

Referenced by brin_desc(), brin_xlog_createidx(), brin_xlog_desummarize_page(), brin_xlog_insert(), brin_xlog_revmap_extend(), brin_xlog_samepage_update(), brin_xlog_update(), btree_desc(), btree_xlog_dedup(), btree_xlog_delete(), btree_xlog_insert(), btree_xlog_mark_page_halfdead(), btree_xlog_newroot(), btree_xlog_reuse_page(), btree_xlog_split(), btree_xlog_unlink_page(), btree_xlog_vacuum(), clog_desc(), clog_redo(), commit_ts_desc(), commit_ts_redo(), dbase_desc(), dbase_redo(), DecodeDelete(), DecodeHeap2Op(), DecodeInsert(), DecodeLogicalMsgOp(), DecodeMultiInsert(), DecodeStandbyOp(), DecodeTruncate(), DecodeUpdate(), DecodeXactOp(), findLastCheckpoint(), generic_desc(), getRecordTimestamp(), gin_desc(), ginRedoCreatePTree(), ginRedoDeleteListPages(), ginRedoDeletePage(), ginRedoInsert(), ginRedoInsertListPage(), ginRedoSplit(), ginRedoUpdateMetapage(), gist_desc(), gistRedoDeleteRecord(), gistRedoPageDelete(), gistRedoPageReuse(), gistRedoPageSplitRecord(), gistRedoPageUpdateRecord(), hash_desc(), hash_xlog_add_ovfl_page(), hash_xlog_delete(), hash_xlog_init_bitmap_page(), hash_xlog_init_meta_page(), hash_xlog_insert(), hash_xlog_move_page_contents(), hash_xlog_split_allocate_page(), hash_xlog_split_complete(), hash_xlog_squeeze_page(), hash_xlog_update_meta_page(), hash_xlog_vacuum_one_page(), heap2_desc(), heap_desc(), heap_xlog_confirm(), heap_xlog_delete(), heap_xlog_freeze_page(), heap_xlog_inplace(), heap_xlog_insert(), heap_xlog_lock(), heap_xlog_lock_updated(), heap_xlog_logical_rewrite(), heap_xlog_multi_insert(), heap_xlog_prune(), heap_xlog_update(), heap_xlog_vacuum(), heap_xlog_visible(), logicalmsg_desc(), multixact_desc(), multixact_redo(), recoveryStopsAfter(), recoveryStopsBefore(), relmap_desc(), relmap_redo(), replorigin_desc(), replorigin_redo(), seq_desc(), seq_redo(), smgr_desc(), smgr_redo(), spg_desc(), spgRedoAddLeaf(), spgRedoAddNode(), spgRedoMoveLeafs(), spgRedoPickSplit(), spgRedoSplitTuple(), spgRedoVacuumLeaf(), spgRedoVacuumRedirect(), spgRedoVacuumRoot(), standby_desc(), standby_redo(), StartupXLOG(), tblspc_desc(), tblspc_redo(), xact_desc(), xact_redo(), xlog_desc(), xlog_redo(), and XlogReadTwoPhaseData().

◆ XLogRecGetDataLen

#define XLogRecGetDataLen (   decoder)    ((decoder)->record->main_data_len)

◆ XLogRecGetInfo

◆ XLogRecGetOrigin

#define XLogRecGetOrigin (   decoder)    ((decoder)->record->record_origin)

◆ XLogRecGetPrev

#define XLogRecGetPrev (   decoder)    ((decoder)->record->header.xl_prev)

Definition at line 376 of file xlogreader.h.

Referenced by xlog_redo(), and XLogDumpDisplayRecord().

◆ XLogRecGetRmid

◆ XLogRecGetTopXid

#define XLogRecGetTopXid (   decoder)    ((decoder)->record->toplevel_xid)

Definition at line 381 of file xlogreader.h.

Referenced by LogicalDecodingProcessRecord().

◆ XLogRecGetTotalLen

#define XLogRecGetTotalLen (   decoder)    ((decoder)->record->header.xl_tot_len)

Definition at line 375 of file xlogreader.h.

Referenced by XLogDumpDisplayRecord(), and XLogDumpRecordLen().

◆ XLogRecGetXid

◆ XLogRecHasAnyBlockRefs

#define XLogRecHasAnyBlockRefs (   decoder)    ((decoder)->record->max_block_id >= 0)

◆ XLogRecHasBlockImage

#define XLogRecHasBlockImage (   decoder,
  block_id 
)    ((decoder)->record->blocks[block_id].has_image)

◆ XLogRecHasBlockRef

#define XLogRecHasBlockRef (   decoder,
  block_id 
)
Value:
((decoder)->record->max_block_id >= (block_id) && \
(decoder)->record->blocks[block_id].in_use)

Definition at line 387 of file xlogreader.h.

Referenced by btree_xlog_unlink_page(), generic_redo(), gistRedoPageSplitRecord(), gistRedoPageUpdateRecord(), hash_xlog_add_ovfl_page(), hash_xlog_squeeze_page(), spgRedoAddNode(), spgRedoPickSplit(), xlog_block_info(), and XLogDumpDisplayRecord().

◆ XLogRecMaxBlockId

#define XLogRecMaxBlockId (   decoder)    ((decoder)->record->max_block_id)

Typedef Documentation

◆ DecodedXLogRecord

◆ WALOpenSegment

◆ WALReadError

typedef struct WALReadError WALReadError

◆ WALSegmentCleanupCB

typedef void(* WALSegmentCleanupCB) (XLogReaderState *xlogreader)

Definition at line 63 of file xlogreader.h.

◆ WALSegmentCloseCB

typedef void(* WALSegmentCloseCB) (XLogReaderState *xlogreader)

Definition at line 69 of file xlogreader.h.

◆ WALSegmentContext

◆ WALSegmentOpenCB

typedef void(* WALSegmentOpenCB) (XLogReaderState *xlogreader, XLogSegNo nextSegNo, TimeLineID *tli_p)

Definition at line 66 of file xlogreader.h.

◆ XLogFindNextRecordState

Definition at line 60 of file xlogreader.h.

◆ XLogReaderState

Definition at line 59 of file xlogreader.h.

◆ XLogReadRecordResult

◆ XLogReadRecordState

Enumeration Type Documentation

◆ XLogReadRecordResult

Enumerator
XLREAD_SUCCESS 
XLREAD_NEED_DATA 
XLREAD_FULL 
XLREAD_FAIL 

Definition at line 104 of file xlogreader.h.

105 {
106  XLREAD_SUCCESS, /* record is successfully read */
107  XLREAD_NEED_DATA, /* need more data. see XLogReadRecord. */
108  XLREAD_FULL, /* cannot hold more data while reading ahead */
109  XLREAD_FAIL /* failed during reading a record */
XLogReadRecordResult
Definition: xlogreader.h:104

◆ XLogReadRecordState

Enumerator
XLREAD_NEXT_RECORD 
XLREAD_TOT_LEN 
XLREAD_FIRST_FRAGMENT 
XLREAD_CONTINUATION 

Definition at line 120 of file xlogreader.h.

Function Documentation

◆ DecodeXLogRecord()

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

Definition at line 1826 of file xlogreader.c.

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_HAS_HOLE, BKPIMAGE_IS_COMPRESSED, DecodedBkpBlock::blkno, blocks, DecodedXLogRecord::blocks, COPY_HEADER_FIELD, DecodedBkpBlock::data, DecodedBkpBlock::data_len, DecodeXLogRecordRequiredSpace(), XLogReaderState::errormsg_buf, 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, offsetof, XLogReaderState::ReadRecPtr, DecodedBkpBlock::recent_buffer, DecodedXLogRecord::record_origin, remaining, report_invalid_record(), DecodedBkpBlock::rnode, 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 XLogDecodeOneRecord(), and XLogInsertRecord().

1831 {
1832  /*
1833  * read next _size bytes from record buffer, but check for overrun first.
1834  */
1835 #define COPY_HEADER_FIELD(_dst, _size) \
1836  do { \
1837  if (remaining < _size) \
1838  goto shortdata_err; \
1839  memcpy(_dst, ptr, _size); \
1840  ptr += _size; \
1841  remaining -= _size; \
1842  } while(0)
1843 
1844  char *ptr;
1845  char *out;
1846  uint32 remaining;
1847  uint32 datatotal;
1848  RelFileNode *rnode = NULL;
1849  uint8 block_id;
1850 
1851  decoded->header = *record;
1852  decoded->lsn = lsn;
1853  decoded->next = NULL;
1854  decoded->record_origin = InvalidRepOriginId;
1856  decoded->main_data = NULL;
1857  decoded->main_data_len = 0;
1858  decoded->max_block_id = -1;
1859  ptr = (char *) record;
1860  ptr += SizeOfXLogRecord;
1861  remaining = record->xl_tot_len - SizeOfXLogRecord;
1862 
1863  /* Decode the headers */
1864  datatotal = 0;
1865  while (remaining > datatotal)
1866  {
1867  COPY_HEADER_FIELD(&block_id, sizeof(uint8));
1868 
1869  if (block_id == XLR_BLOCK_ID_DATA_SHORT)
1870  {
1871  /* XLogRecordDataHeaderShort */
1872  uint8 main_data_len;
1873 
1874  COPY_HEADER_FIELD(&main_data_len, sizeof(uint8));
1875 
1876  decoded->main_data_len = main_data_len;
1877  datatotal += main_data_len;
1878  break; /* by convention, the main data fragment is
1879  * always last */
1880  }
1881  else if (block_id == XLR_BLOCK_ID_DATA_LONG)
1882  {
1883  /* XLogRecordDataHeaderLong */
1884  uint32 main_data_len;
1885 
1886  COPY_HEADER_FIELD(&main_data_len, sizeof(uint32));
1887  decoded->main_data_len = main_data_len;
1888  datatotal += main_data_len;
1889  break; /* by convention, the main data fragment is
1890  * always last */
1891  }
1892  else if (block_id == XLR_BLOCK_ID_ORIGIN)
1893  {
1894  COPY_HEADER_FIELD(&decoded->record_origin, sizeof(RepOriginId));
1895  }
1896  else if (block_id == XLR_BLOCK_ID_TOPLEVEL_XID)
1897  {
1898  COPY_HEADER_FIELD(&decoded->toplevel_xid, sizeof(TransactionId));
1899  }
1900  else if (block_id <= XLR_MAX_BLOCK_ID)
1901  {
1902  /* XLogRecordBlockHeader */
1903  DecodedBkpBlock *blk;
1904  uint8 fork_flags;
1905 
1906  /* mark any intervening block IDs as not in use */
1907  for (int i = decoded->max_block_id + 1; i < block_id; ++i)
1908  decoded->blocks[i].in_use = false;
1909 
1910  if (block_id <= decoded->max_block_id)
1911  {
1912  report_invalid_record(state,
1913  "out-of-order block_id %u at %X/%X",
1914  block_id,
1915  LSN_FORMAT_ARGS(state->ReadRecPtr));
1916  goto err;
1917  }
1918  decoded->max_block_id = block_id;
1919 
1920  blk = &decoded->blocks[block_id];
1921  blk->in_use = true;
1922  blk->apply_image = false;
1923 
1924  COPY_HEADER_FIELD(&fork_flags, sizeof(uint8));
1925  blk->forknum = fork_flags & BKPBLOCK_FORK_MASK;
1926  blk->flags = fork_flags;
1927  blk->has_image = ((fork_flags & BKPBLOCK_HAS_IMAGE) != 0);
1928  blk->has_data = ((fork_flags & BKPBLOCK_HAS_DATA) != 0);
1929 
1931 
1932  COPY_HEADER_FIELD(&blk->data_len, sizeof(uint16));
1933  /* cross-check that the HAS_DATA flag is set iff data_length > 0 */
1934  if (blk->has_data && blk->data_len == 0)
1935  {
1936  report_invalid_record(state,
1937  "BKPBLOCK_HAS_DATA set, but no data included at %X/%X",
1938  LSN_FORMAT_ARGS(state->ReadRecPtr));
1939  goto err;
1940  }
1941  if (!blk->has_data && blk->data_len != 0)
1942  {
1943  report_invalid_record(state,
1944  "BKPBLOCK_HAS_DATA not set, but data length is %u at %X/%X",
1945  (unsigned int) blk->data_len,
1946  LSN_FORMAT_ARGS(state->ReadRecPtr));
1947  goto err;
1948  }
1949  datatotal += blk->data_len;
1950 
1951  if (blk->has_image)
1952  {
1953  COPY_HEADER_FIELD(&blk->bimg_len, sizeof(uint16));
1954  COPY_HEADER_FIELD(&blk->hole_offset, sizeof(uint16));
1955  COPY_HEADER_FIELD(&blk->bimg_info, sizeof(uint8));
1956 
1957  blk->apply_image = ((blk->bimg_info & BKPIMAGE_APPLY) != 0);
1958 
1959  if (blk->bimg_info & BKPIMAGE_IS_COMPRESSED)
1960  {
1961  if (blk->bimg_info & BKPIMAGE_HAS_HOLE)
1962  COPY_HEADER_FIELD(&blk->hole_length, sizeof(uint16));
1963  else
1964  blk->hole_length = 0;
1965  }
1966  else
1967  blk->hole_length = BLCKSZ - blk->bimg_len;
1968  datatotal += blk->bimg_len;
1969 
1970  /*
1971  * cross-check that hole_offset > 0, hole_length > 0 and
1972  * bimg_len < BLCKSZ if the HAS_HOLE flag is set.
1973  */
1974  if ((blk->bimg_info & BKPIMAGE_HAS_HOLE) &&
1975  (blk->hole_offset == 0 ||
1976  blk->hole_length == 0 ||
1977  blk->bimg_len == BLCKSZ))
1978  {
1979  report_invalid_record(state,
1980  "BKPIMAGE_HAS_HOLE set, but hole offset %u length %u block image length %u at %X/%X",
1981  (unsigned int) blk->hole_offset,
1982  (unsigned int) blk->hole_length,
1983  (unsigned int) blk->bimg_len,
1984  LSN_FORMAT_ARGS(state->ReadRecPtr));
1985  goto err;
1986  }
1987 
1988  /*
1989  * cross-check that hole_offset == 0 and hole_length == 0 if
1990  * the HAS_HOLE flag is not set.
1991  */
1992  if (!(blk->bimg_info & BKPIMAGE_HAS_HOLE) &&
1993  (blk->hole_offset != 0 || blk->hole_length != 0))
1994  {
1995  report_invalid_record(state,
1996  "BKPIMAGE_HAS_HOLE not set, but hole offset %u length %u at %X/%X",
1997  (unsigned int) blk->hole_offset,
1998  (unsigned int) blk->hole_length,
1999  LSN_FORMAT_ARGS(state->ReadRecPtr));
2000  goto err;
2001  }
2002 
2003  /*
2004  * cross-check that bimg_len < BLCKSZ if the IS_COMPRESSED
2005  * flag is set.
2006  */
2007  if ((blk->bimg_info & BKPIMAGE_IS_COMPRESSED) &&
2008  blk->bimg_len == BLCKSZ)
2009  {
2010  report_invalid_record(state,
2011  "BKPIMAGE_IS_COMPRESSED set, but block image length %u at %X/%X",
2012  (unsigned int) blk->bimg_len,
2013  LSN_FORMAT_ARGS(state->ReadRecPtr));
2014  goto err;
2015  }
2016 
2017  /*
2018  * cross-check that bimg_len = BLCKSZ if neither HAS_HOLE nor
2019  * IS_COMPRESSED flag is set.
2020  */
2021  if (!(blk->bimg_info & BKPIMAGE_HAS_HOLE) &&
2022  !(blk->bimg_info & BKPIMAGE_IS_COMPRESSED) &&
2023  blk->bimg_len != BLCKSZ)
2024  {
2025  report_invalid_record(state,
2026  "neither BKPIMAGE_HAS_HOLE nor BKPIMAGE_IS_COMPRESSED set, but block image length is %u at %X/%X",
2027  (unsigned int) blk->data_len,
2028  LSN_FORMAT_ARGS(state->ReadRecPtr));
2029  goto err;
2030  }
2031  }
2032  if (!(fork_flags & BKPBLOCK_SAME_REL))
2033  {
2034  COPY_HEADER_FIELD(&blk->rnode, sizeof(RelFileNode));
2035  rnode = &blk->rnode;
2036  }
2037  else
2038  {
2039  if (rnode == NULL)
2040  {
2041  report_invalid_record(state,
2042  "BKPBLOCK_SAME_REL set but no previous rel at %X/%X",
2043  LSN_FORMAT_ARGS(state->ReadRecPtr));
2044  goto err;
2045  }
2046 
2047  blk->rnode = *rnode;
2048  }
2049  COPY_HEADER_FIELD(&blk->blkno, sizeof(BlockNumber));
2050  }
2051  else
2052  {
2053  report_invalid_record(state,
2054  "invalid block_id %u at %X/%X",
2055  block_id, LSN_FORMAT_ARGS(state->ReadRecPtr));
2056  goto err;
2057  }
2058  }
2059 
2060  if (remaining != datatotal)
2061  goto shortdata_err;
2062 
2063  /*
2064  * Ok, we've parsed the fragment headers, and verified that the total
2065  * length of the payload in the fragments is equal to the amount of data
2066  * left. Copy the data of each fragment to contiguous space after the
2067  * blocks array, inserting alignment padding before the data fragments so
2068  * they can be cast to struct pointers by REDO routines.
2069  */
2070  out = ((char *) decoded) +
2072  sizeof(decoded->blocks[0]) * (decoded->max_block_id + 1);
2073 
2074  /* block data first */
2075  for (block_id = 0; block_id <= decoded->max_block_id; block_id++)
2076  {
2077  DecodedBkpBlock *blk = &decoded->blocks[block_id];
2078 
2079  if (!blk->in_use)
2080  continue;
2081 
2082  Assert(blk->has_image || !blk->apply_image);
2083 
2084  if (blk->has_image)
2085  {
2086  /* no need to align image */
2087  blk->bkp_image = out;
2088  memcpy(out, ptr, blk->bimg_len);
2089  ptr += blk->bimg_len;
2090  out += blk->bimg_len;
2091  }
2092  if (blk->has_data)
2093  {
2094  out = (char *) MAXALIGN(out);
2095  blk->data = out;
2096  memcpy(blk->data, ptr, blk->data_len);
2097  ptr += blk->data_len;
2098  out += blk->data_len;
2099  }
2100  }
2101 
2102  /* and finally, the main data */
2103  if (decoded->main_data_len > 0)
2104  {
2105  out = (char *) MAXALIGN(out);
2106  decoded->main_data = out;
2107  memcpy(decoded->main_data, ptr, decoded->main_data_len);
2108  ptr += decoded->main_data_len;
2109  out += decoded->main_data_len;
2110  }
2111 
2112  /* Report the actual size we used. */
2113  decoded->size = MAXALIGN(out - (char *) decoded);
2115  decoded->size);
2116 
2117  return true;
2118 
2119 shortdata_err:
2120  report_invalid_record(state,
2121  "record with invalid length at %X/%X",
2122  LSN_FORMAT_ARGS(state->ReadRecPtr));
2123 err:
2124  *errormsg = state->errormsg_buf;
2125 
2126  return false;
2127 }
int remaining
Definition: informix.c:667
BlockNumber blkno
Definition: xlogreader.h:79
#define BKPIMAGE_HAS_HOLE
Definition: xlogrecord.h:146
struct DecodedXLogRecord * next
Definition: xlogreader.h:138
uint32 TransactionId
Definition: c.h:587
TransactionId toplevel_xid
Definition: xlogreader.h:145
#define XLR_BLOCK_ID_DATA_LONG
Definition: xlogrecord.h:224
uint16 hole_offset
Definition: xlogreader.h:91
unsigned char uint8
Definition: c.h:439
#define InvalidBuffer
Definition: buf.h:25
uint16 RepOriginId
Definition: xlogdefs.h:65
static void report_invalid_record(XLogReaderState *state, const char *fmt,...) pg_attribute_printf(2
Definition: xlogreader.c:63
uint32 BlockNumber
Definition: block.h:31
uint16 bimg_len
Definition: xlogreader.h:93
uint32 main_data_len
Definition: xlogreader.h:147
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
unsigned short uint16
Definition: c.h:440
uint16 hole_length
Definition: xlogreader.h:92
#define XLR_BLOCK_ID_TOPLEVEL_XID
Definition: xlogrecord.h:226
uint32 xl_tot_len
Definition: xlogrecord.h:43
Buffer recent_buffer
Definition: xlogreader.h:82
#define BKPIMAGE_APPLY
Definition: xlogrecord.h:148
XLogRecPtr ReadRecPtr
Definition: xlogreader.h:178
#define COPY_HEADER_FIELD(_dst, _size)
#define InvalidTransactionId
Definition: transam.h:31
unsigned int uint32
Definition: c.h:441
XLogRecPtr lsn
Definition: xlogreader.h:141
RepOriginId record_origin
Definition: xlogreader.h:144
#define XLR_MAX_BLOCK_ID
Definition: xlogrecord.h:221
DecodedBkpBlock blocks[FLEXIBLE_ARRAY_MEMBER]
Definition: xlogreader.h:149
#define SizeOfXLogRecord
Definition: xlogrecord.h:55
#define BKPBLOCK_SAME_REL
Definition: xlogrecord.h:183
#define BKPIMAGE_IS_COMPRESSED
Definition: xlogrecord.h:147
#define BKPBLOCK_HAS_IMAGE
Definition: xlogrecord.h:180
ForkNumber forknum
Definition: xlogreader.h:78
uint16 data_len
Definition: xlogreader.h:99
#define Assert(condition)
Definition: c.h:804
#define XLR_BLOCK_ID_ORIGIN
Definition: xlogrecord.h:225
#define MAXALIGN(LEN)
Definition: c.h:757
static int64 blocks
Definition: pg_checksums.c:35
#define InvalidRepOriginId
Definition: origin.h:33
char * bkp_image
Definition: xlogreader.h:90
#define XLR_BLOCK_ID_DATA_SHORT
Definition: xlogrecord.h:223
size_t DecodeXLogRecordRequiredSpace(size_t xl_tot_len)
Definition: xlogreader.c:1793
#define BKPBLOCK_FORK_MASK
Definition: xlogrecord.h:178
int i
XLogRecord header
Definition: xlogreader.h:143
char * errormsg_buf
Definition: xlogreader.h:291
RelFileNode rnode
Definition: xlogreader.h:77
#define offsetof(type, field)
Definition: c.h:727
#define BKPBLOCK_HAS_DATA
Definition: xlogrecord.h:181

◆ DecodeXLogRecordRequiredSpace()

size_t DecodeXLogRecordRequiredSpace ( size_t  xl_tot_len)

Definition at line 1793 of file xlogreader.c.

References blocks, offsetof, and XLR_MAX_BLOCK_ID.

Referenced by DecodeXLogRecord(), XLogInsertRecord(), and XLogReadRecordAlloc().

1794 {
1795  size_t size = 0;
1796 
1797  /* Account for the fixed size part of the decoded record struct. */
1798  size += offsetof(DecodedXLogRecord, blocks[0]);
1799  /* Account for the flexible blocks array of maximum possible size. */
1800  size += sizeof(DecodedBkpBlock) * (XLR_MAX_BLOCK_ID + 1);
1801  /* Account for all the raw main and block data. */
1802  size += xl_tot_len;
1803  /* We might insert padding before main_data. */
1804  size += (MAXIMUM_ALIGNOF - 1);
1805  /* We might insert padding before each block's data. */
1806  size += (MAXIMUM_ALIGNOF - 1) * (XLR_MAX_BLOCK_ID + 1);
1807  /* We might insert padding at the end. */
1808  size += (MAXIMUM_ALIGNOF - 1);
1809 
1810  return size;
1811 }
#define XLR_MAX_BLOCK_ID
Definition: xlogrecord.h:221
static int64 blocks
Definition: pg_checksums.c:35
#define offsetof(type, field)
Definition: c.h:727

◆ RestoreBlockImage()

bool RestoreBlockImage ( XLogReaderState record,
uint8  block_id,
char *  page 
)

Definition at line 2203 of file xlogreader.c.

References DecodedBkpBlock::bimg_info, DecodedBkpBlock::bimg_len, DecodedBkpBlock::bkp_image, BKPIMAGE_IS_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 checkXLogConsistency(), and XLogReadBufferForRedoExtended().

2204 {
2205  DecodedBkpBlock *bkpb;
2206  char *ptr;
2207  PGAlignedBlock tmp;
2208 
2209  if (block_id > record->record->max_block_id ||
2210  !record->record->blocks[block_id].in_use)
2211  return false;
2212  if (!record->record->blocks[block_id].has_image)
2213  return false;
2214 
2215  bkpb = &record->record->blocks[block_id];
2216  ptr = bkpb->bkp_image;
2217 
2218  if (bkpb->bimg_info & BKPIMAGE_IS_COMPRESSED)
2219  {
2220  /* If a backup block image is compressed, decompress it */
2221  if (pglz_decompress(ptr, bkpb->bimg_len, tmp.data,
2222  BLCKSZ - bkpb->hole_length, true) < 0)
2223  {
2224  report_invalid_record(record, "invalid compressed image at %X/%X, block %d",
2225  LSN_FORMAT_ARGS(record->ReadRecPtr),
2226  block_id);
2227  return false;
2228  }
2229  ptr = tmp.data;
2230  }
2231 
2232  /* generate page, taking into account hole if necessary */
2233  if (bkpb->hole_length == 0)
2234  {
2235  memcpy(page, ptr, BLCKSZ);
2236  }
2237  else
2238  {
2239  memcpy(page, ptr, bkpb->hole_offset);
2240  /* must zero-fill the hole */
2241  MemSet(page + bkpb->hole_offset, 0, bkpb->hole_length);
2242  memcpy(page + (bkpb->hole_offset + bkpb->hole_length),
2243  ptr + bkpb->hole_offset,
2244  BLCKSZ - (bkpb->hole_offset + bkpb->hole_length));
2245  }
2246 
2247  return true;
2248 }
uint16 hole_offset
Definition: xlogreader.h:91
static void report_invalid_record(XLogReaderState *state, const char *fmt,...) pg_attribute_printf(2
Definition: xlogreader.c:63
#define MemSet(start, val, len)
Definition: c.h:1008
uint16 bimg_len
Definition: xlogreader.h:93
int32 pglz_decompress(const char *source, int32 slen, char *dest, int32 rawsize, bool check_complete)
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
char data[BLCKSZ]
Definition: c.h:1141
uint16 hole_length
Definition: xlogreader.h:92
XLogRecPtr ReadRecPtr
Definition: xlogreader.h:178
DecodedBkpBlock blocks[FLEXIBLE_ARRAY_MEMBER]
Definition: xlogreader.h:149
#define BKPIMAGE_IS_COMPRESSED
Definition: xlogrecord.h:147
DecodedXLogRecord * record
Definition: xlogreader.h:214
char * bkp_image
Definition: xlogreader.h:90

◆ WALRead()

bool WALRead ( XLogReaderState state,
WALSegmentOpenCB  segopenfn,
WALSegmentCloseCB  sgclosefn,
char *  buf,
XLogRecPtr  startptr,
Size  count,
TimeLineID  tli,
WALReadError errinfo 
)

Definition at line 1665 of file xlogreader.c.

References Assert, buf, pg_pread(), pgstat_report_wait_end(), pgstat_report_wait_start(), XLogReaderState::seg, XLogReaderState::segcxt, startptr, WAIT_EVENT_WAL_READ, WALReadError::wre_errno, WALReadError::wre_off, WALReadError::wre_read, WALReadError::wre_req, WALReadError::wre_seg, WALOpenSegment::ws_file, WALOpenSegment::ws_segno, WALSegmentContext::ws_segsize, WALOpenSegment::ws_tli, XLByteInSeg, XLByteToSeg, and XLogSegmentOffset.

Referenced by logical_read_xlog_page(), read_local_xlog_page(), WALDumpReadPage(), and XLogSendPhysical().

1669 {
1670  char *p;
1671  XLogRecPtr recptr;
1672  Size nbytes;
1673 
1674  p = buf;
1675  recptr = startptr;
1676  nbytes = count;
1677 
1678  while (nbytes > 0)
1679  {
1680  uint32 startoff;
1681  int segbytes;
1682  int readbytes;
1683 
1684  startoff = XLogSegmentOffset(recptr, state->segcxt.ws_segsize);
1685 
1686  /*
1687  * If the data we want is not in a segment we have open, close what we
1688  * have (if anything) and open the next one, using the caller's
1689  * provided openSegment callback.
1690  */
1691  if (state->seg.ws_file < 0 ||
1692  !XLByteInSeg(recptr, state->seg.ws_segno, state->segcxt.ws_segsize) ||
1693  tli != state->seg.ws_tli)
1694  {
1695  XLogSegNo nextSegNo;
1696 
1697  if (state->seg.ws_file >= 0)
1698  segclosefn(state);
1699 
1700  XLByteToSeg(recptr, nextSegNo, state->segcxt.ws_segsize);
1701  segopenfn(state, nextSegNo, &tli);
1702 
1703  /* This shouldn't happen -- indicates a bug in segment_open */
1704  Assert(state->seg.ws_file >= 0);
1705 
1706  /* Update the current segment info. */
1707  state->seg.ws_tli = tli;
1708  state->seg.ws_segno = nextSegNo;
1709  }
1710 
1711  /* How many bytes are within this segment? */
1712  if (nbytes > (state->segcxt.ws_segsize - startoff))
1713  segbytes = state->segcxt.ws_segsize - startoff;
1714  else
1715  segbytes = nbytes;
1716 
1717 #ifndef FRONTEND
1719 #endif
1720 
1721  /* Reset errno first; eases reporting non-errno-affecting errors */
1722  errno = 0;
1723  readbytes = pg_pread(state->seg.ws_file, p, segbytes, (off_t) startoff);
1724 
1725 #ifndef FRONTEND
1727 #endif
1728 
1729  if (readbytes <= 0)
1730  {
1731  errinfo->wre_errno = errno;
1732  errinfo->wre_req = segbytes;
1733  errinfo->wre_read = readbytes;
1734  errinfo->wre_off = startoff;
1735  errinfo->wre_seg = state->seg;
1736  return false;
1737  }
1738 
1739  /* Update state for read */
1740  recptr += readbytes;
1741  nbytes -= readbytes;
1742  p += readbytes;
1743  }
1744 
1745  return true;
1746 }
WALOpenSegment wre_seg
Definition: xlogreader.h:358
static void pgstat_report_wait_end(void)
Definition: wait_event.h:277
ssize_t pg_pread(int fd, void *buf, size_t nbyte, off_t offset)
Definition: pread.c:27
#define XLByteInSeg(xlrp, logSegNo, wal_segsz_bytes)
WALOpenSegment seg
Definition: xlogreader.h:243
static char * buf
Definition: pg_test_fsync.c:68
uint64 XLogSegNo
Definition: xlogdefs.h:48
XLogSegNo ws_segno
Definition: xlogreader.h:48
unsigned int uint32
Definition: c.h:441
static void pgstat_report_wait_start(uint32 wait_event_info)
Definition: wait_event.h:261
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:804
size_t Size
Definition: c.h:540
TimeLineID ws_tli
Definition: xlogreader.h:49
WALSegmentContext segcxt
Definition: xlogreader.h:242
static XLogRecPtr startptr
Definition: basebackup.c:116
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)

◆ XLogBeginRead()

void XLogBeginRead ( XLogReaderState state,
XLogRecPtr  RecPtr 
)

Definition at line 252 of file xlogreader.c.

References Assert, XLogReaderState::DecodeRecPtr, XLogReaderState::EndRecPtr, InvalidXLogRecPtr, XLogReaderState::NextRecPtr, XLogReaderState::readRecordState, XLogReaderState::ReadRecPtr, ResetDecoder(), XLogRecPtrIsInvalid, and XLREAD_NEXT_RECORD.

Referenced by DecodingContextFindStartpoint(), extractPageMap(), findLastCheckpoint(), pg_logical_replication_slot_advance(), pg_logical_slot_get_changes_guts(), ReadCheckpointRecord(), readOneRecord(), StartLogicalReplication(), StartupXLOG(), XLogReaderSetInputData(), XLogReaderValidatePageHeader(), and XlogReadTwoPhaseData().

253 {
254  Assert(!XLogRecPtrIsInvalid(RecPtr));
255 
256  ResetDecoder(state);
257 
258  /* Begin at the passed-in record pointer. */
259  state->EndRecPtr = RecPtr;
260  state->NextRecPtr = RecPtr;
261  state->ReadRecPtr = InvalidXLogRecPtr;
264 }
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
XLogRecPtr NextRecPtr
Definition: xlogreader.h:210
XLogRecPtr EndRecPtr
Definition: xlogreader.h:179
XLogRecPtr ReadRecPtr
Definition: xlogreader.h:178
XLogRecPtr DecodeRecPtr
Definition: xlogreader.h:209
#define XLogRecPtrIsInvalid(r)
Definition: xlogdefs.h:29
#define Assert(condition)
Definition: c.h:804
XLogReadRecordState readRecordState
Definition: xlogreader.h:282
static void ResetDecoder(XLogReaderState *state)
Definition: xlogreader.c:1758

◆ XLogNextRecord()

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

Definition at line 397 of file xlogreader.c.

References Assert, XLogReaderState::decode_queue_tail, XLogReaderState::DecodeRecPtr, XLogReaderState::EndRecPtr, XLogReaderState::errormsg_buf, XLogReaderState::errormsg_deferred, DecodedXLogRecord::lsn, DecodedXLogRecord::next_lsn, XLogReaderState::ReadRecPtr, XLogReaderState::record, SizeOfXLogLongPHD, SizeOfXLogShortPHD, XLogDecodeOneRecord(), XLogReleasePreviousRecord(), XLREAD_FAIL, XLREAD_FULL, XLREAD_NEED_DATA, and XLREAD_SUCCESS.

Referenced by XLogReaderSetInputData(), and XLogReadRecord().

400 {
401  /* Release the space occupied by the last record we returned. */
402  if (state->record)
404 
405  for (;;)
406  {
407  XLogReadRecordResult result;
408 
409  /* We can now return the oldest item in the queue, if there is one. */
410  if (state->decode_queue_tail)
411  {
412  /*
413  * Record this as the most recent record returned, so that we'll
414  * release it next time. This also exposes it to the
415  * XLogRecXXX(decoder) macros, which pass in the decoder rather
416  * than the record for historical reasons.
417  */
418  state->record = state->decode_queue_tail;
419 
420  /*
421  * It should be immediately after the last the record returned by
422  * XLogReadRecord(), or at the position set by XLogBeginRead() if
423  * XLogReadRecord() hasn't been called yet. It may be after a
424  * page header, though.
425  */
426  Assert(state->record->lsn == state->EndRecPtr ||
427  (state->EndRecPtr % XLOG_BLCKSZ == 0 &&
428  (state->record->lsn == state->EndRecPtr + SizeOfXLogShortPHD ||
429  state->record->lsn == state->EndRecPtr + SizeOfXLogLongPHD)));
430 
431  /*
432  * Set ReadRecPtr and EndRecPtr to correspond to that
433  * record.
434  *
435  * Calling code could access these through the returned decoded
436  * record, but for now we'll update them directly here, for the
437  * benefit of all the existing code that accesses these variables
438  * directly.
439  */
440  state->ReadRecPtr = state->record->lsn;
441  state->EndRecPtr = state->record->next_lsn;
442 
443  *errormsg = NULL;
444  *record = state->record;
445 
446  return XLREAD_SUCCESS;
447  }
448  else if (state->errormsg_deferred)
449  {
450  /*
451  * If we've run out of records, but we have a deferred error, now
452  * is the time to report it.
453  */
454  state->errormsg_deferred = false;
455  if (state->errormsg_buf[0] != '\0')
456  *errormsg = state->errormsg_buf;
457  else
458  *errormsg = NULL;
459  *record = NULL;
460  state->EndRecPtr = state->DecodeRecPtr;
461 
462  return XLREAD_FAIL;
463  }
464 
465  /* We need to get a decoded record into our queue first. */
466  result = XLogDecodeOneRecord(state, true /* allow_oversized */ );
467  switch(result)
468  {
469  case XLREAD_NEED_DATA:
470  *errormsg = NULL;
471  *record = NULL;
472  return result;
473  case XLREAD_SUCCESS:
474  Assert(state->decode_queue_tail != NULL);
475  break;
476  case XLREAD_FULL:
477  /* Not expected because we passed allow_oversized = true */
478  Assert(false);
479  break;
480  case XLREAD_FAIL:
481  /*
482  * If that produced neither a queued record nor a queued error,
483  * then we're at the end (for example, archive recovery with no
484  * more files available).
485  */
486  Assert(state->decode_queue_tail == NULL);
487  if (!state->errormsg_deferred)
488  {
489  state->EndRecPtr = state->DecodeRecPtr;
490  *errormsg = NULL;
491  *record = NULL;
492  return result;
493  }
494  break;
495  }
496  }
497 
498  /* unreachable */
499  return XLREAD_FAIL;
500 }
DecodedXLogRecord * decode_queue_tail
Definition: xlogreader.h:239
XLogRecPtr next_lsn
Definition: xlogreader.h:142
static void XLogReleasePreviousRecord(XLogReaderState *state)
Definition: xlogreader.c:271
XLogReadRecordResult
Definition: xlogreader.h:104
XLogRecPtr EndRecPtr
Definition: xlogreader.h:179
XLogRecPtr ReadRecPtr
Definition: xlogreader.h:178
XLogRecPtr DecodeRecPtr
Definition: xlogreader.h:209
XLogRecPtr lsn
Definition: xlogreader.h:141
bool errormsg_deferred
Definition: xlogreader.h:292
DecodedXLogRecord * record
Definition: xlogreader.h:214
#define Assert(condition)
Definition: c.h:804
#define SizeOfXLogShortPHD
Definition: xlog_internal.h:52
static XLogReadRecordResult XLogDecodeOneRecord(XLogReaderState *state, bool allow_oversized)
Definition: xlogreader.c:657
char * errormsg_buf
Definition: xlogreader.h:291
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:69

◆ XLogReadAhead()

XLogReadRecordResult XLogReadAhead ( XLogReaderState state,
DecodedXLogRecord **  record,
char **  errormsg 
)

Definition at line 511 of file xlogreader.c.

References Assert, XLogReaderState::decode_queue_head, XLogReaderState::errormsg_buf, XLogReaderState::errormsg_deferred, unlikely, XLogDecodeOneRecord(), XLREAD_FAIL, XLREAD_FULL, XLREAD_NEED_DATA, and XLREAD_SUCCESS.

Referenced by XLogPrefetcherScanRecords(), and XLogReaderSetInputData().

512 {
513  XLogReadRecordResult result;
514 
515  /* We stop trying after encountering an error. */
516  if (unlikely(state->errormsg_deferred))
517  {
518  /* We only report the error message the first time, see below. */
519  *errormsg = NULL;
520  return XLREAD_FAIL;
521  }
522 
523  /*
524  * Try to decode one more record, if we have space. Pass allow_oversized
525  * = false, so that this call returns fast if the decode buffer is full.
526  */
527  result = XLogDecodeOneRecord(state, false);
528  switch (result)
529  {
530  case XLREAD_SUCCESS:
531  /* New record at head of decode record queue. */
532  Assert(state->decode_queue_head != NULL);
533  *record = state->decode_queue_head;
534  return result;
535  case XLREAD_FULL:
536  /* No space in circular decode buffer. */
537  return result;
538  case XLREAD_NEED_DATA:
539  /* The caller needs to insert more data. */
540  return result;
541  case XLREAD_FAIL:
542  /* Report the error. XLogReadRecord() will also report it. */
543  Assert(state->errormsg_deferred);
544  if (state->errormsg_buf[0] != '\0')
545  *errormsg = state->errormsg_buf;
546  return result;
547  }
548 
549  /* Unreachable. */
550  return XLREAD_FAIL;
551 }
XLogReadRecordResult
Definition: xlogreader.h:104
bool errormsg_deferred
Definition: xlogreader.h:292
#define Assert(condition)
Definition: c.h:804
static XLogReadRecordResult XLogDecodeOneRecord(XLogReaderState *state, bool allow_oversized)
Definition: xlogreader.c:657
#define unlikely(x)
Definition: c.h:273
char * errormsg_buf
Definition: xlogreader.h:291
DecodedXLogRecord * decode_queue_head
Definition: xlogreader.h:238

◆ XLogReaderAllocate()

XLogReaderState* XLogReaderAllocate ( int  wal_segment_size,
const char *  waldir,
WALSegmentCleanupCB  cleanup_cb 
)

Definition at line 82 of file xlogreader.c.

References allocate_recordbuf(), XLogReaderState::cleanup_cb, XLogReaderState::errormsg_buf, MAX_ERRORMSG_LEN, MCXT_ALLOC_NO_OOM, MCXT_ALLOC_ZERO, palloc_extended(), pfree(), XLogReaderState::readBuf, XLogReaderState::seg, XLogReaderState::segcxt, and WALOpenSegmentInit().

Referenced by extractPageMap(), findLastCheckpoint(), main(), readOneRecord(), StartReplication(), StartupDecodingContext(), StartupXLOG(), XLogInsertRecord(), XLogReaderSetInputData(), and XlogReadTwoPhaseData().

84 {
86 
87  state = (XLogReaderState *)
90  if (!state)
91  return NULL;
92 
93  /* initialize caller-provided support functions */
94  state->cleanup_cb = cleanup_cb;
95 
96  /*
97  * Permanently allocate readBuf. We do it this way, rather than just
98  * making a static array, for two reasons: (1) no need to waste the
99  * storage in most instantiations of the backend; (2) a static char array
100  * isn't guaranteed to have any particular alignment, whereas
101  * palloc_extended() will provide MAXALIGN'd storage.
102  */
103  state->readBuf = (char *) palloc_extended(XLOG_BLCKSZ,
105  if (!state->readBuf)
106  {
107  pfree(state);
108  return NULL;
109  }
110 
111  /* Initialize segment info. */
112  WALOpenSegmentInit(&state->seg, &state->segcxt, wal_segment_size,
113  waldir);
114 
115  /* ReadRecPtr, EndRecPtr, reqLen and readLen initialized to zeroes above */
118  if (!state->errormsg_buf)
119  {
120  pfree(state->readBuf);
121  pfree(state);
122  return NULL;
123  }
124  state->errormsg_buf[0] = '\0';
125 
126  /*
127  * Allocate an initial readRecordBuf of minimal size, which can later be
128  * enlarged if necessary.
129  */
130  if (!allocate_recordbuf(state, 0))
131  {
132  pfree(state->errormsg_buf);
133  pfree(state->readBuf);
134  pfree(state);
135  return NULL;
136  }
137 
138  return state;
139 }
static void WALOpenSegmentInit(WALOpenSegment *seg, WALSegmentContext *segcxt, int segsize, const char *waldir)
Definition: xlogreader.c:228
int wal_segment_size
Definition: xlog.c:121
void * palloc_extended(Size size, int flags)
Definition: mcxt.c:1126
#define MCXT_ALLOC_NO_OOM
Definition: fe_memutils.h:18
#define MAX_ERRORMSG_LEN
Definition: xlogreader.c:54
WALOpenSegment seg
Definition: xlogreader.h:243
void pfree(void *pointer)
Definition: mcxt.c:1169
static void static bool allocate_recordbuf(XLogReaderState *state, uint32 reclength)
Definition: xlogreader.c:185
Definition: regguts.h:317
#define MCXT_ALLOC_ZERO
Definition: fe_memutils.h:19
WALSegmentContext segcxt
Definition: xlogreader.h:242
char * errormsg_buf
Definition: xlogreader.h:291
WALSegmentCleanupCB cleanup_cb
Definition: xlogreader.h:157

◆ XLogReaderFree()

void XLogReaderFree ( XLogReaderState state)

Definition at line 142 of file xlogreader.c.

References XLogReaderState::cleanup_cb, XLogReaderState::decode_buffer, XLogReaderState::errormsg_buf, XLogReaderState::free_decode_buffer, pfree(), XLogReaderState::readBuf, XLogReaderState::readRecordBuf, XLogReaderState::seg, and WALOpenSegment::ws_file.

Referenced by extractPageMap(), findLastCheckpoint(), FreeDecodingContext(), main(), readOneRecord(), StartupXLOG(), XLogReaderSetInputData(), and XlogReadTwoPhaseData().

143 {
144  if (state->seg.ws_file >= 0)
145  state->cleanup_cb(state);
146 
147  if (state->decode_buffer && state->free_decode_buffer)
148  pfree(state->decode_buffer);
149 
150  pfree(state->errormsg_buf);
151  if (state->readRecordBuf)
152  pfree(state->readRecordBuf);
153  pfree(state->readBuf);
154  pfree(state);
155 }
char * decode_buffer
Definition: xlogreader.h:227
char * readRecordBuf
Definition: xlogreader.h:276
WALOpenSegment seg
Definition: xlogreader.h:243
void pfree(void *pointer)
Definition: mcxt.c:1169
bool free_decode_buffer
Definition: xlogreader.h:229
char * errormsg_buf
Definition: xlogreader.h:291
WALSegmentCleanupCB cleanup_cb
Definition: xlogreader.h:157

◆ XLogReaderSetDecodeBuffer()

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

Definition at line 163 of file xlogreader.c.

References Assert, XLogReaderState::decode_buffer, XLogReaderState::decode_buffer_head, XLogReaderState::decode_buffer_size, and XLogReaderState::decode_buffer_tail.

Referenced by StartupXLOG(), and XLogReaderSetInputData().

164 {
165  Assert(state->decode_buffer == NULL);
166 
167  state->decode_buffer = buffer;
168  state->decode_buffer_size = size;
169  state->decode_buffer_head = buffer;
170  state->decode_buffer_tail = buffer;
171 }
char * decode_buffer
Definition: xlogreader.h:227
char * decode_buffer_tail
Definition: xlogreader.h:231
size_t decode_buffer_size
Definition: xlogreader.h:228
char * decode_buffer_head
Definition: xlogreader.h:230
#define Assert(condition)
Definition: c.h:804

◆ XLogReaderSetInputData()

◆ XLogReaderValidatePageHeader()

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

Definition at line 1370 of file xlogreader.c.

References Assert, XLogFindNextRecordState::currRecPtr, header(), InvalidXLogRecPtr, XLogReaderState::latestPagePtr, XLogReaderState::latestPageTLI, LSN_FORMAT_ARGS, MAXALIGN, MAXFNAMELEN, MCXT_ALLOC_NO_OOM, MCXT_ALLOC_ZERO, XLogReaderState::page_verified, palloc_extended(), XLogReaderState::readBuf, XLogFindNextRecordState::reader_state, XLogReaderState::readLen, XLogReaderState::ReadRecPtr, report_invalid_record(), XLogReaderState::seg, XLogReaderState::segcxt, XLogReaderState::system_identifier, XLogFindNextRecordState::targetRecPtr, WALSegmentContext::ws_segsize, WALOpenSegment::ws_tli, XLByteToSeg, XLOG_PAGE_MAGIC, XLogBeginRead(), XLogFileName, XLogNeedData(), XLogPageHeaderSize, XLogReaderInvalReadState(), XLogReadRecord(), XLogRecPtrIsInvalid, XLogSegmentOffset, XLogSegNoOffsetToRecPtr, XLP_ALL_FLAGS, XLP_FIRST_IS_CONTRECORD, XLogPageHeaderData::xlp_info, XLP_LONG_HEADER, XLogPageHeaderData::xlp_magic, XLogPageHeaderData::xlp_pageaddr, XLogPageHeaderData::xlp_rem_len, XLogLongPageHeaderData::xlp_seg_size, XLogLongPageHeaderData::xlp_sysid, XLogPageHeaderData::xlp_tli, XLogLongPageHeaderData::xlp_xlog_blcksz, XLREAD_FAIL, and XLREAD_NEED_DATA.

Referenced by XLogNeedData(), XLogPageRead(), and XLogReaderSetInputData().

1372 {
1373  XLogRecPtr recaddr;
1374  XLogSegNo segno;
1375  int32 offset;
1376  XLogPageHeader hdr = (XLogPageHeader) phdr;
1377 
1378  Assert((recptr % XLOG_BLCKSZ) == 0);
1379 
1380  XLByteToSeg(recptr, segno, state->segcxt.ws_segsize);
1381  offset = XLogSegmentOffset(recptr, state->segcxt.ws_segsize);
1382 
1383  XLogSegNoOffsetToRecPtr(segno, offset, state->segcxt.ws_segsize, recaddr);
1384 
1385  if (hdr->xlp_magic != XLOG_PAGE_MAGIC)
1386  {
1387  char fname[MAXFNAMELEN];
1388 
1389  XLogFileName(fname, state->seg.ws_tli, segno, state->segcxt.ws_segsize);
1390 
1391  report_invalid_record(state,
1392  "invalid magic number %04X in log segment %s, offset %u",
1393  hdr->xlp_magic,
1394  fname,
1395  offset);
1396  return false;
1397  }
1398 
1399  if ((hdr->xlp_info & ~XLP_ALL_FLAGS) != 0)
1400  {
1401  char fname[MAXFNAMELEN];
1402 
1403  XLogFileName(fname, state->seg.ws_tli, segno, state->segcxt.ws_segsize);
1404 
1405  report_invalid_record(state,
1406  "invalid info bits %04X in log segment %s, offset %u",
1407  hdr->xlp_info,
1408  fname,
1409  offset);
1410  return false;
1411  }
1412 
1413  if (hdr->xlp_info & XLP_LONG_HEADER)
1414  {
1415  XLogLongPageHeader longhdr = (XLogLongPageHeader) hdr;
1416 
1417  if (state->system_identifier &&
1418  longhdr->xlp_sysid != state->system_identifier)
1419  {
1420  report_invalid_record(state,
1421  "WAL file is from different database system: WAL file database system identifier is %llu, pg_control database system identifier is %llu",
1422  (unsigned long long) longhdr->xlp_sysid,
1423  (unsigned long long) state->system_identifier);
1424  return false;
1425  }
1426  else if (longhdr->xlp_seg_size != state->segcxt.ws_segsize)
1427  {
1428  report_invalid_record(state,
1429  "WAL file is from different database system: incorrect segment size in page header");
1430  return false;
1431  }
1432  else if (longhdr->xlp_xlog_blcksz != XLOG_BLCKSZ)
1433  {
1434  report_invalid_record(state,
1435  "WAL file is from different database system: incorrect XLOG_BLCKSZ in page header");
1436  return false;
1437  }
1438  }
1439  else if (offset == 0)
1440  {
1441  char fname[MAXFNAMELEN];
1442 
1443  XLogFileName(fname, state->seg.ws_tli, segno, state->segcxt.ws_segsize);
1444 
1445  /* hmm, first page of file doesn't have a long header? */
1446  report_invalid_record(state,
1447  "invalid info bits %04X in log segment %s, offset %u",
1448  hdr->xlp_info,
1449  fname,
1450  offset);
1451  return false;
1452  }
1453 
1454  /*
1455  * Check that the address on the page agrees with what we expected. This
1456  * check typically fails when an old WAL segment is recycled, and hasn't
1457  * yet been overwritten with new data yet.
1458  */
1459  if (hdr->xlp_pageaddr != recaddr)
1460  {
1461  char fname[MAXFNAMELEN];
1462 
1463  XLogFileName(fname, state->seg.ws_tli, segno, state->segcxt.ws_segsize);
1464 
1465  report_invalid_record(state,
1466  "unexpected pageaddr %X/%X in log segment %s, offset %u",
1468  fname,
1469  offset);
1470  return false;
1471  }
1472 
1473  /*
1474  * Since child timelines are always assigned a TLI greater than their
1475  * immediate parent's TLI, we should never see TLI go backwards across
1476  * successive pages of a consistent WAL sequence.
1477  *
1478  * Sometimes we re-read a segment that's already been (partially) read. So
1479  * we only verify TLIs for pages that are later than the last remembered
1480  * LSN.
1481  */
1482  if (recptr > state->latestPagePtr)
1483  {
1484  if (hdr->xlp_tli < state->latestPageTLI)
1485  {
1486  char fname[MAXFNAMELEN];
1487 
1488  XLogFileName(fname, state->seg.ws_tli, segno, state->segcxt.ws_segsize);
1489 
1490  report_invalid_record(state,
1491  "out-of-sequence timeline ID %u (after %u) in log segment %s, offset %u",
1492  hdr->xlp_tli,
1493  state->latestPageTLI,
1494  fname,
1495  offset);
1496  return false;
1497  }
1498  }
1499  state->latestPagePtr = recptr;
1500  state->latestPageTLI = hdr->xlp_tli;
1501 
1502  return true;
1503 }
static void report_invalid_record(XLogReaderState *state, const char *fmt,...) pg_attribute_printf(2
Definition: xlogreader.c:63
XLogPageHeaderData * XLogPageHeader
Definition: xlog_internal.h:54
signed int int32
Definition: c.h:429
XLogLongPageHeaderData * XLogLongPageHeader
Definition: xlog_internal.h:71
WALOpenSegment seg
Definition: xlogreader.h:243
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
XLogRecPtr latestPagePtr
Definition: xlogreader.h:250
#define XLOG_PAGE_MAGIC
Definition: xlog_internal.h:34
uint64 XLogSegNo
Definition: xlogdefs.h:48
TimeLineID xlp_tli
Definition: xlog_internal.h:40
XLogRecPtr xlp_pageaddr
Definition: xlog_internal.h:41
#define MAXFNAMELEN
#define XLogSegmentOffset(xlogptr, wal_segsz_bytes)
#define XLP_ALL_FLAGS
Definition: xlog_internal.h:80
#define XLogSegNoOffsetToRecPtr(segno, offset, wal_segsz_bytes, dest)
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:804
#define XLP_LONG_HEADER
Definition: xlog_internal.h:76
#define XLogFileName(fname, tli, logSegNo, wal_segsz_bytes)
TimeLineID ws_tli
Definition: xlogreader.h:49
uint64 system_identifier
Definition: xlogreader.h:168
WALSegmentContext segcxt
Definition: xlogreader.h:242
TimeLineID latestPageTLI
Definition: xlogreader.h:251
#define XLByteToSeg(xlrp, logSegNo, wal_segsz_bytes)

◆ XLogReadRecord()

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

Definition at line 346 of file xlogreader.c.

References DecodedXLogRecord::header, XLogNextRecord(), and XLREAD_SUCCESS.

Referenced by DecodingContextFindStartpoint(), extractPageMap(), findLastCheckpoint(), main(), pg_logical_replication_slot_advance(), pg_logical_slot_get_changes_guts(), readOneRecord(), ReadRecord(), XLogReaderSetInputData(), XLogReaderValidatePageHeader(), XlogReadTwoPhaseData(), and XLogSendLogical().

347 {
348  XLogReadRecordResult result;
349  DecodedXLogRecord *decoded;
350 
351  /* Consume the next decoded record. */
352  result = XLogNextRecord(state, &decoded, errormsg);
353  if (result == XLREAD_SUCCESS)
354  {
355  /*
356  * The traditional interface just returns the header, not the decoded
357  * record. The caller will access the decoded record through the
358  * XLogRecGetXXX() macros.
359  */
360  *record = &decoded->header;
361  }
362  else
363  *record = NULL;
364  return result;
365 }
XLogReadRecordResult
Definition: xlogreader.h:104
XLogReadRecordResult XLogNextRecord(XLogReaderState *state, DecodedXLogRecord **record, char **errormsg)
Definition: xlogreader.c:397
XLogRecord header
Definition: xlogreader.h:143

◆ XLogRecGetBlockData()

char* XLogRecGetBlockData ( XLogReaderState record,
uint8  block_id,
Size len 
)

Definition at line 2173 of file xlogreader.c.

References DecodedXLogRecord::blocks, DecodedBkpBlock::data, DecodedBkpBlock::data_len, DecodedBkpBlock::has_data, DecodedBkpBlock::in_use, 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(), heap_xlog_freeze_page(), heap_xlog_inplace(), heap_xlog_insert(), heap_xlog_multi_insert(), heap_xlog_prune(), heap_xlog_update(), and heap_xlog_vacuum().

2174 {
2175  DecodedBkpBlock *bkpb;
2176 
2177  if (block_id > record->record->max_block_id ||
2178  !record->record->blocks[block_id].in_use)
2179  return NULL;
2180 
2181  bkpb = &record->record->blocks[block_id];
2182 
2183  if (!bkpb->has_data)
2184  {
2185  if (len)
2186  *len = 0;
2187  return NULL;
2188  }
2189  else
2190  {
2191  if (len)
2192  *len = bkpb->data_len;
2193  return bkpb->data;
2194  }
2195 }
DecodedBkpBlock blocks[FLEXIBLE_ARRAY_MEMBER]
Definition: xlogreader.h:149
DecodedXLogRecord * record
Definition: xlogreader.h:214
uint16 data_len
Definition: xlogreader.h:99

◆ XLogRecGetBlockTag()

◆ XLogRecGetFullXid()

FullTransactionId XLogRecGetFullXid ( XLogReaderState record)

Definition at line 2256 of file xlogreader.c.

References AmStartupProcess, Assert, epoch, EpochFromFullTransactionId, FullTransactionIdFromEpochAndXid(), IsUnderPostmaster, VariableCacheData::nextXid, ShmemVariableCache, unlikely, XidFromFullTransactionId, and XLogRecGetXid.

2257 {
2258  TransactionId xid,
2259  next_xid;
2260  uint32 epoch;
2261 
2262  /*
2263  * This function is only safe during replay, because it depends on the
2264  * replay state. See AdvanceNextFullTransactionIdPastXid() for more.
2265  */
2267 
2268  xid = XLogRecGetXid(record);
2271 
2272  /*
2273  * If xid is numerically greater than next_xid, it has to be from the last
2274  * epoch.
2275  */
2276  if (unlikely(xid > next_xid))
2277  --epoch;
2278 
2279  return FullTransactionIdFromEpochAndXid(epoch, xid);
2280 }
#define AmStartupProcess()
Definition: miscadmin.h:433
uint32 TransactionId
Definition: c.h:587
FullTransactionId nextXid
Definition: transam.h:213
#define XidFromFullTransactionId(x)
Definition: transam.h:48
bool IsUnderPostmaster
Definition: globals.c:112
VariableCache ShmemVariableCache
Definition: varsup.c:34
unsigned int uint32
Definition: c.h:441
#define XLogRecGetXid(decoder)
Definition: xlogreader.h:379
#define EpochFromFullTransactionId(x)
Definition: transam.h:47
#define Assert(condition)
Definition: c.h:804
static FullTransactionId FullTransactionIdFromEpochAndXid(uint32 epoch, TransactionId xid)
Definition: transam.h:71
static const unsigned __int64 epoch
Definition: gettimeofday.c:34
#define unlikely(x)
Definition: c.h:273

◆ XLogRecGetRecentBuffer()

bool XLogRecGetRecentBuffer ( XLogReaderState record,
uint8  block_id,
RelFileNode rnode,
ForkNumber forknum,
BlockNumber blknum,
Buffer recent_buffer 
)

Definition at line 2145 of file xlogreader.c.

References DecodedBkpBlock::blkno, DecodedXLogRecord::blocks, DecodedBkpBlock::forknum, DecodedBkpBlock::in_use, DecodedXLogRecord::max_block_id, DecodedBkpBlock::recent_buffer, XLogReaderState::record, and DecodedBkpBlock::rnode.

Referenced by XLogReadBufferForRedoExtended(), and XLogRecGetBlockTag().

2148 {
2149  DecodedBkpBlock *bkpb;
2150 
2151  if (block_id > record->record->max_block_id ||
2152  !record->record->blocks[block_id].in_use)
2153  return false;
2154 
2155  bkpb = &record->record->blocks[block_id];
2156  if (rnode)
2157  *rnode = bkpb->rnode;
2158  if (forknum)
2159  *forknum = bkpb->forknum;
2160  if (blknum)
2161  *blknum = bkpb->blkno;
2162  if (recent_buffer)
2163  *recent_buffer = bkpb->recent_buffer;
2164  return true;
2165 }
BlockNumber blkno
Definition: xlogreader.h:79
Buffer recent_buffer
Definition: xlogreader.h:82
DecodedBkpBlock blocks[FLEXIBLE_ARRAY_MEMBER]
Definition: xlogreader.h:149
ForkNumber forknum
Definition: xlogreader.h:78
DecodedXLogRecord * record
Definition: xlogreader.h:214
RelFileNode rnode
Definition: xlogreader.h:77