PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
xloginsert.c File Reference
#include "postgres.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "access/xlog_internal.h"
#include "access/xloginsert.h"
#include "catalog/pg_control.h"
#include "common/pg_lzcompress.h"
#include "miscadmin.h"
#include "pg_trace.h"
#include "replication/origin.h"
#include "storage/bufmgr.h"
#include "storage/proc.h"
#include "utils/memutils.h"
Include dependency graph for xloginsert.c:

Go to the source code of this file.

Data Structures

struct  registered_buffer
 

Macros

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

Functions

static XLogRecDataXLogRecordAssemble (RmgrId rmid, uint8 info, XLogRecPtr RedoRecPtr, bool doPageWrites, XLogRecPtr *fpw_lsn, int *num_fpi, bool *topxid_included)
 
static bool XLogCompressBackupBlock (const PageData *page, uint16 hole_offset, uint16 hole_length, void *dest, uint16 *dlen)
 
void XLogBeginInsert (void)
 
void XLogEnsureRecordSpace (int max_block_id, int ndatas)
 
void XLogResetInsertion (void)
 
void XLogRegisterBuffer (uint8 block_id, Buffer buffer, uint8 flags)
 
void XLogRegisterBlock (uint8 block_id, RelFileLocator *rlocator, ForkNumber forknum, BlockNumber blknum, const PageData *page, uint8 flags)
 
void XLogRegisterData (const void *data, uint32 len)
 
void XLogRegisterBufData (uint8 block_id, const void *data, uint32 len)
 
void XLogSetRecordFlags (uint8 flags)
 
XLogRecPtr XLogInsert (RmgrId rmid, uint8 info)
 
bool XLogCheckBufferNeedsBackup (Buffer buffer)
 
XLogRecPtr XLogSaveBufferForHint (Buffer buffer, bool buffer_std)
 
XLogRecPtr log_newpage (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)
 
void InitXLogInsert (void)
 

Variables

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

Macro Definition Documentation

◆ COMPRESS_BUFSIZE

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

Definition at line 62 of file xloginsert.c.

◆ HEADER_SCRATCH_SIZE

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

Definition at line 119 of file xloginsert.c.

◆ LZ4_MAX_BLCKSZ

#define LZ4_MAX_BLCKSZ   0

Definition at line 50 of file xloginsert.c.

◆ PGLZ_MAX_BLCKSZ

#define PGLZ_MAX_BLCKSZ   PGLZ_MAX_OUTPUT(BLCKSZ)

Definition at line 59 of file xloginsert.c.

◆ SizeOfXlogOrigin

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

Definition at line 116 of file xloginsert.c.

◆ SizeOfXLogTransactionId

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

Definition at line 117 of file xloginsert.c.

◆ ZSTD_MAX_BLCKSZ

#define ZSTD_MAX_BLCKSZ   0

Definition at line 56 of file xloginsert.c.

Function Documentation

◆ InitXLogInsert()

void InitXLogInsert ( void  )

Definition at line 1348 of file xloginsert.c.

1349{
1350#ifdef USE_ASSERT_CHECKING
1351
1352 /*
1353 * Check that any records assembled can be decoded. This is capped based
1354 * on what XLogReader would require at its maximum bound. The XLOG_BLCKSZ
1355 * addend covers the larger allocate_recordbuf() demand. This code path
1356 * is called once per backend, more than enough for this check.
1357 */
1358 size_t max_required =
1360
1361 Assert(AllocSizeIsValid(max_required));
1362#endif
1363
1364 /* Initialize the working areas */
1365 if (xloginsert_cxt == NULL)
1366 {
1368 "WAL record construction",
1370 }
1371
1372 if (registered_buffers == NULL)
1373 {
1378 }
1379 if (rdatas == NULL)
1380 {
1382 sizeof(XLogRecData) * XLR_NORMAL_RDATAS);
1384 }
1385
1386 /*
1387 * Allocate a buffer to hold the header information for a WAL record.
1388 */
1389 if (hdr_scratch == NULL)
1392}
Assert(PointerIsAligned(start, uint64))
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1256
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1290
MemoryContext TopMemoryContext
Definition: mcxt.c:165
#define AllocSetContextCreate
Definition: memutils.h:149
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:180
#define AllocSizeIsValid(size)
Definition: memutils.h:45
static int max_registered_buffers
Definition: xloginsert.c:90
static MemoryContext xloginsert_cxt
Definition: xloginsert.c:135
static char * hdr_scratch
Definition: xloginsert.c:114
static XLogRecData * rdatas
Definition: xloginsert.c:128
static registered_buffer * registered_buffers
Definition: xloginsert.c:89
static int max_rdatas
Definition: xloginsert.c:130
#define HEADER_SCRATCH_SIZE
Definition: xloginsert.c:119
#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:1639
#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 1143 of file xloginsert.c.

1145{
1146 int flags;
1147 XLogRecPtr recptr;
1148
1149 flags = REGBUF_FORCE_IMAGE;
1150 if (page_std)
1151 flags |= REGBUF_STANDARD;
1152
1154 XLogRegisterBlock(0, rlocator, forknum, blkno, page, flags);
1155 recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI);
1156
1157 /*
1158 * The page may be uninitialized. If so, we can't set the LSN because that
1159 * would corrupt the page.
1160 */
1161 if (!PageIsNew(page))
1162 {
1163 PageSetLSN(page, recptr);
1164 }
1165
1166 return recptr;
1167}
static bool PageIsNew(const PageData *page)
Definition: bufpage.h:234
static void PageSetLSN(Page page, XLogRecPtr lsn)
Definition: bufpage.h:391
#define XLOG_FPI
Definition: pg_control.h:79
uint64 XLogRecPtr
Definition: xlogdefs.h:21
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:474
void XLogRegisterBlock(uint8 block_id, RelFileLocator *rlocator, ForkNumber forknum, BlockNumber blknum, const PageData *page, uint8 flags)
Definition: xloginsert.c:309
void XLogBeginInsert(void)
Definition: xloginsert.c:149
#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 1237 of file xloginsert.c.

1238{
1239 Page page = BufferGetPage(buffer);
1240 RelFileLocator rlocator;
1241 ForkNumber forknum;
1242 BlockNumber blkno;
1243
1244 /* Shared buffers should be modified in a critical section. */
1246
1247 BufferGetTag(buffer, &rlocator, &forknum, &blkno);
1248
1249 return log_newpage(&rlocator, forknum, blkno, page, page_std);
1250}
uint32 BlockNumber
Definition: block.h:31
void BufferGetTag(Buffer buffer, RelFileLocator *rlocator, ForkNumber *forknum, BlockNumber *blknum)
Definition: bufmgr.c:4182
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:414
PageData * Page
Definition: bufpage.h:82
volatile uint32 CritSectionCount
Definition: globals.c:46
ForkNumber
Definition: relpath.h:56
XLogRecPtr log_newpage(RelFileLocator *rlocator, ForkNumber forknum, BlockNumber blkno, Page page, bool page_std)
Definition: xloginsert.c:1143

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

1273{
1274 int flags;
1275 BlockNumber blkno;
1276
1277 flags = REGBUF_FORCE_IMAGE;
1278 if (page_std)
1279 flags |= REGBUF_STANDARD;
1280
1281 /*
1282 * Iterate over all the pages in the range. They are collected into
1283 * batches of XLR_MAX_BLOCK_ID pages, and a single WAL-record is written
1284 * for each batch.
1285 */
1287
1288 blkno = startblk;
1289 while (blkno < endblk)
1290 {
1291 Buffer bufpack[XLR_MAX_BLOCK_ID];
1292 XLogRecPtr recptr;
1293 int nbufs;
1294 int i;
1295
1297
1298 /* Collect a batch of blocks. */
1299 nbufs = 0;
1300 while (nbufs < XLR_MAX_BLOCK_ID && blkno < endblk)
1301 {
1302 Buffer buf = ReadBufferExtended(rel, forknum, blkno,
1303 RBM_NORMAL, NULL);
1304
1306
1307 /*
1308 * Completely empty pages are not WAL-logged. Writing a WAL record
1309 * would change the LSN, and we don't want that. We want the page
1310 * to stay empty.
1311 */
1313 bufpack[nbufs++] = buf;
1314 else
1316 blkno++;
1317 }
1318
1319 /* Nothing more to do if all remaining blocks were empty. */
1320 if (nbufs == 0)
1321 break;
1322
1323 /* Write WAL record for this batch. */
1325
1327 for (i = 0; i < nbufs; i++)
1328 {
1329 MarkBufferDirty(bufpack[i]);
1330 XLogRegisterBuffer(i, bufpack[i], flags);
1331 }
1332
1333 recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI);
1334
1335 for (i = 0; i < nbufs; i++)
1336 {
1337 PageSetLSN(BufferGetPage(bufpack[i]), recptr);
1338 UnlockReleaseBuffer(bufpack[i]);
1339 }
1341 }
1342}
int Buffer
Definition: buf.h:23
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:5320
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:2945
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:5537
Buffer ReadBufferExtended(Relation reln, ForkNumber forkNum, BlockNumber blockNum, ReadBufferMode mode, BufferAccessStrategy strategy)
Definition: bufmgr.c:798
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:198
@ 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:242
void XLogEnsureRecordSpace(int max_block_id, int ndatas)
Definition: xloginsert.c:175

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

1177{
1178 int flags;
1179 XLogRecPtr recptr;
1180 int i;
1181 int j;
1182
1183 flags = REGBUF_FORCE_IMAGE;
1184 if (page_std)
1185 flags |= REGBUF_STANDARD;
1186
1187 /*
1188 * Iterate over all the pages. They are collected into batches of
1189 * XLR_MAX_BLOCK_ID pages, and a single WAL-record is written for each
1190 * batch.
1191 */
1193
1194 i = 0;
1195 while (i < num_pages)
1196 {
1197 int batch_start = i;
1198 int nbatch;
1199
1201
1202 nbatch = 0;
1203 while (nbatch < XLR_MAX_BLOCK_ID && i < num_pages)
1204 {
1205 XLogRegisterBlock(nbatch, rlocator, forknum, blknos[i], pages[i], flags);
1206 i++;
1207 nbatch++;
1208 }
1209
1210 recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI);
1211
1212 for (j = batch_start; j < i; j++)
1213 {
1214 /*
1215 * The page may be uninitialized. If so, we can't set the LSN
1216 * because that would corrupt the page.
1217 */
1218 if (!PageIsNew(pages[j]))
1219 {
1220 PageSetLSN(pages[j], recptr);
1221 }
1222 }
1223 }
1224}
int j
Definition: isn.c:78
Datum batch_start(PG_FUNCTION_ARGS)
Definition: test_aio.c:662

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

150{
153 Assert(mainrdata_len == 0);
154
155 /* cross-check on whether we should be here or not */
156 if (!XLogInsertAllowed())
157 elog(ERROR, "cannot make new WAL entries during recovery");
158
160 elog(ERROR, "XLogBeginInsert was already called");
161
162 begininsert_called = true;
163}
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
bool XLogInsertAllowed(void)
Definition: xlog.c:6577
static XLogRecData * mainrdata_head
Definition: xloginsert.c:98
static uint64 mainrdata_len
Definition: xloginsert.c:100
static bool begininsert_called
Definition: xloginsert.c:132
static int max_registered_block_id
Definition: xloginsert.c:91
static XLogRecData * mainrdata_last
Definition: xloginsert.c:99

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_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(), 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 1027 of file xloginsert.c.

1028{
1030 bool doPageWrites;
1031 Page page;
1032
1034
1035 page = BufferGetPage(buffer);
1036
1037 if (doPageWrites && PageGetLSN(page) <= RedoRecPtr)
1038 return true; /* buffer requires backup */
1039
1040 return false; /* buffer does not need to be backed up */
1041}
static XLogRecPtr PageGetLSN(const PageData *page)
Definition: bufpage.h:386
void GetFullPageWriteInfo(XLogRecPtr *RedoRecPtr_p, bool *doPageWrites_p)
Definition: xlog.c:6655
static XLogRecPtr RedoRecPtr
Definition: xlog.c:273
static bool doPageWrites
Definition: xlog.c:286

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

Referenced by heap_page_prune_and_freeze(), and log_heap_update().

◆ XLogCompressBackupBlock()

static bool XLogCompressBackupBlock ( const PageData page,
uint16  hole_offset,
uint16  hole_length,
void *  dest,
uint16 dlen 
)
static

Definition at line 944 of file xloginsert.c.

946{
947 int32 orig_len = BLCKSZ - hole_length;
948 int32 len = -1;
949 int32 extra_bytes = 0;
950 const void *source;
951 PGAlignedBlock tmp;
952
953 if (hole_length != 0)
954 {
955 /* must skip the hole */
956 memcpy(tmp.data, page, hole_offset);
957 memcpy(tmp.data + hole_offset,
958 page + (hole_offset + hole_length),
959 BLCKSZ - (hole_length + hole_offset));
960 source = tmp.data;
961
962 /*
963 * Extra data needs to be stored in WAL record for the compressed
964 * version of block image if the hole exists.
965 */
967 }
968 else
969 source = page;
970
972 {
975 break;
976
978#ifdef USE_LZ4
979 len = LZ4_compress_default(source, dest, orig_len,
981 if (len <= 0)
982 len = -1; /* failure */
983#else
984 elog(ERROR, "LZ4 is not supported by this build");
985#endif
986 break;
987
989#ifdef USE_ZSTD
990 len = ZSTD_compress(dest, COMPRESS_BUFSIZE, source, orig_len,
991 ZSTD_CLEVEL_DEFAULT);
992 if (ZSTD_isError(len))
993 len = -1; /* failure */
994#else
995 elog(ERROR, "zstd is not supported by this build");
996#endif
997 break;
998
1000 Assert(false); /* cannot happen */
1001 break;
1002 /* no default case, so that compiler will warn */
1003 }
1004
1005 /*
1006 * We recheck the actual size even if compression reports success and see
1007 * if the number of bytes saved by compression is larger than the length
1008 * of extra data needed for the compressed version of block image.
1009 */
1010 if (len >= 0 &&
1011 len + extra_bytes < orig_len)
1012 {
1013 *dlen = (uint16) len; /* successful compression */
1014 return true;
1015 }
1016 return false;
1017}
int32_t int32
Definition: c.h:498
uint16_t uint16
Definition: c.h:501
const void size_t len
const PGLZ_Strategy *const PGLZ_strategy_default
int32 pglz_compress(const char *source, int32 slen, char *dest, const PGLZ_Strategy *strategy)
static rewind_source * source
Definition: pg_rewind.c:89
char data[BLCKSZ]
Definition: c.h:1090
int wal_compression
Definition: xlog.c:124
WalCompression
Definition: xlog.h:81
@ WAL_COMPRESSION_NONE
Definition: xlog.h:82
@ WAL_COMPRESSION_LZ4
Definition: xlog.h:84
@ WAL_COMPRESSION_PGLZ
Definition: xlog.h:83
@ WAL_COMPRESSION_ZSTD
Definition: xlog.h:85
#define COMPRESS_BUFSIZE
Definition: xloginsert.c:62
#define SizeOfXLogRecordBlockCompressHeader
Definition: xlogrecord.h:177

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

Referenced by XLogRecordAssemble().

◆ XLogEnsureRecordSpace()

void XLogEnsureRecordSpace ( int  max_block_id,
int  ndatas 
)

Definition at line 175 of file xloginsert.c.

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

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

475{
476 XLogRecPtr EndPos;
477
478 /* XLogBeginInsert() must have been called. */
480 elog(ERROR, "XLogBeginInsert was not called");
481
482 /*
483 * The caller can set rmgr bits, XLR_SPECIAL_REL_UPDATE and
484 * XLR_CHECK_CONSISTENCY; the rest are reserved for use by me.
485 */
486 if ((info & ~(XLR_RMGR_INFO_MASK |
489 elog(PANIC, "invalid xlog info mask %02X", info);
490
491 TRACE_POSTGRESQL_WAL_INSERT(rmid, info);
492
493 /*
494 * In bootstrap mode, we don't actually log anything but XLOG resources;
495 * return a phony record pointer.
496 */
497 if (IsBootstrapProcessingMode() && rmid != RM_XLOG_ID)
498 {
500 EndPos = SizeOfXLogLongPHD; /* start of 1st chkpt record */
501 return EndPos;
502 }
503
504 do
505 {
507 bool doPageWrites;
508 bool topxid_included = false;
509 XLogRecPtr fpw_lsn;
510 XLogRecData *rdt;
511 int num_fpi = 0;
512
513 /*
514 * Get values needed to decide whether to do full-page writes. Since
515 * we don't yet have an insertion lock, these could change under us,
516 * but XLogInsertRecord will recheck them once it has a lock.
517 */
519
520 rdt = XLogRecordAssemble(rmid, info, RedoRecPtr, doPageWrites,
521 &fpw_lsn, &num_fpi, &topxid_included);
522
523 EndPos = XLogInsertRecord(rdt, fpw_lsn, curinsert_flags, num_fpi,
524 topxid_included);
525 } while (EndPos == InvalidXLogRecPtr);
526
528
529 return EndPos;
530}
#define PANIC
Definition: elog.h:42
#define IsBootstrapProcessingMode()
Definition: miscadmin.h:477
XLogRecPtr XLogInsertRecord(XLogRecData *rdata, XLogRecPtr fpw_lsn, uint8 flags, int num_fpi, bool topxid_included)
Definition: xlog.c:759
#define SizeOfXLogLongPHD
Definition: xlog_internal.h:69
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
static uint8 curinsert_flags
Definition: xloginsert.c:103
void XLogResetInsertion(void)
Definition: xloginsert.c:222
static XLogRecData * XLogRecordAssemble(RmgrId rmid, uint8 info, XLogRecPtr RedoRecPtr, bool doPageWrites, XLogRecPtr *fpw_lsn, int *num_fpi, bool *topxid_included)
Definition: xloginsert.c:548
#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_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(), 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().

◆ XLogRecordAssemble()

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

Definition at line 548 of file xloginsert.c.

551{
552 XLogRecData *rdt;
553 uint64 total_len = 0;
554 int block_id;
555 pg_crc32c rdata_crc;
556 registered_buffer *prev_regbuf = NULL;
557 XLogRecData *rdt_datas_last;
558 XLogRecord *rechdr;
559 char *scratch = hdr_scratch;
560
561 /*
562 * Note: this function can be called multiple times for the same record.
563 * All the modifications we do to the rdata chains below must handle that.
564 */
565
566 /* The record begins with the fixed-size header */
567 rechdr = (XLogRecord *) scratch;
568 scratch += SizeOfXLogRecord;
569
570 hdr_rdt.next = NULL;
571 rdt_datas_last = &hdr_rdt;
573
574 /*
575 * Enforce consistency checks for this record if user is looking for it.
576 * Do this before at the beginning of this routine to give the possibility
577 * for callers of XLogInsert() to pass XLR_CHECK_CONSISTENCY directly for
578 * a record.
579 */
580 if (wal_consistency_checking[rmid])
581 info |= XLR_CHECK_CONSISTENCY;
582
583 /*
584 * Make an rdata chain containing all the data portions of all block
585 * references. This includes the data for full-page images. Also append
586 * the headers for the block references in the scratch buffer.
587 */
588 *fpw_lsn = InvalidXLogRecPtr;
589 for (block_id = 0; block_id < max_registered_block_id; block_id++)
590 {
591 registered_buffer *regbuf = &registered_buffers[block_id];
592 bool needs_backup;
593 bool needs_data;
597 bool samerel;
598 bool is_compressed = false;
599 bool include_image;
600
601 if (!regbuf->in_use)
602 continue;
603
604 /* Determine if this block needs to be backed up */
605 if (regbuf->flags & REGBUF_FORCE_IMAGE)
606 needs_backup = true;
607 else if (regbuf->flags & REGBUF_NO_IMAGE)
608 needs_backup = false;
609 else if (!doPageWrites)
610 needs_backup = false;
611 else
612 {
613 /*
614 * We assume page LSN is first data on *every* page that can be
615 * passed to XLogInsert, whether it has the standard page layout
616 * or not.
617 */
618 XLogRecPtr page_lsn = PageGetLSN(regbuf->page);
619
620 needs_backup = (page_lsn <= RedoRecPtr);
621 if (!needs_backup)
622 {
623 if (*fpw_lsn == InvalidXLogRecPtr || page_lsn < *fpw_lsn)
624 *fpw_lsn = page_lsn;
625 }
626 }
627
628 /* Determine if the buffer data needs to included */
629 if (regbuf->rdata_len == 0)
630 needs_data = false;
631 else if ((regbuf->flags & REGBUF_KEEP_DATA) != 0)
632 needs_data = true;
633 else
634 needs_data = !needs_backup;
635
636 bkpb.id = block_id;
637 bkpb.fork_flags = regbuf->forkno;
638 bkpb.data_length = 0;
639
640 if ((regbuf->flags & REGBUF_WILL_INIT) == REGBUF_WILL_INIT)
642
643 /*
644 * If needs_backup is true or WAL checking is enabled for current
645 * resource manager, log a full-page write for the current block.
646 */
647 include_image = needs_backup || (info & XLR_CHECK_CONSISTENCY) != 0;
648
649 if (include_image)
650 {
651 const PageData *page = regbuf->page;
652 uint16 compressed_len = 0;
653
654 /*
655 * The page needs to be backed up, so calculate its hole length
656 * and offset.
657 */
658 if (regbuf->flags & REGBUF_STANDARD)
659 {
660 /* Assume we can omit data between pd_lower and pd_upper */
661 uint16 lower = ((PageHeader) page)->pd_lower;
662 uint16 upper = ((PageHeader) page)->pd_upper;
663
665 upper > lower &&
666 upper <= BLCKSZ)
667 {
668 bimg.hole_offset = lower;
669 cbimg.hole_length = upper - lower;
670 }
671 else
672 {
673 /* No "hole" to remove */
674 bimg.hole_offset = 0;
675 cbimg.hole_length = 0;
676 }
677 }
678 else
679 {
680 /* Not a standard page header, don't try to eliminate "hole" */
681 bimg.hole_offset = 0;
682 cbimg.hole_length = 0;
683 }
684
685 /*
686 * Try to compress a block image if wal_compression is enabled
687 */
689 {
690 is_compressed =
692 cbimg.hole_length,
693 regbuf->compressed_page,
694 &compressed_len);
695 }
696
697 /*
698 * Fill in the remaining fields in the XLogRecordBlockHeader
699 * struct
700 */
702
703 /* Report a full page image constructed for the WAL record */
704 *num_fpi += 1;
705
706 /*
707 * Construct XLogRecData entries for the page content.
708 */
709 rdt_datas_last->next = &regbuf->bkp_rdatas[0];
710 rdt_datas_last = rdt_datas_last->next;
711
712 bimg.bimg_info = (cbimg.hole_length == 0) ? 0 : BKPIMAGE_HAS_HOLE;
713
714 /*
715 * If WAL consistency checking is enabled for the resource manager
716 * of this WAL record, a full-page image is included in the record
717 * for the block modified. During redo, the full-page is replayed
718 * only if BKPIMAGE_APPLY is set.
719 */
720 if (needs_backup)
722
723 if (is_compressed)
724 {
725 /* The current compression is stored in the WAL record */
726 bimg.length = compressed_len;
727
728 /* Set the compression method used for this block */
730 {
733 break;
734
736#ifdef USE_LZ4
738#else
739 elog(ERROR, "LZ4 is not supported by this build");
740#endif
741 break;
742
744#ifdef USE_ZSTD
746#else
747 elog(ERROR, "zstd is not supported by this build");
748#endif
749 break;
750
752 Assert(false); /* cannot happen */
753 break;
754 /* no default case, so that compiler will warn */
755 }
756
757 rdt_datas_last->data = regbuf->compressed_page;
758 rdt_datas_last->len = compressed_len;
759 }
760 else
761 {
762 bimg.length = BLCKSZ - cbimg.hole_length;
763
764 if (cbimg.hole_length == 0)
765 {
766 rdt_datas_last->data = page;
767 rdt_datas_last->len = BLCKSZ;
768 }
769 else
770 {
771 /* must skip the hole */
772 rdt_datas_last->data = page;
773 rdt_datas_last->len = bimg.hole_offset;
774
775 rdt_datas_last->next = &regbuf->bkp_rdatas[1];
776 rdt_datas_last = rdt_datas_last->next;
777
778 rdt_datas_last->data =
779 page + (bimg.hole_offset + cbimg.hole_length);
780 rdt_datas_last->len =
781 BLCKSZ - (bimg.hole_offset + cbimg.hole_length);
782 }
783 }
784
785 total_len += bimg.length;
786 }
787
788 if (needs_data)
789 {
790 /*
791 * When copying to XLogRecordBlockHeader, the length is narrowed
792 * to an uint16. Double-check that it is still correct.
793 */
794 Assert(regbuf->rdata_len <= UINT16_MAX);
795
796 /*
797 * Link the caller-supplied rdata chain for this buffer to the
798 * overall list.
799 */
801 bkpb.data_length = (uint16) regbuf->rdata_len;
802 total_len += regbuf->rdata_len;
803
804 rdt_datas_last->next = regbuf->rdata_head;
805 rdt_datas_last = regbuf->rdata_tail;
806 }
807
808 if (prev_regbuf && RelFileLocatorEquals(regbuf->rlocator, prev_regbuf->rlocator))
809 {
810 samerel = true;
812 }
813 else
814 samerel = false;
815 prev_regbuf = regbuf;
816
817 /* Ok, copy the header to the scratch buffer */
818 memcpy(scratch, &bkpb, SizeOfXLogRecordBlockHeader);
820 if (include_image)
821 {
822 memcpy(scratch, &bimg, SizeOfXLogRecordBlockImageHeader);
824 if (cbimg.hole_length != 0 && is_compressed)
825 {
826 memcpy(scratch, &cbimg,
829 }
830 }
831 if (!samerel)
832 {
833 memcpy(scratch, &regbuf->rlocator, sizeof(RelFileLocator));
834 scratch += sizeof(RelFileLocator);
835 }
836 memcpy(scratch, &regbuf->block, sizeof(BlockNumber));
837 scratch += sizeof(BlockNumber);
838 }
839
840 /* followed by the record's origin, if any */
843 {
844 *(scratch++) = (char) XLR_BLOCK_ID_ORIGIN;
845 memcpy(scratch, &replorigin_session_origin, sizeof(replorigin_session_origin));
846 scratch += sizeof(replorigin_session_origin);
847 }
848
849 /* followed by toplevel XID, if not already included in previous record */
851 {
853
854 /* Set the flag that the top xid is included in the WAL */
855 *topxid_included = true;
856
857 *(scratch++) = (char) XLR_BLOCK_ID_TOPLEVEL_XID;
858 memcpy(scratch, &xid, sizeof(TransactionId));
859 scratch += sizeof(TransactionId);
860 }
861
862 /* followed by main data, if any */
863 if (mainrdata_len > 0)
864 {
865 if (mainrdata_len > 255)
866 {
867 uint32 mainrdata_len_4b;
868
871 (errmsg_internal("too much WAL data"),
872 errdetail_internal("Main data length is %" PRIu64 " bytes for a maximum of %u bytes.",
874 PG_UINT32_MAX)));
875
876 mainrdata_len_4b = (uint32) mainrdata_len;
877 *(scratch++) = (char) XLR_BLOCK_ID_DATA_LONG;
878 memcpy(scratch, &mainrdata_len_4b, sizeof(uint32));
879 scratch += sizeof(uint32);
880 }
881 else
882 {
883 *(scratch++) = (char) XLR_BLOCK_ID_DATA_SHORT;
884 *(scratch++) = (uint8) mainrdata_len;
885 }
886 rdt_datas_last->next = mainrdata_head;
887 rdt_datas_last = mainrdata_last;
888 total_len += mainrdata_len;
889 }
890 rdt_datas_last->next = NULL;
891
892 hdr_rdt.len = (scratch - hdr_scratch);
893 total_len += hdr_rdt.len;
894
895 /*
896 * Calculate CRC of the data
897 *
898 * Note that the record header isn't added into the CRC initially since we
899 * don't know the prev-link yet. Thus, the CRC will represent the CRC of
900 * the whole record in the order: rdata, then backup blocks, then record
901 * header.
902 */
903 INIT_CRC32C(rdata_crc);
905 for (rdt = hdr_rdt.next; rdt != NULL; rdt = rdt->next)
906 COMP_CRC32C(rdata_crc, rdt->data, rdt->len);
907
908 /*
909 * Ensure that the XLogRecord is not too large.
910 *
911 * XLogReader machinery is only able to handle records up to a certain
912 * size (ignoring machine resource limitations), so make sure that we will
913 * not emit records larger than the sizes advertised to be supported.
914 */
915 if (total_len > XLogRecordMaxSize)
917 (errmsg_internal("oversized WAL record"),
918 errdetail_internal("WAL record would be %" PRIu64 " bytes (of maximum %u bytes); rmid %u flags %u.",
919 total_len, XLogRecordMaxSize, rmid, info)));
920
921 /*
922 * Fill in the fields in the record header. Prev-link is filled in later,
923 * once we know where in the WAL the record will be inserted. The CRC does
924 * not include the record header yet.
925 */
927 rechdr->xl_tot_len = (uint32) total_len;
928 rechdr->xl_info = info;
929 rechdr->xl_rmid = rmid;
930 rechdr->xl_prev = InvalidXLogRecPtr;
931 rechdr->xl_crc = rdata_crc;
932
933 return &hdr_rdt;
934}
PageHeaderData * PageHeader
Definition: bufpage.h:174
char PageData
Definition: bufpage.h:81
#define SizeOfPageHeaderData
Definition: bufpage.h:217
uint8_t uint8
Definition: c.h:500
#define PG_UINT32_MAX
Definition: c.h:561
uint64_t uint64
Definition: c.h:503
uint32_t uint32
Definition: c.h:502
uint32 TransactionId
Definition: c.h:623
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1158
int errdetail_internal(const char *fmt,...)
Definition: elog.c:1231
#define ereport(elevel,...)
Definition: elog.h:149
Datum lower(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:49
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:80
RepOriginId replorigin_session_origin
Definition: origin.c:163
#define InvalidRepOriginId
Definition: origin.h:33
uint32 pg_crc32c
Definition: pg_crc32c.h:38
#define COMP_CRC32C(crc, data, len)
Definition: pg_crc32c.h:153
#define INIT_CRC32C(crc)
Definition: pg_crc32c.h:41
struct RelFileLocator RelFileLocator
#define RelFileLocatorEquals(locator1, locator2)
const void * data
struct XLogRecData * next
XLogRecPtr xl_prev
Definition: xlogrecord.h:45
pg_crc32c xl_crc
Definition: xlogrecord.h:49
uint8 xl_info
Definition: xlogrecord.h:46
uint32 xl_tot_len
Definition: xlogrecord.h:43
TransactionId xl_xid
Definition: xlogrecord.h:44
RmgrId xl_rmid
Definition: xlogrecord.h:47
XLogRecData bkp_rdatas[2]
Definition: xloginsert.c:82
char compressed_page[COMPRESS_BUFSIZE]
Definition: xloginsert.c:86
XLogRecData * rdata_tail
Definition: xloginsert.c:79
BlockNumber block
Definition: xloginsert.c:74
XLogRecData * rdata_head
Definition: xloginsert.c:77
ForkNumber forkno
Definition: xloginsert.c:73
RelFileLocator rlocator
Definition: xloginsert.c:72
const PageData * page
Definition: xloginsert.c:75
TransactionId GetTopTransactionIdIfAny(void)
Definition: xact.c:441
TransactionId GetCurrentTransactionIdIfAny(void)
Definition: xact.c:471
bool IsSubxactTopXidLogPending(void)
Definition: xact.c:559
bool * wal_consistency_checking
Definition: xlog.c:126
#define XLOG_INCLUDE_ORIGIN
Definition: xlog.h:154
static bool XLogCompressBackupBlock(const PageData *page, uint16 hole_offset, uint16 hole_length, void *dest, uint16 *dlen)
Definition: xloginsert.c:944
static XLogRecData hdr_rdt
Definition: xloginsert.c:113
#define REGBUF_NO_IMAGE
Definition: xloginsert.h:33
#define REGBUF_KEEP_DATA
Definition: xloginsert.h:36
#define REGBUF_WILL_INIT
Definition: xloginsert.h:34
#define SizeOfXLogRecordBlockImageHeader
Definition: xlogrecord.h:153
#define BKPIMAGE_COMPRESS_ZSTD
Definition: xlogrecord.h:162
#define BKPBLOCK_HAS_DATA
Definition: xlogrecord.h:198
#define BKPIMAGE_APPLY
Definition: xlogrecord.h:158
#define BKPIMAGE_HAS_HOLE
Definition: xlogrecord.h:157
#define XLR_BLOCK_ID_DATA_LONG
Definition: xlogrecord.h:242
#define BKPBLOCK_WILL_INIT
Definition: xlogrecord.h:199
#define BKPIMAGE_COMPRESS_LZ4
Definition: xlogrecord.h:161
#define XLR_BLOCK_ID_TOPLEVEL_XID
Definition: xlogrecord.h:244
#define XLR_BLOCK_ID_DATA_SHORT
Definition: xlogrecord.h:241
#define BKPBLOCK_SAME_REL
Definition: xlogrecord.h:200
#define SizeOfXLogRecordBlockHeader
Definition: xlogrecord.h:115
#define BKPIMAGE_COMPRESS_PGLZ
Definition: xlogrecord.h:160
#define XLR_BLOCK_ID_ORIGIN
Definition: xlogrecord.h:243
#define BKPBLOCK_HAS_IMAGE
Definition: xlogrecord.h:197

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

Referenced by XLogInsert().

◆ XLogRegisterBlock()

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

Definition at line 309 of file xloginsert.c.

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

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

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

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

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

References Assert(), begininsert_called, registered_buffer::block, BufferGetPage(), BufferGetTag(), BufferIsDirty(), BufferIsExclusiveLocked(), 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(), do_setval(), 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(), shiftList(), spgAddNodeAction(), spgSplitNodeAction(), vacuumLeafPage(), vacuumLeafRoot(), vacuumRedirectAndPlaceholder(), writeListPage(), and xlogVacuumPage().

◆ XLogRegisterData()

void XLogRegisterData ( const void *  data,
uint32  len 
)

Definition at line 364 of file xloginsert.c.

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

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

◆ XLogSaveBufferForHint()

XLogRecPtr XLogSaveBufferForHint ( Buffer  buffer,
bool  buffer_std 
)

Definition at line 1065 of file xloginsert.c.

1066{
1068 XLogRecPtr lsn;
1070
1071 /*
1072 * Ensure no checkpoint can change our view of RedoRecPtr.
1073 */
1075
1076 /*
1077 * Update RedoRecPtr so that we can make the right decision
1078 */
1080
1081 /*
1082 * We assume page LSN is first data on *every* page that can be passed to
1083 * XLogInsert, whether it has the standard page layout or not. Since we're
1084 * only holding a share-lock on the page, we must take the buffer header
1085 * lock when we look at the LSN.
1086 */
1087 lsn = BufferGetLSNAtomic(buffer);
1088
1089 if (lsn <= RedoRecPtr)
1090 {
1091 int flags = 0;
1092 PGAlignedBlock copied_buffer;
1093 char *origdata = (char *) BufferGetBlock(buffer);
1094 RelFileLocator rlocator;
1095 ForkNumber forkno;
1096 BlockNumber blkno;
1097
1098 /*
1099 * Copy buffer so we don't have to worry about concurrent hint bit or
1100 * lsn updates. We assume pd_lower/upper cannot be changed without an
1101 * exclusive lock, so the contents bkp are not racy.
1102 */
1103 if (buffer_std)
1104 {
1105 /* Assume we can omit data between pd_lower and pd_upper */
1106 Page page = BufferGetPage(buffer);
1107 uint16 lower = ((PageHeader) page)->pd_lower;
1108 uint16 upper = ((PageHeader) page)->pd_upper;
1109
1110 memcpy(copied_buffer.data, origdata, lower);
1111 memcpy(copied_buffer.data + upper, origdata + upper, BLCKSZ - upper);
1112 }
1113 else
1114 memcpy(copied_buffer.data, origdata, BLCKSZ);
1115
1117
1118 if (buffer_std)
1119 flags |= REGBUF_STANDARD;
1120
1121 BufferGetTag(buffer, &rlocator, &forkno, &blkno);
1122 XLogRegisterBlock(0, &rlocator, forkno, blkno, copied_buffer.data, flags);
1123
1124 recptr = XLogInsert(RM_XLOG_ID, XLOG_FPI_FOR_HINT);
1125 }
1126
1127 return recptr;
1128}
XLogRecPtr BufferGetLSNAtomic(Buffer buffer)
Definition: bufmgr.c:4423
static Block BufferGetBlock(Buffer buffer)
Definition: bufmgr.h:381
#define XLOG_FPI_FOR_HINT
Definition: pg_control.h:78
#define DELAY_CHKPT_START
Definition: proc.h:120
PGPROC * MyProc
Definition: proc.c:67
int delayChkptFlags
Definition: proc.h:241
XLogRecPtr GetRedoRecPtr(void)
Definition: xlog.c:6625

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

Referenced by MarkBufferDirtyHint().

◆ XLogSetRecordFlags()

Variable Documentation

◆ begininsert_called

◆ curinsert_flags

uint8 curinsert_flags = 0
static

◆ hdr_rdt

XLogRecData hdr_rdt
static

Definition at line 113 of file xloginsert.c.

Referenced by XLogRecordAssemble().

◆ hdr_scratch

char* hdr_scratch = NULL
static

Definition at line 114 of file xloginsert.c.

Referenced by InitXLogInsert(), and XLogRecordAssemble().

◆ mainrdata_head

XLogRecData* mainrdata_head
static

Definition at line 98 of file xloginsert.c.

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

◆ mainrdata_last

XLogRecData* mainrdata_last = (XLogRecData *) &mainrdata_head
static

◆ mainrdata_len

uint64 mainrdata_len
static

◆ max_rdatas

int max_rdatas
static

◆ max_registered_block_id

int max_registered_block_id = 0
static

◆ max_registered_buffers

int max_registered_buffers
static

◆ num_rdatas

int num_rdatas
static

Definition at line 129 of file xloginsert.c.

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

◆ rdatas

XLogRecData* rdatas
static

◆ registered_buffers

◆ xloginsert_cxt

MemoryContext xloginsert_cxt
static

Definition at line 135 of file xloginsert.c.

Referenced by InitXLogInsert().