summaryrefslogtreecommitdiff
path: root/src/mongo/db/storage/mmap_v1/record_store_v1_test_help.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/storage/mmap_v1/record_store_v1_test_help.cpp')
-rw-r--r--src/mongo/db/storage/mmap_v1/record_store_v1_test_help.cpp1016
1 files changed, 497 insertions, 519 deletions
diff --git a/src/mongo/db/storage/mmap_v1/record_store_v1_test_help.cpp b/src/mongo/db/storage/mmap_v1/record_store_v1_test_help.cpp
index 7bfaee1867e..12801124b95 100644
--- a/src/mongo/db/storage/mmap_v1/record_store_v1_test_help.cpp
+++ b/src/mongo/db/storage/mmap_v1/record_store_v1_test_help.cpp
@@ -47,631 +47,609 @@
namespace mongo {
- using std::numeric_limits;
-
- DummyRecordStoreV1MetaData::DummyRecordStoreV1MetaData( bool capped, int userFlags ) {
- _dataSize = 0;
- _numRecords = 0;
- _capped = capped;
- _userFlags = userFlags;
- _lastExtentSize = 0;
- _paddingFactor = 1;
- _maxCappedDocs = numeric_limits<long long>::max();
- _capFirstNewRecord.setInvalid();
- if ( _capped ) {
- // copied from NamespaceDetails::NamespaceDetails()
- setDeletedListEntry( NULL, 1, DiskLoc().setInvalid() );
- }
- }
-
- const DiskLoc& DummyRecordStoreV1MetaData::capExtent() const {
- return _capExtent;
- }
-
- void DummyRecordStoreV1MetaData::setCapExtent( OperationContext* txn,
- const DiskLoc& loc ) {
- _capExtent = loc;
- }
-
- const DiskLoc& DummyRecordStoreV1MetaData::capFirstNewRecord() const {
- return _capFirstNewRecord;
- }
-
- void DummyRecordStoreV1MetaData::setCapFirstNewRecord( OperationContext* txn,
- const DiskLoc& loc ) {
- _capFirstNewRecord = loc;
- }
-
- long long DummyRecordStoreV1MetaData::dataSize() const {
- return _dataSize;
+using std::numeric_limits;
+
+DummyRecordStoreV1MetaData::DummyRecordStoreV1MetaData(bool capped, int userFlags) {
+ _dataSize = 0;
+ _numRecords = 0;
+ _capped = capped;
+ _userFlags = userFlags;
+ _lastExtentSize = 0;
+ _paddingFactor = 1;
+ _maxCappedDocs = numeric_limits<long long>::max();
+ _capFirstNewRecord.setInvalid();
+ if (_capped) {
+ // copied from NamespaceDetails::NamespaceDetails()
+ setDeletedListEntry(NULL, 1, DiskLoc().setInvalid());
}
+}
- long long DummyRecordStoreV1MetaData::numRecords() const {
- return _numRecords;
- }
+const DiskLoc& DummyRecordStoreV1MetaData::capExtent() const {
+ return _capExtent;
+}
- void DummyRecordStoreV1MetaData::incrementStats( OperationContext* txn,
- long long dataSizeIncrement,
- long long numRecordsIncrement ) {
- _dataSize += dataSizeIncrement;
- _numRecords += numRecordsIncrement;
- }
+void DummyRecordStoreV1MetaData::setCapExtent(OperationContext* txn, const DiskLoc& loc) {
+ _capExtent = loc;
+}
- void DummyRecordStoreV1MetaData::setStats( OperationContext* txn,
- long long dataSize,
- long long numRecords ) {
- _dataSize = dataSize;
- _numRecords = numRecords;
- }
+const DiskLoc& DummyRecordStoreV1MetaData::capFirstNewRecord() const {
+ return _capFirstNewRecord;
+}
- namespace {
- DiskLoc myNull;
- }
+void DummyRecordStoreV1MetaData::setCapFirstNewRecord(OperationContext* txn, const DiskLoc& loc) {
+ _capFirstNewRecord = loc;
+}
- DiskLoc DummyRecordStoreV1MetaData::deletedListEntry( int bucket ) const {
- invariant( bucket >= 0 );
- if ( static_cast<size_t>( bucket ) >= _deletedLists.size() )
- return myNull;
- return _deletedLists[bucket];
- }
+long long DummyRecordStoreV1MetaData::dataSize() const {
+ return _dataSize;
+}
- void DummyRecordStoreV1MetaData::setDeletedListEntry( OperationContext* txn,
- int bucket,
- const DiskLoc& loc ) {
- invariant( bucket >= 0 );
- invariant( bucket < 1000 );
- while ( static_cast<size_t>( bucket ) >= _deletedLists.size() )
- _deletedLists.push_back( DiskLoc() );
- _deletedLists[bucket] = loc;
- }
+long long DummyRecordStoreV1MetaData::numRecords() const {
+ return _numRecords;
+}
- DiskLoc DummyRecordStoreV1MetaData::deletedListLegacyGrabBag() const {
- return _deletedListLegacyGrabBag;
- }
+void DummyRecordStoreV1MetaData::incrementStats(OperationContext* txn,
+ long long dataSizeIncrement,
+ long long numRecordsIncrement) {
+ _dataSize += dataSizeIncrement;
+ _numRecords += numRecordsIncrement;
+}
- void DummyRecordStoreV1MetaData::setDeletedListLegacyGrabBag(OperationContext* txn,
- const DiskLoc& loc) {
- _deletedListLegacyGrabBag = loc;
- }
+void DummyRecordStoreV1MetaData::setStats(OperationContext* txn,
+ long long dataSize,
+ long long numRecords) {
+ _dataSize = dataSize;
+ _numRecords = numRecords;
+}
- void DummyRecordStoreV1MetaData::orphanDeletedList(OperationContext* txn) {
- // They will be recreated on demand.
- _deletedLists.clear();
- }
+namespace {
+DiskLoc myNull;
+}
- const DiskLoc& DummyRecordStoreV1MetaData::firstExtent(OperationContext* txn) const {
- return _firstExtent;
- }
+DiskLoc DummyRecordStoreV1MetaData::deletedListEntry(int bucket) const {
+ invariant(bucket >= 0);
+ if (static_cast<size_t>(bucket) >= _deletedLists.size())
+ return myNull;
+ return _deletedLists[bucket];
+}
- void DummyRecordStoreV1MetaData::setFirstExtent( OperationContext* txn,
- const DiskLoc& loc ) {
- _firstExtent = loc;
- }
+void DummyRecordStoreV1MetaData::setDeletedListEntry(OperationContext* txn,
+ int bucket,
+ const DiskLoc& loc) {
+ invariant(bucket >= 0);
+ invariant(bucket < 1000);
+ while (static_cast<size_t>(bucket) >= _deletedLists.size())
+ _deletedLists.push_back(DiskLoc());
+ _deletedLists[bucket] = loc;
+}
- const DiskLoc& DummyRecordStoreV1MetaData::lastExtent(OperationContext* txn) const {
- return _lastExtent;
- }
+DiskLoc DummyRecordStoreV1MetaData::deletedListLegacyGrabBag() const {
+ return _deletedListLegacyGrabBag;
+}
- void DummyRecordStoreV1MetaData::setLastExtent( OperationContext* txn,
- const DiskLoc& loc ) {
- _lastExtent = loc;
- }
+void DummyRecordStoreV1MetaData::setDeletedListLegacyGrabBag(OperationContext* txn,
+ const DiskLoc& loc) {
+ _deletedListLegacyGrabBag = loc;
+}
- bool DummyRecordStoreV1MetaData::isCapped() const {
- return _capped;
- }
+void DummyRecordStoreV1MetaData::orphanDeletedList(OperationContext* txn) {
+ // They will be recreated on demand.
+ _deletedLists.clear();
+}
- bool DummyRecordStoreV1MetaData::isUserFlagSet( int flag ) const {
- return _userFlags & flag;
- }
+const DiskLoc& DummyRecordStoreV1MetaData::firstExtent(OperationContext* txn) const {
+ return _firstExtent;
+}
- bool DummyRecordStoreV1MetaData::setUserFlag( OperationContext* txn, int flag ) {
- if ( ( _userFlags & flag ) == flag )
- return false;
+void DummyRecordStoreV1MetaData::setFirstExtent(OperationContext* txn, const DiskLoc& loc) {
+ _firstExtent = loc;
+}
- _userFlags |= flag;
- return true;
+const DiskLoc& DummyRecordStoreV1MetaData::lastExtent(OperationContext* txn) const {
+ return _lastExtent;
+}
- }
- bool DummyRecordStoreV1MetaData::clearUserFlag( OperationContext* txn, int flag ) {
- if ( ( _userFlags & flag ) == 0 )
- return false;
+void DummyRecordStoreV1MetaData::setLastExtent(OperationContext* txn, const DiskLoc& loc) {
+ _lastExtent = loc;
+}
- _userFlags &= ~flag;
- return true;
+bool DummyRecordStoreV1MetaData::isCapped() const {
+ return _capped;
+}
- }
- bool DummyRecordStoreV1MetaData::replaceUserFlags( OperationContext* txn, int flags ) {
- if ( _userFlags == flags )
- return false;
- _userFlags = flags;
- return true;
- }
+bool DummyRecordStoreV1MetaData::isUserFlagSet(int flag) const {
+ return _userFlags & flag;
+}
+bool DummyRecordStoreV1MetaData::setUserFlag(OperationContext* txn, int flag) {
+ if ((_userFlags & flag) == flag)
+ return false;
- int DummyRecordStoreV1MetaData::lastExtentSize(OperationContext* txn) const {
- return _lastExtentSize;
- }
+ _userFlags |= flag;
+ return true;
+}
+bool DummyRecordStoreV1MetaData::clearUserFlag(OperationContext* txn, int flag) {
+ if ((_userFlags & flag) == 0)
+ return false;
- void DummyRecordStoreV1MetaData::setLastExtentSize( OperationContext* txn, int newMax ) {
- _lastExtentSize = newMax;
- }
+ _userFlags &= ~flag;
+ return true;
+}
+bool DummyRecordStoreV1MetaData::replaceUserFlags(OperationContext* txn, int flags) {
+ if (_userFlags == flags)
+ return false;
+ _userFlags = flags;
+ return true;
+}
- long long DummyRecordStoreV1MetaData::maxCappedDocs() const {
- return _maxCappedDocs;
- }
- // -----------------------------------------
+int DummyRecordStoreV1MetaData::lastExtentSize(OperationContext* txn) const {
+ return _lastExtentSize;
+}
- DummyExtentManager::~DummyExtentManager() {
- for ( size_t i = 0; i < _extents.size(); i++ ) {
- if ( _extents[i].data )
- free( _extents[i].data );
- }
- }
+void DummyRecordStoreV1MetaData::setLastExtentSize(OperationContext* txn, int newMax) {
+ _lastExtentSize = newMax;
+}
- Status DummyExtentManager::init(OperationContext* txn) {
- return Status::OK();
- }
+long long DummyRecordStoreV1MetaData::maxCappedDocs() const {
+ return _maxCappedDocs;
+}
- int DummyExtentManager::numFiles() const {
- return static_cast<int>( _extents.size() );
- }
+// -----------------------------------------
- long long DummyExtentManager::fileSize() const {
- invariant( false );
- return -1;
+DummyExtentManager::~DummyExtentManager() {
+ for (size_t i = 0; i < _extents.size(); i++) {
+ if (_extents[i].data)
+ free(_extents[i].data);
}
+}
- DiskLoc DummyExtentManager::allocateExtent( OperationContext* txn,
- bool capped,
- int size,
- bool enforceQuota ) {
- size = quantizeExtentSize( size );
+Status DummyExtentManager::init(OperationContext* txn) {
+ return Status::OK();
+}
- ExtentInfo info;
- info.data = static_cast<char*>( mongoMalloc( size ) );
- info.length = size;
+int DummyExtentManager::numFiles() const {
+ return static_cast<int>(_extents.size());
+}
- DiskLoc loc( _extents.size(), 0 );
- _extents.push_back( info );
+long long DummyExtentManager::fileSize() const {
+ invariant(false);
+ return -1;
+}
- Extent* e = getExtent( loc, false );
- e->magic = Extent::extentSignature;
- e->myLoc = loc;
- e->xnext.Null();
- e->xprev.Null();
- e->length = size;
- e->firstRecord.Null();
- e->lastRecord.Null();
+DiskLoc DummyExtentManager::allocateExtent(OperationContext* txn,
+ bool capped,
+ int size,
+ bool enforceQuota) {
+ size = quantizeExtentSize(size);
+
+ ExtentInfo info;
+ info.data = static_cast<char*>(mongoMalloc(size));
+ info.length = size;
+
+ DiskLoc loc(_extents.size(), 0);
+ _extents.push_back(info);
+
+ Extent* e = getExtent(loc, false);
+ e->magic = Extent::extentSignature;
+ e->myLoc = loc;
+ e->xnext.Null();
+ e->xprev.Null();
+ e->length = size;
+ e->firstRecord.Null();
+ e->lastRecord.Null();
+
+ return loc;
+}
- return loc;
+void DummyExtentManager::freeExtents(OperationContext* txn, DiskLoc firstExt, DiskLoc lastExt) {
+ // XXX
+}
- }
+void DummyExtentManager::freeExtent(OperationContext* txn, DiskLoc extent) {
+ // XXX
+}
+void DummyExtentManager::freeListStats(OperationContext* txn,
+ int* numExtents,
+ int64_t* totalFreeSizeBytes) const {
+ invariant(false);
+}
- void DummyExtentManager::freeExtents( OperationContext* txn,
- DiskLoc firstExt, DiskLoc lastExt ) {
- // XXX
- }
+std::unique_ptr<RecordFetcher> DummyExtentManager::recordNeedsFetch(const DiskLoc& loc) const {
+ return {};
+}
- void DummyExtentManager::freeExtent( OperationContext* txn, DiskLoc extent ) {
- // XXX
- }
- void DummyExtentManager::freeListStats(OperationContext* txn,
- int* numExtents,
- int64_t* totalFreeSizeBytes) const {
- invariant(false);
- }
+MmapV1RecordHeader* DummyExtentManager::recordForV1(const DiskLoc& loc) const {
+ if (static_cast<size_t>(loc.a()) >= _extents.size())
+ return NULL;
+ if (static_cast<size_t>(loc.getOfs()) >= _extents[loc.a()].length)
+ return NULL;
+ char* root = _extents[loc.a()].data;
+ return reinterpret_cast<MmapV1RecordHeader*>(root + loc.getOfs());
+}
- std::unique_ptr<RecordFetcher> DummyExtentManager::recordNeedsFetch(const DiskLoc& loc) const {
- return {};
- }
+Extent* DummyExtentManager::extentForV1(const DiskLoc& loc) const {
+ invariant(false);
+}
- MmapV1RecordHeader* DummyExtentManager::recordForV1( const DiskLoc& loc ) const {
- if ( static_cast<size_t>( loc.a() ) >= _extents.size() )
- return NULL;
- if ( static_cast<size_t>( loc.getOfs() ) >= _extents[loc.a()].length )
- return NULL;
- char* root = _extents[loc.a()].data;
- return reinterpret_cast<MmapV1RecordHeader*>( root + loc.getOfs() );
- }
+DiskLoc DummyExtentManager::extentLocForV1(const DiskLoc& loc) const {
+ return DiskLoc(loc.a(), 0);
+}
- Extent* DummyExtentManager::extentForV1( const DiskLoc& loc ) const {
- invariant( false );
- }
+Extent* DummyExtentManager::getExtent(const DiskLoc& loc, bool doSanityCheck) const {
+ invariant(!loc.isNull());
+ invariant(static_cast<size_t>(loc.a()) < _extents.size());
+ invariant(loc.getOfs() == 0);
+ Extent* ext = reinterpret_cast<Extent*>(_extents[loc.a()].data);
+ if (doSanityCheck)
+ ext->assertOk();
+ return ext;
+}
- DiskLoc DummyExtentManager::extentLocForV1( const DiskLoc& loc ) const {
- return DiskLoc( loc.a(), 0 );
- }
+int DummyExtentManager::maxSize() const {
+ return 1024 * 1024 * 64;
+}
- Extent* DummyExtentManager::getExtent( const DiskLoc& loc, bool doSanityCheck ) const {
- invariant( !loc.isNull() );
- invariant( static_cast<size_t>( loc.a() ) < _extents.size() );
- invariant( loc.getOfs() == 0 );
- Extent* ext = reinterpret_cast<Extent*>( _extents[loc.a()].data );
- if (doSanityCheck)
- ext->assertOk();
- return ext;
- }
+DummyExtentManager::CacheHint* DummyExtentManager::cacheHint(const DiskLoc& extentLoc,
+ const HintType& hint) {
+ return new CacheHint();
+}
- int DummyExtentManager::maxSize() const {
- return 1024 * 1024 * 64;
- }
+namespace {
+void accumulateExtentSizeRequirements(const LocAndSize* las, std::map<int, size_t>* sizes) {
+ if (!las)
+ return;
- DummyExtentManager::CacheHint* DummyExtentManager::cacheHint( const DiskLoc& extentLoc, const HintType& hint ) {
- return new CacheHint();
- }
+ while (!las->loc.isNull()) {
+ // We require passed in offsets to be > 1000 to leave room for Extent headers.
+ invariant(Extent::HeaderSize() < 1000);
+ invariant(las->loc.getOfs() >= 1000);
-namespace {
- void accumulateExtentSizeRequirements(const LocAndSize* las, std::map<int, size_t>* sizes) {
- if (!las)
- return;
-
- while (!las->loc.isNull()) {
- // We require passed in offsets to be > 1000 to leave room for Extent headers.
- invariant(Extent::HeaderSize() < 1000);
- invariant(las->loc.getOfs() >= 1000);
-
- const size_t end = las->loc.getOfs() + las->size;
- size_t& sizeNeeded = (*sizes)[las->loc.a()];
- sizeNeeded = std::max(sizeNeeded, end);
- las++;
- }
+ const size_t end = las->loc.getOfs() + las->size;
+ size_t& sizeNeeded = (*sizes)[las->loc.a()];
+ sizeNeeded = std::max(sizeNeeded, end);
+ las++;
}
+}
- void printRecList(OperationContext* txn,
- const ExtentManager* em,
- const RecordStoreV1MetaData* md) {
- log() << " *** BEGIN ACTUAL RECORD LIST *** ";
- DiskLoc extLoc = md->firstExtent(txn);
- std::set<DiskLoc> seenLocs;
- while (!extLoc.isNull()) {
- Extent* ext = em->getExtent(extLoc, true);
- DiskLoc actualLoc = ext->firstRecord;
- while (!actualLoc.isNull()) {
- const MmapV1RecordHeader* actualRec = em->recordForV1(actualLoc);
- const int actualSize = actualRec->lengthWithHeaders();
-
- log() << "loc: " << actualLoc // <--hex
- << " (" << actualLoc.getOfs() << ")"
- << " size: " << actualSize
- << " prev: " << actualRec->prevOfs()
- << " next: " << actualRec->nextOfs()
- << (actualLoc == md->capFirstNewRecord() ? " (CAP_FIRST_NEW)" : "")
- ;
-
- const bool foundCycle = !seenLocs.insert(actualLoc).second;
- invariant(!foundCycle);
-
- const int nextOfs = actualRec->nextOfs();
- actualLoc = (nextOfs == DiskLoc::NullOfs ? DiskLoc()
- : DiskLoc(actualLoc.a(), nextOfs));
- }
- extLoc = ext->xnext;
+void printRecList(OperationContext* txn, const ExtentManager* em, const RecordStoreV1MetaData* md) {
+ log() << " *** BEGIN ACTUAL RECORD LIST *** ";
+ DiskLoc extLoc = md->firstExtent(txn);
+ std::set<DiskLoc> seenLocs;
+ while (!extLoc.isNull()) {
+ Extent* ext = em->getExtent(extLoc, true);
+ DiskLoc actualLoc = ext->firstRecord;
+ while (!actualLoc.isNull()) {
+ const MmapV1RecordHeader* actualRec = em->recordForV1(actualLoc);
+ const int actualSize = actualRec->lengthWithHeaders();
+
+ log() << "loc: " << actualLoc // <--hex
+ << " (" << actualLoc.getOfs() << ")"
+ << " size: " << actualSize << " prev: " << actualRec->prevOfs()
+ << " next: " << actualRec->nextOfs()
+ << (actualLoc == md->capFirstNewRecord() ? " (CAP_FIRST_NEW)" : "");
+
+ const bool foundCycle = !seenLocs.insert(actualLoc).second;
+ invariant(!foundCycle);
+
+ const int nextOfs = actualRec->nextOfs();
+ actualLoc = (nextOfs == DiskLoc::NullOfs ? DiskLoc() : DiskLoc(actualLoc.a(), nextOfs));
}
- log() << " *** END ACTUAL RECORD LIST *** ";
+ extLoc = ext->xnext;
}
+ log() << " *** END ACTUAL RECORD LIST *** ";
+}
- void printDRecList(const ExtentManager* em, const RecordStoreV1MetaData* md) {
- log() << " *** BEGIN ACTUAL DELETED RECORD LIST *** ";
- std::set<DiskLoc> seenLocs;
- for (int bucketIdx = 0; bucketIdx < RecordStoreV1Base::Buckets; bucketIdx++) {
- DiskLoc actualLoc = md->deletedListEntry(bucketIdx);
- while (!actualLoc.isNull()) {
- const DeletedRecord* actualDrec = &em->recordForV1(actualLoc)->asDeleted();
- const int actualSize = actualDrec->lengthWithHeaders();
+void printDRecList(const ExtentManager* em, const RecordStoreV1MetaData* md) {
+ log() << " *** BEGIN ACTUAL DELETED RECORD LIST *** ";
+ std::set<DiskLoc> seenLocs;
+ for (int bucketIdx = 0; bucketIdx < RecordStoreV1Base::Buckets; bucketIdx++) {
+ DiskLoc actualLoc = md->deletedListEntry(bucketIdx);
+ while (!actualLoc.isNull()) {
+ const DeletedRecord* actualDrec = &em->recordForV1(actualLoc)->asDeleted();
+ const int actualSize = actualDrec->lengthWithHeaders();
- log() << "loc: " << actualLoc // <--hex
- << " (" << actualLoc.getOfs() << ")"
- << " size: " << actualSize
- << " bucket: " << bucketIdx
- << " next: " << actualDrec->nextDeleted();
+ log() << "loc: " << actualLoc // <--hex
+ << " (" << actualLoc.getOfs() << ")"
+ << " size: " << actualSize << " bucket: " << bucketIdx
+ << " next: " << actualDrec->nextDeleted();
- const bool foundCycle = !seenLocs.insert(actualLoc).second;
- invariant(!foundCycle);
+ const bool foundCycle = !seenLocs.insert(actualLoc).second;
+ invariant(!foundCycle);
- actualLoc = actualDrec->nextDeleted();
- }
-
- // Only print bucket 0 in capped collections since it contains all deleted records
- if (md->isCapped())
- break;
+ actualLoc = actualDrec->nextDeleted();
}
- log() << " *** END ACTUAL DELETED RECORD LIST *** ";
+
+ // Only print bucket 0 in capped collections since it contains all deleted records
+ if (md->isCapped())
+ break;
}
+ log() << " *** END ACTUAL DELETED RECORD LIST *** ";
+}
}
- void initializeV1RS(OperationContext* txn,
- const LocAndSize* records,
- const LocAndSize* drecs,
- const LocAndSize* legacyGrabBag,
- DummyExtentManager* em,
- DummyRecordStoreV1MetaData* md) {
- invariant(records || drecs); // if both are NULL nothing is being created...
-
- // Need to start with a blank slate
- invariant(em->numFiles() == 0);
- invariant(md->firstExtent(txn).isNull());
-
- // pre-allocate extents (even extents that aren't part of this RS)
- {
- typedef std::map<int, size_t> ExtentSizes;
- ExtentSizes extentSizes;
- accumulateExtentSizeRequirements(records, &extentSizes);
- accumulateExtentSizeRequirements(drecs, &extentSizes);
- accumulateExtentSizeRequirements(legacyGrabBag, &extentSizes);
- invariant(!extentSizes.empty());
-
- const int maxExtent = extentSizes.rbegin()->first;
- for (int i = 0; i <= maxExtent; i++) {
- const size_t size = extentSizes.count(i) ? extentSizes[i] : 0;
- const DiskLoc loc = em->allocateExtent(txn, md->isCapped(), size, 0);
-
- // This function and assertState depend on these details of DummyExtentManager
- invariant(loc.a() == i);
- invariant(loc.getOfs() == 0);
- }
-
- // link together extents that should be part of this RS
- md->setFirstExtent(txn, DiskLoc(extentSizes.begin()->first, 0));
- md->setLastExtent(txn, DiskLoc(extentSizes.rbegin()->first, 0));
- for (ExtentSizes::iterator it = extentSizes.begin();
- boost::next(it) != extentSizes.end(); /* ++it */ ) {
- const int a = it->first;
- ++it;
- const int b = it->first;
- em->getExtent(DiskLoc(a, 0))->xnext = DiskLoc(b, 0);
- em->getExtent(DiskLoc(b, 0))->xprev = DiskLoc(a, 0);
- }
+void initializeV1RS(OperationContext* txn,
+ const LocAndSize* records,
+ const LocAndSize* drecs,
+ const LocAndSize* legacyGrabBag,
+ DummyExtentManager* em,
+ DummyRecordStoreV1MetaData* md) {
+ invariant(records || drecs); // if both are NULL nothing is being created...
+
+ // Need to start with a blank slate
+ invariant(em->numFiles() == 0);
+ invariant(md->firstExtent(txn).isNull());
+
+ // pre-allocate extents (even extents that aren't part of this RS)
+ {
+ typedef std::map<int, size_t> ExtentSizes;
+ ExtentSizes extentSizes;
+ accumulateExtentSizeRequirements(records, &extentSizes);
+ accumulateExtentSizeRequirements(drecs, &extentSizes);
+ accumulateExtentSizeRequirements(legacyGrabBag, &extentSizes);
+ invariant(!extentSizes.empty());
+
+ const int maxExtent = extentSizes.rbegin()->first;
+ for (int i = 0; i <= maxExtent; i++) {
+ const size_t size = extentSizes.count(i) ? extentSizes[i] : 0;
+ const DiskLoc loc = em->allocateExtent(txn, md->isCapped(), size, 0);
+
+ // This function and assertState depend on these details of DummyExtentManager
+ invariant(loc.a() == i);
+ invariant(loc.getOfs() == 0);
+ }
- // This signals "done allocating new extents".
- if (md->isCapped())
- md->setDeletedListEntry(txn, 1, DiskLoc());
+ // link together extents that should be part of this RS
+ md->setFirstExtent(txn, DiskLoc(extentSizes.begin()->first, 0));
+ md->setLastExtent(txn, DiskLoc(extentSizes.rbegin()->first, 0));
+ for (ExtentSizes::iterator it = extentSizes.begin(); boost::next(it) != extentSizes.end();
+ /* ++it */) {
+ const int a = it->first;
+ ++it;
+ const int b = it->first;
+ em->getExtent(DiskLoc(a, 0))->xnext = DiskLoc(b, 0);
+ em->getExtent(DiskLoc(b, 0))->xprev = DiskLoc(a, 0);
}
- if (records && !records[0].loc.isNull()) {
- int recIdx = 0;
- DiskLoc extLoc = md->firstExtent(txn);
- while (!extLoc.isNull()) {
- Extent* ext = em->getExtent(extLoc);
- int prevOfs = DiskLoc::NullOfs;
- while (extLoc.a() == records[recIdx].loc.a()) { // for all records in this extent
- const DiskLoc loc = records[recIdx].loc;
- const int size = records[recIdx].size;;
- invariant(size >= MmapV1RecordHeader::HeaderSize);
+ // This signals "done allocating new extents".
+ if (md->isCapped())
+ md->setDeletedListEntry(txn, 1, DiskLoc());
+ }
- md->incrementStats(txn, size - MmapV1RecordHeader::HeaderSize, 1);
+ if (records && !records[0].loc.isNull()) {
+ int recIdx = 0;
+ DiskLoc extLoc = md->firstExtent(txn);
+ while (!extLoc.isNull()) {
+ Extent* ext = em->getExtent(extLoc);
+ int prevOfs = DiskLoc::NullOfs;
+ while (extLoc.a() == records[recIdx].loc.a()) { // for all records in this extent
+ const DiskLoc loc = records[recIdx].loc;
+ const int size = records[recIdx].size;
+ ;
+ invariant(size >= MmapV1RecordHeader::HeaderSize);
- if (ext->firstRecord.isNull())
- ext->firstRecord = loc;
+ md->incrementStats(txn, size - MmapV1RecordHeader::HeaderSize, 1);
- MmapV1RecordHeader* rec = em->recordForV1(loc);
- rec->lengthWithHeaders() = size;
- rec->extentOfs() = 0;
+ if (ext->firstRecord.isNull())
+ ext->firstRecord = loc;
- rec->prevOfs() = prevOfs;
- prevOfs = loc.getOfs();
+ MmapV1RecordHeader* rec = em->recordForV1(loc);
+ rec->lengthWithHeaders() = size;
+ rec->extentOfs() = 0;
- const DiskLoc nextLoc = records[recIdx + 1].loc;
- if (nextLoc.a() == loc.a()) { // if next is in same extent
- rec->nextOfs() = nextLoc.getOfs();
- }
- else {
- rec->nextOfs() = DiskLoc::NullOfs;
- ext->lastRecord = loc;
- }
+ rec->prevOfs() = prevOfs;
+ prevOfs = loc.getOfs();
- recIdx++;
+ const DiskLoc nextLoc = records[recIdx + 1].loc;
+ if (nextLoc.a() == loc.a()) { // if next is in same extent
+ rec->nextOfs() = nextLoc.getOfs();
+ } else {
+ rec->nextOfs() = DiskLoc::NullOfs;
+ ext->lastRecord = loc;
}
- extLoc = ext->xnext;
+
+ recIdx++;
}
- invariant(records[recIdx].loc.isNull());
+ extLoc = ext->xnext;
}
-
- if (drecs && !drecs[0].loc.isNull()) {
- int drecIdx = 0;
- DiskLoc* prevNextPtr = NULL;
- int lastBucket = -1;
- while (!drecs[drecIdx].loc.isNull()) {
- const DiskLoc loc = drecs[drecIdx].loc;
- const int size = drecs[drecIdx].size;
- invariant(size >= MmapV1RecordHeader::HeaderSize);
- const int bucket = RecordStoreV1Base::bucket(size);
-
- if (md->isCapped()) {
- // All drecs form a single list in bucket 0
- if (prevNextPtr == NULL) {
- md->setDeletedListEntry(txn, 0, loc);
- }
- else {
- *prevNextPtr = loc;
- }
-
- if (loc.a() < md->capExtent().a()
- && drecs[drecIdx + 1].loc.a() == md->capExtent().a()) {
- // Bucket 1 is known as cappedLastDelRecLastExtent
- md->setDeletedListEntry(txn, 1, loc);
- }
- }
- else if (bucket != lastBucket) {
- invariant(bucket > lastBucket); // if this fails, drecs weren't sorted by bucket
- md->setDeletedListEntry(txn, bucket, loc);
- lastBucket = bucket;
- }
- else {
+ invariant(records[recIdx].loc.isNull());
+ }
+
+ if (drecs && !drecs[0].loc.isNull()) {
+ int drecIdx = 0;
+ DiskLoc* prevNextPtr = NULL;
+ int lastBucket = -1;
+ while (!drecs[drecIdx].loc.isNull()) {
+ const DiskLoc loc = drecs[drecIdx].loc;
+ const int size = drecs[drecIdx].size;
+ invariant(size >= MmapV1RecordHeader::HeaderSize);
+ const int bucket = RecordStoreV1Base::bucket(size);
+
+ if (md->isCapped()) {
+ // All drecs form a single list in bucket 0
+ if (prevNextPtr == NULL) {
+ md->setDeletedListEntry(txn, 0, loc);
+ } else {
*prevNextPtr = loc;
}
- DeletedRecord* drec = &em->recordForV1(loc)->asDeleted();
- drec->lengthWithHeaders() = size;
- drec->extentOfs() = 0;
- drec->nextDeleted() = DiskLoc();
- prevNextPtr = &drec->nextDeleted();
-
- drecIdx++;
+ if (loc.a() < md->capExtent().a() &&
+ drecs[drecIdx + 1].loc.a() == md->capExtent().a()) {
+ // Bucket 1 is known as cappedLastDelRecLastExtent
+ md->setDeletedListEntry(txn, 1, loc);
+ }
+ } else if (bucket != lastBucket) {
+ invariant(bucket > lastBucket); // if this fails, drecs weren't sorted by bucket
+ md->setDeletedListEntry(txn, bucket, loc);
+ lastBucket = bucket;
+ } else {
+ *prevNextPtr = loc;
}
- }
- if (legacyGrabBag && !legacyGrabBag[0].loc.isNull()) {
- invariant(!md->isCapped()); // capped should have an empty legacy grab bag.
+ DeletedRecord* drec = &em->recordForV1(loc)->asDeleted();
+ drec->lengthWithHeaders() = size;
+ drec->extentOfs() = 0;
+ drec->nextDeleted() = DiskLoc();
+ prevNextPtr = &drec->nextDeleted();
- int grabBagIdx = 0;
- DiskLoc* prevNextPtr = NULL;
- while (!legacyGrabBag[grabBagIdx].loc.isNull()) {
- const DiskLoc loc = legacyGrabBag[grabBagIdx].loc;
- const int size = legacyGrabBag[grabBagIdx].size;
- invariant(size >= MmapV1RecordHeader::HeaderSize);
+ drecIdx++;
+ }
+ }
- if (grabBagIdx == 0) {
- md->setDeletedListLegacyGrabBag(txn, loc);
- }
- else {
- *prevNextPtr = loc;
- }
+ if (legacyGrabBag && !legacyGrabBag[0].loc.isNull()) {
+ invariant(!md->isCapped()); // capped should have an empty legacy grab bag.
- DeletedRecord* drec = &em->recordForV1(loc)->asDeleted();
- drec->lengthWithHeaders() = size;
- drec->extentOfs() = 0;
- drec->nextDeleted() = DiskLoc();
- prevNextPtr = &drec->nextDeleted();
+ int grabBagIdx = 0;
+ DiskLoc* prevNextPtr = NULL;
+ while (!legacyGrabBag[grabBagIdx].loc.isNull()) {
+ const DiskLoc loc = legacyGrabBag[grabBagIdx].loc;
+ const int size = legacyGrabBag[grabBagIdx].size;
+ invariant(size >= MmapV1RecordHeader::HeaderSize);
- grabBagIdx++;
+ if (grabBagIdx == 0) {
+ md->setDeletedListLegacyGrabBag(txn, loc);
+ } else {
+ *prevNextPtr = loc;
}
- }
- // Make sure we set everything up as requested.
- assertStateV1RS(txn, records, drecs, legacyGrabBag, em, md);
+ DeletedRecord* drec = &em->recordForV1(loc)->asDeleted();
+ drec->lengthWithHeaders() = size;
+ drec->extentOfs() = 0;
+ drec->nextDeleted() = DiskLoc();
+ prevNextPtr = &drec->nextDeleted();
+
+ grabBagIdx++;
+ }
}
- void assertStateV1RS(OperationContext* txn,
- const LocAndSize* records,
- const LocAndSize* drecs,
- const LocAndSize* legacyGrabBag,
- const ExtentManager* em,
- const DummyRecordStoreV1MetaData* md) {
- invariant(records || drecs); // if both are NULL nothing is being asserted...
-
- try {
- if (records) {
- long long dataSize = 0;
- long long numRecs = 0;
-
- int recIdx = 0;
-
- DiskLoc extLoc = md->firstExtent(txn);
- while (!extLoc.isNull()) { // for each Extent
- Extent* ext = em->getExtent(extLoc, true);
- int expectedPrevOfs = DiskLoc::NullOfs;
- DiskLoc actualLoc = ext->firstRecord;
- while (!actualLoc.isNull()) { // for each MmapV1RecordHeader in this Extent
- const MmapV1RecordHeader* actualRec = em->recordForV1(actualLoc);
- const int actualSize = actualRec->lengthWithHeaders();
-
- dataSize += actualSize - MmapV1RecordHeader::HeaderSize;
- numRecs += 1;
-
- ASSERT_EQUALS(actualLoc, records[recIdx].loc);
- ASSERT_EQUALS(actualSize, records[recIdx].size);
-
- ASSERT_EQUALS(actualRec->extentOfs(), extLoc.getOfs());
- ASSERT_EQUALS(actualRec->prevOfs(), expectedPrevOfs);
- expectedPrevOfs = actualLoc.getOfs();
-
- recIdx++;
- const int nextOfs = actualRec->nextOfs();
- actualLoc = (nextOfs == DiskLoc::NullOfs ? DiskLoc()
- : DiskLoc(actualLoc.a(), nextOfs));
- }
+ // Make sure we set everything up as requested.
+ assertStateV1RS(txn, records, drecs, legacyGrabBag, em, md);
+}
- if (ext->xnext.isNull()) {
- ASSERT_EQUALS(md->lastExtent(txn), extLoc);
- }
+void assertStateV1RS(OperationContext* txn,
+ const LocAndSize* records,
+ const LocAndSize* drecs,
+ const LocAndSize* legacyGrabBag,
+ const ExtentManager* em,
+ const DummyRecordStoreV1MetaData* md) {
+ invariant(records || drecs); // if both are NULL nothing is being asserted...
- extLoc = ext->xnext;
- }
+ try {
+ if (records) {
+ long long dataSize = 0;
+ long long numRecs = 0;
- // both the expected and actual record lists must be done at this point
- ASSERT_EQUALS(records[recIdx].loc, DiskLoc());
+ int recIdx = 0;
- ASSERT_EQUALS(dataSize, md->dataSize());
- ASSERT_EQUALS(numRecs, md->numRecords());
- }
+ DiskLoc extLoc = md->firstExtent(txn);
+ while (!extLoc.isNull()) { // for each Extent
+ Extent* ext = em->getExtent(extLoc, true);
+ int expectedPrevOfs = DiskLoc::NullOfs;
+ DiskLoc actualLoc = ext->firstRecord;
+ while (!actualLoc.isNull()) { // for each MmapV1RecordHeader in this Extent
+ const MmapV1RecordHeader* actualRec = em->recordForV1(actualLoc);
+ const int actualSize = actualRec->lengthWithHeaders();
- if (drecs) {
- int drecIdx = 0;
- for (int bucketIdx = 0; bucketIdx < RecordStoreV1Base::Buckets; bucketIdx++) {
- DiskLoc actualLoc = md->deletedListEntry(bucketIdx);
-
- if (md->isCapped() && bucketIdx == 1) {
- // In capped collections, the 2nd bucket (index 1) points to the drec before
- // the first drec in the capExtent. If the capExtent is the first Extent,
- // it should be Null.
-
- if (md->capExtent() == md->firstExtent(txn)) {
- ASSERT_EQUALS(actualLoc, DiskLoc());
- }
- else {
- ASSERT_NOT_EQUALS(actualLoc.a(), md->capExtent().a());
- const DeletedRecord* actualDrec =
- &em->recordForV1(actualLoc)->asDeleted();
- ASSERT_EQUALS(actualDrec->nextDeleted().a(), md->capExtent().a());
- }
-
- // Don't do normal checking of bucket 1 in capped collections. Checking
- // other buckets to verify that they are Null.
- continue;
- }
+ dataSize += actualSize - MmapV1RecordHeader::HeaderSize;
+ numRecs += 1;
- while (!actualLoc.isNull()) {
- const DeletedRecord* actualDrec = &em->recordForV1(actualLoc)->asDeleted();
- const int actualSize = actualDrec->lengthWithHeaders();
+ ASSERT_EQUALS(actualLoc, records[recIdx].loc);
+ ASSERT_EQUALS(actualSize, records[recIdx].size);
+
+ ASSERT_EQUALS(actualRec->extentOfs(), extLoc.getOfs());
+ ASSERT_EQUALS(actualRec->prevOfs(), expectedPrevOfs);
+ expectedPrevOfs = actualLoc.getOfs();
+
+ recIdx++;
+ const int nextOfs = actualRec->nextOfs();
+ actualLoc =
+ (nextOfs == DiskLoc::NullOfs ? DiskLoc() : DiskLoc(actualLoc.a(), nextOfs));
+ }
+
+ if (ext->xnext.isNull()) {
+ ASSERT_EQUALS(md->lastExtent(txn), extLoc);
+ }
- ASSERT_EQUALS(actualLoc, drecs[drecIdx].loc);
- ASSERT_EQUALS(actualSize, drecs[drecIdx].size);
+ extLoc = ext->xnext;
+ }
- // Make sure the drec is correct
- ASSERT_EQUALS(actualDrec->extentOfs(), 0);
+ // both the expected and actual record lists must be done at this point
+ ASSERT_EQUALS(records[recIdx].loc, DiskLoc());
- // in capped collections all drecs are linked into a single list in bucket 0
- ASSERT_EQUALS(bucketIdx, md->isCapped()
- ? 0
- : RecordStoreV1Base::bucket(actualSize));
+ ASSERT_EQUALS(dataSize, md->dataSize());
+ ASSERT_EQUALS(numRecs, md->numRecords());
+ }
- drecIdx++;
- actualLoc = actualDrec->nextDeleted();
+ if (drecs) {
+ int drecIdx = 0;
+ for (int bucketIdx = 0; bucketIdx < RecordStoreV1Base::Buckets; bucketIdx++) {
+ DiskLoc actualLoc = md->deletedListEntry(bucketIdx);
+
+ if (md->isCapped() && bucketIdx == 1) {
+ // In capped collections, the 2nd bucket (index 1) points to the drec before
+ // the first drec in the capExtent. If the capExtent is the first Extent,
+ // it should be Null.
+
+ if (md->capExtent() == md->firstExtent(txn)) {
+ ASSERT_EQUALS(actualLoc, DiskLoc());
+ } else {
+ ASSERT_NOT_EQUALS(actualLoc.a(), md->capExtent().a());
+ const DeletedRecord* actualDrec = &em->recordForV1(actualLoc)->asDeleted();
+ ASSERT_EQUALS(actualDrec->nextDeleted().a(), md->capExtent().a());
}
+
+ // Don't do normal checking of bucket 1 in capped collections. Checking
+ // other buckets to verify that they are Null.
+ continue;
}
- // both the expected and actual deleted lists must be done at this point
- ASSERT_EQUALS(drecs[drecIdx].loc, DiskLoc());
- }
- if (legacyGrabBag) {
- int grabBagIdx = 0;
- DiskLoc actualLoc = md->deletedListLegacyGrabBag();
while (!actualLoc.isNull()) {
const DeletedRecord* actualDrec = &em->recordForV1(actualLoc)->asDeleted();
const int actualSize = actualDrec->lengthWithHeaders();
- ASSERT_EQUALS(actualLoc, legacyGrabBag[grabBagIdx].loc);
- ASSERT_EQUALS(actualSize, legacyGrabBag[grabBagIdx].size);
+ ASSERT_EQUALS(actualLoc, drecs[drecIdx].loc);
+ ASSERT_EQUALS(actualSize, drecs[drecIdx].size);
+
+ // Make sure the drec is correct
+ ASSERT_EQUALS(actualDrec->extentOfs(), 0);
+
+ // in capped collections all drecs are linked into a single list in bucket 0
+ ASSERT_EQUALS(bucketIdx,
+ md->isCapped() ? 0 : RecordStoreV1Base::bucket(actualSize));
- grabBagIdx++;
+ drecIdx++;
actualLoc = actualDrec->nextDeleted();
}
-
- // both the expected and actual deleted lists must be done at this point
- ASSERT_EQUALS(legacyGrabBag[grabBagIdx].loc, DiskLoc());
- }
- else {
- // Unless a test is actually using the grabBag it should be empty
- ASSERT_EQUALS(md->deletedListLegacyGrabBag(), DiskLoc());
}
+ // both the expected and actual deleted lists must be done at this point
+ ASSERT_EQUALS(drecs[drecIdx].loc, DiskLoc());
}
- catch (...) {
- // If a test fails, provide extra info to make debugging easier
- printRecList(txn, em, md);
- printDRecList(em, md);
- throw;
+
+ if (legacyGrabBag) {
+ int grabBagIdx = 0;
+ DiskLoc actualLoc = md->deletedListLegacyGrabBag();
+ while (!actualLoc.isNull()) {
+ const DeletedRecord* actualDrec = &em->recordForV1(actualLoc)->asDeleted();
+ const int actualSize = actualDrec->lengthWithHeaders();
+
+ ASSERT_EQUALS(actualLoc, legacyGrabBag[grabBagIdx].loc);
+ ASSERT_EQUALS(actualSize, legacyGrabBag[grabBagIdx].size);
+
+ grabBagIdx++;
+ actualLoc = actualDrec->nextDeleted();
+ }
+
+ // both the expected and actual deleted lists must be done at this point
+ ASSERT_EQUALS(legacyGrabBag[grabBagIdx].loc, DiskLoc());
+ } else {
+ // Unless a test is actually using the grabBag it should be empty
+ ASSERT_EQUALS(md->deletedListLegacyGrabBag(), DiskLoc());
}
+ } catch (...) {
+ // If a test fails, provide extra info to make debugging easier
+ printRecList(txn, em, md);
+ printDRecList(em, md);
+ throw;
}
}
+}