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