PostgreSQL Source Code  git master
storage.c File Reference
#include "postgres.h"
#include "miscadmin.h"
#include "access/visibilitymap.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "access/xloginsert.h"
#include "access/xlogutils.h"
#include "catalog/storage.h"
#include "catalog/storage_xlog.h"
#include "storage/freespace.h"
#include "storage/smgr.h"
#include "utils/memutils.h"
#include "utils/rel.h"
Include dependency graph for storage.c:

Go to the source code of this file.

Data Structures

struct  PendingRelDelete
 

Typedefs

typedef struct PendingRelDelete PendingRelDelete
 

Functions

SMgrRelation RelationCreateStorage (RelFileNode rnode, char relpersistence)
 
void log_smgrcreate (const RelFileNode *rnode, ForkNumber forkNum)
 
void RelationDropStorage (Relation rel)
 
void RelationPreserveStorage (RelFileNode rnode, bool atCommit)
 
void RelationTruncate (Relation rel, BlockNumber nblocks)
 
void RelationCopyStorage (SMgrRelation src, SMgrRelation dst, ForkNumber forkNum, char relpersistence)
 
void smgrDoPendingDeletes (bool isCommit)
 
int smgrGetPendingDeletes (bool forCommit, RelFileNode **ptr)
 
void PostPrepare_smgr (void)
 
void AtSubCommit_smgr (void)
 
void AtSubAbort_smgr (void)
 
void smgr_redo (XLogReaderState *record)
 

Variables

static PendingRelDeletependingDeletes = NULL
 

Typedef Documentation

◆ PendingRelDelete

Function Documentation

◆ AtSubAbort_smgr()

void AtSubAbort_smgr ( void  )

Definition at line 564 of file storage.c.

References smgrDoPendingDeletes().

Referenced by AbortSubTransaction().

565 {
566  smgrDoPendingDeletes(false);
567 }
void smgrDoPendingDeletes(bool isCommit)
Definition: storage.c:399

◆ AtSubCommit_smgr()

void AtSubCommit_smgr ( void  )

Definition at line 544 of file storage.c.

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

Referenced by CommitSubTransaction().

545 {
546  int nestLevel = GetCurrentTransactionNestLevel();
547  PendingRelDelete *pending;
548 
549  for (pending = pendingDeletes; pending != NULL; pending = pending->next)
550  {
551  if (pending->nestLevel >= nestLevel)
552  pending->nestLevel = nestLevel - 1;
553  }
554 }
struct PendingRelDelete * next
Definition: storage.c:62
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:842
static PendingRelDelete * pendingDeletes
Definition: storage.c:65

◆ log_smgrcreate()

void log_smgrcreate ( const RelFileNode rnode,
ForkNumber  forkNum 
)

Definition at line 128 of file storage.c.

References xl_smgr_create::forkNum, xl_smgr_create::rnode, XLOG_SMGR_CREATE, XLogBeginInsert(), XLogInsert(), XLogRegisterData(), and XLR_SPECIAL_REL_UPDATE.

Referenced by heapam_relation_copy_data(), heapam_relation_set_new_filenode(), index_copy_data(), and RelationCreateStorage().

129 {
130  xl_smgr_create xlrec;
131 
132  /*
133  * Make an XLOG entry reporting the file creation.
134  */
135  xlrec.rnode = *rnode;
136  xlrec.forkNum = forkNum;
137 
138  XLogBeginInsert();
139  XLogRegisterData((char *) &xlrec, sizeof(xlrec));
141 }
#define XLR_SPECIAL_REL_UPDATE
Definition: xlogrecord.h:71
#define XLOG_SMGR_CREATE
Definition: storage_xlog.h:30
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
ForkNumber forkNum
Definition: storage_xlog.h:36
void XLogBeginInsert(void)
Definition: xloginsert.c:120
RelFileNode rnode
Definition: storage_xlog.h:35

◆ PostPrepare_smgr()

void PostPrepare_smgr ( void  )

Definition at line 523 of file storage.c.

References PendingRelDelete::next, and pfree().

Referenced by PrepareTransaction().

524 {
525  PendingRelDelete *pending;
527 
528  for (pending = pendingDeletes; pending != NULL; pending = next)
529  {
530  next = pending->next;
532  /* must explicitly free the list entry */
533  pfree(pending);
534  }
535 }
static int32 next
Definition: blutils.c:213
void pfree(void *pointer)
Definition: mcxt.c:1031
struct PendingRelDelete * next
Definition: storage.c:62
static PendingRelDelete * pendingDeletes
Definition: storage.c:65

◆ RelationCopyStorage()

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

Definition at line 305 of file storage.c.

References RelFileNodeBackend::backend, buf, CHECK_FOR_INTERRUPTS, PGAlignedBlock::data, ereport, errcode(), ERRCODE_DATA_CORRUPTED, errmsg(), ERROR, INIT_FORKNUM, log_newpage(), RelFileNodeBackend::node, PageIsVerified(), PageSetChecksumInplace(), relpathbackend, SMgrRelationData::smgr_rnode, smgrextend(), smgrimmedsync(), smgrnblocks(), smgrread(), and XLogIsNeeded.

Referenced by heapam_relation_copy_data(), and index_copy_data().

307 {
309  Page page;
310  bool use_wal;
311  bool copying_initfork;
312  BlockNumber nblocks;
313  BlockNumber blkno;
314 
315  page = (Page) buf.data;
316 
317  /*
318  * The init fork for an unlogged relation in many respects has to be
319  * treated the same as normal relation, changes need to be WAL logged and
320  * it needs to be synced to disk.
321  */
322  copying_initfork = relpersistence == RELPERSISTENCE_UNLOGGED &&
323  forkNum == INIT_FORKNUM;
324 
325  /*
326  * We need to log the copied data in WAL iff WAL archiving/streaming is
327  * enabled AND it's a permanent relation.
328  */
329  use_wal = XLogIsNeeded() &&
330  (relpersistence == RELPERSISTENCE_PERMANENT || copying_initfork);
331 
332  nblocks = smgrnblocks(src, forkNum);
333 
334  for (blkno = 0; blkno < nblocks; blkno++)
335  {
336  /* If we got a cancel signal during the copy of the data, quit */
338 
339  smgrread(src, forkNum, blkno, buf.data);
340 
341  if (!PageIsVerified(page, blkno))
342  ereport(ERROR,
344  errmsg("invalid page in block %u of relation %s",
345  blkno,
347  src->smgr_rnode.backend,
348  forkNum))));
349 
350  /*
351  * WAL-log the copied page. Unfortunately we don't know what kind of a
352  * page this is, so we have to log the full page including any unused
353  * space.
354  */
355  if (use_wal)
356  log_newpage(&dst->smgr_rnode.node, forkNum, blkno, page, false);
357 
358  PageSetChecksumInplace(page, blkno);
359 
360  /*
361  * Now write the page. We say isTemp = true even if it's not a temp
362  * rel, because there's no need for smgr to schedule an fsync for this
363  * write; we'll do it ourselves below.
364  */
365  smgrextend(dst, forkNum, blkno, buf.data, true);
366  }
367 
368  /*
369  * If the rel is WAL-logged, must fsync before commit. We use heap_sync
370  * to ensure that the toast table gets fsync'd too. (For a temp or
371  * unlogged rel we don't care since the data will be gone after a crash
372  * anyway.)
373  *
374  * It's obvious that we must do this when not WAL-logging the copy. It's
375  * less obvious that we have to do it even if we did WAL-log the copied
376  * pages. The reason is that since we're copying outside shared buffers, a
377  * CHECKPOINT occurring during the copy has no way to flush the previously
378  * written data to disk (indeed it won't know the new rel even exists). A
379  * crash later on would replay WAL from the checkpoint, therefore it
380  * wouldn't replay our earlier WAL entries. If we do not fsync those pages
381  * here, they might still not be on disk when the crash occurs.
382  */
383  if (relpersistence == RELPERSISTENCE_PERMANENT || copying_initfork)
384  smgrimmedsync(dst, forkNum);
385 }
bool PageIsVerified(Page page, BlockNumber blkno)
Definition: bufpage.c:82
#define XLogIsNeeded()
Definition: xlog.h:181
int errcode(int sqlerrcode)
Definition: elog.c:570
uint32 BlockNumber
Definition: block.h:31
void smgrread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer)
Definition: smgr.c:562
char data[BLCKSZ]
Definition: c.h:1060
#define ERROR
Definition: elog.h:43
char relpersistence
Definition: pg_class.h:78
RelFileNodeBackend smgr_rnode
Definition: smgr.h:42
static char * buf
Definition: pg_test_fsync.c:68
#define ereport(elevel, rest)
Definition: elog.h:141
#define ERRCODE_DATA_CORRUPTED
Definition: pg_basebackup.c:44
RelFileNode node
Definition: relfilenode.h:74
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:609
BackendId backend
Definition: relfilenode.h:75
void PageSetChecksumInplace(Page page, BlockNumber blkno)
Definition: bufpage.c:1198
void smgrextend(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer, bool skipFsync)
Definition: smgr.c:537
int errmsg(const char *fmt,...)
Definition: elog.c:784
XLogRecPtr log_newpage(RelFileNode *rnode, ForkNumber forkNum, BlockNumber blkno, Page page, bool page_std)
Definition: xloginsert.c:972
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:99
#define relpathbackend(rnode, backend, forknum)
Definition: relpath.h:78
void smgrimmedsync(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:671
Pointer Page
Definition: bufpage.h:78

◆ RelationCreateStorage()

SMgrRelation RelationCreateStorage ( RelFileNode  rnode,
char  relpersistence 
)

Definition at line 79 of file storage.c.

References PendingRelDelete::atCommit, PendingRelDelete::backend, BackendIdForTempRelations, elog, ERROR, GetCurrentTransactionNestLevel(), InvalidBackendId, log_smgrcreate(), MAIN_FORKNUM, MemoryContextAlloc(), PendingRelDelete::nestLevel, PendingRelDelete::next, RelFileNodeBackend::node, pendingDeletes, PendingRelDelete::relnode, SMgrRelationData::smgr_rnode, smgrcreate(), smgropen(), and TopMemoryContext.

Referenced by heap_create(), heapam_relation_copy_data(), heapam_relation_set_new_filenode(), index_copy_data(), and RelationSetNewRelfilenode().

80 {
81  PendingRelDelete *pending;
82  SMgrRelation srel;
83  BackendId backend;
84  bool needs_wal;
85 
86  switch (relpersistence)
87  {
88  case RELPERSISTENCE_TEMP:
89  backend = BackendIdForTempRelations();
90  needs_wal = false;
91  break;
92  case RELPERSISTENCE_UNLOGGED:
93  backend = InvalidBackendId;
94  needs_wal = false;
95  break;
96  case RELPERSISTENCE_PERMANENT:
97  backend = InvalidBackendId;
98  needs_wal = true;
99  break;
100  default:
101  elog(ERROR, "invalid relpersistence: %c", relpersistence);
102  return NULL; /* placate compiler */
103  }
104 
105  srel = smgropen(rnode, backend);
106  smgrcreate(srel, MAIN_FORKNUM, false);
107 
108  if (needs_wal)
110 
111  /* Add the relation to the list of stuff to delete at abort */
112  pending = (PendingRelDelete *)
114  pending->relnode = rnode;
115  pending->backend = backend;
116  pending->atCommit = false; /* delete if abort */
118  pending->next = pendingDeletes;
119  pendingDeletes = pending;
120 
121  return srel;
122 }
BackendId backend
Definition: storage.c:59
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:333
#define ERROR
Definition: elog.h:43
char relpersistence
Definition: pg_class.h:78
RelFileNodeBackend smgr_rnode
Definition: smgr.h:42
#define BackendIdForTempRelations()
Definition: backendid.h:34
MemoryContext TopMemoryContext
Definition: mcxt.c:44
SMgrRelation smgropen(RelFileNode rnode, BackendId backend)
Definition: smgr.c:145
struct PendingRelDelete * next
Definition: storage.c:62
#define InvalidBackendId
Definition: backendid.h:23
int BackendId
Definition: backendid.h:21
RelFileNode node
Definition: relfilenode.h:74
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:842
static PendingRelDelete * pendingDeletes
Definition: storage.c:65
RelFileNode relnode
Definition: storage.c:58
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:771
#define elog(elevel,...)
Definition: elog.h:226
void log_smgrcreate(const RelFileNode *rnode, ForkNumber forkNum)
Definition: storage.c:128

◆ RelationDropStorage()

void RelationDropStorage ( Relation  rel)

Definition at line 148 of file storage.c.

References PendingRelDelete::atCommit, PendingRelDelete::backend, GetCurrentTransactionNestLevel(), MemoryContextAlloc(), PendingRelDelete::nestLevel, PendingRelDelete::next, pendingDeletes, RelationData::rd_backend, RelationData::rd_node, RelationCloseSmgr, PendingRelDelete::relnode, and TopMemoryContext.

Referenced by DefineQueryRewrite(), heap_drop_with_catalog(), heapam_relation_copy_data(), index_copy_data(), index_drop(), and RelationSetNewRelfilenode().

149 {
150  PendingRelDelete *pending;
151 
152  /* Add the relation to the list of stuff to delete at commit */
153  pending = (PendingRelDelete *)
155  pending->relnode = rel->rd_node;
156  pending->backend = rel->rd_backend;
157  pending->atCommit = true; /* delete if commit */
159  pending->next = pendingDeletes;
160  pendingDeletes = pending;
161 
162  /*
163  * NOTE: if the relation was created in this transaction, it will now be
164  * present in the pending-delete list twice, once with atCommit true and
165  * once with atCommit false. Hence, it will be physically deleted at end
166  * of xact in either case (and the other entry will be ignored by
167  * smgrDoPendingDeletes, so no error will occur). We could instead remove
168  * the existing list entry and delete the physical file immediately, but
169  * for now I'll keep the logic simple.
170  */
171 
172  RelationCloseSmgr(rel);
173 }
BackendId backend
Definition: storage.c:59
#define RelationCloseSmgr(relation)
Definition: rel.h:485
MemoryContext TopMemoryContext
Definition: mcxt.c:44
struct PendingRelDelete * next
Definition: storage.c:62
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:842
RelFileNode rd_node
Definition: rel.h:54
BackendId rd_backend
Definition: rel.h:58
static PendingRelDelete * pendingDeletes
Definition: storage.c:65
RelFileNode relnode
Definition: storage.c:58
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:771

◆ RelationPreserveStorage()

void RelationPreserveStorage ( RelFileNode  rnode,
bool  atCommit 
)

Definition at line 193 of file storage.c.

References PendingRelDelete::atCommit, PendingRelDelete::next, pfree(), RelFileNodeEquals, and PendingRelDelete::relnode.

Referenced by ATExecAddIndex(), and write_relmap_file().

194 {
195  PendingRelDelete *pending;
196  PendingRelDelete *prev;
198 
199  prev = NULL;
200  for (pending = pendingDeletes; pending != NULL; pending = next)
201  {
202  next = pending->next;
203  if (RelFileNodeEquals(rnode, pending->relnode)
204  && pending->atCommit == atCommit)
205  {
206  /* unlink and delete list entry */
207  if (prev)
208  prev->next = next;
209  else
211  pfree(pending);
212  /* prev does not change */
213  }
214  else
215  {
216  /* unrelated entry, don't touch it */
217  prev = pending;
218  }
219  }
220 }
static int32 next
Definition: blutils.c:213
void pfree(void *pointer)
Definition: mcxt.c:1031
struct PendingRelDelete * next
Definition: storage.c:62
static PendingRelDelete * pendingDeletes
Definition: storage.c:65
RelFileNode relnode
Definition: storage.c:58
#define RelFileNodeEquals(node1, node2)
Definition: relfilenode.h:88

◆ RelationTruncate()

void RelationTruncate ( Relation  rel,
BlockNumber  nblocks 
)

Definition at line 230 of file storage.c.

References xl_smgr_truncate::blkno, xl_smgr_truncate::flags, FreeSpaceMapTruncateRel(), FSM_FORKNUM, InvalidBlockNumber, MAIN_FORKNUM, RelationData::rd_node, RelationData::rd_smgr, RelationNeedsWAL, RelationOpenSmgr, xl_smgr_truncate::rnode, SMgrRelationData::smgr_fsm_nblocks, SMgrRelationData::smgr_targblock, SMGR_TRUNCATE_ALL, SMgrRelationData::smgr_vm_nblocks, smgrexists(), smgrtruncate(), VISIBILITYMAP_FORKNUM, visibilitymap_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().

231 {
232  bool fsm;
233  bool vm;
234 
235  /* Open it at the smgr level if not already done */
236  RelationOpenSmgr(rel);
237 
238  /*
239  * Make sure smgr_targblock etc aren't pointing somewhere past new end
240  */
244 
245  /* Truncate the FSM first if it exists */
246  fsm = smgrexists(rel->rd_smgr, FSM_FORKNUM);
247  if (fsm)
248  FreeSpaceMapTruncateRel(rel, nblocks);
249 
250  /* Truncate the visibility map too if it exists. */
252  if (vm)
253  visibilitymap_truncate(rel, nblocks);
254 
255  /*
256  * We WAL-log the truncation before actually truncating, which means
257  * trouble if the truncation fails. If we then crash, the WAL replay
258  * likely isn't going to succeed in the truncation either, and cause a
259  * PANIC. It's tempting to put a critical section here, but that cure
260  * would be worse than the disease. It would turn a usually harmless
261  * failure to truncate, that might spell trouble at WAL replay, into a
262  * certain PANIC.
263  */
264  if (RelationNeedsWAL(rel))
265  {
266  /*
267  * Make an XLOG entry reporting the file truncation.
268  */
269  XLogRecPtr lsn;
270  xl_smgr_truncate xlrec;
271 
272  xlrec.blkno = nblocks;
273  xlrec.rnode = rel->rd_node;
274  xlrec.flags = SMGR_TRUNCATE_ALL;
275 
276  XLogBeginInsert();
277  XLogRegisterData((char *) &xlrec, sizeof(xlrec));
278 
279  lsn = XLogInsert(RM_SMGR_ID,
281 
282  /*
283  * Flush, because otherwise the truncation of the main relation might
284  * hit the disk before the WAL record, and the truncation of the FSM
285  * or visibility map. If we crashed during that window, we'd be left
286  * with a truncated heap, but the FSM or visibility map would still
287  * contain entries for the non-existent heap pages.
288  */
289  if (fsm || vm)
290  XLogFlush(lsn);
291  }
292 
293  /* Do the real work */
294  smgrtruncate(rel->rd_smgr, MAIN_FORKNUM, nblocks);
295 }
BlockNumber smgr_vm_nblocks
Definition: smgr.h:56
#define XLR_SPECIAL_REL_UPDATE
Definition: xlogrecord.h:71
struct SMgrRelationData * rd_smgr
Definition: rel.h:56
void smgrtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks)
Definition: smgr.c:621
BlockNumber smgr_fsm_nblocks
Definition: smgr.h:55
RelFileNode rnode
Definition: storage_xlog.h:49
bool smgrexists(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:247
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2798
#define RelationOpenSmgr(relation)
Definition: rel.h:473
void FreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks)
Definition: freespace.c:259
#define XLOG_SMGR_TRUNCATE
Definition: storage_xlog.h:31
void XLogRegisterData(char *data, int len)
Definition: xloginsert.c:323
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:415
RelFileNode rd_node
Definition: rel.h:54
uint64 XLogRecPtr
Definition: xlogdefs.h:21
BlockNumber smgr_targblock
Definition: smgr.h:54
void visibilitymap_truncate(Relation rel, BlockNumber nheapblocks)
#define InvalidBlockNumber
Definition: block.h:33
#define RelationNeedsWAL(relation)
Definition: rel.h:518
BlockNumber blkno
Definition: storage_xlog.h:48
#define SMGR_TRUNCATE_ALL
Definition: storage_xlog.h:43
void XLogBeginInsert(void)
Definition: xloginsert.c:120

◆ smgr_redo()

void smgr_redo ( XLogReaderState record)

Definition at line 570 of file storage.c.

References Assert, xl_smgr_truncate::blkno, CreateFakeRelcacheEntry(), elog, XLogReaderState::EndRecPtr, xl_smgr_truncate::flags, xl_smgr_create::forkNum, FreeFakeRelcacheEntry(), FreeSpaceMapTruncateRel(), FSM_FORKNUM, InvalidBackendId, MAIN_FORKNUM, PANIC, xl_smgr_create::rnode, xl_smgr_truncate::rnode, SMGR_TRUNCATE_FSM, SMGR_TRUNCATE_HEAP, SMGR_TRUNCATE_VM, smgrcreate(), smgrexists(), smgropen(), smgrtruncate(), VISIBILITYMAP_FORKNUM, visibilitymap_truncate(), XLOG_SMGR_CREATE, XLOG_SMGR_TRUNCATE, XLogFlush(), XLogRecGetData, XLogRecGetInfo, XLogRecHasAnyBlockRefs, XLogTruncateRelation(), and XLR_INFO_MASK.

571 {
572  XLogRecPtr lsn = record->EndRecPtr;
573  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
574 
575  /* Backup blocks are not used in smgr records */
576  Assert(!XLogRecHasAnyBlockRefs(record));
577 
578  if (info == XLOG_SMGR_CREATE)
579  {
580  xl_smgr_create *xlrec = (xl_smgr_create *) XLogRecGetData(record);
581  SMgrRelation reln;
582 
583  reln = smgropen(xlrec->rnode, InvalidBackendId);
584  smgrcreate(reln, xlrec->forkNum, true);
585  }
586  else if (info == XLOG_SMGR_TRUNCATE)
587  {
588  xl_smgr_truncate *xlrec = (xl_smgr_truncate *) XLogRecGetData(record);
589  SMgrRelation reln;
590  Relation rel;
591 
592  reln = smgropen(xlrec->rnode, InvalidBackendId);
593 
594  /*
595  * Forcibly create relation if it doesn't exist (which suggests that
596  * it was dropped somewhere later in the WAL sequence). As in
597  * XLogReadBufferForRedo, we prefer to recreate the rel and replay the
598  * log as best we can until the drop is seen.
599  */
600  smgrcreate(reln, MAIN_FORKNUM, true);
601 
602  /*
603  * Before we perform the truncation, update minimum recovery point to
604  * cover this WAL record. Once the relation is truncated, there's no
605  * going back. The buffer manager enforces the WAL-first rule for
606  * normal updates to relation files, so that the minimum recovery
607  * point is always updated before the corresponding change in the data
608  * file is flushed to disk. We have to do the same manually here.
609  *
610  * Doing this before the truncation means that if the truncation fails
611  * for some reason, you cannot start up the system even after restart,
612  * until you fix the underlying situation so that the truncation will
613  * succeed. Alternatively, we could update the minimum recovery point
614  * after truncation, but that would leave a small window where the
615  * WAL-first rule could be violated.
616  */
617  XLogFlush(lsn);
618 
619  if ((xlrec->flags & SMGR_TRUNCATE_HEAP) != 0)
620  {
621  smgrtruncate(reln, MAIN_FORKNUM, xlrec->blkno);
622 
623  /* Also tell xlogutils.c about it */
624  XLogTruncateRelation(xlrec->rnode, MAIN_FORKNUM, xlrec->blkno);
625  }
626 
627  /* Truncate FSM and VM too */
628  rel = CreateFakeRelcacheEntry(xlrec->rnode);
629 
630  if ((xlrec->flags & SMGR_TRUNCATE_FSM) != 0 &&
631  smgrexists(reln, FSM_FORKNUM))
632  FreeSpaceMapTruncateRel(rel, xlrec->blkno);
633  if ((xlrec->flags & SMGR_TRUNCATE_VM) != 0 &&
635  visibilitymap_truncate(rel, xlrec->blkno);
636 
638  }
639  else
640  elog(PANIC, "smgr_redo: unknown op code %u", info);
641 }
void XLogTruncateRelation(RelFileNode rnode, ForkNumber forkNum, BlockNumber nblocks)
Definition: xlogutils.c:636
#define SMGR_TRUNCATE_HEAP
Definition: storage_xlog.h:40
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:333
unsigned char uint8
Definition: c.h:356
#define SMGR_TRUNCATE_FSM
Definition: storage_xlog.h:42
void smgrtruncate(SMgrRelation reln, ForkNumber forknum, BlockNumber nblocks)
Definition: smgr.c:621
RelFileNode rnode
Definition: storage_xlog.h:49
bool smgrexists(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:247
#define PANIC
Definition: elog.h:53
void XLogFlush(XLogRecPtr record)
Definition: xlog.c:2798
#define XLOG_SMGR_CREATE
Definition: storage_xlog.h:30
XLogRecPtr EndRecPtr
Definition: xlogreader.h:124
#define XLogRecGetData(decoder)
Definition: xlogreader.h:237
Relation CreateFakeRelcacheEntry(RelFileNode rnode)
Definition: xlogutils.c:550
void FreeSpaceMapTruncateRel(Relation rel, BlockNumber nblocks)
Definition: freespace.c:259
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:233
SMgrRelation smgropen(RelFileNode rnode, BackendId backend)
Definition: smgr.c:145
#define XLOG_SMGR_TRUNCATE
Definition: storage_xlog.h:31
void FreeFakeRelcacheEntry(Relation fakerel)
Definition: xlogutils.c:591
#define InvalidBackendId
Definition: backendid.h:23
ForkNumber forkNum
Definition: storage_xlog.h:36
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:732
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
void visibilitymap_truncate(Relation rel, BlockNumber nheapblocks)
#define SMGR_TRUNCATE_VM
Definition: storage_xlog.h:41
#define elog(elevel,...)
Definition: elog.h:226
#define XLogRecHasAnyBlockRefs(decoder)
Definition: xlogreader.h:239
BlockNumber blkno
Definition: storage_xlog.h:48
RelFileNode rnode
Definition: storage_xlog.h:35

◆ smgrDoPendingDeletes()

void smgrDoPendingDeletes ( bool  isCommit)

Definition at line 399 of file storage.c.

References PendingRelDelete::atCommit, PendingRelDelete::backend, GetCurrentTransactionNestLevel(), i, PendingRelDelete::nestLevel, PendingRelDelete::next, palloc(), pfree(), PendingRelDelete::relnode, repalloc(), smgrclose(), smgrdounlinkall(), and smgropen().

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

400 {
401  int nestLevel = GetCurrentTransactionNestLevel();
402  PendingRelDelete *pending;
403  PendingRelDelete *prev;
405  int nrels = 0,
406  i = 0,
407  maxrels = 0;
408  SMgrRelation *srels = NULL;
409 
410  prev = NULL;
411  for (pending = pendingDeletes; pending != NULL; pending = next)
412  {
413  next = pending->next;
414  if (pending->nestLevel < nestLevel)
415  {
416  /* outer-level entries should not be processed yet */
417  prev = pending;
418  }
419  else
420  {
421  /* unlink list entry first, so we don't retry on failure */
422  if (prev)
423  prev->next = next;
424  else
426  /* do deletion if called for */
427  if (pending->atCommit == isCommit)
428  {
429  SMgrRelation srel;
430 
431  srel = smgropen(pending->relnode, pending->backend);
432 
433  /* allocate the initial array, or extend it, if needed */
434  if (maxrels == 0)
435  {
436  maxrels = 8;
437  srels = palloc(sizeof(SMgrRelation) * maxrels);
438  }
439  else if (maxrels <= nrels)
440  {
441  maxrels *= 2;
442  srels = repalloc(srels, sizeof(SMgrRelation) * maxrels);
443  }
444 
445  srels[nrels++] = srel;
446  }
447  /* must explicitly free the list entry */
448  pfree(pending);
449  /* prev does not change */
450  }
451  }
452 
453  if (nrels > 0)
454  {
455  smgrdounlinkall(srels, nrels, false);
456 
457  for (i = 0; i < nrels; i++)
458  smgrclose(srels[i]);
459 
460  pfree(srels);
461  }
462 }
BackendId backend
Definition: storage.c:59
void smgrclose(SMgrRelation reln)
Definition: smgr.c:256
static int32 next
Definition: blutils.c:213
void smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
Definition: smgr.c:408
void pfree(void *pointer)
Definition: mcxt.c:1031
SMgrRelation smgropen(RelFileNode rnode, BackendId backend)
Definition: smgr.c:145
struct PendingRelDelete * next
Definition: storage.c:62
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:842
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1044
static PendingRelDelete * pendingDeletes
Definition: storage.c:65
void * palloc(Size size)
Definition: mcxt.c:924
RelFileNode relnode
Definition: storage.c:58
int i

◆ smgrGetPendingDeletes()

int smgrGetPendingDeletes ( bool  forCommit,
RelFileNode **  ptr 
)

Definition at line 482 of file storage.c.

References PendingRelDelete::atCommit, PendingRelDelete::backend, GetCurrentTransactionNestLevel(), InvalidBackendId, PendingRelDelete::nestLevel, PendingRelDelete::next, palloc(), and PendingRelDelete::relnode.

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

483 {
484  int nestLevel = GetCurrentTransactionNestLevel();
485  int nrels;
486  RelFileNode *rptr;
487  PendingRelDelete *pending;
488 
489  nrels = 0;
490  for (pending = pendingDeletes; pending != NULL; pending = pending->next)
491  {
492  if (pending->nestLevel >= nestLevel && pending->atCommit == forCommit
493  && pending->backend == InvalidBackendId)
494  nrels++;
495  }
496  if (nrels == 0)
497  {
498  *ptr = NULL;
499  return 0;
500  }
501  rptr = (RelFileNode *) palloc(nrels * sizeof(RelFileNode));
502  *ptr = rptr;
503  for (pending = pendingDeletes; pending != NULL; pending = pending->next)
504  {
505  if (pending->nestLevel >= nestLevel && pending->atCommit == forCommit
506  && pending->backend == InvalidBackendId)
507  {
508  *rptr = pending->relnode;
509  rptr++;
510  }
511  }
512  return nrels;
513 }
BackendId backend
Definition: storage.c:59
struct PendingRelDelete * next
Definition: storage.c:62
#define InvalidBackendId
Definition: backendid.h:23
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:842
static PendingRelDelete * pendingDeletes
Definition: storage.c:65
void * palloc(Size size)
Definition: mcxt.c:924
RelFileNode relnode
Definition: storage.c:58

Variable Documentation

◆ pendingDeletes

PendingRelDelete* pendingDeletes = NULL
static

Definition at line 65 of file storage.c.

Referenced by RelationCreateStorage(), and RelationDropStorage().