PostgreSQL Source Code  git master
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 947 of file storage.c.

948 {
949  smgrDoPendingDeletes(false);
950 }
void smgrDoPendingDeletes(bool isCommit)
Definition: storage.c:645

References smgrDoPendingDeletes().

Referenced by AbortSubTransaction().

◆ AtSubCommit_smgr()

void AtSubCommit_smgr ( void  )

Definition at line 927 of file storage.c.

928 {
929  int nestLevel = GetCurrentTransactionNestLevel();
930  PendingRelDelete *pending;
931 
932  for (pending = pendingDeletes; pending != NULL; pending = pending->next)
933  {
934  if (pending->nestLevel >= nestLevel)
935  pending->nestLevel = nestLevel - 1;
936  }
937 }
static PendingRelDelete * pendingDeletes
Definition: storage.c:76
struct PendingRelDelete * next
Definition: storage.c:67
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:928

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

Referenced by CommitSubTransaction().

◆ EstimatePendingSyncsSpace()

Size EstimatePendingSyncsSpace ( void  )

Definition at line 559 of file storage.c.

560 {
561  long entries;
562 
564  return mul_size(1 + entries, sizeof(RelFileLocator));
565 }
long hash_get_num_entries(HTAB *hashp)
Definition: dynahash.c:1341
Size mul_size(Size s1, Size s2)
Definition: shmem.c:505
static HTAB * pendingSyncHash
Definition: storage.c:77

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

Referenced by InitializeParallelDSM().

◆ PostPrepare_smgr()

void PostPrepare_smgr ( void  )

Definition at line 906 of file storage.c.

907 {
908  PendingRelDelete *pending;
910 
911  for (pending = pendingDeletes; pending != NULL; pending = next)
912  {
913  next = pending->next;
915  /* must explicitly free the list entry */
916  pfree(pending);
917  }
918 }
static int32 next
Definition: blutils.c:219
void pfree(void *pointer)
Definition: mcxt.c:1521

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

Referenced by PrepareTransaction().

◆ RelationCopyStorage()

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

Definition at line 465 of file storage.c.

467 {
468  bool use_wal;
469  bool copying_initfork;
470  BlockNumber nblocks;
471  BlockNumber blkno;
472  BulkWriteState *bulkstate;
473 
474  /*
475  * The init fork for an unlogged relation in many respects has to be
476  * treated the same as normal relation, changes need to be WAL logged and
477  * it needs to be synced to disk.
478  */
479  copying_initfork = relpersistence == RELPERSISTENCE_UNLOGGED &&
480  forkNum == INIT_FORKNUM;
481 
482  /*
483  * We need to log the copied data in WAL iff WAL archiving/streaming is
484  * enabled AND it's a permanent relation. This gives the same answer as
485  * "RelationNeedsWAL(rel) || copying_initfork", because we know the
486  * current operation created new relation storage.
487  */
488  use_wal = XLogIsNeeded() &&
489  (relpersistence == RELPERSISTENCE_PERMANENT || copying_initfork);
490 
491  bulkstate = smgr_bulk_start_smgr(dst, forkNum, use_wal);
492 
493  nblocks = smgrnblocks(src, forkNum);
494 
495  for (blkno = 0; blkno < nblocks; blkno++)
496  {
498 
499  /* If we got a cancel signal during the copy of the data, quit */
501 
502  buf = smgr_bulk_get_buf(bulkstate);
503  smgrread(src, forkNum, blkno, (Page) buf);
504 
505  if (!PageIsVerifiedExtended((Page) buf, blkno,
507  {
508  /*
509  * For paranoia's sake, capture the file path before invoking the
510  * ereport machinery. This guards against the possibility of a
511  * relcache flush caused by, e.g., an errcontext callback.
512  * (errcontext callbacks shouldn't be risking any such thing, but
513  * people have been known to forget that rule.)
514  */
516  src->smgr_rlocator.backend,
517  forkNum);
518 
519  ereport(ERROR,
521  errmsg("invalid page in block %u of relation %s",
522  blkno, relpath)));
523  }
524 
525  /*
526  * Queue the page for WAL-logging and writing out. Unfortunately we
527  * don't know what kind of a page this is, so we have to log the full
528  * page including any unused space.
529  */
530  smgr_bulk_write(bulkstate, blkno, buf, false);
531  }
532  smgr_bulk_finish(bulkstate);
533 }
uint32 BlockNumber
Definition: block.h:31
bool PageIsVerifiedExtended(Page page, BlockNumber blkno, int flags)
Definition: bufpage.c:88
Pointer Page
Definition: bufpage.h:81
#define PIV_LOG_WARNING
Definition: bufpage.h:468
#define PIV_REPORT_STAT
Definition: bufpage.h:469
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:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
#define ERRCODE_DATA_CORRUPTED
Definition: pg_basebackup.c:41
static char * buf
Definition: pg_test_fsync.c:72
@ INIT_FORKNUM
Definition: relpath.h:61
#define relpath(rlocator, forknum)
Definition: relpath.h:102
#define relpathbackend(rlocator, backend, forknum)
Definition: relpath.h:93
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:677
static void smgrread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, void *buffer)
Definition: smgr.h:116
RelFileLocator locator
RelFileLocatorBackend smgr_rlocator
Definition: smgr.h:37
#define XLogIsNeeded()
Definition: xlog.h:109

References RelFileLocatorBackend::backend, buf, CHECK_FOR_INTERRUPTS, ereport, errcode(), ERRCODE_DATA_CORRUPTED, errmsg(), ERROR, INIT_FORKNUM, RelFileLocatorBackend::locator, PageIsVerifiedExtended(), PIV_LOG_WARNING, PIV_REPORT_STAT, 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 121 of file storage.c.

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

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 206 of file storage.c.

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

252 {
253  PendingRelDelete *pending;
254  PendingRelDelete *prev;
256 
257  prev = NULL;
258  for (pending = pendingDeletes; pending != NULL; pending = next)
259  {
260  next = pending->next;
261  if (RelFileLocatorEquals(rlocator, pending->rlocator)
262  && pending->atCommit == atCommit)
263  {
264  /* unlink and delete list entry */
265  if (prev)
266  prev->next = next;
267  else
269  pfree(pending);
270  /* prev does not change */
271  }
272  else
273  {
274  /* unrelated entry, don't touch it */
275  prev = pending;
276  }
277  }
278 }
#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 437 of file storage.c.

438 {
439  PendingRelSync *pending;
440 
441  if (!pendingSyncHash)
442  return;
443 
444  pending = hash_search(pendingSyncHash,
445  &(RelationGetSmgr(rel)->smgr_rlocator.locator),
446  HASH_FIND, NULL);
447  if (pending)
448  pending->is_truncated = true;
449 }
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:567
bool is_truncated
Definition: storage.c:73

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

Referenced by RelationTruncate().

◆ RelationTruncate()

void RelationTruncate ( Relation  rel,
BlockNumber  nblocks 
)

Definition at line 288 of file storage.c.

289 {
290  bool fsm;
291  bool vm;
292  bool need_fsm_vacuum = false;
293  ForkNumber forks[MAX_FORKNUM];
294  BlockNumber blocks[MAX_FORKNUM];
295  int nforks = 0;
296  SMgrRelation reln;
297 
298  /*
299  * Make sure smgr_targblock etc aren't pointing somewhere past new end.
300  * (Note: don't rely on this reln pointer below this loop.)
301  */
302  reln = RelationGetSmgr(rel);
304  for (int i = 0; i <= MAX_FORKNUM; ++i)
306 
307  /* Prepare for truncation of MAIN fork of the relation */
308  forks[nforks] = MAIN_FORKNUM;
309  blocks[nforks] = nblocks;
310  nforks++;
311 
312  /* Prepare for truncation of the FSM if it exists */
314  if (fsm)
315  {
316  blocks[nforks] = FreeSpaceMapPrepareTruncateRel(rel, nblocks);
317  if (BlockNumberIsValid(blocks[nforks]))
318  {
319  forks[nforks] = FSM_FORKNUM;
320  nforks++;
321  need_fsm_vacuum = true;
322  }
323  }
324 
325  /* Prepare for truncation of the visibility map too if it exists */
327  if (vm)
328  {
329  blocks[nforks] = visibilitymap_prepare_truncate(rel, nblocks);
330  if (BlockNumberIsValid(blocks[nforks]))
331  {
332  forks[nforks] = VISIBILITYMAP_FORKNUM;
333  nforks++;
334  }
335  }
336 
337  RelationPreTruncate(rel);
338 
339  /*
340  * The code which follows can interact with concurrent checkpoints in two
341  * separate ways.
342  *
343  * First, the truncation operation might drop buffers that the checkpoint
344  * otherwise would have flushed. If it does, then it's essential that the
345  * files actually get truncated on disk before the checkpoint record is
346  * written. Otherwise, if reply begins from that checkpoint, the
347  * to-be-truncated blocks might still exist on disk but have older
348  * contents than expected, which can cause replay to fail. It's OK for the
349  * blocks to not exist on disk at all, but not for them to have the wrong
350  * contents. For this reason, we need to set DELAY_CHKPT_COMPLETE while
351  * this code executes.
352  *
353  * Second, the call to smgrtruncate() below will in turn call
354  * RegisterSyncRequest(). We need the sync request created by that call to
355  * be processed before the checkpoint completes. CheckPointGuts() will
356  * call ProcessSyncRequests(), but if we register our sync request after
357  * that happens, then the WAL record for the truncation could end up
358  * preceding the checkpoint record, while the actual sync doesn't happen
359  * until the next checkpoint. To prevent that, we need to set
360  * DELAY_CHKPT_START here. That way, if the XLOG_SMGR_TRUNCATE precedes
361  * the redo pointer of a concurrent checkpoint, we're guaranteed that the
362  * corresponding sync request will be processed before the checkpoint
363  * completes.
364  */
367 
368  /*
369  * We WAL-log the truncation before actually truncating, which means
370  * trouble if the truncation fails. If we then crash, the WAL replay
371  * likely isn't going to succeed in the truncation either, and cause a
372  * PANIC. It's tempting to put a critical section here, but that cure
373  * would be worse than the disease. It would turn a usually harmless
374  * failure to truncate, that might spell trouble at WAL replay, into a
375  * certain PANIC.
376  */
377  if (RelationNeedsWAL(rel))
378  {
379  /*
380  * Make an XLOG entry reporting the file truncation.
381  */
382  XLogRecPtr lsn;
383  xl_smgr_truncate xlrec;
384 
385  xlrec.blkno = nblocks;
386  xlrec.rlocator = rel->rd_locator;
387  xlrec.flags = SMGR_TRUNCATE_ALL;
388 
389  XLogBeginInsert();
390  XLogRegisterData((char *) &xlrec, sizeof(xlrec));
391 
392  lsn = XLogInsert(RM_SMGR_ID,
394 
395  /*
396  * Flush, because otherwise the truncation of the main relation might
397  * hit the disk before the WAL record, and the truncation of the FSM
398  * or visibility map. If we crashed during that window, we'd be left
399  * with a truncated heap, but the FSM or visibility map would still
400  * contain entries for the non-existent heap pages.
401  */
402  if (fsm || vm)
403  XLogFlush(lsn);
404  }
405 
406  /*
407  * This will first remove any buffers from the buffer pool that should no
408  * longer exist after truncation is complete, and then truncate the
409  * corresponding files on disk.
410  */
411  smgrtruncate(RelationGetSmgr(rel), forks, nforks, blocks);
412 
413  /* We've done all the critical work, so checkpoints are OK now. */
415 
416  /*
417  * Update upper-level FSM pages to account for the truncation. This is
418  * important because the just-truncated pages were likely marked as
419  * all-free, and would be preferentially selected.
420  *
421  * NB: There's no point in delaying checkpoints until this is done.
422  * Because the FSM is not WAL-logged, we have to be prepared for the
423  * possibility of corruption after a crash anyway.
424  */
425  if (need_fsm_vacuum)
427 }
#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:72
#define DELAY_CHKPT_START
Definition: proc.h:119
#define DELAY_CHKPT_COMPLETE
Definition: proc.h:120
#define RelationNeedsWAL(relation)
Definition: rel.h:628
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 *nblocks)
Definition: smgr.c:725
bool smgrexists(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:401
PGPROC * MyProc
Definition: proc.c:66
void RelationPreTruncate(Relation rel)
Definition: storage.c:437
#define SMGR_TRUNCATE_ALL
Definition: storage_xlog.h:43
#define XLOG_SMGR_TRUNCATE
Definition: storage_xlog.h:31
int delayChkptFlags
Definition: proc.h:240
BlockNumber smgr_targblock
Definition: smgr.h:45
BlockNumber smgr_cached_nblocks[MAX_FORKNUM+1]
Definition: smgr.h:46
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:2802
uint64 XLogRecPtr
Definition: xlogdefs.h:21
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:474
void XLogRegisterData(const char *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, 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(), smgrtruncate(), 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 545 of file storage.c.

546 {
547  if (!pendingSyncHash ||
548  hash_search(pendingSyncHash, &rlocator, HASH_FIND, NULL) == NULL)
549  return false;
550 
551  return true;
552 }

References HASH_FIND, hash_search(), and pendingSyncHash.

Referenced by MarkBufferDirtyHint(), and RelationInitPhysicalAddr().

◆ RestorePendingSyncs()

void RestorePendingSyncs ( char *  startAddress)

Definition at line 623 of file storage.c.

624 {
625  RelFileLocator *rlocator;
626 
627  Assert(pendingSyncHash == NULL);
628  for (rlocator = (RelFileLocator *) startAddress; rlocator->relNumber != 0;
629  rlocator++)
630  AddPendingSync(rlocator);
631 }
RelFileNumber relNumber

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

Referenced by ParallelWorkerMain().

◆ SerializePendingSyncs()

void SerializePendingSyncs ( Size  maxSize,
char *  startAddress 
)

Definition at line 572 of file storage.c.

573 {
574  HTAB *tmphash;
575  HASHCTL ctl;
576  HASH_SEQ_STATUS scan;
577  PendingRelSync *sync;
578  PendingRelDelete *delete;
579  RelFileLocator *src;
580  RelFileLocator *dest = (RelFileLocator *) startAddress;
581 
582  if (!pendingSyncHash)
583  goto terminate;
584 
585  /* Create temporary hash to collect active relfilelocators */
586  ctl.keysize = sizeof(RelFileLocator);
587  ctl.entrysize = sizeof(RelFileLocator);
588  ctl.hcxt = CurrentMemoryContext;
589  tmphash = hash_create("tmp relfilelocators",
592 
593  /* collect all rlocator from pending syncs */
595  while ((sync = (PendingRelSync *) hash_seq_search(&scan)))
596  (void) hash_search(tmphash, &sync->rlocator, HASH_ENTER, NULL);
597 
598  /* remove deleted rnodes */
599  for (delete = pendingDeletes; delete != NULL; delete = delete->next)
600  if (delete->atCommit)
601  (void) hash_search(tmphash, &delete->rlocator,
602  HASH_REMOVE, NULL);
603 
604  hash_seq_init(&scan, tmphash);
605  while ((src = (RelFileLocator *) hash_seq_search(&scan)))
606  *dest++ = *src;
607 
608  hash_destroy(tmphash);
609 
610 terminate:
611  MemSet(dest, 0, sizeof(RelFileLocator));
612 }
#define MemSet(start, val, len)
Definition: c.h:974
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:865
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:352
void * hash_seq_search(HASH_SEQ_STATUS *status)
Definition: dynahash.c:1420
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:143
tree ctl
Definition: radixtree.h:1853
struct RelFileLocator RelFileLocator
Definition: dynahash.c:220
RelFileLocator rlocator
Definition: storage.c:72

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 645 of file storage.c.

646 {
647  int nestLevel = GetCurrentTransactionNestLevel();
648  PendingRelDelete *pending;
649  PendingRelDelete *prev;
651  int nrels = 0,
652  maxrels = 0;
653  SMgrRelation *srels = NULL;
654 
655  prev = NULL;
656  for (pending = pendingDeletes; pending != NULL; pending = next)
657  {
658  next = pending->next;
659  if (pending->nestLevel < nestLevel)
660  {
661  /* outer-level entries should not be processed yet */
662  prev = pending;
663  }
664  else
665  {
666  /* unlink list entry first, so we don't retry on failure */
667  if (prev)
668  prev->next = next;
669  else
671  /* do deletion if called for */
672  if (pending->atCommit == isCommit)
673  {
674  SMgrRelation srel;
675 
676  srel = smgropen(pending->rlocator, pending->procNumber);
677 
678  /* allocate the initial array, or extend it, if needed */
679  if (maxrels == 0)
680  {
681  maxrels = 8;
682  srels = palloc(sizeof(SMgrRelation) * maxrels);
683  }
684  else if (maxrels <= nrels)
685  {
686  maxrels *= 2;
687  srels = repalloc(srels, sizeof(SMgrRelation) * maxrels);
688  }
689 
690  srels[nrels++] = srel;
691  }
692  /* must explicitly free the list entry */
693  pfree(pending);
694  /* prev does not change */
695  }
696  }
697 
698  if (nrels > 0)
699  {
700  smgrdounlinkall(srels, nrels, false);
701 
702  for (int i = 0; i < nrels; i++)
703  smgrclose(srels[i]);
704 
705  pfree(srels);
706  }
707 }
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1541
void * palloc(Size size)
Definition: mcxt.c:1317
void smgrclose(SMgrRelation reln)
Definition: smgr.c:323
void smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
Definition: smgr.c:465

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 713 of file storage.c.

714 {
715  PendingRelDelete *pending;
716  int nrels = 0,
717  maxrels = 0;
718  SMgrRelation *srels = NULL;
719  HASH_SEQ_STATUS scan;
720  PendingRelSync *pendingsync;
721 
723 
724  if (!pendingSyncHash)
725  return; /* no relation needs sync */
726 
727  /* Abort -- just throw away all pending syncs */
728  if (!isCommit)
729  {
730  pendingSyncHash = NULL;
731  return;
732  }
733 
735 
736  /* Parallel worker -- just throw away all pending syncs */
737  if (isParallelWorker)
738  {
739  pendingSyncHash = NULL;
740  return;
741  }
742 
743  /* Skip syncing nodes that smgrDoPendingDeletes() will delete. */
744  for (pending = pendingDeletes; pending != NULL; pending = pending->next)
745  if (pending->atCommit)
746  (void) hash_search(pendingSyncHash, &pending->rlocator,
747  HASH_REMOVE, NULL);
748 
750  while ((pendingsync = (PendingRelSync *) hash_seq_search(&scan)))
751  {
752  ForkNumber fork;
753  BlockNumber nblocks[MAX_FORKNUM + 1];
754  BlockNumber total_blocks = 0;
755  SMgrRelation srel;
756 
757  srel = smgropen(pendingsync->rlocator, INVALID_PROC_NUMBER);
758 
759  /*
760  * We emit newpage WAL records for smaller relations.
761  *
762  * Small WAL records have a chance to be flushed along with other
763  * backends' WAL records. We emit WAL records instead of syncing for
764  * files that are smaller than a certain threshold, expecting faster
765  * commit. The threshold is defined by the GUC wal_skip_threshold.
766  */
767  if (!pendingsync->is_truncated)
768  {
769  for (fork = 0; fork <= MAX_FORKNUM; fork++)
770  {
771  if (smgrexists(srel, fork))
772  {
773  BlockNumber n = smgrnblocks(srel, fork);
774 
775  /* we shouldn't come here for unlogged relations */
776  Assert(fork != INIT_FORKNUM);
777  nblocks[fork] = n;
778  total_blocks += n;
779  }
780  else
781  nblocks[fork] = InvalidBlockNumber;
782  }
783  }
784 
785  /*
786  * Sync file or emit WAL records for its contents.
787  *
788  * Although we emit WAL record if the file is small enough, do file
789  * sync regardless of the size if the file has experienced a
790  * truncation. It is because the file would be followed by trailing
791  * garbage blocks after a crash recovery if, while a past longer file
792  * had been flushed out, we omitted syncing-out of the file and
793  * emitted WAL instead. You might think that we could choose WAL if
794  * the current main fork is longer than ever, but there's a case where
795  * main fork is longer than ever but FSM fork gets shorter.
796  */
797  if (pendingsync->is_truncated ||
798  total_blocks * BLCKSZ / 1024 >= wal_skip_threshold)
799  {
800  /* allocate the initial array, or extend it, if needed */
801  if (maxrels == 0)
802  {
803  maxrels = 8;
804  srels = palloc(sizeof(SMgrRelation) * maxrels);
805  }
806  else if (maxrels <= nrels)
807  {
808  maxrels *= 2;
809  srels = repalloc(srels, sizeof(SMgrRelation) * maxrels);
810  }
811 
812  srels[nrels++] = srel;
813  }
814  else
815  {
816  /* Emit WAL records for all blocks. The file is small enough. */
817  for (fork = 0; fork <= MAX_FORKNUM; fork++)
818  {
819  int n = nblocks[fork];
820  Relation rel;
821 
822  if (!BlockNumberIsValid(n))
823  continue;
824 
825  /*
826  * Emit WAL for the whole file. Unfortunately we don't know
827  * what kind of a page this is, so we have to log the full
828  * page including any unused space. ReadBufferExtended()
829  * counts some pgstat events; unfortunately, we discard them.
830  */
832  log_newpage_range(rel, fork, 0, n, false);
834  }
835  }
836  }
837 
838  pendingSyncHash = NULL;
839 
840  if (nrels > 0)
841  {
842  smgrdosyncall(srels, nrels);
843  pfree(srels);
844  }
845 }
#define AssertPendingSyncs_RelationCache()
Definition: relcache.h:135
void smgrdosyncall(SMgrRelation *rels, int nrels)
Definition: smgr.c:429
int wal_skip_threshold
Definition: storage.c:39
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:629
Relation CreateFakeRelcacheEntry(RelFileLocator rlocator)
Definition: xlogutils.c:582

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 865 of file storage.c.

866 {
867  int nestLevel = GetCurrentTransactionNestLevel();
868  int nrels;
869  RelFileLocator *rptr;
870  PendingRelDelete *pending;
871 
872  nrels = 0;
873  for (pending = pendingDeletes; pending != NULL; pending = pending->next)
874  {
875  if (pending->nestLevel >= nestLevel && pending->atCommit == forCommit
876  && pending->procNumber == INVALID_PROC_NUMBER)
877  nrels++;
878  }
879  if (nrels == 0)
880  {
881  *ptr = NULL;
882  return 0;
883  }
884  rptr = (RelFileLocator *) palloc(nrels * sizeof(RelFileLocator));
885  *ptr = rptr;
886  for (pending = pendingDeletes; pending != NULL; pending = pending->next)
887  {
888  if (pending->nestLevel >= nestLevel && pending->atCommit == forCommit
889  && pending->procNumber == INVALID_PROC_NUMBER)
890  {
891  *rptr = pending->rlocator;
892  rptr++;
893  }
894  }
895  return nrels;
896 }

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 39 of file storage.c.

Referenced by smgrDoPendingSyncs().