Fennel: /home/pub/open/dev/fennel/segment/SnapshotRandomAllocationSegment.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/cache/PagePredicate.h" 00026 #include "fennel/segment/SnapshotRandomAllocationSegment.h" 00027 #include "fennel/segment/SegmentFactory.h" 00028 #include "fennel/segment/SegmentAccessor.h" 00029 00030 FENNEL_BEGIN_CPPFILE("$Id: //open/dev/fennel/segment/SnapshotRandomAllocationSegment.cpp#16 $"); 00031 00032 SnapshotRandomAllocationSegment::SnapshotRandomAllocationSegment( 00033 SharedSegment delegateSegment, 00034 SharedSegment versionedSegment, 00035 TxnId snapshotCsnInit, 00036 bool readOnlyCommittedDataInit) 00037 : DelegatingSegment(delegateSegment) 00038 { 00039 pVersionedRandomSegment = 00040 SegmentFactory::dynamicCast<VersionedRandomAllocationSegment *>( 00041 versionedSegment); 00042 assert(pVersionedRandomSegment); 00043 00044 snapshotCsn = snapshotCsnInit; 00045 readOnlyCommittedData = readOnlyCommittedDataInit; 00046 needPageFlush = false; 00047 forceCacheUnmap = false; 00048 } 00049 00050 TxnId SnapshotRandomAllocationSegment::getSnapshotCsn() 00051 { 00052 return snapshotCsn; 00053 } 00054 00055 BlockId SnapshotRandomAllocationSegment::translatePageId(PageId pageId) 00056 { 00057 PageId snapshotId = getSnapshotId(pageId); 00058 return DelegatingSegment::translatePageId(snapshotId); 00059 } 00060 00061 PageId SnapshotRandomAllocationSegment::getSnapshotId(PageId pageId) 00062 { 00063 StrictMutexGuard mutexGuard(snapshotPageMapMutex); 00064 00065
00066 PageMapConstIter pSnapshotPageId = snapshotPageMap.find(pageId); 00067 if (pSnapshotPageId != snapshotPageMap.end()) { 00068 return pSnapshotPageId->second; 00069 } 00070 00071 VersionedPageEntry pageEntry; 00072 pVersionedRandomSegment->getLatestPageEntryCopy(pageId, pageEntry); 00073
00074 if (pageEntry.versionChainPageId == pageId) { 00075 assert(snapshotCsn >= pageEntry.allocationCsn); 00076 snapshotPageMap[pageId] = pageId; 00077 return pageId; 00078 } 00079 00080
00081
00082
00083
00084
00085
00086 assert(pageId == getAnchorPageId(pageId)); 00087 PageId chainPageId = pageEntry.versionChainPageId; 00088 do { 00089 pVersionedRandomSegment->getLatestPageEntryCopy(chainPageId, pageEntry); 00090 if (snapshotCsn >= pageEntry.allocationCsn) { 00091
00092
00093 if ((readOnlyCommittedData && 00094 pageEntry.ownerId == UNCOMMITTED_PAGE_OWNER_ID && 00095 snapshotCsn == pageEntry.allocationCsn) || 00096 pageEntry.ownerId != UNCOMMITTED_PAGE_OWNER_ID) 00097 { 00098 snapshotPageMap[pageId] = chainPageId; 00099 return chainPageId; 00100 } 00101 } 00102
00103 permAssert(chainPageId != pageId); 00104 chainPageId = pageEntry.versionChainPageId; 00105 } while (true); 00106 } 00107 00108 PageId SnapshotRandomAllocationSegment::getPageSuccessor(PageId pageId) 00109 { 00110 PageId snapshotId = getSnapshotId(pageId); 00111 return DelegatingSegment::getPageSuccessor(snapshotId); 00112 } 00113 00114 void SnapshotRandomAllocationSegment::setPageSuccessor( 00115 PageId pageId, PageId successorId) 00116 { 00117 assert(readOnlyCommittedData); 00118 00119
00120
00121 PageId snapshotId = getSnapshotId(pageId); 00122 DelegatingSegment::setPageSuccessor(snapshotId, successorId); 00123 00124 SXMutexExclusiveGuard mapGuard(modPageMapMutex); 00125 incrPageUpdateCount( 00126 snapshotId, 00127 ANON_PAGE_OWNER_ID, 00128 ModifiedPageEntry::MODIFIED); 00129 } 00130 00131 void SnapshotRandomAllocationSegment::incrPageUpdateCount( 00132 PageId pageId, 00133 PageOwnerId ownerId, 00134 ModifiedPageEntry::ModType modType) 00135 { 00136 assert(modPageMapMutex.isLocked(LOCKMODE_X)); 00137 00138 needPageFlush = true; 00139 00140
00141
00142 ModifiedPageEntryMapIter iter = modPageEntriesMap.find(pageId); 00143 SharedModifiedPageEntry pModPageEntry; 00144 if (iter == modPageEntriesMap.end()) { 00145 pModPageEntry = SharedModifiedPageEntry(new ModifiedPageEntry()); 00146 pModPageEntry->updateCount = 0; 00147 pModPageEntry->allocationCount = 0; 00148 pModPageEntry->lastModType = modType; 00149 pModPageEntry->ownerId = ownerId; 00150 } else { 00151 pModPageEntry = iter->second; 00152
00153
00154 assert(pModPageEntry->lastModType != ModifiedPageEntry::DEALLOCATED); 00155 } 00156 00157
00158 if (modType == ModifiedPageEntry::ALLOCATED) { 00159 pModPageEntry->allocationCount++; 00160 assert(pModPageEntry->allocationCount <= 1); 00161 pModPageEntry->lastModType = modType; 00162 pModPageEntry->ownerId = ownerId; 00163 } else if (modType == ModifiedPageEntry::DEALLOCATED) { 00164 pModPageEntry->lastModType = modType; 00165 } 00166 00167
00168 pModPageEntry->updateCount++; 00169 00170 if (iter == modPageEntriesMap.end()) { 00171 modPageEntriesMap.insert( 00172 ModifiedPageEntryMap::value_type(pageId, pModPageEntry)); 00173 } 00174 } 00175 00176 PageId SnapshotRandomAllocationSegment::getAnchorPageId(PageId snapshotId) 00177 { 00178
00179
00180 SXMutexSharedGuard(pVersionedRandomSegment->getDeallocationMutex()); 00181 00182
00183
00184 PageId chainPageId = snapshotId; 00185 VersionedPageEntry pageEntry; 00186 PageId anchorPageId = NULL_PAGE_ID; 00187 TxnId minCsn = NULL_TXN_ID; 00188 do { 00189 pVersionedRandomSegment->getLatestPageEntryCopy(chainPageId, pageEntry); 00190 if (chainPageId == snapshotId || pageEntry.allocationCsn < minCsn) { 00191 minCsn = pageEntry.allocationCsn; 00192 anchorPageId = chainPageId; 00193 } else if (pageEntry.allocationCsn > minCsn) { 00194 break; 00195 } 00196 chainPageId = pageEntry.versionChainPageId; 00197 } while (chainPageId != snapshotId); 00198 00199 return anchorPageId; 00200 } 00201 00202 PageId SnapshotRandomAllocationSegment::allocatePageId(PageOwnerId ownerId) 00203 { 00204 assert(readOnlyCommittedData); 00205 SXMutexExclusiveGuard mapGuard(modPageMapMutex); 00206 00207 PageId pageId = 00208 DelegatingSegment::allocatePageId(UNCOMMITTED_PAGE_OWNER_ID); 00209 incrPageUpdateCount(pageId, ownerId, ModifiedPageEntry::ALLOCATED); 00210 pVersionedRandomSegment->initPageEntry( 00211 pageId, 00212 pageId, 00213 snapshotCsn); 00214 incrPageUpdateCount( 00215 pageId, 00216 ANON_PAGE_OWNER_ID, 00217 ModifiedPageEntry::MODIFIED); 00218 return pageId; 00219 } 00220 00221 void SnapshotRandomAllocationSegment::deallocatePageRange( 00222 PageId startPageId, 00223 PageId endPageId) 00224 { 00225 assert(readOnlyCommittedData); 00226 permAssert(startPageId != NULL_PAGE_ID); 00227 permAssert(startPageId == endPageId); 00228 00229 SXMutexExclusiveGuard mapGuard(modPageMapMutex); 00230 StrictMutexGuard mutexGuard(snapshotPageMapMutex); 00231 00232
00233
00234
00235 00236
00237
00238
00239
00240 00241 PageId chainPageId = startPageId; 00242 VersionedPageEntry pageEntry; 00243 do { 00244 pVersionedRandomSegment->getLatestPageEntryCopy(chainPageId, pageEntry); 00245 DelegatingSegment::deallocatePageRange(chainPageId, chainPageId); 00246 incrPageUpdateCount( 00247 chainPageId, 00248 ANON_PAGE_OWNER_ID, 00249 ModifiedPageEntry::DEALLOCATED); 00250 snapshotPageMap.erase(chainPageId); 00251 00252 chainPageId = pageEntry.versionChainPageId; 00253 } while (chainPageId != startPageId); 00254 } 00255 00256 PageId SnapshotRandomAllocationSegment::updatePage( 00257 PageId pageId, 00258 bool needsTranslation) 00259 { 00260 assert(readOnlyCommittedData); 00261 00262 PageId anchorPageId; 00263 PageId snapshotId; 00264 PageOwnerId ownerId; 00265 00266
00267
00268
00269
00270 00271 if (needsTranslation) { 00272 assert(pageId == getAnchorPageId(pageId)); 00273 VersionedPageEntry pageEntry; 00274 pVersionedRandomSegment->getLatestPageEntryCopy(pageId, pageEntry); 00275 assert(pageEntry.versionChainPageId == getSnapshotId(pageId)); 00276 if (isPageNewlyAllocated(pageEntry.versionChainPageId)) { 00277 return NULL_PAGE_ID; 00278 } 00279 00280 anchorPageId = pageId; 00281 snapshotId = pageEntry.versionChainPageId; 00282 ownerId = pageEntry.ownerId; 00283 00284 } else { 00285 if (isPageNewlyAllocated(pageId)) { 00286 return NULL_PAGE_ID; 00287 } 00288 VersionedPageEntry pageEntry; 00289 anchorPageId = getAnchorPageId(pageId); 00290 pVersionedRandomSegment->getLatestPageEntryCopy( 00291 anchorPageId, 00292 pageEntry); 00293 assert(pageEntry.versionChainPageId == pageId); 00294 assert(pageId == getSnapshotId(anchorPageId)); 00295 00296 snapshotId = pageId; 00297 ownerId = pageEntry.ownerId; 00298 } 00299 00300
00301
00302
00303
00304 00305 PageId newPageId = allocatePageId(ownerId); 00306 00307 SXMutexExclusiveGuard mapGuard(modPageMapMutex); 00308 00309 VersionedPageEntry pageEntry; 00310 pVersionedRandomSegment->getLatestPageEntryCopy(snapshotId, pageEntry); 00311 chainPageEntries( 00312 newPageId, 00313 snapshotId, 00314 pageEntry.successorId); 00315 chainPageEntries(anchorPageId, newPageId, NULL_PAGE_ID); 00316 00317
00318
00319
00320 StrictMutexGuard mutexGuard(snapshotPageMapMutex); 00321 snapshotPageMap[newPageId] = newPageId; 00322 snapshotPageMap[anchorPageId] = newPageId; 00323 return newPageId; 00324 } 00325 00326 void SnapshotRandomAllocationSegment::chainPageEntries( 00327 PageId pageId, 00328 PageId versionChainPageId, 00329 PageId successorId) 00330 { 00331 pVersionedRandomSegment->chainPageEntries( 00332 pageId, 00333 versionChainPageId, 00334 successorId); 00335 incrPageUpdateCount( 00336 pageId, 00337 ANON_PAGE_OWNER_ID, 00338 ModifiedPageEntry::MODIFIED); 00339 } 00340 00341 bool SnapshotRandomAllocationSegment::isPageNewlyAllocated(PageId pageId) 00342 { 00343 SXMutexSharedGuard mapGuard(modPageMapMutex); 00344 00345 ModifiedPageEntryMapIter iter = modPageEntriesMap.find(pageId); 00346 if (iter != modPageEntriesMap.end()) { 00347 SharedModifiedPageEntry pModPageEntry = iter->second; 00348 if (pModPageEntry->lastModType == ModifiedPageEntry::ALLOCATED) { 00349 return true; 00350 } 00351 } 00352 return false; 00353 } 00354 00355 void SnapshotRandomAllocationSegment::commitChanges(TxnId commitCsn) 00356 { 00357 assert(readOnlyCommittedData); 00358 SXMutexExclusiveGuard mapGuard(modPageMapMutex); 00359 00360 pVersionedRandomSegment->updateAllocNodes( 00361 modPageEntriesMap, 00362 commitCsn, 00363 true, 00364 getTracingSegment()); 00365 modPageEntriesMap.clear(); 00366 snapshotPageMap.clear(); 00367 } 00368 00369 void SnapshotRandomAllocationSegment::rollbackChanges() 00370 { 00371 assert(readOnlyCommittedData); 00372 SXMutexExclusiveGuard mapGuard(modPageMapMutex); 00373 00374 pVersionedRandomSegment->updateAllocNodes( 00375 modPageEntriesMap, 00376 NULL_TXN_ID, 00377 false, 00378 getTracingSegment()); 00379 modPageEntriesMap.clear(); 00380 snapshotPageMap.clear(); 00381 } 00382 00383 MappedPageListener *SnapshotRandomAllocationSegment::getMappedPageListener( 00384 BlockId blockId) 00385 { 00386 PageId snapshotId = translateBlockId(blockId); 00387 if (isPageNewlyAllocated(snapshotId)) { 00388 return this; 00389 } else { 00390 return pVersionedRandomSegment; 00391 } 00392 } 00393 00394 void SnapshotRandomAllocationSegment::setForceCacheUnmap() 00395 { 00396 forceCacheUnmap = true; 00397 } 00398 00399 void SnapshotRandomAllocationSegment::delegatedCheckpoint( 00400 Segment &delegatingSegment, 00401 CheckpointType checkpointType) 00402 { 00403
00404
00405
00406
00407
00408
00409 if (needPageFlush || 00410 (checkpointType == CHECKPOINT_FLUSH_AND_UNMAP && forceCacheUnmap)) 00411 { 00412 MappedPageListenerPredicate pagePredicate(delegatingSegment); 00413 pCache->checkpointPages(pagePredicate,checkpointType); 00414 needPageFlush = false; 00415 } 00416 } 00417 00418 MappedPageListener 00419 *SnapshotRandomAllocationSegment::notifyAfterPageCheckpointFlush( 00420 CachePage &page) 00421 { 00422 assert(readOnlyCommittedData); 00423 return pVersionedRandomSegment; 00424 } 00425 00426 bool SnapshotRandomAllocationSegment::canFlushPage(CachePage &page) 00427 { 00428 assert(readOnlyCommittedData); 00429 00430
00431
00432
00433 return true; 00434 } 00435 00436 void SnapshotRandomAllocationSegment::notifyPageDirty( 00437 CachePage &page, 00438 bool bDataValid) 00439 { 00440 assert(readOnlyCommittedData); 00441 00442
00443
00444
00445
00446
00447
00448 if (!bDataValid) { 00449 DelegatingSegment::notifyPageDirty(page, bDataValid); 00450 } 00451 } 00452 00453 void SnapshotRandomAllocationSegment::versionPage( 00454 PageId destAnchorPageId, 00455 PageId srcAnchorPageId) 00456 { 00457 assert(readOnlyCommittedData); 00458 assert(destAnchorPageId == getAnchorPageId(destAnchorPageId)); 00459 assert(srcAnchorPageId == getAnchorPageId(srcAnchorPageId)); 00460 00461 VersionedPageEntry pageEntry; 00462 pVersionedRandomSegment->getLatestPageEntryCopy( 00463 destAnchorPageId, 00464 pageEntry); 00465 TxnId largestDestCsn = pageEntry.allocationCsn; 00466 if (pageEntry.versionChainPageId != destAnchorPageId) { 00467 pVersionedRandomSegment->getLatestPageEntryCopy( 00468 pageEntry.versionChainPageId, 00469 pageEntry); 00470 largestDestCsn = pageEntry.allocationCsn; 00471 } 00472 00473 SXMutexExclusiveGuard mapGuard(modPageMapMutex); 00474 00475
00476
00477
00478 pVersionedRandomSegment->getLatestPageEntryCopy( 00479 srcAnchorPageId, 00480 pageEntry); 00481 assert(pageEntry.allocationCsn >= largestDestCsn); 00482 PageId pageIdAfterSrcAnchor = pageEntry.versionChainPageId; 00483 pVersionedRandomSegment->getLatestPageEntryCopy( 00484 destAnchorPageId, 00485 pageEntry); 00486 PageId pageIdAfterDestAnchor = pageEntry.versionChainPageId; 00487 00488 chainPageEntries(destAnchorPageId, pageIdAfterSrcAnchor, NULL_PAGE_ID); 00489 chainPageEntries(srcAnchorPageId, pageIdAfterDestAnchor, NULL_PAGE_ID); 00490 00491 StrictMutexGuard mutexGuard(snapshotPageMapMutex); 00492 snapshotPageMap[destAnchorPageId] = pageIdAfterSrcAnchor; 00493 } 00494 00495 bool SnapshotRandomAllocationSegment::isWriteVersioned() 00496 { 00497 return true; 00498 } 00499 00500 FENNEL_END_CPPFILE("$Id: //open/dev/fennel/segment/SnapshotRandomAllocationSegment.cpp#16 $"); 00501 00502