PostgreSQL Source Code  git master
storage.h File Reference
#include "storage/block.h"
#include "storage/relfilenode.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

void RelationCreateStorage (RelFileNode rnode, char relpersistence)
 
void RelationDropStorage (Relation rel)
 
void RelationPreserveStorage (RelFileNode rnode, bool atCommit)
 
void RelationTruncate (Relation rel, BlockNumber nblocks)
 
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 470 of file storage.c.

References smgrDoPendingDeletes().

Referenced by AbortSubTransaction().

471 {
472  smgrDoPendingDeletes(false);
473 }
void smgrDoPendingDeletes(bool isCommit)
Definition: storage.c:305

◆ AtSubCommit_smgr()

void AtSubCommit_smgr ( void  )

Definition at line 450 of file storage.c.

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

Referenced by CommitSubTransaction().

451 {
452  int nestLevel = GetCurrentTransactionNestLevel();
453  PendingRelDelete *pending;
454 
455  for (pending = pendingDeletes; pending != NULL; pending = pending->next)
456  {
457  if (pending->nestLevel >= nestLevel)
458  pending->nestLevel = nestLevel - 1;
459  }
460 }
struct PendingRelDelete * next
Definition: storage.c:60
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:753
static PendingRelDelete * pendingDeletes
Definition: storage.c:63

◆ PostPrepare_smgr()

void PostPrepare_smgr ( void  )

Definition at line 429 of file storage.c.

References PendingRelDelete::next, and pfree().

Referenced by PrepareTransaction().

430 {
431  PendingRelDelete *pending;
433 
434  for (pending = pendingDeletes; pending != NULL; pending = next)
435  {
436  next = pending->next;
438  /* must explicitly free the list entry */
439  pfree(pending);
440  }
441 }
static int32 next
Definition: blutils.c:211
void pfree(void *pointer)
Definition: mcxt.c:1031
struct PendingRelDelete * next
Definition: storage.c:60
static PendingRelDelete * pendingDeletes
Definition: storage.c:63

◆ RelationCreateStorage()

void RelationCreateStorage ( RelFileNode  rnode,
char  relpersistence 
)

Definition at line 77 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 ATExecSetTableSpace(), heap_create(), and RelationSetNewRelfilenode().

78 {
79  PendingRelDelete *pending;
80  SMgrRelation srel;
81  BackendId backend;
82  bool needs_wal;
83 
84  switch (relpersistence)
85  {
86  case RELPERSISTENCE_TEMP:
87  backend = BackendIdForTempRelations();
88  needs_wal = false;
89  break;
90  case RELPERSISTENCE_UNLOGGED:
91  backend = InvalidBackendId;
92  needs_wal = false;
93  break;
94  case RELPERSISTENCE_PERMANENT:
95  backend = InvalidBackendId;
96  needs_wal = true;
97  break;
98  default:
99  elog(ERROR, "invalid relpersistence: %c", relpersistence);
100  return; /* placate compiler */
101  }
102 
103  srel = smgropen(rnode, backend);
104  smgrcreate(srel, MAIN_FORKNUM, false);
105 
106  if (needs_wal)
108 
109  /* Add the relation to the list of stuff to delete at abort */
110  pending = (PendingRelDelete *)
112  pending->relnode = rnode;
113  pending->backend = backend;
114  pending->atCommit = false; /* delete if abort */
116  pending->next = pendingDeletes;
117  pendingDeletes = pending;
118 }
BackendId backend
Definition: storage.c:57
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:376
#define ERROR
Definition: elog.h:43
char relpersistence
Definition: pg_class.h:50
RelFileNodeBackend smgr_rnode
Definition: smgr.h:43
#define BackendIdForTempRelations()
Definition: backendid.h:34
MemoryContext TopMemoryContext
Definition: mcxt.c:44
SMgrRelation smgropen(RelFileNode rnode, BackendId backend)
Definition: smgr.c:137
struct PendingRelDelete * next
Definition: storage.c:60
#define InvalidBackendId
Definition: backendid.h:23
int BackendId
Definition: backendid.h:21
RelFileNode node
Definition: relfilenode.h:74
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:753
static PendingRelDelete * pendingDeletes
Definition: storage.c:63
RelFileNode relnode
Definition: storage.c:56
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:771
void log_smgrcreate(RelFileNode *rnode, ForkNumber forkNum)
Definition: storage.c:124
#define elog
Definition: elog.h:219

◆ RelationDropStorage()

void RelationDropStorage ( Relation  rel)

Definition at line 144 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 ATExecSetTableSpace(), DefineQueryRewrite(), heap_drop_with_catalog(), index_drop(), and RelationSetNewRelfilenode().

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

◆ RelationPreserveStorage()

void RelationPreserveStorage ( RelFileNode  rnode,
bool  atCommit 
)

Definition at line 189 of file storage.c.

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

Referenced by ATExecAddIndex(), and write_relmap_file().

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

◆ RelationTruncate()

void RelationTruncate ( Relation  rel,
BlockNumber  nblocks 
)

Definition at line 226 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 heap_truncate_one_rel(), lazy_truncate_heap(), RelationTruncateIndexes(), and spgvacuumscan().

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

◆ smgrDoPendingDeletes()

void smgrDoPendingDeletes ( bool  isCommit)

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

306 {
307  int nestLevel = GetCurrentTransactionNestLevel();
308  PendingRelDelete *pending;
309  PendingRelDelete *prev;
311  int nrels = 0,
312  i = 0,
313  maxrels = 0;
314  SMgrRelation *srels = NULL;
315 
316  prev = NULL;
317  for (pending = pendingDeletes; pending != NULL; pending = next)
318  {
319  next = pending->next;
320  if (pending->nestLevel < nestLevel)
321  {
322  /* outer-level entries should not be processed yet */
323  prev = pending;
324  }
325  else
326  {
327  /* unlink list entry first, so we don't retry on failure */
328  if (prev)
329  prev->next = next;
330  else
332  /* do deletion if called for */
333  if (pending->atCommit == isCommit)
334  {
335  SMgrRelation srel;
336 
337  srel = smgropen(pending->relnode, pending->backend);
338 
339  /* allocate the initial array, or extend it, if needed */
340  if (maxrels == 0)
341  {
342  maxrels = 8;
343  srels = palloc(sizeof(SMgrRelation) * maxrels);
344  }
345  else if (maxrels <= nrels)
346  {
347  maxrels *= 2;
348  srels = repalloc(srels, sizeof(SMgrRelation) * maxrels);
349  }
350 
351  srels[nrels++] = srel;
352  }
353  /* must explicitly free the list entry */
354  pfree(pending);
355  /* prev does not change */
356  }
357  }
358 
359  if (nrels > 0)
360  {
361  smgrdounlinkall(srels, nrels, false);
362 
363  for (i = 0; i < nrels; i++)
364  smgrclose(srels[i]);
365 
366  pfree(srels);
367  }
368 }
BackendId backend
Definition: storage.c:57
void smgrclose(SMgrRelation reln)
Definition: smgr.c:296
static int32 next
Definition: blutils.c:211
void smgrdounlinkall(SMgrRelation *rels, int nrels, bool isRedo)
Definition: smgr.c:471
void pfree(void *pointer)
Definition: mcxt.c:1031
SMgrRelation smgropen(RelFileNode rnode, BackendId backend)
Definition: smgr.c:137
struct PendingRelDelete * next
Definition: storage.c:60
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:753
void * repalloc(void *pointer, Size size)
Definition: mcxt.c:1044
static PendingRelDelete * pendingDeletes
Definition: storage.c:63
void * palloc(Size size)
Definition: mcxt.c:924
RelFileNode relnode
Definition: storage.c:56
int i

◆ smgrGetPendingDeletes()

int smgrGetPendingDeletes ( bool  forCommit,
RelFileNode **  ptr 
)

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

389 {
390  int nestLevel = GetCurrentTransactionNestLevel();
391  int nrels;
392  RelFileNode *rptr;
393  PendingRelDelete *pending;
394 
395  nrels = 0;
396  for (pending = pendingDeletes; pending != NULL; pending = pending->next)
397  {
398  if (pending->nestLevel >= nestLevel && pending->atCommit == forCommit
399  && pending->backend == InvalidBackendId)
400  nrels++;
401  }
402  if (nrels == 0)
403  {
404  *ptr = NULL;
405  return 0;
406  }
407  rptr = (RelFileNode *) palloc(nrels * sizeof(RelFileNode));
408  *ptr = rptr;
409  for (pending = pendingDeletes; pending != NULL; pending = pending->next)
410  {
411  if (pending->nestLevel >= nestLevel && pending->atCommit == forCommit
412  && pending->backend == InvalidBackendId)
413  {
414  *rptr = pending->relnode;
415  rptr++;
416  }
417  }
418  return nrels;
419 }
BackendId backend
Definition: storage.c:57
struct PendingRelDelete * next
Definition: storage.c:60
#define InvalidBackendId
Definition: backendid.h:23
int GetCurrentTransactionNestLevel(void)
Definition: xact.c:753
static PendingRelDelete * pendingDeletes
Definition: storage.c:63
void * palloc(Size size)
Definition: mcxt.c:924
RelFileNode relnode
Definition: storage.c:56