PostgreSQL Source Code  git master
storage.h File Reference
#include "storage/block.h"
#include "storage/relfilenode.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 (RelFileNode rnode, char relpersistence)
 
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 AtSubCommit_smgr (void)
 
void AtSubAbort_smgr (void)
 
void PostPrepare_smgr (void)
 

Function Documentation

◆ AtSubAbort_smgr()

void AtSubAbort_smgr ( void  )

Definition at line 595 of file storage.c.

References smgrDoPendingDeletes().

Referenced by AbortSubTransaction().

596 {
597  smgrDoPendingDeletes(false);
598 }
void smgrDoPendingDeletes(bool isCommit)
Definition: storage.c:430

◆ AtSubCommit_smgr()

void AtSubCommit_smgr ( void  )

Definition at line 575 of file storage.c.

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

Referenced by CommitSubTransaction().

576 {
577  int nestLevel = GetCurrentTransactionNestLevel();
578  PendingRelDelete *pending;
579 
580  for (pending = pendingDeletes; pending != NULL; pending = pending->next)
581  {
582  if (pending->nestLevel >= nestLevel)
583  pending->nestLevel = nestLevel - 1;
584  }
585 }
struct PendingRelDelete * next
Definition: storage.c:61
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:841
static PendingRelDelete * pendingDeletes
Definition: storage.c:64

◆ PostPrepare_smgr()

void PostPrepare_smgr ( void  )

Definition at line 554 of file storage.c.

References PendingRelDelete::next, and pfree().

Referenced by PrepareTransaction().

555 {
556  PendingRelDelete *pending;
558 
559  for (pending = pendingDeletes; pending != NULL; pending = next)
560  {
561  next = pending->next;
563  /* must explicitly free the list entry */
564  pfree(pending);
565  }
566 }
static int32 next
Definition: blutils.c:213
void pfree(void *pointer)
Definition: mcxt.c:1056
struct PendingRelDelete * next
Definition: storage.c:61
static PendingRelDelete * pendingDeletes
Definition: storage.c:64

◆ RelationCopyStorage()

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

Definition at line 336 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().

338 {
340  Page page;
341  bool use_wal;
342  bool copying_initfork;
343  BlockNumber nblocks;
344  BlockNumber blkno;
345 
346  page = (Page) buf.data;
347 
348  /*
349  * The init fork for an unlogged relation in many respects has to be
350  * treated the same as normal relation, changes need to be WAL logged and
351  * it needs to be synced to disk.
352  */
353  copying_initfork = relpersistence == RELPERSISTENCE_UNLOGGED &&
354  forkNum == INIT_FORKNUM;
355 
356  /*
357  * We need to log the copied data in WAL iff WAL archiving/streaming is
358  * enabled AND it's a permanent relation.
359  */
360  use_wal = XLogIsNeeded() &&
361  (relpersistence == RELPERSISTENCE_PERMANENT || copying_initfork);
362 
363  nblocks = smgrnblocks(src, forkNum);
364 
365  for (blkno = 0; blkno < nblocks; blkno++)
366  {
367  /* If we got a cancel signal during the copy of the data, quit */
369 
370  smgrread(src, forkNum, blkno, buf.data);
371 
372  if (!PageIsVerified(page, blkno))
373  ereport(ERROR,
375  errmsg("invalid page in block %u of relation %s",
376  blkno,
378  src->smgr_rnode.backend,
379  forkNum))));
380 
381  /*
382  * WAL-log the copied page. Unfortunately we don't know what kind of a
383  * page this is, so we have to log the full page including any unused
384  * space.
385  */
386  if (use_wal)
387  log_newpage(&dst->smgr_rnode.node, forkNum, blkno, page, false);
388 
389  PageSetChecksumInplace(page, blkno);
390 
391  /*
392  * Now write the page. We say skipFsync = true because there's no
393  * need for smgr to schedule an fsync for this write; we'll do it
394  * ourselves below.
395  */
396  smgrextend(dst, forkNum, blkno, buf.data, true);
397  }
398 
399  /*
400  * If the rel is WAL-logged, must fsync before commit. We use heap_sync
401  * to ensure that the toast table gets fsync'd too. (For a temp or
402  * unlogged rel we don't care since the data will be gone after a crash
403  * anyway.)
404  *
405  * It's obvious that we must do this when not WAL-logging the copy. It's
406  * less obvious that we have to do it even if we did WAL-log the copied
407  * pages. The reason is that since we're copying outside shared buffers, a
408  * CHECKPOINT occurring during the copy has no way to flush the previously
409  * written data to disk (indeed it won't know the new rel even exists). A
410  * crash later on would replay WAL from the checkpoint, therefore it
411  * wouldn't replay our earlier WAL entries. If we do not fsync those pages
412  * here, they might still not be on disk when the crash occurs.
413  */
414  if (relpersistence == RELPERSISTENCE_PERMANENT || copying_initfork)
415  smgrimmedsync(dst, forkNum);
416 }
bool PageIsVerified(Page page, BlockNumber blkno)
Definition: bufpage.c:82
#define XLogIsNeeded()
Definition: xlog.h:181
int errcode(int sqlerrcode)
Definition: elog.c:608
uint32 BlockNumber
Definition: block.h:31
void smgrread(SMgrRelation reln, ForkNumber forknum, BlockNumber blocknum, char *buffer)
Definition: smgr.c:508
char data[BLCKSZ]
Definition: c.h:1091
#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:67
#define ereport(elevel, rest)
Definition: elog.h:141
#define ERRCODE_DATA_CORRUPTED
Definition: pg_basebackup.c:45
RelFileNode node
Definition: relfilenode.h:74
BlockNumber smgrnblocks(SMgrRelation reln, ForkNumber forknum)
Definition: smgr.c:555
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:483
int errmsg(const char *fmt,...)
Definition: elog.c:822
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:637
Pointer Page
Definition: bufpage.h:78

◆ RelationCreateStorage()

SMgrRelation RelationCreateStorage ( RelFileNode  rnode,
char  relpersistence 
)

Definition at line 78 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().

79 {
80  PendingRelDelete *pending;
81  SMgrRelation srel;
82  BackendId backend;
83  bool needs_wal;
84 
85  switch (relpersistence)
86  {
87  case RELPERSISTENCE_TEMP:
88  backend = BackendIdForTempRelations();
89  needs_wal = false;
90  break;
91  case RELPERSISTENCE_UNLOGGED:
92  backend = InvalidBackendId;
93  needs_wal = false;
94  break;
95  case RELPERSISTENCE_PERMANENT:
96  backend = InvalidBackendId;
97  needs_wal = true;
98  break;
99  default:
100  elog(ERROR, "invalid relpersistence: %c", relpersistence);
101  return NULL; /* placate compiler */
102  }
103 
104  srel = smgropen(rnode, backend);
105  smgrcreate(srel, MAIN_FORKNUM, false);
106 
107  if (needs_wal)
109 
110  /* Add the relation to the list of stuff to delete at abort */
111  pending = (PendingRelDelete *)
113  pending->relnode = rnode;
114  pending->backend = backend;
115  pending->atCommit = false; /* delete if abort */
117  pending->next = pendingDeletes;
118  pendingDeletes = pending;
119 
120  return srel;
121 }
BackendId backend
Definition: storage.c:58
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:61
#define InvalidBackendId
Definition: backendid.h:23
int BackendId
Definition: backendid.h:21
RelFileNode node
Definition: relfilenode.h:74
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:841
static PendingRelDelete * pendingDeletes
Definition: storage.c:64
RelFileNode relnode
Definition: storage.c:57
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:796
#define elog(elevel,...)
Definition: elog.h:228
void log_smgrcreate(const RelFileNode *rnode, ForkNumber forkNum)
Definition: storage.c:127

◆ RelationDropStorage()

void RelationDropStorage ( Relation  rel)

Definition at line 147 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().

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

◆ RelationPreserveStorage()

void RelationPreserveStorage ( RelFileNode  rnode,
bool  atCommit 
)

Definition at line 192 of file storage.c.

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

Referenced by ATExecAddIndex(), and write_relmap_file().

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

◆ RelationTruncate()

void RelationTruncate ( Relation  rel,
BlockNumber  nblocks 
)

Definition at line 229 of file storage.c.

References xl_smgr_truncate::blkno, BlockNumberIsValid, blocks, xl_smgr_truncate::flags, FreeSpaceMapPrepareTruncateRel(), FreeSpaceMapVacuumRange(), FSM_FORKNUM, InvalidBlockNumber, MAIN_FORKNUM, MAX_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_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().

230 {
231  bool fsm;
232  bool vm;
233  bool need_fsm_vacuum = false;
234  ForkNumber forks[MAX_FORKNUM];
236  int nforks = 0;
237 
238  /* Open it at the smgr level if not already done */
239  RelationOpenSmgr(rel);
240 
241  /*
242  * Make sure smgr_targblock etc aren't pointing somewhere past new end
243  */
247 
248  /* Prepare for truncation of MAIN fork of the relation */
249  forks[nforks] = MAIN_FORKNUM;
250  blocks[nforks] = nblocks;
251  nforks++;
252 
253  /* Prepare for truncation of the FSM if it exists */
254  fsm = smgrexists(rel->rd_smgr, FSM_FORKNUM);
255  if (fsm)
256  {
257  blocks[nforks] = FreeSpaceMapPrepareTruncateRel(rel, nblocks);
258  if (BlockNumberIsValid(blocks[nforks]))
259  {
260  forks[nforks] = FSM_FORKNUM;
261  nforks++;
262  need_fsm_vacuum = true;
263  }
264  }
265 
266  /* Prepare for truncation of the visibility map too if it exists */
268  if (vm)
269  {
270  blocks[nforks] = visibilitymap_prepare_truncate(rel, nblocks);
271  if (BlockNumberIsValid(blocks[nforks]))
272  {
273  forks[nforks] = VISIBILITYMAP_FORKNUM;
274  nforks++;
275  }
276  }
277 
278  /*
279  * We WAL-log the truncation before actually truncating, which means
280  * trouble if the truncation fails. If we then crash, the WAL replay
281  * likely isn't going to succeed in the truncation either, and cause a
282  * PANIC. It's tempting to put a critical section here, but that cure
283  * would be worse than the disease. It would turn a usually harmless
284  * failure to truncate, that might spell trouble at WAL replay, into a
285  * certain PANIC.
286  */
287  if (RelationNeedsWAL(rel))
288  {
289  /*
290  * Make an XLOG entry reporting the file truncation.
291  */
292  XLogRecPtr lsn;
293  xl_smgr_truncate xlrec;
294 
295  xlrec.blkno = nblocks;
296  xlrec.rnode = rel->rd_node;
297  xlrec.flags = SMGR_TRUNCATE_ALL;
298 
299  XLogBeginInsert();
300  XLogRegisterData((char *) &xlrec, sizeof(xlrec));
301 
302  lsn = XLogInsert(RM_SMGR_ID,
304 
305  /*
306  * Flush, because otherwise the truncation of the main relation might
307  * hit the disk before the WAL record, and the truncation of the FSM
308  * or visibility map. If we crashed during that window, we'd be left
309  * with a truncated heap, but the FSM or visibility map would still
310  * contain entries for the non-existent heap pages.
311  */
312  if (fsm || vm)
313  XLogFlush(lsn);
314  }
315 
316  /* Do the real work to truncate relation forks */
317  smgrtruncate(rel->rd_smgr, forks, nforks, blocks);
318 
319  /*
320  * Update upper-level FSM pages to account for the truncation.
321  * This is important because the just-truncated pages were likely
322  * marked as all-free, and would be preferentially selected.
323  */
324  if (need_fsm_vacuum)
326 }
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
uint32 BlockNumber
Definition: block.h:31
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:2805
#define RelationOpenSmgr(relation)
Definition: rel.h:479
BlockNumber FreeSpaceMapPrepareTruncateRel(Relation rel, BlockNumber nblocks)
Definition: freespace.c:261
ForkNumber
Definition: relpath.h:40
#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
void smgrtruncate(SMgrRelation reln, ForkNumber *forknum, int nforks, BlockNumber *nblocks)
Definition: smgr.c:571
#define BlockNumberIsValid(blockNumber)
Definition: block.h:70
RelFileNode rd_node
Definition: rel.h:54
uint64 XLogRecPtr
Definition: xlogdefs.h:21
BlockNumber smgr_targblock
Definition: smgr.h:54
#define InvalidBlockNumber
Definition: block.h:33
#define MAX_FORKNUM
Definition: relpath.h:55
#define RelationNeedsWAL(relation)
Definition: rel.h:524
static int64 blocks
Definition: pg_checksums.c:35
BlockNumber visibilitymap_prepare_truncate(Relation rel, BlockNumber nheapblocks)
BlockNumber blkno
Definition: storage_xlog.h:48
#define SMGR_TRUNCATE_ALL
Definition: storage_xlog.h:43
void XLogBeginInsert(void)
Definition: xloginsert.c:120
void FreeSpaceMapVacuumRange(Relation rel, BlockNumber start, BlockNumber end)
Definition: freespace.c:352

◆ smgrDoPendingDeletes()

void smgrDoPendingDeletes ( bool  isCommit)

Definition at line 430 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().

431 {
432  int nestLevel = GetCurrentTransactionNestLevel();
433  PendingRelDelete *pending;
434  PendingRelDelete *prev;
436  int nrels = 0,
437  i = 0,
438  maxrels = 0;
439  SMgrRelation *srels = NULL;
440 
441  prev = NULL;
442  for (pending = pendingDeletes; pending != NULL; pending = next)
443  {
444  next = pending->next;
445  if (pending->nestLevel < nestLevel)
446  {
447  /* outer-level entries should not be processed yet */
448  prev = pending;
449  }
450  else
451  {
452  /* unlink list entry first, so we don't retry on failure */
453  if (prev)
454  prev->next = next;
455  else
457  /* do deletion if called for */
458  if (pending->atCommit == isCommit)
459  {
460  SMgrRelation srel;
461 
462  srel = smgropen(pending->relnode, pending->backend);
463 
464  /* allocate the initial array, or extend it, if needed */
465  if (maxrels == 0)
466  {
467  maxrels = 8;
468  srels = palloc(sizeof(SMgrRelation) * maxrels);
469  }
470  else if (maxrels <= nrels)
471  {
472  maxrels *= 2;
473  srels = repalloc(srels, sizeof(SMgrRelation) * maxrels);
474  }
475 
476  srels[nrels++] = srel;
477  }
478  /* must explicitly free the list entry */
479  pfree(pending);
480  /* prev does not change */
481  }
482  }
483 
484  if (nrels > 0)
485  {
486  smgrdounlinkall(srels, nrels, false);
487 
488  for (i = 0; i < nrels; i++)
489  smgrclose(srels[i]);
490 
491  pfree(srels);
492  }
493 }
BackendId backend
Definition: storage.c:58
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:405
void pfree(void *pointer)
Definition: mcxt.c:1056
SMgrRelation smgropen(RelFileNode rnode, BackendId backend)
Definition: smgr.c:145
struct PendingRelDelete * next
Definition: storage.c:61
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:841
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1069
static PendingRelDelete * pendingDeletes
Definition: storage.c:64
void * palloc(Size size)
Definition: mcxt.c:949
RelFileNode relnode
Definition: storage.c:57
int i

◆ smgrGetPendingDeletes()

int smgrGetPendingDeletes ( bool  forCommit,
RelFileNode **  ptr 
)

Definition at line 513 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().

514 {
515  int nestLevel = GetCurrentTransactionNestLevel();
516  int nrels;
517  RelFileNode *rptr;
518  PendingRelDelete *pending;
519 
520  nrels = 0;
521  for (pending = pendingDeletes; pending != NULL; pending = pending->next)
522  {
523  if (pending->nestLevel >= nestLevel && pending->atCommit == forCommit
524  && pending->backend == InvalidBackendId)
525  nrels++;
526  }
527  if (nrels == 0)
528  {
529  *ptr = NULL;
530  return 0;
531  }
532  rptr = (RelFileNode *) palloc(nrels * sizeof(RelFileNode));
533  *ptr = rptr;
534  for (pending = pendingDeletes; pending != NULL; pending = pending->next)
535  {
536  if (pending->nestLevel >= nestLevel && pending->atCommit == forCommit
537  && pending->backend == InvalidBackendId)
538  {
539  *rptr = pending->relnode;
540  rptr++;
541  }
542  }
543  return nrels;
544 }
BackendId backend
Definition: storage.c:58
struct PendingRelDelete * next
Definition: storage.c:61
#define InvalidBackendId
Definition: backendid.h:23
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:841
static PendingRelDelete * pendingDeletes
Definition: storage.c:64
void * palloc(Size size)
Definition: mcxt.c:949
RelFileNode relnode
Definition: storage.c:57