#include "access/xlog.h"#include "lib/stringinfo.h"#include "storage/block.h"#include "storage/relfilenode.h"#include "utils/relcache.h"


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) |
| 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 }
1.5.8