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