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/bufpage.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
 
#define REGBUF_NO_CHANGE   0x20 /* intentionally register clean buffer */
 

Functions

void XLogBeginInsert (void)
 
void XLogSetRecordFlags (uint8 flags)
 
XLogRecPtr XLogInsert (RmgrId rmid, uint8 info)
 
XLogRecPtr XLogSimpleInsertInt64 (RmgrId rmid, uint8 info, int64 value)
 
void XLogEnsureRecordSpace (int max_block_id, int ndatas)
 
void XLogRegisterData (const void *data, uint32 len)
 
void XLogRegisterBuffer (uint8 block_id, Buffer buffer, uint8 flags)
 
void XLogRegisterBlock (uint8 block_id, RelFileLocator *rlocator, ForkNumber forknum, BlockNumber blknum, const PageData *page, uint8 flags)
 
void XLogRegisterBufData (uint8 block_id, const void *data, uint32 len)
 
void XLogResetInsertion (void)
 
bool XLogCheckBufferNeedsBackup (Buffer buffer)
 
XLogRecPtr log_newpage (RelFileLocator *rlocator, ForkNumber forknum, BlockNumber blkno, Page page, bool page_std)
 
void log_newpages (RelFileLocator *rlocator, 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)
 
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 32 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 36 of file xloginsert.h.

◆ REGBUF_NO_CHANGE

#define REGBUF_NO_CHANGE   0x20 /* intentionally register clean buffer */

Definition at line 37 of file xloginsert.h.

◆ REGBUF_NO_IMAGE

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

Definition at line 33 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 35 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 34 of file xloginsert.h.

◆ XLR_NORMAL_MAX_BLOCK_ID

#define XLR_NORMAL_MAX_BLOCK_ID   4

Definition at line 28 of file xloginsert.h.

◆ XLR_NORMAL_RDATAS

#define XLR_NORMAL_RDATAS   20

Definition at line 29 of file xloginsert.h.

Function Documentation

◆ InitXLogInsert()

void InitXLogInsert ( void  )

Definition at line 1370 of file xloginsert.c.

1371{
1372#ifdef USE_ASSERT_CHECKING
1373
1374 /*
1375 * Check that any records assembled can be decoded. This is capped based
1376 * on what XLogReader would require at its maximum bound. The XLOG_BLCKSZ
1377 * addend covers the larger allocate_recordbuf() demand. This code path
1378 * is called once per backend, more than enough for this check.
1379 */
1380 size_t max_required =
1382
1383 Assert(AllocSizeIsValid(max_required));
1384#endif
1385
1386 /* Initialize the working areas */
1387 if (xloginsert_cxt == NULL)
1388 {
1390 "WAL record construction",
1392 }
1393
1394 if (registered_buffers == NULL)
1395 {
1400 }
1401 if (rdatas == NULL)
1402 {
1404 sizeof(XLogRecData) * XLR_NORMAL_RDATAS);
1406 }
1407
1408 /*
1409 * Allocate a buffer to hold the header information for a WAL record.
1410 */
1411 if (hdr_scratch == NULL)
1414}
Assert(PointerIsAligned(start, uint64))
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1229
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1263
MemoryContext TopMemoryContext
Definition: mcxt.c:166
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
#define AllocSizeIsValid(size)
Definition: memutils.h:42
static int max_registered_buffers
Definition: xloginsert.c:92
static MemoryContext xloginsert_cxt
Definition: xloginsert.c:137
static char * hdr_scratch
Definition: xloginsert.c:116
static XLogRecData * rdatas
Definition: xloginsert.c:130
static registered_buffer * registered_buffers
Definition: xloginsert.c:91
static int max_rdatas
Definition: xloginsert.c:132
#define HEADER_SCRATCH_SIZE
Definition: xloginsert.c:121
#define XLR_NORMAL_MAX_BLOCK_ID
Definition: xloginsert.h:28
#define XLR_NORMAL_RDATAS
Definition: xloginsert.h:29
size_t DecodeXLogRecordRequiredSpace(size_t xl_tot_len)
Definition: xlogreader.c:1649
#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,
Page  page,
bool  page_std 
)

Definition at line 1165 of file xloginsert.c.

1167{
1168 int flags;
1169 XLogRecPtr recptr;
1170
1171 flags = REGBUF_FORCE_IMAGE;
1172 if (page_std)
1173 flags |= REGBUF_STANDARD;
1174
1176 XLogRegisterBlock(0, rlocator, forknum, blkno, page, flags);
1177 recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI);
1178
1179 /*
1180 * The page may be uninitialized. If so, we can't set the LSN because that
1181 * would corrupt the page.
1182 */
1183 if (!PageIsNew(page))
1184 {
1185 PageSetLSN(page, recptr);
1186 }
1187
1188 return recptr;
1189}
static bool PageIsNew(const PageData *page)
Definition: bufpage.h:233
static void PageSetLSN(Page page, XLogRecPtr lsn)
Definition: bufpage.h:390
#define XLOG_FPI
Definition: pg_control.h:79
uint64 XLogRecPtr
Definition: xlogdefs.h:21
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:478
void XLogRegisterBlock(uint8 block_id, RelFileLocator *rlocator, ForkNumber forknum, BlockNumber blknum, const PageData *page, uint8 flags)
Definition: xloginsert.c:313
void XLogBeginInsert(void)
Definition: xloginsert.c:152
#define REGBUF_STANDARD
Definition: xloginsert.h:35
#define REGBUF_FORCE_IMAGE
Definition: xloginsert.h:32

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

Referenced by _hash_alloc_buckets(), _hash_init(), and log_newpage_buffer().

◆ log_newpage_buffer()

XLogRecPtr log_newpage_buffer ( Buffer  buffer,
bool  page_std 
)

Definition at line 1259 of file xloginsert.c.

1260{
1261 Page page = BufferGetPage(buffer);
1262 RelFileLocator rlocator;
1263 ForkNumber forknum;
1264 BlockNumber blkno;
1265
1266 /* Shared buffers should be modified in a critical section. */
1268
1269 BufferGetTag(buffer, &rlocator, &forknum, &blkno);
1270
1271 return log_newpage(&rlocator, forknum, blkno, page, page_std);
1272}
uint32 BlockNumber
Definition: block.h:31
void BufferGetTag(Buffer buffer, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum)
Definition: bufmgr.c:4244
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:425
PageData * Page
Definition: bufpage.h:81
volatile uint32 CritSectionCount
Definition: globals.c:45
ForkNumber
Definition: relpath.h:56
XLogRecPtr log_newpage(RelFileLocator *rlocator, ForkNumber forknum, BlockNumber blkno, Page page, bool page_std)
Definition: xloginsert.c:1165

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

1295{
1296 int flags;
1297 BlockNumber blkno;
1298
1299 flags = REGBUF_FORCE_IMAGE;
1300 if (page_std)
1301 flags |= REGBUF_STANDARD;
1302
1303 /*
1304 * Iterate over all the pages in the range. They are collected into
1305 * batches of XLR_MAX_BLOCK_ID pages, and a single WAL-record is written
1306 * for each batch.
1307 */
1309
1310 blkno = startblk;
1311 while (blkno < endblk)
1312 {
1313 Buffer bufpack[XLR_MAX_BLOCK_ID];
1314 XLogRecPtr recptr;
1315 int nbufs;
1316 int i;
1317
1319
1320 /* Collect a batch of blocks. */
1321 nbufs = 0;
1322 while (nbufs < XLR_MAX_BLOCK_ID && blkno < endblk)
1323 {
1324 Buffer buf = ReadBufferExtended(rel, forknum, blkno,
1325 RBM_NORMAL, NULL);
1326
1328
1329 /*
1330 * Completely empty pages are not WAL-logged. Writing a WAL record
1331 * would change the LSN, and we don't want that. We want the page
1332 * to stay empty.
1333 */
1335 bufpack[nbufs++] = buf;
1336 else
1338 blkno++;
1339 }
1340
1341 /* Nothing more to do if all remaining blocks were empty. */
1342 if (nbufs == 0)
1343 break;
1344
1345 /* Write WAL record for this batch. */
1347
1349 for (i = 0; i < nbufs; i++)
1350 {
1351 MarkBufferDirty(bufpack[i]);
1352 XLogRegisterBuffer(i, bufpack[i], flags);
1353 }
1354
1355 recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI);
1356
1357 for (i = 0; i < nbufs; i++)
1358 {
1359 PageSetLSN(BufferGetPage(bufpack[i]), recptr);
1360 UnlockReleaseBuffer(bufpack[i]);
1361 }
1363 }
1364}
int Buffer
Definition: buf.h:23
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:5383
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:2943
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:5604
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:792
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:205
@ RBM_NORMAL
Definition: bufmgr.h:46
int i
Definition: isn.c:77
#define START_CRIT_SECTION()
Definition: miscadmin.h:150
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:123
#define END_CRIT_SECTION()
Definition: miscadmin.h:152
static char * buf
Definition: pg_test_fsync.c:72
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:245
void XLogEnsureRecordSpace(int max_block_id, int ndatas)
Definition: xloginsert.c:178
#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,
Page pages,
bool  page_std 
)

Definition at line 1197 of file xloginsert.c.

1199{
1200 int flags;
1201 XLogRecPtr recptr;
1202 int i;
1203 int j;
1204
1205 flags = REGBUF_FORCE_IMAGE;
1206 if (page_std)
1207 flags |= REGBUF_STANDARD;
1208
1209 /*
1210 * Iterate over all the pages. They are collected into batches of
1211 * XLR_MAX_BLOCK_ID pages, and a single WAL-record is written for each
1212 * batch.
1213 */
1215
1216 i = 0;
1217 while (i < num_pages)
1218 {
1219 int batch_start = i;
1220 int nbatch;
1221
1223
1224 nbatch = 0;
1225 while (nbatch < XLR_MAX_BLOCK_ID && i < num_pages)
1226 {
1227 XLogRegisterBlock(nbatch, rlocator, forknum, blknos[i], pages[i], flags);
1228 i++;
1229 nbatch++;
1230 }
1231
1232 recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI);
1233
1234 for (j = batch_start; j < i; j++)
1235 {
1236 /*
1237 * The page may be uninitialized. If so, we can't set the LSN
1238 * because that would corrupt the page.
1239 */
1240 if (!PageIsNew(pages[j]))
1241 {
1242 PageSetLSN(pages[j], recptr);
1243 }
1244 }
1245 }
1246}
int j
Definition: isn.c:78
Datum batch_start(PG_FUNCTION_ARGS)
Definition: test_aio.c:668

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

Referenced by smgr_bulk_flush().

◆ XLogBeginInsert()

void XLogBeginInsert ( void  )

Definition at line 152 of file xloginsert.c.

153{
156 Assert(mainrdata_len == 0);
157
158 /* cross-check on whether we should be here or not */
159 if (!XLogInsertAllowed())
160 elog(ERROR, "cannot make new WAL entries during recovery");
161
163 elog(ERROR, "XLogBeginInsert was already called");
164
165 begininsert_called = true;
166}
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
bool XLogInsertAllowed(void)
Definition: xlog.c:6461
static XLogRecData * mainrdata_head
Definition: xloginsert.c:100
static uint64 mainrdata_len
Definition: xloginsert.c:102
static bool begininsert_called
Definition: xloginsert.c:134
static int max_registered_block_id
Definition: xloginsert.c:93
static XLogRecData * mainrdata_last
Definition: xloginsert.c:101

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(), 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_and_unlock(), heap_insert(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_update(), log_heap_new_cid(), log_heap_prune_and_freeze(), 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(), SetSequence(), shiftList(), spgAddNodeAction(), spgSplitNodeAction(), test_custom_rmgrs_insert_wal_record(), UpdateFullPageWrites(), vacuumLeafPage(), vacuumLeafRoot(), vacuumRedirectAndPlaceholder(), write_relmap_file(), writeListPage(), WriteMTruncateXlogRec(), WriteTruncateXlogRec(), XactLogAbortRecord(), XactLogCommitRecord(), XLogPutNextOid(), XLogReportParameters(), XLogRestorePoint(), XLogSaveBufferForHint(), XLogSimpleInsertInt64(), and xlogVacuumPage().

◆ XLogCheckBufferNeedsBackup()

bool XLogCheckBufferNeedsBackup ( Buffer  buffer)

Definition at line 1049 of file xloginsert.c.

1050{
1052 bool doPageWrites;
1053 Page page;
1054
1056
1057 page = BufferGetPage(buffer);
1058
1059 if (doPageWrites && PageGetLSN(page) <= RedoRecPtr)
1060 return true; /* buffer requires backup */
1061
1062 return false; /* buffer does not need to be backed up */
1063}
static XLogRecPtr PageGetLSN(const PageData *page)
Definition: bufpage.h:385
void GetFullPageWriteInfo(XLogRecPtr *RedoRecPtr_p, bool *doPageWrites_p)
Definition: xlog.c:6539
static XLogRecPtr RedoRecPtr
Definition: xlog.c:275
static bool doPageWrites
Definition: xlog.c:288

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

Referenced by heap_page_will_freeze(), and log_heap_update().

◆ XLogEnsureRecordSpace()

void XLogEnsureRecordSpace ( int  max_block_id,
int  ndatas 
)

Definition at line 178 of file xloginsert.c.

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

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

479{
480 XLogRecPtr EndPos;
481
482 /* XLogBeginInsert() must have been called. */
484 elog(ERROR, "XLogBeginInsert was not called");
485
486 /*
487 * The caller can set rmgr bits, XLR_SPECIAL_REL_UPDATE and
488 * XLR_CHECK_CONSISTENCY; the rest are reserved for use by me.
489 */
490 if ((info & ~(XLR_RMGR_INFO_MASK |
493 elog(PANIC, "invalid xlog info mask %02X", info);
494
495 TRACE_POSTGRESQL_WAL_INSERT(rmid, info);
496
497 /*
498 * In bootstrap mode, we don't actually log anything but XLOG resources;
499 * return a phony record pointer.
500 */
501 if (IsBootstrapProcessingMode() && rmid != RM_XLOG_ID)
502 {
504 EndPos = SizeOfXLogLongPHD; /* start of 1st chkpt record */
505 return EndPos;
506 }
507
508 do
509 {
511 bool doPageWrites;
512 bool topxid_included = false;
513 XLogRecPtr fpw_lsn;
514 XLogRecData *rdt;
515 int num_fpi = 0;
516 uint64 fpi_bytes = 0;
517
518 /*
519 * Get values needed to decide whether to do full-page writes. Since
520 * we don't yet have an insertion lock, these could change under us,
521 * but XLogInsertRecord will recheck them once it has a lock.
522 */
524
525 rdt = XLogRecordAssemble(rmid, info, RedoRecPtr, doPageWrites,
526 &fpw_lsn, &num_fpi, &fpi_bytes,
527 &topxid_included);
528
529 EndPos = XLogInsertRecord(rdt, fpw_lsn, curinsert_flags, num_fpi,
530 fpi_bytes, topxid_included);
531 } while (!XLogRecPtrIsValid(EndPos));
532
534
535 return EndPos;
536}
uint64_t uint64
Definition: c.h:544
#define PANIC
Definition: elog.h:42
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:477
XLogRecPtr XLogInsertRecord(XLogRecData *rdata, XLogRecPtr fpw_lsn, uint8 flags, int num_fpi, uint64 fpi_bytes, bool topxid_included)
Definition: xlog.c:749
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:69
#define XLogRecPtrIsValid(r)
Definition: xlogdefs.h:29
static uint8 curinsert_flags
Definition: xloginsert.c:105
void XLogResetInsertion(void)
Definition: xloginsert.c:225
static XLogRecData * XLogRecordAssemble(RmgrId rmid, uint8 info, XLogRecPtr RedoRecPtr, bool doPageWrites, XLogRecPtr *fpw_lsn, int *num_fpi, uint64 *fpi_bytes, bool *topxid_included)
Definition: xloginsert.c:566
#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(), IsBootstrapProcessingMode, PANIC, RedoRecPtr, SizeOfXLogLongPHD, XLogInsertRecord(), XLogRecordAssemble(), XLogRecPtrIsValid, 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(), 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_and_unlock(), heap_insert(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_update(), log_heap_new_cid(), log_heap_prune_and_freeze(), 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(), SetSequence(), shiftList(), spgAddNodeAction(), spgSplitNodeAction(), test_custom_rmgrs_insert_wal_record(), UpdateFullPageWrites(), vacuumLeafPage(), vacuumLeafRoot(), vacuumRedirectAndPlaceholder(), write_relmap_file(), writeListPage(), WriteMTruncateXlogRec(), WriteTruncateXlogRec(), XactLogAbortRecord(), XactLogCommitRecord(), XLogPutNextOid(), XLogReportParameters(), XLogRestorePoint(), XLogSaveBufferForHint(), XLogSimpleInsertInt64(), and xlogVacuumPage().

◆ XLogRegisterBlock()

void XLogRegisterBlock ( uint8  block_id,
RelFileLocator rlocator,
ForkNumber  forknum,
BlockNumber  blknum,
const PageData page,
uint8  flags 
)

Definition at line 313 of file xloginsert.c.

315{
316 registered_buffer *regbuf;
317
319
320 if (block_id >= max_registered_block_id)
321 max_registered_block_id = block_id + 1;
322
323 if (block_id >= max_registered_buffers)
324 elog(ERROR, "too many registered buffers");
325
326 regbuf = &registered_buffers[block_id];
327
328 regbuf->rlocator = *rlocator;
329 regbuf->forkno = forknum;
330 regbuf->block = blknum;
331 regbuf->page = page;
332 regbuf->flags = flags;
333 regbuf->rdata_tail = (XLogRecData *) &regbuf->rdata_head;
334 regbuf->rdata_len = 0;
335
336 /*
337 * Check that this page hasn't already been registered with some other
338 * block_id.
339 */
340#ifdef USE_ASSERT_CHECKING
341 {
342 int i;
343
344 for (i = 0; i < max_registered_block_id; i++)
345 {
346 registered_buffer *regbuf_old = &registered_buffers[i];
347
348 if (i == block_id || !regbuf_old->in_use)
349 continue;
350
351 Assert(!RelFileLocatorEquals(regbuf_old->rlocator, regbuf->rlocator) ||
352 regbuf_old->forkno != regbuf->forkno ||
353 regbuf_old->block != regbuf->block);
354 }
355 }
356#endif
357
358 regbuf->in_use = true;
359}
for(;;)
#define RelFileLocatorEquals(locator1, locator2)
XLogRecData * rdata_tail
Definition: xloginsert.c:81
BlockNumber block
Definition: xloginsert.c:76
XLogRecData * rdata_head
Definition: xloginsert.c:79
ForkNumber forkno
Definition: xloginsert.c:75
RelFileLocator rlocator
Definition: xloginsert.c:74
const PageData * page
Definition: xloginsert.c:77

References Assert(), begininsert_called, registered_buffer::block, elog, ERROR, registered_buffer::flags, for(), 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 heap_inplace_update_and_unlock(), log_newpage(), log_newpages(), and XLogSaveBufferForHint().

◆ XLogRegisterBufData()

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

Definition at line 409 of file xloginsert.c.

410{
411 registered_buffer *regbuf;
412 XLogRecData *rdata;
413
415
416 /* find the registered buffer struct */
417 regbuf = &registered_buffers[block_id];
418 if (!regbuf->in_use)
419 elog(ERROR, "no block with id %d registered with WAL insertion",
420 block_id);
421
422 /*
423 * Check against max_rdatas and ensure we do not register more data per
424 * buffer than can be handled by the physical data format; i.e. that
425 * regbuf->rdata_len does not grow beyond what
426 * XLogRecordBlockHeader->data_length can hold.
427 */
428 if (num_rdatas >= max_rdatas)
430 (errmsg_internal("too much WAL data"),
431 errdetail_internal("%d out of %d data segments are already in use.",
433 if (regbuf->rdata_len + len > UINT16_MAX || len > UINT16_MAX)
435 (errmsg_internal("too much WAL data"),
436 errdetail_internal("Registering more than maximum %u bytes allowed to block %u: current %u bytes, adding %u bytes.",
437 UINT16_MAX, block_id, regbuf->rdata_len, len)));
438
439 rdata = &rdatas[num_rdatas++];
440
441 rdata->data = data;
442 rdata->len = len;
443
444 regbuf->rdata_tail->next = rdata;
445 regbuf->rdata_tail = rdata;
446 regbuf->rdata_len += len;
447}
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1170
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1243
#define ereport(elevel,...)
Definition: elog.h:150
const void size_t len
const void * data
const void * data
struct XLogRecData * next
static int num_rdatas
Definition: xloginsert.c:131

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_inplace_update_and_unlock(), heap_insert(), heap_multi_insert(), log_heap_prune_and_freeze(), log_heap_update(), and writeListPage().

◆ XLogRegisterBuffer()

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

Definition at line 245 of file xloginsert.c.

246{
247 registered_buffer *regbuf;
248
249 /* NO_IMAGE doesn't make sense with FORCE_IMAGE */
250 Assert(!((flags & REGBUF_FORCE_IMAGE) && (flags & (REGBUF_NO_IMAGE))));
252
253 /*
254 * Ordinarily, buffer should be exclusive-locked and marked dirty before
255 * we get here, otherwise we could end up violating one of the rules in
256 * access/transam/README.
257 *
258 * Some callers intentionally register a clean page and never update that
259 * page's LSN; in that case they can pass the flag REGBUF_NO_CHANGE to
260 * bypass these checks.
261 */
262#ifdef USE_ASSERT_CHECKING
263 if (!(flags & REGBUF_NO_CHANGE))
265 BufferIsDirty(buffer));
266#endif
267
268 if (block_id >= max_registered_block_id)
269 {
270 if (block_id >= max_registered_buffers)
271 elog(ERROR, "too many registered buffers");
272 max_registered_block_id = block_id + 1;
273 }
274
275 regbuf = &registered_buffers[block_id];
276
277 BufferGetTag(buffer, &regbuf->rlocator, &regbuf->forkno, &regbuf->block);
278 regbuf->page = BufferGetPage(buffer);
279 regbuf->flags = flags;
280 regbuf->rdata_tail = (XLogRecData *) &regbuf->rdata_head;
281 regbuf->rdata_len = 0;
282
283 /*
284 * Check that this page hasn't already been registered with some other
285 * block_id.
286 */
287#ifdef USE_ASSERT_CHECKING
288 {
289 int i;
290
291 for (i = 0; i < max_registered_block_id; i++)
292 {
293 registered_buffer *regbuf_old = &registered_buffers[i];
294
295 if (i == block_id || !regbuf_old->in_use)
296 continue;
297
298 Assert(!RelFileLocatorEquals(regbuf_old->rlocator, regbuf->rlocator) ||
299 regbuf_old->forkno != regbuf->forkno ||
300 regbuf_old->block != regbuf->block);
301 }
302 }
303#endif
304
305 regbuf->in_use = true;
306}
bool BufferIsLockedByMeInMode(Buffer buffer, int mode)
Definition: bufmgr.c:2869
bool BufferIsDirty(Buffer buffer)
Definition: bufmgr.c:2911
#define REGBUF_NO_CHANGE
Definition: xloginsert.h:37
#define REGBUF_NO_IMAGE
Definition: xloginsert.h:33

References Assert(), begininsert_called, registered_buffer::block, BUFFER_LOCK_EXCLUSIVE, BufferGetPage(), BufferGetTag(), BufferIsDirty(), BufferIsLockedByMeInMode(), elog, ERROR, registered_buffer::flags, for(), 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_CHANGE, 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(), dataExecPlaceToPageInternal(), dataExecPlaceToPageLeaf(), doPickSplit(), entryExecPlaceToPage(), 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_insert(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_update(), log_heap_prune_and_freeze(), log_heap_update(), log_heap_visible(), log_newpage_range(), log_split_page(), moveLeafs(), nextval_internal(), revmap_physical_extend(), SetSequence(), shiftList(), spgAddNodeAction(), spgSplitNodeAction(), vacuumLeafPage(), vacuumLeafRoot(), vacuumRedirectAndPlaceholder(), writeListPage(), and xlogVacuumPage().

◆ XLogRegisterData()

void XLogRegisterData ( const void *  data,
uint32  len 
)

Definition at line 368 of file xloginsert.c.

369{
370 XLogRecData *rdata;
371
373
374 if (num_rdatas >= max_rdatas)
376 (errmsg_internal("too much WAL data"),
377 errdetail_internal("%d out of %d data segments are already in use.",
379 rdata = &rdatas[num_rdatas++];
380
381 rdata->data = data;
382 rdata->len = len;
383
384 /*
385 * we use the mainrdata_last pointer to track the end of the chain, so no
386 * need to clear 'next' here.
387 */
388
389 mainrdata_last->next = rdata;
390 mainrdata_last = rdata;
391
393}

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(), 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_and_unlock(), heap_insert(), heap_lock_tuple(), heap_lock_updated_tuple_rec(), heap_multi_insert(), heap_update(), log_heap_new_cid(), log_heap_prune_and_freeze(), 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(), SetSequence(), shiftList(), spgAddNodeAction(), spgSplitNodeAction(), test_custom_rmgrs_insert_wal_record(), UpdateFullPageWrites(), vacuumLeafPage(), vacuumLeafRoot(), vacuumRedirectAndPlaceholder(), write_relmap_file(), writeListPage(), WriteMTruncateXlogRec(), WriteTruncateXlogRec(), XactLogAbortRecord(), XactLogCommitRecord(), XLogPutNextOid(), XLogReportParameters(), XLogRestorePoint(), and XLogSimpleInsertInt64().

◆ XLogResetInsertion()

void XLogResetInsertion ( void  )

◆ XLogSaveBufferForHint()

XLogRecPtr XLogSaveBufferForHint ( Buffer  buffer,
bool  buffer_std 
)

Definition at line 1087 of file xloginsert.c.

1088{
1090 XLogRecPtr lsn;
1092
1093 /*
1094 * Ensure no checkpoint can change our view of RedoRecPtr.
1095 */
1097
1098 /*
1099 * Update RedoRecPtr so that we can make the right decision
1100 */
1102
1103 /*
1104 * We assume page LSN is first data on *every* page that can be passed to
1105 * XLogInsert, whether it has the standard page layout or not. Since we're
1106 * only holding a share-lock on the page, we must take the buffer header
1107 * lock when we look at the LSN.
1108 */
1109 lsn = BufferGetLSNAtomic(buffer);
1110
1111 if (lsn <= RedoRecPtr)
1112 {
1113 int flags = 0;
1114 PGAlignedBlock copied_buffer;
1115 char *origdata = (char *) BufferGetBlock(buffer);
1116 RelFileLocator rlocator;
1117 ForkNumber forkno;
1118 BlockNumber blkno;
1119
1120 /*
1121 * Copy buffer so we don't have to worry about concurrent hint bit or
1122 * lsn updates. We assume pd_lower/upper cannot be changed without an
1123 * exclusive lock, so the contents bkp are not racy.
1124 */
1125 if (buffer_std)
1126 {
1127 /* Assume we can omit data between pd_lower and pd_upper */
1128 Page page = BufferGetPage(buffer);
1129 uint16 lower = ((PageHeader) page)->pd_lower;
1130 uint16 upper = ((PageHeader) page)->pd_upper;
1131
1132 memcpy(copied_buffer.data, origdata, lower);
1133 memcpy(copied_buffer.data + upper, origdata + upper, BLCKSZ - upper);
1134 }
1135 else
1136 memcpy(copied_buffer.data, origdata, BLCKSZ);
1137
1139
1140 if (buffer_std)
1141 flags |= REGBUF_STANDARD;
1142
1143 BufferGetTag(buffer, &rlocator, &forkno, &blkno);
1144 XLogRegisterBlock(0, &rlocator, forkno, blkno, copied_buffer.data, flags);
1145
1146 recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI_FOR_HINT);
1147 }
1148
1149 return recptr;
1150}
XLogRecPtr BufferGetLSNAtomic(Buffer buffer)
Definition: bufmgr.c:4499
static Block BufferGetBlock(Buffer buffer)
Definition: bufmgr.h:392
PageHeaderData * PageHeader
Definition: bufpage.h:173
uint16_t uint16
Definition: c.h:542
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:78
#define DELAY_CHKPT_START
Definition: proc.h:135
PGPROC * MyProc
Definition: proc.c:67
char data[BLCKSZ]
Definition: c.h:1121
int delayChkptFlags
Definition: proc.h:257
XLogRecPtr GetRedoRecPtr(void)
Definition: xlog.c:6509
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28

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

◆ XLogSimpleInsertInt64()

XLogRecPtr XLogSimpleInsertInt64 ( RmgrId  rmid,
uint8  info,
int64  value 
)

Definition at line 543 of file xloginsert.c.

544{
546 XLogRegisterData(&value, sizeof(value));
547 return XLogInsert(rmid, info);
548}
static struct @171 value
void XLogRegisterData(const void *data, uint32 len)
Definition: xloginsert.c:368

References value, XLogBeginInsert(), XLogInsert(), and XLogRegisterData().

Referenced by ExtendCLOG(), ExtendCommitTs(), ExtendMultiXactMember(), and ExtendMultiXactOffset().