PostgreSQL Source Code  git master
xloginsert.c File Reference
#include "postgres.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "access/xlog_internal.h"
#include "access/xloginsert.h"
#include "catalog/pg_control.h"
#include "common/pg_lzcompress.h"
#include "executor/instrument.h"
#include "miscadmin.h"
#include "pg_trace.h"
#include "replication/origin.h"
#include "storage/bufmgr.h"
#include "storage/proc.h"
#include "utils/memutils.h"
Include dependency graph for xloginsert.c:

Go to the source code of this file.

Data Structures

struct  registered_buffer
 

Macros

#define LZ4_MAX_BLCKSZ   0
 
#define ZSTD_MAX_BLCKSZ   0
 
#define PGLZ_MAX_BLCKSZ   PGLZ_MAX_OUTPUT(BLCKSZ)
 
#define COMPRESS_BUFSIZE   Max(Max(PGLZ_MAX_BLCKSZ, LZ4_MAX_BLCKSZ), ZSTD_MAX_BLCKSZ)
 
#define SizeOfXlogOrigin   (sizeof(RepOriginId) + sizeof(char))
 
#define SizeOfXLogTransactionId   (sizeof(TransactionId) + sizeof(char))
 
#define HEADER_SCRATCH_SIZE
 

Functions

static XLogRecDataXLogRecordAssemble (RmgrId rmid, uint8 info, XLogRecPtr RedoRecPtr, bool doPageWrites, XLogRecPtr *fpw_lsn, int *num_fpi, bool *topxid_included)
 
static bool XLogCompressBackupBlock (char *page, uint16 hole_offset, uint16 hole_length, char *dest, uint16 *dlen)
 
void XLogBeginInsert (void)
 
void XLogEnsureRecordSpace (int max_block_id, int ndatas)
 
void XLogResetInsertion (void)
 
void XLogRegisterBuffer (uint8 block_id, Buffer buffer, uint8 flags)
 
void XLogRegisterBlock (uint8 block_id, RelFileNode *rnode, ForkNumber forknum, BlockNumber blknum, Page page, uint8 flags)
 
void XLogRegisterData (char *data, int len)
 
void XLogRegisterBufData (uint8 block_id, char *data, int len)
 
void XLogSetRecordFlags (uint8 flags)
 
XLogRecPtr XLogInsert (RmgrId rmid, uint8 info)
 
bool XLogCheckBufferNeedsBackup (Buffer buffer)
 
XLogRecPtr XLogSaveBufferForHint (Buffer buffer, bool buffer_std)
 
XLogRecPtr log_newpage (RelFileNode *rnode, ForkNumber forkNum, BlockNumber blkno, Page page, bool page_std)
 
void log_newpages (RelFileNode *rnode, ForkNumber forkNum, int num_pages, BlockNumber *blknos, Page *pages, bool page_std)
 
XLogRecPtr log_newpage_buffer (Buffer buffer, bool page_std)
 
void log_newpage_range (Relation rel, ForkNumber forkNum, BlockNumber startblk, BlockNumber endblk, bool page_std)
 
void InitXLogInsert (void)
 

Variables

static registered_bufferregistered_buffers
 
static int max_registered_buffers
 
static int max_registered_block_id = 0
 
static XLogRecDatamainrdata_head
 
static XLogRecDatamainrdata_last = (XLogRecData *) &mainrdata_head
 
static uint32 mainrdata_len
 
static uint8 curinsert_flags = 0
 
static XLogRecData hdr_rdt
 
static char * hdr_scratch = NULL
 
static XLogRecDatardatas
 
static int num_rdatas
 
static int max_rdatas
 
static bool begininsert_called = false
 
static MemoryContext xloginsert_cxt
 

Macro Definition Documentation

◆ COMPRESS_BUFSIZE

#define COMPRESS_BUFSIZE   Max(Max(PGLZ_MAX_BLCKSZ, LZ4_MAX_BLCKSZ), ZSTD_MAX_BLCKSZ)

Definition at line 63 of file xloginsert.c.

◆ HEADER_SCRATCH_SIZE

#define HEADER_SCRATCH_SIZE
Value:
MaxSizeOfXLogRecordBlockHeader * (XLR_MAX_BLOCK_ID + 1) + \
#define SizeOfXlogOrigin
Definition: xloginsert.c:117
#define SizeOfXLogTransactionId
Definition: xloginsert.c:118
#define XLR_MAX_BLOCK_ID
Definition: xlogrecord.h:228
#define SizeOfXLogRecordDataHeaderLong
Definition: xlogrecord.h:214
#define SizeOfXLogRecord
Definition: xlogrecord.h:55

Definition at line 120 of file xloginsert.c.

◆ LZ4_MAX_BLCKSZ

#define LZ4_MAX_BLCKSZ   0

Definition at line 51 of file xloginsert.c.

◆ PGLZ_MAX_BLCKSZ

#define PGLZ_MAX_BLCKSZ   PGLZ_MAX_OUTPUT(BLCKSZ)

Definition at line 60 of file xloginsert.c.

◆ SizeOfXlogOrigin

#define SizeOfXlogOrigin   (sizeof(RepOriginId) + sizeof(char))

Definition at line 117 of file xloginsert.c.

◆ SizeOfXLogTransactionId

#define SizeOfXLogTransactionId   (sizeof(TransactionId) + sizeof(char))

Definition at line 118 of file xloginsert.c.

◆ ZSTD_MAX_BLCKSZ

#define ZSTD_MAX_BLCKSZ   0

Definition at line 57 of file xloginsert.c.

Function Documentation

◆ InitXLogInsert()

void InitXLogInsert ( void  )

Definition at line 1284 of file xloginsert.c.

1285 {
1286  /* Initialize the working areas */
1287  if (xloginsert_cxt == NULL)
1288  {
1290  "WAL record construction",
1292  }
1293 
1294  if (registered_buffers == NULL)
1295  {
1298  sizeof(registered_buffer) * (XLR_NORMAL_MAX_BLOCK_ID + 1));
1300  }
1301  if (rdatas == NULL)
1302  {
1304  sizeof(XLogRecData) * XLR_NORMAL_RDATAS);
1306  }
1307 
1308  /*
1309  * Allocate a buffer to hold the header information for a WAL record.
1310  */
1311  if (hdr_scratch == NULL)
1314 }
MemoryContext TopMemoryContext
Definition: mcxt.c:48
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:906
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
#define AllocSetContextCreate
Definition: memutils.h:173
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:197
static int max_registered_buffers
Definition: xloginsert.c:91
static MemoryContext xloginsert_cxt
Definition: xloginsert.c:136
static char * hdr_scratch
Definition: xloginsert.c:115
static XLogRecData * rdatas
Definition: xloginsert.c:129
static registered_buffer * registered_buffers
Definition: xloginsert.c:90
static int max_rdatas
Definition: xloginsert.c:131
#define HEADER_SCRATCH_SIZE
Definition: xloginsert.c:120
#define XLR_NORMAL_MAX_BLOCK_ID
Definition: xloginsert.h:27
#define XLR_NORMAL_RDATAS
Definition: xloginsert.h:28

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, hdr_scratch, HEADER_SCRATCH_SIZE, max_rdatas, max_registered_buffers, MemoryContextAlloc(), MemoryContextAllocZero(), rdatas, registered_buffers, TopMemoryContext, xloginsert_cxt, XLR_NORMAL_MAX_BLOCK_ID, and XLR_NORMAL_RDATAS.

Referenced by BaseInit().

◆ log_newpage()

XLogRecPtr log_newpage ( RelFileNode rnode,
ForkNumber  forkNum,
BlockNumber  blkno,
Page  page,
bool  page_std 
)

Definition at line 1083 of file xloginsert.c.

1085 {
1086  int flags;
1087  XLogRecPtr recptr;
1088 
1089  flags = REGBUF_FORCE_IMAGE;
1090  if (page_std)
1091  flags |= REGBUF_STANDARD;
1092 
1093  XLogBeginInsert();
1094  XLogRegisterBlock(0, rnode, forkNum, blkno, page, flags);
1095  recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI);
1096 
1097  /*
1098  * The page may be uninitialized. If so, we can't set the LSN because that
1099  * would corrupt the page.
1100  */
1101  if (!PageIsNew(page))
1102  {
1103  PageSetLSN(page, recptr);
1104  }
1105 
1106  return recptr;
1107 }
#define PageSetLSN(page, lsn)
Definition: bufpage.h:367
#define PageIsNew(page)
Definition: bufpage.h:228
#define XLOG_FPI
Definition: pg_control.h:78
uint64 XLogRecPtr
Definition: xlogdefs.h:21
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:443
void XLogBeginInsert(void)
Definition: xloginsert.c:150
void XLogRegisterBlock(uint8 block_id, RelFileNode *rnode, ForkNumber forknum, BlockNumber blknum, Page page, uint8 flags)
Definition: xloginsert.c:296
#define REGBUF_STANDARD
Definition: xloginsert.h:34
#define REGBUF_FORCE_IMAGE
Definition: xloginsert.h:31

References PageIsNew, PageSetLSN, REGBUF_FORCE_IMAGE, REGBUF_STANDARD, XLOG_FPI, XLogBeginInsert(), XLogInsert(), and XLogRegisterBlock().

Referenced by _bt_blwritepage(), _hash_alloc_buckets(), _hash_init(), blbuildempty(), btbuildempty(), end_heap_rewrite(), gist_indexsortbuild(), log_newpage_buffer(), raw_heap_insert(), RelationCopyStorage(), and spgbuildempty().

◆ log_newpage_buffer()

XLogRecPtr log_newpage_buffer ( Buffer  buffer,
bool  page_std 
)

Definition at line 1177 of file xloginsert.c.

1178 {
1179  Page page = BufferGetPage(buffer);
1180  RelFileNode rnode;
1181  ForkNumber forkNum;
1182  BlockNumber blkno;
1183 
1184  /* Shared buffers should be modified in a critical section. */
1185  Assert(CritSectionCount > 0);
1186 
1187  BufferGetTag(buffer, &rnode, &forkNum, &blkno);
1188 
1189  return log_newpage(&rnode, forkNum, blkno, page, page_std);
1190 }
uint32 BlockNumber
Definition: block.h:31
void BufferGetTag(Buffer buffer, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum)
Definition: bufmgr.c:2776
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
Pointer Page
Definition: bufpage.h:78
volatile uint32 CritSectionCount
Definition: globals.c:42
Assert(fmt[strlen(fmt) - 1] !='\n')
ForkNumber
Definition: relpath.h:41
XLogRecPtr log_newpage(RelFileNode *rnode, ForkNumber forkNum, BlockNumber blkno, Page page, bool page_std)
Definition: xloginsert.c:1083

References Assert(), BufferGetPage, BufferGetTag(), CritSectionCount, and log_newpage().

Referenced by brin_initialize_empty_new_buffer(), brinbuildempty(), FreeSpaceMapPrepareTruncateRel(), ginbuildempty(), gistbuildempty(), heap_force_common(), lazy_scan_new_or_empty(), RelationCopyStorageUsingBuffer(), and visibilitymap_prepare_truncate().

◆ log_newpage_range()

void log_newpage_range ( Relation  rel,
ForkNumber  forkNum,
BlockNumber  startblk,
BlockNumber  endblk,
bool  page_std 
)

Definition at line 1210 of file xloginsert.c.

1213 {
1214  int flags;
1215  BlockNumber blkno;
1216 
1217  flags = REGBUF_FORCE_IMAGE;
1218  if (page_std)
1219  flags |= REGBUF_STANDARD;
1220 
1221  /*
1222  * Iterate over all the pages in the range. They are collected into
1223  * batches of XLR_MAX_BLOCK_ID pages, and a single WAL-record is written
1224  * for each batch.
1225  */
1227 
1228  blkno = startblk;
1229  while (blkno < endblk)
1230  {
1231  Buffer bufpack[XLR_MAX_BLOCK_ID];
1232  XLogRecPtr recptr;
1233  int nbufs;
1234  int i;
1235 
1237 
1238  /* Collect a batch of blocks. */
1239  nbufs = 0;
1240  while (nbufs < XLR_MAX_BLOCK_ID && blkno < endblk)
1241  {
1242  Buffer buf = ReadBufferExtended(rel, forkNum, blkno,
1243  RBM_NORMAL, NULL);
1244 
1246 
1247  /*
1248  * Completely empty pages are not WAL-logged. Writing a WAL record
1249  * would change the LSN, and we don't want that. We want the page
1250  * to stay empty.
1251  */
1252  if (!PageIsNew(BufferGetPage(buf)))
1253  bufpack[nbufs++] = buf;
1254  else
1256  blkno++;
1257  }
1258 
1259  /* Write WAL record for this batch. */
1260  XLogBeginInsert();
1261 
1263  for (i = 0; i < nbufs; i++)
1264  {
1265  XLogRegisterBuffer(i, bufpack[i], flags);
1266  MarkBufferDirty(bufpack[i]);
1267  }
1268 
1269  recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI);
1270 
1271  for (i = 0; i < nbufs; i++)
1272  {
1273  PageSetLSN(BufferGetPage(bufpack[i]), recptr);
1274  UnlockReleaseBuffer(bufpack[i]);
1275  }
1276  END_CRIT_SECTION();
1277  }
1278 }
int Buffer
Definition: buf.h:23
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3938
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1573
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:4156
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:749
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:98
@ RBM_NORMAL
Definition: bufmgr.h:39
int i
Definition: isn.c:73
#define START_CRIT_SECTION()
Definition: miscadmin.h:148
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:121
#define END_CRIT_SECTION()
Definition: miscadmin.h:150
static char * buf
Definition: pg_test_fsync.c:67
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:243
void XLogEnsureRecordSpace(int max_block_id, int ndatas)
Definition: xloginsert.c:176

References buf, BUFFER_LOCK_EXCLUSIVE, BufferGetPage, CHECK_FOR_INTERRUPTS, END_CRIT_SECTION, i, LockBuffer(), MarkBufferDirty(), PageIsNew, PageSetLSN, RBM_NORMAL, ReadBufferExtended(), REGBUF_FORCE_IMAGE, REGBUF_STANDARD, START_CRIT_SECTION, UnlockReleaseBuffer(), XLOG_FPI, XLogBeginInsert(), XLogEnsureRecordSpace(), XLogInsert(), XLogRegisterBuffer(), and XLR_MAX_BLOCK_ID.

Referenced by ginbuild(), gistbuild(), smgrDoPendingSyncs(), and spgbuild().

◆ log_newpages()

void log_newpages ( RelFileNode rnode,
ForkNumber  forkNum,
int  num_pages,
BlockNumber blknos,
Page pages,
bool  page_std 
)

Definition at line 1115 of file xloginsert.c.

1117 {
1118  int flags;
1119  XLogRecPtr recptr;
1120  int i;
1121  int j;
1122 
1123  flags = REGBUF_FORCE_IMAGE;
1124  if (page_std)
1125  flags |= REGBUF_STANDARD;
1126 
1127  /*
1128  * Iterate over all the pages. They are collected into batches of
1129  * XLR_MAX_BLOCK_ID pages, and a single WAL-record is written for each
1130  * batch.
1131  */
1133 
1134  i = 0;
1135  while (i < num_pages)
1136  {
1137  int batch_start = i;
1138  int nbatch;
1139 
1140  XLogBeginInsert();
1141 
1142  nbatch = 0;
1143  while (nbatch < XLR_MAX_BLOCK_ID && i < num_pages)
1144  {
1145  XLogRegisterBlock(nbatch, rnode, forkNum, blknos[i], pages[i], flags);
1146  i++;
1147  nbatch++;
1148  }
1149 
1150  recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI);
1151 
1152  for (j = batch_start; j < i; j++)
1153  {
1154  /*
1155  * The page may be uninitialized. If so, we can't set the LSN
1156  * because that would corrupt the page.
1157  */
1158  if (!PageIsNew(pages[j]))
1159  {
1160  PageSetLSN(pages[j], recptr);
1161  }
1162  }
1163  }
1164 }
int j
Definition: isn.c:74

References i, j, PageIsNew, PageSetLSN, REGBUF_FORCE_IMAGE, REGBUF_STANDARD, XLOG_FPI, XLogBeginInsert(), XLogEnsureRecordSpace(), XLogInsert(), XLogRegisterBlock(), and XLR_MAX_BLOCK_ID.

Referenced by gist_indexsortbuild_flush_ready_pages().

◆ XLogBeginInsert()

void XLogBeginInsert ( void  )

Definition at line 150 of file xloginsert.c.

151 {
154  Assert(mainrdata_len == 0);
155 
156  /* cross-check on whether we should be here or not */
157  if (!XLogInsertAllowed())
158  elog(ERROR, "cannot make new WAL entries during recovery");
159 
160  if (begininsert_called)
161  elog(ERROR, "XLogBeginInsert was already called");
162 
163  begininsert_called = true;
164 }
#define ERROR
Definition: elog.h:33
#define elog(elevel,...)
Definition: elog.h:218
bool XLogInsertAllowed(void)
Definition: xlog.c:5808
static XLogRecData * mainrdata_head
Definition: xloginsert.c:99
static bool begininsert_called
Definition: xloginsert.c:133
static int max_registered_block_id
Definition: xloginsert.c:92
static uint32 mainrdata_len
Definition: xloginsert.c:101
static XLogRecData * mainrdata_last
Definition: xloginsert.c:100

References Assert(), begininsert_called, elog, ERROR, mainrdata_head, mainrdata_last, mainrdata_len, max_registered_block_id, and XLogInsertAllowed().

Referenced by _bt_dedup_pass(), _bt_delitems_delete(), _bt_delitems_vacuum(), _bt_getroot(), _bt_insertonpg(), _bt_log_reuse_page(), _bt_mark_page_halfdead(), _bt_newroot(), _bt_set_cleanup_info(), _bt_split(), _bt_unlink_halfdead_page(), _hash_addovflpage(), _hash_doinsert(), _hash_expandtable(), _hash_freeovflpage(), _hash_init(), _hash_splitbucket(), _hash_squeezebucket(), _hash_vacuum_one_page(), addLeafTuple(), AssignTransactionId(), brin_doinsert(), brin_doupdate(), brinbuild(), brinRevmapDesummarizeRange(), CreateCheckPoint(), CreateDatabaseUsingFileCopy(), CreateDirAndVersionFile(), CreateEndOfRecoveryRecord(), CreateOverwriteContrecordRecord(), createPostingTree(), CreateTableSpace(), do_pg_backup_stop(), do_setval(), doPickSplit(), DropTableSpace(), EndPrepare(), ExecuteTruncateGuts(), fill_seq_fork_with_data(), GenericXLogFinish(), ginDeletePage(), ginHeapTupleFastInsert(), ginPlaceToPage(), ginUpdateStats(), ginVacuumPostingTreeLeaf(), gistXLogAssignLSN(), gistXLogDelete(), gistXLogPageDelete(), gistXLogPageReuse(), gistXLogSplit(), gistXLogUpdate(), hashbucketcleanup(), hashbulkdelete(), heap_abort_speculative(), heap_delete(), heap_finish_speculative(), heap_inplace_update(), heap_insert(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_page_prune(), heap_update(), lazy_vacuum_heap_page(), log_heap_freeze(), log_heap_new_cid(), log_heap_update(), log_heap_visible(), log_newpage(), log_newpage_range(), log_newpages(), log_smgrcreate(), log_split_page(), LogAccessExclusiveLocks(), LogCurrentRunningXacts(), logical_heap_rewrite_flush_mappings(), LogLogicalInvalidations(), LogLogicalMessage(), LogStandbyInvalidations(), movedb(), moveLeafs(), MultiXactIdCreateFromMembers(), nextval_internal(), pg_truncate_visibility_map(), RelationTruncate(), remove_dbtablespaces(), replorigin_advance(), replorigin_drop_guts(), RequestXLogSwitch(), revmap_physical_extend(), shiftList(), spgAddNodeAction(), spgSplitNodeAction(), UpdateFullPageWrites(), vacuumLeafPage(), vacuumLeafRoot(), vacuumRedirectAndPlaceholder(), write_relmap_file(), writeListPage(), WriteMTruncateXlogRec(), WriteMZeroPageXlogRec(), WriteTruncateXlogRec(), WriteZeroPageXlogRec(), XactLogAbortRecord(), XactLogCommitRecord(), XLogPutNextOid(), XLogReportParameters(), XLogRestorePoint(), XLogSaveBufferForHint(), and xlogVacuumPage().

◆ XLogCheckBufferNeedsBackup()

bool XLogCheckBufferNeedsBackup ( Buffer  buffer)

Definition at line 967 of file xloginsert.c.

968 {
970  bool doPageWrites;
971  Page page;
972 
974 
975  page = BufferGetPage(buffer);
976 
977  if (doPageWrites && PageGetLSN(page) <= RedoRecPtr)
978  return true; /* buffer requires backup */
979 
980  return false; /* buffer does not need to be backed up */
981 }
#define PageGetLSN(page)
Definition: bufpage.h:365
void GetFullPageWriteInfo(XLogRecPtr *RedoRecPtr_p, bool *doPageWrites_p)
Definition: xlog.c:5886
static XLogRecPtr RedoRecPtr
Definition: xlog.c:270
static bool doPageWrites
Definition: xlog.c:283

References BufferGetPage, doPageWrites, GetFullPageWriteInfo(), PageGetLSN, and RedoRecPtr.

Referenced by log_heap_update().

◆ XLogCompressBackupBlock()

static bool XLogCompressBackupBlock ( char *  page,
uint16  hole_offset,
uint16  hole_length,
char *  dest,
uint16 dlen 
)
static

Definition at line 884 of file xloginsert.c.

886 {
887  int32 orig_len = BLCKSZ - hole_length;
888  int32 len = -1;
889  int32 extra_bytes = 0;
890  char *source;
891  PGAlignedBlock tmp;
892 
893  if (hole_length != 0)
894  {
895  /* must skip the hole */
896  source = tmp.data;
897  memcpy(source, page, hole_offset);
898  memcpy(source + hole_offset,
899  page + (hole_offset + hole_length),
900  BLCKSZ - (hole_length + hole_offset));
901 
902  /*
903  * Extra data needs to be stored in WAL record for the compressed
904  * version of block image if the hole exists.
905  */
907  }
908  else
909  source = page;
910 
912  {
915  break;
916 
917  case WAL_COMPRESSION_LZ4:
918 #ifdef USE_LZ4
919  len = LZ4_compress_default(source, dest, orig_len,
921  if (len <= 0)
922  len = -1; /* failure */
923 #else
924  elog(ERROR, "LZ4 is not supported by this build");
925 #endif
926  break;
927 
929 #ifdef USE_ZSTD
930  len = ZSTD_compress(dest, COMPRESS_BUFSIZE, source, orig_len,
931  ZSTD_CLEVEL_DEFAULT);
932  if (ZSTD_isError(len))
933  len = -1; /* failure */
934 #else
935  elog(ERROR, "zstd is not supported by this build");
936 #endif
937  break;
938 
940  Assert(false); /* cannot happen */
941  break;
942  /* no default case, so that compiler will warn */
943  }
944 
945  /*
946  * We recheck the actual size even if compression reports success and see
947  * if the number of bytes saved by compression is larger than the length
948  * of extra data needed for the compressed version of block image.
949  */
950  if (len >= 0 &&
951  len + extra_bytes < orig_len)
952  {
953  *dlen = (uint16) len; /* successful compression */
954  return true;
955  }
956  return false;
957 }
unsigned short uint16
Definition: c.h:440
signed int int32
Definition: c.h:429
const void size_t len
const PGLZ_Strategy *const PGLZ_strategy_default
int32 pglz_compress(const char *source, int32 slen, char *dest, const PGLZ_Strategy *strategy)
static rewind_source * source
Definition: pg_rewind.c:81
char data[BLCKSZ]
Definition: c.h:1138
int wal_compression
Definition: xlog.c:125
WalCompression
Definition: xlog.h:76
@ WAL_COMPRESSION_NONE
Definition: xlog.h:77
@ WAL_COMPRESSION_LZ4
Definition: xlog.h:79
@ WAL_COMPRESSION_PGLZ
Definition: xlog.h:78
@ WAL_COMPRESSION_ZSTD
Definition: xlog.h:80
#define COMPRESS_BUFSIZE
Definition: xloginsert.c:63
#define SizeOfXLogRecordBlockCompressHeader
Definition: xlogrecord.h:166

References Assert(), COMPRESS_BUFSIZE, PGAlignedBlock::data, generate_unaccent_rules::dest, elog, ERROR, len, pglz_compress(), PGLZ_strategy_default, SizeOfXLogRecordBlockCompressHeader, source, wal_compression, WAL_COMPRESSION_LZ4, WAL_COMPRESSION_NONE, WAL_COMPRESSION_PGLZ, and WAL_COMPRESSION_ZSTD.

Referenced by XLogRecordAssemble().

◆ XLogEnsureRecordSpace()

void XLogEnsureRecordSpace ( int  max_block_id,
int  ndatas 
)

Definition at line 176 of file xloginsert.c.

177 {
178  int nbuffers;
179 
180  /*
181  * This must be called before entering a critical section, because
182  * allocating memory inside a critical section can fail. repalloc() will
183  * check the same, but better to check it here too so that we fail
184  * consistently even if the arrays happen to be large enough already.
185  */
186  Assert(CritSectionCount == 0);
187 
188  /* the minimum values can't be decreased */
189  if (max_block_id < XLR_NORMAL_MAX_BLOCK_ID)
190  max_block_id = XLR_NORMAL_MAX_BLOCK_ID;
191  if (ndatas < XLR_NORMAL_RDATAS)
192  ndatas = XLR_NORMAL_RDATAS;
193 
194  if (max_block_id > XLR_MAX_BLOCK_ID)
195  elog(ERROR, "maximum number of WAL record block references exceeded");
196  nbuffers = max_block_id + 1;
197 
198  if (nbuffers > max_registered_buffers)
199  {
201  repalloc(registered_buffers, sizeof(registered_buffer) * nbuffers);
202 
203  /*
204  * At least the padding bytes in the structs must be zeroed, because
205  * they are included in WAL data, but initialize it all for tidiness.
206  */
208  (nbuffers - max_registered_buffers) * sizeof(registered_buffer));
209  max_registered_buffers = nbuffers;
210  }
211 
212  if (ndatas > max_rdatas)
213  {
214  rdatas = (XLogRecData *) repalloc(rdatas, sizeof(XLogRecData) * ndatas);
215  max_rdatas = ndatas;
216  }
217 }
#define MemSet(start, val, len)
Definition: c.h:1008
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1188

References Assert(), CritSectionCount, elog, ERROR, max_rdatas, max_registered_buffers, MemSet, rdatas, registered_buffers, repalloc(), XLR_MAX_BLOCK_ID, XLR_NORMAL_MAX_BLOCK_ID, and XLR_NORMAL_RDATAS.

Referenced by _hash_freeovflpage(), _hash_squeezebucket(), EndPrepare(), gistplacetopage(), log_newpage_range(), log_newpages(), and shiftList().

◆ XLogInsert()

XLogRecPtr XLogInsert ( RmgrId  rmid,
uint8  info 
)

Definition at line 443 of file xloginsert.c.

444 {
445  XLogRecPtr EndPos;
446 
447  /* XLogBeginInsert() must have been called. */
448  if (!begininsert_called)
449  elog(ERROR, "XLogBeginInsert was not called");
450 
451  /*
452  * The caller can set rmgr bits, XLR_SPECIAL_REL_UPDATE and
453  * XLR_CHECK_CONSISTENCY; the rest are reserved for use by me.
454  */
455  if ((info & ~(XLR_RMGR_INFO_MASK |
457  XLR_CHECK_CONSISTENCY)) != 0)
458  elog(PANIC, "invalid xlog info mask %02X", info);
459 
460  TRACE_POSTGRESQL_WAL_INSERT(rmid, info);
461 
462  /*
463  * In bootstrap mode, we don't actually log anything but XLOG resources;
464  * return a phony record pointer.
465  */
466  if (IsBootstrapProcessingMode() && rmid != RM_XLOG_ID)
467  {
469  EndPos = SizeOfXLogLongPHD; /* start of 1st chkpt record */
470  return EndPos;
471  }
472 
473  do
474  {
476  bool doPageWrites;
477  bool topxid_included = false;
478  XLogRecPtr fpw_lsn;
479  XLogRecData *rdt;
480  int num_fpi = 0;
481 
482  /*
483  * Get values needed to decide whether to do full-page writes. Since
484  * we don't yet have an insertion lock, these could change under us,
485  * but XLogInsertRecord will recheck them once it has a lock.
486  */
488 
489  rdt = XLogRecordAssemble(rmid, info, RedoRecPtr, doPageWrites,
490  &fpw_lsn, &num_fpi, &topxid_included);
491 
492  EndPos = XLogInsertRecord(rdt, fpw_lsn, curinsert_flags, num_fpi,
493  topxid_included);
494  } while (EndPos == InvalidXLogRecPtr);
495 
497 
498  return EndPos;
499 }
#define PANIC
Definition: elog.h:36
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:406
XLogRecPtr XLogInsertRecord(XLogRecData *rdata, XLogRecPtr fpw_lsn, uint8 flags, int num_fpi, bool topxid_included)
Definition: xlog.c:728
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:69
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
static uint8 curinsert_flags
Definition: xloginsert.c:104
void XLogResetInsertion(void)
Definition: xloginsert.c:223
static XLogRecData * XLogRecordAssemble(RmgrId rmid, uint8 info, XLogRecPtr RedoRecPtr, bool doPageWrites, XLogRecPtr *fpw_lsn, int *num_fpi, bool *topxid_included)
Definition: xloginsert.c:517
#define XLR_RMGR_INFO_MASK
Definition: xlogrecord.h:63
#define XLR_SPECIAL_REL_UPDATE
Definition: xlogrecord.h:71
#define XLR_CHECK_CONSISTENCY
Definition: xlogrecord.h:80

References begininsert_called, curinsert_flags, doPageWrites, elog, ERROR, GetFullPageWriteInfo(), InvalidXLogRecPtr, IsBootstrapProcessingMode, PANIC, RedoRecPtr, SizeOfXLogLongPHD, XLogInsertRecord(), XLogRecordAssemble(), XLogResetInsertion(), XLR_CHECK_CONSISTENCY, XLR_RMGR_INFO_MASK, and XLR_SPECIAL_REL_UPDATE.

Referenced by _bt_dedup_pass(), _bt_delitems_delete(), _bt_delitems_vacuum(), _bt_getroot(), _bt_insertonpg(), _bt_log_reuse_page(), _bt_mark_page_halfdead(), _bt_newroot(), _bt_set_cleanup_info(), _bt_split(), _bt_unlink_halfdead_page(), _hash_addovflpage(), _hash_doinsert(), _hash_expandtable(), _hash_freeovflpage(), _hash_init(), _hash_splitbucket(), _hash_squeezebucket(), _hash_vacuum_one_page(), addLeafTuple(), AssignTransactionId(), brin_doinsert(), brin_doupdate(), brinbuild(), brinRevmapDesummarizeRange(), CreateCheckPoint(), CreateDatabaseUsingFileCopy(), CreateDirAndVersionFile(), CreateEndOfRecoveryRecord(), CreateOverwriteContrecordRecord(), createPostingTree(), CreateTableSpace(), do_pg_backup_stop(), do_setval(), doPickSplit(), DropTableSpace(), EndPrepare(), ExecuteTruncateGuts(), fill_seq_fork_with_data(), GenericXLogFinish(), ginDeletePage(), ginHeapTupleFastInsert(), ginPlaceToPage(), ginUpdateStats(), ginVacuumPostingTreeLeaf(), gistXLogAssignLSN(), gistXLogDelete(), gistXLogPageDelete(), gistXLogPageReuse(), gistXLogSplit(), gistXLogUpdate(), hashbucketcleanup(), hashbulkdelete(), heap_abort_speculative(), heap_delete(), heap_finish_speculative(), heap_inplace_update(), heap_insert(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_page_prune(), heap_update(), lazy_vacuum_heap_page(), log_heap_freeze(), log_heap_new_cid(), log_heap_update(), log_heap_visible(), log_newpage(), log_newpage_range(), log_newpages(), log_smgrcreate(), log_split_page(), LogAccessExclusiveLocks(), LogCurrentRunningXacts(), logical_heap_rewrite_flush_mappings(), LogLogicalInvalidations(), LogLogicalMessage(), LogStandbyInvalidations(), movedb(), moveLeafs(), MultiXactIdCreateFromMembers(), nextval_internal(), pg_truncate_visibility_map(), RelationTruncate(), remove_dbtablespaces(), replorigin_advance(), replorigin_drop_guts(), RequestXLogSwitch(), revmap_physical_extend(), shiftList(), spgAddNodeAction(), spgSplitNodeAction(), UpdateFullPageWrites(), vacuumLeafPage(), vacuumLeafRoot(), vacuumRedirectAndPlaceholder(), write_relmap_file(), writeListPage(), WriteMTruncateXlogRec(), WriteMZeroPageXlogRec(), WriteTruncateXlogRec(), WriteZeroPageXlogRec(), XactLogAbortRecord(), XactLogCommitRecord(), XLogPutNextOid(), XLogReportParameters(), XLogRestorePoint(), XLogSaveBufferForHint(), and xlogVacuumPage().

◆ XLogRecordAssemble()

static XLogRecData * XLogRecordAssemble ( RmgrId  rmid,
uint8  info,
XLogRecPtr  RedoRecPtr,
bool  doPageWrites,
XLogRecPtr fpw_lsn,
int *  num_fpi,
bool topxid_included 
)
static

Definition at line 517 of file xloginsert.c.

520 {
521  XLogRecData *rdt;
522  uint32 total_len = 0;
523  int block_id;
524  pg_crc32c rdata_crc;
525  registered_buffer *prev_regbuf = NULL;
526  XLogRecData *rdt_datas_last;
527  XLogRecord *rechdr;
528  char *scratch = hdr_scratch;
529 
530  /*
531  * Note: this function can be called multiple times for the same record.
532  * All the modifications we do to the rdata chains below must handle that.
533  */
534 
535  /* The record begins with the fixed-size header */
536  rechdr = (XLogRecord *) scratch;
537  scratch += SizeOfXLogRecord;
538 
539  hdr_rdt.next = NULL;
540  rdt_datas_last = &hdr_rdt;
542 
543  /*
544  * Enforce consistency checks for this record if user is looking for it.
545  * Do this before at the beginning of this routine to give the possibility
546  * for callers of XLogInsert() to pass XLR_CHECK_CONSISTENCY directly for
547  * a record.
548  */
549  if (wal_consistency_checking[rmid])
550  info |= XLR_CHECK_CONSISTENCY;
551 
552  /*
553  * Make an rdata chain containing all the data portions of all block
554  * references. This includes the data for full-page images. Also append
555  * the headers for the block references in the scratch buffer.
556  */
557  *fpw_lsn = InvalidXLogRecPtr;
558  for (block_id = 0; block_id < max_registered_block_id; block_id++)
559  {
560  registered_buffer *regbuf = &registered_buffers[block_id];
561  bool needs_backup;
562  bool needs_data;
565  XLogRecordBlockCompressHeader cbimg = {0};
566  bool samerel;
567  bool is_compressed = false;
568  bool include_image;
569 
570  if (!regbuf->in_use)
571  continue;
572 
573  /* Determine if this block needs to be backed up */
574  if (regbuf->flags & REGBUF_FORCE_IMAGE)
575  needs_backup = true;
576  else if (regbuf->flags & REGBUF_NO_IMAGE)
577  needs_backup = false;
578  else if (!doPageWrites)
579  needs_backup = false;
580  else
581  {
582  /*
583  * We assume page LSN is first data on *every* page that can be
584  * passed to XLogInsert, whether it has the standard page layout
585  * or not.
586  */
587  XLogRecPtr page_lsn = PageGetLSN(regbuf->page);
588 
589  needs_backup = (page_lsn <= RedoRecPtr);
590  if (!needs_backup)
591  {
592  if (*fpw_lsn == InvalidXLogRecPtr || page_lsn < *fpw_lsn)
593  *fpw_lsn = page_lsn;
594  }
595  }
596 
597  /* Determine if the buffer data needs to included */
598  if (regbuf->rdata_len == 0)
599  needs_data = false;
600  else if ((regbuf->flags & REGBUF_KEEP_DATA) != 0)
601  needs_data = true;
602  else
603  needs_data = !needs_backup;
604 
605  bkpb.id = block_id;
606  bkpb.fork_flags = regbuf->forkno;
607  bkpb.data_length = 0;
608 
609  if ((regbuf->flags & REGBUF_WILL_INIT) == REGBUF_WILL_INIT)
611 
612  /*
613  * If needs_backup is true or WAL checking is enabled for current
614  * resource manager, log a full-page write for the current block.
615  */
616  include_image = needs_backup || (info & XLR_CHECK_CONSISTENCY) != 0;
617 
618  if (include_image)
619  {
620  Page page = regbuf->page;
621  uint16 compressed_len = 0;
622 
623  /*
624  * The page needs to be backed up, so calculate its hole length
625  * and offset.
626  */
627  if (regbuf->flags & REGBUF_STANDARD)
628  {
629  /* Assume we can omit data between pd_lower and pd_upper */
630  uint16 lower = ((PageHeader) page)->pd_lower;
631  uint16 upper = ((PageHeader) page)->pd_upper;
632 
633  if (lower >= SizeOfPageHeaderData &&
634  upper > lower &&
635  upper <= BLCKSZ)
636  {
637  bimg.hole_offset = lower;
638  cbimg.hole_length = upper - lower;
639  }
640  else
641  {
642  /* No "hole" to remove */
643  bimg.hole_offset = 0;
644  cbimg.hole_length = 0;
645  }
646  }
647  else
648  {
649  /* Not a standard page header, don't try to eliminate "hole" */
650  bimg.hole_offset = 0;
651  cbimg.hole_length = 0;
652  }
653 
654  /*
655  * Try to compress a block image if wal_compression is enabled
656  */
658  {
659  is_compressed =
661  cbimg.hole_length,
662  regbuf->compressed_page,
663  &compressed_len);
664  }
665 
666  /*
667  * Fill in the remaining fields in the XLogRecordBlockHeader
668  * struct
669  */
671 
672  /* Report a full page image constructed for the WAL record */
673  *num_fpi += 1;
674 
675  /*
676  * Construct XLogRecData entries for the page content.
677  */
678  rdt_datas_last->next = &regbuf->bkp_rdatas[0];
679  rdt_datas_last = rdt_datas_last->next;
680 
681  bimg.bimg_info = (cbimg.hole_length == 0) ? 0 : BKPIMAGE_HAS_HOLE;
682 
683  /*
684  * If WAL consistency checking is enabled for the resource manager
685  * of this WAL record, a full-page image is included in the record
686  * for the block modified. During redo, the full-page is replayed
687  * only if BKPIMAGE_APPLY is set.
688  */
689  if (needs_backup)
690  bimg.bimg_info |= BKPIMAGE_APPLY;
691 
692  if (is_compressed)
693  {
694  /* The current compression is stored in the WAL record */
695  bimg.length = compressed_len;
696 
697  /* Set the compression method used for this block */
699  {
702  break;
703 
704  case WAL_COMPRESSION_LZ4:
705 #ifdef USE_LZ4
707 #else
708  elog(ERROR, "LZ4 is not supported by this build");
709 #endif
710  break;
711 
713 #ifdef USE_ZSTD
715 #else
716  elog(ERROR, "zstd is not supported by this build");
717 #endif
718  break;
719 
721  Assert(false); /* cannot happen */
722  break;
723  /* no default case, so that compiler will warn */
724  }
725 
726  rdt_datas_last->data = regbuf->compressed_page;
727  rdt_datas_last->len = compressed_len;
728  }
729  else
730  {
731  bimg.length = BLCKSZ - cbimg.hole_length;
732 
733  if (cbimg.hole_length == 0)
734  {
735  rdt_datas_last->data = page;
736  rdt_datas_last->len = BLCKSZ;
737  }
738  else
739  {
740  /* must skip the hole */
741  rdt_datas_last->data = page;
742  rdt_datas_last->len = bimg.hole_offset;
743 
744  rdt_datas_last->next = &regbuf->bkp_rdatas[1];
745  rdt_datas_last = rdt_datas_last->next;
746 
747  rdt_datas_last->data =
748  page + (bimg.hole_offset + cbimg.hole_length);
749  rdt_datas_last->len =
750  BLCKSZ - (bimg.hole_offset + cbimg.hole_length);
751  }
752  }
753 
754  total_len += bimg.length;
755  }
756 
757  if (needs_data)
758  {
759  /*
760  * Link the caller-supplied rdata chain for this buffer to the
761  * overall list.
762  */
764  bkpb.data_length = regbuf->rdata_len;
765  total_len += regbuf->rdata_len;
766 
767  rdt_datas_last->next = regbuf->rdata_head;
768  rdt_datas_last = regbuf->rdata_tail;
769  }
770 
771  if (prev_regbuf && RelFileNodeEquals(regbuf->rnode, prev_regbuf->rnode))
772  {
773  samerel = true;
775  }
776  else
777  samerel = false;
778  prev_regbuf = regbuf;
779 
780  /* Ok, copy the header to the scratch buffer */
781  memcpy(scratch, &bkpb, SizeOfXLogRecordBlockHeader);
782  scratch += SizeOfXLogRecordBlockHeader;
783  if (include_image)
784  {
785  memcpy(scratch, &bimg, SizeOfXLogRecordBlockImageHeader);
787  if (cbimg.hole_length != 0 && is_compressed)
788  {
789  memcpy(scratch, &cbimg,
792  }
793  }
794  if (!samerel)
795  {
796  memcpy(scratch, &regbuf->rnode, sizeof(RelFileNode));
797  scratch += sizeof(RelFileNode);
798  }
799  memcpy(scratch, &regbuf->block, sizeof(BlockNumber));
800  scratch += sizeof(BlockNumber);
801  }
802 
803  /* followed by the record's origin, if any */
806  {
807  *(scratch++) = (char) XLR_BLOCK_ID_ORIGIN;
808  memcpy(scratch, &replorigin_session_origin, sizeof(replorigin_session_origin));
809  scratch += sizeof(replorigin_session_origin);
810  }
811 
812  /* followed by toplevel XID, if not already included in previous record */
814  {
816 
817  /* Set the flag that the top xid is included in the WAL */
818  *topxid_included = true;
819 
820  *(scratch++) = (char) XLR_BLOCK_ID_TOPLEVEL_XID;
821  memcpy(scratch, &xid, sizeof(TransactionId));
822  scratch += sizeof(TransactionId);
823  }
824 
825  /* followed by main data, if any */
826  if (mainrdata_len > 0)
827  {
828  if (mainrdata_len > 255)
829  {
830  *(scratch++) = (char) XLR_BLOCK_ID_DATA_LONG;
831  memcpy(scratch, &mainrdata_len, sizeof(uint32));
832  scratch += sizeof(uint32);
833  }
834  else
835  {
836  *(scratch++) = (char) XLR_BLOCK_ID_DATA_SHORT;
837  *(scratch++) = (uint8) mainrdata_len;
838  }
839  rdt_datas_last->next = mainrdata_head;
840  rdt_datas_last = mainrdata_last;
841  total_len += mainrdata_len;
842  }
843  rdt_datas_last->next = NULL;
844 
845  hdr_rdt.len = (scratch - hdr_scratch);
846  total_len += hdr_rdt.len;
847 
848  /*
849  * Calculate CRC of the data
850  *
851  * Note that the record header isn't added into the CRC initially since we
852  * don't know the prev-link yet. Thus, the CRC will represent the CRC of
853  * the whole record in the order: rdata, then backup blocks, then record
854  * header.
855  */
856  INIT_CRC32C(rdata_crc);
858  for (rdt = hdr_rdt.next; rdt != NULL; rdt = rdt->next)
859  COMP_CRC32C(rdata_crc, rdt->data, rdt->len);
860 
861  /*
862  * Fill in the fields in the record header. Prev-link is filled in later,
863  * once we know where in the WAL the record will be inserted. The CRC does
864  * not include the record header yet.
865  */
867  rechdr->xl_tot_len = total_len;
868  rechdr->xl_info = info;
869  rechdr->xl_rmid = rmid;
870  rechdr->xl_prev = InvalidXLogRecPtr;
871  rechdr->xl_crc = rdata_crc;
872 
873  return &hdr_rdt;
874 }
PageHeaderData * PageHeader
Definition: bufpage.h:166
#define SizeOfPageHeaderData
Definition: bufpage.h:215
unsigned int uint32
Definition: c.h:441
unsigned char uint8
Definition: c.h:439
uint32 TransactionId
Definition: c.h:587
Datum lower(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:48
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:79
RepOriginId replorigin_session_origin
Definition: origin.c:155
#define InvalidRepOriginId
Definition: origin.h:33
uint32 pg_crc32c
Definition: pg_crc32c.h:38
#define COMP_CRC32C(crc, data, len)
Definition: pg_crc32c.h:89
#define INIT_CRC32C(crc)
Definition: pg_crc32c.h:41
struct RelFileNode RelFileNode
#define RelFileNodeEquals(node1, node2)
Definition: relfilenode.h:88
struct XLogRecData * next
XLogRecPtr xl_prev
Definition: xlogrecord.h:45
pg_crc32c xl_crc
Definition: xlogrecord.h:49
uint8 xl_info
Definition: xlogrecord.h:46
uint32 xl_tot_len
Definition: xlogrecord.h:43
TransactionId xl_xid
Definition: xlogrecord.h:44
RmgrId xl_rmid
Definition: xlogrecord.h:47
XLogRecData bkp_rdatas[2]
Definition: xloginsert.c:83
char compressed_page[COMPRESS_BUFSIZE]
Definition: xloginsert.c:87
RelFileNode rnode
Definition: xloginsert.c:73
XLogRecData * rdata_tail
Definition: xloginsert.c:80
BlockNumber block
Definition: xloginsert.c:75
XLogRecData * rdata_head
Definition: xloginsert.c:78
ForkNumber forkno
Definition: xloginsert.c:74
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:428
TransactionId GetCurrentTransactionIdIfAny(void)
Definition: xact.c:458
bool IsSubxactTopXidLogPending(void)
Definition: xact.c:546
bool * wal_consistency_checking
Definition: xlog.c:127
#define XLOG_INCLUDE_ORIGIN
Definition: xlog.h:149
static XLogRecData hdr_rdt
Definition: xloginsert.c:114
static bool XLogCompressBackupBlock(char *page, uint16 hole_offset, uint16 hole_length, char *dest, uint16 *dlen)
Definition: xloginsert.c:884
#define REGBUF_NO_IMAGE
Definition: xloginsert.h:32
#define REGBUF_KEEP_DATA
Definition: xloginsert.h:35
#define REGBUF_WILL_INIT
Definition: xloginsert.h:33
#define SizeOfXLogRecordBlockImageHeader
Definition: xlogrecord.h:142
#define BKPIMAGE_COMPRESS_ZSTD
Definition: xlogrecord.h:151
#define BKPBLOCK_HAS_DATA
Definition: xlogrecord.h:187
#define BKPIMAGE_APPLY
Definition: xlogrecord.h:147
#define BKPIMAGE_HAS_HOLE
Definition: xlogrecord.h:146
#define XLR_BLOCK_ID_DATA_LONG
Definition: xlogrecord.h:231
#define BKPBLOCK_WILL_INIT
Definition: xlogrecord.h:188
#define BKPIMAGE_COMPRESS_LZ4
Definition: xlogrecord.h:150
#define XLR_BLOCK_ID_TOPLEVEL_XID
Definition: xlogrecord.h:233
#define XLR_BLOCK_ID_DATA_SHORT
Definition: xlogrecord.h:230
#define BKPBLOCK_SAME_REL
Definition: xlogrecord.h:189
#define SizeOfXLogRecordBlockHeader
Definition: xlogrecord.h:104
#define BKPIMAGE_COMPRESS_PGLZ
Definition: xlogrecord.h:149
#define XLR_BLOCK_ID_ORIGIN
Definition: xlogrecord.h:232
#define BKPBLOCK_HAS_IMAGE
Definition: xlogrecord.h:186

References Assert(), XLogRecordBlockImageHeader::bimg_info, registered_buffer::bkp_rdatas, BKPBLOCK_HAS_DATA, BKPBLOCK_HAS_IMAGE, BKPBLOCK_SAME_REL, BKPBLOCK_WILL_INIT, BKPIMAGE_APPLY, BKPIMAGE_COMPRESS_LZ4, BKPIMAGE_COMPRESS_PGLZ, BKPIMAGE_COMPRESS_ZSTD, BKPIMAGE_HAS_HOLE, registered_buffer::block, COMP_CRC32C, registered_buffer::compressed_page, curinsert_flags, XLogRecData::data, XLogRecordBlockHeader::data_length, doPageWrites, elog, ERROR, registered_buffer::flags, XLogRecordBlockHeader::fork_flags, registered_buffer::forkno, GetCurrentTransactionIdIfAny(), GetTopTransactionIdIfAny(), hdr_rdt, hdr_scratch, XLogRecordBlockCompressHeader::hole_length, XLogRecordBlockImageHeader::hole_offset, XLogRecordBlockHeader::id, registered_buffer::in_use, INIT_CRC32C, InvalidRepOriginId, InvalidXLogRecPtr, IsSubxactTopXidLogPending(), XLogRecData::len, XLogRecordBlockImageHeader::length, lower(), mainrdata_head, mainrdata_last, mainrdata_len, max_registered_block_id, XLogRecData::next, registered_buffer::page, PageGetLSN, registered_buffer::rdata_head, registered_buffer::rdata_len, registered_buffer::rdata_tail, RedoRecPtr, REGBUF_FORCE_IMAGE, REGBUF_KEEP_DATA, REGBUF_NO_IMAGE, REGBUF_STANDARD, REGBUF_WILL_INIT, registered_buffers, RelFileNodeEquals, replorigin_session_origin, registered_buffer::rnode, SizeOfPageHeaderData, SizeOfXLogRecord, SizeOfXLogRecordBlockCompressHeader, SizeOfXLogRecordBlockHeader, SizeOfXLogRecordBlockImageHeader, upper(), wal_compression, WAL_COMPRESSION_LZ4, WAL_COMPRESSION_NONE, WAL_COMPRESSION_PGLZ, WAL_COMPRESSION_ZSTD, wal_consistency_checking, XLogRecord::xl_crc, XLogRecord::xl_info, XLogRecord::xl_prev, XLogRecord::xl_rmid, XLogRecord::xl_tot_len, XLogRecord::xl_xid, XLOG_INCLUDE_ORIGIN, XLogCompressBackupBlock(), XLR_BLOCK_ID_DATA_LONG, XLR_BLOCK_ID_DATA_SHORT, XLR_BLOCK_ID_ORIGIN, XLR_BLOCK_ID_TOPLEVEL_XID, and XLR_CHECK_CONSISTENCY.

Referenced by XLogInsert().

◆ XLogRegisterBlock()

void XLogRegisterBlock ( uint8  block_id,
RelFileNode rnode,
ForkNumber  forknum,
BlockNumber  blknum,
Page  page,
uint8  flags 
)

Definition at line 296 of file xloginsert.c.

298 {
299  registered_buffer *regbuf;
300 
302 
303  if (block_id >= max_registered_block_id)
304  max_registered_block_id = block_id + 1;
305 
306  if (block_id >= max_registered_buffers)
307  elog(ERROR, "too many registered buffers");
308 
309  regbuf = &registered_buffers[block_id];
310 
311  regbuf->rnode = *rnode;
312  regbuf->forkno = forknum;
313  regbuf->block = blknum;
314  regbuf->page = page;
315  regbuf->flags = flags;
316  regbuf->rdata_tail = (XLogRecData *) &regbuf->rdata_head;
317  regbuf->rdata_len = 0;
318 
319  /*
320  * Check that this page hasn't already been registered with some other
321  * block_id.
322  */
323 #ifdef USE_ASSERT_CHECKING
324  {
325  int i;
326 
327  for (i = 0; i < max_registered_block_id; i++)
328  {
329  registered_buffer *regbuf_old = &registered_buffers[i];
330 
331  if (i == block_id || !regbuf_old->in_use)
332  continue;
333 
334  Assert(!RelFileNodeEquals(regbuf_old->rnode, regbuf->rnode) ||
335  regbuf_old->forkno != regbuf->forkno ||
336  regbuf_old->block != regbuf->block);
337  }
338  }
339 #endif
340 
341  regbuf->in_use = true;
342 }

References Assert(), begininsert_called, registered_buffer::block, elog, ERROR, registered_buffer::flags, registered_buffer::forkno, i, registered_buffer::in_use, max_registered_block_id, max_registered_buffers, registered_buffer::page, registered_buffer::rdata_head, registered_buffer::rdata_len, registered_buffer::rdata_tail, registered_buffers, RelFileNodeEquals, and registered_buffer::rnode.

Referenced by log_newpage(), log_newpages(), and XLogSaveBufferForHint().

◆ XLogRegisterBufData()

void XLogRegisterBufData ( uint8  block_id,
char *  data,
int  len 
)

Definition at line 389 of file xloginsert.c.

390 {
391  registered_buffer *regbuf;
392  XLogRecData *rdata;
393 
395 
396  /* find the registered buffer struct */
397  regbuf = &registered_buffers[block_id];
398  if (!regbuf->in_use)
399  elog(ERROR, "no block with id %d registered with WAL insertion",
400  block_id);
401 
402  if (num_rdatas >= max_rdatas)
403  elog(ERROR, "too much WAL data");
404  rdata = &rdatas[num_rdatas++];
405 
406  rdata->data = data;
407  rdata->len = len;
408 
409  regbuf->rdata_tail->next = rdata;
410  regbuf->rdata_tail = rdata;
411  regbuf->rdata_len += len;
412 }
const void * data
static int num_rdatas
Definition: xloginsert.c:130

References Assert(), begininsert_called, XLogRecData::data, data, elog, ERROR, registered_buffer::in_use, XLogRecData::len, len, max_rdatas, XLogRecData::next, num_rdatas, registered_buffer::rdata_len, registered_buffer::rdata_tail, rdatas, and registered_buffers.

Referenced by _bt_dedup_pass(), _bt_delitems_delete(), _bt_delitems_vacuum(), _bt_getroot(), _bt_insertonpg(), _bt_newroot(), _bt_set_cleanup_info(), _bt_split(), _bt_unlink_halfdead_page(), _hash_addovflpage(), _hash_doinsert(), _hash_expandtable(), _hash_freeovflpage(), _hash_squeezebucket(), brin_doinsert(), brin_doupdate(), dataExecPlaceToPageInternal(), dataExecPlaceToPageLeaf(), entryExecPlaceToPage(), GenericXLogFinish(), ginHeapTupleFastInsert(), ginVacuumPostingTreeLeaf(), gistXLogSplit(), gistXLogUpdate(), hashbucketcleanup(), heap_inplace_update(), heap_insert(), heap_multi_insert(), heap_page_prune(), lazy_vacuum_heap_page(), log_heap_freeze(), log_heap_update(), and writeListPage().

◆ XLogRegisterBuffer()

void XLogRegisterBuffer ( uint8  block_id,
Buffer  buffer,
uint8  flags 
)

Definition at line 243 of file xloginsert.c.

244 {
245  registered_buffer *regbuf;
246 
247  /* NO_IMAGE doesn't make sense with FORCE_IMAGE */
248  Assert(!((flags & REGBUF_FORCE_IMAGE) && (flags & (REGBUF_NO_IMAGE))));
250 
251  if (block_id >= max_registered_block_id)
252  {
253  if (block_id >= max_registered_buffers)
254  elog(ERROR, "too many registered buffers");
255  max_registered_block_id = block_id + 1;
256  }
257 
258  regbuf = &registered_buffers[block_id];
259 
260  BufferGetTag(buffer, &regbuf->rnode, &regbuf->forkno, &regbuf->block);
261  regbuf->page = BufferGetPage(buffer);
262  regbuf->flags = flags;
263  regbuf->rdata_tail = (XLogRecData *) &regbuf->rdata_head;
264  regbuf->rdata_len = 0;
265 
266  /*
267  * Check that this page hasn't already been registered with some other
268  * block_id.
269  */
270 #ifdef USE_ASSERT_CHECKING
271  {
272  int i;
273 
274  for (i = 0; i < max_registered_block_id; i++)
275  {
276  registered_buffer *regbuf_old = &registered_buffers[i];
277 
278  if (i == block_id || !regbuf_old->in_use)
279  continue;
280 
281  Assert(!RelFileNodeEquals(regbuf_old->rnode, regbuf->rnode) ||
282  regbuf_old->forkno != regbuf->forkno ||
283  regbuf_old->block != regbuf->block);
284  }
285  }
286 #endif
287 
288  regbuf->in_use = true;
289 }

References Assert(), begininsert_called, registered_buffer::block, BufferGetPage, BufferGetTag(), elog, ERROR, registered_buffer::flags, registered_buffer::forkno, i, registered_buffer::in_use, max_registered_block_id, max_registered_buffers, registered_buffer::page, registered_buffer::rdata_head, registered_buffer::rdata_len, registered_buffer::rdata_tail, REGBUF_FORCE_IMAGE, REGBUF_NO_IMAGE, registered_buffers, RelFileNodeEquals, and registered_buffer::rnode.

Referenced by _bt_dedup_pass(), _bt_delitems_delete(), _bt_delitems_vacuum(), _bt_getroot(), _bt_insertonpg(), _bt_mark_page_halfdead(), _bt_newroot(), _bt_set_cleanup_info(), _bt_split(), _bt_unlink_halfdead_page(), _hash_addovflpage(), _hash_doinsert(), _hash_expandtable(), _hash_freeovflpage(), _hash_init(), _hash_splitbucket(), _hash_squeezebucket(), _hash_vacuum_one_page(), addLeafTuple(), brin_doinsert(), brin_doupdate(), brinbuild(), brinRevmapDesummarizeRange(), createPostingTree(), do_setval(), doPickSplit(), fill_seq_fork_with_data(), GenericXLogFinish(), ginDeletePage(), ginHeapTupleFastInsert(), ginPlaceToPage(), ginUpdateStats(), ginVacuumPostingTreeLeaf(), gistXLogDelete(), gistXLogPageDelete(), gistXLogSplit(), gistXLogUpdate(), hashbucketcleanup(), hashbulkdelete(), heap_abort_speculative(), heap_delete(), heap_finish_speculative(), heap_inplace_update(), heap_insert(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_page_prune(), heap_update(), lazy_vacuum_heap_page(), log_heap_freeze(), log_heap_update(), log_heap_visible(), log_newpage_range(), log_split_page(), moveLeafs(), nextval_internal(), revmap_physical_extend(), shiftList(), spgAddNodeAction(), spgSplitNodeAction(), vacuumLeafPage(), vacuumLeafRoot(), vacuumRedirectAndPlaceholder(), writeListPage(), and xlogVacuumPage().

◆ XLogRegisterData()

void XLogRegisterData ( char *  data,
int  len 
)

Definition at line 351 of file xloginsert.c.

352 {
353  XLogRecData *rdata;
354 
356 
357  if (num_rdatas >= max_rdatas)
358  elog(ERROR, "too much WAL data");
359  rdata = &rdatas[num_rdatas++];
360 
361  rdata->data = data;
362  rdata->len = len;
363 
364  /*
365  * we use the mainrdata_last pointer to track the end of the chain, so no
366  * need to clear 'next' here.
367  */
368 
369  mainrdata_last->next = rdata;
370  mainrdata_last = rdata;
371 
372  mainrdata_len += len;
373 }

References Assert(), begininsert_called, XLogRecData::data, data, elog, ERROR, XLogRecData::len, len, mainrdata_last, mainrdata_len, max_rdatas, XLogRecData::next, num_rdatas, and rdatas.

Referenced by _bt_dedup_pass(), _bt_delitems_delete(), _bt_delitems_vacuum(), _bt_getroot(), _bt_insertonpg(), _bt_log_reuse_page(), _bt_mark_page_halfdead(), _bt_newroot(), _bt_split(), _bt_unlink_halfdead_page(), _hash_addovflpage(), _hash_doinsert(), _hash_expandtable(), _hash_freeovflpage(), _hash_init(), _hash_splitbucket(), _hash_squeezebucket(), _hash_vacuum_one_page(), addLeafTuple(), AssignTransactionId(), brin_doinsert(), brin_doupdate(), brinbuild(), brinRevmapDesummarizeRange(), CreateCheckPoint(), CreateDatabaseUsingFileCopy(), CreateDirAndVersionFile(), CreateEndOfRecoveryRecord(), CreateOverwriteContrecordRecord(), createPostingTree(), CreateTableSpace(), do_pg_backup_stop(), do_setval(), doPickSplit(), DropTableSpace(), EndPrepare(), ExecuteTruncateGuts(), fill_seq_fork_with_data(), ginDeletePage(), ginHeapTupleFastInsert(), ginPlaceToPage(), ginUpdateStats(), gistXLogAssignLSN(), gistXLogDelete(), gistXLogPageDelete(), gistXLogPageReuse(), gistXLogSplit(), gistXLogUpdate(), hashbucketcleanup(), hashbulkdelete(), heap_abort_speculative(), heap_delete(), heap_finish_speculative(), heap_inplace_update(), heap_insert(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_page_prune(), heap_update(), lazy_vacuum_heap_page(), log_heap_freeze(), log_heap_new_cid(), log_heap_update(), log_heap_visible(), log_smgrcreate(), LogAccessExclusiveLocks(), LogCurrentRunningXacts(), logical_heap_rewrite_flush_mappings(), LogLogicalInvalidations(), LogLogicalMessage(), LogStandbyInvalidations(), movedb(), moveLeafs(), MultiXactIdCreateFromMembers(), nextval_internal(), pg_truncate_visibility_map(), RelationTruncate(), remove_dbtablespaces(), replorigin_advance(), replorigin_drop_guts(), revmap_physical_extend(), shiftList(), spgAddNodeAction(), spgSplitNodeAction(), UpdateFullPageWrites(), vacuumLeafPage(), vacuumLeafRoot(), vacuumRedirectAndPlaceholder(), write_relmap_file(), writeListPage(), WriteMTruncateXlogRec(), WriteMZeroPageXlogRec(), WriteTruncateXlogRec(), WriteZeroPageXlogRec(), XactLogAbortRecord(), XactLogCommitRecord(), XLogPutNextOid(), XLogReportParameters(), and XLogRestorePoint().

◆ XLogResetInsertion()

void XLogResetInsertion ( void  )

Definition at line 223 of file xloginsert.c.

224 {
225  int i;
226 
227  for (i = 0; i < max_registered_block_id; i++)
228  registered_buffers[i].in_use = false;
229 
230  num_rdatas = 0;
232  mainrdata_len = 0;
234  curinsert_flags = 0;
235  begininsert_called = false;
236 }

References begininsert_called, curinsert_flags, i, mainrdata_head, mainrdata_last, mainrdata_len, max_registered_block_id, num_rdatas, and registered_buffers.

Referenced by AbortSubTransaction(), AbortTransaction(), and XLogInsert().

◆ XLogSaveBufferForHint()

XLogRecPtr XLogSaveBufferForHint ( Buffer  buffer,
bool  buffer_std 
)

Definition at line 1005 of file xloginsert.c.

1006 {
1007  XLogRecPtr recptr = InvalidXLogRecPtr;
1008  XLogRecPtr lsn;
1010 
1011  /*
1012  * Ensure no checkpoint can change our view of RedoRecPtr.
1013  */
1015 
1016  /*
1017  * Update RedoRecPtr so that we can make the right decision
1018  */
1020 
1021  /*
1022  * We assume page LSN is first data on *every* page that can be passed to
1023  * XLogInsert, whether it has the standard page layout or not. Since we're
1024  * only holding a share-lock on the page, we must take the buffer header
1025  * lock when we look at the LSN.
1026  */
1027  lsn = BufferGetLSNAtomic(buffer);
1028 
1029  if (lsn <= RedoRecPtr)
1030  {
1031  int flags = 0;
1032  PGAlignedBlock copied_buffer;
1033  char *origdata = (char *) BufferGetBlock(buffer);
1034  RelFileNode rnode;
1035  ForkNumber forkno;
1036  BlockNumber blkno;
1037 
1038  /*
1039  * Copy buffer so we don't have to worry about concurrent hint bit or
1040  * lsn updates. We assume pd_lower/upper cannot be changed without an
1041  * exclusive lock, so the contents bkp are not racy.
1042  */
1043  if (buffer_std)
1044  {
1045  /* Assume we can omit data between pd_lower and pd_upper */
1046  Page page = BufferGetPage(buffer);
1047  uint16 lower = ((PageHeader) page)->pd_lower;
1048  uint16 upper = ((PageHeader) page)->pd_upper;
1049 
1050  memcpy(copied_buffer.data, origdata, lower);
1051  memcpy(copied_buffer.data + upper, origdata + upper, BLCKSZ - upper);
1052  }
1053  else
1054  memcpy(copied_buffer.data, origdata, BLCKSZ);
1055 
1056  XLogBeginInsert();
1057 
1058  if (buffer_std)
1059  flags |= REGBUF_STANDARD;
1060 
1061  BufferGetTag(buffer, &rnode, &forkno, &blkno);
1062  XLogRegisterBlock(0, &rnode, forkno, blkno, copied_buffer.data, flags);
1063 
1064  recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI_FOR_HINT);
1065  }
1066 
1067  return recptr;
1068 }
XLogRecPtr BufferGetLSNAtomic(Buffer buffer)
Definition: bufmgr.c:3004
#define BufferGetBlock(buffer)
Definition: bufmgr.h:136
#define XLOG_FPI_FOR_HINT
Definition: pg_control.h:77
#define DELAY_CHKPT_START
Definition: proc.h:117
PGPROC * MyProc
Definition: proc.c:68
int delayChkptFlags
Definition: proc.h:225
XLogRecPtr GetRedoRecPtr(void)
Definition: xlog.c:5856

References Assert(), BufferGetBlock, BufferGetLSNAtomic(), BufferGetPage, BufferGetTag(), PGAlignedBlock::data, DELAY_CHKPT_START, PGPROC::delayChkptFlags, GetRedoRecPtr(), InvalidXLogRecPtr, lower(), MyProc, RedoRecPtr, REGBUF_STANDARD, upper(), XLOG_FPI_FOR_HINT, XLogBeginInsert(), XLogInsert(), and XLogRegisterBlock().

Referenced by MarkBufferDirtyHint().

◆ XLogSetRecordFlags()

Variable Documentation

◆ begininsert_called

◆ curinsert_flags

uint8 curinsert_flags = 0
static

◆ hdr_rdt

XLogRecData hdr_rdt
static

Definition at line 114 of file xloginsert.c.

Referenced by XLogRecordAssemble().

◆ hdr_scratch

char* hdr_scratch = NULL
static

Definition at line 115 of file xloginsert.c.

Referenced by InitXLogInsert(), and XLogRecordAssemble().

◆ mainrdata_head

XLogRecData* mainrdata_head
static

Definition at line 99 of file xloginsert.c.

Referenced by XLogBeginInsert(), XLogRecordAssemble(), and XLogResetInsertion().

◆ mainrdata_last

XLogRecData* mainrdata_last = (XLogRecData *) &mainrdata_head
static

◆ mainrdata_len

uint32 mainrdata_len
static

◆ max_rdatas

int max_rdatas
static

◆ max_registered_block_id

int max_registered_block_id = 0
static

◆ max_registered_buffers

int max_registered_buffers
static

◆ num_rdatas

int num_rdatas
static

Definition at line 130 of file xloginsert.c.

Referenced by XLogRegisterBufData(), XLogRegisterData(), and XLogResetInsertion().

◆ rdatas

XLogRecData* rdatas
static

◆ registered_buffers

◆ xloginsert_cxt

MemoryContext xloginsert_cxt
static

Definition at line 136 of file xloginsert.c.

Referenced by InitXLogInsert().