Reverse natural iteration of a non capped or capped collection will abort when the first empty extent is encountered, because Record::getPrev() does not skip over empty extents.
inline DiskLoc Record::getPrev(const DiskLoc& myLoc) { _accessing(); if ( _prevOfs != DiskLoc::NullOfs ) return DiskLoc(myLoc.a(), _prevOfs); Extent *e = myExtent(myLoc); if ( e->xprev.isNull() ) return DiskLoc(); return e->xprev.ext()->lastRecord; }
Test
c = db.c;
c.drop();
a = 0;
c.save( { a:a++ } );
big = new Array( 1024*1024 ).toString();
// Save 3 extents of data.
while( c.stats().numExtents < 3 ) {
c.save( { a:a++, b:big } );
}
savedCount = c.count();
assert.gt( savedCount, 2 );
// Remove all but the first and last documents, with the expectation that the first doc is in the
// first extent and the last in the last extent. This leaves the middle extent empty.
c.remove( { a:{ $gt:0, $lt:a-1 } } );
assert.eq( 2, c.count() );
assert.eq( 2, c.find().sort( { $natural:1 } ).itcount() );
// Check that reverse iteration properly iterates past the empty middle extent.
// Currently it stops at the empty extent (and only sees one document).
assert.eq( 2, c.find().sort( { $natural:-1 } ).itcount() );