Header And Logo

PostgreSQL
| The world's most advanced open source database.

storage.h File Reference

#include "access/xlog.h"
#include "lib/stringinfo.h"
#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, bool istemp)
void RelationDropStorage (Relation rel)
void RelationTruncate (Relation rel, BlockNumber nblocks)
void smgrDoPendingDeletes (bool isCommit)
int smgrGetPendingDeletes (bool forCommit, RelFileNode **ptr, bool *haveNonTemp)
void AtSubCommit_smgr (void)
void AtSubAbort_smgr (void)
void PostPrepare_smgr (void)
void smgr_redo (XLogRecPtr lsn, XLogRecord *record)
void smgr_desc (StringInfo buf, uint8 xl_info, char *rec)


Function Documentation

void AtSubAbort_smgr ( void   ) 

Definition at line 394 of file storage.c.

References smgrDoPendingDeletes().

Referenced by AbortSubTransaction().

00395 {
00396     smgrDoPendingDeletes(false);
00397 }

void AtSubCommit_smgr ( void   ) 

Definition at line 374 of file storage.c.

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

Referenced by CommitSubTransaction().

00375 {
00376     int         nestLevel = GetCurrentTransactionNestLevel();
00377     PendingRelDelete *pending;
00378 
00379     for (pending = pendingDeletes; pending != NULL; pending = pending->next)
00380     {
00381         if (pending->nestLevel >= nestLevel)
00382             pending->nestLevel = nestLevel - 1;
00383     }
00384 }

void PostPrepare_smgr ( void   ) 

Definition at line 353 of file storage.c.

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

Referenced by PrepareTransaction().

00354 {
00355     PendingRelDelete *pending;
00356     PendingRelDelete *next;
00357 
00358     for (pending = pendingDeletes; pending != NULL; pending = next)
00359     {
00360         next = pending->next;
00361         pendingDeletes = next;
00362         /* must explicitly free the list entry */
00363         pfree(pending);
00364     }
00365 }

void RelationCreateStorage ( RelFileNode  rnode,
bool  istemp 
)

Definition at line 98 of file storage.c.

References PendingRelDelete::atCommit, XLogRecData::buffer, XLogRecData::data, GetCurrentTransactionNestLevel(), InvalidBuffer, PendingRelDelete::isTemp, XLogRecData::len, MAIN_FORKNUM, MemoryContextAlloc(), PendingRelDelete::nestLevel, PendingRelDelete::next, XLogRecData::next, NULL, PendingRelDelete::relnode, RM_SMGR_ID, xl_smgr_create::rnode, smgrcreate(), smgropen(), TopMemoryContext, XLOG_SMGR_CREATE, and XLogInsert().

Referenced by ATExecSetTableSpace(), heap_create(), and setNewRelfilenode().

00099 {
00100     PendingRelDelete *pending;
00101     XLogRecPtr  lsn;
00102     XLogRecData rdata;
00103     xl_smgr_create xlrec;
00104     SMgrRelation srel;
00105 
00106     srel = smgropen(rnode);
00107     smgrcreate(srel, MAIN_FORKNUM, false);
00108 
00109     if (!istemp)
00110     {
00111         /*
00112          * Make an XLOG entry showing the file creation.  If we abort, the
00113          * file will be dropped at abort time.
00114          */
00115         xlrec.rnode = rnode;
00116 
00117         rdata.data = (char *) &xlrec;
00118         rdata.len = sizeof(xlrec);
00119         rdata.buffer = InvalidBuffer;
00120         rdata.next = NULL;
00121 
00122         lsn = XLogInsert(RM_SMGR_ID, XLOG_SMGR_CREATE, &rdata);
00123     }
00124 
00125     /* Add the relation to the list of stuff to delete at abort */
00126     pending = (PendingRelDelete *)
00127         MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDelete));
00128     pending->relnode = rnode;
00129     pending->isTemp = istemp;
00130     pending->atCommit = false;  /* delete if abort */
00131     pending->nestLevel = GetCurrentTransactionNestLevel();
00132     pending->next = pendingDeletes;
00133     pendingDeletes = pending;
00134 }

void RelationDropStorage ( Relation  rel  ) 

Definition at line 141 of file storage.c.

References PendingRelDelete::atCommit, GetCurrentTransactionNestLevel(), PendingRelDelete::isTemp, MemoryContextAlloc(), PendingRelDelete::nestLevel, PendingRelDelete::next, RelationData::rd_istemp, RelationData::rd_node, RelationCloseSmgr, PendingRelDelete::relnode, and TopMemoryContext.

Referenced by ATExecSetTableSpace(), DefineQueryRewrite(), heap_drop_with_catalog(), index_drop(), and setNewRelfilenode().

00142 {
00143     PendingRelDelete *pending;
00144 
00145     /* Add the relation to the list of stuff to delete at commit */
00146     pending = (PendingRelDelete *)
00147         MemoryContextAlloc(TopMemoryContext, sizeof(PendingRelDelete));
00148     pending->relnode = rel->rd_node;
00149     pending->isTemp = rel->rd_istemp;
00150     pending->atCommit = true;   /* delete if commit */
00151     pending->nestLevel = GetCurrentTransactionNestLevel();
00152     pending->next = pendingDeletes;
00153     pendingDeletes = pending;
00154 
00155     /*
00156      * NOTE: if the relation was created in this transaction, it will now be
00157      * present in the pending-delete list twice, once with atCommit true and
00158      * once with atCommit false.  Hence, it will be physically deleted at end
00159      * of xact in either case (and the other entry will be ignored by
00160      * smgrDoPendingDeletes, so no error will occur).  We could instead remove
00161      * the existing list entry and delete the physical file immediately, but
00162      * for now I'll keep the logic simple.
00163      */
00164 
00165     RelationCloseSmgr(rel);
00166 }

void RelationTruncate ( Relation  rel,
BlockNumber  nblocks 
)

Definition at line 176 of file storage.c.

References xl_smgr_truncate::blkno, XLogRecData::buffer, XLogRecData::data, FreeSpaceMapTruncateRel(), FSM_FORKNUM, InvalidBlockNumber, InvalidBuffer, XLogRecData::len, MAIN_FORKNUM, XLogRecData::next, NULL, RelationData::rd_istemp, RelationData::rd_node, RelationData::rd_smgr, RelationData::rd_targblock, RelationOpenSmgr, RM_SMGR_ID, xl_smgr_truncate::rnode, smgrexists(), smgrtruncate(), VISIBILITYMAP_FORKNUM, visibilitymap_truncate(), XLOG_SMGR_TRUNCATE, XLogFlush(), and XLogInsert().

Referenced by btvacuumscan(), ginvacuumcleanup(), gistvacuumcleanup(), heap_truncate(), lazy_truncate_heap(), reindex_index(), RelationTruncateIndexes(), repair_frag(), and vacuum_heap().

00177 {
00178     bool        fsm;
00179     bool        vm;
00180 
00181     /* Open it at the smgr level if not already done */
00182     RelationOpenSmgr(rel);
00183 
00184     /* Make sure rd_targblock isn't pointing somewhere past end */
00185     rel->rd_targblock = InvalidBlockNumber;
00186 
00187     /* Truncate the FSM first if it exists */
00188     fsm = smgrexists(rel->rd_smgr, FSM_FORKNUM);
00189     if (fsm)
00190         FreeSpaceMapTruncateRel(rel, nblocks);
00191 
00192     /* Truncate the visibility map too if it exists. */
00193     vm = smgrexists(rel->rd_smgr, VISIBILITYMAP_FORKNUM);
00194     if (vm)
00195         visibilitymap_truncate(rel, nblocks);
00196 
00197     /*
00198      * We WAL-log the truncation before actually truncating, which means
00199      * trouble if the truncation fails. If we then crash, the WAL replay
00200      * likely isn't going to succeed in the truncation either, and cause a
00201      * PANIC. It's tempting to put a critical section here, but that cure
00202      * would be worse than the disease. It would turn a usually harmless
00203      * failure to truncate, that could spell trouble at WAL replay, into a
00204      * certain PANIC.
00205      */
00206     if (!rel->rd_istemp)
00207     {
00208         /*
00209          * Make an XLOG entry showing the file truncation.
00210          */
00211         XLogRecPtr  lsn;
00212         XLogRecData rdata;
00213         xl_smgr_truncate xlrec;
00214 
00215         xlrec.blkno = nblocks;
00216         xlrec.rnode = rel->rd_node;
00217 
00218         rdata.data = (char *) &xlrec;
00219         rdata.len = sizeof(xlrec);
00220         rdata.buffer = InvalidBuffer;
00221         rdata.next = NULL;
00222 
00223         lsn = XLogInsert(RM_SMGR_ID, XLOG_SMGR_TRUNCATE, &rdata);
00224 
00225         /*
00226          * Flush, because otherwise the truncation of the main relation might
00227          * hit the disk before the WAL record, and the truncation of the FSM
00228          * or visibility map. If we crashed during that window, we'd be left
00229          * with a truncated heap, but the FSM or visibility map would still
00230          * contain entries for the non-existent heap pages.
00231          */
00232         if (fsm || vm)
00233             XLogFlush(lsn);
00234     }
00235 
00236     /* Do the real work */
00237     smgrtruncate(rel->rd_smgr, MAIN_FORKNUM, nblocks, rel->rd_istemp);
00238 }

void smgr_desc ( StringInfo  buf,
uint8  xl_info,
char *  rec 
)

Definition at line 450 of file storage.c.

References appendStringInfo(), xl_smgr_truncate::blkno, MAIN_FORKNUM, pfree(), relpath(), xl_smgr_truncate::rnode, xl_smgr_create::rnode, XLOG_SMGR_CREATE, XLOG_SMGR_TRUNCATE, and XLR_INFO_MASK.

00451 {
00452     uint8       info = xl_info & ~XLR_INFO_MASK;
00453 
00454     if (info == XLOG_SMGR_CREATE)
00455     {
00456         xl_smgr_create *xlrec = (xl_smgr_create *) rec;
00457         char       *path = relpath(xlrec->rnode, MAIN_FORKNUM);
00458 
00459         appendStringInfo(buf, "file create: %s", path);
00460         pfree(path);
00461     }
00462     else if (info == XLOG_SMGR_TRUNCATE)
00463     {
00464         xl_smgr_truncate *xlrec = (xl_smgr_truncate *) rec;
00465         char       *path = relpath(xlrec->rnode, MAIN_FORKNUM);
00466 
00467         appendStringInfo(buf, "file truncate: %s to %u blocks", path,
00468                          xlrec->blkno);
00469         pfree(path);
00470     }
00471     else
00472         appendStringInfo(buf, "UNKNOWN");
00473 }

void smgr_redo ( XLogRecPtr  lsn,
XLogRecord record 
)

Definition at line 400 of file storage.c.

References Assert, xl_smgr_truncate::blkno, CreateFakeRelcacheEntry(), elog, FreeFakeRelcacheEntry(), FreeSpaceMapTruncateRel(), FSM_FORKNUM, MAIN_FORKNUM, PANIC, xl_smgr_truncate::rnode, xl_smgr_create::rnode, smgrcreate(), smgrexists(), smgropen(), smgrtruncate(), XLogRecord::xl_info, XLOG_SMGR_CREATE, XLOG_SMGR_TRUNCATE, XLogRecGetData, XLogTruncateRelation(), XLR_BKP_BLOCK_MASK, and XLR_INFO_MASK.

00401 {
00402     uint8       info = record->xl_info & ~XLR_INFO_MASK;
00403 
00404     /* Backup blocks are not used in smgr records */
00405     Assert(!(record->xl_info & XLR_BKP_BLOCK_MASK));
00406 
00407     if (info == XLOG_SMGR_CREATE)
00408     {
00409         xl_smgr_create *xlrec = (xl_smgr_create *) XLogRecGetData(record);
00410         SMgrRelation reln;
00411 
00412         reln = smgropen(xlrec->rnode);
00413         smgrcreate(reln, MAIN_FORKNUM, true);
00414     }
00415     else if (info == XLOG_SMGR_TRUNCATE)
00416     {
00417         xl_smgr_truncate *xlrec = (xl_smgr_truncate *) XLogRecGetData(record);
00418         SMgrRelation reln;
00419 
00420         reln = smgropen(xlrec->rnode);
00421 
00422         /*
00423          * Forcibly create relation if it doesn't exist (which suggests that
00424          * it was dropped somewhere later in the WAL sequence).  As in
00425          * XLogOpenRelation, we prefer to recreate the rel and replay the log
00426          * as best we can until the drop is seen.
00427          */
00428         smgrcreate(reln, MAIN_FORKNUM, true);
00429 
00430         smgrtruncate(reln, MAIN_FORKNUM, xlrec->blkno, false);
00431 
00432         /* Also tell xlogutils.c about it */
00433         XLogTruncateRelation(xlrec->rnode, MAIN_FORKNUM, xlrec->blkno);
00434 
00435         /* Truncate FSM too */
00436         if (smgrexists(reln, FSM_FORKNUM))
00437         {
00438             Relation    rel = CreateFakeRelcacheEntry(xlrec->rnode);
00439 
00440             FreeSpaceMapTruncateRel(rel, xlrec->blkno);
00441             FreeFakeRelcacheEntry(rel);
00442         }
00443 
00444     }
00445     else
00446         elog(PANIC, "smgr_redo: unknown op code %u", info);
00447 }

void smgrDoPendingDeletes ( bool  isCommit  ) 

Definition at line 247 of file storage.c.

References PendingRelDelete::atCommit, GetCurrentTransactionNestLevel(), i, PendingRelDelete::isTemp, MAX_FORKNUM, PendingRelDelete::nestLevel, PendingRelDelete::next, next(), NULL, pfree(), PendingRelDelete::relnode, smgrclose(), smgrdounlink(), smgrexists(), and smgropen().

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

00248 {
00249     int         nestLevel = GetCurrentTransactionNestLevel();
00250     PendingRelDelete *pending;
00251     PendingRelDelete *prev;
00252     PendingRelDelete *next;
00253 
00254     prev = NULL;
00255     for (pending = pendingDeletes; pending != NULL; pending = next)
00256     {
00257         next = pending->next;
00258         if (pending->nestLevel < nestLevel)
00259         {
00260             /* outer-level entries should not be processed yet */
00261             prev = pending;
00262         }
00263         else
00264         {
00265             /* unlink list entry first, so we don't retry on failure */
00266             if (prev)
00267                 prev->next = next;
00268             else
00269                 pendingDeletes = next;
00270             /* do deletion if called for */
00271             if (pending->atCommit == isCommit)
00272             {
00273                 int         i;
00274 
00275                 /* schedule unlinking old files */
00276                 SMgrRelation srel;
00277 
00278                 srel = smgropen(pending->relnode);
00279                 for (i = 0; i <= MAX_FORKNUM; i++)
00280                 {
00281                     if (smgrexists(srel, i))
00282                         smgrdounlink(srel,
00283                                      i,
00284                                      pending->isTemp,
00285                                      false);
00286                 }
00287                 smgrclose(srel);
00288             }
00289             /* must explicitly free the list entry */
00290             pfree(pending);
00291             /* prev does not change */
00292         }
00293     }
00294 }

int smgrGetPendingDeletes ( bool  forCommit,
RelFileNode **  ptr,
bool haveNonTemp 
)

Definition at line 310 of file storage.c.

References PendingRelDelete::atCommit, GetCurrentTransactionNestLevel(), PendingRelDelete::isTemp, PendingRelDelete::nestLevel, PendingRelDelete::next, NULL, palloc, and PendingRelDelete::relnode.

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

00311 {
00312     int         nestLevel = GetCurrentTransactionNestLevel();
00313     int         nrels;
00314     RelFileNode *rptr;
00315     PendingRelDelete *pending;
00316 
00317     nrels = 0;
00318     if (haveNonTemp)
00319         *haveNonTemp = false;
00320     for (pending = pendingDeletes; pending != NULL; pending = pending->next)
00321     {
00322         if (pending->nestLevel >= nestLevel && pending->atCommit == forCommit)
00323             nrels++;
00324     }
00325     if (nrels == 0)
00326     {
00327         *ptr = NULL;
00328         return 0;
00329     }
00330     rptr = (RelFileNode *) palloc(nrels * sizeof(RelFileNode));
00331     *ptr = rptr;
00332     for (pending = pendingDeletes; pending != NULL; pending = pending->next)
00333     {
00334         if (pending->nestLevel >= nestLevel && pending->atCommit == forCommit)
00335         {
00336             *rptr = pending->relnode;
00337             rptr++;
00338         }
00339         if (haveNonTemp && !pending->isTemp)
00340             *haveNonTemp = true;
00341     }
00342     return nrels;
00343 }


Generated on Sat Jul 4 03:08:44 2009 for PostgreSQL Source Code by  doxygen 1.5.8