summaryrefslogtreecommitdiff
path: root/src/mongo/db/storage/mmap_v1/record_store_v1_capped.cpp
diff options
context:
space:
mode:
authorMark Benvenuto <mark.benvenuto@mongodb.com>2015-06-20 00:22:50 -0400
committerMark Benvenuto <mark.benvenuto@mongodb.com>2015-06-20 10:56:02 -0400
commit9c2ed42daa8fbbef4a919c21ec564e2db55e8d60 (patch)
tree3814f79c10d7b490948d8cb7b112ac1dd41ceff1 /src/mongo/db/storage/mmap_v1/record_store_v1_capped.cpp
parent01965cf52bce6976637ecb8f4a622aeb05ab256a (diff)
downloadmongo-9c2ed42daa8fbbef4a919c21ec564e2db55e8d60.tar.gz
SERVER-18579: Clang-Format - reformat code, no comment reflow
Diffstat (limited to 'src/mongo/db/storage/mmap_v1/record_store_v1_capped.cpp')
-rw-r--r--src/mongo/db/storage/mmap_v1/record_store_v1_capped.cpp1068
1 files changed, 520 insertions, 548 deletions
diff --git a/src/mongo/db/storage/mmap_v1/record_store_v1_capped.cpp b/src/mongo/db/storage/mmap_v1/record_store_v1_capped.cpp
index a41dd66ab1e..2674861bdb1 100644
--- a/src/mongo/db/storage/mmap_v1/record_store_v1_capped.cpp
+++ b/src/mongo/db/storage/mmap_v1/record_store_v1_capped.cpp
@@ -62,658 +62,630 @@
namespace mongo {
- using std::dec;
- using std::endl;
- using std::hex;
- using std::vector;
-
- CappedRecordStoreV1::CappedRecordStoreV1( OperationContext* txn,
- CappedDocumentDeleteCallback* collection,
- StringData ns,
- RecordStoreV1MetaData* details,
- ExtentManager* em,
- bool isSystemIndexes )
- : RecordStoreV1Base( ns, details, em, isSystemIndexes ),
- _deleteCallback( collection ) {
-
- DiskLoc extentLoc = details->firstExtent(txn);
- while ( !extentLoc.isNull() ) {
- _extentAdvice.push_back( _extentManager->cacheHint( extentLoc,
- ExtentManager::Sequential ) );
- Extent* extent = em->getExtent( extentLoc );
- extentLoc = extent->xnext;
- }
-
- // this is for VERY VERY old versions of capped collections
- cappedCheckMigrate(txn);
+using std::dec;
+using std::endl;
+using std::hex;
+using std::vector;
+
+CappedRecordStoreV1::CappedRecordStoreV1(OperationContext* txn,
+ CappedDocumentDeleteCallback* collection,
+ StringData ns,
+ RecordStoreV1MetaData* details,
+ ExtentManager* em,
+ bool isSystemIndexes)
+ : RecordStoreV1Base(ns, details, em, isSystemIndexes), _deleteCallback(collection) {
+ DiskLoc extentLoc = details->firstExtent(txn);
+ while (!extentLoc.isNull()) {
+ _extentAdvice.push_back(_extentManager->cacheHint(extentLoc, ExtentManager::Sequential));
+ Extent* extent = em->getExtent(extentLoc);
+ extentLoc = extent->xnext;
}
- CappedRecordStoreV1::~CappedRecordStoreV1() {
- }
+ // this is for VERY VERY old versions of capped collections
+ cappedCheckMigrate(txn);
+}
- StatusWith<DiskLoc> CappedRecordStoreV1::allocRecord( OperationContext* txn,
- int lenToAlloc,
- bool enforceQuota ) {
- {
- // align very slightly.
- lenToAlloc = (lenToAlloc + 3) & 0xfffffffc;
- }
+CappedRecordStoreV1::~CappedRecordStoreV1() {}
- if ( lenToAlloc > theCapExtent()->length ) {
- // the extent check is a way to try and improve performance
- // since we have to iterate all the extents (for now) to get
- // storage size
- if ( lenToAlloc > storageSize(txn) ) {
- return StatusWith<DiskLoc>( ErrorCodes::DocTooLargeForCapped,
- mongoutils::str::stream()
- << "document is larger than capped size "
- << lenToAlloc << " > " << storageSize(txn),
- 16328 );
- }
+StatusWith<DiskLoc> CappedRecordStoreV1::allocRecord(OperationContext* txn,
+ int lenToAlloc,
+ bool enforceQuota) {
+ {
+ // align very slightly.
+ lenToAlloc = (lenToAlloc + 3) & 0xfffffffc;
+ }
+ if (lenToAlloc > theCapExtent()->length) {
+ // the extent check is a way to try and improve performance
+ // since we have to iterate all the extents (for now) to get
+ // storage size
+ if (lenToAlloc > storageSize(txn)) {
+ return StatusWith<DiskLoc>(ErrorCodes::DocTooLargeForCapped,
+ mongoutils::str::stream()
+ << "document is larger than capped size " << lenToAlloc
+ << " > " << storageSize(txn),
+ 16328);
}
- DiskLoc loc;
- { // do allocation
-
- // signal done allocating new extents.
- if ( !cappedLastDelRecLastExtent().isValid() )
- setLastDelRecLastExtent( txn, DiskLoc() );
+ }
+ DiskLoc loc;
+ { // do allocation
- invariant( lenToAlloc < 400000000 );
- int passes = 0;
+ // signal done allocating new extents.
+ if (!cappedLastDelRecLastExtent().isValid())
+ setLastDelRecLastExtent(txn, DiskLoc());
- // delete records until we have room and the max # objects limit achieved.
+ invariant(lenToAlloc < 400000000);
+ int passes = 0;
- /* this fails on a rename -- that is ok but must keep commented out */
- //invariant( theCapExtent()->ns == ns );
+ // delete records until we have room and the max # objects limit achieved.
- theCapExtent()->assertOk();
- DiskLoc firstEmptyExtent; // This prevents us from infinite looping.
- while ( 1 ) {
- if ( _details->numRecords() < _details->maxCappedDocs() ) {
- loc = __capAlloc( txn, lenToAlloc );
- if ( !loc.isNull() )
- break;
- }
+ /* this fails on a rename -- that is ok but must keep commented out */
+ // invariant( theCapExtent()->ns == ns );
- // If on first iteration through extents, don't delete anything.
- if ( !_details->capFirstNewRecord().isValid() ) {
- advanceCapExtent( txn, _ns );
+ theCapExtent()->assertOk();
+ DiskLoc firstEmptyExtent; // This prevents us from infinite looping.
+ while (1) {
+ if (_details->numRecords() < _details->maxCappedDocs()) {
+ loc = __capAlloc(txn, lenToAlloc);
+ if (!loc.isNull())
+ break;
+ }
- if ( _details->capExtent() != _details->firstExtent(txn) )
- _details->setCapFirstNewRecord( txn, DiskLoc().setInvalid() );
- // else signal done with first iteration through extents.
- continue;
- }
+ // If on first iteration through extents, don't delete anything.
+ if (!_details->capFirstNewRecord().isValid()) {
+ advanceCapExtent(txn, _ns);
- if ( !_details->capFirstNewRecord().isNull() &&
- theCapExtent()->firstRecord == _details->capFirstNewRecord() ) {
- // We've deleted all records that were allocated on the previous
- // iteration through this extent.
- advanceCapExtent( txn, _ns );
- continue;
- }
+ if (_details->capExtent() != _details->firstExtent(txn))
+ _details->setCapFirstNewRecord(txn, DiskLoc().setInvalid());
+ // else signal done with first iteration through extents.
+ continue;
+ }
- if ( theCapExtent()->firstRecord.isNull() ) {
- if ( firstEmptyExtent.isNull() )
- firstEmptyExtent = _details->capExtent();
- advanceCapExtent( txn, _ns );
- if ( firstEmptyExtent == _details->capExtent() ) {
- // All records have been deleted but there is still no room for this record.
- // Nothing we can do but fail.
- _maybeComplain( txn, lenToAlloc );
- return StatusWith<DiskLoc>(
- ErrorCodes::DocTooLargeForCapped,
- str::stream() << "document doesn't fit in capped collection."
- << " size: " << lenToAlloc
- << " storageSize:" << storageSize(txn),
- 28575);
- }
- continue;
- }
+ if (!_details->capFirstNewRecord().isNull() &&
+ theCapExtent()->firstRecord == _details->capFirstNewRecord()) {
+ // We've deleted all records that were allocated on the previous
+ // iteration through this extent.
+ advanceCapExtent(txn, _ns);
+ continue;
+ }
- const RecordId fr = theCapExtent()->firstRecord.toRecordId();
- Status status = _deleteCallback->aboutToDeleteCapped( txn, fr, dataFor(txn, fr) );
- if ( !status.isOK() )
- return StatusWith<DiskLoc>( status );
- deleteRecord( txn, fr );
-
- _compact(txn);
- if ((++passes % 5000) == 0) {
- StringBuilder sb;
- log() << "passes = " << passes << " in CappedRecordStoreV1::allocRecord:"
- << " ns: " << _ns
- << ", lenToAlloc: " << lenToAlloc
- << ", maxCappedDocs: " << _details->maxCappedDocs()
- << ", nrecords: " << _details->numRecords()
- << ", datasize: " << _details->dataSize()
- << ". Continuing to delete old records to make room.";
+ if (theCapExtent()->firstRecord.isNull()) {
+ if (firstEmptyExtent.isNull())
+ firstEmptyExtent = _details->capExtent();
+ advanceCapExtent(txn, _ns);
+ if (firstEmptyExtent == _details->capExtent()) {
+ // All records have been deleted but there is still no room for this record.
+ // Nothing we can do but fail.
+ _maybeComplain(txn, lenToAlloc);
+ return StatusWith<DiskLoc>(ErrorCodes::DocTooLargeForCapped,
+ str::stream()
+ << "document doesn't fit in capped collection."
+ << " size: " << lenToAlloc
+ << " storageSize:" << storageSize(txn),
+ 28575);
}
+ continue;
}
- // Remember first record allocated on this iteration through capExtent.
- if ( _details->capFirstNewRecord().isValid() && _details->capFirstNewRecord().isNull() )
- _details->setCapFirstNewRecord( txn, loc );
+ const RecordId fr = theCapExtent()->firstRecord.toRecordId();
+ Status status = _deleteCallback->aboutToDeleteCapped(txn, fr, dataFor(txn, fr));
+ if (!status.isOK())
+ return StatusWith<DiskLoc>(status);
+ deleteRecord(txn, fr);
+
+ _compact(txn);
+ if ((++passes % 5000) == 0) {
+ StringBuilder sb;
+ log() << "passes = " << passes << " in CappedRecordStoreV1::allocRecord:"
+ << " ns: " << _ns << ", lenToAlloc: " << lenToAlloc
+ << ", maxCappedDocs: " << _details->maxCappedDocs()
+ << ", nrecords: " << _details->numRecords()
+ << ", datasize: " << _details->dataSize()
+ << ". Continuing to delete old records to make room.";
+ }
}
- invariant( !loc.isNull() );
+ // Remember first record allocated on this iteration through capExtent.
+ if (_details->capFirstNewRecord().isValid() && _details->capFirstNewRecord().isNull())
+ _details->setCapFirstNewRecord(txn, loc);
+ }
- // possibly slice up if we've allocated too much space
+ invariant(!loc.isNull());
- DeletedRecord *r = drec( loc );
+ // possibly slice up if we've allocated too much space
- /* note we want to grab from the front so our next pointers on disk tend
- to go in a forward direction which is important for performance. */
- int regionlen = r->lengthWithHeaders();
- invariant( r->extentOfs() < loc.getOfs() );
+ DeletedRecord* r = drec(loc);
- int left = regionlen - lenToAlloc;
+ /* note we want to grab from the front so our next pointers on disk tend
+ to go in a forward direction which is important for performance. */
+ int regionlen = r->lengthWithHeaders();
+ invariant(r->extentOfs() < loc.getOfs());
- /* split off some for further use. */
- txn->recoveryUnit()->writingInt(r->lengthWithHeaders()) = lenToAlloc;
- DiskLoc newDelLoc = loc;
- newDelLoc.inc(lenToAlloc);
- DeletedRecord* newDel = drec( newDelLoc );
- DeletedRecord* newDelW = txn->recoveryUnit()->writing(newDel);
- newDelW->extentOfs() = r->extentOfs();
- newDelW->lengthWithHeaders() = left;
- newDelW->nextDeleted().Null();
+ int left = regionlen - lenToAlloc;
- addDeletedRec(txn, newDelLoc);
+ /* split off some for further use. */
+ txn->recoveryUnit()->writingInt(r->lengthWithHeaders()) = lenToAlloc;
+ DiskLoc newDelLoc = loc;
+ newDelLoc.inc(lenToAlloc);
+ DeletedRecord* newDel = drec(newDelLoc);
+ DeletedRecord* newDelW = txn->recoveryUnit()->writing(newDel);
+ newDelW->extentOfs() = r->extentOfs();
+ newDelW->lengthWithHeaders() = left;
+ newDelW->nextDeleted().Null();
- return StatusWith<DiskLoc>( loc );
- }
+ addDeletedRec(txn, newDelLoc);
- Status CappedRecordStoreV1::truncate(OperationContext* txn) {
- setLastDelRecLastExtent( txn, DiskLoc() );
- setListOfAllDeletedRecords( txn, DiskLoc() );
-
- // preserve firstExtent/lastExtent
- _details->setCapExtent( txn, _details->firstExtent(txn) );
- _details->setStats( txn, 0, 0 );
- // preserve lastExtentSize
- // nIndexes preserve 0
- // capped preserve true
- // max preserve
- // paddingFactor is unused
- _details->setCapFirstNewRecord( txn, DiskLoc().setInvalid() );
- setLastDelRecLastExtent( txn, DiskLoc().setInvalid() );
- // dataFileVersion preserve
- // indexFileVersion preserve
-
- // Reset all existing extents and recreate the deleted list.
- Extent* ext;
- for( DiskLoc extLoc = _details->firstExtent(txn);
- !extLoc.isNull();
- extLoc = ext->xnext ) {
- ext = _extentManager->getExtent(extLoc);
-
- txn->recoveryUnit()->writing( &ext->firstRecord )->Null();
- txn->recoveryUnit()->writing( &ext->lastRecord )->Null();
-
- addDeletedRec( txn, _findFirstSpot( txn, extLoc, ext ) );
- }
+ return StatusWith<DiskLoc>(loc);
+}
- return Status::OK();
+Status CappedRecordStoreV1::truncate(OperationContext* txn) {
+ setLastDelRecLastExtent(txn, DiskLoc());
+ setListOfAllDeletedRecords(txn, DiskLoc());
+
+ // preserve firstExtent/lastExtent
+ _details->setCapExtent(txn, _details->firstExtent(txn));
+ _details->setStats(txn, 0, 0);
+ // preserve lastExtentSize
+ // nIndexes preserve 0
+ // capped preserve true
+ // max preserve
+ // paddingFactor is unused
+ _details->setCapFirstNewRecord(txn, DiskLoc().setInvalid());
+ setLastDelRecLastExtent(txn, DiskLoc().setInvalid());
+ // dataFileVersion preserve
+ // indexFileVersion preserve
+
+ // Reset all existing extents and recreate the deleted list.
+ Extent* ext;
+ for (DiskLoc extLoc = _details->firstExtent(txn); !extLoc.isNull(); extLoc = ext->xnext) {
+ ext = _extentManager->getExtent(extLoc);
+
+ txn->recoveryUnit()->writing(&ext->firstRecord)->Null();
+ txn->recoveryUnit()->writing(&ext->lastRecord)->Null();
+
+ addDeletedRec(txn, _findFirstSpot(txn, extLoc, ext));
}
- void CappedRecordStoreV1::temp_cappedTruncateAfter( OperationContext* txn,
- RecordId end,
- bool inclusive ) {
- cappedTruncateAfter( txn, _ns.c_str(), DiskLoc::fromRecordId(end), inclusive );
- }
+ return Status::OK();
+}
- /* combine adjacent deleted records *for the current extent* of the capped collection
+void CappedRecordStoreV1::temp_cappedTruncateAfter(OperationContext* txn,
+ RecordId end,
+ bool inclusive) {
+ cappedTruncateAfter(txn, _ns.c_str(), DiskLoc::fromRecordId(end), inclusive);
+}
- this is O(n^2) but we call it for capped tables where typically n==1 or 2!
- (or 3...there will be a little unused sliver at the end of the extent.)
- */
- void CappedRecordStoreV1::_compact(OperationContext* txn) {
- DDD( "CappedRecordStoreV1::compact enter" );
+/* combine adjacent deleted records *for the current extent* of the capped collection
- vector<DiskLoc> drecs;
+ this is O(n^2) but we call it for capped tables where typically n==1 or 2!
+ (or 3...there will be a little unused sliver at the end of the extent.)
+*/
+void CappedRecordStoreV1::_compact(OperationContext* txn) {
+ DDD("CappedRecordStoreV1::compact enter");
- // Pull out capExtent's DRs from deletedList
- DiskLoc i = cappedFirstDeletedInCurExtent();
- for (; !i.isNull() && inCapExtent( i ); i = deletedRecordFor( i )->nextDeleted() ) {
- DDD( "\t" << i );
- drecs.push_back( i );
- }
+ vector<DiskLoc> drecs;
+
+ // Pull out capExtent's DRs from deletedList
+ DiskLoc i = cappedFirstDeletedInCurExtent();
+ for (; !i.isNull() && inCapExtent(i); i = deletedRecordFor(i)->nextDeleted()) {
+ DDD("\t" << i);
+ drecs.push_back(i);
+ }
- setFirstDeletedInCurExtent( txn, i );
+ setFirstDeletedInCurExtent(txn, i);
- std::sort( drecs.begin(), drecs.end() );
- DDD( "\t drecs.size(): " << drecs.size() );
+ std::sort(drecs.begin(), drecs.end());
+ DDD("\t drecs.size(): " << drecs.size());
- vector<DiskLoc>::const_iterator j = drecs.begin();
- invariant( j != drecs.end() );
- DiskLoc a = *j;
- while ( 1 ) {
+ vector<DiskLoc>::const_iterator j = drecs.begin();
+ invariant(j != drecs.end());
+ DiskLoc a = *j;
+ while (1) {
+ j++;
+ if (j == drecs.end()) {
+ DDD("\t compact adddelrec");
+ addDeletedRec(txn, a);
+ break;
+ }
+ DiskLoc b = *j;
+ while (a.a() == b.a() && a.getOfs() + drec(a)->lengthWithHeaders() == b.getOfs()) {
+ // a & b are adjacent. merge.
+ txn->recoveryUnit()->writingInt(drec(a)->lengthWithHeaders()) +=
+ drec(b)->lengthWithHeaders();
j++;
- if ( j == drecs.end() ) {
- DDD( "\t compact adddelrec" );
+ if (j == drecs.end()) {
+ DDD("\t compact adddelrec2");
addDeletedRec(txn, a);
- break;
+ return;
}
- DiskLoc b = *j;
- while ( a.a() == b.a() &&
- a.getOfs() + drec( a )->lengthWithHeaders() == b.getOfs() ) {
-
- // a & b are adjacent. merge.
- txn->recoveryUnit()->writingInt( drec(a)->lengthWithHeaders() ) += drec(b)->lengthWithHeaders();
- j++;
- if ( j == drecs.end() ) {
- DDD( "\t compact adddelrec2" );
- addDeletedRec(txn, a);
- return;
- }
- b = *j;
- }
- DDD( "\t compact adddelrec3" );
- addDeletedRec(txn, a);
- a = b;
+ b = *j;
}
-
- }
-
- DiskLoc CappedRecordStoreV1::cappedFirstDeletedInCurExtent() const {
- if ( cappedLastDelRecLastExtent().isNull() )
- return cappedListOfAllDeletedRecords();
- else
- return drec(cappedLastDelRecLastExtent())->nextDeleted();
+ DDD("\t compact adddelrec3");
+ addDeletedRec(txn, a);
+ a = b;
}
+}
- void CappedRecordStoreV1::setFirstDeletedInCurExtent( OperationContext* txn,
- const DiskLoc& loc ) {
- if ( cappedLastDelRecLastExtent().isNull() )
- setListOfAllDeletedRecords( txn, loc );
- else
- *txn->recoveryUnit()->writing( &drec(cappedLastDelRecLastExtent())->nextDeleted() ) = loc;
- }
+DiskLoc CappedRecordStoreV1::cappedFirstDeletedInCurExtent() const {
+ if (cappedLastDelRecLastExtent().isNull())
+ return cappedListOfAllDeletedRecords();
+ else
+ return drec(cappedLastDelRecLastExtent())->nextDeleted();
+}
- void CappedRecordStoreV1::cappedCheckMigrate(OperationContext* txn) {
- // migrate old RecordStoreV1MetaData format
- if ( _details->capExtent().a() == 0 && _details->capExtent().getOfs() == 0 ) {
- WriteUnitOfWork wunit(txn);
- _details->setCapFirstNewRecord( txn, DiskLoc().setInvalid() );
- // put all the DeletedRecords in cappedListOfAllDeletedRecords()
- for ( int i = 1; i < Buckets; ++i ) {
- DiskLoc first = _details->deletedListEntry( i );
- if ( first.isNull() )
- continue;
- DiskLoc last = first;
- for (; !drec(last)->nextDeleted().isNull(); last = drec(last)->nextDeleted() );
- *txn->recoveryUnit()->writing(&drec(last)->nextDeleted()) = cappedListOfAllDeletedRecords();
- setListOfAllDeletedRecords( txn, first );
- _details->setDeletedListEntry(txn, i, DiskLoc());
- }
- // NOTE cappedLastDelRecLastExtent() set to DiskLoc() in above
+void CappedRecordStoreV1::setFirstDeletedInCurExtent(OperationContext* txn, const DiskLoc& loc) {
+ if (cappedLastDelRecLastExtent().isNull())
+ setListOfAllDeletedRecords(txn, loc);
+ else
+ *txn->recoveryUnit()->writing(&drec(cappedLastDelRecLastExtent())->nextDeleted()) = loc;
+}
- // Last, in case we're killed before getting here
- _details->setCapExtent( txn, _details->firstExtent(txn) );
- wunit.commit();
+void CappedRecordStoreV1::cappedCheckMigrate(OperationContext* txn) {
+ // migrate old RecordStoreV1MetaData format
+ if (_details->capExtent().a() == 0 && _details->capExtent().getOfs() == 0) {
+ WriteUnitOfWork wunit(txn);
+ _details->setCapFirstNewRecord(txn, DiskLoc().setInvalid());
+ // put all the DeletedRecords in cappedListOfAllDeletedRecords()
+ for (int i = 1; i < Buckets; ++i) {
+ DiskLoc first = _details->deletedListEntry(i);
+ if (first.isNull())
+ continue;
+ DiskLoc last = first;
+ for (; !drec(last)->nextDeleted().isNull(); last = drec(last)->nextDeleted())
+ ;
+ *txn->recoveryUnit()->writing(&drec(last)->nextDeleted()) =
+ cappedListOfAllDeletedRecords();
+ setListOfAllDeletedRecords(txn, first);
+ _details->setDeletedListEntry(txn, i, DiskLoc());
}
+ // NOTE cappedLastDelRecLastExtent() set to DiskLoc() in above
+
+ // Last, in case we're killed before getting here
+ _details->setCapExtent(txn, _details->firstExtent(txn));
+ wunit.commit();
}
+}
- bool CappedRecordStoreV1::inCapExtent( const DiskLoc &dl ) const {
- invariant( !dl.isNull() );
+bool CappedRecordStoreV1::inCapExtent(const DiskLoc& dl) const {
+ invariant(!dl.isNull());
- if ( dl.a() != _details->capExtent().a() )
- return false;
+ if (dl.a() != _details->capExtent().a())
+ return false;
- if ( dl.getOfs() < _details->capExtent().getOfs() )
- return false;
+ if (dl.getOfs() < _details->capExtent().getOfs())
+ return false;
- const Extent* e = theCapExtent();
- int end = _details->capExtent().getOfs() + e->length;
- return dl.getOfs() <= end;
- }
+ const Extent* e = theCapExtent();
+ int end = _details->capExtent().getOfs() + e->length;
+ return dl.getOfs() <= end;
+}
- bool CappedRecordStoreV1::nextIsInCapExtent( const DiskLoc &dl ) const {
- invariant( !dl.isNull() );
- DiskLoc next = drec(dl)->nextDeleted();
- if ( next.isNull() )
- return false;
- return inCapExtent( next );
+bool CappedRecordStoreV1::nextIsInCapExtent(const DiskLoc& dl) const {
+ invariant(!dl.isNull());
+ DiskLoc next = drec(dl)->nextDeleted();
+ if (next.isNull())
+ return false;
+ return inCapExtent(next);
+}
+
+void CappedRecordStoreV1::advanceCapExtent(OperationContext* txn, StringData ns) {
+ // We want cappedLastDelRecLastExtent() to be the last DeletedRecord of the prev cap extent
+ // (or DiskLoc() if new capExtent == firstExtent)
+ if (_details->capExtent() == _details->lastExtent(txn))
+ setLastDelRecLastExtent(txn, DiskLoc());
+ else {
+ DiskLoc i = cappedFirstDeletedInCurExtent();
+ for (; !i.isNull() && nextIsInCapExtent(i); i = drec(i)->nextDeleted())
+ ;
+ setLastDelRecLastExtent(txn, i);
}
- void CappedRecordStoreV1::advanceCapExtent( OperationContext* txn, StringData ns ) {
- // We want cappedLastDelRecLastExtent() to be the last DeletedRecord of the prev cap extent
- // (or DiskLoc() if new capExtent == firstExtent)
- if ( _details->capExtent() == _details->lastExtent(txn) )
- setLastDelRecLastExtent( txn, DiskLoc() );
- else {
- DiskLoc i = cappedFirstDeletedInCurExtent();
- for (; !i.isNull() && nextIsInCapExtent( i ); i = drec(i)->nextDeleted() );
- setLastDelRecLastExtent( txn, i );
- }
+ _details->setCapExtent(
+ txn, theCapExtent()->xnext.isNull() ? _details->firstExtent(txn) : theCapExtent()->xnext);
- _details->setCapExtent( txn,
- theCapExtent()->xnext.isNull() ? _details->firstExtent(txn)
- : theCapExtent()->xnext );
+ /* this isn't true if a collection has been renamed...that is ok just used for diagnostics */
+ // dassert( theCapExtent()->ns == ns );
- /* this isn't true if a collection has been renamed...that is ok just used for diagnostics */
- //dassert( theCapExtent()->ns == ns );
+ theCapExtent()->assertOk();
+ _details->setCapFirstNewRecord(txn, DiskLoc());
+}
- theCapExtent()->assertOk();
- _details->setCapFirstNewRecord( txn, DiskLoc() );
+DiskLoc CappedRecordStoreV1::__capAlloc(OperationContext* txn, int len) {
+ DiskLoc prev = cappedLastDelRecLastExtent();
+ DiskLoc i = cappedFirstDeletedInCurExtent();
+ DiskLoc ret;
+ for (; !i.isNull() && inCapExtent(i); prev = i, i = drec(i)->nextDeleted()) {
+ // We need to keep at least one DR per extent in cappedListOfAllDeletedRecords(),
+ // so make sure there's space to create a DR at the end.
+ if (drec(i)->lengthWithHeaders() >= len + 24) {
+ ret = i;
+ break;
+ }
}
- DiskLoc CappedRecordStoreV1::__capAlloc( OperationContext* txn, int len ) {
- DiskLoc prev = cappedLastDelRecLastExtent();
- DiskLoc i = cappedFirstDeletedInCurExtent();
- DiskLoc ret;
- for (; !i.isNull() && inCapExtent( i ); prev = i, i = drec(i)->nextDeleted() ) {
- // We need to keep at least one DR per extent in cappedListOfAllDeletedRecords(),
- // so make sure there's space to create a DR at the end.
- if ( drec(i)->lengthWithHeaders() >= len + 24 ) {
- ret = i;
- break;
- }
- }
+ /* unlink ourself from the deleted list */
+ if (!ret.isNull()) {
+ if (prev.isNull())
+ setListOfAllDeletedRecords(txn, drec(ret)->nextDeleted());
+ else
+ *txn->recoveryUnit()->writing(&drec(prev)->nextDeleted()) = drec(ret)->nextDeleted();
+ *txn->recoveryUnit()->writing(&drec(ret)->nextDeleted()) =
+ DiskLoc().setInvalid(); // defensive.
+ invariant(drec(ret)->extentOfs() < ret.getOfs());
+ }
- /* unlink ourself from the deleted list */
- if ( !ret.isNull() ) {
- if ( prev.isNull() )
- setListOfAllDeletedRecords( txn, drec(ret)->nextDeleted() );
- else
- *txn->recoveryUnit()->writing(&drec(prev)->nextDeleted()) = drec(ret)->nextDeleted();
- *txn->recoveryUnit()->writing(&drec(ret)->nextDeleted()) = DiskLoc().setInvalid(); // defensive.
- invariant( drec(ret)->extentOfs() < ret.getOfs() );
- }
+ return ret;
+}
- return ret;
+void CappedRecordStoreV1::cappedTruncateLastDelUpdate(OperationContext* txn) {
+ if (_details->capExtent() == _details->firstExtent(txn)) {
+ // Only one extent of the collection is in use, so there
+ // is no deleted record in a previous extent, so nullify
+ // cappedLastDelRecLastExtent().
+ setLastDelRecLastExtent(txn, DiskLoc());
+ } else {
+ // Scan through all deleted records in the collection
+ // until the last deleted record for the extent prior
+ // to the new capExtent is found. Then set
+ // cappedLastDelRecLastExtent() to that deleted record.
+ DiskLoc i = cappedListOfAllDeletedRecords();
+ for (; !drec(i)->nextDeleted().isNull() && !inCapExtent(drec(i)->nextDeleted());
+ i = drec(i)->nextDeleted())
+ ;
+ // In our capped storage model, every extent must have at least one
+ // deleted record. Here we check that 'i' is not the last deleted
+ // record. (We expect that there will be deleted records in the new
+ // capExtent as well.)
+ invariant(!drec(i)->nextDeleted().isNull());
+ setLastDelRecLastExtent(txn, i);
}
+}
- void CappedRecordStoreV1::cappedTruncateLastDelUpdate(OperationContext* txn) {
- if ( _details->capExtent() == _details->firstExtent(txn) ) {
- // Only one extent of the collection is in use, so there
- // is no deleted record in a previous extent, so nullify
- // cappedLastDelRecLastExtent().
- setLastDelRecLastExtent( txn, DiskLoc() );
+void CappedRecordStoreV1::cappedTruncateAfter(OperationContext* txn,
+ const char* ns,
+ DiskLoc end,
+ bool inclusive) {
+ invariant(cappedLastDelRecLastExtent().isValid());
+
+ // We iteratively remove the newest document until the newest document
+ // is 'end', then we remove 'end' if requested.
+ bool foundLast = false;
+ while (1) {
+ if (foundLast) {
+ // 'end' has been found and removed, so break.
+ break;
}
- else {
- // Scan through all deleted records in the collection
- // until the last deleted record for the extent prior
- // to the new capExtent is found. Then set
- // cappedLastDelRecLastExtent() to that deleted record.
- DiskLoc i = cappedListOfAllDeletedRecords();
- for( ;
- !drec(i)->nextDeleted().isNull() &&
- !inCapExtent( drec(i)->nextDeleted() );
- i = drec(i)->nextDeleted() );
- // In our capped storage model, every extent must have at least one
- // deleted record. Here we check that 'i' is not the last deleted
- // record. (We expect that there will be deleted records in the new
- // capExtent as well.)
- invariant( !drec(i)->nextDeleted().isNull() );
- setLastDelRecLastExtent( txn, i );
- }
- }
-
- void CappedRecordStoreV1::cappedTruncateAfter(OperationContext* txn,
- const char* ns,
- DiskLoc end,
- bool inclusive) {
- invariant( cappedLastDelRecLastExtent().isValid() );
-
- // We iteratively remove the newest document until the newest document
- // is 'end', then we remove 'end' if requested.
- bool foundLast = false;
- while( 1 ) {
- if ( foundLast ) {
- // 'end' has been found and removed, so break.
+ // 'curr' will point to the newest document in the collection.
+ const DiskLoc curr = theCapExtent()->lastRecord;
+ const RecordId currId = curr.toRecordId();
+ invariant(!curr.isNull());
+ if (curr == end) {
+ if (inclusive) {
+ // 'end' has been found, so break next iteration.
+ foundLast = true;
+ } else {
+ // 'end' has been found, so break.
break;
}
- // 'curr' will point to the newest document in the collection.
- const DiskLoc curr = theCapExtent()->lastRecord;
- const RecordId currId = curr.toRecordId();
- invariant( !curr.isNull() );
- if ( curr == end ) {
- if ( inclusive ) {
- // 'end' has been found, so break next iteration.
- foundLast = true;
- }
- else {
- // 'end' has been found, so break.
- break;
- }
- }
-
- // TODO The algorithm used in this function cannot generate an
- // empty collection, but we could call emptyCappedCollection() in
- // this case instead of asserting.
- uassert( 13415, "emptying the collection is not allowed", _details->numRecords() > 1 );
-
- WriteUnitOfWork wunit(txn);
- // Delete the newest record, and coalesce the new deleted
- // record with existing deleted records.
- Status status = _deleteCallback->aboutToDeleteCapped(txn, currId, dataFor(txn, currId));
- uassertStatusOK( status );
- deleteRecord( txn, currId );
- _compact(txn);
-
- // This is the case where we have not yet had to remove any
- // documents to make room for other documents, and we are allocating
- // documents from free space in fresh extents instead of reusing
- // space from familiar extents.
- if ( !_details->capLooped() ) {
-
- // We just removed the last record from the 'capExtent', and
- // the 'capExtent' can't be empty, so we set 'capExtent' to
- // capExtent's prev extent.
- if ( theCapExtent()->lastRecord.isNull() ) {
- invariant( !theCapExtent()->xprev.isNull() );
- // NOTE Because we didn't delete the last document, and
- // capLooped() is false, capExtent is not the first extent
- // so xprev will be nonnull.
- _details->setCapExtent( txn, theCapExtent()->xprev );
- theCapExtent()->assertOk();
-
- // update cappedLastDelRecLastExtent()
- cappedTruncateLastDelUpdate(txn);
- }
- wunit.commit();
- continue;
- }
-
- // This is the case where capLooped() is true, and we just deleted
- // from capExtent, and we just deleted capFirstNewRecord, which was
- // the last record on the fresh side of capExtent.
- // NOTE In this comparison, curr and potentially capFirstNewRecord
- // may point to invalid data, but we can still compare the
- // references themselves.
- if ( curr == _details->capFirstNewRecord() ) {
-
- // Set 'capExtent' to the first nonempty extent prior to the
- // initial capExtent. There must be such an extent because we
- // have not deleted the last document in the collection. It is
- // possible that all extents other than the capExtent are empty.
- // In this case we will keep the initial capExtent and specify
- // that all records contained within are on the fresh rather than
- // stale side of the extent.
- DiskLoc newCapExtent = _details->capExtent();
- do {
- // Find the previous extent, looping if necessary.
- newCapExtent = ( newCapExtent == _details->firstExtent(txn) ) ?
- _details->lastExtent(txn) :
- _extentManager->getExtent(newCapExtent)->xprev;
- _extentManager->getExtent(newCapExtent)->assertOk();
- }
- while ( _extentManager->getExtent(newCapExtent)->firstRecord.isNull() );
- _details->setCapExtent( txn, newCapExtent );
+ }
- // Place all documents in the new capExtent on the fresh side
- // of the capExtent by setting capFirstNewRecord to the first
- // document in the new capExtent.
- _details->setCapFirstNewRecord( txn, theCapExtent()->firstRecord );
+ // TODO The algorithm used in this function cannot generate an
+ // empty collection, but we could call emptyCappedCollection() in
+ // this case instead of asserting.
+ uassert(13415, "emptying the collection is not allowed", _details->numRecords() > 1);
+
+ WriteUnitOfWork wunit(txn);
+ // Delete the newest record, and coalesce the new deleted
+ // record with existing deleted records.
+ Status status = _deleteCallback->aboutToDeleteCapped(txn, currId, dataFor(txn, currId));
+ uassertStatusOK(status);
+ deleteRecord(txn, currId);
+ _compact(txn);
+
+ // This is the case where we have not yet had to remove any
+ // documents to make room for other documents, and we are allocating
+ // documents from free space in fresh extents instead of reusing
+ // space from familiar extents.
+ if (!_details->capLooped()) {
+ // We just removed the last record from the 'capExtent', and
+ // the 'capExtent' can't be empty, so we set 'capExtent' to
+ // capExtent's prev extent.
+ if (theCapExtent()->lastRecord.isNull()) {
+ invariant(!theCapExtent()->xprev.isNull());
+ // NOTE Because we didn't delete the last document, and
+ // capLooped() is false, capExtent is not the first extent
+ // so xprev will be nonnull.
+ _details->setCapExtent(txn, theCapExtent()->xprev);
+ theCapExtent()->assertOk();
// update cappedLastDelRecLastExtent()
cappedTruncateLastDelUpdate(txn);
}
-
wunit.commit();
+ continue;
}
- }
- DiskLoc CappedRecordStoreV1::cappedListOfAllDeletedRecords() const {
- return _details->deletedListEntry(0);
- }
+ // This is the case where capLooped() is true, and we just deleted
+ // from capExtent, and we just deleted capFirstNewRecord, which was
+ // the last record on the fresh side of capExtent.
+ // NOTE In this comparison, curr and potentially capFirstNewRecord
+ // may point to invalid data, but we can still compare the
+ // references themselves.
+ if (curr == _details->capFirstNewRecord()) {
+ // Set 'capExtent' to the first nonempty extent prior to the
+ // initial capExtent. There must be such an extent because we
+ // have not deleted the last document in the collection. It is
+ // possible that all extents other than the capExtent are empty.
+ // In this case we will keep the initial capExtent and specify
+ // that all records contained within are on the fresh rather than
+ // stale side of the extent.
+ DiskLoc newCapExtent = _details->capExtent();
+ do {
+ // Find the previous extent, looping if necessary.
+ newCapExtent = (newCapExtent == _details->firstExtent(txn))
+ ? _details->lastExtent(txn)
+ : _extentManager->getExtent(newCapExtent)->xprev;
+ _extentManager->getExtent(newCapExtent)->assertOk();
+ } while (_extentManager->getExtent(newCapExtent)->firstRecord.isNull());
+ _details->setCapExtent(txn, newCapExtent);
+
+ // Place all documents in the new capExtent on the fresh side
+ // of the capExtent by setting capFirstNewRecord to the first
+ // document in the new capExtent.
+ _details->setCapFirstNewRecord(txn, theCapExtent()->firstRecord);
+
+ // update cappedLastDelRecLastExtent()
+ cappedTruncateLastDelUpdate(txn);
+ }
- void CappedRecordStoreV1::setListOfAllDeletedRecords( OperationContext* txn,
- const DiskLoc& loc ) {
- return _details->setDeletedListEntry(txn, 0, loc);
+ wunit.commit();
}
+}
- DiskLoc CappedRecordStoreV1::cappedLastDelRecLastExtent() const {
- return _details->deletedListEntry(1);
- }
+DiskLoc CappedRecordStoreV1::cappedListOfAllDeletedRecords() const {
+ return _details->deletedListEntry(0);
+}
- void CappedRecordStoreV1::setLastDelRecLastExtent( OperationContext* txn,
- const DiskLoc& loc ) {
- return _details->setDeletedListEntry(txn, 1, loc);
- }
+void CappedRecordStoreV1::setListOfAllDeletedRecords(OperationContext* txn, const DiskLoc& loc) {
+ return _details->setDeletedListEntry(txn, 0, loc);
+}
- Extent* CappedRecordStoreV1::theCapExtent() const {
- return _extentManager->getExtent(_details->capExtent());
- }
+DiskLoc CappedRecordStoreV1::cappedLastDelRecLastExtent() const {
+ return _details->deletedListEntry(1);
+}
- void CappedRecordStoreV1::addDeletedRec( OperationContext* txn, const DiskLoc& dloc ) {
- DeletedRecord* d = txn->recoveryUnit()->writing( drec( dloc ) );
-
- if ( !cappedLastDelRecLastExtent().isValid() ) {
- // Initial extent allocation. Insert at end.
- d->nextDeleted() = DiskLoc();
- if ( cappedListOfAllDeletedRecords().isNull() )
- setListOfAllDeletedRecords( txn, dloc );
- else {
- DiskLoc i = cappedListOfAllDeletedRecords();
- for (; !drec(i)->nextDeleted().isNull(); i = drec(i)->nextDeleted() )
- ;
- *txn->recoveryUnit()->writing(&drec(i)->nextDeleted()) = dloc;
- }
- }
+void CappedRecordStoreV1::setLastDelRecLastExtent(OperationContext* txn, const DiskLoc& loc) {
+ return _details->setDeletedListEntry(txn, 1, loc);
+}
+
+Extent* CappedRecordStoreV1::theCapExtent() const {
+ return _extentManager->getExtent(_details->capExtent());
+}
+
+void CappedRecordStoreV1::addDeletedRec(OperationContext* txn, const DiskLoc& dloc) {
+ DeletedRecord* d = txn->recoveryUnit()->writing(drec(dloc));
+
+ if (!cappedLastDelRecLastExtent().isValid()) {
+ // Initial extent allocation. Insert at end.
+ d->nextDeleted() = DiskLoc();
+ if (cappedListOfAllDeletedRecords().isNull())
+ setListOfAllDeletedRecords(txn, dloc);
else {
- d->nextDeleted() = cappedFirstDeletedInCurExtent();
- setFirstDeletedInCurExtent( txn, dloc );
- // always _compact() after this so order doesn't matter
+ DiskLoc i = cappedListOfAllDeletedRecords();
+ for (; !drec(i)->nextDeleted().isNull(); i = drec(i)->nextDeleted())
+ ;
+ *txn->recoveryUnit()->writing(&drec(i)->nextDeleted()) = dloc;
}
+ } else {
+ d->nextDeleted() = cappedFirstDeletedInCurExtent();
+ setFirstDeletedInCurExtent(txn, dloc);
+ // always _compact() after this so order doesn't matter
}
+}
- std::unique_ptr<RecordCursor> CappedRecordStoreV1::getCursor(OperationContext* txn,
- bool forward) const {
-
- return stdx::make_unique<CappedRecordStoreV1Iterator>(txn, this, forward);
- }
+std::unique_ptr<RecordCursor> CappedRecordStoreV1::getCursor(OperationContext* txn,
+ bool forward) const {
+ return stdx::make_unique<CappedRecordStoreV1Iterator>(txn, this, forward);
+}
- vector<std::unique_ptr<RecordCursor>> CappedRecordStoreV1::getManyCursors(
- OperationContext* txn) const {
- vector<std::unique_ptr<RecordCursor>> cursors;
+vector<std::unique_ptr<RecordCursor>> CappedRecordStoreV1::getManyCursors(
+ OperationContext* txn) const {
+ vector<std::unique_ptr<RecordCursor>> cursors;
- if (!_details->capLooped()) {
- // if we haven't looped yet, just spit out all extents (same as non-capped impl)
- const Extent* ext;
- for (DiskLoc extLoc = details()->firstExtent(txn); !extLoc.isNull(); extLoc = ext->xnext) {
- ext = _getExtent(txn, extLoc);
- if (ext->firstRecord.isNull())
- continue;
+ if (!_details->capLooped()) {
+ // if we haven't looped yet, just spit out all extents (same as non-capped impl)
+ const Extent* ext;
+ for (DiskLoc extLoc = details()->firstExtent(txn); !extLoc.isNull(); extLoc = ext->xnext) {
+ ext = _getExtent(txn, extLoc);
+ if (ext->firstRecord.isNull())
+ continue;
- cursors.push_back(stdx::make_unique<RecordStoreV1Base::IntraExtentIterator>(
- txn, ext->firstRecord, this));
- }
+ cursors.push_back(stdx::make_unique<RecordStoreV1Base::IntraExtentIterator>(
+ txn, ext->firstRecord, this));
}
- else {
- // if we've looped we need to iterate the extents, starting and ending with the
- // capExtent
- const DiskLoc capExtent = details()->capExtent();
- invariant(!capExtent.isNull());
- invariant(capExtent.isValid());
-
- // First do the "old" portion of capExtent if there is any
- DiskLoc extLoc = capExtent;
- {
- const Extent* ext = _getExtent(txn, extLoc);
- if (ext->firstRecord != details()->capFirstNewRecord()) {
- // this means there is old data in capExtent
- cursors.push_back(stdx::make_unique<RecordStoreV1Base::IntraExtentIterator>(
- txn, ext->firstRecord, this));
- }
-
- extLoc = ext->xnext.isNull() ? details()->firstExtent(txn) : ext->xnext;
- }
-
- // Next handle all the other extents
- while (extLoc != capExtent) {
- const Extent* ext = _getExtent(txn, extLoc);
+ } else {
+ // if we've looped we need to iterate the extents, starting and ending with the
+ // capExtent
+ const DiskLoc capExtent = details()->capExtent();
+ invariant(!capExtent.isNull());
+ invariant(capExtent.isValid());
+
+ // First do the "old" portion of capExtent if there is any
+ DiskLoc extLoc = capExtent;
+ {
+ const Extent* ext = _getExtent(txn, extLoc);
+ if (ext->firstRecord != details()->capFirstNewRecord()) {
+ // this means there is old data in capExtent
cursors.push_back(stdx::make_unique<RecordStoreV1Base::IntraExtentIterator>(
- txn, ext->firstRecord, this));
-
- extLoc = ext->xnext.isNull() ? details()->firstExtent(txn) : ext->xnext;
+ txn, ext->firstRecord, this));
}
- // Finally handle the "new" data in the capExtent
+ extLoc = ext->xnext.isNull() ? details()->firstExtent(txn) : ext->xnext;
+ }
+
+ // Next handle all the other extents
+ while (extLoc != capExtent) {
+ const Extent* ext = _getExtent(txn, extLoc);
cursors.push_back(stdx::make_unique<RecordStoreV1Base::IntraExtentIterator>(
- txn, details()->capFirstNewRecord(), this));
+ txn, ext->firstRecord, this));
+
+ extLoc = ext->xnext.isNull() ? details()->firstExtent(txn) : ext->xnext;
}
- return cursors;
+ // Finally handle the "new" data in the capExtent
+ cursors.push_back(stdx::make_unique<RecordStoreV1Base::IntraExtentIterator>(
+ txn, details()->capFirstNewRecord(), this));
}
- void CappedRecordStoreV1::_maybeComplain( OperationContext* txn, int len ) const {
- RARELY {
- std::stringstream buf;
- buf << "couldn't make room for record len: " << len << " in capped ns " << _ns << '\n';
- buf << "numRecords: " << numRecords(txn) << '\n';
- int i = 0;
- for ( DiskLoc e = _details->firstExtent(txn);
- !e.isNull();
- e = _extentManager->getExtent( e )->xnext, ++i ) {
- buf << " Extent " << i;
- if ( e == _details->capExtent() )
- buf << " (capExtent)";
- buf << ' ' << e;
- buf << '\n';
-
- buf << " magic: " << hex << _extentManager->getExtent( e )->magic << dec
- << " extent->ns: " << _extentManager->getExtent( e )->nsDiagnostic.toString()
- << '\n';
- buf << " fr: " << _extentManager->getExtent( e )->firstRecord.toString()
- << " lr: " << _extentManager->getExtent( e )->lastRecord.toString()
- << " extent->len: " << _extentManager->getExtent( e )->length << '\n';
- }
-
- warning() << buf.str();
+ return cursors;
+}
- // assume it is unusually large record; if not, something is broken
- fassert( 17438, len * 5 > _details->lastExtentSize(txn) );
+void CappedRecordStoreV1::_maybeComplain(OperationContext* txn, int len) const {
+ RARELY {
+ std::stringstream buf;
+ buf << "couldn't make room for record len: " << len << " in capped ns " << _ns << '\n';
+ buf << "numRecords: " << numRecords(txn) << '\n';
+ int i = 0;
+ for (DiskLoc e = _details->firstExtent(txn); !e.isNull();
+ e = _extentManager->getExtent(e)->xnext, ++i) {
+ buf << " Extent " << i;
+ if (e == _details->capExtent())
+ buf << " (capExtent)";
+ buf << ' ' << e;
+ buf << '\n';
+
+ buf << " magic: " << hex << _extentManager->getExtent(e)->magic << dec
+ << " extent->ns: " << _extentManager->getExtent(e)->nsDiagnostic.toString() << '\n';
+ buf << " fr: " << _extentManager->getExtent(e)->firstRecord.toString()
+ << " lr: " << _extentManager->getExtent(e)->lastRecord.toString()
+ << " extent->len: " << _extentManager->getExtent(e)->length << '\n';
}
- }
-
- DiskLoc CappedRecordStoreV1::firstRecord( OperationContext* txn,
- const DiskLoc &startExtent ) const {
- for (DiskLoc i = startExtent.isNull() ? _details->firstExtent(txn) : startExtent;
- !i.isNull();
- i = _extentManager->getExtent( i )->xnext ) {
- Extent* e = _extentManager->getExtent( i );
+ warning() << buf.str();
- if ( !e->firstRecord.isNull() )
- return e->firstRecord;
- }
- return DiskLoc();
+ // assume it is unusually large record; if not, something is broken
+ fassert(17438, len * 5 > _details->lastExtentSize(txn));
}
+}
- DiskLoc CappedRecordStoreV1::lastRecord( OperationContext* txn,
- const DiskLoc &startExtent ) const {
- for (DiskLoc i = startExtent.isNull() ? _details->lastExtent(txn) : startExtent;
- !i.isNull();
- i = _extentManager->getExtent( i )->xprev ) {
+DiskLoc CappedRecordStoreV1::firstRecord(OperationContext* txn, const DiskLoc& startExtent) const {
+ for (DiskLoc i = startExtent.isNull() ? _details->firstExtent(txn) : startExtent; !i.isNull();
+ i = _extentManager->getExtent(i)->xnext) {
+ Extent* e = _extentManager->getExtent(i);
- Extent* e = _extentManager->getExtent( i );
- if ( !e->lastRecord.isNull() )
- return e->lastRecord;
- }
- return DiskLoc();
+ if (!e->firstRecord.isNull())
+ return e->firstRecord;
}
+ return DiskLoc();
+}
+DiskLoc CappedRecordStoreV1::lastRecord(OperationContext* txn, const DiskLoc& startExtent) const {
+ for (DiskLoc i = startExtent.isNull() ? _details->lastExtent(txn) : startExtent; !i.isNull();
+ i = _extentManager->getExtent(i)->xprev) {
+ Extent* e = _extentManager->getExtent(i);
+ if (!e->lastRecord.isNull())
+ return e->lastRecord;
+ }
+ return DiskLoc();
+}
}