Fennel: /home/pub/open/dev/fennel/segment/VersionedRandomAllocationSegment.cpp Source File (original) (raw)

00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 00011 00012 00013 00014 00015 00016 00017 00018 00019 00020 00021 00022 00023 00024 #include "fennel/common/CommonPreamble.h" 00025 #include "fennel/common/AbortExcn.h" 00026 #include "fennel/common/FennelResource.h" 00027 #include "fennel/segment/RandomAllocationSegmentBaseImpl.h" 00028 #include "fennel/segment/VersionedRandomAllocationSegmentImpl.h" 00029 00030 FENNEL_BEGIN_CPPFILE("$Id: //open/dev/fennel/segment/VersionedRandomAllocationSegment.cpp#19 $"); 00031 00032 VersionedRandomAllocationSegment::VersionedRandomAllocationSegment( 00033 SharedSegment delegateSegment, 00034 SharedSegment pTempSegmentInit) 00035 : RandomAllocationSegmentBase(delegateSegment) 00036 { 00037 nPagesPerExtent = 00038 (getUsablePageSize() - sizeof(VersionedExtentAllocationNode)) 00039 / sizeof(VersionedPageEntry); 00040 00041
00042 nPagesPerSegAlloc = nPagesPerExtent*nExtentsPerSegAlloc + 1; 00043 00044 pTempSegment = pTempSegmentInit; 00045 } 00046 00047 void VersionedRandomAllocationSegment::initForUse() 00048 { 00049
00050
00051 SXMutexSharedGuard mapGuard(mapMutex); 00052 00053 RandomAllocationSegmentBase::initForUse(); 00054 } 00055 00056 void VersionedRandomAllocationSegment::formatPageExtents( 00057 SegmentAllocationNode &segAllocNode, 00058 ExtentNum &extentNum) 00059 { 00060 formatPageExtentsTemplate< 00061 VersionedExtentAllocationNode, 00062 VersionedExtentAllocLock, 00063 VersionedPageEntry>( 00064 segAllocNode, 00065 extentNum); 00066 } 00067 00068 PageId VersionedRandomAllocationSegment::allocatePageId(PageOwnerId ownerId) 00069 { 00070 return allocatePageIdFromSegment(ownerId, pTempSegment); 00071 } 00072 00073 PageId VersionedRandomAllocationSegment::getSegAllocPageIdForWrite( 00074 PageId origSegAllocPageId) 00075 { 00076 return getTempAllocNodePage(origSegAllocPageId, true); 00077 } 00078 00079 void VersionedRandomAllocationSegment::undoSegAllocPageWrite( 00080 PageId segAllocPageId) 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 } 00089 00090 PageId VersionedRandomAllocationSegment::getSegAllocPageIdForRead( 00091 PageId origSegAllocPageId, 00092 SharedSegment &allocNodeSegment) 00093 { 00094 return findAllocPageIdForRead(origSegAllocPageId, allocNodeSegment); 00095 } 00096 00097 PageId VersionedRandomAllocationSegment::getExtAllocPageIdForRead( 00098 ExtentNum extentNum, 00099 SharedSegment &allocNodeSegment) 00100 { 00101 return 00102 findAllocPageIdForRead( 00103 getExtentAllocPageId(extentNum), 00104 allocNodeSegment); 00105 } 00106 00107 PageId VersionedRandomAllocationSegment::findAllocPageIdForRead( 00108 PageId origAllocNodePageId, 00109 SharedSegment &allocNodeSegment) 00110 { 00111
00112
00113
00114
00115
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 } 00130 00131 PageId VersionedRandomAllocationSegment::allocateFromNewExtent( 00132 ExtentNum extentNum, 00133 PageOwnerId ownerId) 00134 { 00135 return 00136 allocateFromNewExtentTemplate< 00137 VersionedExtentAllocationNode, 00138 VersionedExtentAllocLock, 00139 VersionedPageEntry>( 00140 extentNum, 00141 ownerId, 00142 pTempSegment); 00143 } 00144 00145 PageId VersionedRandomAllocationSegment::allocateFromExtent( 00146 ExtentNum extentNum, 00147 PageOwnerId ownerId) 00148 { 00149 return 00150 allocateFromExtentTemplate< 00151 VersionedExtentAllocationNode, 00152 VersionedExtentAllocLock, 00153 VersionedPageEntry>( 00154 extentNum, 00155 ownerId, 00156 pTempSegment); 00157 } 00158 00159 void VersionedRandomAllocationSegment::deallocatePageRange( 00160 PageId startPageId, 00161 PageId endPageId) 00162 { 00163 assert(startPageId == endPageId); 00164 00165 if (startPageId == NULL_PAGE_ID) { 00166 format(); 00167 } else { 00168
00169
00170
00171
00172 00173
00174
00175 SXMutexExclusiveGuard deallocationGuard(deallocationMutex); 00176 00177
00178
00179 deferDeallocation(startPageId); 00180 } 00181 } 00182 00183 void VersionedRandomAllocationSegment::deferDeallocation(PageId pageId) 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
00201
00202 pageEntry.ownerId = makeDeallocatedPageOwnerId(TxnId(0)); 00203 } 00204 00205 void VersionedRandomAllocationSegment::freePageEntry( 00206 ExtentNum extentNum, 00207 BlockNum iPageInExtent) 00208 { 00209 freePageEntryTemplate< 00210 VersionedExtentAllocationNode, 00211 VersionedExtentAllocLock, 00212 VersionedPageEntry>( 00213 extentNum, 00214 iPageInExtent); 00215 } 00216 00217 void VersionedRandomAllocationSegment::markPageEntryUnused( 00218 PageEntry &pageEntry) 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 } 00227 00228 PageId VersionedRandomAllocationSegment::getPageSuccessor(PageId pageId) 00229 { 00230 VersionedPageEntry pageEntry; 00231 00232 getLatestPageEntryCopy(pageId, pageEntry); 00233 return pageEntry.successorId; 00234 } 00235 00236 void VersionedRandomAllocationSegment::setPageSuccessor( 00237 PageId pageId, PageId successorId) 00238 { 00239 setPageSuccessorTemplate< 00240 VersionedExtentAllocationNode, 00241 VersionedExtentAllocLock>( 00242 pageId, 00243 successorId, 00244 pTempSegment); 00245 } 00246 00247 bool VersionedRandomAllocationSegment::isPageIdAllocated(PageId pageId) 00248 { 00249 return testPageId(pageId, true, false); 00250 } 00251 00252 bool VersionedRandomAllocationSegment::isPageIdAllocateCommitted(PageId pageId) 00253 { 00254 return testPageId(pageId, true, true); 00255 } 00256 00257 bool VersionedRandomAllocationSegment::isPageIdValid(PageId pageId) 00258 { 00259 return testPageId(pageId, false, false); 00260 } 00261 00262 PageId VersionedRandomAllocationSegment::getExtAllocPageIdForWrite( 00263 ExtentNum extentNum) 00264 { 00265 return 00266 getTempAllocNodePage( 00267 getExtentAllocPageId(extentNum), 00268 false); 00269 } 00270 00271 PageOwnerId VersionedRandomAllocationSegment::getPageOwnerId( 00272 PageId pageId, 00273 bool thisSegment) 00274 { 00275 return getPageOwnerIdTemplate(pageId, thisSegment); 00276 } 00277 00278 void VersionedRandomAllocationSegment::getPageEntryCopy( 00279 PageId pageId, 00280 PageEntry &pageEntryCopy, 00281 bool isAllocated, 00282 bool thisSegment) 00283 { 00284
00285
00286
00287
00288
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 } 00302 00303 void VersionedRandomAllocationSegment::getLatestPageEntryCopy( 00304 PageId pageId, 00305 VersionedPageEntry &pageEntryCopy) 00306 { 00307 getPageEntryCopy(pageId, pageEntryCopy, true, false); 00308 } 00309 00310 void VersionedRandomAllocationSegment::getCommittedPageEntryCopy( 00311 PageId pageId, 00312 VersionedPageEntry &pageEntryCopy) 00313 { 00314 getPageEntryCopy(pageId, pageEntryCopy, true, true); 00315 } 00316 00317 void VersionedRandomAllocationSegment::initPageEntry( 00318 PageId pageId, 00319 PageId versionChainId, 00320 TxnId allocationCsn) 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 } 00343 00344 void VersionedRandomAllocationSegment::chainPageEntries( 00345 PageId pageId, 00346 PageId versionChainId, 00347 PageId successorId) 00348 { 00349 chainPageEntries(pageId, versionChainId, successorId, false); 00350 } 00351 00352 void VersionedRandomAllocationSegment::chainPageEntries( 00353 PageId pageId, 00354 PageId versionChainId, 00355 PageId successorId, 00356 bool thisSegment) 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
00367
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 } 00388 00389 void VersionedRandomAllocationSegment::updateAllocNodes( 00390 ModifiedPageEntryMap const &modifiedPageEntryMap, 00391 TxnId commitCsn, 00392 bool commit, 00393 SharedSegment pOrigSegment) 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
00413
00414 allocateAllocNodes(iSegAlloc, NULL_PAGE_ID, extentNum); 00415 00416
00417
00418
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
00439
00440
00441
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 } 00454 00455 void VersionedRandomAllocationSegment::updatePageEntry( 00456 PageId pageId, 00457 ExtentNum extentNum, 00458 uint iPageInExtent, 00459 SharedModifiedPageEntry pModEntry, 00460 TxnId commitCsn, 00461 bool commit, 00462 SharedSegment pOrigSegment) 00463 { 00464 assert(mapMutex.isLocked(LOCKMODE_X)); 00465 00466
00467
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
00485
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 } 00495 00496 void VersionedRandomAllocationSegment::copyPageEntryFromTemp( 00497 PageId pageId, 00498 PageId origPageId, 00499 PageId tempPageId, 00500 BlockNum iPageInExtent, 00501 ModifiedPageEntry::ModType lastModType, 00502 TxnId commitCsn, 00503 PageOwnerId ownerId) 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
00522
00523
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 } 00534 00535 void VersionedRandomAllocationSegment::copyPageEntryToTemp( 00536 PageId origPageId, 00537 PageId tempPageId, 00538 BlockNum iPageInExtent) 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 } 00558 00559 void VersionedRandomAllocationSegment::updateExtentEntry( 00560 uint iSegAlloc, 00561 ExtentNum extentNum, 00562 uint allocationCount, 00563 bool commit) 00564 { 00565 assert(mapMutex.isLocked(LOCKMODE_X)); 00566 00567
00568
00569 00570 if (allocationCount) { 00571
00572
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 } 00604 00605 void VersionedRandomAllocationSegment::allocateAllocNodes( 00606 uint iSegAlloc, 00607 PageId nextPageId, 00608 ExtentNum extentNum) 00609 { 00610 SegmentAccessor selfAccessor(getTracingSegment(), pCache); 00611 SegAllocLock segAllocLock(selfAccessor); 00612 PageId segAllocPageId = getSegAllocPageId(iSegAlloc); 00613 segAllocLock.lockExclusive(segAllocPageId); 00614 if (segAllocLock.checkMagicNumber()) { 00615
00616
00617
00618
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
00628
00629
00630
00631
00632
00633 00634 permAssert(iSegAlloc >= 1); 00635 segAllocLock.setMagicNumber(); 00636 SegmentAllocationNode &newNode = segAllocLock.getNodeForWrite(); 00637
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 } 00647 00648 void VersionedRandomAllocationSegment::allocateExtAllocNodes( 00649 SegmentAllocationNode &segAllocNode, 00650 uint iSegAlloc, 00651 ExtentNum extentNum) 00652 { 00653
00654
00655
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 } 00669 00670 bool VersionedRandomAllocationSegment::validateFreePageCount(PageId pageId) 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 } 00704 00705 void VersionedRandomAllocationSegment::freeTempPage( 00706 PageId origAllocNodePageId, 00707 PageId tempAllocNodePageId) 00708 { 00709 assert(mapMutex.isLocked(LOCKMODE_X)); 00710 pTempSegment->deallocatePageRange(tempAllocNodePageId, tempAllocNodePageId); 00711 allocationNodeMap.erase(origAllocNodePageId); 00712 } 00713 00714 bool VersionedRandomAllocationSegment::getOldPageIds( 00715 uint &iSegAlloc, 00716 ExtentNum &extentNum, 00717 TxnId oldestActiveTxnId, 00718 uint numPages, 00719 PageSet &oldPageSet) 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
00737
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
00753
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
00762 PageId pageId = getLinearPageId(makePageNum(extentNum, j)); 00763 00764
00765
00766 if (pageEntry.versionChainPageId == pageId && 00767 isDeallocatedPageOwnerId(pageEntry.ownerId)) 00768 { 00769 continue; 00770 } 00771 00772
00773
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 } 00793 00794 void VersionedRandomAllocationSegment::deallocateOldPages( 00795 PageSet const &oldPageSet, 00796 TxnId oldestActiveTxnId) 00797 { 00798 SXMutexExclusiveGuard deallocationGuard(deallocationMutex); 00799 SXMutexExclusiveGuard mapGuard(mapMutex); 00800 00801 std::hash_set deallocatedPageSet; 00802 for (PageSetConstIter pageIter = oldPageSet.begin(); 00803 pageIter != oldPageSet.end(); pageIter++) 00804 { 00805 PageId pageId = *pageIter; 00806 00807
00808
00809 if (deallocatedPageSet.find(pageId) != deallocatedPageSet.end()) { 00810 continue; 00811 } 00812
00813
00814 if (isPageIdAllocateCommitted(pageId)) { 00815 deallocatedPageSet.insert(pageId); 00816 continue; 00817 } 00818 00819
00820
00821
00822
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
00844
00845 deallocatePageChain(anchorPageId, deallocationCsn, deallocatedPageSet); 00846 } 00847 } 00848 00849 TxnId VersionedRandomAllocationSegment::getOldestTxnId( 00850 PageId pageId, 00851 TxnId oldestActiveTxnId, 00852 PageId &anchorPageId, 00853 std::hash_set &deallocatedPageSet, 00854 bool &deallocateChain) 00855 { 00856
00857
00858
00859
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
00893
00894
00895
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
00927
00928
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
00939 assert(newestOldPageId != NULL_PAGE_ID); 00940 assert(anchorPageId != NULL_PAGE_ID); 00941 assert(nextNewestOldCsn == NULL_TXN_ID || nextNewestOldCsn < newestOldCsn); 00942 00943
00944
00945
00946
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
00957
00958 TxnId deallocationCsn = nextNewestOldCsn + 1; 00959 assert(deallocationCsn < oldestActiveTxnId); 00960 00961 return deallocationCsn; 00962 } 00963 00964 void VersionedRandomAllocationSegment::deallocateEntirePageChain( 00965 PageId pageId, 00966 TxnId oldestActiveTxnId, 00967 std::hash_set &deallocatedPageSet) 00968 { 00969 PageId chainPageId = pageId; 00970 VersionedPageEntry pageEntry; 00971 do { 00972 getCommittedPageEntryCopy(chainPageId, pageEntry); 00973 00974
00975
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 } 00984 00985 void VersionedRandomAllocationSegment::deallocateSinglePage( 00986 PageId pageId, 00987 std::hash_set &deallocatedPageSet) 00988 { 00989 assert(mapMutex.isLocked(LOCKMODE_X)); 00990 00991
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
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
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 } 01028 01029 void VersionedRandomAllocationSegment::deallocatePageChain( 01030 PageId anchorPageId, 01031 TxnId deallocationCsn, 01032 std::hash_set &deallocatedPageSet) 01033 { 01034 VersionedPageEntry prevPageEntry; 01035 getCommittedPageEntryCopy(anchorPageId, prevPageEntry); 01036 assert( 01037 prevPageEntry.ownerId != UNALLOCATED_PAGE_OWNER_ID && 01038 isDeallocatedPageOwnerId(prevPageEntry.ownerId)); 01039 01040
01041
01042
01043
01044
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
01058
01059
01060
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
01073
01074 if (needsUpdate) { 01075 updateTempPageEntry(prevPageId, prevPageEntry); 01076 } 01077 needsUpdate = false; 01078 01079
01080 prevPageId = nextPageId; 01081 prevPageEntry = pageEntry; 01082 nextPageId = pageEntry.versionChainPageId; 01083 } 01084 } while (nextPageId != anchorPageId); 01085 01086
01087 if (needsUpdate) { 01088 updateTempPageEntry(prevPageId, prevPageEntry); 01089 } 01090 } 01091 01092 bool VersionedRandomAllocationSegment::uncommittedDeallocation( 01093 PageId anchorPageId, 01094 std::hash_set &deallocatedPageSet) 01095 { 01096 ExtentNum extentNum; 01097 BlockNum iPageInExtent; 01098 uint iSegAlloc; 01099 splitPageId(anchorPageId, iSegAlloc, extentNum, iPageInExtent); 01100 assert(iPageInExtent); 01101 01102
01103
01104
01105
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 } 01132 01133 void VersionedRandomAllocationSegment::skipDeferredDeallocations( 01134 PageId pageId, 01135 std::hash_set &deallocatedPageSet) 01136 { 01137
01138
01139
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 } 01149 01150 bool VersionedRandomAllocationSegment::validatePageChain(PageId anchorPageId) 01151 { 01152
01153
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 } 01164 01165 void VersionedRandomAllocationSegment::updateTempPageEntry( 01166 PageId pageId, 01167 VersionedPageEntry const &pageEntry) 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 } 01190 01191 void VersionedRandomAllocationSegment::freeTempPages() 01192 { 01193 SXMutexExclusiveGuard mapGuard(mapMutex); 01194 01195 ModifiedAllocationNodeMap::iterator iter = allocationNodeMap.begin(); 01196 while (iter != allocationNodeMap.end()) { 01197
01198
01199
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 } 01207 01208 SXMutex &VersionedRandomAllocationSegment::getDeallocationMutex() 01209 { 01210 return deallocationMutex; 01211 } 01212 01213 BlockNum VersionedRandomAllocationSegment::backupAllocationNodes( 01214 SharedSegPageBackupRestoreDevice pBackupDevice, 01215 bool countDataPages, 01216 TxnId lowerBoundCsn, 01217 TxnId upperBoundCsn, 01218 bool volatile const &abortFlag) 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
01251
01252 if (extentEntry.nUnallocatedPages == nPagesPerExtent - 1) { 01253 continue; 01254 } 01255 01256 VersionedExtentAllocationNode const &extentNode = 01257 extentAllocLock.getNodeForRead(); 01258 01259
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 } 01283 01284 void VersionedRandomAllocationSegment::backupDataPages( 01285 SharedSegPageBackupRestoreDevice pBackupDevice, 01286 TxnId lowerBoundCsn, 01287 TxnId upperBoundCsn, 01288 bool volatile const &abortFlag) 01289 { 01290 locateDataPages( 01291 pBackupDevice, 01292 lowerBoundCsn, 01293 upperBoundCsn, 01294 true, 01295 abortFlag); 01296 } 01297 01298 void VersionedRandomAllocationSegment::locateDataPages( 01299 SharedSegPageBackupRestoreDevice pBackupDevice, 01300 TxnId lowerBoundCsn, 01301 TxnId upperBoundCsn, 01302 bool isBackup, 01303 bool volatile const &abortFlag) 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
01321
01322
01323
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
01365 for (uint j = 1; j < nPagesPerExtent; j++) { 01366 checkAbort(abortFlag); 01367 VersionedPageEntry const &pageEntry = 01368 extentNode.getPageEntry(j); 01369
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
01379
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
01396 pBackupDevice->waitForPendingWrites(); 01397 } 01398 01399 void VersionedRandomAllocationSegment::restoreFromBackup( 01400 SharedSegPageBackupRestoreDevice pBackupDevice, 01401 TxnId lowerBoundCsn, 01402 TxnId upperBoundCsn, 01403 bool volatile const &abortFlag) 01404 { 01405
01406
01407
01408
01409
01410 01411 SegmentAccessor selfAccessor(getTracingSegment(), pCache); 01412 SegAllocLock segAllocLock(selfAccessor); 01413 uint iSegAlloc = 0; 01414 ExtentNum extentNum = 0; 01415 01416 while (true) { 01417
01418
01419
01420
01421
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
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
01461
01462
01463
01464 pBackupDevice->waitForPendingWrites(); 01465 locateDataPages( 01466 pBackupDevice, 01467 lowerBoundCsn, 01468 upperBoundCsn, 01469 false, 01470 abortFlag); 01471 } 01472 01473 void VersionedRandomAllocationSegment::checkAbort( 01474 bool volatile const &abortFlag) 01475 { 01476 if (abortFlag) { 01477 throw AbortExcn(); 01478 } 01479 } 01480 01481 FENNEL_END_CPPFILE("$Id: //open/dev/fennel/segment/VersionedRandomAllocationSegment.cpp#19 $"); 01482 01483