00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef Fennel_RandomAllocationSegmentBaseImpl_Included
00025 #define Fennel_RandomAllocationSegmentBaseImpl_Included
00026
00027 #include "fennel/segment/RandomAllocationSegmentBase.h"
00028 #include "fennel/segment/SegPageLock.h"
00029
00030 FENNEL_BEGIN_NAMESPACE
00031
00032
00033
00034
00038 static const PageOwnerId UNALLOCATED_PAGE_OWNER_ID = PageOwnerId(0);
00039
00044 struct FENNEL_SEGMENT_EXPORT SegmentAllocationNode
00045 : public StoredNode
00046 {
00047 static const MagicNumber MAGIC_NUMBER = 0xa3db80b98208bfd4LL;
00048
00052 struct ExtentEntry
00053 {
00054
00055
00056
00057
00058 uint32_t nUnallocatedPages;
00059 };
00060
00067 BlockNum nPagesPerExtent;
00068
00077 PageId nextSegAllocPageId;
00078
00082 uint nExtents;
00083
00084 ExtentEntry &getExtentEntry(uint i)
00085 {
00086 assert(i < nExtents);
00087 return reinterpret_cast<ExtentEntry *>(this+1)[i];
00088 }
00089
00090 ExtentEntry const &getExtentEntry(uint i) const
00091 {
00092 assert(i < nExtents);
00093 return reinterpret_cast<ExtentEntry const *>(this+1)[i];
00094 }
00095 };
00096
00097 typedef SegNodeLock<SegmentAllocationNode> SegAllocLock;
00098
00099 inline PageId RandomAllocationSegmentBase::getFirstSegAllocPageId() const
00100 {
00101 return FIRST_LINEAR_PAGE_ID;
00102 }
00103
00104 inline PageId RandomAllocationSegmentBase::getSegAllocPageId(
00105 uint iSegPage) const
00106 {
00107 return getLinearPageId(nPagesPerSegAlloc*iSegPage);
00108 }
00109
00110 inline BlockNum RandomAllocationSegmentBase::makePageNum(
00111 ExtentNum extentNum,BlockNum iPageInExtent) const
00112 {
00113
00114 uint nSegPages = extentNum / nExtentsPerSegAlloc + 1;
00115 return iPageInExtent + extentNum*nPagesPerExtent + nSegPages;
00116 }
00117
00118 inline PageId RandomAllocationSegmentBase::getExtentAllocPageId(
00119 ExtentNum extentNum) const
00120 {
00121 return getLinearPageId(makePageNum(extentNum,0));
00122 }
00123
00124 template <class ExtentAllocationNodeT,
00125 class ExtentAllocLockT,
00126 class PageEntryT>
00127 PageId RandomAllocationSegmentBase::allocateFromExtentTemplate(
00128 ExtentNum extentNum,
00129 PageOwnerId ownerId,
00130 SharedSegment allocNodeSegment)
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 }
00144
00145 template <class ExtentAllocationNodeT, class ExtentAllocLockT, class PageEntryT>
00146 void RandomAllocationSegmentBase::formatPageExtentsTemplate(
00147 SegmentAllocationNode &segAllocNode,
00148 ExtentNum &extentNum)
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
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 }
00166
00167 template <class ExtentAllocationNodeT, class ExtentAllocLockT, class PageEntryT>
00168 void RandomAllocationSegmentBase::formatExtentTemplate(
00169 ExtentAllocationNodeT &extentNode)
00170 {
00171
00172 for (uint i = 0; i < nPagesPerExtent; i++) {
00173 PageEntryT &pageEntry = extentNode.getPageEntry(i);
00174 markPageEntryUnused(pageEntry);
00175 }
00176
00177
00178
00179 extentNode.getPageEntry(0).ownerId = ANON_PAGE_OWNER_ID;
00180 }
00181
00182 template <class ExtentAllocationNodeT, class ExtentAllocLockT, class PageEntryT>
00183 PageId RandomAllocationSegmentBase::allocateFromNewExtentTemplate(
00184 ExtentNum extentNum,
00185 PageOwnerId ownerId,
00186 SharedSegment allocNodeSegment)
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 }
00201
00202 template <class ExtentAllocationNodeT, class PageEntryT>
00203 PageId RandomAllocationSegmentBase::allocateFromLockedExtentTemplate(
00204 ExtentAllocationNodeT &node, ExtentNum extentNum, PageOwnerId ownerId)
00205 {
00206
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
00212
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 }
00223
00224 template <class ExtentAllocationNodeT, class ExtentAllocLockT, class PageEntryT>
00225 void RandomAllocationSegmentBase::freePageEntryTemplate(
00226 ExtentNum extentNum,
00227 BlockNum iPageInExtent)
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 }
00238
00239 template <class ExtentAllocationNodeT, class ExtentAllocLockT>
00240 void RandomAllocationSegmentBase::setPageSuccessorTemplate(
00241 PageId pageId,
00242 PageId successorId,
00243 SharedSegment allocNodeSegment)
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 }
00260
00261 template <class PageEntryT>
00262 PageOwnerId RandomAllocationSegmentBase::getPageOwnerIdTemplate(
00263 PageId pageId,
00264 bool thisSegment)
00265 {
00266 PageEntryT pageEntry;
00267
00268 getPageEntryCopy(pageId, pageEntry, false, thisSegment);
00269 return pageEntry.ownerId;
00270 }
00271
00272 template <class ExtentAllocationNodeT, class ExtentAllocLockT, class PageEntryT>
00273 void RandomAllocationSegmentBase::getPageEntryCopyTemplate(
00274 PageId pageId,
00275 PageEntryT &pageEntryCopy,
00276 bool isAllocated,
00277 bool thisSegment)
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 }
00309
00310 FENNEL_END_NAMESPACE
00311
00312 #endif
00313
00314