VersionedRandomAllocationSegment Class Reference

VersionedRandomAllocationSegment refines RandomAllocationSegmentBase, defining a VersionedExtentAllocationNode where each page entry within the segment is versioned. More...

#include <VersionedRandomAllocationSegment.h>

Inheritance diagram for VersionedRandomAllocationSegment:

RandomAllocationSegmentBase DelegatingSegment Segment MappedPageListener ClosableObject List of all members.

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.
SXMutexgetDeallocationMutex ()
 
Returns:
the deallocation mutex that prevents reading of the page chain while deallocations are in progress

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
 
Returns:
the AllocationOrder for this segment

virtual BlockNum getAllocatedSizeInPages ()
 
Returns:
number of pages allocated from this segment

virtual BlockNum getNumPagesOccupiedHighWater ()
 Returns the max number of pages occupied by this segment instance.
SharedSegment const & getDelegateSegment () const
virtual BlockNum getNumPagesExtended ()
 
Returns:
the number of incremental pages added to this instance of the segment

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
 
Returns:
the Cache for this Segment

uint getFullPageSize () const
 
Returns:
the full size of pages stored in this segment; this is the same as the size of underlying cache pages

uint getUsablePageSize () const
 
Returns:
the full size of pages stored in this segment minus the size for any footer information stored at the end of each page

SharedSegment getTracingSegment ()
 
Returns:
tracing segment associated with this segment if tracing is turned on; otherwise, returns the segment itself

void setTracingSegment (WeakSegment pTracingSegmentInit)
 Sets the tracing segment associated with this segment.
void checkpoint (CheckpointType checkpointType=CHECKPOINT_FLUSH_ALL)
 Checkpoints this segment.
virtual MappedPageListenergetMappedPageListener (BlockId blockId)
 Returns the mapped page listener corresponding to a page.
virtual bool isWriteVersioned ()
 
Returns:
true if the segment supports versioning

virtual MappedPageListenergetTracingListener ()
 Retrieves the tracing wrapper corresponding to this listener if tracing is turned on.
virtual MappedPageListenernotifyAfterPageCheckpointFlush (CachePage &page)
 Receives notification that a page has been flushed during a checkpoint.
bool isClosed () const
 
Returns:
whether the object has been closed

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
 
Returns:
the PageId of the first SegmentAllocationNode

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

Detailed Description

VersionedRandomAllocationSegment refines RandomAllocationSegmentBase, defining a VersionedExtentAllocationNode where each page entry within the segment is versioned.

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.


Member Typedef Documentation

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]

Definition at line 56 of file Segment.h.

typedef PageMap::const_iterator Segment::PageMapConstIter [protected, inherited]

Definition at line 57 of file Segment.h.


Member Enumeration Documentation

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.

Enumerator:
RANDOM_ALLOCATION  Random order.
ASCENDING_ALLOCATION  Later calls always return greater PageIds, but not necessarily consecutively.
CONSECUTIVE_ALLOCATION  PageIds are returned in consecutive ascending order of BlockNum; the DeviceId is always the same.
LINEAR_ALLOCATION  PageIds are returned in consecutive ascending order starting with 0; all bytes of the PageId are used (no division into DeviceId/BlockNum), yielding maximum range.

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     };


Constructor & Destructor Documentation

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 }


Member Function Documentation

template<class AllocationLockT>
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.

Parameters:
origNodePageId pageId of the node in the permanent segment
isSegAllocNode true if the page being retrieved is a segment allocation node
Returns:
pageId of node in the temporary segment

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.

Parameters:
origAllocNodePageId pageId of the node in the permanent segment
[out] allocNodeSegment the temp segment if the node has been modified; otherwise, the segment itself
Returns:
the pageId of the node in the temp segment if the page has been modified; otherwise, the original pageId

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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
[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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
pageId pageId corresponding to the allocation nodes to be verified
Returns:
true if the counts match

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.

Parameters:
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.

Parameters:
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
Returns:
the txnId one larger than the commit sequence number on the oldest page that can be deallocated or NULL_TXN_ID if the page chain should be left as is (either because there's nothing to deallocate, or the page chain contains deallocation-deferred pages)

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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
anchorPageId the pageId of the anchor page in the chain
Returns:
always returns true

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.

Parameters:
anchorPageId pageId of the anchor page in a chain
[in,out] deallocatedPageSet set of pages that have been deallocated or need to be skipped
Returns:
true if the anchor page entry is marked as deallocation-deferred in its temporary page entry

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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
[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.

Parameters:
txnId the id of the txn that deallocated the page
Returns:
constructed pageOwnerId

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.

Parameters:
pageOwnerId the pageOwnerId under question
Returns:
true if the pageOwnerId corresponds to a deallocation-deferred page

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.

Parameters:
pageOwnerId the pageOwnerId of the deallocated page
Returns:
the txnId

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).

Parameters:
pageId the PageId to test
Returns:
true iff pageId is valid

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.

Parameters:
origSegAllocPageId original SegmentAllocationNode pageId
Returns:
pageId of the SegmentAllocationNode to be updated

Implements RandomAllocationSegmentBase.

Definition at line 73 of file VersionedRandomAllocationSegment.cpp.

00075 {
00076     return getTempAllocNodePage<SegAllocLock>(origSegAllocPageId, true);
00077 }

void VersionedRandomAllocationSegment::undoSegAllocPageWrite ( PageId  segAllocPageId  )  [private, virtual]

Indicates that no new pages were allocated from extents within a SegmentAllocationNode.

Parameters:
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.

Parameters:
extentNum absolute 0-based extent number
Returns:
pageId of the extent allocation to be updated

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.

See also:
allocateFromExtentTemplate()
Parameters:
extentNum absolute 0-based extent number from which to allocate
ownerId PageOwnerId of owning object
Returns:
allocated PageId

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.

See also:
formatPageExtentsTemplate()
Parameters:
[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.

See also:
allocateFromNewExtentTemplate()
Parameters:
extentNum absolute extent number from which to allocate
ownerId PageOwnerId of owning object
Returns:
allocated PageId

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.

See also:
freePageEntryTemplate()
Parameters:
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.

Parameters:
[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.

See also:
getPageOwnerIdTemplate()
Parameters:
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
Returns:
ownerId

Implements RandomAllocationSegmentBase.

Definition at line 271 of file VersionedRandomAllocationSegment.cpp.

00274 {
00275     return getPageOwnerIdTemplate<VersionedPageEntry>(pageId, thisSegment);
00276 }

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.

Parameters:
origSegAllocPageId original SegmentAllocationNode pageId
[out] allocNodeSegment segment from which the allocation node to be read originates
Returns:
pageId to be read

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.

Parameters:
extentNum absolute 0-based extent number
[out] allocNodeSegment segment from which the allocation node to be read originates
Returns:
pageId to be read

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.

See also:
getPageEntryCopyTemplate()
Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
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 (  ) 

Returns:
the deallocation mutex that prevents reading of the page chain while deallocations are in progress

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.

Parameters:
[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
Returns:
true if additional pages need to be searched; false if reached end of search

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.

Parameters:
[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.

Parameters:
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
Returns:
number of data pages that will be backed up if countDataPages is true; otherwise, returns 0

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.

Parameters:
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.

Parameters:
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.

Parameters:
pageId the PageId of interest
Returns:
true iff the PageId is currently allocated in this segment

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.

Parameters:
ownerId the PageOwnerId of the object which will own this page, or ANON_PAGE_OWNER_ID for pages unassociated with an owner
Returns:
the PageId of the allocated page, or NULL_PAGE_ID if none could be allocated

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.

Parameters:
pageId PageId for which the successor is to be found
Returns:
successor PageId

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.

Parameters:
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.

Parameters:
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.

Parameters:
iSegPage 0-based index of desired SegmentAllocationNode
Returns:
corresponding PageId

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.

Parameters:
extentNum absolute 0-based extent number
Returns:
corresponding PageId

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.

Parameters:
extentNum absolute 0-based extent number of extent containing desired page
iPageInExtent 0-based index of page in extent
Returns:
BlockNum corresponding to a linear PageId in this segment

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.

Parameters:
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 }

template<class PageEntryT>
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.

Parameters:
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
Returns:
ownerId

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 }

template<class ExtentAllocationNodeT, class ExtentAllocLockT, class PageEntryT>
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.

Parameters:
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]

Returns:
the PageId of the first SegmentAllocationNode

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 }

template<class ExtentAllocationNodeT, class ExtentAllocLockT, class PageEntryT>
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.

Parameters:
[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 }

template<class ExtentAllocationNodeT, class ExtentAllocLockT, class PageEntryT>
void RandomAllocationSegmentBase::formatExtentTemplate ( ExtentAllocationNodeT &  extentNode  )  [protected, inherited]

Formats one extent allocation.

This template method allows the caller to specify different extent allocation node types.

Parameters:
[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.

Parameters:
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
Returns:
the PageId of the allocated page, or NULL_PAGE_ID if none could be allocated

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 }

template<class ExtentAllocationNodeT, class ExtentAllocLockT, class PageEntryT>
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.

Parameters:
extentNum absolute 0-based extent number from which to allocate
ownerId PageOwnerId of owning object
allocNodeSegment segment that the allocation node page originates from
Returns:
allocated PageId

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 }

template<class ExtentAllocationNodeT, class ExtentAllocLockT, class PageEntryT>
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.

Parameters:
extentNum absolute 0-based extent number from which to allocate
ownerId PageOwnerId of owning object
allocNodeSegment segment that the allocation node page originates from
Returns:
allocated PageId

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 }

template<class ExtentAllocationNodeT, class PageEntryT>
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.

Parameters:
[in] extentNode locked extent allocation node corresponding to extentNum
extentNum absolute extent number from which to allocate
ownerId PageOwnerId of owning object
Returns:
allocated PageId

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 }

template<class ExtentAllocationNodeT, class ExtentAllocLockT>
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.

Parameters:
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 }

template<class ExtentAllocationNodeT, class ExtentAllocLockT, class PageEntryT>
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.

Parameters:
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]

Returns:
the AllocationOrder for this segment

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]

Returns:
number of pages allocated from this segment

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.

Returns:
the max number of pages occupied by a segment

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]

Returns:
the number of incremental pages added to this instance of the segment

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.

Parameters:
nPages lower bound for getAllocatedSizeInPages()
Returns:
true if enough pages could be allocated; false if not

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.

Parameters:
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.

Parameters:
pageId pageId of the page being modified
needsTranslation true if the pageId needs to be mapped to the appropriate update page; defaults to false
Returns:
NULL_PAGE_ID if the page can be updated in place; otherwise, the pageId of the page that should be used when updates are made to the page

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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
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.

Parameters:
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 }

PBuffer Segment::getWritableFooter ( CachePage page  )  [protected, inherited]

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]

Returns:
the Cache for this Segment

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]

Returns:
the full size of pages stored in this segment; this is the same as the size of underlying cache pages

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]

Returns:
the full size of pages stored in this segment minus the size for any footer information stored at the end of each page

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]

Returns:
tracing segment associated with this segment if tracing is turned on; otherwise, returns the segment itself

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.

Parameters:
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.

Parameters:
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.

Parameters:
blockId blockId of the page whose page listener we are returning
Returns:
segment corresponding to mapped page listener

Reimplemented in DynamicDelegatingSegment, SnapshotRandomAllocationSegment, and TracingSegment.

Definition at line 153 of file Segment.cpp.

00154 {
00155     return this;
00156 }

bool Segment::isWriteVersioned (  )  [virtual, inherited]

Returns:
true if the segment supports versioning

Reimplemented in DynamicDelegatingSegment, SnapshotRandomAllocationSegment, and TracingSegment.

Definition at line 158 of file Segment.cpp.

00159 {
00160     return false;
00161 }

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().

00349 {
00350     return PageId(iPage);
00351 }

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.

Returns:
tracing segment corresponding to a listener

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.

Parameters:
page the page that was flushed
Returns:
NULL if the listener on the page does not need to be reset; otherwise, returns the listener that the page should be reset to

Reimplemented in SnapshotRandomAllocationSegment, and TracingSegment.

Definition at line 62 of file MappedPageListener.cpp.

00064 {
00065     return NULL;
00066 }

bool ClosableObject::isClosed (  )  const [inline, inherited]

Returns:
whether the object has been closed

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 }


Friends And Related Function Documentation

friend class SegmentFactory [friend, inherited]

Definition at line 140 of file RandomAllocationSegmentBase.h.


Member Data Documentation

ModifiedAllocationNodeMap VersionedRandomAllocationSegment::allocationNodeMap [private]

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().

SXMutex VersionedRandomAllocationSegment::mapMutex [private]

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().

SXMutex VersionedRandomAllocationSegment::deallocationMutex [private]

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().

SharedSegment VersionedRandomAllocationSegment::pTempSegment [private]

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().


The documentation for this class was generated from the following files:
Generated on Mon Jun 22 04:00:49 2009 for Fennel by  doxygen 1.5.1