PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
storage.h File Reference
#include "storage/block.h"
#include "storage/relfilelocator.h"
#include "storage/smgr.h"
#include "utils/relcache.h"
Include dependency graph for storage.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

SMgrRelation RelationCreateStorage (RelFileLocator rlocator, char relpersistence, bool register_delete)
 
void RelationDropStorage (Relation rel)
 
void RelationPreserveStorage (RelFileLocator rlocator, bool atCommit)
 
void RelationPreTruncate (Relation rel)
 
void RelationTruncate (Relation rel, BlockNumber nblocks)
 
void RelationCopyStorage (SMgrRelation src, SMgrRelation dst, ForkNumber forkNum, char relpersistence)
 
bool RelFileLocatorSkippingWAL (RelFileLocator rlocator)
 
Size EstimatePendingSyncsSpace (void)
 
void SerializePendingSyncs (Size maxSize, char *startAddress)
 
void RestorePendingSyncs (char *startAddress)
 
void smgrDoPendingDeletes (bool isCommit)
 
void smgrDoPendingSyncs (bool isCommit, bool isParallelWorker)
 
int smgrGetPendingDeletes (bool forCommit, RelFileLocator **ptr)
 
void AtSubCommit_smgr (void)
 
void AtSubAbort_smgr (void)
 
void PostPrepare_smgr (void)
 

Variables

PGDLLIMPORT int wal_skip_threshold
 

Function Documentation

◆ AtSubAbort_smgr()

void AtSubAbort_smgr ( void  )

Definition at line 975 of file storage.c.

976{
978}
void smgrDoPendingDeletes(bool isCommit)
Definition: storage.c:673

References smgrDoPendingDeletes().

Referenced by AbortSubTransaction().

◆ AtSubCommit_smgr()

void AtSubCommit_smgr ( void  )

Definition at line 955 of file storage.c.

956{
957 int nestLevel = GetCurrentTransactionNestLevel();
958 PendingRelDelete *pending;
959
960 for (pending = pendingDeletes; pending != NULL; pending = pending->next)
961 {
962 if (pending->nestLevel >= nestLevel)
963 pending->nestLevel = nestLevel - 1;
964 }
965}
static PendingRelDelete * pendingDeletes
Definition: storage.c:77
struct PendingRelDelete * next
Definition: storage.c:68
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:929

References GetCurrentTransactionNestLevel(), PendingRelDelete::nestLevel, PendingRelDelete::next, and pendingDeletes.

Referenced by CommitSubTransaction().

◆ EstimatePendingSyncsSpace()

Size EstimatePendingSyncsSpace ( void  )

Definition at line 587 of file storage.c.

588{
589 long entries;
590
592 return mul_size(1 + entries, sizeof(RelFileLocator));
593}
long hash_get_num_entries(HTAB *hashp)
Definition: dynahash.c:1341
Size mul_size(Size s1, Size s2)
Definition: shmem.c:510
static HTAB * pendingSyncHash
Definition: storage.c:78

References hash_get_num_entries(), mul_size(), and pendingSyncHash.

Referenced by InitializeParallelDSM().

◆ PostPrepare_smgr()

void PostPrepare_smgr ( void  )

Definition at line 934 of file storage.c.

935{
936 PendingRelDelete *pending;
938
939 for (pending = pendingDeletes; pending != NULL; pending = next)
940 {
941 next = pending->next;
943 /* must explicitly free the list entry */
944 pfree(pending);
945 }
946}
static int32 next
Definition: blutils.c:224
void pfree(void *pointer)
Definition: mcxt.c:2146

References next, PendingRelDelete::next, pendingDeletes, and pfree().

Referenced by PrepareTransaction().

◆ RelationCopyStorage()

void RelationCopyStorage ( SMgrRelation  src,
SMgrRelation  dst,
ForkNumber  forkNum,
char  relpersistence 
)

Definition at line 478 of file storage.c.

480{
481 bool use_wal;
482 bool copying_initfork;
483 BlockNumber nblocks;
484 BlockNumber blkno;
485 BulkWriteState *bulkstate;
486
487 /*
488 * The init fork for an unlogged relation in many respects has to be
489 * treated the same as normal relation, changes need to be WAL logged and
490 * it needs to be synced to disk.
491 */
492 copying_initfork = relpersistence == RELPERSISTENCE_UNLOGGED &&
493 forkNum == INIT_FORKNUM;
494
495 /*
496 * We need to log the copied data in WAL iff WAL archiving/streaming is
497 * enabled AND it's a permanent relation. This gives the same answer as
498 * "RelationNeedsWAL(rel) || copying_initfork", because we know the
499 * current operation created new relation storage.
500 */
501 use_wal = XLogIsNeeded() &&
502 (relpersistence == RELPERSISTENCE_PERMANENT || copying_initfork);
503
504 bulkstate = smgr_bulk_start_smgr(dst, forkNum, use_wal);
505
506 nblocks = smgrnblocks(src, forkNum);
507
508 for (blkno = 0; blkno < nblocks; blkno++)
509 {
511 int piv_flags;
512 bool checksum_failure;
513 bool verified;
514
515 /* If we got a cancel signal during the copy of the data, quit */
517
518 buf = smgr_bulk_get_buf(bulkstate);
519 smgrread(src, forkNum, blkno, (Page) buf);
520
521 piv_flags = PIV_LOG_WARNING;
523 piv_flags |= PIV_IGNORE_CHECKSUM_FAILURE;
524 verified = PageIsVerified((Page) buf, blkno, piv_flags,
527 {
529
532 }
533
534 if (!verified)
535 {
536 /*
537 * For paranoia's sake, capture the file path before invoking the
538 * ereport machinery. This guards against the possibility of a
539 * relcache flush caused by, e.g., an errcontext callback.
540 * (errcontext callbacks shouldn't be risking any such thing, but
541 * people have been known to forget that rule.)
542 */
545 forkNum);
546
549 errmsg("invalid page in block %u of relation %s",
550 blkno, relpath.str)));
551 }
552
553 /*
554 * Queue the page for WAL-logging and writing out. Unfortunately we
555 * don't know what kind of a page this is, so we have to log the full
556 * page including any unused space.
557 */
558 smgr_bulk_write(bulkstate, blkno, buf, false);
559 }
560 smgr_bulk_finish(bulkstate);
561}
uint32 BlockNumber
Definition: block.h:31
bool ignore_checksum_failure
Definition: bufpage.c:27
bool PageIsVerified(PageData *page, BlockNumber blkno, int flags, bool *checksum_failure_p)
Definition: bufpage.c:94
#define PIV_LOG_WARNING
Definition: bufpage.h:468
PageData * Page
Definition: bufpage.h:82
#define PIV_IGNORE_CHECKSUM_FAILURE
Definition: bufpage.h:470
void smgr_bulk_write(BulkWriteState *bulkstate, BlockNumber blocknum, BulkWriteBuffer buf, bool page_std)
Definition: bulk_write.c:323
BulkWriteBuffer smgr_bulk_get_buf(BulkWriteState *bulkstate)
Definition: bulk_write.c:347
BulkWriteState * smgr_bulk_start_smgr(SMgrRelation smgr, ForkNumber forknum, bool use_wal)
Definition: bulk_write.c:100
void smgr_bulk_finish(BulkWriteState *bulkstate)
Definition: bulk_write.c:130
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:123
static bool checksum_failure
#define ERRCODE_DATA_CORRUPTED
Definition: pg_basebackup.c:41
static char * buf
Definition: pg_test_fsync.c:72
void pgstat_prepare_report_checksum_failure(Oid dboid)
void pgstat_report_checksum_failures_in_db(Oid dboid, int failurecount)
@ INIT_FORKNUM
Definition: relpath.h:61
#define relpath(rlocator, forknum)
Definition: relpath.h:150
#define relpathbackend(rlocator, backend, forknum)
Definition: relpath.h:141
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:819
static void smgrread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, void *buffer)
Definition: smgr.h:124
RelFileLocator locator
RelFileLocatorBackend smgr_rlocator
Definition: smgr.h:38
#define XLogIsNeeded()
Definition: xlog.h:109

References RelFileLocatorBackend::backend, buf, CHECK_FOR_INTERRUPTS, checksum_failure, RelFileLocator::dbOid, ereport, errcode(), ERRCODE_DATA_CORRUPTED, errmsg(), ERROR, ignore_checksum_failure, INIT_FORKNUM, RelFileLocatorBackend::locator, PageIsVerified(), pgstat_prepare_report_checksum_failure(), pgstat_report_checksum_failures_in_db(), PIV_IGNORE_CHECKSUM_FAILURE, PIV_LOG_WARNING, relpath, relpathbackend, smgr_bulk_finish(), smgr_bulk_get_buf(), smgr_bulk_start_smgr(), smgr_bulk_write(), SMgrRelationData::smgr_rlocator, smgrnblocks(), smgrread(), and XLogIsNeeded.

Referenced by heapam_relation_copy_data(), and index_copy_data().

◆ RelationCreateStorage()

SMgrRelation RelationCreateStorage ( RelFileLocator  rlocator,
char  relpersistence,
bool  register_delete 
)

Definition at line 122 of file storage.c.

124{
125 SMgrRelation srel;
126 ProcNumber procNumber;
127 bool needs_wal;
128
129 Assert(!IsInParallelMode()); /* couldn't update pendingSyncHash */
130
131 switch (relpersistence)
132 {
133 case RELPERSISTENCE_TEMP:
134 procNumber = ProcNumberForTempRelations();
135 needs_wal = false;
136 break;
137 case RELPERSISTENCE_UNLOGGED:
138 procNumber = INVALID_PROC_NUMBER;
139 needs_wal = false;
140 break;
141 case RELPERSISTENCE_PERMANENT:
142 procNumber = INVALID_PROC_NUMBER;
143 needs_wal = true;
144 break;
145 default:
146 elog(ERROR, "invalid relpersistence: %c", relpersistence);
147 return NULL; /* placate compiler */
148 }
149
150 srel = smgropen(rlocator, procNumber);
151 smgrcreate(srel, MAIN_FORKNUM, false);
152
153 if (needs_wal)
155
156 /*
157 * Add the relation to the list of stuff to delete at abort, if we are
158 * asked to do so.
159 */
160 if (register_delete)
161 {
162 PendingRelDelete *pending;
163
164 pending = (PendingRelDelete *)
166 pending->rlocator = rlocator;
167 pending->procNumber = procNumber;
168 pending->atCommit = false; /* delete if abort */
170 pending->next = pendingDeletes;
171 pendingDeletes = pending;
172 }
173
174 if (relpersistence == RELPERSISTENCE_PERMANENT && !XLogIsNeeded())
175 {
176 Assert(procNumber == INVALID_PROC_NUMBER);
177 AddPendingSync(&rlocator);
178 }
179
180 return srel;
181}
#define elog(elevel,...)
Definition: elog.h:226
Assert(PointerIsAligned(start, uint64))
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1256
MemoryContext TopMemoryContext
Definition: mcxt.c:165
#define INVALID_PROC_NUMBER
Definition: procnumber.h:26
int ProcNumber
Definition: procnumber.h:24
#define ProcNumberForTempRelations()
Definition: procnumber.h:53
@ MAIN_FORKNUM
Definition: relpath.h:58
SMgrRelation smgropen(RelFileLocator rlocator, ProcNumber backend)
Definition: smgr.c:240
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:481
static void AddPendingSync(const RelFileLocator *rlocator)
Definition: storage.c:86
void log_smgrcreate(const RelFileLocator *rlocator, ForkNumber forkNum)
Definition: storage.c:187
ProcNumber procNumber
Definition: storage.c:65
RelFileLocator rlocator
Definition: storage.c:64
bool IsInParallelMode(void)
Definition: xact.c:1089

References AddPendingSync(), Assert(), PendingRelDelete::atCommit, elog, ERROR, GetCurrentTransactionNestLevel(), INVALID_PROC_NUMBER, IsInParallelMode(), RelFileLocatorBackend::locator, log_smgrcreate(), MAIN_FORKNUM, MemoryContextAlloc(), PendingRelDelete::nestLevel, PendingRelDelete::next, pendingDeletes, PendingRelDelete::procNumber, ProcNumberForTempRelations, PendingRelDelete::rlocator, SMgrRelationData::smgr_rlocator, smgrcreate(), smgropen(), TopMemoryContext, and XLogIsNeeded.

Referenced by CreateAndCopyRelationData(), heap_create(), heapam_relation_copy_data(), heapam_relation_set_new_filelocator(), index_copy_data(), and RelationSetNewRelfilenumber().

◆ RelationDropStorage()

void RelationDropStorage ( Relation  rel)

Definition at line 207 of file storage.c.

208{
209 PendingRelDelete *pending;
210
211 /* Add the relation to the list of stuff to delete at commit */
212 pending = (PendingRelDelete *)
214 pending->rlocator = rel->rd_locator;
215 pending->procNumber = rel->rd_backend;
216 pending->atCommit = true; /* delete if commit */
218 pending->next = pendingDeletes;
219 pendingDeletes = pending;
220
221 /*
222 * NOTE: if the relation was created in this transaction, it will now be
223 * present in the pending-delete list twice, once with atCommit true and
224 * once with atCommit false. Hence, it will be physically deleted at end
225 * of xact in either case (and the other entry will be ignored by
226 * smgrDoPendingDeletes, so no error will occur). We could instead remove
227 * the existing list entry and delete the physical file immediately, but
228 * for now I'll keep the logic simple.
229 */
230
232}
static void RelationCloseSmgr(Relation relation)
Definition: rel.h:593
ProcNumber rd_backend
Definition: rel.h:60
RelFileLocator rd_locator
Definition: rel.h:57

References PendingRelDelete::atCommit, GetCurrentTransactionNestLevel(), MemoryContextAlloc(), PendingRelDelete::nestLevel, PendingRelDelete::next, pendingDeletes, PendingRelDelete::procNumber, RelationData::rd_backend, RelationData::rd_locator, RelationCloseSmgr(), PendingRelDelete::rlocator, and TopMemoryContext.

Referenced by heap_drop_with_catalog(), heapam_relation_copy_data(), index_copy_data(), index_drop(), reindex_index(), and RelationSetNewRelfilenumber().

◆ RelationPreserveStorage()

void RelationPreserveStorage ( RelFileLocator  rlocator,
bool  atCommit 
)

Definition at line 252 of file storage.c.

253{
254 PendingRelDelete *pending;
255 PendingRelDelete *prev;
257
258 prev = NULL;
259 for (pending = pendingDeletes; pending != NULL; pending = next)
260 {
261 next = pending->next;
262 if (RelFileLocatorEquals(rlocator, pending->rlocator)
263 && pending->atCommit == atCommit)
264 {
265 /* unlink and delete list entry */
266 if (prev)
267 prev->next = next;
268 else
270 pfree(pending);
271 /* prev does not change */
272 }
273 else
274 {
275 /* unrelated entry, don't touch it */
276 prev = pending;
277 }
278 }
279}
#define RelFileLocatorEquals(locator1, locator2)

References PendingRelDelete::atCommit, next, PendingRelDelete::next, pendingDeletes, pfree(), RelFileLocatorEquals, and PendingRelDelete::rlocator.

Referenced by ATExecAddIndex(), and write_relmap_file().

◆ RelationPreTruncate()

void RelationPreTruncate ( Relation  rel)

Definition at line 450 of file storage.c.

451{
452 PendingRelSync *pending;
453
454 if (!pendingSyncHash)
455 return;
456
458 &(RelationGetSmgr(rel)->smgr_rlocator.locator),
459 HASH_FIND, NULL);
460 if (pending)
461 pending->is_truncated = true;
462}
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:955
@ HASH_FIND
Definition: hsearch.h:113
static SMgrRelation RelationGetSmgr(Relation rel)
Definition: rel.h:578
bool is_truncated
Definition: storage.c:74

References HASH_FIND, hash_search(), PendingRelSync::is_truncated, pendingSyncHash, and RelationGetSmgr().

Referenced by RelationTruncate().

◆ RelationTruncate()

void RelationTruncate ( Relation  rel,
BlockNumber  nblocks 
)

Definition at line 289 of file storage.c.

290{
291 bool fsm;
292 bool vm;
293 bool need_fsm_vacuum = false;
294 ForkNumber forks[MAX_FORKNUM];
295 BlockNumber old_blocks[MAX_FORKNUM];
296 BlockNumber blocks[MAX_FORKNUM];
297 int nforks = 0;
298 SMgrRelation reln;
299
300 /*
301 * Make sure smgr_targblock etc aren't pointing somewhere past new end.
302 * (Note: don't rely on this reln pointer below this loop.)
303 */
304 reln = RelationGetSmgr(rel);
306 for (int i = 0; i <= MAX_FORKNUM; ++i)
308
309 /* Prepare for truncation of MAIN fork of the relation */
310 forks[nforks] = MAIN_FORKNUM;
311 old_blocks[nforks] = smgrnblocks(reln, MAIN_FORKNUM);
312 blocks[nforks] = nblocks;
313 nforks++;
314
315 /* Prepare for truncation of the FSM if it exists */
317 if (fsm)
318 {
319 blocks[nforks] = FreeSpaceMapPrepareTruncateRel(rel, nblocks);
320 if (BlockNumberIsValid(blocks[nforks]))
321 {
322 forks[nforks] = FSM_FORKNUM;
323 old_blocks[nforks] = smgrnblocks(reln, FSM_FORKNUM);
324 nforks++;
325 need_fsm_vacuum = true;
326 }
327 }
328
329 /* Prepare for truncation of the visibility map too if it exists */
331 if (vm)
332 {
333 blocks[nforks] = visibilitymap_prepare_truncate(rel, nblocks);
334 if (BlockNumberIsValid(blocks[nforks]))
335 {
336 forks[nforks] = VISIBILITYMAP_FORKNUM;
337 old_blocks[nforks] = smgrnblocks(reln, VISIBILITYMAP_FORKNUM);
338 nforks++;
339 }
340 }
341
343
344 /*
345 * The code which follows can interact with concurrent checkpoints in two
346 * separate ways.
347 *
348 * First, the truncation operation might drop buffers that the checkpoint
349 * otherwise would have flushed. If it does, then it's essential that the
350 * files actually get truncated on disk before the checkpoint record is
351 * written. Otherwise, if reply begins from that checkpoint, the
352 * to-be-truncated blocks might still exist on disk but have older
353 * contents than expected, which can cause replay to fail. It's OK for the
354 * blocks to not exist on disk at all, but not for them to have the wrong
355 * contents. For this reason, we need to set DELAY_CHKPT_COMPLETE while
356 * this code executes.
357 *
358 * Second, the call to smgrtruncate() below will in turn call
359 * RegisterSyncRequest(). We need the sync request created by that call to
360 * be processed before the checkpoint completes. CheckPointGuts() will
361 * call ProcessSyncRequests(), but if we register our sync request after
362 * that happens, then the WAL record for the truncation could end up
363 * preceding the checkpoint record, while the actual sync doesn't happen
364 * until the next checkpoint. To prevent that, we need to set
365 * DELAY_CHKPT_START here. That way, if the XLOG_SMGR_TRUNCATE precedes
366 * the redo pointer of a concurrent checkpoint, we're guaranteed that the
367 * corresponding sync request will be processed before the checkpoint
368 * completes.
369 */
372
373 /*
374 * We WAL-log the truncation first and then truncate in a critical
375 * section. Truncation drops buffers, even if dirty, and then truncates
376 * disk files. All of that work needs to complete before the lock is
377 * released, or else old versions of pages on disk that are missing recent
378 * changes would become accessible again. We'll try the whole operation
379 * again in crash recovery if we panic, but even then we can't give up
380 * because we don't want standbys' relation sizes to diverge and break
381 * replay or visibility invariants downstream. The critical section also
382 * suppresses interrupts.
383 *
384 * (See also visibilitymap.c if changing this code.)
385 */
387
388 if (RelationNeedsWAL(rel))
389 {
390 /*
391 * Make an XLOG entry reporting the file truncation.
392 */
393 XLogRecPtr lsn;
394 xl_smgr_truncate xlrec;
395
396 xlrec.blkno = nblocks;
397 xlrec.rlocator = rel->rd_locator;
398 xlrec.flags = SMGR_TRUNCATE_ALL;
399
401 XLogRegisterData(&xlrec, sizeof(xlrec));
402
403 lsn = XLogInsert(RM_SMGR_ID,
405
406 /*
407 * Flush, because otherwise the truncation of the main relation might
408 * hit the disk before the WAL record, and the truncation of the FSM
409 * or visibility map. If we crashed during that window, we'd be left
410 * with a truncated heap, but the FSM or visibility map would still
411 * contain entries for the non-existent heap pages, and standbys would
412 * also never replay the truncation.
413 */
414 XLogFlush(lsn);
415 }
416
417 /*
418 * This will first remove any buffers from the buffer pool that should no
419 * longer exist after truncation is complete, and then truncate the
420 * corresponding files on disk.
421 */
422 smgrtruncate(RelationGetSmgr(rel), forks, nforks, old_blocks, blocks);
423
425
426 /* We've done all the critical work, so checkpoints are OK now. */
428
429 /*
430 * Update upper-level FSM pages to account for the truncation. This is
431 * important because the just-truncated pages were likely marked as
432 * all-free, and would be preferentially selected.
433 *
434 * NB: There's no point in delaying checkpoints until this is done.
435 * Because the FSM is not WAL-logged, we have to be prepared for the
436 * possibility of corruption after a crash anyway.
437 */
438 if (need_fsm_vacuum)
440}
#define InvalidBlockNumber
Definition: block.h:33
static bool BlockNumberIsValid(BlockNumber blockNumber)
Definition: block.h:71
void FreeSpaceMapVacuumRange(Relation rel, BlockNumber start, BlockNumber end)
Definition: freespace.c:377
BlockNumber FreeSpaceMapPrepareTruncateRel(Relation rel, BlockNumber nblocks)
Definition: freespace.c:275
int i
Definition: isn.c:77
#define START_CRIT_SECTION()
Definition: miscadmin.h:150
#define END_CRIT_SECTION()
Definition: miscadmin.h:152
#define DELAY_CHKPT_START
Definition: proc.h:120
#define DELAY_CHKPT_COMPLETE
Definition: proc.h:121
#define RelationNeedsWAL(relation)
Definition: rel.h:639
ForkNumber
Definition: relpath.h:56
@ FSM_FORKNUM
Definition: relpath.h:59
@ VISIBILITYMAP_FORKNUM
Definition: relpath.h:60
#define MAX_FORKNUM
Definition: relpath.h:70
void smgrtruncate(SMgrRelation reln, ForkNumber *forknum, int nforks, BlockNumber *old_nblocks, BlockNumber *nblocks)
Definition: smgr.c:875
bool smgrexists(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:462
PGPROC * MyProc
Definition: proc.c:67
void RelationPreTruncate(Relation rel)
Definition: storage.c:450
#define SMGR_TRUNCATE_ALL
Definition: storage_xlog.h:43
#define XLOG_SMGR_TRUNCATE
Definition: storage_xlog.h:31
int delayChkptFlags
Definition: proc.h:241
BlockNumber smgr_targblock
Definition: smgr.h:46
BlockNumber smgr_cached_nblocks[MAX_FORKNUM+1]
Definition: smgr.h:47
RelFileLocator rlocator
Definition: storage_xlog.h:49
BlockNumber blkno
Definition: storage_xlog.h:48
BlockNumber visibilitymap_prepare_truncate(Relation rel, BlockNumber nheapblocks)
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2923
uint64 XLogRecPtr
Definition: xlogdefs.h:21
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:474
void XLogRegisterData(const void *data, uint32 len)
Definition: xloginsert.c:364
void XLogBeginInsert(void)
Definition: xloginsert.c:149
#define XLR_SPECIAL_REL_UPDATE
Definition: xlogrecord.h:82

References Assert(), xl_smgr_truncate::blkno, BlockNumberIsValid(), DELAY_CHKPT_COMPLETE, DELAY_CHKPT_START, PGPROC::delayChkptFlags, END_CRIT_SECTION, xl_smgr_truncate::flags, FreeSpaceMapPrepareTruncateRel(), FreeSpaceMapVacuumRange(), FSM_FORKNUM, i, InvalidBlockNumber, MAIN_FORKNUM, MAX_FORKNUM, MyProc, RelationData::rd_locator, RelationGetSmgr(), RelationNeedsWAL, RelationPreTruncate(), xl_smgr_truncate::rlocator, SMgrRelationData::smgr_cached_nblocks, SMgrRelationData::smgr_targblock, SMGR_TRUNCATE_ALL, smgrexists(), smgrnblocks(), smgrtruncate(), START_CRIT_SECTION, VISIBILITYMAP_FORKNUM, visibilitymap_prepare_truncate(), XLOG_SMGR_TRUNCATE, XLogBeginInsert(), XLogFlush(), XLogInsert(), XLogRegisterData(), and XLR_SPECIAL_REL_UPDATE.

Referenced by heapam_relation_nontransactional_truncate(), lazy_truncate_heap(), RelationTruncateIndexes(), and spgvacuumscan().

◆ RelFileLocatorSkippingWAL()

bool RelFileLocatorSkippingWAL ( RelFileLocator  rlocator)

Definition at line 573 of file storage.c.

574{
575 if (!pendingSyncHash ||
576 hash_search(pendingSyncHash, &rlocator, HASH_FIND, NULL) == NULL)
577 return false;
578
579 return true;
580}

References HASH_FIND, hash_search(), and pendingSyncHash.

Referenced by MarkBufferDirtyHint(), and RelationInitPhysicalAddr().

◆ RestorePendingSyncs()

void RestorePendingSyncs ( char *  startAddress)

Definition at line 651 of file storage.c.

652{
653 RelFileLocator *rlocator;
654
655 Assert(pendingSyncHash == NULL);
656 for (rlocator = (RelFileLocator *) startAddress; rlocator->relNumber != 0;
657 rlocator++)
658 AddPendingSync(rlocator);
659}
RelFileNumber relNumber

References AddPendingSync(), Assert(), pendingSyncHash, and RelFileLocator::relNumber.

Referenced by ParallelWorkerMain().

◆ SerializePendingSyncs()

void SerializePendingSyncs ( Size  maxSize,
char *  startAddress 
)

Definition at line 600 of file storage.c.

601{
602 HTAB *tmphash;
603 HASHCTL ctl;
604 HASH_SEQ_STATUS scan;
605 PendingRelSync *sync;
606 PendingRelDelete *delete;
607 RelFileLocator *src;
608 RelFileLocator *dest = (RelFileLocator *) startAddress;
609
610 if (!pendingSyncHash)
611 goto terminate;
612
613 /* Create temporary hash to collect active relfilelocators */
614 ctl.keysize = sizeof(RelFileLocator);
615 ctl.entrysize = sizeof(RelFileLocator);
617 tmphash = hash_create("tmp relfilelocators",
620
621 /* collect all rlocator from pending syncs */
623 while ((sync = (PendingRelSync *) hash_seq_search(&scan)))
624 (void) hash_search(tmphash, &sync->rlocator, HASH_ENTER, NULL);
625
626 /* remove deleted rnodes */
627 for (delete = pendingDeletes; delete != NULL; delete = delete->next)
628 if (delete->atCommit)
629 (void) hash_search(tmphash, &delete->rlocator,
630 HASH_REMOVE, NULL);
631
632 hash_seq_init(&scan, tmphash);
633 while ((src = (RelFileLocator *) hash_seq_search(&scan)))
634 *dest++ = *src;
635
636 hash_destroy(tmphash);
637
638terminate:
639 MemSet(dest, 0, sizeof(RelFileLocator));
640}
#define MemSet(start, val, len)
Definition: c.h:991
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:865
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1420
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
void hash_seq_init(HASH_SEQ_STATUS *status, HTAB *hashp)
Definition: dynahash.c:1385
@ HASH_REMOVE
Definition: hsearch.h:115
@ HASH_ENTER
Definition: hsearch.h:114
#define HASH_CONTEXT
Definition: hsearch.h:102
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
MemoryContext CurrentMemoryContext
Definition: mcxt.c:159
tree ctl
Definition: radixtree.h:1838
struct RelFileLocator RelFileLocator
Definition: dynahash.c:220
RelFileLocator rlocator
Definition: storage.c:73

References ctl, CurrentMemoryContext, generate_unaccent_rules::dest, HASH_BLOBS, HASH_CONTEXT, hash_create(), hash_destroy(), HASH_ELEM, HASH_ENTER, hash_get_num_entries(), HASH_REMOVE, hash_search(), hash_seq_init(), hash_seq_search(), MemSet, PendingRelDelete::next, pendingDeletes, pendingSyncHash, and PendingRelSync::rlocator.

Referenced by InitializeParallelDSM().

◆ smgrDoPendingDeletes()

void smgrDoPendingDeletes ( bool  isCommit)

Definition at line 673 of file storage.c.

674{
675 int nestLevel = GetCurrentTransactionNestLevel();
676 PendingRelDelete *pending;
677 PendingRelDelete *prev;
679 int nrels = 0,
680 maxrels = 0;
681 SMgrRelation *srels = NULL;
682
683 prev = NULL;
684 for (pending = pendingDeletes; pending != NULL; pending = next)
685 {
686 next = pending->next;
687 if (pending->nestLevel < nestLevel)
688 {
689 /* outer-level entries should not be processed yet */
690 prev = pending;
691 }
692 else
693 {
694 /* unlink list entry first, so we don't retry on failure */
695 if (prev)
696 prev->next = next;
697 else
699 /* do deletion if called for */
700 if (pending->atCommit == isCommit)
701 {
702 SMgrRelation srel;
703
704 srel = smgropen(pending->rlocator, pending->procNumber);
705
706 /* allocate the initial array, or extend it, if needed */
707 if (maxrels == 0)
708 {
709 maxrels = 8;
710 srels = palloc(sizeof(SMgrRelation) * maxrels);
711 }
712 else if (maxrels <= nrels)
713 {
714 maxrels *= 2;
715 srels = repalloc(srels, sizeof(SMgrRelation) * maxrels);
716 }
717
718 srels[nrels++] = srel;
719 }
720 /* must explicitly free the list entry */
721 pfree(pending);
722 /* prev does not change */
723 }
724 }
725
726 if (nrels > 0)
727 {
728 smgrdounlinkall(srels, nrels, false);
729
730 for (int i = 0; i < nrels; i++)
731 smgrclose(srels[i]);
732
733 pfree(srels);
734 }
735}
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:2166
void * palloc(Size size)
Definition: mcxt.c:1939
void smgrclose(SMgrRelation reln)
Definition: smgr.c:374
void smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
Definition: smgr.c:538

References PendingRelDelete::atCommit, GetCurrentTransactionNestLevel(), i, PendingRelDelete::nestLevel, next, PendingRelDelete::next, palloc(), pendingDeletes, pfree(), PendingRelDelete::procNumber, repalloc(), PendingRelDelete::rlocator, smgrclose(), smgrdounlinkall(), and smgropen().

Referenced by AbortTransaction(), AtSubAbort_smgr(), and CommitTransaction().

◆ smgrDoPendingSyncs()

void smgrDoPendingSyncs ( bool  isCommit,
bool  isParallelWorker 
)

Definition at line 741 of file storage.c.

742{
743 PendingRelDelete *pending;
744 int nrels = 0,
745 maxrels = 0;
746 SMgrRelation *srels = NULL;
747 HASH_SEQ_STATUS scan;
748 PendingRelSync *pendingsync;
749
751
752 if (!pendingSyncHash)
753 return; /* no relation needs sync */
754
755 /* Abort -- just throw away all pending syncs */
756 if (!isCommit)
757 {
758 pendingSyncHash = NULL;
759 return;
760 }
761
763
764 /* Parallel worker -- just throw away all pending syncs */
765 if (isParallelWorker)
766 {
767 pendingSyncHash = NULL;
768 return;
769 }
770
771 /* Skip syncing nodes that smgrDoPendingDeletes() will delete. */
772 for (pending = pendingDeletes; pending != NULL; pending = pending->next)
773 if (pending->atCommit)
774 (void) hash_search(pendingSyncHash, &pending->rlocator,
775 HASH_REMOVE, NULL);
776
778 while ((pendingsync = (PendingRelSync *) hash_seq_search(&scan)))
779 {
780 ForkNumber fork;
781 BlockNumber nblocks[MAX_FORKNUM + 1];
782 uint64 total_blocks = 0;
783 SMgrRelation srel;
784
785 srel = smgropen(pendingsync->rlocator, INVALID_PROC_NUMBER);
786
787 /*
788 * We emit newpage WAL records for smaller relations.
789 *
790 * Small WAL records have a chance to be flushed along with other
791 * backends' WAL records. We emit WAL records instead of syncing for
792 * files that are smaller than a certain threshold, expecting faster
793 * commit. The threshold is defined by the GUC wal_skip_threshold.
794 */
795 if (!pendingsync->is_truncated)
796 {
797 for (fork = 0; fork <= MAX_FORKNUM; fork++)
798 {
799 if (smgrexists(srel, fork))
800 {
801 BlockNumber n = smgrnblocks(srel, fork);
802
803 /* we shouldn't come here for unlogged relations */
804 Assert(fork != INIT_FORKNUM);
805 nblocks[fork] = n;
806 total_blocks += n;
807 }
808 else
809 nblocks[fork] = InvalidBlockNumber;
810 }
811 }
812
813 /*
814 * Sync file or emit WAL records for its contents.
815 *
816 * Although we emit WAL record if the file is small enough, do file
817 * sync regardless of the size if the file has experienced a
818 * truncation. It is because the file would be followed by trailing
819 * garbage blocks after a crash recovery if, while a past longer file
820 * had been flushed out, we omitted syncing-out of the file and
821 * emitted WAL instead. You might think that we could choose WAL if
822 * the current main fork is longer than ever, but there's a case where
823 * main fork is longer than ever but FSM fork gets shorter.
824 */
825 if (pendingsync->is_truncated ||
826 total_blocks >= wal_skip_threshold * (uint64) 1024 / BLCKSZ)
827 {
828 /* allocate the initial array, or extend it, if needed */
829 if (maxrels == 0)
830 {
831 maxrels = 8;
832 srels = palloc(sizeof(SMgrRelation) * maxrels);
833 }
834 else if (maxrels <= nrels)
835 {
836 maxrels *= 2;
837 srels = repalloc(srels, sizeof(SMgrRelation) * maxrels);
838 }
839
840 srels[nrels++] = srel;
841 }
842 else
843 {
844 /* Emit WAL records for all blocks. The file is small enough. */
845 for (fork = 0; fork <= MAX_FORKNUM; fork++)
846 {
847 int n = nblocks[fork];
848 Relation rel;
849
850 if (!BlockNumberIsValid(n))
851 continue;
852
853 /*
854 * Emit WAL for the whole file. Unfortunately we don't know
855 * what kind of a page this is, so we have to log the full
856 * page including any unused space. ReadBufferExtended()
857 * counts some pgstat events; unfortunately, we discard them.
858 */
860 log_newpage_range(rel, fork, 0, n, false);
862 }
863 }
864 }
865
866 pendingSyncHash = NULL;
867
868 if (nrels > 0)
869 {
870 smgrdosyncall(srels, nrels);
871 pfree(srels);
872 }
873}
uint64_t uint64
Definition: c.h:503
#define AssertPendingSyncs_RelationCache()
Definition: relcache.h:143
void smgrdosyncall(SMgrRelation *rels, int nrels)
Definition: smgr.c:498
int wal_skip_threshold
Definition: storage.c:40
void log_newpage_range(Relation rel, ForkNumber forknum, BlockNumber startblk, BlockNumber endblk, bool page_std)
Definition: xloginsert.c:1270
void FreeFakeRelcacheEntry(Relation fakerel)
Definition: xlogutils.c:618
Relation CreateFakeRelcacheEntry(RelFileLocator rlocator)
Definition: xlogutils.c:571

References Assert(), AssertPendingSyncs_RelationCache, PendingRelDelete::atCommit, BlockNumberIsValid(), CreateFakeRelcacheEntry(), FreeFakeRelcacheEntry(), GetCurrentTransactionNestLevel(), HASH_REMOVE, hash_search(), hash_seq_init(), hash_seq_search(), INIT_FORKNUM, INVALID_PROC_NUMBER, InvalidBlockNumber, PendingRelSync::is_truncated, RelFileLocatorBackend::locator, log_newpage_range(), MAX_FORKNUM, PendingRelDelete::next, palloc(), pendingDeletes, pendingSyncHash, pfree(), repalloc(), PendingRelDelete::rlocator, PendingRelSync::rlocator, SMgrRelationData::smgr_rlocator, smgrdosyncall(), smgrexists(), smgrnblocks(), smgropen(), and wal_skip_threshold.

Referenced by AbortTransaction(), CommitTransaction(), and PrepareTransaction().

◆ smgrGetPendingDeletes()

int smgrGetPendingDeletes ( bool  forCommit,
RelFileLocator **  ptr 
)

Definition at line 893 of file storage.c.

894{
895 int nestLevel = GetCurrentTransactionNestLevel();
896 int nrels;
897 RelFileLocator *rptr;
898 PendingRelDelete *pending;
899
900 nrels = 0;
901 for (pending = pendingDeletes; pending != NULL; pending = pending->next)
902 {
903 if (pending->nestLevel >= nestLevel && pending->atCommit == forCommit
904 && pending->procNumber == INVALID_PROC_NUMBER)
905 nrels++;
906 }
907 if (nrels == 0)
908 {
909 *ptr = NULL;
910 return 0;
911 }
912 rptr = (RelFileLocator *) palloc(nrels * sizeof(RelFileLocator));
913 *ptr = rptr;
914 for (pending = pendingDeletes; pending != NULL; pending = pending->next)
915 {
916 if (pending->nestLevel >= nestLevel && pending->atCommit == forCommit
917 && pending->procNumber == INVALID_PROC_NUMBER)
918 {
919 *rptr = pending->rlocator;
920 rptr++;
921 }
922 }
923 return nrels;
924}

References PendingRelDelete::atCommit, GetCurrentTransactionNestLevel(), INVALID_PROC_NUMBER, PendingRelDelete::nestLevel, PendingRelDelete::next, palloc(), pendingDeletes, PendingRelDelete::procNumber, and PendingRelDelete::rlocator.

Referenced by RecordTransactionAbort(), RecordTransactionCommit(), and StartPrepare().

Variable Documentation

◆ wal_skip_threshold

PGDLLIMPORT int wal_skip_threshold
extern

Definition at line 40 of file storage.c.

Referenced by smgrDoPendingSyncs().