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/relfilenode.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, int len)
 
void XLogRegisterBuffer (uint8 block_id, Buffer buffer, uint8 flags)
 
void XLogRegisterBlock (uint8 block_id, RelFileNode *rnode, ForkNumber forknum, BlockNumber blknum, char *page, uint8 flags)
 
void XLogRegisterBufData (uint8 block_id, char *data, int len)
 
void XLogResetInsertion (void)
 
bool XLogCheckBufferNeedsBackup (Buffer buffer)
 
XLogRecPtr log_newpage (RelFileNode *rnode, ForkNumber forkNum, BlockNumber blk, char *page, bool page_std)
 
void log_newpages (RelFileNode *rnode, 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

◆ REGBUF_KEEP_DATA

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

Definition at line 38 of file xloginsert.h.

Referenced by heap_insert(), heap_multi_insert(), log_heap_update(), and XLogRecordAssemble().

◆ REGBUF_NO_IMAGE

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

◆ REGBUF_STANDARD

◆ REGBUF_WILL_INIT

◆ XLR_NORMAL_MAX_BLOCK_ID

#define XLR_NORMAL_MAX_BLOCK_ID   4

Definition at line 27 of file xloginsert.h.

Referenced by InitXLogInsert(), and XLogEnsureRecordSpace().

◆ XLR_NORMAL_RDATAS

#define XLR_NORMAL_RDATAS   20

Definition at line 28 of file xloginsert.h.

Referenced by InitXLogInsert(), and XLogEnsureRecordSpace().

Function Documentation

◆ InitXLogInsert()

void InitXLogInsert ( void  )

Definition at line 1197 of file xloginsert.c.

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

Referenced by CreateCheckPoint(), and InitXLOGAccess().

1198 {
1199  /* Initialize the working areas */
1200  if (xloginsert_cxt == NULL)
1201  {
1203  "WAL record construction",
1205  }
1206 
1207  if (registered_buffers == NULL)
1208  {
1211  sizeof(registered_buffer) * (XLR_NORMAL_MAX_BLOCK_ID + 1));
1213  }
1214  if (rdatas == NULL)
1215  {
1217  sizeof(XLogRecData) * XLR_NORMAL_RDATAS);
1219  }
1220 
1221  /*
1222  * Allocate a buffer to hold the header information for a WAL record.
1223  */
1224  if (hdr_scratch == NULL)
1227 }
#define AllocSetContextCreate
Definition: memutils.h:170
#define HEADER_SCRATCH_SIZE
Definition: xloginsert.c:94
#define XLR_NORMAL_RDATAS
Definition: xloginsert.h:28
static int max_registered_buffers
Definition: xloginsert.c:65
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
static int max_rdatas
Definition: xloginsert.c:105
MemoryContext TopMemoryContext
Definition: mcxt.c:44
static registered_buffer * registered_buffers
Definition: xloginsert.c:64
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:840
#define XLR_NORMAL_MAX_BLOCK_ID
Definition: xloginsert.h:27
static char * hdr_scratch
Definition: xloginsert.c:89
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:797
static MemoryContext xloginsert_cxt
Definition: xloginsert.c:110
static XLogRecData * rdatas
Definition: xloginsert.c:103

◆ log_newpage()

XLogRecPtr log_newpage ( RelFileNode rnode,
ForkNumber  forkNum,
BlockNumber  blk,
char *  page,
bool  page_std 
)

Definition at line 996 of file xloginsert.c.

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

998 {
999  int flags;
1000  XLogRecPtr recptr;
1001 
1002  flags = REGBUF_FORCE_IMAGE;
1003  if (page_std)
1004  flags |= REGBUF_STANDARD;
1005 
1006  XLogBeginInsert();
1007  XLogRegisterBlock(0, rnode, forkNum, blkno, page, flags);
1008  recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI);
1009 
1010  /*
1011  * The page may be uninitialized. If so, we can't set the LSN because that
1012  * would corrupt the page.
1013  */
1014  if (!PageIsNew(page))
1015  {
1016  PageSetLSN(page, recptr);
1017  }
1018 
1019  return recptr;
1020 }
void XLogRegisterBlock(uint8 block_id, RelFileNode *rnode, ForkNumber forknum, BlockNumber blknum, Page page, uint8 flags)
Definition: xloginsert.c:273
#define REGBUF_STANDARD
Definition: xloginsert.h:35
#define REGBUF_FORCE_IMAGE
Definition: xloginsert.h:31
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:422
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define XLOG_FPI
Definition: pg_control.h:78
#define PageIsNew(page)
Definition: bufpage.h:229
void XLogBeginInsert(void)
Definition: xloginsert.c:123
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368

◆ log_newpage_buffer()

XLogRecPtr log_newpage_buffer ( Buffer  buffer,
bool  page_std 
)

Definition at line 1090 of file xloginsert.c.

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

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

1091 {
1092  Page page = BufferGetPage(buffer);
1093  RelFileNode rnode;
1094  ForkNumber forkNum;
1095  BlockNumber blkno;
1096 
1097  /* Shared buffers should be modified in a critical section. */
1098  Assert(CritSectionCount > 0);
1099 
1100  BufferGetTag(buffer, &rnode, &forkNum, &blkno);
1101 
1102  return log_newpage(&rnode, forkNum, blkno, page, page_std);
1103 }
uint32 BlockNumber
Definition: block.h:31
volatile uint32 CritSectionCount
Definition: globals.c:38
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
ForkNumber
Definition: relpath.h:40
#define Assert(condition)
Definition: c.h:745
XLogRecPtr log_newpage(RelFileNode *rnode, ForkNumber forkNum, BlockNumber blkno, Page page, bool page_std)
Definition: xloginsert.c:996
void BufferGetTag(Buffer buffer, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum)
Definition: bufmgr.c:2682
Pointer Page
Definition: bufpage.h:78

◆ log_newpage_range()

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

Definition at line 1123 of file xloginsert.c.

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

1126 {
1127  int flags;
1128  BlockNumber blkno;
1129 
1130  flags = REGBUF_FORCE_IMAGE;
1131  if (page_std)
1132  flags |= REGBUF_STANDARD;
1133 
1134  /*
1135  * Iterate over all the pages in the range. They are collected into
1136  * batches of XLR_MAX_BLOCK_ID pages, and a single WAL-record is written
1137  * for each batch.
1138  */
1140 
1141  blkno = startblk;
1142  while (blkno < endblk)
1143  {
1144  Buffer bufpack[XLR_MAX_BLOCK_ID];
1145  XLogRecPtr recptr;
1146  int nbufs;
1147  int i;
1148 
1150 
1151  /* Collect a batch of blocks. */
1152  nbufs = 0;
1153  while (nbufs < XLR_MAX_BLOCK_ID && blkno < endblk)
1154  {
1155  Buffer buf = ReadBufferExtended(rel, forkNum, blkno,
1156  RBM_NORMAL, NULL);
1157 
1159 
1160  /*
1161  * Completely empty pages are not WAL-logged. Writing a WAL record
1162  * would change the LSN, and we don't want that. We want the page
1163  * to stay empty.
1164  */
1165  if (!PageIsNew(BufferGetPage(buf)))
1166  bufpack[nbufs++] = buf;
1167  else
1168  UnlockReleaseBuffer(buf);
1169  blkno++;
1170  }
1171 
1172  /* Write WAL record for this batch. */
1173  XLogBeginInsert();
1174 
1176  for (i = 0; i < nbufs; i++)
1177  {
1178  XLogRegisterBuffer(i, bufpack[i], flags);
1179  MarkBufferDirty(bufpack[i]);
1180  }
1181 
1182  recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI);
1183 
1184  for (i = 0; i < nbufs; i++)
1185  {
1186  PageSetLSN(BufferGetPage(bufpack[i]), recptr);
1187  UnlockReleaseBuffer(bufpack[i]);
1188  }
1189  END_CRIT_SECTION();
1190  }
1191 }
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:1469
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:220
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:653
#define END_CRIT_SECTION()
Definition: miscadmin.h:134
#define START_CRIT_SECTION()
Definition: miscadmin.h:132
uint32 BlockNumber
Definition: block.h:31
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:98
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3534
static char * buf
Definition: pg_test_fsync.c:68
#define REGBUF_STANDARD
Definition: xloginsert.h:35
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
#define XLR_MAX_BLOCK_ID
Definition: xlogrecord.h:221
#define REGBUF_FORCE_IMAGE
Definition: xloginsert.h:31
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:422
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:3750
uint64 XLogRecPtr
Definition: xlogdefs.h:21
void XLogEnsureRecordSpace(int max_block_id, int ndatas)
Definition: xloginsert.c:149
#define XLOG_FPI
Definition: pg_control.h:78
#define PageIsNew(page)
Definition: bufpage.h:229
int i
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
void XLogBeginInsert(void)
Definition: xloginsert.c:123
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368
int Buffer
Definition: buf.h:23

◆ log_newpages()

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

Definition at line 1028 of file xloginsert.c.

References i, 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().

1030 {
1031  int flags;
1032  XLogRecPtr recptr;
1033  int i;
1034  int j;
1035 
1036  flags = REGBUF_FORCE_IMAGE;
1037  if (page_std)
1038  flags |= REGBUF_STANDARD;
1039 
1040  /*
1041  * Iterate over all the pages. They are collected into batches of
1042  * XLR_MAX_BLOCK_ID pages, and a single WAL-record is written for each
1043  * batch.
1044  */
1046 
1047  i = 0;
1048  while (i < num_pages)
1049  {
1050  int batch_start = i;
1051  int nbatch;
1052 
1053  XLogBeginInsert();
1054 
1055  nbatch = 0;
1056  while (nbatch < XLR_MAX_BLOCK_ID && i < num_pages)
1057  {
1058  XLogRegisterBlock(nbatch, rnode, forkNum, blknos[i], pages[i], flags);
1059  i++;
1060  nbatch++;
1061  }
1062 
1063  recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI);
1064 
1065  for (j = batch_start; j < i; j++)
1066  {
1067  /*
1068  * The page may be uninitialized. If so, we can't set the LSN because that
1069  * would corrupt the page.
1070  */
1071  if (!PageIsNew(pages[j]))
1072  {
1073  PageSetLSN(pages[j], recptr);
1074  }
1075  }
1076  }
1077 }
void XLogRegisterBlock(uint8 block_id, RelFileNode *rnode, ForkNumber forknum, BlockNumber blknum, Page page, uint8 flags)
Definition: xloginsert.c:273
#define REGBUF_STANDARD
Definition: xloginsert.h:35
#define XLR_MAX_BLOCK_ID
Definition: xlogrecord.h:221
#define REGBUF_FORCE_IMAGE
Definition: xloginsert.h:31
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:422
uint64 XLogRecPtr
Definition: xlogdefs.h:21
void XLogEnsureRecordSpace(int max_block_id, int ndatas)
Definition: xloginsert.c:149
#define XLOG_FPI
Definition: pg_control.h:78
#define PageIsNew(page)
Definition: bufpage.h:229
int i
void XLogBeginInsert(void)
Definition: xloginsert.c:123
#define PageSetLSN(page, lsn)
Definition: bufpage.h:368

◆ XLogBeginInsert()

void XLogBeginInsert ( void  )

Definition at line 123 of file xloginsert.c.

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

Referenced by _bt_dedup_one_page(), _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(), _bt_update_meta_cleanup_info(), _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(), createdb(), CreateEndOfRecoveryRecord(), createPostingTree(), CreateTableSpace(), do_pg_stop_backup(), do_setval(), doPickSplit(), DropTableSpace(), EndPrepare(), ExecuteTruncateGuts(), fill_seq_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_update(), log_heap_clean(), log_heap_cleanup_info(), 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(), RequestXLogSwitch(), revmap_physical_extend(), shiftList(), spgAddNodeAction(), spgSplitNodeAction(), UpdateFullPageWrites(), vacuumLeafPage(), vacuumLeafRoot(), vacuumRedirectAndPlaceholder(), write_relmap_file(), writeListPage(), WriteMTruncateXlogRec(), WriteMZeroPageXlogRec(), WriteSetTimestampXlogRec(), WriteTruncateXlogRec(), WriteZeroPageXlogRec(), XactLogAbortRecord(), XactLogCommitRecord(), XLogPutNextOid(), XLogReportParameters(), XLogRestorePoint(), XLogSaveBufferForHint(), and xlogVacuumPage().

124 {
127  Assert(mainrdata_len == 0);
128 
129  /* cross-check on whether we should be here or not */
130  if (!XLogInsertAllowed())
131  elog(ERROR, "cannot make new WAL entries during recovery");
132 
133  if (begininsert_called)
134  elog(ERROR, "XLogBeginInsert was already called");
135 
136  begininsert_called = true;
137 }
static uint32 mainrdata_len
Definition: xloginsert.c:75
static bool begininsert_called
Definition: xloginsert.c:107
#define ERROR
Definition: elog.h:43
static XLogRecData * mainrdata_head
Definition: xloginsert.c:73
bool XLogInsertAllowed(void)
Definition: xlog.c:8187
static XLogRecData * mainrdata_last
Definition: xloginsert.c:74
#define Assert(condition)
Definition: c.h:745
static int max_registered_block_id
Definition: xloginsert.c:66
#define elog(elevel,...)
Definition: elog.h:214

◆ XLogCheckBufferNeedsBackup()

bool XLogCheckBufferNeedsBackup ( Buffer  buffer)

Definition at line 879 of file xloginsert.c.

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

Referenced by log_heap_update().

880 {
882  bool doPageWrites;
883  Page page;
884 
885  GetFullPageWriteInfo(&RedoRecPtr, &doPageWrites);
886 
887  page = BufferGetPage(buffer);
888 
889  if (doPageWrites && PageGetLSN(page) <= RedoRecPtr)
890  return true; /* buffer requires backup */
891 
892  return false; /* buffer does not need to be backed up */
893 }
static bool doPageWrites
Definition: xlog.c:381
static XLogRecPtr RedoRecPtr
Definition: xlog.c:374
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define PageGetLSN(page)
Definition: bufpage.h:366
void GetFullPageWriteInfo(XLogRecPtr *RedoRecPtr_p, bool *doPageWrites_p)
Definition: xlog.c:8395
Pointer Page
Definition: bufpage.h:78

◆ XLogEnsureRecordSpace()

void XLogEnsureRecordSpace ( int  max_block_id,
int  ndatas 
)

Definition at line 149 of file xloginsert.c.

References Assert, CritSectionCount, elog, ERROR, max_rdatas, max_registered_buffers, MemSet, 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().

150 {
151  int nbuffers;
152 
153  /*
154  * This must be called before entering a critical section, because
155  * allocating memory inside a critical section can fail. repalloc() will
156  * check the same, but better to check it here too so that we fail
157  * consistently even if the arrays happen to be large enough already.
158  */
159  Assert(CritSectionCount == 0);
160 
161  /* the minimum values can't be decreased */
162  if (max_block_id < XLR_NORMAL_MAX_BLOCK_ID)
163  max_block_id = XLR_NORMAL_MAX_BLOCK_ID;
164  if (ndatas < XLR_NORMAL_RDATAS)
165  ndatas = XLR_NORMAL_RDATAS;
166 
167  if (max_block_id > XLR_MAX_BLOCK_ID)
168  elog(ERROR, "maximum number of WAL record block references exceeded");
169  nbuffers = max_block_id + 1;
170 
171  if (nbuffers > max_registered_buffers)
172  {
174  repalloc(registered_buffers, sizeof(registered_buffer) * nbuffers);
175 
176  /*
177  * At least the padding bytes in the structs must be zeroed, because
178  * they are included in WAL data, but initialize it all for tidiness.
179  */
181  (nbuffers - max_registered_buffers) * sizeof(registered_buffer));
182  max_registered_buffers = nbuffers;
183  }
184 
185  if (ndatas > max_rdatas)
186  {
187  rdatas = (XLogRecData *) repalloc(rdatas, sizeof(XLogRecData) * ndatas);
188  max_rdatas = ndatas;
189  }
190 }
#define XLR_NORMAL_RDATAS
Definition: xloginsert.h:28
#define MemSet(start, val, len)
Definition: c.h:949
#define ERROR
Definition: elog.h:43
static int max_registered_buffers
Definition: xloginsert.c:65
volatile uint32 CritSectionCount
Definition: globals.c:38
static int max_rdatas
Definition: xloginsert.c:105
#define XLR_MAX_BLOCK_ID
Definition: xlogrecord.h:221
static registered_buffer * registered_buffers
Definition: xloginsert.c:64
#define XLR_NORMAL_MAX_BLOCK_ID
Definition: xloginsert.h:27
#define Assert(condition)
Definition: c.h:745
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1070
#define elog(elevel,...)
Definition: elog.h:214
static XLogRecData * rdatas
Definition: xloginsert.c:103

◆ XLogInsert()

XLogRecPtr XLogInsert ( RmgrId  rmid,
uint8  info 
)

Definition at line 422 of file xloginsert.c.

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_one_page(), _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(), _bt_update_meta_cleanup_info(), _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(), createdb(), CreateEndOfRecoveryRecord(), createPostingTree(), CreateTableSpace(), do_pg_stop_backup(), do_setval(), doPickSplit(), DropTableSpace(), EndPrepare(), ExecuteTruncateGuts(), fill_seq_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_update(), log_heap_clean(), log_heap_cleanup_info(), 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(), RequestXLogSwitch(), revmap_physical_extend(), shiftList(), spgAddNodeAction(), spgSplitNodeAction(), UpdateFullPageWrites(), vacuumLeafPage(), vacuumLeafRoot(), vacuumRedirectAndPlaceholder(), write_relmap_file(), writeListPage(), WriteMTruncateXlogRec(), WriteMZeroPageXlogRec(), WriteSetTimestampXlogRec(), WriteTruncateXlogRec(), WriteZeroPageXlogRec(), XactLogAbortRecord(), XactLogCommitRecord(), XLogPutNextOid(), XLogReportParameters(), XLogRestorePoint(), XLogSaveBufferForHint(), and xlogVacuumPage().

423 {
424  XLogRecPtr EndPos;
425 
426  /* XLogBeginInsert() must have been called. */
427  if (!begininsert_called)
428  elog(ERROR, "XLogBeginInsert was not called");
429 
430  /*
431  * The caller can set rmgr bits, XLR_SPECIAL_REL_UPDATE and
432  * XLR_CHECK_CONSISTENCY; the rest are reserved for use by me.
433  */
434  if ((info & ~(XLR_RMGR_INFO_MASK |
436  XLR_CHECK_CONSISTENCY)) != 0)
437  elog(PANIC, "invalid xlog info mask %02X", info);
438 
439  TRACE_POSTGRESQL_WAL_INSERT(rmid, info);
440 
441  /*
442  * In bootstrap mode, we don't actually log anything but XLOG resources;
443  * return a phony record pointer.
444  */
445  if (IsBootstrapProcessingMode() && rmid != RM_XLOG_ID)
446  {
448  EndPos = SizeOfXLogLongPHD; /* start of 1st chkpt record */
449  return EndPos;
450  }
451 
452  do
453  {
455  bool doPageWrites;
456  XLogRecPtr fpw_lsn;
457  XLogRecData *rdt;
458  int num_fpi = 0;
459 
460  /*
461  * Get values needed to decide whether to do full-page writes. Since
462  * we don't yet have an insertion lock, these could change under us,
463  * but XLogInsertRecord will recheck them once it has a lock.
464  */
465  GetFullPageWriteInfo(&RedoRecPtr, &doPageWrites);
466 
467  rdt = XLogRecordAssemble(rmid, info, RedoRecPtr, doPageWrites,
468  &fpw_lsn, &num_fpi);
469 
470  EndPos = XLogInsertRecord(rdt, fpw_lsn, curinsert_flags, num_fpi);
471  } while (EndPos == InvalidXLogRecPtr);
472 
474 
475  return EndPos;
476 }
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
#define XLR_SPECIAL_REL_UPDATE
Definition: xlogrecord.h:71
static bool begininsert_called
Definition: xloginsert.c:107
#define PANIC
Definition: elog.h:53
#define XLR_CHECK_CONSISTENCY
Definition: xlogrecord.h:80
static bool doPageWrites
Definition: xlog.c:381
#define ERROR
Definition: elog.h:43
void XLogResetInsertion(void)
Definition: xloginsert.c:196
static XLogRecData * XLogRecordAssemble(RmgrId rmid, uint8 info, XLogRecPtr RedoRecPtr, bool doPageWrites, XLogRecPtr *fpw_lsn, int *num_fpi)
Definition: xloginsert.c:491
static XLogRecPtr RedoRecPtr
Definition: xlog.c:374
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:393
void GetFullPageWriteInfo(XLogRecPtr *RedoRecPtr_p, bool *doPageWrites_p)
Definition: xlog.c:8395
#define elog(elevel,...)
Definition: elog.h:214
XLogRecPtr XLogInsertRecord(XLogRecData *rdata, XLogRecPtr fpw_lsn, uint8 flags, int num_fpi)
Definition: xlog.c:999
static uint8 curinsert_flags
Definition: xloginsert.c:78
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:69
#define XLR_RMGR_INFO_MASK
Definition: xlogrecord.h:63

◆ XLogRegisterBlock()

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

Definition at line 273 of file xloginsert.c.

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, REGBUF_FORCE_IMAGE, RelFileNodeEquals, and registered_buffer::rnode.

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

275 {
276  registered_buffer *regbuf;
277 
278  /* This is currently only used to WAL-log a full-page image of a page */
279  Assert(flags & REGBUF_FORCE_IMAGE);
281 
282  if (block_id >= max_registered_block_id)
283  max_registered_block_id = block_id + 1;
284 
285  if (block_id >= max_registered_buffers)
286  elog(ERROR, "too many registered buffers");
287 
288  regbuf = &registered_buffers[block_id];
289 
290  regbuf->rnode = *rnode;
291  regbuf->forkno = forknum;
292  regbuf->block = blknum;
293  regbuf->page = page;
294  regbuf->flags = flags;
295  regbuf->rdata_tail = (XLogRecData *) &regbuf->rdata_head;
296  regbuf->rdata_len = 0;
297 
298  /*
299  * Check that this page hasn't already been registered with some other
300  * block_id.
301  */
302 #ifdef USE_ASSERT_CHECKING
303  {
304  int i;
305 
306  for (i = 0; i < max_registered_block_id; i++)
307  {
308  registered_buffer *regbuf_old = &registered_buffers[i];
309 
310  if (i == block_id || !regbuf_old->in_use)
311  continue;
312 
313  Assert(!RelFileNodeEquals(regbuf_old->rnode, regbuf->rnode) ||
314  regbuf_old->forkno != regbuf->forkno ||
315  regbuf_old->block != regbuf->block);
316  }
317  }
318 #endif
319 
320  regbuf->in_use = true;
321 }
BlockNumber block
Definition: xloginsert.c:49
static bool begininsert_called
Definition: xloginsert.c:107
XLogRecData * rdata_head
Definition: xloginsert.c:52
RelFileNode rnode
Definition: xloginsert.c:47
#define ERROR
Definition: elog.h:43
static int max_registered_buffers
Definition: xloginsert.c:65
XLogRecData * rdata_tail
Definition: xloginsert.c:54
static registered_buffer * registered_buffers
Definition: xloginsert.c:64
#define REGBUF_FORCE_IMAGE
Definition: xloginsert.h:31
#define Assert(condition)
Definition: c.h:745
ForkNumber forkno
Definition: xloginsert.c:48
static int max_registered_block_id
Definition: xloginsert.c:66
#define elog(elevel,...)
Definition: elog.h:214
int i
#define RelFileNodeEquals(node1, node2)
Definition: relfilenode.h:88

◆ XLogRegisterBufData()

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

Definition at line 368 of file xloginsert.c.

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

Referenced by _bt_dedup_one_page(), _bt_delitems_delete(), _bt_delitems_vacuum(), _bt_getroot(), _bt_insertonpg(), _bt_newroot(), _bt_split(), _bt_unlink_halfdead_page(), _bt_update_meta_cleanup_info(), _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(), log_heap_clean(), log_heap_freeze(), log_heap_update(), and writeListPage().

369 {
370  registered_buffer *regbuf;
371  XLogRecData *rdata;
372 
374 
375  /* find the registered buffer struct */
376  regbuf = &registered_buffers[block_id];
377  if (!regbuf->in_use)
378  elog(ERROR, "no block with id %d registered with WAL insertion",
379  block_id);
380 
381  if (num_rdatas >= max_rdatas)
382  elog(ERROR, "too much WAL data");
383  rdata = &rdatas[num_rdatas++];
384 
385  rdata->data = data;
386  rdata->len = len;
387 
388  regbuf->rdata_tail->next = rdata;
389  regbuf->rdata_tail = rdata;
390  regbuf->rdata_len += len;
391 }
static bool begininsert_called
Definition: xloginsert.c:107
#define ERROR
Definition: elog.h:43
XLogRecData * rdata_tail
Definition: xloginsert.c:54
static int max_rdatas
Definition: xloginsert.c:105
static registered_buffer * registered_buffers
Definition: xloginsert.c:64
static int num_rdatas
Definition: xloginsert.c:104
#define Assert(condition)
Definition: c.h:745
struct XLogRecData * next
#define elog(elevel,...)
Definition: elog.h:214
static XLogRecData * rdatas
Definition: xloginsert.c:103

◆ XLogRegisterBuffer()

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

Definition at line 220 of file xloginsert.c.

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, RelFileNodeEquals, and registered_buffer::rnode.

Referenced by _bt_dedup_one_page(), _bt_delitems_delete(), _bt_delitems_vacuum(), _bt_getroot(), _bt_insertonpg(), _bt_mark_page_halfdead(), _bt_newroot(), _bt_split(), _bt_unlink_halfdead_page(), _bt_update_meta_cleanup_info(), _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_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_update(), log_heap_clean(), 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().

221 {
222  registered_buffer *regbuf;
223 
224  /* NO_IMAGE doesn't make sense with FORCE_IMAGE */
225  Assert(!((flags & REGBUF_FORCE_IMAGE) && (flags & (REGBUF_NO_IMAGE))));
227 
228  if (block_id >= max_registered_block_id)
229  {
230  if (block_id >= max_registered_buffers)
231  elog(ERROR, "too many registered buffers");
232  max_registered_block_id = block_id + 1;
233  }
234 
235  regbuf = &registered_buffers[block_id];
236 
237  BufferGetTag(buffer, &regbuf->rnode, &regbuf->forkno, &regbuf->block);
238  regbuf->page = BufferGetPage(buffer);
239  regbuf->flags = flags;
240  regbuf->rdata_tail = (XLogRecData *) &regbuf->rdata_head;
241  regbuf->rdata_len = 0;
242 
243  /*
244  * Check that this page hasn't already been registered with some other
245  * block_id.
246  */
247 #ifdef USE_ASSERT_CHECKING
248  {
249  int i;
250 
251  for (i = 0; i < max_registered_block_id; i++)
252  {
253  registered_buffer *regbuf_old = &registered_buffers[i];
254 
255  if (i == block_id || !regbuf_old->in_use)
256  continue;
257 
258  Assert(!RelFileNodeEquals(regbuf_old->rnode, regbuf->rnode) ||
259  regbuf_old->forkno != regbuf->forkno ||
260  regbuf_old->block != regbuf->block);
261  }
262  }
263 #endif
264 
265  regbuf->in_use = true;
266 }
BlockNumber block
Definition: xloginsert.c:49
static bool begininsert_called
Definition: xloginsert.c:107
XLogRecData * rdata_head
Definition: xloginsert.c:52
RelFileNode rnode
Definition: xloginsert.c:47
#define ERROR
Definition: elog.h:43
static int max_registered_buffers
Definition: xloginsert.c:65
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
XLogRecData * rdata_tail
Definition: xloginsert.c:54
static registered_buffer * registered_buffers
Definition: xloginsert.c:64
#define REGBUF_FORCE_IMAGE
Definition: xloginsert.h:31
#define Assert(condition)
Definition: c.h:745
#define REGBUF_NO_IMAGE
Definition: xloginsert.h:32
ForkNumber forkno
Definition: xloginsert.c:48
static int max_registered_block_id
Definition: xloginsert.c:66
#define elog(elevel,...)
Definition: elog.h:214
int i
void BufferGetTag(Buffer buffer, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum)
Definition: bufmgr.c:2682
#define RelFileNodeEquals(node1, node2)
Definition: relfilenode.h:88

◆ XLogRegisterData()

void XLogRegisterData ( char *  data,
int  len 
)

Definition at line 330 of file xloginsert.c.

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

Referenced by _bt_dedup_one_page(), _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(), createdb(), CreateEndOfRecoveryRecord(), createPostingTree(), CreateTableSpace(), do_pg_stop_backup(), do_setval(), doPickSplit(), DropTableSpace(), EndPrepare(), ExecuteTruncateGuts(), fill_seq_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_update(), log_heap_clean(), log_heap_cleanup_info(), 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(), revmap_physical_extend(), shiftList(), spgAddNodeAction(), spgSplitNodeAction(), UpdateFullPageWrites(), vacuumLeafPage(), vacuumLeafRoot(), vacuumRedirectAndPlaceholder(), write_relmap_file(), writeListPage(), WriteMTruncateXlogRec(), WriteMZeroPageXlogRec(), WriteSetTimestampXlogRec(), WriteTruncateXlogRec(), WriteZeroPageXlogRec(), XactLogAbortRecord(), XactLogCommitRecord(), XLogPutNextOid(), XLogReportParameters(), and XLogRestorePoint().

331 {
332  XLogRecData *rdata;
333 
335 
336  if (num_rdatas >= max_rdatas)
337  elog(ERROR, "too much WAL data");
338  rdata = &rdatas[num_rdatas++];
339 
340  rdata->data = data;
341  rdata->len = len;
342 
343  /*
344  * we use the mainrdata_last pointer to track the end of the chain, so no
345  * need to clear 'next' here.
346  */
347 
348  mainrdata_last->next = rdata;
349  mainrdata_last = rdata;
350 
351  mainrdata_len += len;
352 }
static uint32 mainrdata_len
Definition: xloginsert.c:75
static bool begininsert_called
Definition: xloginsert.c:107
#define ERROR
Definition: elog.h:43
static int max_rdatas
Definition: xloginsert.c:105
static XLogRecData * mainrdata_last
Definition: xloginsert.c:74
static int num_rdatas
Definition: xloginsert.c:104
#define Assert(condition)
Definition: c.h:745
struct XLogRecData * next
#define elog(elevel,...)
Definition: elog.h:214
static XLogRecData * rdatas
Definition: xloginsert.c:103

◆ XLogResetInsertion()

void XLogResetInsertion ( void  )

Definition at line 196 of file xloginsert.c.

References begininsert_called, curinsert_flags, i, mainrdata_len, MarkSubTransactionAssigned(), max_registered_block_id, num_rdatas, and XLOG_INCLUDE_XID.

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

197 {
198  int i;
199 
200  /* reset the subxact assignment flag (if needed) */
203 
204  for (i = 0; i < max_registered_block_id; i++)
205  registered_buffers[i].in_use = false;
206 
207  num_rdatas = 0;
208  max_registered_block_id = 0;
209  mainrdata_len = 0;
211  curinsert_flags = 0;
212  begininsert_called = false;
213 }
void MarkSubTransactionAssigned(void)
Definition: xact.c:6107
static uint32 mainrdata_len
Definition: xloginsert.c:75
static bool begininsert_called
Definition: xloginsert.c:107
static XLogRecData * mainrdata_head
Definition: xloginsert.c:73
static registered_buffer * registered_buffers
Definition: xloginsert.c:64
#define XLOG_INCLUDE_XID
Definition: xlog.h:240
static XLogRecData * mainrdata_last
Definition: xloginsert.c:74
static int num_rdatas
Definition: xloginsert.c:104
static int max_registered_block_id
Definition: xloginsert.c:66
int i
static uint8 curinsert_flags
Definition: xloginsert.c:78

◆ XLogSaveBufferForHint()

XLogRecPtr XLogSaveBufferForHint ( Buffer  buffer,
bool  buffer_std 
)

Definition at line 917 of file xloginsert.c.

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

Referenced by MarkBufferDirtyHint().

918 {
919  XLogRecPtr recptr = InvalidXLogRecPtr;
920  XLogRecPtr lsn;
922 
923  /*
924  * Ensure no checkpoint can change our view of RedoRecPtr.
925  */
927 
928  /*
929  * Update RedoRecPtr so that we can make the right decision
930  */
931  RedoRecPtr = GetRedoRecPtr();
932 
933  /*
934  * We assume page LSN is first data on *every* page that can be passed to
935  * XLogInsert, whether it has the standard page layout or not. Since we're
936  * only holding a share-lock on the page, we must take the buffer header
937  * lock when we look at the LSN.
938  */
939  lsn = BufferGetLSNAtomic(buffer);
940 
941  if (lsn <= RedoRecPtr)
942  {
943  int flags;
944  PGAlignedBlock copied_buffer;
945  char *origdata = (char *) BufferGetBlock(buffer);
946  RelFileNode rnode;
947  ForkNumber forkno;
948  BlockNumber blkno;
949 
950  /*
951  * Copy buffer so we don't have to worry about concurrent hint bit or
952  * lsn updates. We assume pd_lower/upper cannot be changed without an
953  * exclusive lock, so the contents bkp are not racy.
954  */
955  if (buffer_std)
956  {
957  /* Assume we can omit data between pd_lower and pd_upper */
958  Page page = BufferGetPage(buffer);
959  uint16 lower = ((PageHeader) page)->pd_lower;
960  uint16 upper = ((PageHeader) page)->pd_upper;
961 
962  memcpy(copied_buffer.data, origdata, lower);
963  memcpy(copied_buffer.data + upper, origdata + upper, BLCKSZ - upper);
964  }
965  else
966  memcpy(copied_buffer.data, origdata, BLCKSZ);
967 
968  XLogBeginInsert();
969 
970  flags = REGBUF_FORCE_IMAGE;
971  if (buffer_std)
972  flags |= REGBUF_STANDARD;
973 
974  BufferGetTag(buffer, &rnode, &forkno, &blkno);
975  XLogRegisterBlock(0, &rnode, forkno, blkno, copied_buffer.data, flags);
976 
977  recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI_FOR_HINT);
978  }
979 
980  return recptr;
981 }
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
Datum lower(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:44
PGPROC * MyProc
Definition: proc.c:67
uint32 BlockNumber
Definition: block.h:31
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:75
char data[BLCKSZ]
Definition: c.h:1082
void XLogRegisterBlock(uint8 block_id, RelFileNode *rnode, ForkNumber forknum, BlockNumber blknum, Page page, uint8 flags)
Definition: xloginsert.c:273
unsigned short uint16
Definition: c.h:373
bool delayChkpt
Definition: proc.h:176
static XLogRecPtr RedoRecPtr
Definition: xlog.c:374
XLogRecPtr BufferGetLSNAtomic(Buffer buffer)
Definition: bufmgr.c:2924
#define REGBUF_STANDARD
Definition: xloginsert.h:35
#define BufferGetPage(buffer)
Definition: bufmgr.h:169
ForkNumber
Definition: relpath.h:40
#define REGBUF_FORCE_IMAGE
Definition: xloginsert.h:31
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:422
PageHeaderData * PageHeader
Definition: bufpage.h:166
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:745
#define XLOG_FPI_FOR_HINT
Definition: pg_control.h:77
XLogRecPtr GetRedoRecPtr(void)
Definition: xlog.c:8366
void BufferGetTag(Buffer buffer, RelFileNode *rnode, ForkNumber *forknum, BlockNumber *blknum)
Definition: bufmgr.c:2682
void XLogBeginInsert(void)
Definition: xloginsert.c:123
#define BufferGetBlock(buffer)
Definition: bufmgr.h:136
Pointer Page
Definition: bufpage.h:78

◆ XLogSetRecordFlags()