#include <VersionedRandomAllocationSegment.h>
Inheritance diagram for VersionedRandomAllocationSegment:
Public Types | |
enum | AllocationOrder { RANDOM_ALLOCATION, ASCENDING_ALLOCATION, CONSECUTIVE_ALLOCATION, LINEAR_ALLOCATION } |
Enumeration of the possible orderings of PageIds returned from allocatePageId. More... | |
Public Member Functions | |
VersionedRandomAllocationSegment (SharedSegment delegateSegment, SharedSegment pTempSegmentInit) | |
void | getLatestPageEntryCopy (PageId pageId, VersionedPageEntry &pageEntryCopy) |
Retrieves the latest copy of a page entry for a specified page, which may correspond to an uncommitted, modified page entry. | |
void | initPageEntry (PageId pageId, PageId versionChainId, TxnId allocationCsn) |
Initializes the versioning fields in a pageEntry for a specified page. | |
void | chainPageEntries (PageId pageId, PageId versionChainId, PageId successorId) |
Chains one page to another, updating the corresponding page entry in the temp segment page. | |
void | updateAllocNodes (ModifiedPageEntryMap const &modifiedPageEntryMap, TxnId commitCsn, bool commit, SharedSegment pOrigSegment) |
Updates the permanent allocation nodes to reflect changes currently in the temporary segment, or vice versa if the updates correspond to a rollback. | |
SXMutex & | getDeallocationMutex () |
| |
bool | getOldPageIds (uint &iSegAlloc, ExtentNum &extentNum, TxnId oldestActiveTxnId, uint numPages, PageSet &oldPageSet) |
Retrieves a batch of pageIds corresponding either to old snapshot pages that are no longer being referenced or pages marked for deallocation. | |
void | deallocateOldPages (PageSet const &oldPageSet, TxnId oldestActiveTxnId) |
Deallocates an old set of pages and updates the version chain that the pages may be a part of. | |
void | freeTempPages () |
Frees any of the remaining temp pages that were used to keep track of allocation node updates. | |
BlockNum | backupAllocationNodes (SharedSegPageBackupRestoreDevice pBackupDevice, bool countDataPages, TxnId lowerBoundCsn, TxnId upperBoundCsn, bool volatile const &abortFlag) |
Writes all the segment and extent allocation pages from this segment sequentially to a backup file. | |
void | backupDataPages (SharedSegPageBackupRestoreDevice pBackupDevice, TxnId lowerBoundCsn, TxnId upperBoundCsn, bool volatile const &abortFlag) |
Walks through all page entries in this segment and locates the ones that have allocationCsn's in between a lower and upper bound. | |
void | restoreFromBackup (SharedSegPageBackupRestoreDevice pBackupDevice, TxnId lowerBoundCsn, TxnId upperBoundCsn, bool volatile const &abortFlag) |
Restores the segment and extent allocation node pages and data pages for this segment from a backup file. | |
virtual bool | isPageIdAllocated (PageId pageId) |
Tests whether a PageId is allocated. | |
virtual PageId | allocatePageId (PageOwnerId ownerId) |
Allocates a page without locking it into memory. | |
virtual PageId | getPageSuccessor (PageId pageId) |
Determines the successor of a given PageId. | |
virtual void | setPageSuccessor (PageId pageId, PageId successorId) |
Sets the successor of a given PageId. | |
virtual void | deallocatePageRange (PageId startPageId, PageId endPageId) |
Deallocates a range of pages allocated from this segment. | |
virtual void | initForUse () |
Performs additional initialization required on the segment after it has been properly formatted. | |
virtual BlockId | translatePageId (PageId) |
Maps from a PageId in this segment to a BlockId. | |
virtual AllocationOrder | getAllocationOrder () const |
| |
virtual BlockNum | getAllocatedSizeInPages () |
| |
virtual BlockNum | getNumPagesOccupiedHighWater () |
Returns the max number of pages occupied by this segment instance. | |
SharedSegment const & | getDelegateSegment () const |
virtual BlockNum | getNumPagesExtended () |
| |
virtual PageId | translateBlockId (BlockId) |
Maps from a BlockId to a PageId in this segment. | |
virtual bool | ensureAllocatedSize (BlockNum nPages) |
Allocates pages as needed to make getAllocatedSizeInPages() meet a lower bound. | |
virtual void | delegatedCheckpoint (Segment &delegatingSegment, CheckpointType checkpointType) |
Helper for DelegatingSegment. | |
virtual PageId | updatePage (PageId pageId, bool needsTranslation=false) |
Determines whether a page can be updated in-place, and if so, prepares the page for update. | |
virtual void | notifyPageMap (CachePage &page) |
Receives notification from CacheImpl as soon as a page is mapped, before any I/O is initiated to retrieve the page contents. | |
virtual void | notifyPageUnmap (CachePage &page) |
Receives notification from CacheImpl just before a page is unmapped. | |
virtual void | notifyAfterPageRead (CachePage &page) |
Receives notification from CacheImpl after a page read completes. | |
virtual void | notifyPageDirty (CachePage &page, bool bDataValid) |
Receives notification from CacheImpl the first time a page becomes dirty after it has been mapped (but before the contents have changed). | |
virtual void | notifyBeforePageFlush (CachePage &page) |
Receives notification from CacheImpl just before a dirty page is flushed to disk. | |
virtual void | notifyAfterPageFlush (CachePage &page) |
Receives notification from CacheImpl when a page flush completes successfully. | |
virtual bool | canFlushPage (CachePage &page) |
Informs CacheImpl whether a dirty page can safely be flushed to disk. | |
SharedCache | getCache () const |
| |
uint | getFullPageSize () const |
| |
uint | getUsablePageSize () const |
| |
SharedSegment | getTracingSegment () |
| |
void | setTracingSegment (WeakSegment pTracingSegmentInit) |
Sets the tracing segment associated with this segment. | |
void | checkpoint (CheckpointType checkpointType=CHECKPOINT_FLUSH_ALL) |
Checkpoints this segment. | |
virtual MappedPageListener * | getMappedPageListener (BlockId blockId) |
Returns the mapped page listener corresponding to a page. | |
virtual bool | isWriteVersioned () |
| |
virtual MappedPageListener * | getTracingListener () |
Retrieves the tracing wrapper corresponding to this listener if tracing is turned on. | |
virtual MappedPageListener * | notifyAfterPageCheckpointFlush (CachePage &page) |
Receives notification that a page has been flushed during a checkpoint. | |
bool | isClosed () const |
| |
void | close () |
Closes this object, releasing any unallocated resources. | |
Static Public Member Functions | |
static PageId | getLinearPageId (BlockNum iPage) |
Constructs a linear PageId based on a linear page number. | |
static BlockNum | getLinearBlockNum (PageId pageId) |
Obtains the linear page number from a linear PageId. | |
Protected Types | |
typedef std::hash_map< PageId, PageId > | PageMap |
typedef PageMap::const_iterator | PageMapConstIter |
Protected Member Functions | |
PageId | getSegAllocPageId (uint iSegPage) const |
Calculates the PageId of a particular SegmentAllocationNode. | |
PageId | getExtentAllocPageId (ExtentNum extentNum) const |
Calculates the PageId of a particular extent allocation node. | |
BlockNum | makePageNum (ExtentNum extentNum, BlockNum iPageInExtent) const |
Calculates a linear page number. | |
void | splitPageId (PageId pageId, uint &iSegAlloc, ExtentNum &extentNum, BlockNum &iPageInExtent) const |
Maps a linear PageId from this segment into the corresponding SegmentAllocationNode, extent allocation node, and extent-relative page index. | |
bool | testPageId (PageId pageId, bool testAllocation, bool thisSegment) |
Common implementation for isPageIdValid and isPageIdAllocated. | |
template<class PageEntryT> | |
PageOwnerId | getPageOwnerIdTemplate (PageId pageId, bool thisSegment) |
Retrieves the ownerId corresponding to a page entry. | |
template<class ExtentAllocationNodeT, class ExtentAllocLockT, class PageEntryT> | |
void | freePageEntryTemplate (ExtentNum extentNum, BlockNum iPageInExtent) |
Marks the page entry corresponding to a deallocated page as unallocated. | |
PageId | getFirstSegAllocPageId () const |
| |
uint | inferSegAllocCount () |
Infers the number of SegmentAllocationNodes from the size of the underlying segment. | |
void | format () |
Formats allocation pages based on current size of underlying segment, marking all pages as deallocated. | |
template<class ExtentAllocationNodeT, class ExtentAllocLockT, class PageEntryT> | |
void | formatPageExtentsTemplate (SegmentAllocationNode &segAllocNode, ExtentNum &extentNum) |
Formats each of the extents within a segment allocation node. | |
template<class ExtentAllocationNodeT, class ExtentAllocLockT, class PageEntryT> | |
void | formatExtentTemplate (ExtentAllocationNodeT &extentNode) |
Formats one extent allocation. | |
PageId | allocatePageIdFromSegment (PageOwnerId ownerId, SharedSegment allocNodeSegment) |
Allocates a page without locking it into memory. | |
template<class ExtentAllocationNodeT, class ExtentAllocLockT, class PageEntryT> | |
PageId | allocateFromExtentTemplate (ExtentNum extentNum, PageOwnerId ownerId, SharedSegment allocNodeSegment) |
Allocates a new page from an extent known to have space. | |
template<class ExtentAllocationNodeT, class ExtentAllocLockT, class PageEntryT> | |
PageId | allocateFromNewExtentTemplate (ExtentNum extentNum, PageOwnerId ownerId, SharedSegment allocNodeSegment) |
Allocates a page from a new extent allocation node. | |
template<class ExtentAllocationNodeT, class PageEntryT> | |
PageId | allocateFromLockedExtentTemplate (ExtentAllocationNodeT &extentNode, ExtentNum extentNum, PageOwnerId ownerId) |
Allocates a new page from an extent known to have space, with the extent allocation node already locked. | |
template<class ExtentAllocationNodeT, class ExtentAllocLockT> | |
void | setPageSuccessorTemplate (PageId pageId, PageId successorId, SharedSegment allocNodeSegment) |
Sets the successor pageId for a page. | |
template<class ExtentAllocationNodeT, class ExtentAllocLockT, class PageEntryT> | |
void | getPageEntryCopyTemplate (PageId pageId, PageEntryT &pageEntryCopy, bool isAllocated, bool thisSegment) |
Retrieves a copy of the page entry for a specified page. | |
void | setUsablePageSize (uint) |
PConstBuffer | getReadableFooter (CachePage &page) |
PBuffer | getWritableFooter (CachePage &page) |
PageId | getLinearPageSuccessor (PageId pageId) |
An implementation of getPageSuccessor suitable for LINEAR_ALLOCATION. | |
void | setLinearPageSuccessor (PageId pageId, PageId successorId) |
An implementation of setPageSuccessor suitable for LINEAR_ALLOCATION. | |
bool | isLinearPageIdAllocated (PageId pageId) |
An implementation of isPageIdAllocated suitable for LINEAR_ALLOCATION when deallocation holes are disallowed. | |
Protected Attributes | |
BlockNum | nPagesPerExtent |
Number of pages in one extent, including the extent allocation node itself (so actual data capacity per extent is one less). | |
BlockNum | nPagesPerSegAlloc |
Number of pages mapped by one SegmentAllocationNode, including the SegmentAllocationNode itself. | |
ExtentNum | nExtentsPerSegAlloc |
Number of extents mapped by a full SegmentAllocationNode. | |
SharedCache | pCache |
Cache managing pages of this segment. | |
WeakSegment | pTracingSegment |
The tracing segment associated with this segment, if tracing is turned on. | |
bool | needsClose |
Private Types | |
typedef std::hash_map< PageId, SharedModifiedAllocationNode > | ModifiedAllocationNodeMap |
typedef ModifiedAllocationNodeMap::const_iterator | NodeMapConstIter |
Private Member Functions | |
template<class AllocationLockT> | |
PageId | getTempAllocNodePage (PageId origNodePageId, bool isSegAllocNode) |
Retrieves the pageId in the temporary segment of the page corresponding to an allocation node page. | |
PageId | findAllocPageIdForRead (PageId origAllocNodePageId, SharedSegment &allocNodeSegment) |
Determines whether an allocation node page has been modified. | |
void | deferDeallocation (PageId pageId) |
Marks a page entry as deallocation deferred in the temporary segment. | |
void | updateExtentEntry (uint iSegAlloc, ExtentNum extentNum, uint allocationCount, bool commit) |
Updates an extent entry corresponding to either a commit or rollback action of page allocations and/or deallocations. | |
void | allocateAllocNodes (uint iSegAlloc, PageId nextPageId, ExtentNum extentNum) |
Allocates a new SegmentAllocationNode and VersionedExtentAllocationNodes if they haven't been allocated yet. | |
void | allocateExtAllocNodes (SegmentAllocationNode &segAllocNode, uint iSegAlloc, ExtentNum extentNum) |
Allocates a new VersionedExtentAllocationNode if it hasn't been allocated yet. | |
void | updatePageEntry (PageId pageId, ExtentNum extentNum, uint iPageInExtent, SharedModifiedPageEntry pModEntry, TxnId commitCsn, bool commit, SharedSegment pOrigSegment) |
Updates a page entry by either copying a page entry from the temporary segment to the permanent one if we're committing the page entry, or the reverse if we're rolling it back. | |
void | copyPageEntryFromTemp (PageId pageId, PageId origPageId, PageId tempPageId, BlockNum iPageInExtent, ModifiedPageEntry::ModType lastModType, TxnId commitCsn, PageOwnerId ownerId) |
Copies a page entry from the temporary segment to the permanent one. | |
void | copyPageEntryToTemp (PageId origPageId, PageId tempPageId, BlockNum iPageInExtent) |
Copies a page entry from the permanent segment to the temporary one. | |
bool | validateFreePageCount (PageId pageId) |
Sanity checks the unallocated page count in a SegmentAllocationNode against the pages marked as unallocated in the corresponding VersionedExtentAllocationNode. | |
void | freeTempPage (PageId origAllocNodePageId, PageId tempAllocNodePageId) |
Frees a temporary page corresponding to an allocation node page, since all temporary updates to the page have either committed or rolled back. | |
TxnId | getOldestTxnId (PageId pageId, TxnId oldestActiveTxnId, PageId &anchorPageId, std::hash_set< PageId > &deallocatedPageSet, bool &deallocateChain) |
Determines the txnId corresponding to the oldest pageId in a page chain that can be deallocated, provided there are pages that can be deallocated. | |
void | deallocateEntirePageChain (PageId pageId, TxnId oldestActiveTxnId, std::hash_set< PageId > &deallocatedPageSet) |
Deallocates an entire page chain. | |
void | deallocateSinglePage (PageId pageId, std::hash_set< PageId > &deallocatedPageSet) |
Deallocates a single page and also discards it from the cache. | |
void | deallocatePageChain (PageId anchorPageId, TxnId deallocationCsn, std::hash_set< PageId > &deallocatedPageSet) |
Deallocates all old pages in a page chain. | |
bool | validatePageChain (PageId anchorPageId) |
Walks a page chain and ensures that all pages in the chain are allocated pages. | |
bool | uncommittedDeallocation (PageId anchorPageId, std::hash_set< PageId > &deallocatedPageSet) |
Determines if a page chain is in the process of being marked deallocation-deferred and has not yet been committed. | |
void | skipDeferredDeallocations (PageId pageId, std::hash_set< PageId > &deallocatedPageSet) |
Adds all pages in a page chain corresponding to deallocation-deferred pages to the set of pages that have been deallocated so we'll skip over them. | |
void | updateTempPageEntry (PageId pageId, VersionedPageEntry const &pageEntry) |
Updates a page entry in the temporary segment, if it exists. | |
void | getCommittedPageEntryCopy (PageId pageId, VersionedPageEntry &pageEntryCopy) |
Retrieves the committed copy of a page entry for a specified page. | |
bool | isPageIdAllocateCommitted (PageId pageId) |
Determines if a page corresponds to a committed allocation. | |
void | chainPageEntries (PageId pageId, PageId versionChainId, PageId successorId, bool thisSegment) |
Chains one page to another, updating either the corresponding permanent page entry or the temporary one. | |
void | locateDataPages (SharedSegPageBackupRestoreDevice pBackupDevice, TxnId lowerBoundCsn, TxnId upperBoundCsn, bool isBackup, bool volatile const &abortFlag) |
void | checkAbort (bool volatile const &abortFlag) |
Determines whether the abort flag is set. | |
PageOwnerId | makeDeallocatedPageOwnerId (TxnId txnId) |
Constructs a pageOwnerId corresponding to a deallocation-deferred page. | |
bool | isDeallocatedPageOwnerId (PageOwnerId pageOwnerId) |
Determines whether a pageOwnerId corresponds to a deallocation-deferred page. | |
TxnId | getDeallocatedTxnId (PageOwnerId pageOwnerId) |
Extracts the id corresponding to the txn that deallocated a page from the page's pageOwnerId. | |
virtual bool | isPageIdValid (PageId pageId) |
Tests whether the given PageId has valid contents (either an allocated data page or an allocation map page). | |
virtual PageId | getSegAllocPageIdForWrite (PageId origSegAllocPageId) |
Retrieves the pageId of the SegmentAllocationNode that should be updated when updates are made to that node. | |
virtual void | undoSegAllocPageWrite (PageId segAllocPageId) |
Indicates that no new pages were allocated from extents within a SegmentAllocationNode. | |
virtual PageId | getExtAllocPageIdForWrite (ExtentNum extentNum) |
Retrieves the pageId of the extent allocation node that should be updated when updates are made to that node. | |
virtual PageId | allocateFromExtent (ExtentNum extentNum, PageOwnerId ownerId) |
Allocates a new page from an extent known to have space. | |
virtual void | formatPageExtents (SegmentAllocationNode &segAllocNode, ExtentNum &extentNum) |
Formats each of the extents within a segment allocation node. | |
virtual PageId | allocateFromNewExtent (ExtentNum extentNum, PageOwnerId ownerId) |
Allocates a page from a new extent allocation node. | |
virtual void | freePageEntry (ExtentNum extentNum, BlockNum iPageInExtent) |
Marks the page entry corresponding to a deallocated page as unallocated. | |
virtual void | markPageEntryUnused (PageEntry &pageEntry) |
Marks a page entry as unused. | |
virtual PageOwnerId | getPageOwnerId (PageId pageId, bool thisSegment) |
Retrieves the ownerId corresponding to a page entry. | |
virtual PageId | getSegAllocPageIdForRead (PageId origSegAllocPageId, SharedSegment &allocNodeSegment) |
Retrieves the actual pageId corresponding to the SegmentAllocationNode that should be accessed when reading from the node. | |
virtual PageId | getExtAllocPageIdForRead (ExtentNum extentNum, SharedSegment &allocNodeSegment) |
Retrieves the actual pageId corresponding to the extent allocation node that should be accessed when reading from the node. | |
virtual void | getPageEntryCopy (PageId pageId, PageEntry &pageEntryCopy, bool isAllocated, bool thisSegment) |
Retrieves a copy of the page entry for a specified page. | |
Private Attributes | |
ModifiedAllocationNodeMap | allocationNodeMap |
Maps allocation node pages to the modified copy of the node that contains uncommitted page modifications. | |
SXMutex | mapMutex |
Mutex used to protect allocationNodeMap. | |
SXMutex | deallocationMutex |
Mutex that prevents multiple deallocations from occuring concurrently. | |
SharedSegment | pTempSegment |
Segment used to allocate pages to store uncommitted modifications to segment and extent allocation node pages. | |
Friends | |
class | SegmentFactory |
When modifications are made to either VersionedExtentAllocationNodes or SegmentAllocationNodes, the changes are reflected in pages originating from a temporary segment. The changes are only copied back to the permanent segment when a transaction commits; changes are thrown away on a rollback.
Page deallocations are handled differently. Deallocated pages are not actually deallocated, but instead are marked as deallocation-deferred. This makes the page unusable but not yet available for re-allocation. A deallocation-deferred page is deallocated by calling the methods getOldPageIds() and deallocateOldPages(). The former finds pages that need to be deallocated, while the latter does the actual deallocation. When the deallocations are done, the modifications are made directly in the permanent segment. The two methods should be called in a loop, one after the other, until getOldPageIds() can no longer find any old pages.
Definition at line 138 of file VersionedRandomAllocationSegment.h.
typedef std::hash_map<PageId, SharedModifiedAllocationNode> VersionedRandomAllocationSegment::ModifiedAllocationNodeMap [private] |
Definition at line 142 of file VersionedRandomAllocationSegment.h.
typedef ModifiedAllocationNodeMap::const_iterator VersionedRandomAllocationSegment::NodeMapConstIter [private] |
Definition at line 144 of file VersionedRandomAllocationSegment.h.
typedef std::hash_map<PageId,PageId> Segment::PageMap [protected, inherited] |
typedef PageMap::const_iterator Segment::PageMapConstIter [protected, inherited] |
enum Segment::AllocationOrder [inherited] |
Enumeration of the possible orderings of PageIds returned from allocatePageId.
The enumeration is from weakest to strongest ordering, and should not be changed.
Definition at line 105 of file Segment.h.
00105 { 00109 RANDOM_ALLOCATION, 00110 00115 ASCENDING_ALLOCATION, 00116 00121 CONSECUTIVE_ALLOCATION, 00122 00128 LINEAR_ALLOCATION 00129 };
VersionedRandomAllocationSegment::VersionedRandomAllocationSegment | ( | SharedSegment | delegateSegment, | |
SharedSegment | pTempSegmentInit | |||
) | [explicit] |
Definition at line 32 of file VersionedRandomAllocationSegment.cpp.
References Segment::getUsablePageSize(), RandomAllocationSegmentBase::nExtentsPerSegAlloc, RandomAllocationSegmentBase::nPagesPerExtent, RandomAllocationSegmentBase::nPagesPerSegAlloc, and pTempSegment.
00035 : RandomAllocationSegmentBase(delegateSegment) 00036 { 00037 nPagesPerExtent = 00038 (getUsablePageSize() - sizeof(VersionedExtentAllocationNode)) 00039 / sizeof(VersionedPageEntry); 00040 00041 // + 1 is for SegAllocNode itself 00042 nPagesPerSegAlloc = nPagesPerExtent*nExtentsPerSegAlloc + 1; 00043 00044 pTempSegment = pTempSegmentInit; 00045 }
PageId VersionedRandomAllocationSegment::getTempAllocNodePage | ( | PageId | origNodePageId, | |
bool | isSegAllocNode | |||
) | [private] |
Retrieves the pageId in the temporary segment of the page corresponding to an allocation node page.
If the page doesn't yet exist in the temporary segment, creates it.
Assumes that the pageEntry will be updated. Therefore, it also increments the update count corresponding to the pageEntry.
origNodePageId | pageId of the node in the permanent segment | |
isSegAllocNode | true if the page being retrieved is a segment allocation node |
Definition at line 82 of file VersionedRandomAllocationSegmentImpl.h.
References allocationNodeMap, Segment::getTracingSegment(), mapMutex, Segment::pCache, and pTempSegment.
00085 { 00086 SXMutexExclusiveGuard mapGuard(mapMutex); 00087 00088 PageId tempNodePageId; 00089 SharedModifiedAllocationNode pModAllocNode; 00090 00091 // If we've already previously modified the allocation node, it 00092 // will be in our map. Otherwise, this is the first time we're modifying 00093 // the node. In that case, allocate a new page in our temp segment 00094 // corresponding to the node. 00095 NodeMapConstIter iter = allocationNodeMap.find(origNodePageId); 00096 if (iter == allocationNodeMap.end()) { 00097 // Allocate a new page and copy the contents of the original page on to 00098 // the new one. 00099 SegmentAccessor tempAccessor(pTempSegment, pCache); 00100 AllocationLockT tempAllocLock(tempAccessor); 00101 tempNodePageId = tempAllocLock.allocatePage(); 00102 00103 SegmentAccessor selfAccessor(getTracingSegment(), pCache); 00104 AllocationLockT allocLock(selfAccessor); 00105 allocLock.lockShared(origNodePageId); 00106 00107 memcpy( 00108 tempAllocLock.getPage().getWritableData(), 00109 allocLock.getPage().getReadableData(), 00110 pTempSegment->getUsablePageSize()); 00111 00112 // Allocate a new map entry 00113 pModAllocNode = 00114 SharedModifiedAllocationNode(new ModifiedAllocationNode()); 00115 pModAllocNode->tempPageId = tempNodePageId; 00116 pModAllocNode->updateCount = 0; 00117 pModAllocNode->isSegAllocNode = isSegAllocNode; 00118 } else { 00119 pModAllocNode = iter->second; 00120 tempNodePageId = pModAllocNode->tempPageId; 00121 } 00122 00123 // Update the map 00124 pModAllocNode->updateCount++; 00125 00126 if (iter == allocationNodeMap.end()) { 00127 allocationNodeMap.insert( 00128 ModifiedAllocationNodeMap::value_type( 00129 origNodePageId, 00130 pModAllocNode)); 00131 } 00132 00133 return tempNodePageId; 00134 }
PageId VersionedRandomAllocationSegment::findAllocPageIdForRead | ( | PageId | origAllocNodePageId, | |
SharedSegment & | allocNodeSegment | |||
) | [private] |
Determines whether an allocation node page has been modified.
If it has been, passes back the temporary pageId corresponding to the page. Otherwise, the original pageId is passed back.
This method assumes that the caller has already acquired a shared mutex on allocationNodeMap.
origAllocNodePageId | pageId of the node in the permanent segment | |
[out] | allocNodeSegment | the temp segment if the node has been modified; otherwise, the segment itself |
Definition at line 107 of file VersionedRandomAllocationSegment.cpp.
References allocationNodeMap, Segment::getTracingSegment(), SXMutex::isLocked(), LOCKMODE_S, mapMutex, and pTempSegment.
Referenced by getExtAllocPageIdForRead(), and getSegAllocPageIdForRead().
00110 { 00111 // If the allocation node corresponding to the desired page has been 00112 // modified, it will be in our map. If so, retrieve the pageId 00113 // corresponding to the modified allocation node, and access that 00114 // page from the temporary segment. Otherwise, access the allocation 00115 // node from permanent storage. 00116 00117 assert(mapMutex.isLocked(LOCKMODE_S)); 00118 PageId tempAllocNodePageId; 00119 NodeMapConstIter iter = allocationNodeMap.find(origAllocNodePageId); 00120 if (iter == allocationNodeMap.end()) { 00121 tempAllocNodePageId = origAllocNodePageId; 00122 allocNodeSegment = getTracingSegment(); 00123 } else { 00124 tempAllocNodePageId = iter->second->tempPageId; 00125 allocNodeSegment = pTempSegment; 00126 } 00127 00128 return tempAllocNodePageId; 00129 }
void VersionedRandomAllocationSegment::deferDeallocation | ( | PageId | pageId | ) | [private] |
Marks a page entry as deallocation deferred in the temporary segment.
Once the txn commits, the permanent entry will also be marked so it can then be deallocated by an ALTER SYSTEM DEALLOCATE OLD statement.
pageId | the pageId of the page entry to be marked |
Definition at line 183 of file VersionedRandomAllocationSegment.cpp.
References getExtAllocPageIdForWrite(), SegNodeLock< Node >::getNodeForWrite(), VersionedExtentAllocationNode::getPageEntry(), isDeallocatedPageOwnerId(), SegPageLock::lockExclusive(), makeDeallocatedPageOwnerId(), PageEntry::ownerId, Segment::pCache, pTempSegment, RandomAllocationSegmentBase::splitPageId(), and UNALLOCATED_PAGE_OWNER_ID.
Referenced by deallocatePageRange().
00184 { 00185 ExtentNum extentNum; 00186 BlockNum iPageInExtent; 00187 uint iSegAlloc; 00188 splitPageId(pageId, iSegAlloc, extentNum, iPageInExtent); 00189 assert(iPageInExtent); 00190 00191 SegmentAccessor segAccessor(pTempSegment, pCache); 00192 VersionedExtentAllocLock extentAllocLock(segAccessor); 00193 extentAllocLock.lockExclusive(getExtAllocPageIdForWrite(extentNum)); 00194 VersionedExtentAllocationNode &extentNode = 00195 extentAllocLock.getNodeForWrite(); 00196 VersionedPageEntry &pageEntry = extentNode.getPageEntry(iPageInExtent); 00197 assert( 00198 pageEntry.ownerId != UNALLOCATED_PAGE_OWNER_ID && 00199 !isDeallocatedPageOwnerId(pageEntry.ownerId)); 00200 // Set the deallocation txnId to an arbitrary value, for now. It will 00201 // get overwritten with a real txnId at commit time. 00202 pageEntry.ownerId = makeDeallocatedPageOwnerId(TxnId(0)); 00203 }
void VersionedRandomAllocationSegment::updateExtentEntry | ( | uint | iSegAlloc, | |
ExtentNum | extentNum, | |||
uint | allocationCount, | |||
bool | commit | |||
) | [private] |
Updates an extent entry corresponding to either a commit or rollback action of page allocations and/or deallocations.
In the case of a commit, the permanent extent entry is updated. In the case of a rollback, the changes made in the temporary extent entry are thrown away.
This method assumes that the caller has already acquired an exclusive mutex on allocationNodeMap.
iSegAlloc | 0-based index of containing SegmentAllocationNode | |
extentNum | absolute 0-based extent number of containing extent allocation node | |
allocationCount | the total number of allocations and deallocations made to a page, which corresponds to the number of updates performed on the extent entry | |
commit | if true, updates correspond to a commit; else updates correspond to a rollback |
Definition at line 559 of file VersionedRandomAllocationSegment.cpp.
References allocationNodeMap, SegmentAllocationNode::getExtentEntry(), SegNodeLock< Node >::getNodeForWrite(), RandomAllocationSegmentBase::getSegAllocPageId(), Segment::getTracingSegment(), SXMutex::isLocked(), SegPageLock::lockExclusive(), LOCKMODE_X, mapMutex, RandomAllocationSegmentBase::nExtentsPerSegAlloc, SegmentAllocationNode::ExtentEntry::nUnallocatedPages, Segment::pCache, and pTempSegment.
Referenced by updateAllocNodes().
00564 { 00565 assert(mapMutex.isLocked(LOCKMODE_X)); 00566 00567 // If the page was newly allocated, we need to update the 00568 // SegmentAllocationNode 00569 00570 if (allocationCount) { 00571 // Update the permanent page if we're committing. Otherwise, update 00572 // the temporary page, reverting the allocations/deallocations. 00573 PageId segAllocPageId = getSegAllocPageId(iSegAlloc); 00574 NodeMapConstIter iter = allocationNodeMap.find(segAllocPageId); 00575 assert(iter != allocationNodeMap.end()); 00576 SharedModifiedAllocationNode pModNode = iter->second; 00577 SharedSegment allocNodeSegment; 00578 PageId segPageId; 00579 if (commit) { 00580 allocNodeSegment = getTracingSegment(); 00581 segPageId = segAllocPageId; 00582 } else { 00583 allocNodeSegment = pTempSegment; 00584 segPageId = pModNode->tempPageId; 00585 } 00586 00587 SegmentAccessor segAccessor(allocNodeSegment, pCache); 00588 SegAllocLock segAllocLock(segAccessor); 00589 segAllocLock.lockExclusive(segPageId); 00590 SegmentAllocationNode &segAllocNode = segAllocLock.getNodeForWrite(); 00591 00592 ExtentNum relativeExtentNum = extentNum % nExtentsPerSegAlloc; 00593 SegmentAllocationNode::ExtentEntry &extentEntry = 00594 segAllocNode.getExtentEntry(relativeExtentNum); 00595 if (commit) { 00596 extentEntry.nUnallocatedPages -= allocationCount; 00597 } else { 00598 extentEntry.nUnallocatedPages += allocationCount; 00599 } 00600 00601 pModNode->updateCount -= allocationCount; 00602 } 00603 }
void VersionedRandomAllocationSegment::allocateAllocNodes | ( | uint | iSegAlloc, | |
PageId | nextPageId, | |||
ExtentNum | extentNum | |||
) | [private] |
Allocates a new SegmentAllocationNode and VersionedExtentAllocationNodes if they haven't been allocated yet.
Also recursively allocates predecessor SegmentAllocationNodes, as needed.
iSegAlloc | 0-based index corresponding to the SegmentAllocationNode that needs to be allocated | |
nextPageId | the pageId to be set as the nextSegAllocPageId for the SegmentAllocationNode being allocated | |
extentNum | absolute 0-based extent number of the extent allocation node that needs to be allocated |
Definition at line 605 of file VersionedRandomAllocationSegment.cpp.
References allocateExtAllocNodes(), SegNodeLock< Node >::checkMagicNumber(), SegNodeLock< Node >::getNodeForWrite(), RandomAllocationSegmentBase::getSegAllocPageId(), Segment::getTracingSegment(), SegPageLock::lockExclusive(), SegmentAllocationNode::nExtents, SegmentAllocationNode::nextSegAllocPageId, RandomAllocationSegmentBase::nPagesPerExtent, SegmentAllocationNode::nPagesPerExtent, NULL_PAGE_ID, Segment::pCache, and SegNodeLock< Node >::setMagicNumber().
Referenced by updateAllocNodes().
00609 { 00610 SegmentAccessor selfAccessor(getTracingSegment(), pCache); 00611 SegAllocLock segAllocLock(selfAccessor); 00612 PageId segAllocPageId = getSegAllocPageId(iSegAlloc); 00613 segAllocLock.lockExclusive(segAllocPageId); 00614 if (segAllocLock.checkMagicNumber()) { 00615 // If the SegmentAllocationNode has already been allocated and this 00616 // is the first call to this method, check if we need to allocate 00617 // VersionedExtentAllocationNodes. Otherwise, set the 00618 // nextSegAllocPageId. 00619 00620 SegmentAllocationNode &node = segAllocLock.getNodeForWrite(); 00621 if (nextPageId == NULL_PAGE_ID) { 00622 allocateExtAllocNodes(node, iSegAlloc, extentNum); 00623 } else { 00624 node.nextSegAllocPageId = nextPageId; 00625 } 00626 } else { 00627 // Allocate a new page and then recursively call this method to set 00628 // the nextSegAllocPageId on the predecessor SegmentAllocationNode 00629 // to the newly allocated page, allocating that SegmentAllocationNode 00630 // if it also hasn't been allocated. If this is the first call to this 00631 // method, check if we need to allocate 00632 // VersionedExtentAllocationNodes. 00633 00634 permAssert(iSegAlloc >= 1); 00635 segAllocLock.setMagicNumber(); 00636 SegmentAllocationNode &newNode = segAllocLock.getNodeForWrite(); 00637 // -1 for the extent allocation node itself 00638 newNode.nPagesPerExtent = nPagesPerExtent - 1; 00639 newNode.nExtents = 0; 00640 newNode.nextSegAllocPageId = nextPageId; 00641 allocateAllocNodes(iSegAlloc - 1, segAllocPageId, extentNum); 00642 if (nextPageId == NULL_PAGE_ID) { 00643 allocateExtAllocNodes(newNode, iSegAlloc, extentNum); 00644 } 00645 } 00646 }
void VersionedRandomAllocationSegment::allocateExtAllocNodes | ( | SegmentAllocationNode & | segAllocNode, | |
uint | iSegAlloc, | |||
ExtentNum | extentNum | |||
) | [private] |
Allocates a new VersionedExtentAllocationNode if it hasn't been allocated yet.
If extent nodes preceding the one that needs to be allocated haven't been allocated either, those are allocated as well.
[in] | segAllocNode | SegmentAllocationNode containing the extent that needs to be allocated |
iSegAlloc | 0-based index corresponding to the SegmentAllocationNode containing the extent that needs to be allocated | |
extentNum | absolute 0-based extent number of the extent allocation node that needs to be allocated |
Definition at line 648 of file VersionedRandomAllocationSegment.cpp.
References RandomAllocationSegmentBase::formatPageExtentsTemplate(), SegmentAllocationNode::nExtents, and RandomAllocationSegmentBase::nExtentsPerSegAlloc.
Referenced by allocateAllocNodes().
00652 { 00653 // Allocate new extents if the one we're going to be updating hasn't 00654 // been allocated yet. Turn off page mapping so the updates will 00655 // be made on the permanent pages. 00656 ExtentNum relativeExtentNum = extentNum % nExtentsPerSegAlloc; 00657 if (segAllocNode.nExtents < relativeExtentNum + 1) { 00658 ExtentNum startExtentNum = 00659 segAllocNode.nExtents + nExtentsPerSegAlloc * iSegAlloc; 00660 segAllocNode.nExtents = relativeExtentNum + 1; 00661 formatPageExtentsTemplate< 00662 VersionedExtentAllocationNode, 00663 VersionedExtentAllocLock, 00664 VersionedPageEntry>( 00665 segAllocNode, 00666 startExtentNum); 00667 } 00668 }
void VersionedRandomAllocationSegment::updatePageEntry | ( | PageId | pageId, | |
ExtentNum | extentNum, | |||
uint | iPageInExtent, | |||
SharedModifiedPageEntry | pModEntry, | |||
TxnId | commitCsn, | |||
bool | commit, | |||
SharedSegment | pOrigSegment | |||
) | [private] |
Updates a page entry by either copying a page entry from the temporary segment to the permanent one if we're committing the page entry, or the reverse if we're rolling it back.
This method assumes that the caller has already acquired an exclusive mutex on allocationNodeMap.
pageId | pageId of the page entry | |
extentNum | absolute 0-based extent number of the extent allocation node corresponding to the page entry | |
iPageInExtent | 0-based index of page in extent | |
pModEntry | information about the modified page entry | |
commitCsn | sequence number to write into the pageEntry on a commit if the pageEntry corresponds to a page allocation; otherwise, set to NULL_TXN_ID | |
commit | true if the updates correspond to a commit | |
pOrigSegment | the originating segment that modified the page entry that needs to be updated |
Definition at line 455 of file VersionedRandomAllocationSegment.cpp.
References ModifiedPageEntry::ALLOCATED, allocationNodeMap, copyPageEntryFromTemp(), copyPageEntryToTemp(), RandomAllocationSegmentBase::getExtentAllocPageId(), SXMutex::isLocked(), LOCKMODE_X, mapMutex, and Segment::pCache.
Referenced by updateAllocNodes().
00463 { 00464 assert(mapMutex.isLocked(LOCKMODE_X)); 00465 00466 // Update the extent allocation page, copying the contents from the 00467 // temporary page in the case of a commit and vice versa for a rollback. 00468 00469 PageId extentPageId = getExtentAllocPageId(extentNum); 00470 NodeMapConstIter iter = allocationNodeMap.find(extentPageId); 00471 assert(iter != allocationNodeMap.end()); 00472 SharedModifiedAllocationNode pModNode = iter->second; 00473 00474 if (commit) { 00475 copyPageEntryFromTemp( 00476 pageId, 00477 extentPageId, 00478 pModNode->tempPageId, 00479 iPageInExtent, 00480 pModEntry->lastModType, 00481 commitCsn, 00482 pModEntry->ownerId); 00483 } else { 00484 // In the case of a rollback of a newly allocated page, remove the 00485 // page from the cache 00486 if (pModEntry->lastModType == ModifiedPageEntry::ALLOCATED) { 00487 pCache->discardPage(pOrigSegment->translatePageId(pageId)); 00488 } 00489 00490 copyPageEntryToTemp(extentPageId, pModNode->tempPageId, iPageInExtent); 00491 } 00492 00493 pModNode->updateCount -= pModEntry->updateCount; 00494 }
void VersionedRandomAllocationSegment::copyPageEntryFromTemp | ( | PageId | pageId, | |
PageId | origPageId, | |||
PageId | tempPageId, | |||
BlockNum | iPageInExtent, | |||
ModifiedPageEntry::ModType | lastModType, | |||
TxnId | commitCsn, | |||
PageOwnerId | ownerId | |||
) | [private] |
Copies a page entry from the temporary segment to the permanent one.
pageId | pageId of the page entry | |
origPageId | pageId of the extent page in the permanent segment | |
tempPageId | pageId of the extent page in the temporary segment | |
iPageInExtent | 0-based index of page in extent | |
lastModType | whether the page was last allocated or deallocated | |
commitCsn | sequence number to write into the pageEntry for page allocations | |
ownerId | the ownerId to set in the pageEntry for page allocations |
Definition at line 496 of file VersionedRandomAllocationSegment.cpp.
References ModifiedPageEntry::ALLOCATED, VersionedPageEntry::allocationCsn, ModifiedPageEntry::DEALLOCATED, SegNodeLock< Node >::getNodeForWrite(), VersionedExtentAllocationNode::getPageEntry(), Segment::getTracingSegment(), isDeallocatedPageOwnerId(), SegPageLock::lockExclusive(), makeDeallocatedPageOwnerId(), PageEntry::ownerId, Segment::pCache, pTempSegment, and UNCOMMITTED_PAGE_OWNER_ID.
Referenced by updatePageEntry().
00504 { 00505 SegmentAccessor tempAccessor(pTempSegment, pCache); 00506 VersionedExtentAllocLock tempAllocLock(tempAccessor); 00507 tempAllocLock.lockExclusive(tempPageId); 00508 VersionedExtentAllocationNode &tempExtentNode = 00509 tempAllocLock.getNodeForWrite(); 00510 VersionedPageEntry &tempPageEntry = 00511 tempExtentNode.getPageEntry(iPageInExtent); 00512 00513 SegmentAccessor selfAccessor(getTracingSegment(), pCache); 00514 VersionedExtentAllocLock extentAllocLock(selfAccessor); 00515 extentAllocLock.lockExclusive(origPageId); 00516 VersionedExtentAllocationNode &extentNode = 00517 extentAllocLock.getNodeForWrite(); 00518 VersionedPageEntry &pageEntry = 00519 extentNode.getPageEntry(iPageInExtent); 00520 00521 // Update the temp page entry's csn and ownerId if this is a new page 00522 // allocation. We need to update the temp entry because we may still 00523 // need to use that temp page. 00524 if (lastModType == ModifiedPageEntry::ALLOCATED) { 00525 assert(tempPageEntry.ownerId == UNCOMMITTED_PAGE_OWNER_ID); 00526 tempPageEntry.allocationCsn = commitCsn; 00527 tempPageEntry.ownerId = ownerId; 00528 } else if (lastModType == ModifiedPageEntry::DEALLOCATED) { 00529 assert(isDeallocatedPageOwnerId(tempPageEntry.ownerId)); 00530 tempPageEntry.ownerId = makeDeallocatedPageOwnerId(commitCsn); 00531 } 00532 pageEntry = tempPageEntry; 00533 }
void VersionedRandomAllocationSegment::copyPageEntryToTemp | ( | PageId | origPageId, | |
PageId | tempPageId, | |||
BlockNum | iPageInExtent | |||
) | [private] |
Copies a page entry from the permanent segment to the temporary one.
origPageId | pageId of the extent page in the permanent segment | |
tempPageId | pageId of the extent page in the temporary segment | |
iPageInExtent | 0-based index of page in extent |
Definition at line 535 of file VersionedRandomAllocationSegment.cpp.
References SegNodeLock< Node >::getNodeForRead(), SegNodeLock< Node >::getNodeForWrite(), VersionedExtentAllocationNode::getPageEntry(), Segment::getTracingSegment(), SegPageLock::lockExclusive(), SegPageLock::lockShared(), Segment::pCache, and pTempSegment.
Referenced by deallocateSinglePage(), and updatePageEntry().
00539 { 00540 SegmentAccessor tempAccessor(pTempSegment, pCache); 00541 VersionedExtentAllocLock tempAllocLock(tempAccessor); 00542 tempAllocLock.lockExclusive(tempPageId); 00543 VersionedExtentAllocationNode &tempExtentNode = 00544 tempAllocLock.getNodeForWrite(); 00545 VersionedPageEntry &tempPageEntry = 00546 tempExtentNode.getPageEntry(iPageInExtent); 00547 00548 SegmentAccessor selfAccessor(getTracingSegment(), pCache); 00549 VersionedExtentAllocLock extentAllocLock(selfAccessor); 00550 extentAllocLock.lockShared(origPageId); 00551 VersionedExtentAllocationNode const &extentNode = 00552 extentAllocLock.getNodeForRead(); 00553 VersionedPageEntry const &pageEntry = 00554 extentNode.getPageEntry(iPageInExtent); 00555 00556 tempPageEntry = pageEntry; 00557 }
bool VersionedRandomAllocationSegment::validateFreePageCount | ( | PageId | pageId | ) | [private] |
Sanity checks the unallocated page count in a SegmentAllocationNode against the pages marked as unallocated in the corresponding VersionedExtentAllocationNode.
pageId | pageId corresponding to the allocation nodes to be verified |
Definition at line 670 of file VersionedRandomAllocationSegment.cpp.
References RandomAllocationSegmentBase::getExtentAllocPageId(), SegmentAllocationNode::getExtentEntry(), SegNodeLock< Node >::getNodeForRead(), VersionedExtentAllocationNode::getPageEntry(), RandomAllocationSegmentBase::getSegAllocPageId(), Segment::getTracingSegment(), SegPageLock::lockExclusive(), SegPageLock::lockShared(), RandomAllocationSegmentBase::nExtentsPerSegAlloc, RandomAllocationSegmentBase::nPagesPerExtent, SegmentAllocationNode::ExtentEntry::nUnallocatedPages, Segment::pCache, RandomAllocationSegmentBase::splitPageId(), and UNALLOCATED_PAGE_OWNER_ID.
00671 { 00672 ExtentNum extentNum; 00673 BlockNum iPageInExtent; 00674 uint iSegAlloc; 00675 splitPageId(pageId, iSegAlloc, extentNum, iPageInExtent); 00676 assert(iPageInExtent); 00677 00678 PageId segAllocPageId = getSegAllocPageId(iSegAlloc); 00679 SegmentAccessor selfAccessor(getTracingSegment(), pCache); 00680 SegAllocLock segAllocLock(selfAccessor); 00681 segAllocLock.lockShared(segAllocPageId); 00682 SegmentAllocationNode const &segAllocNode = segAllocLock.getNodeForRead(); 00683 00684 ExtentNum relativeExtentNum = extentNum % nExtentsPerSegAlloc; 00685 SegmentAllocationNode::ExtentEntry const &extentEntry = 00686 segAllocNode.getExtentEntry(relativeExtentNum); 00687 00688 VersionedExtentAllocLock extentAllocLock(selfAccessor); 00689 PageId extentPageId = getExtentAllocPageId(extentNum); 00690 extentAllocLock.lockExclusive(extentPageId); 00691 VersionedExtentAllocationNode const &extentNode = 00692 extentAllocLock.getNodeForRead(); 00693 uint freePageCount = 0; 00694 for (uint i = 0; i < nPagesPerExtent; i++) { 00695 VersionedPageEntry const &pageEntry = extentNode.getPageEntry(i); 00696 if (pageEntry.ownerId == UNALLOCATED_PAGE_OWNER_ID) { 00697 freePageCount++; 00698 } 00699 } 00700 00701 bool rc = (freePageCount == extentEntry.nUnallocatedPages); 00702 return rc; 00703 }
void VersionedRandomAllocationSegment::freeTempPage | ( | PageId | origAllocNodePageId, | |
PageId | tempAllocNodePageId | |||
) | [private] |
Frees a temporary page corresponding to an allocation node page, since all temporary updates to the page have either committed or rolled back.
This method assumes the caller has already acquired an exclusive mutex on allocationNodeMap.
origAllocNodePageId | pageId of the original allocation node corresponding to the one being freed | |
tempAllocNodePageId | pageId of the temporary allocation node page to be freed |
Definition at line 705 of file VersionedRandomAllocationSegment.cpp.
References allocationNodeMap, SXMutex::isLocked(), LOCKMODE_X, mapMutex, and pTempSegment.
Referenced by freeTempPages(), and updateAllocNodes().
00708 { 00709 assert(mapMutex.isLocked(LOCKMODE_X)); 00710 pTempSegment->deallocatePageRange(tempAllocNodePageId, tempAllocNodePageId); 00711 allocationNodeMap.erase(origAllocNodePageId); 00712 }
TxnId VersionedRandomAllocationSegment::getOldestTxnId | ( | PageId | pageId, | |
TxnId | oldestActiveTxnId, | |||
PageId & | anchorPageId, | |||
std::hash_set< PageId > & | deallocatedPageSet, | |||
bool & | deallocateChain | |||
) | [private] |
Determines the txnId corresponding to the oldest pageId in a page chain that can be deallocated, provided there are pages that can be deallocated.
If pages in the chain are marked deallocation-deferred and are no longer being referenced, then set the flag indicating that the entire page chain should be deallocated.
pageId | a pageId in a page chain corresponding to an old page | |
oldestActiveTxnId | the txnId of the current, oldest active txnId; used as the threshhold for determining which pages are old | |
[out] | anchorPageId | the pageId of the anchor in the page chain |
[in,out] | deallocatedPageSet | set of pages that have already been deallocated or need to be skipped because they can't be deallocated |
[out] | deallocateChain | set to true if the entire page chain needs to be deallocated because the pages are marked as deallocation- deferred and are no longer referenced |
Definition at line 849 of file VersionedRandomAllocationSegment.cpp.
References VersionedPageEntry::allocationCsn, getDeallocatedTxnId(), RandomAllocationSegmentBase::getExtentAllocPageId(), SegNodeLock< Node >::getNodeForRead(), VersionedExtentAllocationNode::getPageEntry(), Segment::getTracingSegment(), isDeallocatedPageOwnerId(), isPageIdAllocateCommitted(), SegPageLock::lockShared(), NULL_PAGE_ID, NULL_TXN_ID, PageEntry::ownerId, Segment::pCache, skipDeferredDeallocations(), RandomAllocationSegmentBase::splitPageId(), UNCOMMITTED_PAGE_OWNER_ID, and VersionedPageEntry::versionChainPageId.
Referenced by deallocateOldPages().
00855 { 00856 // Loop through the page chain, looking for the anchor page, and the 00857 // second, newest old page. The second, newest old page will be the newest 00858 // page that can be deallocated. Note that we can't deallocate the newest 00859 // old page because it's still being referenced by active txns. 00860 00861 PageId chainPageId = pageId; 00862 TxnId anchorCsn = NULL_TXN_ID; 00863 TxnId newestOldCsn = NULL_TXN_ID; 00864 TxnId nextNewestOldCsn = NULL_TXN_ID; 00865 anchorPageId = NULL_PAGE_ID; 00866 PageId newestOldPageId = NULL_PAGE_ID; 00867 PageId nextNewestOldPageId = NULL_PAGE_ID; 00868 00869 deallocateChain = false; 00870 do { 00871 if (deallocatedPageSet.find(chainPageId) != deallocatedPageSet.end()) { 00872 return NULL_TXN_ID; 00873 } 00874 assert(isPageIdAllocateCommitted(chainPageId)); 00875 00876 ExtentNum extentNum; 00877 BlockNum iPageInExtent; 00878 uint iSegAlloc; 00879 splitPageId(chainPageId, iSegAlloc, extentNum, iPageInExtent); 00880 assert(iPageInExtent); 00881 00882 SegmentAccessor selfAccessor(getTracingSegment(), pCache); 00883 PageId extentPageId = getExtentAllocPageId(extentNum); 00884 VersionedExtentAllocLock extentAllocLock(selfAccessor); 00885 extentAllocLock.lockShared(extentPageId); 00886 VersionedExtentAllocationNode const &extentNode = 00887 extentAllocLock.getNodeForRead(); 00888 VersionedPageEntry const &pageEntry = 00889 extentNode.getPageEntry(iPageInExtent); 00890 assert(pageEntry.ownerId != UNCOMMITTED_PAGE_OWNER_ID); 00891 00892 // If the page is marked as deallocation-deferred, need to deallocate 00893 // the entire page chain, if the oldest active txn is newer than the 00894 // txn that marked the page. Otherwise, wait until the active txns 00895 // referencing those pages have committed. 00896 if (isDeallocatedPageOwnerId(pageEntry.ownerId)) { 00897 if (getDeallocatedTxnId(pageEntry.ownerId) < oldestActiveTxnId) { 00898 deallocateChain = true; 00899 } else { 00900 skipDeferredDeallocations(pageId, deallocatedPageSet); 00901 } 00902 return NULL_TXN_ID; 00903 } 00904 00905 if (anchorCsn == NULL_TXN_ID || 00906 pageEntry.allocationCsn < anchorCsn) 00907 { 00908 anchorCsn = pageEntry.allocationCsn; 00909 anchorPageId = chainPageId; 00910 } 00911 if (pageEntry.allocationCsn < oldestActiveTxnId) { 00912 if (newestOldCsn == NULL_TXN_ID || 00913 pageEntry.allocationCsn > newestOldCsn) 00914 { 00915 if (newestOldCsn != NULL_TXN_ID) { 00916 nextNewestOldCsn = newestOldCsn; 00917 nextNewestOldPageId = newestOldPageId; 00918 } 00919 newestOldCsn = pageEntry.allocationCsn; 00920 newestOldPageId = chainPageId; 00921 } else { 00922 if (((nextNewestOldCsn == NULL_TXN_ID) || 00923 (pageEntry.allocationCsn > nextNewestOldCsn)) && 00924 (pageEntry.allocationCsn != newestOldCsn)) 00925 { 00926 // It's possible to have two page entries with the same csn 00927 // if a page is truncated and then versioned within the 00928 // same transaction. 00929 nextNewestOldCsn = pageEntry.allocationCsn; 00930 nextNewestOldPageId = chainPageId; 00931 } 00932 } 00933 } 00934 assert(pageEntry.versionChainPageId != NULL_PAGE_ID); 00935 chainPageId = pageEntry.versionChainPageId; 00936 } while (chainPageId != pageId); 00937 00938 // At least one page in the chain has to be old 00939 assert(newestOldPageId != NULL_PAGE_ID); 00940 assert(anchorPageId != NULL_PAGE_ID); 00941 assert(nextNewestOldCsn == NULL_TXN_ID || nextNewestOldCsn < newestOldCsn); 00942 00943 // If there is no next newest old page, then there's nothing to deallocate 00944 // in the page chain. Add the pages we know are old to the 00945 // deallocatedPageSet so we can directly skip over them if we encounter 00946 // them again. 00947 if (nextNewestOldPageId == anchorPageId || 00948 nextNewestOldPageId == NULL_PAGE_ID) 00949 { 00950 deallocatedPageSet.insert(anchorPageId); 00951 deallocatedPageSet.insert(pageId); 00952 deallocatedPageSet.insert(newestOldPageId); 00953 return NULL_TXN_ID; 00954 } 00955 00956 // Set the deallocationCsn so only the next newest old page and any 00957 // pages older than it will be deallocated 00958 TxnId deallocationCsn = nextNewestOldCsn + 1; 00959 assert(deallocationCsn < oldestActiveTxnId); 00960 00961 return deallocationCsn; 00962 }
void VersionedRandomAllocationSegment::deallocateEntirePageChain | ( | PageId | pageId, | |
TxnId | oldestActiveTxnId, | |||
std::hash_set< PageId > & | deallocatedPageSet | |||
) | [private] |
Deallocates an entire page chain.
All pages in the chain should be marked as deallocation-deferred, and there must not be any active txns older than the txn that marked the pages as deallocation-deferred.
pageId | a pageId in the page chain; not necessarily the anchor | |
oldestActiveTxnId | the txnId of the current, oldest active txnId | |
[in,out] | deallocatedPageSet | set of pageIds deallocated |
Definition at line 964 of file VersionedRandomAllocationSegment.cpp.
References VersionedPageEntry::allocationCsn, deallocateSinglePage(), getCommittedPageEntryCopy(), getDeallocatedTxnId(), isDeallocatedPageOwnerId(), PageEntry::ownerId, and VersionedPageEntry::versionChainPageId.
Referenced by deallocateOldPages().
00968 { 00969 PageId chainPageId = pageId; 00970 VersionedPageEntry pageEntry; 00971 do { 00972 getCommittedPageEntryCopy(chainPageId, pageEntry); 00973 00974 // All pages in the chain should be marked as deallocation-deferred 00975 // since we mark them atomically. They also must be old. 00976 assert(isDeallocatedPageOwnerId(pageEntry.ownerId)); 00977 assert(getDeallocatedTxnId(pageEntry.ownerId) < oldestActiveTxnId); 00978 assert(pageEntry.allocationCsn < oldestActiveTxnId); 00979 00980 deallocateSinglePage(chainPageId, deallocatedPageSet); 00981 chainPageId = pageEntry.versionChainPageId; 00982 } while (chainPageId != pageId); 00983 }
void VersionedRandomAllocationSegment::deallocateSinglePage | ( | PageId | pageId, | |
std::hash_set< PageId > & | deallocatedPageSet | |||
) | [private] |
Deallocates a single page and also discards it from the cache.
This method assumes that the caller has already acquired an exclusive mutex on allocationNodeMap.
pageId | pageId of the page to be deallocated | |
[in,out] | deallocatedPageSet | set of pageIds deallocated |
Definition at line 985 of file VersionedRandomAllocationSegment.cpp.
References allocationNodeMap, copyPageEntryToTemp(), RandomAllocationSegmentBase::deallocatePageRange(), RandomAllocationSegmentBase::getExtentAllocPageId(), SegmentAllocationNode::getExtentEntry(), SegNodeLock< Node >::getNodeForWrite(), RandomAllocationSegmentBase::getSegAllocPageId(), SXMutex::isLocked(), SegPageLock::lockExclusive(), LOCKMODE_X, mapMutex, RandomAllocationSegmentBase::nExtentsPerSegAlloc, SegmentAllocationNode::ExtentEntry::nUnallocatedPages, Segment::pCache, pTempSegment, and RandomAllocationSegmentBase::splitPageId().
Referenced by deallocateEntirePageChain(), and deallocatePageChain().
00988 { 00989 assert(mapMutex.isLocked(LOCKMODE_X)); 00990 00991 // We rely on superclass to discard page from cache as part of deallocation. 00992 RandomAllocationSegmentBase::deallocatePageRange(pageId, pageId); 00993 00994 ExtentNum extentNum; 00995 BlockNum iPageInExtent; 00996 uint iSegAlloc; 00997 splitPageId(pageId, iSegAlloc, extentNum, iPageInExtent); 00998 assert(iPageInExtent); 00999 01000 // Reflect the changes in the temporary page entry, if it exists 01001 PageId extentPageId = getExtentAllocPageId(extentNum); 01002 NodeMapConstIter iter = allocationNodeMap.find(extentPageId); 01003 if (iter != allocationNodeMap.end()) { 01004 copyPageEntryToTemp( 01005 extentPageId, 01006 iter->second->tempPageId, 01007 iPageInExtent); 01008 } 01009 01010 // Reflect the changes in the temporary extent entry, if it exists 01011 PageId segAllocPageId = getSegAllocPageId(iSegAlloc); 01012 iter = allocationNodeMap.find(segAllocPageId); 01013 if (iter != allocationNodeMap.end()) { 01014 PageId tempSegAllocNodePageId = iter->second->tempPageId; 01015 SegmentAccessor segAccessor(pTempSegment, pCache); 01016 SegAllocLock tempSegAllocLock(segAccessor); 01017 tempSegAllocLock.lockExclusive(tempSegAllocNodePageId); 01018 SegmentAllocationNode &tempSegAllocNode = 01019 tempSegAllocLock.getNodeForWrite(); 01020 ExtentNum relativeExtentNum = extentNum % nExtentsPerSegAlloc; 01021 SegmentAllocationNode::ExtentEntry &tempExtentEntry = 01022 tempSegAllocNode.getExtentEntry(relativeExtentNum); 01023 tempExtentEntry.nUnallocatedPages++; 01024 } 01025 01026 deallocatedPageSet.insert(pageId); 01027 }
void VersionedRandomAllocationSegment::deallocatePageChain | ( | PageId | anchorPageId, | |
TxnId | deallocationCsn, | |||
std::hash_set< PageId > & | deallocatedPageSet | |||
) | [private] |
Deallocates all old pages in a page chain.
anchorPageId | pageId of the anchor page in the page chain | |
deallocationCsn | the open, upper bound on the allocationCsn corresponding to pages that should be deallocated | |
[in,out] | deallocatedPageSet | set of pageIds corresponding to pages that have been deallocated |
Definition at line 1029 of file VersionedRandomAllocationSegment.cpp.
References VersionedPageEntry::allocationCsn, chainPageEntries(), deallocateSinglePage(), getCommittedPageEntryCopy(), isDeallocatedPageOwnerId(), NULL_PAGE_ID, PageEntry::ownerId, UNALLOCATED_PAGE_OWNER_ID, uncommittedDeallocation(), updateTempPageEntry(), and VersionedPageEntry::versionChainPageId.
Referenced by deallocateOldPages().
01033 { 01034 VersionedPageEntry prevPageEntry; 01035 getCommittedPageEntryCopy(anchorPageId, prevPageEntry); 01036 assert( 01037 prevPageEntry.ownerId != UNALLOCATED_PAGE_OWNER_ID && 01038 !isDeallocatedPageOwnerId(prevPageEntry.ownerId)); 01039 01040 // See if the page is in the process of being marked 01041 // deallocation-deferred. If it is, then don't deallocate any of the 01042 // pages in the page chain, even if they are old. We'll wait until 01043 // the deallocation-deferral is actually committed before deallocating 01044 // them. 01045 if (uncommittedDeallocation(anchorPageId, deallocatedPageSet)) { 01046 return; 01047 } 01048 01049 bool needsUpdate = false; 01050 PageId prevPageId = anchorPageId; 01051 PageId nextPageId = prevPageEntry.versionChainPageId; 01052 do { 01053 VersionedPageEntry pageEntry; 01054 getCommittedPageEntryCopy(nextPageId, pageEntry); 01055 01056 if (pageEntry.allocationCsn < deallocationCsn) { 01057 // Deallocate the page entry and chain the previous page 01058 // entry to the page chained from the deallocated entry. 01059 // All of this is being done in the permanent page entry. 01060 // The temporary entry will be updated below. 01061 deallocateSinglePage(nextPageId, deallocatedPageSet); 01062 nextPageId = pageEntry.versionChainPageId; 01063 chainPageEntries( 01064 prevPageId, 01065 nextPageId, 01066 NULL_PAGE_ID, 01067 true); 01068 prevPageEntry.versionChainPageId = nextPageId; 01069 needsUpdate = true; 01070 01071 } else { 01072 // Reflect the changes made in the previous page entry 01073 // in the temporary page entry, if it exists 01074 if (needsUpdate) { 01075 updateTempPageEntry(prevPageId, prevPageEntry); 01076 } 01077 needsUpdate = false; 01078 01079 // Move the info for the current page entry into the previous 01080 prevPageId = nextPageId; 01081 prevPageEntry = pageEntry; 01082 nextPageId = pageEntry.versionChainPageId; 01083 } 01084 } while (nextPageId != anchorPageId); 01085 01086 // Update the last previous entry if needed 01087 if (needsUpdate) { 01088 updateTempPageEntry(prevPageId, prevPageEntry); 01089 } 01090 }
bool VersionedRandomAllocationSegment::validatePageChain | ( | PageId | anchorPageId | ) | [private] |
Walks a page chain and ensures that all pages in the chain are allocated pages.
anchorPageId | the pageId of the anchor page in the chain |
Definition at line 1150 of file VersionedRandomAllocationSegment.cpp.
References getCommittedPageEntryCopy(), and VersionedPageEntry::versionChainPageId.
01151 { 01152 // TODO zfong 25-Oct-2007: Check that the page chain is not circular, 01153 // except for the expected reference back to the anchor page. 01154 01155 PageId chainPageId = anchorPageId; 01156 VersionedPageEntry pageEntry; 01157 do { 01158 getCommittedPageEntryCopy(chainPageId, pageEntry); 01159 chainPageId = pageEntry.versionChainPageId; 01160 } while (chainPageId != anchorPageId); 01161 01162 return true; 01163 }
bool VersionedRandomAllocationSegment::uncommittedDeallocation | ( | PageId | anchorPageId, | |
std::hash_set< PageId > & | deallocatedPageSet | |||
) | [private] |
Determines if a page chain is in the process of being marked deallocation-deferred and has not yet been committed.
This method assumes that the caller has already acquired an exclusive mutex on allocationNodeMap.
anchorPageId | pageId of the anchor page in a chain | |
[in,out] | deallocatedPageSet | set of pages that have been deallocated or need to be skipped |
Definition at line 1092 of file VersionedRandomAllocationSegment.cpp.
References allocationNodeMap, getDeallocatedTxnId(), RandomAllocationSegmentBase::getExtentAllocPageId(), SegNodeLock< Node >::getNodeForRead(), VersionedExtentAllocationNode::getPageEntry(), isDeallocatedPageOwnerId(), SXMutex::isLocked(), LOCKMODE_X, SegPageLock::lockShared(), mapMutex, PageEntry::ownerId, Segment::pCache, pTempSegment, skipDeferredDeallocations(), and RandomAllocationSegmentBase::splitPageId().
Referenced by deallocatePageChain().
01095 { 01096 ExtentNum extentNum; 01097 BlockNum iPageInExtent; 01098 uint iSegAlloc; 01099 splitPageId(anchorPageId, iSegAlloc, extentNum, iPageInExtent); 01100 assert(iPageInExtent); 01101 01102 // See if the page entry corresponding to the anchor is marked as 01103 // deallocation-deferred with a txnId of 0 in the temporary page entry. 01104 // If it is, then that means the txn doing the deallocation has not 01105 // committed yet. 01106 01107 assert(mapMutex.isLocked(LOCKMODE_X)); 01108 NodeMapConstIter iter = 01109 allocationNodeMap.find(getExtentAllocPageId(extentNum)); 01110 if (iter == allocationNodeMap.end()) { 01111 return false; 01112 } 01113 01114 PageId tempExtentPageId = iter->second->tempPageId; 01115 SegmentAccessor segAccessor(pTempSegment, pCache); 01116 VersionedExtentAllocLock tempExtAllocLock(segAccessor); 01117 tempExtAllocLock.lockShared(tempExtentPageId); 01118 VersionedExtentAllocationNode const &tempExtentNode = 01119 tempExtAllocLock.getNodeForRead(); 01120 VersionedPageEntry const &tempPageEntry = 01121 tempExtentNode.getPageEntry(iPageInExtent); 01122 if (!isDeallocatedPageOwnerId(tempPageEntry.ownerId)) { 01123 return false; 01124 } 01125 if (getDeallocatedTxnId(tempPageEntry.ownerId) != TxnId(0)) { 01126 return false; 01127 } 01128 01129 skipDeferredDeallocations(anchorPageId, deallocatedPageSet); 01130 return true; 01131 }
void VersionedRandomAllocationSegment::skipDeferredDeallocations | ( | PageId | pageId, | |
std::hash_set< PageId > & | deallocatedPageSet | |||
) | [private] |
Adds all pages in a page chain corresponding to deallocation-deferred pages to the set of pages that have been deallocated so we'll skip over them.
pageId | pageId of a page in the chain | |
[in,out] | deallocatedPageSet | set of pages that have been deallocated or need to be skipped |
Definition at line 1133 of file VersionedRandomAllocationSegment.cpp.
References getCommittedPageEntryCopy(), isDeallocatedPageOwnerId(), PageEntry::ownerId, and VersionedPageEntry::versionChainPageId.
Referenced by getOldestTxnId(), and uncommittedDeallocation().
01136 { 01137 // Add all the pages in the chain to the deallocated page set so we'll 01138 // skip over them. All the other pages in the chain should also be 01139 // marked as deallocation-deferred. 01140 PageId chainPageId = pageId; 01141 VersionedPageEntry pageEntry; 01142 do { 01143 deallocatedPageSet.insert(chainPageId); 01144 getCommittedPageEntryCopy(chainPageId, pageEntry); 01145 assert(isDeallocatedPageOwnerId(pageEntry.ownerId)); 01146 chainPageId = pageEntry.versionChainPageId; 01147 } while (chainPageId != pageId); 01148 }
void VersionedRandomAllocationSegment::updateTempPageEntry | ( | PageId | pageId, | |
VersionedPageEntry const & | pageEntry | |||
) | [private] |
Updates a page entry in the temporary segment, if it exists.
This method assumes that the caller has already acquired an exclusive mutex on allocationNodeMap.
pageId | of the page entry that needs to be updated | |
[in] | pageEntry | source page entry |
Definition at line 1165 of file VersionedRandomAllocationSegment.cpp.
References allocationNodeMap, RandomAllocationSegmentBase::getExtentAllocPageId(), SegNodeLock< Node >::getNodeForWrite(), VersionedExtentAllocationNode::getPageEntry(), SXMutex::isLocked(), SegPageLock::lockExclusive(), LOCKMODE_X, mapMutex, Segment::pCache, pTempSegment, and RandomAllocationSegmentBase::splitPageId().
Referenced by deallocatePageChain().
01168 { 01169 ExtentNum extentNum; 01170 BlockNum iPageInExtent; 01171 uint iSegAlloc; 01172 splitPageId(pageId, iSegAlloc, extentNum, iPageInExtent); 01173 assert(iPageInExtent); 01174 01175 assert(mapMutex.isLocked(LOCKMODE_X)); 01176 NodeMapConstIter iter = 01177 allocationNodeMap.find(getExtentAllocPageId(extentNum)); 01178 if (iter != allocationNodeMap.end()) { 01179 PageId tempExtentPageId = iter->second->tempPageId; 01180 SegmentAccessor segAccessor(pTempSegment, pCache); 01181 VersionedExtentAllocLock tempExtAllocLock(segAccessor); 01182 tempExtAllocLock.lockExclusive(tempExtentPageId); 01183 VersionedExtentAllocationNode &tempExtentNode = 01184 tempExtAllocLock.getNodeForWrite(); 01185 VersionedPageEntry &tempPageEntry = 01186 tempExtentNode.getPageEntry(iPageInExtent); 01187 tempPageEntry = pageEntry; 01188 } 01189 }
void VersionedRandomAllocationSegment::getCommittedPageEntryCopy | ( | PageId | pageId, | |
VersionedPageEntry & | pageEntryCopy | |||
) | [private] |
Retrieves the committed copy of a page entry for a specified page.
pageId | pageId of the page whose page entry data we are retrieving | |
[out] | pageEntryCopy | copy of page entry retrieved |
Definition at line 310 of file VersionedRandomAllocationSegment.cpp.
References getPageEntryCopy().
Referenced by deallocateEntirePageChain(), deallocatePageChain(), skipDeferredDeallocations(), and validatePageChain().
00313 { 00314 getPageEntryCopy(pageId, pageEntryCopy, true, true); 00315 }
bool VersionedRandomAllocationSegment::isPageIdAllocateCommitted | ( | PageId | pageId | ) | [private] |
Determines if a page corresponds to a committed allocation.
pageId | pageId of the page being checked |
Definition at line 252 of file VersionedRandomAllocationSegment.cpp.
References RandomAllocationSegmentBase::testPageId().
Referenced by deallocateOldPages(), and getOldestTxnId().
00253 { 00254 return testPageId(pageId, true, true); 00255 }
void VersionedRandomAllocationSegment::chainPageEntries | ( | PageId | pageId, | |
PageId | versionChainId, | |||
PageId | successorId, | |||
bool | thisSegment | |||
) | [private] |
Chains one page to another, updating either the corresponding permanent page entry or the temporary one.
Also may set the successorId of the first page.
pageId | the pageId of the page that will be chained to the page corresponding to the second parameter | |
versionChainId | the pageId of the page to be chained from the first parameter | |
successorId | if not set to NULL_PAGE_ID, the successorId of the pageEntry corresponding to the first parameter is set | |
thisSegment | if true, make updates in the permanent page entry rather than the temporary one |
Definition at line 352 of file VersionedRandomAllocationSegment.cpp.
References getExtAllocPageIdForWrite(), RandomAllocationSegmentBase::getExtentAllocPageId(), SegNodeLock< Node >::getNodeForWrite(), VersionedExtentAllocationNode::getPageEntry(), Segment::getTracingSegment(), isPageIdAllocated(), SegPageLock::lockExclusive(), NULL_PAGE_ID, Segment::pCache, pTempSegment, RandomAllocationSegmentBase::splitPageId(), PageEntry::successorId, and VersionedPageEntry::versionChainPageId.
Referenced by chainPageEntries(), SnapshotRandomAllocationSegment::chainPageEntries(), and deallocatePageChain().
00357 { 00358 assert(isPageIdAllocated(pageId)); 00359 00360 ExtentNum extentNum; 00361 BlockNum iPageInExtent; 00362 uint iSegAlloc; 00363 splitPageId(pageId, iSegAlloc, extentNum, iPageInExtent); 00364 assert(iPageInExtent); 00365 00366 // Update the pageEntry either in the permanent or temp segment 00367 // depending on the "thisSegment" parameter passed in 00368 SharedSegment allocNodeSegment = 00369 (thisSegment) ? getTracingSegment() : pTempSegment; 00370 SegmentAccessor segAccessor(allocNodeSegment, pCache); 00371 VersionedExtentAllocLock extentAllocLock(segAccessor); 00372 PageId extentPageId = 00373 (thisSegment) ? 00374 getExtentAllocPageId(extentNum) : 00375 getExtAllocPageIdForWrite(extentNum); 00376 00377 extentAllocLock.lockExclusive(extentPageId); 00378 VersionedExtentAllocationNode &extentNode = 00379 extentAllocLock.getNodeForWrite(); 00380 VersionedPageEntry &pageEntry = 00381 extentNode.getPageEntry(iPageInExtent); 00382 if (successorId != NULL_PAGE_ID) { 00383 pageEntry.successorId = successorId; 00384 } 00385 assert(versionChainId != NULL_PAGE_ID); 00386 pageEntry.versionChainPageId = versionChainId; 00387 }
void VersionedRandomAllocationSegment::locateDataPages | ( | SharedSegPageBackupRestoreDevice | pBackupDevice, | |
TxnId | lowerBoundCsn, | |||
TxnId | upperBoundCsn, | |||
bool | isBackup, | |||
bool volatile const & | abortFlag | |||
) | [private] |
Definition at line 1298 of file VersionedRandomAllocationSegment.cpp.
References VersionedPageEntry::allocationCsn, checkAbort(), RandomAllocationSegmentBase::getExtentAllocPageId(), SegmentAllocationNode::getExtentEntry(), Segment::getFullPageSize(), Segment::getLinearPageId(), SegNodeLock< Node >::getNodeForRead(), SegPageLock::getPage(), VersionedExtentAllocationNode::getPageEntry(), CachePage::getReadableData(), RandomAllocationSegmentBase::getSegAllocPageId(), Segment::getTracingSegment(), SegPageLock::lockShared(), RandomAllocationSegmentBase::makePageNum(), SegmentAllocationNode::nExtents, RandomAllocationSegmentBase::nExtentsPerSegAlloc, SegmentAllocationNode::nextSegAllocPageId, RandomAllocationSegmentBase::nPagesPerExtent, NULL_PAGE_ID, NULL_TXN_ID, SegmentAllocationNode::ExtentEntry::nUnallocatedPages, PageEntry::ownerId, Segment::pCache, RandomAllocationSegmentBase::translatePageId(), UNALLOCATED_PAGE_OWNER_ID, and SegPageLock::unlock().
Referenced by backupDataPages(), and restoreFromBackup().
01304 { 01305 assert(upperBoundCsn != NULL_TXN_ID); 01306 SegmentAccessor selfAccessor(getTracingSegment(), pCache); 01307 SegAllocLock segAllocLock(selfAccessor); 01308 uint iSegAlloc = 0; 01309 ExtentNum extentNum = 0; 01310 PBuffer segNodeBuffer = NULL; 01311 PBuffer extentNodeBuffer = NULL; 01312 if (isBackup) { 01313 segNodeBuffer = pBackupDevice->getReservedBufferPage(); 01314 extentNodeBuffer = pBackupDevice->getReservedBufferPage(); 01315 } 01316 01317 while (true) { 01318 PageId segAllocPageId = getSegAllocPageId(iSegAlloc); 01319 segAllocLock.lockShared(segAllocPageId); 01320 // In the case of a backup, make a copy of the allocation nodes so 01321 // we don't pin them while we're doing I/O on the data pages mapped 01322 // by the extent entries in those nodes. Keeping the nodes pinned 01323 // prevents new pages from being allocated from those nodes. 01324 if (isBackup) { 01325 memcpy( 01326 segNodeBuffer, 01327 segAllocLock.getPage().getReadableData(), 01328 getFullPageSize()); 01329 segAllocLock.unlock(); 01330 } 01331 SegmentAllocationNode const &segAllocNode = 01332 (isBackup) ? 01333 *reinterpret_cast<SegmentAllocationNode const *> 01334 (segNodeBuffer) : 01335 segAllocLock.getNodeForRead(); 01336 ExtentNum relativeExtentNum = extentNum % nExtentsPerSegAlloc; 01337 01338 for (uint i = relativeExtentNum; i < segAllocNode.nExtents; 01339 i++, extentNum++) 01340 { 01341 checkAbort(abortFlag); 01342 01343 SegmentAllocationNode::ExtentEntry const &extentEntry = 01344 segAllocNode.getExtentEntry(i); 01345 if (extentEntry.nUnallocatedPages == nPagesPerExtent - 1) { 01346 continue; 01347 } 01348 01349 VersionedExtentAllocLock extentAllocLock(selfAccessor); 01350 extentAllocLock.lockShared(getExtentAllocPageId(extentNum)); 01351 if (isBackup) { 01352 memcpy( 01353 extentNodeBuffer, 01354 extentAllocLock.getPage().getReadableData(), 01355 getFullPageSize()); 01356 extentAllocLock.unlock(); 01357 } 01358 VersionedExtentAllocationNode const &extentNode = 01359 (isBackup) ? 01360 *reinterpret_cast<VersionedExtentAllocationNode const *> 01361 (extentNodeBuffer) : 01362 extentAllocLock.getNodeForRead(); 01363 01364 // Start at pageEntry 1 to skip past the extent header page 01365 for (uint j = 1; j < nPagesPerExtent; j++) { 01366 checkAbort(abortFlag); 01367 VersionedPageEntry const &pageEntry = 01368 extentNode.getPageEntry(j); 01369 // Ignore pages outside the csn boundaries 01370 if (pageEntry.ownerId == UNALLOCATED_PAGE_OWNER_ID || 01371 (lowerBoundCsn != NULL_TXN_ID && 01372 pageEntry.allocationCsn <= lowerBoundCsn) || 01373 (pageEntry.allocationCsn > upperBoundCsn)) 01374 { 01375 continue; 01376 } 01377 01378 // Map the pageEntry to its pageId, and then either back up 01379 // or restore it. 01380 PageId pageId = getLinearPageId(makePageNum(extentNum, j)); 01381 BlockId blockId = translatePageId(pageId); 01382 if (isBackup) { 01383 pBackupDevice->backupPage(blockId); 01384 } else { 01385 pBackupDevice->restorePage(blockId); 01386 } 01387 } 01388 } 01389 ++iSegAlloc; 01390 if (segAllocNode.nextSegAllocPageId == NULL_PAGE_ID) { 01391 break; 01392 } 01393 } 01394 01395 // Wait for all pending writes to complete 01396 pBackupDevice->waitForPendingWrites(); 01397 }
void VersionedRandomAllocationSegment::checkAbort | ( | bool volatile const & | abortFlag | ) | [private] |
Determines whether the abort flag is set.
If it is, throws an exception.
[in] | abortFlag | reference to the abort flag |
Definition at line 1473 of file VersionedRandomAllocationSegment.cpp.
Referenced by backupAllocationNodes(), locateDataPages(), and restoreFromBackup().
01475 { 01476 if (abortFlag) { 01477 throw AbortExcn(); 01478 } 01479 }
PageOwnerId VersionedRandomAllocationSegment::makeDeallocatedPageOwnerId | ( | TxnId | txnId | ) | [inline, private] |
Constructs a pageOwnerId corresponding to a deallocation-deferred page.
txnId | the id of the txn that deallocated the page |
Definition at line 136 of file VersionedRandomAllocationSegmentImpl.h.
References DEALLOCATED_PAGE_OWNER_ID_MASK, and opaqueToInt().
Referenced by copyPageEntryFromTemp(), and deferDeallocation().
00138 { 00139 assert(VALID_PAGE_OWNER_ID(txnId)); 00140 return PageOwnerId(DEALLOCATED_PAGE_OWNER_ID_MASK | opaqueToInt(txnId)); 00141 }
bool VersionedRandomAllocationSegment::isDeallocatedPageOwnerId | ( | PageOwnerId | pageOwnerId | ) | [inline, private] |
Determines whether a pageOwnerId corresponds to a deallocation-deferred page.
pageOwnerId | the pageOwnerId under question |
Definition at line 143 of file VersionedRandomAllocationSegmentImpl.h.
References ANON_PAGE_OWNER_ID, DEALLOCATED_PAGE_OWNER_ID_MASK, and opaqueToInt().
Referenced by copyPageEntryFromTemp(), deallocateEntirePageChain(), deallocatePageChain(), deferDeallocation(), getDeallocatedTxnId(), getOldestTxnId(), getOldPageIds(), skipDeferredDeallocations(), and uncommittedDeallocation().
00145 { 00146 return 00147 (pageOwnerId != ANON_PAGE_OWNER_ID && 00148 (opaqueToInt(pageOwnerId) & DEALLOCATED_PAGE_OWNER_ID_MASK)); 00149 }
TxnId VersionedRandomAllocationSegment::getDeallocatedTxnId | ( | PageOwnerId | pageOwnerId | ) | [inline, private] |
Extracts the id corresponding to the txn that deallocated a page from the page's pageOwnerId.
pageOwnerId | the pageOwnerId of the deallocated page |
Definition at line 151 of file VersionedRandomAllocationSegmentImpl.h.
References DEALLOCATED_PAGE_OWNER_ID_MASK, isDeallocatedPageOwnerId(), and opaqueToInt().
Referenced by deallocateEntirePageChain(), getOldestTxnId(), getOldPageIds(), and uncommittedDeallocation().
00153 { 00154 assert(isDeallocatedPageOwnerId(pageOwnerId)); 00155 return TxnId(opaqueToInt(pageOwnerId) & ~DEALLOCATED_PAGE_OWNER_ID_MASK); 00156 }
bool VersionedRandomAllocationSegment::isPageIdValid | ( | PageId | pageId | ) | [private, virtual] |
Tests whether the given PageId has valid contents (either an allocated data page or an allocation map page).
pageId | the PageId to test |
Reimplemented from RandomAllocationSegmentBase.
Definition at line 257 of file VersionedRandomAllocationSegment.cpp.
References RandomAllocationSegmentBase::testPageId().
00258 { 00259 return testPageId(pageId, false, false); 00260 }
PageId VersionedRandomAllocationSegment::getSegAllocPageIdForWrite | ( | PageId | origSegAllocPageId | ) | [private, virtual] |
Retrieves the pageId of the SegmentAllocationNode that should be updated when updates are made to that node.
origSegAllocPageId | original SegmentAllocationNode pageId |
Implements RandomAllocationSegmentBase.
Definition at line 73 of file VersionedRandomAllocationSegment.cpp.
void VersionedRandomAllocationSegment::undoSegAllocPageWrite | ( | PageId | segAllocPageId | ) | [private, virtual] |
Indicates that no new pages were allocated from extents within a SegmentAllocationNode.
segAllocPageId | SegmentAllocationNode pageId |
Implements RandomAllocationSegmentBase.
Definition at line 79 of file VersionedRandomAllocationSegment.cpp.
References allocationNodeMap, and mapMutex.
00081 { 00082 SXMutexExclusiveGuard mapGuard(mapMutex); 00083 00084 NodeMapConstIter iter = allocationNodeMap.find(segAllocPageId); 00085 assert(iter != allocationNodeMap.end()); 00086 SharedModifiedAllocationNode pModAllocNode = iter->second; 00087 pModAllocNode->updateCount--; 00088 }
PageId VersionedRandomAllocationSegment::getExtAllocPageIdForWrite | ( | ExtentNum | extentNum | ) | [private, virtual] |
Retrieves the pageId of the extent allocation node that should be updated when updates are made to that node.
extentNum | absolute 0-based extent number |
Implements RandomAllocationSegmentBase.
Definition at line 262 of file VersionedRandomAllocationSegment.cpp.
References RandomAllocationSegmentBase::getExtentAllocPageId().
Referenced by chainPageEntries(), deferDeallocation(), and initPageEntry().
00264 { 00265 return 00266 getTempAllocNodePage<VersionedExtentAllocLock>( 00267 getExtentAllocPageId(extentNum), 00268 false); 00269 }
PageId VersionedRandomAllocationSegment::allocateFromExtent | ( | ExtentNum | extentNum, | |
PageOwnerId | ownerId | |||
) | [private, virtual] |
Allocates a new page from an extent known to have space.
extentNum | absolute 0-based extent number from which to allocate | |
ownerId | PageOwnerId of owning object |
Implements RandomAllocationSegmentBase.
Definition at line 145 of file VersionedRandomAllocationSegment.cpp.
References RandomAllocationSegmentBase::allocateFromExtentTemplate(), and pTempSegment.
00148 { 00149 return 00150 allocateFromExtentTemplate< 00151 VersionedExtentAllocationNode, 00152 VersionedExtentAllocLock, 00153 VersionedPageEntry>( 00154 extentNum, 00155 ownerId, 00156 pTempSegment); 00157 }
void VersionedRandomAllocationSegment::formatPageExtents | ( | SegmentAllocationNode & | segAllocNode, | |
ExtentNum & | extentNum | |||
) | [private, virtual] |
Formats each of the extents within a segment allocation node.
[in] | segAllocNode | locked segment allocation node |
[in,out] | extentNum | on input, the initial absolute 0-based extent number that needs to be formatted; on output, the last extent number formatted + 1 |
Implements RandomAllocationSegmentBase.
Definition at line 56 of file VersionedRandomAllocationSegment.cpp.
References RandomAllocationSegmentBase::formatPageExtentsTemplate().
00059 { 00060 formatPageExtentsTemplate< 00061 VersionedExtentAllocationNode, 00062 VersionedExtentAllocLock, 00063 VersionedPageEntry>( 00064 segAllocNode, 00065 extentNum); 00066 }
PageId VersionedRandomAllocationSegment::allocateFromNewExtent | ( | ExtentNum | extentNum, | |
PageOwnerId | ownerId | |||
) | [private, virtual] |
Allocates a page from a new extent allocation node.
extentNum | absolute extent number from which to allocate | |
ownerId | PageOwnerId of owning object |
Implements RandomAllocationSegmentBase.
Definition at line 131 of file VersionedRandomAllocationSegment.cpp.
References RandomAllocationSegmentBase::allocateFromNewExtentTemplate(), and pTempSegment.
00134 { 00135 return 00136 allocateFromNewExtentTemplate< 00137 VersionedExtentAllocationNode, 00138 VersionedExtentAllocLock, 00139 VersionedPageEntry>( 00140 extentNum, 00141 ownerId, 00142 pTempSegment); 00143 }
void VersionedRandomAllocationSegment::freePageEntry | ( | ExtentNum | extentNum, | |
BlockNum | iPageInExtent | |||
) | [private, virtual] |
Marks the page entry corresponding to a deallocated page as unallocated.
extentNum | absolute 0-based extent number | |
iPageInExtent | 0-based index of page in extent |
Implements RandomAllocationSegmentBase.
Definition at line 205 of file VersionedRandomAllocationSegment.cpp.
References RandomAllocationSegmentBase::freePageEntryTemplate().
00208 { 00209 freePageEntryTemplate< 00210 VersionedExtentAllocationNode, 00211 VersionedExtentAllocLock, 00212 VersionedPageEntry>( 00213 extentNum, 00214 iPageInExtent); 00215 }
void VersionedRandomAllocationSegment::markPageEntryUnused | ( | PageEntry & | pageEntry | ) | [private, virtual] |
Marks a page entry as unused.
[in,out] | pageEntry | entry to be marked |
Reimplemented from RandomAllocationSegmentBase.
Definition at line 217 of file VersionedRandomAllocationSegment.cpp.
References VersionedPageEntry::allocationCsn, RandomAllocationSegmentBase::markPageEntryUnused(), NULL_PAGE_ID, NULL_TXN_ID, and VersionedPageEntry::versionChainPageId.
00219 { 00220 RandomAllocationSegmentBase::markPageEntryUnused(pageEntry); 00221 00222 VersionedPageEntry *pVersionedPageEntry = 00223 reinterpret_cast<VersionedPageEntry *>(&pageEntry); 00224 pVersionedPageEntry->versionChainPageId = NULL_PAGE_ID; 00225 pVersionedPageEntry->allocationCsn = NULL_TXN_ID; 00226 }
PageOwnerId VersionedRandomAllocationSegment::getPageOwnerId | ( | PageId | pageId, | |
bool | thisSegment | |||
) | [private, virtual] |
Retrieves the ownerId corresponding to a page entry.
pageId | PageId of the page whose owner we are retrieving | |
thisSegment | if true, retrieve page entry from this segment; otherwise, retrieve it from an alternative segment |
Implements RandomAllocationSegmentBase.
Definition at line 271 of file VersionedRandomAllocationSegment.cpp.
PageId VersionedRandomAllocationSegment::getSegAllocPageIdForRead | ( | PageId | origSegAllocPageId, | |
SharedSegment & | allocNodeSegment | |||
) | [private, virtual] |
Retrieves the actual pageId corresponding to the SegmentAllocationNode that should be accessed when reading from the node.
origSegAllocPageId | original SegmentAllocationNode pageId | |
[out] | allocNodeSegment | segment from which the allocation node to be read originates |
Implements RandomAllocationSegmentBase.
Definition at line 90 of file VersionedRandomAllocationSegment.cpp.
References findAllocPageIdForRead().
00093 { 00094 return findAllocPageIdForRead(origSegAllocPageId, allocNodeSegment); 00095 }
PageId VersionedRandomAllocationSegment::getExtAllocPageIdForRead | ( | ExtentNum | extentNum, | |
SharedSegment & | allocNodeSegment | |||
) | [private, virtual] |
Retrieves the actual pageId corresponding to the extent allocation node that should be accessed when reading from the node.
extentNum | absolute 0-based extent number | |
[out] | allocNodeSegment | segment from which the allocation node to be read originates |
Implements RandomAllocationSegmentBase.
Definition at line 97 of file VersionedRandomAllocationSegment.cpp.
References findAllocPageIdForRead(), and RandomAllocationSegmentBase::getExtentAllocPageId().
00100 { 00101 return 00102 findAllocPageIdForRead( 00103 getExtentAllocPageId(extentNum), 00104 allocNodeSegment); 00105 }
void VersionedRandomAllocationSegment::getPageEntryCopy | ( | PageId | pageId, | |
PageEntry & | pageEntryCopy, | |||
bool | isAllocated, | |||
bool | thisSegment | |||
) | [private, virtual] |
Retrieves a copy of the page entry for a specified page.
pageId | pageId of the page whose page entry data we are retrieving | |
[out] | pageEntryCopy | copy of page entry retrieved |
isAllocated | if true, assert that the page is allocated | |
thisSegment | if true, retrieve page entry from this segment; otherwise, retrieve it from an alternative segment |
Implements RandomAllocationSegmentBase.
Definition at line 278 of file VersionedRandomAllocationSegment.cpp.
References RandomAllocationSegmentBase::getPageEntryCopyTemplate(), and mapMutex.
Referenced by getCommittedPageEntryCopy(), and getLatestPageEntryCopy().
00283 { 00284 // We need to get a copy of the page entry rather than a reference 00285 // because the page entry may originate from a temporary page, which 00286 // can be freed by another thread. By holding the mutex on the 00287 // allocationNodeMap while we're retrieving the copy, we're ensured that 00288 // the page cannot be freed until we exit this method. 00289 SXMutexSharedGuard mapGuard(mapMutex); 00290 00291 VersionedPageEntry *pVersionedPageEntry = 00292 static_cast<VersionedPageEntry *>(&pageEntryCopy); 00293 getPageEntryCopyTemplate< 00294 VersionedExtentAllocationNode, 00295 VersionedExtentAllocLock, 00296 VersionedPageEntry>( 00297 pageId, 00298 *pVersionedPageEntry, 00299 isAllocated, 00300 thisSegment); 00301 }
void VersionedRandomAllocationSegment::getLatestPageEntryCopy | ( | PageId | pageId, | |
VersionedPageEntry & | pageEntryCopy | |||
) |
Retrieves the latest copy of a page entry for a specified page, which may correspond to an uncommitted, modified page entry.
pageId | pageId of the page whose page entry data we are retrieving | |
[out] | pageEntryCopy | copy of page entry retrieved |
Definition at line 303 of file VersionedRandomAllocationSegment.cpp.
References getPageEntryCopy().
Referenced by SnapshotRandomAllocationSegment::deallocatePageRange(), SnapshotRandomAllocationSegment::getAnchorPageId(), getPageSuccessor(), SnapshotRandomAllocationSegment::getSnapshotId(), SnapshotRandomAllocationSegment::updatePage(), and SnapshotRandomAllocationSegment::versionPage().
00306 { 00307 getPageEntryCopy(pageId, pageEntryCopy, true, false); 00308 }
void VersionedRandomAllocationSegment::initPageEntry | ( | PageId | pageId, | |
PageId | versionChainId, | |||
TxnId | allocationCsn | |||
) |
Initializes the versioning fields in a pageEntry for a specified page.
pageId | pageId of the page whose PageEntry we are setting | |
versionChainId | version chain pageId to be set | |
allocationCsn | commit sequence number to be set |
Definition at line 317 of file VersionedRandomAllocationSegment.cpp.
References VersionedPageEntry::allocationCsn, getExtAllocPageIdForWrite(), SegNodeLock< Node >::getNodeForWrite(), VersionedExtentAllocationNode::getPageEntry(), isPageIdAllocated(), SegPageLock::lockExclusive(), NULL_TXN_ID, PageEntry::ownerId, Segment::pCache, pTempSegment, RandomAllocationSegmentBase::splitPageId(), UNALLOCATED_PAGE_OWNER_ID, and VersionedPageEntry::versionChainPageId.
Referenced by SnapshotRandomAllocationSegment::allocatePageId().
00321 { 00322 assert(isPageIdAllocated(pageId)); 00323 00324 ExtentNum extentNum; 00325 BlockNum iPageInExtent; 00326 uint iSegAlloc; 00327 splitPageId(pageId, iSegAlloc, extentNum, iPageInExtent); 00328 assert(iPageInExtent); 00329 00330 SegmentAccessor segAccessor(pTempSegment, pCache); 00331 VersionedExtentAllocLock extentAllocLock(segAccessor); 00332 extentAllocLock.lockExclusive(getExtAllocPageIdForWrite(extentNum)); 00333 VersionedExtentAllocationNode &extentNode = 00334 extentAllocLock.getNodeForWrite(); 00335 VersionedPageEntry &pageEntry = 00336 extentNode.getPageEntry(iPageInExtent); 00337 assert(pageEntry.ownerId != UNALLOCATED_PAGE_OWNER_ID); 00338 pageEntry.versionChainPageId = versionChainId; 00339 if (allocationCsn != NULL_TXN_ID) { 00340 pageEntry.allocationCsn = allocationCsn; 00341 } 00342 }
void VersionedRandomAllocationSegment::chainPageEntries | ( | PageId | pageId, | |
PageId | versionChainId, | |||
PageId | successorId | |||
) |
Chains one page to another, updating the corresponding page entry in the temp segment page.
Also may set the successorId of the first page.
pageId | the pageId of the page that will be chained to the page corresponding to the second parameter | |
versionChainId | the pageId of the page to be chained from the first parameter | |
successorId | if not set to NULL_PAGE_ID, the successorId of the pageEntry corresponding to the first parameter is set |
Definition at line 344 of file VersionedRandomAllocationSegment.cpp.
References chainPageEntries().
00348 { 00349 chainPageEntries(pageId, versionChainId, successorId, false); 00350 }
void VersionedRandomAllocationSegment::updateAllocNodes | ( | ModifiedPageEntryMap const & | modifiedPageEntryMap, | |
TxnId | commitCsn, | |||
bool | commit, | |||
SharedSegment | pOrigSegment | |||
) |
Updates the permanent allocation nodes to reflect changes currently in the temporary segment, or vice versa if the updates correspond to a rollback.
modifiedPageEntryMap | map containing information on page entries that have been modified | |
commitCsn | sequence number to write into the pageEntry on a commit if the pageEntry corresponds to a page allocation; otherwise, set to NULL_TXN_ID | |
commit | true if the updates correspond to a commit | |
pOrigSegment | the originating segment that modified the allocation nodes that need to be updated |
Definition at line 389 of file VersionedRandomAllocationSegment.cpp.
References allocateAllocNodes(), ModifiedPageEntry::ALLOCATED, allocationNodeMap, ModifiedPageEntry::DEALLOCATED, freeTempPage(), isPageIdAllocated(), mapMutex, NULL_PAGE_ID, RandomAllocationSegmentBase::splitPageId(), updateExtentEntry(), and updatePageEntry().
Referenced by SnapshotRandomAllocationSegment::commitChanges(), and SnapshotRandomAllocationSegment::rollbackChanges().
00394 { 00395 SXMutexExclusiveGuard mapGuard(mapMutex); 00396 00397 for (ModifiedPageEntryMapIter iter = modifiedPageEntryMap.begin(); 00398 iter != modifiedPageEntryMap.end(); 00399 iter++) 00400 { 00401 PageId pageId = iter->first; 00402 SharedModifiedPageEntry pModEntry = iter->second; 00403 00404 assert(isPageIdAllocated(pageId)); 00405 00406 ExtentNum extentNum; 00407 BlockNum iPageInExtent; 00408 uint iSegAlloc; 00409 splitPageId(pageId, iSegAlloc, extentNum, iPageInExtent); 00410 assert(iPageInExtent); 00411 00412 // First make sure the page/extent entry we're going to be updating 00413 // has been allocated 00414 allocateAllocNodes(iSegAlloc, NULL_PAGE_ID, extentNum); 00415 00416 // No need to order updates to the extent and page entries because no 00417 // other thread should be modifying the permanent allocation node 00418 // pages at the same time. 00419 if ((pModEntry->lastModType == ModifiedPageEntry::ALLOCATED) || 00420 (pModEntry->lastModType == ModifiedPageEntry::DEALLOCATED)) 00421 { 00422 updateExtentEntry( 00423 iSegAlloc, 00424 extentNum, 00425 pModEntry->allocationCount, 00426 commit); 00427 } 00428 updatePageEntry( 00429 pageId, 00430 extentNum, 00431 iPageInExtent, 00432 pModEntry, 00433 commitCsn, 00434 commit, 00435 pOrigSegment); 00436 } 00437 00438 // Deallocate any temp allocation node pages corresponding to extent 00439 // allocation nodes that no longer contain any uncommitted updates. 00440 // Segment allocation nodes are not deallocated because those nodes can 00441 // be accessed frequently, especially if all extents on the page are full. 00442 ModifiedAllocationNodeMap::iterator iter = allocationNodeMap.begin(); 00443 while (iter != allocationNodeMap.end()) { 00444 SharedModifiedAllocationNode pModNode = iter->second; 00445 if (pModNode->updateCount == 0 && !pModNode->isSegAllocNode) { 00446 PageId pageId = iter->first; 00447 iter++; 00448 freeTempPage(pageId, pModNode->tempPageId); 00449 } else { 00450 iter++; 00451 } 00452 } 00453 }
SXMutex & VersionedRandomAllocationSegment::getDeallocationMutex | ( | ) |
Definition at line 1208 of file VersionedRandomAllocationSegment.cpp.
References deallocationMutex.
Referenced by SnapshotRandomAllocationSegment::getAnchorPageId().
01209 { 01210 return deallocationMutex; 01211 }
bool VersionedRandomAllocationSegment::getOldPageIds | ( | uint & | iSegAlloc, | |
ExtentNum & | extentNum, | |||
TxnId | oldestActiveTxnId, | |||
uint | numPages, | |||
PageSet & | oldPageSet | |||
) |
Retrieves a batch of pageIds corresponding either to old snapshot pages that are no longer being referenced or pages marked for deallocation.
The number of pageIds returned must be at least some value as specified by an input parameter, unless there are no more pages left to deallocate. The old pages are located starting at a location specified by the index of a SegmentAllocationNode and the offset of an extent within that node. Upon exit, those parameters are replaced with the location where the search should be resumed the next time the method is called.
Once a batch of pages have been identified, deallocateOldPages() should then be called. After deallocating that set of pages, getOldPageIds() should be called again to identify the next set of old pages.
[in,out] | iSegAlloc | on input, 0-based index of starting SegmentAllocationNode; on exit, the index where the search should be resumed the next time this method is called |
[in,out] | extentNum | on input, the 0-based extent number of the extent from which to start the search for old pages; upon exit, the extent number where the search should be resumed the next time this method is called |
oldestActiveTxnId | the txnId of the current, oldest active txnId; used as the threshhold for determining which pages are old | |
numPages | lower bound on the number of pages to pass back, unless there are no more pages to deallocate | |
[out] | oldPageSet | set of old pageIds found |
Definition at line 714 of file VersionedRandomAllocationSegment.cpp.
References getDeallocatedTxnId(), RandomAllocationSegmentBase::getExtentAllocPageId(), SegmentAllocationNode::getExtentEntry(), Segment::getLinearPageId(), SegNodeLock< Node >::getNodeForRead(), VersionedExtentAllocationNode::getPageEntry(), RandomAllocationSegmentBase::getSegAllocPageId(), Segment::getTracingSegment(), isDeallocatedPageOwnerId(), SegPageLock::lockShared(), RandomAllocationSegmentBase::makePageNum(), SegmentAllocationNode::nExtents, RandomAllocationSegmentBase::nExtentsPerSegAlloc, SegmentAllocationNode::nextSegAllocPageId, RandomAllocationSegmentBase::nPagesPerExtent, NULL_PAGE_ID, SegmentAllocationNode::ExtentEntry::nUnallocatedPages, Segment::pCache, and UNALLOCATED_PAGE_OWNER_ID.
Referenced by SnapshotSegmentTest::deallocateOldPages(), and Database::deallocateOldPages().
00720 { 00721 uint numOldPages = 0; 00722 SegmentAccessor selfAccessor(getTracingSegment(), pCache); 00723 SegAllocLock segAllocLock(selfAccessor); 00724 00725 while (numOldPages < numPages) { 00726 PageId segAllocPageId = getSegAllocPageId(iSegAlloc); 00727 segAllocLock.lockShared(segAllocPageId); 00728 SegmentAllocationNode const &segAllocNode = 00729 segAllocLock.getNodeForRead(); 00730 ExtentNum relativeExtentNum = extentNum % nExtentsPerSegAlloc; 00731 00732 for (uint i = relativeExtentNum; i < segAllocNode.nExtents; 00733 i++, extentNum++) 00734 { 00735 if (numOldPages >= numPages) { 00736 // Wait until we've reached an extent boundary before 00737 // returning 00738 return true; 00739 } 00740 00741 SegmentAllocationNode::ExtentEntry const &extentEntry = 00742 segAllocNode.getExtentEntry(i); 00743 if (extentEntry.nUnallocatedPages == nPagesPerExtent - 1) { 00744 continue; 00745 } 00746 00747 VersionedExtentAllocLock extentAllocLock(selfAccessor); 00748 extentAllocLock.lockShared(getExtentAllocPageId(extentNum)); 00749 VersionedExtentAllocationNode const &extentNode = 00750 extentAllocLock.getNodeForRead(); 00751 00752 // Start at pageEntry 1 to skip past the extent header page, 00753 // which we can never deallocate 00754 for (uint j = 1; j < nPagesPerExtent; j++) { 00755 VersionedPageEntry const &pageEntry = 00756 extentNode.getPageEntry(j); 00757 if (pageEntry.ownerId == UNALLOCATED_PAGE_OWNER_ID) { 00758 continue; 00759 } 00760 00761 // Map the pageEntry to its pageId 00762 PageId pageId = getLinearPageId(makePageNum(extentNum, j)); 00763 00764 // Skip over pages that have no snapshots, unless the page 00765 // is deallocation-deferred 00766 if (pageEntry.versionChainPageId == pageId && 00767 !isDeallocatedPageOwnerId(pageEntry.ownerId)) 00768 { 00769 continue; 00770 } 00771 00772 // Only consider deallocation-deferred pages if there are no 00773 // longer any active txns that might be accessing the pages 00774 if ((!isDeallocatedPageOwnerId(pageEntry.ownerId) && 00775 pageEntry.allocationCsn < oldestActiveTxnId) || 00776 (isDeallocatedPageOwnerId(pageEntry.ownerId) && 00777 getDeallocatedTxnId(pageEntry.ownerId) < 00778 oldestActiveTxnId)) 00779 { 00780 ++numOldPages; 00781 oldPageSet.insert(oldPageSet.end(), pageId); 00782 } 00783 } 00784 } 00785 ++iSegAlloc; 00786 if (segAllocNode.nextSegAllocPageId == NULL_PAGE_ID) { 00787 return false; 00788 } 00789 } 00790 00791 return true; 00792 }
void VersionedRandomAllocationSegment::deallocateOldPages | ( | PageSet const & | oldPageSet, | |
TxnId | oldestActiveTxnId | |||
) |
Deallocates an old set of pages and updates the version chain that the pages may be a part of.
Old pages are identified by calling getOldPageIds().
The actual deallocation of pages is in a separate method to minimize the duration the deallocation mutex is held.
[in] | oldPageSet | set of old pageIds that need to be deallocated |
oldestActiveTxnId | the txnId of the current, oldest active txnId; used as the threshhold for determining which pages should be deallocated |
Definition at line 794 of file VersionedRandomAllocationSegment.cpp.
References deallocateEntirePageChain(), deallocatePageChain(), deallocationMutex, getOldestTxnId(), isPageIdAllocateCommitted(), mapMutex, and NULL_TXN_ID.
Referenced by SnapshotSegmentTest::deallocateOldPages(), and Database::deallocateOldPages().
00797 { 00798 SXMutexExclusiveGuard deallocationGuard(deallocationMutex); 00799 SXMutexExclusiveGuard mapGuard(mapMutex); 00800 00801 std::hash_set<PageId> deallocatedPageSet; 00802 for (PageSetConstIter pageIter = oldPageSet.begin(); 00803 pageIter != oldPageSet.end(); pageIter++) 00804 { 00805 PageId pageId = *pageIter; 00806 00807 // Skip over pages that have already been deallocated while walking 00808 // through the page chain of a previous page 00809 if (deallocatedPageSet.find(pageId) != deallocatedPageSet.end()) { 00810 continue; 00811 } 00812 // Skip over pages that may have been deallocated by another 00813 // thread calling deallocateOldPages(). 00814 if (!isPageIdAllocateCommitted(pageId)) { 00815 deallocatedPageSet.insert(pageId); 00816 continue; 00817 } 00818 00819 // Determine the txnId corresponding to the oldest page in the page 00820 // chain that can be deallocated. If no pages can be deallocated, 00821 // then skip the page. If the page is marked as deallocation-deferred, 00822 // deallocate the entire page chain. 00823 PageId anchorPageId; 00824 bool deallocateChain; 00825 TxnId deallocationCsn = 00826 getOldestTxnId( 00827 pageId, 00828 oldestActiveTxnId, 00829 anchorPageId, 00830 deallocatedPageSet, 00831 deallocateChain); 00832 if (deallocateChain) { 00833 deallocateEntirePageChain( 00834 pageId, 00835 oldestActiveTxnId, 00836 deallocatedPageSet); 00837 continue; 00838 } 00839 if (deallocationCsn == NULL_TXN_ID) { 00840 continue; 00841 } 00842 00843 // Deallocate all pages following the anchor that are older than 00844 // deallocationCsn 00845 deallocatePageChain(anchorPageId, deallocationCsn, deallocatedPageSet); 00846 } 00847 }
void VersionedRandomAllocationSegment::freeTempPages | ( | ) |
Frees any of the remaining temp pages that were used to keep track of allocation node updates.
All of the remaining pages should correspond to segment allocation nodes, since extent allocation node pages are freed once they no longer contain any pending updates.
Definition at line 1191 of file VersionedRandomAllocationSegment.cpp.
References allocationNodeMap, freeTempPage(), and mapMutex.
Referenced by Database::closeImpl(), and SnapshotSegmentTestBase::closeStorage().
01192 { 01193 SXMutexExclusiveGuard mapGuard(mapMutex); 01194 01195 ModifiedAllocationNodeMap::iterator iter = allocationNodeMap.begin(); 01196 while (iter != allocationNodeMap.end()) { 01197 // All entries in the map should correspond to segment allocation 01198 // nodes because we free the nodes corresponding to extent allocation 01199 // nodes once their update counts reach 0. 01200 SharedModifiedAllocationNode pModAllocNode = iter->second; 01201 assert(!pModAllocNode->updateCount && pModAllocNode->isSegAllocNode); 01202 PageId pageId = iter->first; 01203 iter++; 01204 freeTempPage(pageId, pModAllocNode->tempPageId); 01205 } 01206 }
BlockNum VersionedRandomAllocationSegment::backupAllocationNodes | ( | SharedSegPageBackupRestoreDevice | pBackupDevice, | |
bool | countDataPages, | |||
TxnId | lowerBoundCsn, | |||
TxnId | upperBoundCsn, | |||
bool volatile const & | abortFlag | |||
) |
Writes all the segment and extent allocation pages from this segment sequentially to a backup file.
If requested, also counts the number of data pages that will need to be backed up later, based on pages whose allocationCsn's are within a lower and upper bound. If the lower bound is set to NULL_TXN_ID, then that indicates that there is no lower bound; otherwise, the lower bound is exclusive. There must always be an upper bound and it is inclusive.
pBackupDevice | device that does all I/O for the backup | |
countDataPages | if true, count the number of data pages that will be backed up | |
lowerBoundCsn | the lower bound allocation csn | |
upperBoundCsn | the upper bound allocation csn | |
[in] | abortFlag | reference to a flag indicating whether the backup should be aborted |
Definition at line 1213 of file VersionedRandomAllocationSegment.cpp.
References VersionedPageEntry::allocationCsn, checkAbort(), RandomAllocationSegmentBase::getExtentAllocPageId(), SegmentAllocationNode::getExtentEntry(), SegNodeLock< Node >::getNodeForRead(), SegPageLock::getPage(), VersionedExtentAllocationNode::getPageEntry(), CachePage::getReadableData(), RandomAllocationSegmentBase::getSegAllocPageId(), Segment::getTracingSegment(), SegPageLock::lockShared(), SegmentAllocationNode::nExtents, RandomAllocationSegmentBase::nExtentsPerSegAlloc, SegmentAllocationNode::nextSegAllocPageId, RandomAllocationSegmentBase::nPagesPerExtent, NULL_PAGE_ID, NULL_TXN_ID, SegmentAllocationNode::ExtentEntry::nUnallocatedPages, PageEntry::ownerId, Segment::pCache, and UNALLOCATED_PAGE_OWNER_ID.
Referenced by BackupRestoreTest::backup().
01219 { 01220 assert(upperBoundCsn != NULL_TXN_ID); 01221 SegmentAccessor selfAccessor(getTracingSegment(), pCache); 01222 SegAllocLock segAllocLock(selfAccessor); 01223 uint iSegAlloc = 0; 01224 ExtentNum extentNum = 0; 01225 BlockNum nDataPages = 0; 01226 01227 while (true) { 01228 PageId segAllocPageId = getSegAllocPageId(iSegAlloc); 01229 segAllocLock.lockShared(segAllocPageId); 01230 pBackupDevice->writeBackupPage( 01231 segAllocLock.getPage().getReadableData()); 01232 01233 SegmentAllocationNode const &segAllocNode = 01234 segAllocLock.getNodeForRead(); 01235 ExtentNum relativeExtentNum = extentNum % nExtentsPerSegAlloc; 01236 01237 for (uint i = relativeExtentNum; i < segAllocNode.nExtents; 01238 i++, extentNum++) 01239 { 01240 checkAbort(abortFlag); 01241 SegmentAllocationNode::ExtentEntry const &extentEntry = 01242 segAllocNode.getExtentEntry(i); 01243 01244 VersionedExtentAllocLock extentAllocLock(selfAccessor); 01245 extentAllocLock.lockShared(getExtentAllocPageId(extentNum)); 01246 pBackupDevice->writeBackupPage( 01247 extentAllocLock.getPage().getReadableData()); 01248 01249 if (countDataPages) { 01250 // Don't bother looping through the entries if we know none 01251 // are allocated 01252 if (extentEntry.nUnallocatedPages == nPagesPerExtent - 1) { 01253 continue; 01254 } 01255 01256 VersionedExtentAllocationNode const &extentNode = 01257 extentAllocLock.getNodeForRead(); 01258 01259 // Start at pageEntry 1 to skip past the extent header page 01260 for (uint j = 1; j < nPagesPerExtent; j++) { 01261 checkAbort(abortFlag); 01262 VersionedPageEntry const &pageEntry = 01263 extentNode.getPageEntry(j); 01264 if (pageEntry.ownerId != UNALLOCATED_PAGE_OWNER_ID && 01265 (lowerBoundCsn == NULL_TXN_ID || 01266 pageEntry.allocationCsn > lowerBoundCsn) && 01267 (pageEntry.allocationCsn <= upperBoundCsn)) 01268 { 01269 nDataPages++; 01270 } 01271 } 01272 } 01273 } 01274 01275 ++iSegAlloc; 01276 if (segAllocNode.nextSegAllocPageId == NULL_PAGE_ID) { 01277 break; 01278 } 01279 } 01280 01281 return nDataPages; 01282 }
void VersionedRandomAllocationSegment::backupDataPages | ( | SharedSegPageBackupRestoreDevice | pBackupDevice, | |
TxnId | lowerBoundCsn, | |||
TxnId | upperBoundCsn, | |||
bool volatile const & | abortFlag | |||
) |
Walks through all page entries in this segment and locates the ones that have allocationCsn's in between a lower and upper bound.
If the lower bound is set to NULL_TXN_ID, then that indicates that there is no lower bound; otherwise, the lower bound is exclusive. There must always be an upper bound and it is inclusive.
pBackupDevice | device that carries out I/O for the backup | |
lowerBoundCsn | the lower bound allocation csn | |
upperBoundCsn | the upper bound allocation csn | |
[in] | abortFlag | reference to a flag indicating whether the backup should be aborted |
Definition at line 1284 of file VersionedRandomAllocationSegment.cpp.
References locateDataPages().
Referenced by BackupRestoreTest::backup(), and Database::completeBackup().
01289 { 01290 locateDataPages( 01291 pBackupDevice, 01292 lowerBoundCsn, 01293 upperBoundCsn, 01294 true, 01295 abortFlag); 01296 }
void VersionedRandomAllocationSegment::restoreFromBackup | ( | SharedSegPageBackupRestoreDevice | pBackupDevice, | |
TxnId | lowerBoundCsn, | |||
TxnId | upperBoundCsn, | |||
bool volatile const & | abortFlag | |||
) |
Restores the segment and extent allocation node pages and data pages for this segment from a backup file.
The data pages in the backup file correspond to pages with allocationCsn's in between a lower and upper bound. If the lower bound is set to NULL_TXN_ID, then that indicates that there is no lower bound; otherwise, the lower bound is exclusive. There must always be an upper bound and it is inclusive.
pBackupDevice | device that carries out I/O during the restore | |
lowerBoundCsn | the lower bound allocation csn | |
upperBoundCsn | the upper bound allocation csn | |
[in] | abortFlag | reference to a flag indicating whether the restore should be aborted |
Definition at line 1399 of file VersionedRandomAllocationSegment.cpp.
References checkAbort(), DelegatingSegment::ensureAllocatedSize(), RandomAllocationSegmentBase::getExtentAllocPageId(), SegmentAllocationNode::getExtentEntry(), SegNodeLock< Node >::getNodeForRead(), RandomAllocationSegmentBase::getSegAllocPageId(), Segment::getTracingSegment(), locateDataPages(), SegPageLock::lockShared(), RandomAllocationSegmentBase::makePageNum(), SegmentAllocationNode::nExtents, RandomAllocationSegmentBase::nExtentsPerSegAlloc, SegmentAllocationNode::nextSegAllocPageId, RandomAllocationSegmentBase::nPagesPerExtent, NULL_PAGE_ID, Segment::pCache, and RandomAllocationSegmentBase::translatePageId().
Referenced by BackupRestoreTest::restore(), and Database::restoreFromBackup().
01404 { 01405 // First restore the allocation node pages. 01406 // 01407 // The assumption is that prior to calling this method, all pages in the 01408 // cache have been unmapped, so we're ensured that when we're reading 01409 // pages from cache, we won't read stale copies. 01410 01411 SegmentAccessor selfAccessor(getTracingSegment(), pCache); 01412 SegAllocLock segAllocLock(selfAccessor); 01413 uint iSegAlloc = 0; 01414 ExtentNum extentNum = 0; 01415 01416 while (true) { 01417 // Restore the allocation node page from the backup file, writing it 01418 // to disk. Then wait for the write to complete before reading it 01419 // into cache, so we're ensured that we pick up the completed write. 01420 // Also make sure there's enough space for the first extent in this 01421 // SegAllocNode. 01422 PageId segAllocPageId = getSegAllocPageId(iSegAlloc); 01423 01424 if (!DelegatingSegment::ensureAllocatedSize( 01425 makePageNum(extentNum, nPagesPerExtent))) 01426 { 01427 throw FennelExcn( 01428 FennelResource::instance().outOfSpaceDuringRestore()); 01429 } 01430 pBackupDevice->restorePage(translatePageId(segAllocPageId)); 01431 pBackupDevice->waitForPendingWrites(); 01432 segAllocLock.lockShared(segAllocPageId); 01433 01434 SegmentAllocationNode const &segAllocNode = 01435 segAllocLock.getNodeForRead(); 01436 ExtentNum relativeExtentNum = extentNum % nExtentsPerSegAlloc; 01437 01438 for (uint i = relativeExtentNum; i < segAllocNode.nExtents; 01439 i++, extentNum++) 01440 { 01441 checkAbort(abortFlag); 01442 SegmentAllocationNode::ExtentEntry const &extentEntry = 01443 segAllocNode.getExtentEntry(i); 01444 // Make sure there's enough space in the segment for this extent 01445 if (!DelegatingSegment::ensureAllocatedSize( 01446 makePageNum(extentNum, nPagesPerExtent))) 01447 { 01448 throw FennelExcn( 01449 FennelResource::instance().outOfSpaceDuringRestore()); 01450 } 01451 pBackupDevice->restorePage( 01452 translatePageId(getExtentAllocPageId(extentNum))); 01453 } 01454 ++iSegAlloc; 01455 if (segAllocNode.nextSegAllocPageId == NULL_PAGE_ID) { 01456 break; 01457 } 01458 } 01459 01460 // Walk through the allocation node pages just restored, looking for 01461 // the page entries within the lower and upper bounds, and restore them. 01462 // But first make sure to wait for the writes of the remaining extent 01463 // allocation node pages to complete. 01464 pBackupDevice->waitForPendingWrites(); 01465 locateDataPages( 01466 pBackupDevice, 01467 lowerBoundCsn, 01468 upperBoundCsn, 01469 false, 01470 abortFlag); 01471 }
bool VersionedRandomAllocationSegment::isPageIdAllocated | ( | PageId | pageId | ) | [virtual] |
Tests whether a PageId is allocated.
pageId | the PageId of interest |
Reimplemented from RandomAllocationSegmentBase.
Definition at line 247 of file VersionedRandomAllocationSegment.cpp.
References RandomAllocationSegmentBase::testPageId().
Referenced by chainPageEntries(), initPageEntry(), and updateAllocNodes().
00248 { 00249 return testPageId(pageId, true, false); 00250 }
PageId VersionedRandomAllocationSegment::allocatePageId | ( | PageOwnerId | ownerId | ) | [virtual] |
Allocates a page without locking it into memory.
ownerId | the PageOwnerId of the object which will own this page, or ANON_PAGE_OWNER_ID for pages unassociated with an owner |
Reimplemented from DelegatingSegment.
Definition at line 68 of file VersionedRandomAllocationSegment.cpp.
References RandomAllocationSegmentBase::allocatePageIdFromSegment(), and pTempSegment.
00069 { 00070 return allocatePageIdFromSegment(ownerId, pTempSegment); 00071 }
PageId VersionedRandomAllocationSegment::getPageSuccessor | ( | PageId | pageId | ) | [virtual] |
Determines the successor of a given PageId.
This is an optional interface only supported by segments with some concept of page ordering.
pageId | PageId for which the successor is to be found |
Reimplemented from DelegatingSegment.
Definition at line 228 of file VersionedRandomAllocationSegment.cpp.
References getLatestPageEntryCopy(), and PageEntry::successorId.
00229 { 00230 VersionedPageEntry pageEntry; 00231 00232 getLatestPageEntryCopy(pageId, pageEntry); 00233 return pageEntry.successorId; 00234 }
void VersionedRandomAllocationSegment::setPageSuccessor | ( | PageId | pageId, | |
PageId | successorId | |||
) | [virtual] |
Sets the successor of a given PageId.
This is an optional interface only supported by segments with some concept of modifiable ordering.
pageId | PageId for which the successor is to be set | |
successorId | PageId of successor |
Reimplemented from DelegatingSegment.
Definition at line 236 of file VersionedRandomAllocationSegment.cpp.
References pTempSegment, and RandomAllocationSegmentBase::setPageSuccessorTemplate().
00238 { 00239 setPageSuccessorTemplate< 00240 VersionedExtentAllocationNode, 00241 VersionedExtentAllocLock>( 00242 pageId, 00243 successorId, 00244 pTempSegment); 00245 }
void VersionedRandomAllocationSegment::deallocatePageRange | ( | PageId | startPageId, | |
PageId | endPageId | |||
) | [virtual] |
Deallocates a range of pages allocated from this segment.
Some segment implementations may impose restrictions on the range (e.g. individual pages only, entire segment truncation only, start-ranges, or end-ranges). The interpretation of the range may also vary by segment (e.g. for a LINEAR_ALLOCATION segment, it's a simple linear PageId range, while for a RANDOM_ALLOCATION segment, successors could be used).
Depending on the circumstances, it may be the responsibility of the segment to discard the corresponding blocks from the cache. The details vary by segment implementation.
startPageId | inclusive start of PageId range to deallocate, or default NULL_PAGE_ID for beginning of segment | |
endPageId | inclusive end of PageId range to deallocate, or default NULL_PAGE_ID for end of segment |
Reimplemented from RandomAllocationSegmentBase.
Definition at line 159 of file VersionedRandomAllocationSegment.cpp.
References deallocationMutex, deferDeallocation(), RandomAllocationSegmentBase::format(), and NULL_PAGE_ID.
00162 { 00163 assert(startPageId == endPageId); 00164 00165 if (startPageId == NULL_PAGE_ID) { 00166 format(); 00167 } else { 00168 // Note that we cannot discard deferred-deallocation pages from cache 00169 // because they really haven't been freed yet and still may be 00170 // referenced by other threads. The pages will be removed from the 00171 // cache when they are actually freed. 00172 00173 // Acquire mutex exclusively to prevent another thread from trying 00174 // to do the actual free of the same page, if it's an old page. 00175 SXMutexExclusiveGuard deallocationGuard(deallocationMutex); 00176 00177 // Simply mark the page as deallocation-deferred. The actual 00178 // deallocation will be done by calls to deallocateOldPages(). 00179 deferDeallocation(startPageId); 00180 } 00181 }
void VersionedRandomAllocationSegment::initForUse | ( | ) | [virtual] |
Performs additional initialization required on the segment after it has been properly formatted.
Reimplemented from RandomAllocationSegmentBase.
Definition at line 47 of file VersionedRandomAllocationSegment.cpp.
References RandomAllocationSegmentBase::initForUse(), and mapMutex.
00048 { 00049 // Since we will be accessing SegmentAllocationNode pages, we need to 00050 // acquire a mutex on the allocationNodeMap. 00051 SXMutexSharedGuard mapGuard(mapMutex); 00052 00053 RandomAllocationSegmentBase::initForUse(); 00054 }
PageId RandomAllocationSegmentBase::getSegAllocPageId | ( | uint | iSegPage | ) | const [inline, protected, inherited] |
Calculates the PageId of a particular SegmentAllocationNode.
iSegPage | 0-based index of desired SegmentAllocationNode |
Definition at line 104 of file RandomAllocationSegmentBaseImpl.h.
References Segment::getLinearPageId(), and RandomAllocationSegmentBase::nPagesPerSegAlloc.
Referenced by allocateAllocNodes(), RandomAllocationSegmentBase::allocatePageIdFromSegment(), backupAllocationNodes(), RandomAllocationSegmentBase::deallocatePageId(), deallocateSinglePage(), RandomAllocationSegmentBase::format(), getOldPageIds(), locateDataPages(), restoreFromBackup(), updateExtentEntry(), and validateFreePageCount().
00106 { 00107 return getLinearPageId(nPagesPerSegAlloc*iSegPage); 00108 }
PageId RandomAllocationSegmentBase::getExtentAllocPageId | ( | ExtentNum | extentNum | ) | const [inline, protected, inherited] |
Calculates the PageId of a particular extent allocation node.
extentNum | absolute 0-based extent number |
Definition at line 118 of file RandomAllocationSegmentBaseImpl.h.
References Segment::getLinearPageId(), and RandomAllocationSegmentBase::makePageNum().
Referenced by backupAllocationNodes(), chainPageEntries(), deallocateSinglePage(), RandomAllocationSegmentBase::formatPageExtentsTemplate(), RandomAllocationSegmentBase::freePageEntryTemplate(), getExtAllocPageIdForRead(), RandomAllocationSegment::getExtAllocPageIdForRead(), getExtAllocPageIdForWrite(), RandomAllocationSegment::getExtAllocPageIdForWrite(), getOldestTxnId(), getOldPageIds(), RandomAllocationSegmentBase::getPageEntryCopyTemplate(), locateDataPages(), restoreFromBackup(), uncommittedDeallocation(), updatePageEntry(), updateTempPageEntry(), and validateFreePageCount().
00120 { 00121 return getLinearPageId(makePageNum(extentNum,0)); 00122 }
BlockNum RandomAllocationSegmentBase::makePageNum | ( | ExtentNum | extentNum, | |
BlockNum | iPageInExtent | |||
) | const [inline, protected, inherited] |
Calculates a linear page number.
extentNum | absolute 0-based extent number of extent containing desired page | |
iPageInExtent | 0-based index of page in extent |
Definition at line 110 of file RandomAllocationSegmentBaseImpl.h.
References RandomAllocationSegmentBase::nExtentsPerSegAlloc, and RandomAllocationSegmentBase::nPagesPerExtent.
Referenced by RandomAllocationSegmentBase::allocateFromLockedExtentTemplate(), RandomAllocationSegmentBase::allocatePageIdFromSegment(), RandomAllocationSegmentBase::getExtentAllocPageId(), getOldPageIds(), locateDataPages(), and restoreFromBackup().
00112 { 00113 // weird calculation to take into account interspersal of SegAllocNodes 00114 uint nSegPages = extentNum / nExtentsPerSegAlloc + 1; 00115 return iPageInExtent + extentNum*nPagesPerExtent + nSegPages; 00116 }
void RandomAllocationSegmentBase::splitPageId | ( | PageId | pageId, | |
uint & | iSegAlloc, | |||
ExtentNum & | extentNum, | |||
BlockNum & | iPageInExtent | |||
) | const [protected, inherited] |
Maps a linear PageId from this segment into the corresponding SegmentAllocationNode, extent allocation node, and extent-relative page index.
pageId | input PageId | |
[out] | iSegAlloc | 0-based index of containing SegmentAllocationNode |
[out] | extentNum | absolute 0-based extent number of containing extent allocation node |
[out] | iPageInExtent | 0-based index of page in extent |
Definition at line 279 of file RandomAllocationSegmentBase.cpp.
References Segment::getLinearBlockNum(), MAXU, RandomAllocationSegmentBase::nExtentsPerSegAlloc, RandomAllocationSegmentBase::nPagesPerExtent, and RandomAllocationSegmentBase::nPagesPerSegAlloc.
Referenced by chainPageEntries(), RandomAllocationSegmentBase::deallocatePageId(), deallocateSinglePage(), deferDeallocation(), getOldestTxnId(), RandomAllocationSegmentBase::getPageEntryCopyTemplate(), initPageEntry(), RandomAllocationSegmentBase::setPageSuccessorTemplate(), RandomAllocationSegmentBase::testPageId(), uncommittedDeallocation(), updateAllocNodes(), updateTempPageEntry(), and validateFreePageCount().
00282 { 00283 // calculate block number relative to containing SegAllocNode 00284 BlockNum iPageInSegAlloc = getLinearBlockNum(pageId) % nPagesPerSegAlloc; 00285 iSegAlloc = getLinearBlockNum(pageId) / nPagesPerSegAlloc; 00286 if (!iPageInSegAlloc) { 00287 // this is the SegAllocNode itself! 00288 extentNum = MAXU; 00289 iPageInExtent = 0; 00290 } else { 00291 // account for the SegAllocNode 00292 --iPageInSegAlloc; 00293 extentNum = 00294 iPageInSegAlloc / nPagesPerExtent + nExtentsPerSegAlloc * iSegAlloc; 00295 iPageInExtent = iPageInSegAlloc % nPagesPerExtent; 00296 } 00297 }
bool RandomAllocationSegmentBase::testPageId | ( | PageId | pageId, | |
bool | testAllocation, | |||
bool | thisSegment | |||
) | [protected, inherited] |
Common implementation for isPageIdValid and isPageIdAllocated.
Definition at line 385 of file RandomAllocationSegmentBase.cpp.
References RandomAllocationSegmentBase::getPageOwnerId(), DelegatingSegment::isPageIdAllocated(), RandomAllocationSegmentBase::splitPageId(), and UNALLOCATED_PAGE_OWNER_ID.
Referenced by RandomAllocationSegmentBase::getPageEntryCopyTemplate(), isPageIdAllocateCommitted(), isPageIdAllocated(), RandomAllocationSegmentBase::isPageIdAllocated(), isPageIdValid(), and RandomAllocationSegmentBase::isPageIdValid().
00389 { 00390 if (!DelegatingSegment::isPageIdAllocated(pageId)) { 00391 return false; 00392 } 00393 00394 uint iSegAlloc; 00395 ExtentNum extentNum; 00396 BlockNum iPageInExtent; 00397 splitPageId(pageId,iSegAlloc,extentNum,iPageInExtent); 00398 if (!iPageInExtent) { 00399 // header pages are valid but not allocated (from the 00400 // perspective of the RandomAllocationSegment, not the 00401 // underlying linear segment) 00402 if (testAllocation) { 00403 return false; 00404 } else { 00405 return true; 00406 } 00407 } 00408 PageOwnerId ownerId = getPageOwnerId(pageId, thisSegment); 00409 return (ownerId != UNALLOCATED_PAGE_OWNER_ID); 00410 }
PageOwnerId RandomAllocationSegmentBase::getPageOwnerIdTemplate | ( | PageId | pageId, | |
bool | thisSegment | |||
) | [protected, inherited] |
Retrieves the ownerId corresponding to a page entry.
This template method allows the caller to specify different page entry types.
pageId | PageId of the page whose owner we are retrieving | |
thisSegment | if true, retrieve page entry from this segment; otherwise, retrieve it from an alternative segment |
Definition at line 262 of file RandomAllocationSegmentBaseImpl.h.
References RandomAllocationSegmentBase::getPageEntryCopy().
00265 { 00266 PageEntryT pageEntry; 00267 00268 getPageEntryCopy(pageId, pageEntry, false, thisSegment); 00269 return pageEntry.ownerId; 00270 }
void RandomAllocationSegmentBase::freePageEntryTemplate | ( | ExtentNum | extentNum, | |
BlockNum | iPageInExtent | |||
) | [protected, inherited] |
Marks the page entry corresponding to a deallocated page as unallocated.
The extent is specified by the the extentNum, the index of the page in the extent, and the segment where the extent allocation node originates from.
This template method allows the caller to specify different extent allocation node types.
extentNum | absolute 0-based extent number | |
iPageInExtent | 0-based index of deallocated page in extent |
Definition at line 225 of file RandomAllocationSegmentBaseImpl.h.
References RandomAllocationSegmentBase::getExtentAllocPageId(), Segment::getTracingSegment(), RandomAllocationSegmentBase::markPageEntryUnused(), Segment::pCache, and UNALLOCATED_PAGE_OWNER_ID.
Referenced by freePageEntry(), and RandomAllocationSegment::freePageEntry().
00228 { 00229 SegmentAccessor segAccessor(getTracingSegment(), pCache); 00230 ExtentAllocLockT extentAllocLock(segAccessor); 00231 00232 extentAllocLock.lockExclusive(getExtentAllocPageId(extentNum)); 00233 ExtentAllocationNodeT &extentNode = extentAllocLock.getNodeForWrite(); 00234 PageEntryT &pageEntry = extentNode.getPageEntry(iPageInExtent); 00235 permAssert(pageEntry.ownerId != UNALLOCATED_PAGE_OWNER_ID); 00236 markPageEntryUnused(pageEntry); 00237 }
PageId RandomAllocationSegmentBase::getFirstSegAllocPageId | ( | ) | const [inline, protected, inherited] |
Definition at line 99 of file RandomAllocationSegmentBaseImpl.h.
References FIRST_LINEAR_PAGE_ID.
Referenced by RandomAllocationSegmentBase::allocatePageIdFromSegment(), and RandomAllocationSegmentBase::countAllocatedPages().
00100 { 00101 return FIRST_LINEAR_PAGE_ID; 00102 }
uint RandomAllocationSegmentBase::inferSegAllocCount | ( | ) | [protected, inherited] |
Infers the number of SegmentAllocationNodes from the size of the underlying segment.
Definition at line 143 of file RandomAllocationSegmentBase.cpp.
References DelegatingSegment::getAllocatedSizeInPages(), and RandomAllocationSegmentBase::nPagesPerSegAlloc.
Referenced by RandomAllocationSegmentBase::format().
00144 { 00145 BlockNum nPages = DelegatingSegment::getAllocatedSizeInPages(); 00146 // round up 00147 return nPages / nPagesPerSegAlloc + 00148 (nPages % nPagesPerSegAlloc ? 1 : 0); 00149 }
void RandomAllocationSegmentBase::format | ( | ) | [protected, inherited] |
Formats allocation pages based on current size of underlying segment, marking all pages as deallocated.
Definition at line 67 of file RandomAllocationSegmentBase.cpp.
References DelegatingSegment::ensureAllocatedSize(), RandomAllocationSegmentBase::formatPageExtents(), DelegatingSegment::getAllocatedSizeInPages(), SegNodeLock< Node >::getNodeForWrite(), RandomAllocationSegmentBase::getSegAllocPageId(), Segment::getTracingSegment(), RandomAllocationSegmentBase::inferSegAllocCount(), SegPageLock::lockExclusive(), min(), SegmentAllocationNode::nExtents, RandomAllocationSegmentBase::nExtentsPerSegAlloc, SegmentAllocationNode::nextSegAllocPageId, SegmentAllocationNode::nPagesPerExtent, RandomAllocationSegmentBase::nPagesPerExtent, NULL_PAGE_ID, Segment::pCache, and SegNodeLock< Node >::setMagicNumber().
Referenced by deallocatePageRange(), and RandomAllocationSegmentBase::deallocatePageRange().
00068 { 00069 // calculate number of SegAllocNodes based on current segment size 00070 uint nSegAllocPages = inferSegAllocCount(); 00071 00072 // calculate number of extents in all but last SegAllocNode 00073 ExtentNum nExtents = (nSegAllocPages-1)*nExtentsPerSegAlloc; 00074 00075 // calculate number of pages in last SegAllocNode 00076 BlockNum nRemainderPages = DelegatingSegment::getAllocatedSizeInPages(); 00077 nRemainderPages -= (nExtents*nPagesPerExtent+nSegAllocPages); 00078 00079 if (nRemainderPages) { 00080 // last SegAllocNode is not full; add number of remainder extents, 00081 // rounding down 00082 nExtents += nRemainderPages / nPagesPerExtent; 00083 } else { 00084 // last SegAllocNode is full 00085 nExtents += nExtentsPerSegAlloc; 00086 } 00087 00088 // always format at least one extent; this is somewhat arbitrary, but helps 00089 // to avoid spurious problems with tiny segments in test cases 00090 if (!nExtents) { 00091 nSegAllocPages = 1; 00092 nExtents = 1; 00093 } 00094 00095 // make sure underlying segment is big enough 00096 bool bigEnough = DelegatingSegment::ensureAllocatedSize( 00097 nExtents*nPagesPerExtent + nSegAllocPages); 00098 permAssert(bigEnough); 00099 00100 // format each SegAllocNode 00101 00102 ExtentNum extentNum = 0; 00103 SegmentAccessor selfAccessor(getTracingSegment(), pCache); 00104 SegAllocLock segAllocLock(selfAccessor); 00105 for (uint iSegAlloc = 0; iSegAlloc < nSegAllocPages; iSegAlloc++) { 00106 PageId segAllocPageId = getSegAllocPageId(iSegAlloc); 00107 segAllocLock.lockExclusive(segAllocPageId); 00108 00109 // REVIEW: have to do setMagicNumber() explicitly since we skipped 00110 // allocation. Should figure out a way to indicate allocation of a 00111 // specific PageId. 00112 segAllocLock.setMagicNumber(); 00113 SegmentAllocationNode &segAllocNode = segAllocLock.getNodeForWrite(); 00114 00115 uint iNextSegAlloc = iSegAlloc + 1; 00116 if (iNextSegAlloc < nSegAllocPages) { 00117 // set up SegAllocNode chain 00118 segAllocNode.nextSegAllocPageId = getSegAllocPageId(iNextSegAlloc); 00119 } else { 00120 // terminate SegAllocNode chain at last node 00121 segAllocNode.nextSegAllocPageId = NULL_PAGE_ID; 00122 } 00123 00124 // format extent array 00125 segAllocNode.nPagesPerExtent = nPagesPerExtent; 00126 segAllocNode.nExtents = std::min(nExtents,nExtentsPerSegAlloc); 00127 nExtents -= segAllocNode.nExtents; 00128 00129 // format each extent node within the page 00130 formatPageExtents(segAllocNode, extentNum); 00131 } 00132 00133 permAssert(!nExtents); 00134 }
void RandomAllocationSegmentBase::formatPageExtentsTemplate | ( | SegmentAllocationNode & | segAllocNode, | |
ExtentNum & | extentNum | |||
) | [protected, inherited] |
Formats each of the extents within a segment allocation node.
This template method allows the caller to specify different extent allocation node types.
[in] | segAllocNode | locked segment allocation node |
[in,out] | extentNum | on input, the initial absolute 0-based extent number that needs to be formatted; on output, the last extent number formatted + 1 |
Definition at line 146 of file RandomAllocationSegmentBaseImpl.h.
References RandomAllocationSegmentBase::formatExtentTemplate(), RandomAllocationSegmentBase::getExtentAllocPageId(), SegmentAllocationNode::getExtentEntry(), Segment::getTracingSegment(), SegmentAllocationNode::nExtents, RandomAllocationSegmentBase::nExtentsPerSegAlloc, RandomAllocationSegmentBase::nPagesPerExtent, and Segment::pCache.
Referenced by allocateExtAllocNodes(), formatPageExtents(), and RandomAllocationSegment::formatPageExtents().
00149 { 00150 SegmentAccessor selfAccessor(getTracingSegment(), pCache); 00151 ExtentAllocLockT extentAllocLock(selfAccessor); 00152 uint startOffset = extentNum % nExtentsPerSegAlloc; 00153 for (uint i = startOffset; i < segAllocNode.nExtents; ++i, ++extentNum) { 00154 // -1 for the extent allocation node itself 00155 segAllocNode.getExtentEntry(i).nUnallocatedPages = 00156 nPagesPerExtent - 1; 00157 extentAllocLock.lockExclusive(getExtentAllocPageId(extentNum)); 00158 extentAllocLock.setMagicNumber(); 00159 formatExtentTemplate< 00160 ExtentAllocationNodeT, 00161 ExtentAllocLockT, 00162 PageEntryT>( 00163 extentAllocLock.getNodeForWrite()); 00164 } 00165 }
void RandomAllocationSegmentBase::formatExtentTemplate | ( | ExtentAllocationNodeT & | extentNode | ) | [protected, inherited] |
Formats one extent allocation.
This template method allows the caller to specify different extent allocation node types.
[in] | extentNode | locked extent allocation node |
Definition at line 168 of file RandomAllocationSegmentBaseImpl.h.
References ANON_PAGE_OWNER_ID, RandomAllocationSegmentBase::markPageEntryUnused(), and RandomAllocationSegmentBase::nPagesPerExtent.
Referenced by RandomAllocationSegmentBase::formatPageExtentsTemplate().
00170 { 00171 // mark all pages as free 00172 for (uint i = 0; i < nPagesPerExtent; i++) { 00173 PageEntryT &pageEntry = extentNode.getPageEntry(i); 00174 markPageEntryUnused(pageEntry); 00175 } 00176 00177 // mark the first entry representing the extent allocation node itself 00178 // as permanently allocated 00179 extentNode.getPageEntry(0).ownerId = ANON_PAGE_OWNER_ID; 00180 }
PageId RandomAllocationSegmentBase::allocatePageIdFromSegment | ( | PageOwnerId | ownerId, | |
SharedSegment | allocNodeSegment | |||
) | [protected, inherited] |
Allocates a page without locking it into memory.
The allocation nodes originate from a specified segment.
ownerId | the PageOwnerId of the object which will own this page, or ANON_PAGE_OWNER_ID for pages unassociated with an owner | |
allocNodeSegment | segment from which the allocation nodes originate |
Definition at line 151 of file RandomAllocationSegmentBase.cpp.
References RandomAllocationSegmentBase::allocateFromExtent(), RandomAllocationSegmentBase::allocateFromNewExtent(), DelegatingSegment::ensureAllocatedSize(), SegmentAllocationNode::getExtentEntry(), RandomAllocationSegmentBase::getFirstSegAllocPageId(), SegNodeLock< Node >::getNodeForRead(), SegNodeLock< Node >::getNodeForWrite(), RandomAllocationSegmentBase::getSegAllocPageId(), RandomAllocationSegmentBase::getSegAllocPageIdForWrite(), RandomAllocationSegmentBase::incrementPageCounters(), RandomAllocationSegmentBase::incrementPagesOccupiedCounter(), SegPageLock::lockExclusive(), RandomAllocationSegmentBase::makePageNum(), SegmentAllocationNode::nExtents, RandomAllocationSegmentBase::nExtentsPerSegAlloc, SegmentAllocationNode::nextSegAllocPageId, SegmentAllocationNode::nPagesPerExtent, RandomAllocationSegmentBase::nPagesPerExtent, NULL_PAGE_ID, SegmentAllocationNode::ExtentEntry::nUnallocatedPages, Segment::pCache, SegNodeLock< Node >::setMagicNumber(), RandomAllocationSegmentBase::undoSegAllocPageWrite(), and SegPageLock::unlock().
Referenced by allocatePageId(), and RandomAllocationSegment::allocatePageId().
00154 { 00155 ExtentNum extentNum = 0; 00156 SegmentAccessor segAccessor(allocNodeSegment, pCache); 00157 SegAllocLock segAllocLock(segAccessor); 00158 00159 // find a SegAllocNode with free space 00160 PageId origSegAllocPageId = getFirstSegAllocPageId(); 00161 PageId segAllocPageId = getSegAllocPageIdForWrite(origSegAllocPageId); 00162 for (uint iSegAlloc = 0; ; ++iSegAlloc) { 00163 // Initially access the node for read because we may not actually 00164 // update it if all extents in the node are full. Once we need 00165 // to update the node, we'll acquire a writable node. 00166 segAllocLock.lockExclusive(segAllocPageId); 00167 SegmentAllocationNode const &readOnlySegAllocNode = 00168 segAllocLock.getNodeForRead(); 00169 00170 // check each extent 00171 for (uint i = 0; i < readOnlySegAllocNode.nExtents; ++i, ++extentNum) { 00172 SegmentAllocationNode::ExtentEntry const &readOnlyExtentEntry = 00173 readOnlySegAllocNode.getExtentEntry(i); 00174 if (readOnlyExtentEntry.nUnallocatedPages) { 00175 // found one, so get a writable node 00176 SegmentAllocationNode &writableSegAllocNode = 00177 segAllocLock.getNodeForWrite(); 00178 SegmentAllocationNode::ExtentEntry &writableExtentEntry = 00179 writableSegAllocNode.getExtentEntry(i); 00180 writableExtentEntry.nUnallocatedPages--; 00181 // explicit unlock to minimize contention window and avoid 00182 // deadlock with deallocatePageId; this is like a Southwest 00183 // airlines reservation: we've got a flight reserved, not a 00184 // particular seat on that flight, but we're guaranteed to find 00185 // a seat when we get on 00186 segAllocLock.unlock(); 00187 incrementPageCounters(); 00188 return allocateFromExtent(extentNum,ownerId); 00189 } 00190 } 00191 00192 if (readOnlySegAllocNode.nextSegAllocPageId != NULL_PAGE_ID) { 00193 // since there's no space on the current SegAllocNode, indicate 00194 // that we haven't allocated any new pages from it 00195 undoSegAllocPageWrite(origSegAllocPageId); 00196 00197 // try next SegAllocNode 00198 origSegAllocPageId = readOnlySegAllocNode.nextSegAllocPageId; 00199 segAllocPageId = getSegAllocPageIdForWrite(origSegAllocPageId); 00200 continue; 00201 } 00202 00203 // We have to extend the underlying segment, so we need to prevent 00204 // anyone else from trying to do the same thing at the same time. So 00205 // hold onto segAllocLock during this process. 00206 00207 if (readOnlySegAllocNode.nExtents < nExtentsPerSegAlloc) { 00208 // Try to allocate a new extent. The parameters to makePageNum 00209 // request just enough space to fit one more extent within the 00210 // current SegAllocNode. 00211 try { 00212 if (!DelegatingSegment::ensureAllocatedSize( 00213 makePageNum(extentNum,nPagesPerExtent))) 00214 { 00215 // couldn't grow 00216 undoSegAllocPageWrite(origSegAllocPageId); 00217 return NULL_PAGE_ID; 00218 } 00219 } catch (...) { 00220 undoSegAllocPageWrite(origSegAllocPageId); 00221 throw; 00222 } 00223 00224 // acquire a writable node now that we're actually updating it 00225 SegmentAllocationNode &writableSegAllocNode = 00226 segAllocLock.getNodeForWrite(); 00227 writableSegAllocNode.nExtents++; 00228 SegmentAllocationNode::ExtentEntry &writableExtentEntry = 00229 writableSegAllocNode.getExtentEntry( 00230 writableSegAllocNode.nExtents - 1); 00231 00232 // -2 = -1 for extent allocation node, -1 for page we're 00233 // about to allocate 00234 writableExtentEntry.nUnallocatedPages = nPagesPerExtent - 2; 00235 00236 incrementPageCounters(); 00237 // another increment for the extent page 00238 incrementPagesOccupiedCounter(); 00239 return allocateFromNewExtent(extentNum, ownerId); 00240 } 00241 00242 // since there's no space on the current SegAllocNode, indicate 00243 // that we haven't allocated any pages from its extents 00244 undoSegAllocPageWrite(origSegAllocPageId); 00245 00246 // Have to allocate a whole new SegAllocNode. The parameters to 00247 // makePageNum request enough space to fit the first extent of a new 00248 // SegAllocNode. 00249 if (!DelegatingSegment::ensureAllocatedSize( 00250 makePageNum(extentNum + 1,0))) 00251 { 00252 // couldn't grow 00253 return NULL_PAGE_ID; 00254 } 00255 00256 SegAllocLock newSegAllocLock(segAccessor); 00257 origSegAllocPageId = getSegAllocPageId(iSegAlloc + 1); 00258 segAllocPageId = getSegAllocPageIdForWrite(origSegAllocPageId); 00259 newSegAllocLock.lockExclusive(segAllocPageId); 00260 newSegAllocLock.setMagicNumber(); 00261 SegmentAllocationNode &newNode = newSegAllocLock.getNodeForWrite(); 00262 newNode.nPagesPerExtent = nPagesPerExtent; 00263 newNode.nExtents = 0; 00264 newNode.nextSegAllocPageId = NULL_PAGE_ID; 00265 // increment for the segment allocation node 00266 incrementPagesOccupiedCounter(); 00267 00268 // acquire a writable node to update the next page pointer 00269 SegmentAllocationNode &writableSegAllocNode = 00270 segAllocLock.getNodeForWrite(); 00271 writableSegAllocNode.nextSegAllocPageId = origSegAllocPageId; 00272 00273 // Carry on with the loop. We'll unlock and relock the node just 00274 // allocated, but that's not a big deal since allocating a new 00275 // SegAllocNode is very rare. 00276 } 00277 }
PageId RandomAllocationSegmentBase::allocateFromExtentTemplate | ( | ExtentNum | extentNum, | |
PageOwnerId | ownerId, | |||
SharedSegment | allocNodeSegment | |||
) | [protected, inherited] |
Allocates a new page from an extent known to have space.
The extent is specified by the absolute extent number and the segment where the extent allocation node originates from.
This template method allows the caller to specify different extent allocation node types.
extentNum | absolute 0-based extent number from which to allocate | |
ownerId | PageOwnerId of owning object | |
allocNodeSegment | segment that the allocation node page originates from |
Definition at line 127 of file RandomAllocationSegmentBaseImpl.h.
References RandomAllocationSegmentBase::getExtAllocPageIdForWrite(), Segment::pCache, and UNALLOCATED_PAGE_OWNER_ID.
Referenced by allocateFromExtent(), and RandomAllocationSegment::allocateFromExtent().
00131 { 00132 permAssert(ownerId != UNALLOCATED_PAGE_OWNER_ID); 00133 00134 SegmentAccessor segAccessor(allocNodeSegment, pCache); 00135 ExtentAllocLockT extentAllocLock(segAccessor); 00136 extentAllocLock.lockExclusive(getExtAllocPageIdForWrite(extentNum)); 00137 ExtentAllocationNodeT &node = extentAllocLock.getNodeForWrite(); 00138 return 00139 allocateFromLockedExtentTemplate<ExtentAllocationNodeT, PageEntryT>( 00140 node, 00141 extentNum, 00142 ownerId); 00143 }
PageId RandomAllocationSegmentBase::allocateFromNewExtentTemplate | ( | ExtentNum | extentNum, | |
PageOwnerId | ownerId, | |||
SharedSegment | allocNodeSegment | |||
) | [protected, inherited] |
Allocates a page from a new extent allocation node.
The extent is specified by the absolute extent number and the segment where the extent allocation node originates from.
This template method allows the caller to specify different extent allocation node types.
extentNum | absolute 0-based extent number from which to allocate | |
ownerId | PageOwnerId of owning object | |
allocNodeSegment | segment that the allocation node page originates from |
Definition at line 183 of file RandomAllocationSegmentBaseImpl.h.
References RandomAllocationSegmentBase::getExtAllocPageIdForWrite(), and Segment::pCache.
Referenced by allocateFromNewExtent(), and RandomAllocationSegment::allocateFromNewExtent().
00187 { 00188 SegmentAccessor segAccessor(allocNodeSegment, pCache); 00189 ExtentAllocLockT extentAllocLock(segAccessor); 00190 extentAllocLock.lockExclusive(getExtAllocPageIdForWrite(extentNum)); 00191 extentAllocLock.setMagicNumber(); 00192 ExtentAllocationNodeT &extentNode = extentAllocLock.getNodeForWrite(); 00193 formatExtentTemplate<ExtentAllocationNodeT, ExtentAllocLockT, PageEntryT>( 00194 extentNode); 00195 return 00196 allocateFromLockedExtentTemplate<ExtentAllocationNodeT, PageEntryT>( 00197 extentNode, 00198 extentNum, 00199 ownerId); 00200 }
PageId RandomAllocationSegmentBase::allocateFromLockedExtentTemplate | ( | ExtentAllocationNodeT & | extentNode, | |
ExtentNum | extentNum, | |||
PageOwnerId | ownerId | |||
) | [protected, inherited] |
Allocates a new page from an extent known to have space, with the extent allocation node already locked.
This template method allows the caller to specify different extent allocation node types.
[in] | extentNode | locked extent allocation node corresponding to extentNum |
extentNum | absolute extent number from which to allocate | |
ownerId | PageOwnerId of owning object |
Definition at line 203 of file RandomAllocationSegmentBaseImpl.h.
References Segment::getLinearPageId(), RandomAllocationSegmentBase::makePageNum(), RandomAllocationSegmentBase::nPagesPerExtent, and UNALLOCATED_PAGE_OWNER_ID.
00205 { 00206 // find a free page 00207 for (uint i = 0; i < nPagesPerExtent; i++) { 00208 PageEntryT &pageEntry = node.getPageEntry(i); 00209 if (pageEntry.ownerId == UNALLOCATED_PAGE_OWNER_ID) { 00210 if (i == 0) { 00211 // entry 0 is the extent allocation node itself so it 00212 // should never be marked as unallocated 00213 permAssert(false); 00214 } 00215 pageEntry.ownerId = ownerId; 00216 PageId pageId = getLinearPageId(makePageNum(extentNum,i)); 00217 return pageId; 00218 } 00219 } 00220 00221 permAssert(false); 00222 }
void RandomAllocationSegmentBase::setPageSuccessorTemplate | ( | PageId | pageId, | |
PageId | successorId, | |||
SharedSegment | allocNodeSegment | |||
) | [protected, inherited] |
Sets the successor pageId for a page.
This template method allows the caller to specify different extent allocation node types.
pageId | pageId of the page whose successor will be set | |
successorId | successor pageId | |
allocNodeSegment | segment that the allocation node page originates from |
Definition at line 240 of file RandomAllocationSegmentBaseImpl.h.
References RandomAllocationSegmentBase::getExtAllocPageIdForWrite(), RandomAllocationSegmentBase::isPageIdAllocated(), NULL_PAGE_ID, Segment::pCache, and RandomAllocationSegmentBase::splitPageId().
Referenced by setPageSuccessor().
00244 { 00245 assert(isPageIdAllocated(pageId)); 00246 assert((successorId == NULL_PAGE_ID) || isPageIdAllocated(successorId)); 00247 00248 uint iSegAlloc; 00249 ExtentNum extentNum; 00250 BlockNum iPageInExtent; 00251 splitPageId(pageId, iSegAlloc, extentNum, iPageInExtent); 00252 permAssert(iPageInExtent); 00253 00254 SegmentAccessor segAccessor(allocNodeSegment, pCache); 00255 ExtentAllocLockT extentAllocLock(segAccessor); 00256 extentAllocLock.lockExclusive(getExtAllocPageIdForWrite(extentNum)); 00257 ExtentAllocationNodeT &node = extentAllocLock.getNodeForWrite(); 00258 node.getPageEntry(iPageInExtent).successorId = successorId; 00259 }
void RandomAllocationSegmentBase::getPageEntryCopyTemplate | ( | PageId | pageId, | |
PageEntryT & | pageEntryCopy, | |||
bool | isAllocated, | |||
bool | thisSegment | |||
) | [protected, inherited] |
Retrieves a copy of the page entry for a specified page.
This template method allows the caller to specify different extent allocation node and page entry types.
pageId | pageId of the page whose page entry data we are retrieving | |
[out] | pageEntryCopy | copy of page entry retrieved |
isAllocated | if true, assert that the page is allocated | |
thisSegment | if true, retrieve page entry from this segment; otherwise, retrieve it from an alternative segment |
Definition at line 273 of file RandomAllocationSegmentBaseImpl.h.
References RandomAllocationSegmentBase::getExtAllocPageIdForRead(), RandomAllocationSegmentBase::getExtentAllocPageId(), Segment::getTracingSegment(), Segment::pCache, RandomAllocationSegmentBase::splitPageId(), and RandomAllocationSegmentBase::testPageId().
Referenced by getPageEntryCopy().
00278 { 00279 if (isAllocated) { 00280 assert(testPageId(pageId, true, thisSegment)); 00281 } 00282 00283 ExtentNum extentNum; 00284 BlockNum iPageInExtent; 00285 uint iSegAlloc; 00286 splitPageId(pageId, iSegAlloc, extentNum, iPageInExtent); 00287 assert(iPageInExtent); 00288 00289 SharedSegment allocNodeSegment; 00290 PageId extentPageId; 00291 if (thisSegment) { 00292 allocNodeSegment = getTracingSegment(); 00293 extentPageId = getExtentAllocPageId(extentNum); 00294 } else { 00295 extentPageId = getExtAllocPageIdForRead(extentNum, allocNodeSegment); 00296 } 00297 00298 SegmentAccessor segAccessor(allocNodeSegment, pCache); 00299 ExtentAllocLockT extentAllocLock(segAccessor); 00300 extentAllocLock.lockShared(extentPageId); 00301 ExtentAllocationNodeT const &extentNode = 00302 extentAllocLock.getNodeForRead(); 00303 00304 PageEntryT const &pageEntry = 00305 extentNode.getPageEntry(iPageInExtent); 00306 00307 pageEntryCopy = pageEntry; 00308 }
BlockId RandomAllocationSegmentBase::translatePageId | ( | PageId | ) | [virtual, inherited] |
Maps from a PageId in this segment to a BlockId.
Reimplemented from DelegatingSegment.
Definition at line 377 of file RandomAllocationSegmentBase.cpp.
References RandomAllocationSegmentBase::isPageIdValid(), and DelegatingSegment::translatePageId().
Referenced by locateDataPages(), and restoreFromBackup().
00378 { 00379 assert( 00380 const_cast<RandomAllocationSegmentBase *>(this)->isPageIdValid(pageId)); 00381 00382 return DelegatingSegment::translatePageId(pageId); 00383 }
Segment::AllocationOrder RandomAllocationSegmentBase::getAllocationOrder | ( | ) | const [virtual, inherited] |
Reimplemented from DelegatingSegment.
Definition at line 372 of file RandomAllocationSegmentBase.cpp.
References Segment::RANDOM_ALLOCATION.
00373 { 00374 return RANDOM_ALLOCATION; 00375 }
BlockNum RandomAllocationSegmentBase::getAllocatedSizeInPages | ( | ) | [virtual, inherited] |
Reimplemented from DelegatingSegment.
Definition at line 422 of file RandomAllocationSegmentBase.cpp.
References RandomAllocationSegmentBase::nPagesAllocated.
Referenced by SnapshotSegmentTest::deallocateOldPages().
00423 { 00424 return nPagesAllocated; 00425 }
BlockNum RandomAllocationSegmentBase::getNumPagesOccupiedHighWater | ( | ) | [virtual, inherited] |
Returns the max number of pages occupied by this segment instance.
In other words, pages that are allocated but subsequently deallocated, are included in this count. Also, the count includes all pages used by the segment, including metadata pages.
Reimplemented from DelegatingSegment.
Definition at line 448 of file RandomAllocationSegmentBase.cpp.
References RandomAllocationSegmentBase::nPagesOccupiedHighWater.
00449 { 00450 return nPagesOccupiedHighWater; 00451 }
SharedSegment const& DelegatingSegment::getDelegateSegment | ( | ) | const [inline, inherited] |
Definition at line 53 of file DelegatingSegment.h.
Referenced by SegmentFactory::dynamicCast(), TracingSegment::getMappedPageListener(), TracingSegment::isWriteVersioned(), and TracingSegment::notifyAfterPageCheckpointFlush().
00054 { 00055 return pDelegateSegment; 00056 }
BlockNum DelegatingSegment::getNumPagesExtended | ( | ) | [virtual, inherited] |
Implements Segment.
Definition at line 57 of file DelegatingSegment.cpp.
References DelegatingSegment::pDelegateSegment.
00058 { 00059 return pDelegateSegment->getNumPagesExtended(); 00060 }
PageId DelegatingSegment::translateBlockId | ( | BlockId | ) | [virtual, inherited] |
Maps from a BlockId to a PageId in this segment.
Implements Segment.
Reimplemented in CircularSegment, LinearViewSegment, and TracingSegment.
Definition at line 77 of file DelegatingSegment.cpp.
References DelegatingSegment::pDelegateSegment.
Referenced by VersionedSegment::canFlushPage(), SnapshotRandomAllocationSegment::getMappedPageListener(), WALSegment::notifyAfterPageFlush(), WALSegment::notifyPageDirty(), VersionedSegment::notifyPageDirty(), TracingSegment::translateBlockId(), LinearViewSegment::translateBlockId(), and CircularSegment::translateBlockId().
00078 { 00079 return pDelegateSegment->translateBlockId(blockId); 00080 }
bool DelegatingSegment::ensureAllocatedSize | ( | BlockNum | nPages | ) | [virtual, inherited] |
Allocates pages as needed to make getAllocatedSizeInPages() meet a lower bound.
The PageId's of the allocated pages are not returned, so this is mostly only meaningful for linear segments.
nPages | lower bound for getAllocatedSizeInPages() |
Reimplemented from Segment.
Reimplemented in TracingSegment.
Definition at line 87 of file DelegatingSegment.cpp.
References DelegatingSegment::pDelegateSegment.
Referenced by RandomAllocationSegmentBase::allocatePageIdFromSegment(), TracingSegment::ensureAllocatedSize(), RandomAllocationSegmentBase::format(), and restoreFromBackup().
00088 { 00089 return pDelegateSegment->ensureAllocatedSize(nPages); 00090 }
void DelegatingSegment::delegatedCheckpoint | ( | Segment & | delegatingSegment, | |
CheckpointType | checkpointType | |||
) | [virtual, inherited] |
Helper for DelegatingSegment.
delegatingSegment | the Segment on which checkpoint was originally called | |
checkpointType | type of checkpoint requested |
Reimplemented from Segment.
Reimplemented in SnapshotRandomAllocationSegment, TracingSegment, and VersionedSegment.
Definition at line 142 of file DelegatingSegment.cpp.
References DelegatingSegment::pDelegateSegment.
Referenced by VersionedSegment::delegatedCheckpoint(), and TracingSegment::delegatedCheckpoint().
00144 { 00145 pDelegateSegment->delegatedCheckpoint(delegatingSegment,checkpointType); 00146 }
PageId DelegatingSegment::updatePage | ( | PageId | pageId, | |
bool | needsTranslation = false | |||
) | [virtual, inherited] |
Determines whether a page can be updated in-place, and if so, prepares the page for update.
pageId | pageId of the page being modified | |
needsTranslation | true if the pageId needs to be mapped to the appropriate update page; defaults to false |
Reimplemented from Segment.
Reimplemented in LinearViewSegment, and SnapshotRandomAllocationSegment.
Definition at line 148 of file DelegatingSegment.cpp.
References DelegatingSegment::pDelegateSegment.
Referenced by LinearViewSegment::updatePage().
00149 { 00150 return pDelegateSegment->updatePage(pageId, needsTranslation); 00151 }
void DelegatingSegment::notifyPageMap | ( | CachePage & | page | ) | [virtual, inherited] |
Receives notification from CacheImpl as soon as a page is mapped, before any I/O is initiated to retrieve the page contents.
Called with the page mutex held, so the implementation must take care to avoid deadlock.
page | the page being mapped |
Reimplemented from MappedPageListener.
Reimplemented in TracingSegment.
Definition at line 107 of file DelegatingSegment.cpp.
References DelegatingSegment::pDelegateSegment.
Referenced by TracingSegment::notifyPageMap().
00108 { 00109 pDelegateSegment->notifyPageMap(page); 00110 }
void DelegatingSegment::notifyPageUnmap | ( | CachePage & | page | ) | [virtual, inherited] |
Receives notification from CacheImpl just before a page is unmapped.
Called with the page mutex held, so the implementation must take care to avoid deadlock.
page | the page being unmapped |
Reimplemented from MappedPageListener.
Reimplemented in TracingSegment, and WALSegment.
Definition at line 112 of file DelegatingSegment.cpp.
References DelegatingSegment::pDelegateSegment.
Referenced by TracingSegment::notifyPageUnmap().
00113 { 00114 pDelegateSegment->notifyPageUnmap(page); 00115 }
void DelegatingSegment::notifyAfterPageRead | ( | CachePage & | page | ) | [virtual, inherited] |
Receives notification from CacheImpl after a page read completes.
Called with the page mutex held, so the implementation must take care to avoid deadlock.
page | the page read |
Reimplemented from MappedPageListener.
Reimplemented in TracingSegment.
Definition at line 117 of file DelegatingSegment.cpp.
References DelegatingSegment::pDelegateSegment.
Referenced by TracingSegment::notifyAfterPageRead().
00118 { 00119 pDelegateSegment->notifyAfterPageRead(page); 00120 }
void DelegatingSegment::notifyPageDirty | ( | CachePage & | page, | |
bool | bDataValid | |||
) | [virtual, inherited] |
Receives notification from CacheImpl the first time a page becomes dirty after it has been mapped (but before the contents have changed).
Allows some logging action to be taken; for example, making a backup copy of the unmodified page contents. Note that when called for a newly allocated page, the page contents are invalid. Because it is implied that the calling thread already has an exclusive lock on the page, no cache locks are held when called.
page | the page being modified | |
bDataValid | if true, the page data was already valid; if false, the data was invalid, but has now been marked valid since it's about to be written |
Reimplemented from MappedPageListener.
Reimplemented in SnapshotRandomAllocationSegment, TracingSegment, VersionedSegment, and WALSegment.
Definition at line 122 of file DelegatingSegment.cpp.
References DelegatingSegment::pDelegateSegment.
Referenced by WALSegment::notifyPageDirty(), VersionedSegment::notifyPageDirty(), TracingSegment::notifyPageDirty(), and SnapshotRandomAllocationSegment::notifyPageDirty().
00123 { 00124 pDelegateSegment->notifyPageDirty(page,bDataValid); 00125 }
void DelegatingSegment::notifyBeforePageFlush | ( | CachePage & | page | ) | [virtual, inherited] |
Receives notification from CacheImpl just before a dirty page is flushed to disk.
Allows some logging action to be taken; for example, flushing corresponding write-ahead log pages, or storing a checksum in the page header. Called with the page mutex held, so the implementation must take care to avoid deadlock.
page | the page to be flushed |
Reimplemented from MappedPageListener.
Reimplemented in TracingSegment.
Definition at line 127 of file DelegatingSegment.cpp.
References DelegatingSegment::pDelegateSegment.
Referenced by TracingSegment::notifyBeforePageFlush().
00128 { 00129 pDelegateSegment->notifyBeforePageFlush(page); 00130 }
void DelegatingSegment::notifyAfterPageFlush | ( | CachePage & | page | ) | [virtual, inherited] |
Receives notification from CacheImpl when a page flush completes successfully.
Called with the page mutex held, so the implementation must take care to avoid deadlock.
page | the page that was flushed |
Reimplemented from MappedPageListener.
Reimplemented in TracingSegment, and WALSegment.
Definition at line 132 of file DelegatingSegment.cpp.
References DelegatingSegment::pDelegateSegment.
Referenced by WALSegment::notifyAfterPageFlush(), and TracingSegment::notifyAfterPageFlush().
00133 { 00134 pDelegateSegment->notifyAfterPageFlush(page); 00135 }
bool DelegatingSegment::canFlushPage | ( | CachePage & | page | ) | [virtual, inherited] |
Informs CacheImpl whether a dirty page can safely be flushed to disk.
Called with the page mutex held, so the implementation must take care to avoid deadlock.
page | the page to be flushed |
Reimplemented from MappedPageListener.
Reimplemented in SnapshotRandomAllocationSegment, and VersionedSegment.
Definition at line 137 of file DelegatingSegment.cpp.
References DelegatingSegment::pDelegateSegment.
Referenced by VersionedSegment::canFlushPage().
00138 { 00139 return pDelegateSegment->canFlushPage(page); 00140 }
void Segment::setUsablePageSize | ( | uint | ) | [protected, inherited] |
Definition at line 70 of file Segment.cpp.
References Segment::cbUsablePerPage.
Referenced by DelegatingSegment::DelegatingSegment(), DynamicDelegatingSegment::DynamicDelegatingSegment(), Segment::Segment(), and VersionedSegment::VersionedSegment().
00071 { 00072 cbUsablePerPage = cb; 00073 }
PConstBuffer Segment::getReadableFooter | ( | CachePage & | page | ) | [protected, inherited] |
Definition at line 75 of file Segment.cpp.
References CachePage::getReadableData(), and Segment::getUsablePageSize().
Referenced by VersionedSegment::getPageVersion(), and VersionedSegment::recover().
00076 { 00077 return page.getReadableData() + getUsablePageSize(); 00078 }
Definition at line 80 of file Segment.cpp.
References Segment::getUsablePageSize(), and CachePage::getWritableData().
Referenced by VersionedSegment::notifyPageDirty().
00081 { 00082 return page.getWritableData() + getUsablePageSize(); 00083 }
PageId Segment::getLinearPageSuccessor | ( | PageId | pageId | ) | [protected, inherited] |
An implementation of getPageSuccessor suitable for LINEAR_ALLOCATION.
Definition at line 85 of file Segment.cpp.
References Segment::isPageIdAllocated(), and NULL_PAGE_ID.
Referenced by ScratchSegment::getPageSuccessor(), LinearViewSegment::getPageSuccessor(), LinearDeviceSegment::getPageSuccessor(), and CircularSegment::getPageSuccessor().
00086 { 00087 assert(isPageIdAllocated(pageId)); 00088 ++pageId; 00089 if (!isPageIdAllocated(pageId)) { 00090 return NULL_PAGE_ID; 00091 } 00092 return pageId; 00093 }
void Segment::setLinearPageSuccessor | ( | PageId | pageId, | |
PageId | successorId | |||
) | [protected, inherited] |
An implementation of setPageSuccessor suitable for LINEAR_ALLOCATION.
Definition at line 95 of file Segment.cpp.
References Segment::getLinearBlockNum(), and Segment::isPageIdAllocated().
Referenced by ScratchSegment::setPageSuccessor(), LinearViewSegment::setPageSuccessor(), LinearDeviceSegment::setPageSuccessor(), and CircularSegment::setPageSuccessor().
00096 { 00097 assert(isPageIdAllocated(pageId)); 00098 assert(isPageIdAllocated(successorId)); 00099 assert(getLinearBlockNum(successorId) 00100 == getLinearBlockNum(pageId) + 1); 00101 }
bool Segment::isLinearPageIdAllocated | ( | PageId | pageId | ) | [protected, inherited] |
An implementation of isPageIdAllocated suitable for LINEAR_ALLOCATION when deallocation holes are disallowed.
Definition at line 103 of file Segment.cpp.
References Segment::getAllocatedSizeInPages(), and Segment::getLinearBlockNum().
Referenced by ScratchSegment::isPageIdAllocated(), LinearViewSegment::isPageIdAllocated(), and LinearDeviceSegment::isPageIdAllocated().
00104 { 00105 if (getLinearBlockNum(pageId) >= getAllocatedSizeInPages()) { 00106 return false; 00107 } 00108 return true; 00109 }
SharedCache Segment::getCache | ( | ) | const [inline, inherited] |
Definition at line 358 of file Segment.h.
References Segment::pCache.
Referenced by ScratchSegment::getCache(), and TempSegDestructor::operator()().
00359 { 00360 return pCache; 00361 }
uint Segment::getFullPageSize | ( | ) | const [inherited] |
Definition at line 133 of file Segment.cpp.
References Segment::pCache.
Referenced by LinearDeviceSegment::ensureAllocatedSize(), LinearDeviceSegment::getAvailableDevicePages(), LinearDeviceSegment::LinearDeviceSegment(), locateDataPages(), VersionedSegment::recover(), Segment::Segment(), and SegPageLock::swapBuffers().
00134 { 00135 return pCache->getPageSize(); 00136 }
uint Segment::getUsablePageSize | ( | ) | const [inline, inherited] |
Definition at line 363 of file Segment.h.
References Segment::cbUsablePerPage.
Referenced by VersionedSegment::computeChecksum(), DynamicDelegatingSegment::DynamicDelegatingSegment(), Segment::getReadableFooter(), Segment::getWritableFooter(), VersionedSegment::notifyPageDirty(), RandomAllocationSegment::RandomAllocationSegment(), RandomAllocationSegmentBase::RandomAllocationSegmentBase(), SegPageLock::swapBuffers(), VersionedRandomAllocationSegment(), and VersionedSegment::VersionedSegment().
00364 { 00365 return cbUsablePerPage; 00366 }
SharedSegment Segment::getTracingSegment | ( | ) | [inherited] |
Definition at line 50 of file Segment.cpp.
References Segment::pTracingSegment.
Referenced by allocateAllocNodes(), RandomAllocationSegment::allocateFromExtent(), RandomAllocationSegment::allocateFromNewExtent(), RandomAllocationSegment::allocatePageId(), backupAllocationNodes(), chainPageEntries(), SnapshotRandomAllocationSegment::commitChanges(), copyPageEntryFromTemp(), copyPageEntryToTemp(), RandomAllocationSegmentBase::deallocatePageId(), findAllocPageIdForRead(), RandomAllocationSegmentBase::format(), RandomAllocationSegmentBase::formatPageExtentsTemplate(), RandomAllocationSegmentBase::freePageEntryTemplate(), RandomAllocationSegment::getExtAllocPageIdForRead(), getOldestTxnId(), getOldPageIds(), RandomAllocationSegmentBase::getPageEntryCopyTemplate(), RandomAllocationSegment::getSegAllocPageIdForRead(), getTempAllocNodePage(), Segment::getTracingListener(), locateDataPages(), restoreFromBackup(), SnapshotRandomAllocationSegment::rollbackChanges(), RandomAllocationSegment::setPageSuccessor(), updateExtentEntry(), and validateFreePageCount().
00051 { 00052 SharedSegment sharedPtr = pTracingSegment.lock(); 00053 if (sharedPtr && sharedPtr.get()) { 00054 return sharedPtr; 00055 } else { 00056 return shared_from_this(); 00057 } 00058 }
void Segment::setTracingSegment | ( | WeakSegment | pTracingSegmentInit | ) | [inherited] |
Sets the tracing segment associated with this segment.
pTracingSegmentInit | the tracing segment |
Definition at line 60 of file Segment.cpp.
References Segment::pTracingSegment.
00061 { 00062 pTracingSegment = pTracingSegmentInit; 00063 }
void Segment::checkpoint | ( | CheckpointType | checkpointType = CHECKPOINT_FLUSH_ALL |
) | [inherited] |
Checkpoints this segment.
checkpointType | type of checkpoint to execute |
Definition at line 111 of file Segment.cpp.
References Segment::delegatedCheckpoint(), and Segment::pTracingSegment.
Referenced by Segment::closeImpl(), BackupRestoreTest::createSnapshotData(), BackupRestoreTest::executeSnapshotTxn(), and LcsClusterReplaceExecStreamTest::testClusterReplace().
00112 { 00113 // Note that we can't use getTracingSegment() here because that method 00114 // references the shared ptr associated with this segment, and the 00115 // shared segment may have already been freed during shutdown by the 00116 // time this method is called. 00117 SharedSegment sharedPtr = pTracingSegment.lock(); 00118 if (sharedPtr && sharedPtr.get()) { 00119 delegatedCheckpoint(*(sharedPtr.get()),checkpointType); 00120 } else { 00121 delegatedCheckpoint(*this,checkpointType); 00122 } 00123 }
MappedPageListener * Segment::getMappedPageListener | ( | BlockId | blockId | ) | [virtual, inherited] |
Returns the mapped page listener corresponding to a page.
blockId | blockId of the page whose page listener we are returning |
Reimplemented in DynamicDelegatingSegment, SnapshotRandomAllocationSegment, and TracingSegment.
Definition at line 153 of file Segment.cpp.
bool Segment::isWriteVersioned | ( | ) | [virtual, inherited] |
Reimplemented in DynamicDelegatingSegment, SnapshotRandomAllocationSegment, and TracingSegment.
Definition at line 158 of file Segment.cpp.
PageId Segment::getLinearPageId | ( | BlockNum | iPage | ) | [inline, static, inherited] |
Constructs a linear PageId based on a linear page number.
Definition at line 348 of file Segment.h.
Referenced by RandomAllocationSegmentBase::allocateFromLockedExtentTemplate(), ScratchSegment::allocatePageId(), LinearViewSegment::allocatePageId(), LinearDeviceSegment::allocatePageId(), CircularSegment::allocatePageId(), RandomAllocationSegmentBase::getExtentAllocPageId(), getOldPageIds(), RandomAllocationSegmentBase::getSegAllocPageId(), Database::init(), locateDataPages(), SegmentTestBase::lockPage(), SegmentTestBase::prefetchPage(), SegPageIterTest::testBoundedIter(), SegPageEntryIterTest::testBoundedIter(), ScratchSegment::translateBlockId(), LinearViewSegment::translateBlockId(), LinearDeviceSegment::translateBlockId(), CircularSegment::translateBlockId(), and CircularSegment::translatePageId().
BlockNum Segment::getLinearBlockNum | ( | PageId | pageId | ) | [inline, static, inherited] |
Obtains the linear page number from a linear PageId.
Definition at line 353 of file Segment.h.
References opaqueToInt().
Referenced by CircularSegment::CircularSegment(), LinearDeviceSegment::deallocatePageRange(), CircularSegment::deallocatePageRange(), Segment::isLinearPageIdAllocated(), CircularSegment::isPageIdAllocated(), SegmentTestBase::lockPage(), SegInputStream::readPrevBuffer(), Segment::setLinearPageSuccessor(), RandomAllocationSegmentBase::splitPageId(), CircularSegment::translateBlockId(), ScratchSegment::translatePageId(), LinearViewSegment::translatePageId(), LinearDeviceSegment::translatePageId(), CircularSegment::translatePageId(), and LinearViewSegment::updatePage().
00354 { 00355 return opaqueToInt(pageId); 00356 }
MappedPageListener * Segment::getTracingListener | ( | ) | [virtual, inherited] |
Retrieves the tracing wrapper corresponding to this listener if tracing is turned on.
Otherwise, returns this listener itself.
Implements MappedPageListener.
Definition at line 65 of file Segment.cpp.
References Segment::getTracingSegment().
00066 { 00067 return getTracingSegment().get(); 00068 }
MappedPageListener * MappedPageListener::notifyAfterPageCheckpointFlush | ( | CachePage & | page | ) | [virtual, inherited] |
Receives notification that a page has been flushed during a checkpoint.
Also determines if the listener on the page needs to be reset.
Note that if the page listener is reset, that page may not be unmapped during a CHECKPOINT_FLUSH_AND_UNMAP checkpoint call.
This method should be called immediately after the page flush has completed while the checkpoint is still in progress.
page | the page that was flushed |
Reimplemented in SnapshotRandomAllocationSegment, and TracingSegment.
Definition at line 62 of file MappedPageListener.cpp.
bool ClosableObject::isClosed | ( | ) | const [inline, inherited] |
Definition at line 58 of file ClosableObject.h.
00059 { 00060 return !needsClose; 00061 }
void ClosableObject::close | ( | ) | [inherited] |
Closes this object, releasing any unallocated resources.
Reimplemented in CollectExecStream, CorrelationJoinExecStream, LcsClusterAppendExecStream, and LcsClusterReplaceExecStream.
Definition at line 39 of file ClosableObject.cpp.
References ClosableObject::closeImpl(), and ClosableObject::needsClose.
Referenced by CacheImpl< PageT, VictimPolicyT >::allocatePages(), LcsRowScanBaseExecStream::closeImpl(), ExecStreamGraphImpl::closeImpl(), FlatFileBuffer::open(), ClosableObjectDestructor::operator()(), and Segment::~Segment().
00040 { 00041 if (!needsClose) { 00042 return; 00043 } 00044 needsClose = false; 00045 closeImpl(); 00046 }
friend class SegmentFactory [friend, inherited] |
Definition at line 140 of file RandomAllocationSegmentBase.h.
Maps allocation node pages to the modified copy of the node that contains uncommitted page modifications.
Definition at line 150 of file VersionedRandomAllocationSegment.h.
Referenced by deallocateSinglePage(), findAllocPageIdForRead(), freeTempPage(), freeTempPages(), getTempAllocNodePage(), uncommittedDeallocation(), undoSegAllocPageWrite(), updateAllocNodes(), updateExtentEntry(), updatePageEntry(), and updateTempPageEntry().
Mutex used to protect allocationNodeMap.
Multiple readers are allowed but only a single writer.
In the case where both mapMutex and deallocationMutex need to be acquired, acquire deallocationMutex first.
Definition at line 159 of file VersionedRandomAllocationSegment.h.
Referenced by deallocateOldPages(), deallocateSinglePage(), findAllocPageIdForRead(), freeTempPage(), freeTempPages(), getPageEntryCopy(), getTempAllocNodePage(), initForUse(), uncommittedDeallocation(), undoSegAllocPageWrite(), updateAllocNodes(), updateExtentEntry(), updatePageEntry(), and updateTempPageEntry().
Mutex that prevents multiple deallocations from occuring concurrently.
In the case where both mapMutex and deallocationMutex need to be acquired, acquire deallocationMutex first.
Definition at line 167 of file VersionedRandomAllocationSegment.h.
Referenced by deallocateOldPages(), deallocatePageRange(), and getDeallocationMutex().
Segment used to allocate pages to store uncommitted modifications to segment and extent allocation node pages.
Definition at line 173 of file VersionedRandomAllocationSegment.h.
Referenced by allocateFromExtent(), allocateFromNewExtent(), allocatePageId(), chainPageEntries(), copyPageEntryFromTemp(), copyPageEntryToTemp(), deallocateSinglePage(), deferDeallocation(), findAllocPageIdForRead(), freeTempPage(), getTempAllocNodePage(), initPageEntry(), setPageSuccessor(), uncommittedDeallocation(), updateExtentEntry(), updateTempPageEntry(), and VersionedRandomAllocationSegment().
BlockNum RandomAllocationSegmentBase::nPagesPerExtent [protected, inherited] |
Number of pages in one extent, including the extent allocation node itself (so actual data capacity per extent is one less).
This is immutable.
Definition at line 147 of file RandomAllocationSegmentBase.h.
Referenced by allocateAllocNodes(), RandomAllocationSegmentBase::allocateFromLockedExtentTemplate(), RandomAllocationSegmentBase::allocatePageIdFromSegment(), backupAllocationNodes(), RandomAllocationSegmentBase::deallocatePageId(), RandomAllocationSegmentBase::format(), RandomAllocationSegmentBase::formatExtentTemplate(), RandomAllocationSegmentBase::formatPageExtentsTemplate(), getOldPageIds(), locateDataPages(), RandomAllocationSegmentBase::makePageNum(), RandomAllocationSegment::RandomAllocationSegment(), restoreFromBackup(), RandomAllocationSegmentBase::splitPageId(), RandomAllocationSegmentBase::tallySegAllocNodePages(), validateFreePageCount(), and VersionedRandomAllocationSegment().
BlockNum RandomAllocationSegmentBase::nPagesPerSegAlloc [protected, inherited] |
Number of pages mapped by one SegmentAllocationNode, including the SegmentAllocationNode itself.
This is immutable.
Definition at line 153 of file RandomAllocationSegmentBase.h.
Referenced by RandomAllocationSegmentBase::getSegAllocPageId(), RandomAllocationSegmentBase::inferSegAllocCount(), RandomAllocationSegment::RandomAllocationSegment(), RandomAllocationSegmentBase::splitPageId(), and VersionedRandomAllocationSegment().
ExtentNum RandomAllocationSegmentBase::nExtentsPerSegAlloc [protected, inherited] |
Number of extents mapped by a full SegmentAllocationNode.
This is immutable.
Definition at line 159 of file RandomAllocationSegmentBase.h.
Referenced by allocateExtAllocNodes(), RandomAllocationSegmentBase::allocatePageIdFromSegment(), backupAllocationNodes(), RandomAllocationSegmentBase::deallocatePageId(), deallocateSinglePage(), RandomAllocationSegmentBase::format(), RandomAllocationSegmentBase::formatPageExtentsTemplate(), getOldPageIds(), locateDataPages(), RandomAllocationSegmentBase::makePageNum(), RandomAllocationSegment::RandomAllocationSegment(), RandomAllocationSegmentBase::RandomAllocationSegmentBase(), restoreFromBackup(), RandomAllocationSegmentBase::splitPageId(), updateExtentEntry(), validateFreePageCount(), and VersionedRandomAllocationSegment().
SharedCache Segment::pCache [protected, inherited] |
Cache managing pages of this segment.
Definition at line 62 of file Segment.h.
Referenced by allocateAllocNodes(), RandomAllocationSegmentBase::allocateFromExtentTemplate(), RandomAllocationSegmentBase::allocateFromNewExtentTemplate(), RandomAllocationSegmentBase::allocatePageIdFromSegment(), backupAllocationNodes(), chainPageEntries(), copyPageEntryFromTemp(), copyPageEntryToTemp(), RandomAllocationSegmentBase::deallocatePageId(), deallocateSinglePage(), deferDeallocation(), VersionedSegment::delegatedCheckpoint(), SnapshotRandomAllocationSegment::delegatedCheckpoint(), Segment::delegatedCheckpoint(), RandomAllocationSegmentBase::format(), RandomAllocationSegmentBase::formatPageExtentsTemplate(), RandomAllocationSegmentBase::freePageEntryTemplate(), Segment::getCache(), Segment::getFullPageSize(), getOldestTxnId(), getOldPageIds(), RandomAllocationSegmentBase::getPageEntryCopyTemplate(), getTempAllocNodePage(), initPageEntry(), locateDataPages(), VersionedSegment::notifyPageDirty(), VersionedSegment::recover(), restoreFromBackup(), RandomAllocationSegmentBase::setPageSuccessorTemplate(), RandomAllocationSegmentBase::tallySegAllocNodePages(), uncommittedDeallocation(), updateExtentEntry(), updatePageEntry(), updateTempPageEntry(), and validateFreePageCount().
WeakSegment Segment::pTracingSegment [protected, inherited] |
The tracing segment associated with this segment, if tracing is turned on.
A weak_ptr is used due to the circular shared pointers between this segment and its tracing segment.
Definition at line 69 of file Segment.h.
Referenced by Segment::checkpoint(), Segment::getTracingSegment(), and Segment::setTracingSegment().
bool ClosableObject::needsClose [protected, inherited] |
Definition at line 44 of file ClosableObject.h.
Referenced by SegStreamAllocation::beginWrite(), ExecStreamGraphImpl::clear(), ClosableObject::ClosableObject(), ClosableObject::close(), FlatFileBuffer::open(), ExecStreamGraphImpl::open(), ExecStream::open(), and ClosableObject::~ClosableObject().