PostgreSQL Source Code  git master
xloginsert.h File Reference
#include "access/rmgr.h"
#include "access/xlogdefs.h"
#include "storage/block.h"
#include "storage/buf.h"
#include "storage/relfilelocator.h"
#include "utils/relcache.h"
Include dependency graph for xloginsert.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define XLR_NORMAL_MAX_BLOCK_ID   4
 
#define XLR_NORMAL_RDATAS   20
 
#define REGBUF_FORCE_IMAGE   0x01 /* force a full-page image */
 
#define REGBUF_NO_IMAGE   0x02 /* don't take a full-page image */
 
#define REGBUF_WILL_INIT
 
#define REGBUF_STANDARD
 
#define REGBUF_KEEP_DATA
 

Functions

void XLogBeginInsert (void)
 
void XLogSetRecordFlags (uint8 flags)
 
XLogRecPtr XLogInsert (RmgrId rmid, uint8 info)
 
void XLogEnsureRecordSpace (int max_block_id, int ndatas)
 
void XLogRegisterData (char *data, uint32 len)
 
void XLogRegisterBuffer (uint8 block_id, Buffer buffer, uint8 flags)
 
void XLogRegisterBlock (uint8 block_id, RelFileLocator *rlocator, ForkNumber forknum, BlockNumber blknum, char *page, uint8 flags)
 
void XLogRegisterBufData (uint8 block_id, char *data, uint32 len)
 
void XLogResetInsertion (void)
 
bool XLogCheckBufferNeedsBackup (Buffer buffer)
 
XLogRecPtr log_newpage (RelFileLocator *rlocator, ForkNumber forknum, BlockNumber blkno, char *page, bool page_std)
 
void log_newpages (RelFileLocator *rlocator, ForkNumber forknum, int num_pages, BlockNumber *blknos, char **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)
 
XLogRecPtr XLogSaveBufferForHint (Buffer buffer, bool buffer_std)
 
void InitXLogInsert (void)
 

Macro Definition Documentation

◆ REGBUF_FORCE_IMAGE

#define REGBUF_FORCE_IMAGE   0x01 /* force a full-page image */

Definition at line 31 of file xloginsert.h.

◆ REGBUF_KEEP_DATA

#define REGBUF_KEEP_DATA
Value:
0x10 /* include data even if a full-page image
* is taken */

Definition at line 35 of file xloginsert.h.

◆ REGBUF_NO_IMAGE

#define REGBUF_NO_IMAGE   0x02 /* don't take a full-page image */

Definition at line 32 of file xloginsert.h.

◆ REGBUF_STANDARD

#define REGBUF_STANDARD
Value:
0x08 /* page follows "standard" page layout,
* (data between pd_lower and pd_upper
* will be skipped) */

Definition at line 34 of file xloginsert.h.

◆ REGBUF_WILL_INIT

#define REGBUF_WILL_INIT
Value:
(0x04 | 0x02) /* page will be re-initialized at
* replay (implies NO_IMAGE) */

Definition at line 33 of file xloginsert.h.

◆ XLR_NORMAL_MAX_BLOCK_ID

#define XLR_NORMAL_MAX_BLOCK_ID   4

Definition at line 27 of file xloginsert.h.

◆ XLR_NORMAL_RDATAS

#define XLR_NORMAL_RDATAS   20

Definition at line 28 of file xloginsert.h.

Function Documentation

◆ InitXLogInsert()

void InitXLogInsert ( void  )

Definition at line 1336 of file xloginsert.c.

1337 {
1338 #ifdef USE_ASSERT_CHECKING
1339 
1340  /*
1341  * Check that any records assembled can be decoded. This is capped based
1342  * on what XLogReader would require at its maximum bound. This code path
1343  * is called once per backend, more than enough for this check.
1344  */
1345  size_t max_required = DecodeXLogRecordRequiredSpace(XLogRecordMaxSize);
1346 
1347  Assert(AllocSizeIsValid(max_required));
1348 #endif
1349 
1350  /* Initialize the working areas */
1351  if (xloginsert_cxt == NULL)
1352  {
1354  "WAL record construction",
1356  }
1357 
1358  if (registered_buffers == NULL)
1359  {
1362  sizeof(registered_buffer) * (XLR_NORMAL_MAX_BLOCK_ID + 1));
1364  }
1365  if (rdatas == NULL)
1366  {
1368  sizeof(XLogRecData) * XLR_NORMAL_RDATAS);
1370  }
1371 
1372  /*
1373  * Allocate a buffer to hold the header information for a WAL record.
1374  */
1375  if (hdr_scratch == NULL)
1378 }
Assert(fmt[strlen(fmt) - 1] !='\n')
MemoryContext TopMemoryContext
Definition: mcxt.c:141
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1064
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1021
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:153
#define AllocSizeIsValid(size)
Definition: memutils.h:42
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
size_t DecodeXLogRecordRequiredSpace(size_t xl_tot_len)
Definition: xlogreader.c:1637
#define XLogRecordMaxSize
Definition: xlogrecord.h:74

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

Referenced by BaseInit().

◆ log_newpage()

XLogRecPtr log_newpage ( RelFileLocator rlocator,
ForkNumber  forknum,
BlockNumber  blkno,
char *  page,
bool  page_std 
)

Definition at line 1131 of file xloginsert.c.

1133 {
1134  int flags;
1135  XLogRecPtr recptr;
1136 
1137  flags = REGBUF_FORCE_IMAGE;
1138  if (page_std)
1139  flags |= REGBUF_STANDARD;
1140 
1141  XLogBeginInsert();
1142  XLogRegisterBlock(0, rlocator, forknum, blkno, page, flags);
1143  recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI);
1144 
1145  /*
1146  * The page may be uninitialized. If so, we can't set the LSN because that
1147  * would corrupt the page.
1148  */
1149  if (!PageIsNew(page))
1150  {
1151  PageSetLSN(page, recptr);
1152  }
1153 
1154  return recptr;
1155 }
static bool PageIsNew(Page page)
Definition: bufpage.h:230
static void PageSetLSN(Page page, XLogRecPtr lsn)
Definition: bufpage.h:388
#define XLOG_FPI
Definition: pg_control.h:78
uint64 XLogRecPtr
Definition: xlogdefs.h:21
void XLogRegisterBlock(uint8 block_id, RelFileLocator *rlocator, ForkNumber forknum, BlockNumber blknum, Page page, uint8 flags)
Definition: xloginsert.c:296
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:461
void XLogBeginInsert(void)
Definition: xloginsert.c:150
#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(), end_heap_rewrite(), gist_indexsortbuild(), log_newpage_buffer(), raw_heap_insert(), and RelationCopyStorage().

◆ log_newpage_buffer()

XLogRecPtr log_newpage_buffer ( Buffer  buffer,
bool  page_std 
)

Definition at line 1225 of file xloginsert.c.

1226 {
1227  Page page = BufferGetPage(buffer);
1228  RelFileLocator rlocator;
1229  ForkNumber forknum;
1230  BlockNumber blkno;
1231 
1232  /* Shared buffers should be modified in a critical section. */
1233  Assert(CritSectionCount > 0);
1234 
1235  BufferGetTag(buffer, &rlocator, &forknum, &blkno);
1236 
1237  return log_newpage(&rlocator, forknum, blkno, page, page_std);
1238 }
uint32 BlockNumber
Definition: block.h:31
void BufferGetTag(Buffer buffer, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum)
Definition: bufmgr.c:3311
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:350
Pointer Page
Definition: bufpage.h:78
volatile uint32 CritSectionCount
Definition: globals.c:42
ForkNumber
Definition: relpath.h:48
XLogRecPtr log_newpage(RelFileLocator *rlocator, ForkNumber forknum, BlockNumber blkno, Page page, bool page_std)
Definition: xloginsert.c:1131

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

Referenced by brin_initialize_empty_new_buffer(), brinbuildempty(), btbuildempty(), FreeSpaceMapPrepareTruncateRel(), ginbuildempty(), gistbuildempty(), heap_force_common(), lazy_scan_new_or_empty(), RelationCopyStorageUsingBuffer(), spgbuildempty(), 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 1258 of file xloginsert.c.

1261 {
1262  int flags;
1263  BlockNumber blkno;
1264 
1265  flags = REGBUF_FORCE_IMAGE;
1266  if (page_std)
1267  flags |= REGBUF_STANDARD;
1268 
1269  /*
1270  * Iterate over all the pages in the range. They are collected into
1271  * batches of XLR_MAX_BLOCK_ID pages, and a single WAL-record is written
1272  * for each batch.
1273  */
1275 
1276  blkno = startblk;
1277  while (blkno < endblk)
1278  {
1279  Buffer bufpack[XLR_MAX_BLOCK_ID];
1280  XLogRecPtr recptr;
1281  int nbufs;
1282  int i;
1283 
1285 
1286  /* Collect a batch of blocks. */
1287  nbufs = 0;
1288  while (nbufs < XLR_MAX_BLOCK_ID && blkno < endblk)
1289  {
1290  Buffer buf = ReadBufferExtended(rel, forknum, blkno,
1291  RBM_NORMAL, NULL);
1292 
1294 
1295  /*
1296  * Completely empty pages are not WAL-logged. Writing a WAL record
1297  * would change the LSN, and we don't want that. We want the page
1298  * to stay empty.
1299  */
1300  if (!PageIsNew(BufferGetPage(buf)))
1301  bufpack[nbufs++] = buf;
1302  else
1304  blkno++;
1305  }
1306 
1307  /* Nothing more to do if all remaining blocks were empty. */
1308  if (nbufs == 0)
1309  break;
1310 
1311  /* Write WAL record for this batch. */
1312  XLogBeginInsert();
1313 
1315  for (i = 0; i < nbufs; i++)
1316  {
1317  XLogRegisterBuffer(i, bufpack[i], flags);
1318  MarkBufferDirty(bufpack[i]);
1319  }
1320 
1321  recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI);
1322 
1323  for (i = 0; i < nbufs; i++)
1324  {
1325  PageSetLSN(BufferGetPage(bufpack[i]), recptr);
1326  UnlockReleaseBuffer(bufpack[i]);
1327  }
1328  END_CRIT_SECTION();
1329  }
1330 }
int Buffer
Definition: buf.h:23
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:4497
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:2111
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:4715
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:755
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:159
@ RBM_NORMAL
Definition: bufmgr.h:44
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
#define XLR_MAX_BLOCK_ID
Definition: xlogrecord.h:239

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 ( RelFileLocator rlocator,
ForkNumber  forknum,
int  num_pages,
BlockNumber blknos,
char **  pages,
bool  page_std 
)

Definition at line 1163 of file xloginsert.c.

1165 {
1166  int flags;
1167  XLogRecPtr recptr;
1168  int i;
1169  int j;
1170 
1171  flags = REGBUF_FORCE_IMAGE;
1172  if (page_std)
1173  flags |= REGBUF_STANDARD;
1174 
1175  /*
1176  * Iterate over all the pages. They are collected into batches of
1177  * XLR_MAX_BLOCK_ID pages, and a single WAL-record is written for each
1178  * batch.
1179  */
1181 
1182  i = 0;
1183  while (i < num_pages)
1184  {
1185  int batch_start = i;
1186  int nbatch;
1187 
1188  XLogBeginInsert();
1189 
1190  nbatch = 0;
1191  while (nbatch < XLR_MAX_BLOCK_ID && i < num_pages)
1192  {
1193  XLogRegisterBlock(nbatch, rlocator, forknum, blknos[i], pages[i], flags);
1194  i++;
1195  nbatch++;
1196  }
1197 
1198  recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI);
1199 
1200  for (j = batch_start; j < i; j++)
1201  {
1202  /*
1203  * The page may be uninitialized. If so, we can't set the LSN
1204  * because that would corrupt the page.
1205  */
1206  if (!PageIsNew(pages[j]))
1207  {
1208  PageSetLSN(pages[j], recptr);
1209  }
1210  }
1211  }
1212 }
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:39
bool XLogInsertAllowed(void)
Definition: xlog.c:6003
static XLogRecData * mainrdata_head
Definition: xloginsert.c:99
static uint64 mainrdata_len
Definition: xloginsert.c:101
static bool begininsert_called
Definition: xloginsert.c:133
static int max_registered_block_id
Definition: xloginsert.c:92
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_allocbuf(), _bt_dedup_pass(), _bt_delitems_delete(), _bt_delitems_vacuum(), _bt_getroot(), _bt_insertonpg(), _bt_mark_page_halfdead(), _bt_newlevel(), _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_freeze_execute_prepared(), 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_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_state_clear(), RequestXLogSwitch(), revmap_physical_extend(), shiftList(), spgAddNodeAction(), spgSplitNodeAction(), test_custom_rmgrs_insert_wal_record(), 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 1015 of file xloginsert.c.

1016 {
1018  bool doPageWrites;
1019  Page page;
1020 
1022 
1023  page = BufferGetPage(buffer);
1024 
1025  if (doPageWrites && PageGetLSN(page) <= RedoRecPtr)
1026  return true; /* buffer requires backup */
1027 
1028  return false; /* buffer does not need to be backed up */
1029 }
static XLogRecPtr PageGetLSN(Page page)
Definition: bufpage.h:383
void GetFullPageWriteInfo(XLogRecPtr *RedoRecPtr_p, bool *doPageWrites_p)
Definition: xlog.c:6081
static XLogRecPtr RedoRecPtr
Definition: xlog.c:276
static bool doPageWrites
Definition: xlog.c:289

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

Referenced by log_heap_update().

◆ 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:1009
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1476

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 461 of file xloginsert.c.

462 {
463  XLogRecPtr EndPos;
464 
465  /* XLogBeginInsert() must have been called. */
466  if (!begininsert_called)
467  elog(ERROR, "XLogBeginInsert was not called");
468 
469  /*
470  * The caller can set rmgr bits, XLR_SPECIAL_REL_UPDATE and
471  * XLR_CHECK_CONSISTENCY; the rest are reserved for use by me.
472  */
473  if ((info & ~(XLR_RMGR_INFO_MASK |
475  XLR_CHECK_CONSISTENCY)) != 0)
476  elog(PANIC, "invalid xlog info mask %02X", info);
477 
478  TRACE_POSTGRESQL_WAL_INSERT(rmid, info);
479 
480  /*
481  * In bootstrap mode, we don't actually log anything but XLOG resources;
482  * return a phony record pointer.
483  */
484  if (IsBootstrapProcessingMode() && rmid != RM_XLOG_ID)
485  {
487  EndPos = SizeOfXLogLongPHD; /* start of 1st chkpt record */
488  return EndPos;
489  }
490 
491  do
492  {
494  bool doPageWrites;
495  bool topxid_included = false;
496  XLogRecPtr fpw_lsn;
497  XLogRecData *rdt;
498  int num_fpi = 0;
499 
500  /*
501  * Get values needed to decide whether to do full-page writes. Since
502  * we don't yet have an insertion lock, these could change under us,
503  * but XLogInsertRecord will recheck them once it has a lock.
504  */
506 
507  rdt = XLogRecordAssemble(rmid, info, RedoRecPtr, doPageWrites,
508  &fpw_lsn, &num_fpi, &topxid_included);
509 
510  EndPos = XLogInsertRecord(rdt, fpw_lsn, curinsert_flags, num_fpi,
511  topxid_included);
512  } while (EndPos == InvalidXLogRecPtr);
513 
515 
516  return EndPos;
517 }
#define PANIC
Definition: elog.h:42
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:414
XLogRecPtr XLogInsertRecord(XLogRecData *rdata, XLogRecPtr fpw_lsn, uint8 flags, int num_fpi, bool topxid_included)
Definition: xlog.c:731
#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:535
#define XLR_RMGR_INFO_MASK
Definition: xlogrecord.h:63
#define XLR_SPECIAL_REL_UPDATE
Definition: xlogrecord.h:82
#define XLR_CHECK_CONSISTENCY
Definition: xlogrecord.h:91

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_allocbuf(), _bt_dedup_pass(), _bt_delitems_delete(), _bt_delitems_vacuum(), _bt_getroot(), _bt_insertonpg(), _bt_mark_page_halfdead(), _bt_newlevel(), _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_freeze_execute_prepared(), 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_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_state_clear(), RequestXLogSwitch(), revmap_physical_extend(), shiftList(), spgAddNodeAction(), spgSplitNodeAction(), test_custom_rmgrs_insert_wal_record(), UpdateFullPageWrites(), vacuumLeafPage(), vacuumLeafRoot(), vacuumRedirectAndPlaceholder(), write_relmap_file(), writeListPage(), WriteMTruncateXlogRec(), WriteMZeroPageXlogRec(), WriteTruncateXlogRec(), WriteZeroPageXlogRec(), XactLogAbortRecord(), XactLogCommitRecord(), XLogPutNextOid(), XLogReportParameters(), XLogRestorePoint(), XLogSaveBufferForHint(), and xlogVacuumPage().

◆ XLogRegisterBlock()

void XLogRegisterBlock ( uint8  block_id,
RelFileLocator rlocator,
ForkNumber  forknum,
BlockNumber  blknum,
char *  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->rlocator = *rlocator;
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(!RelFileLocatorEquals(regbuf_old->rlocator, regbuf->rlocator) ||
335  regbuf_old->forkno != regbuf->forkno ||
336  regbuf_old->block != regbuf->block);
337  }
338  }
339 #endif
340 
341  regbuf->in_use = true;
342 }
#define RelFileLocatorEquals(locator1, locator2)
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
RelFileLocator rlocator
Definition: xloginsert.c:73

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, RelFileLocatorEquals, and registered_buffer::rlocator.

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

◆ XLogRegisterBufData()

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

Definition at line 392 of file xloginsert.c.

393 {
394  registered_buffer *regbuf;
395  XLogRecData *rdata;
396 
398 
399  /* find the registered buffer struct */
400  regbuf = &registered_buffers[block_id];
401  if (!regbuf->in_use)
402  elog(ERROR, "no block with id %d registered with WAL insertion",
403  block_id);
404 
405  /*
406  * Check against max_rdatas and ensure we do not register more data per
407  * buffer than can be handled by the physical data format; i.e. that
408  * regbuf->rdata_len does not grow beyond what
409  * XLogRecordBlockHeader->data_length can hold.
410  */
411  if (num_rdatas >= max_rdatas)
412  ereport(ERROR,
413  (errmsg_internal("too much WAL data"),
414  errdetail_internal("%d out of %d data segments are already in use.",
416  if (regbuf->rdata_len + len > UINT16_MAX || len > UINT16_MAX)
417  ereport(ERROR,
418  (errmsg_internal("too much WAL data"),
419  errdetail_internal("Registering more than maximum %u bytes allowed to block %u: current %u bytes, adding %u bytes.",
420  UINT16_MAX, block_id, regbuf->rdata_len, len)));
421 
422  rdata = &rdatas[num_rdatas++];
423 
424  rdata->data = data;
425  rdata->len = len;
426 
427  regbuf->rdata_tail->next = rdata;
428  regbuf->rdata_tail = rdata;
429  regbuf->rdata_len += len;
430 }
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1156
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1229
#define ereport(elevel,...)
Definition: elog.h:149
const void size_t len
const void * data
struct XLogRecData * next
static int num_rdatas
Definition: xloginsert.c:130

References Assert(), begininsert_called, XLogRecData::data, data, elog(), ereport, errdetail_internal(), errmsg_internal(), 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_newlevel(), _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_freeze_execute_prepared(), heap_inplace_update(), heap_insert(), heap_multi_insert(), heap_page_prune(), lazy_vacuum_heap_page(), 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->rlocator, &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(!RelFileLocatorEquals(regbuf_old->rlocator, regbuf->rlocator) ||
282  regbuf_old->forkno != regbuf->forkno ||
283  regbuf_old->block != regbuf->block);
284  }
285  }
286 #endif
287 
288  regbuf->in_use = true;
289 }
#define REGBUF_NO_IMAGE
Definition: xloginsert.h:32

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, RelFileLocatorEquals, and registered_buffer::rlocator.

Referenced by _bt_dedup_pass(), _bt_delitems_delete(), _bt_delitems_vacuum(), _bt_getroot(), _bt_insertonpg(), _bt_mark_page_halfdead(), _bt_newlevel(), _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_freeze_execute_prepared(), 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_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,
uint32  len 
)

Definition at line 351 of file xloginsert.c.

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

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

Referenced by _bt_allocbuf(), _bt_dedup_pass(), _bt_delitems_delete(), _bt_delitems_vacuum(), _bt_getroot(), _bt_insertonpg(), _bt_mark_page_halfdead(), _bt_newlevel(), _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_freeze_execute_prepared(), 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_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_state_clear(), revmap_physical_extend(), shiftList(), spgAddNodeAction(), spgSplitNodeAction(), test_custom_rmgrs_insert_wal_record(), 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 1053 of file xloginsert.c.

1054 {
1055  XLogRecPtr recptr = InvalidXLogRecPtr;
1056  XLogRecPtr lsn;
1058 
1059  /*
1060  * Ensure no checkpoint can change our view of RedoRecPtr.
1061  */
1063 
1064  /*
1065  * Update RedoRecPtr so that we can make the right decision
1066  */
1068 
1069  /*
1070  * We assume page LSN is first data on *every* page that can be passed to
1071  * XLogInsert, whether it has the standard page layout or not. Since we're
1072  * only holding a share-lock on the page, we must take the buffer header
1073  * lock when we look at the LSN.
1074  */
1075  lsn = BufferGetLSNAtomic(buffer);
1076 
1077  if (lsn <= RedoRecPtr)
1078  {
1079  int flags = 0;
1080  PGAlignedBlock copied_buffer;
1081  char *origdata = (char *) BufferGetBlock(buffer);
1082  RelFileLocator rlocator;
1083  ForkNumber forkno;
1084  BlockNumber blkno;
1085 
1086  /*
1087  * Copy buffer so we don't have to worry about concurrent hint bit or
1088  * lsn updates. We assume pd_lower/upper cannot be changed without an
1089  * exclusive lock, so the contents bkp are not racy.
1090  */
1091  if (buffer_std)
1092  {
1093  /* Assume we can omit data between pd_lower and pd_upper */
1094  Page page = BufferGetPage(buffer);
1095  uint16 lower = ((PageHeader) page)->pd_lower;
1096  uint16 upper = ((PageHeader) page)->pd_upper;
1097 
1098  memcpy(copied_buffer.data, origdata, lower);
1099  memcpy(copied_buffer.data + upper, origdata + upper, BLCKSZ - upper);
1100  }
1101  else
1102  memcpy(copied_buffer.data, origdata, BLCKSZ);
1103 
1104  XLogBeginInsert();
1105 
1106  if (buffer_std)
1107  flags |= REGBUF_STANDARD;
1108 
1109  BufferGetTag(buffer, &rlocator, &forkno, &blkno);
1110  XLogRegisterBlock(0, &rlocator, forkno, blkno, copied_buffer.data, flags);
1111 
1112  recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI_FOR_HINT);
1113  }
1114 
1115  return recptr;
1116 }
XLogRecPtr BufferGetLSNAtomic(Buffer buffer)
Definition: bufmgr.c:3551
static Block BufferGetBlock(Buffer buffer)
Definition: bufmgr.h:317
PageHeaderData * PageHeader
Definition: bufpage.h:170
unsigned short uint16
Definition: c.h:494
Datum lower(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:49
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:80
#define XLOG_FPI_FOR_HINT
Definition: pg_control.h:77
#define DELAY_CHKPT_START
Definition: proc.h:119
PGPROC * MyProc
Definition: proc.c:66
int delayChkptFlags
Definition: proc.h:231
char data[BLCKSZ]
Definition: c.h:1132
XLogRecPtr GetRedoRecPtr(void)
Definition: xlog.c:6051

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()