DiskLoc CappedIterator::getNextCapped(const NamespaceDetails* nsd, const ExtentManager* em, const DiskLoc& dl, CollectionScanParams::Direction direction ) { verify(!dl.isNull()); if (CollectionScanParams::FORWARD == direction) { // If it's not looped, it's easy. if (!nsd->capLooped()) { return em->getNextRecord( dl ); } // TODO ELABORATE // EOF. if (dl == em->getExtent( nsd->capExtent() )->lastRecord) { return DiskLoc(); } DiskLoc ret = nextLoop(nsd,em,dl); // If we become capFirstNewRecord from same extent, advance to next extent. if (ret == nsd->capFirstNewRecord() && ret != em->getExtent( nsd->capExtent() )->firstRecord) { ret = nextLoop(nsd,em,em->getExtent( nsd->capExtent() )->lastRecord); } // If we have just gotten to beginning of capExtent, skip to capFirstNewRecord if (ret == em->getExtent( nsd->capExtent() )->firstRecord) { ret = nsd->capFirstNewRecord(); } return ret; } else { if (!nsd->capLooped()) { return em->getPrevRecord( dl ); } // TODO ELABORATE // Last record if (nsd->capFirstNewRecord() == em->getExtent( nsd->capExtent() )->firstRecord) { if (dl == nextLoop(nsd,em,em->getExtent( nsd->capExtent() )->lastRecord)) { return DiskLoc(); } } else { if (dl == em->getExtent( nsd->capExtent() )->firstRecord) { return DiskLoc(); } } DiskLoc ret; // If we are capFirstNewRecord, advance to prev extent, otherwise just get prev. if (dl == nsd->capFirstNewRecord()) { ret = prevLoop(nsd, em, em->getExtent( nsd->capExtent() )->firstRecord); } else { ret = prevLoop(nsd, em, dl); } // If we just became last in cap extent, advance past capFirstNewRecord // (We know capExtent.ext()->firstRecord != capFirstNewRecord, since would // have returned DiskLoc() earlier otherwise.) if (ret == em->getExtent( nsd->capExtent() )->lastRecord) { ret = em->getPrevRecord( nsd->capFirstNewRecord() ); } return ret; } }
xPL_Node* xPL_Node::prevLoop() { if (_parent) { xPL_Node* n = _parent->child(); while(n->nextLoop()!=this) n=nextLoop(); return n; } return NULL; }
CappedIterator::CappedIterator(const CollectionTemp* collection, const DiskLoc& start, bool tailable, const CollectionScanParams::Direction& dir) : _collection(collection), _curr(start), _tailable(tailable), _direction(dir), _killedByInvalidate(false) { verify( collection->ok() ); if (_curr.isNull()) { const NamespaceDetails* nsd = _collection->_details; const ExtentManager* em = _collection->getExtentManager(); // If a start position isn't specified, we fill one out from the start of the // collection. if (CollectionScanParams::FORWARD == _direction) { // Going forwards. if (!nsd->capLooped()) { // If our capped collection doesn't loop around, the first record is easy. _curr = nsd->firstRecord(); } else { // Our capped collection has "looped' around. // Copied verbatim from ForwardCappedCursor::init. // TODO ELABORATE _curr = em->getExtent( nsd->capExtent() )->firstRecord; if (!_curr.isNull() && _curr == nsd->capFirstNewRecord()) { _curr = em->getExtent( nsd->capExtent() )->lastRecord; _curr = nextLoop(nsd,em,_curr); } } } else { // Going backwards if (!nsd->capLooped()) { // Start at the end. _curr = nsd->lastRecord(); } else { _curr = em->getExtent( nsd->capExtent() )->lastRecord; } } } }
// // Capped collection traversal // CappedRecordStoreV1Iterator::CappedRecordStoreV1Iterator( OperationContext* txn, const CappedRecordStoreV1* collection, const DiskLoc& start, bool tailable, const CollectionScanParams::Direction& dir) : _txn(txn), _recordStore(collection), _curr(start), _tailable(tailable), _direction(dir), _killedByInvalidate(false) { if (_curr.isNull()) { const RecordStoreV1MetaData* nsd = _recordStore->details(); // If a start position isn't specified, we fill one out from the start of the // collection. if (CollectionScanParams::FORWARD == _direction) { // Going forwards. if (!nsd->capLooped()) { // If our capped collection doesn't loop around, the first record is easy. _curr = collection->firstRecord(_txn); } else { // Our capped collection has "looped' around. // Copied verbatim from ForwardCappedCursor::init. // TODO ELABORATE _curr = _getExtent( nsd->capExtent() )->firstRecord; if (!_curr.isNull() && _curr == nsd->capFirstNewRecord()) { _curr = _getExtent( nsd->capExtent() )->lastRecord; _curr = nextLoop(_curr); } } } else { // Going backwards if (!nsd->capLooped()) { // Start at the end. _curr = collection->lastRecord(_txn); } else { _curr = _getExtent( nsd->capExtent() )->lastRecord; } } } }
DiskLoc CappedRecordStoreV1Iterator::getNextCapped(const DiskLoc& dl) { invariant(!dl.isNull()); const RecordStoreV1MetaData* details = _recordStore->details(); if (CollectionScanParams::FORWARD == _direction) { // If it's not looped, it's easy. if (!_recordStore->details()->capLooped()) { return _getNextRecord( dl ); } // TODO ELABORATE // EOF. if (dl == _getExtent( details->capExtent() )->lastRecord) { return DiskLoc(); } DiskLoc ret = nextLoop(dl); // If we become capFirstNewRecord from same extent, advance to next extent. if (ret == details->capFirstNewRecord() && ret != _getExtent( details->capExtent() )->firstRecord) { ret = nextLoop(_getExtent( details->capExtent() )->lastRecord); } // If we have just gotten to beginning of capExtent, skip to capFirstNewRecord if (ret == _getExtent( details->capExtent() )->firstRecord) { ret = details->capFirstNewRecord(); } return ret; } else { if (!details->capLooped()) { return _getPrevRecord( dl ); } // TODO ELABORATE // Last record if (details->capFirstNewRecord() == _getExtent( details->capExtent() )->firstRecord) { if (dl == nextLoop(_getExtent( details->capExtent() )->lastRecord)) { return DiskLoc(); } } else { if (dl == _getExtent( details->capExtent() )->firstRecord) { return DiskLoc(); } } DiskLoc ret; // If we are capFirstNewRecord, advance to prev extent, otherwise just get prev. if (dl == details->capFirstNewRecord()) { ret = prevLoop(_getExtent( details->capExtent() )->firstRecord); } else { ret = prevLoop(dl); } // If we just became last in cap extent, advance past capFirstNewRecord // (We know ext(capExtent)->firstRecord != capFirstNewRecord, since would // have returned DiskLoc() earlier otherwise.) if (ret == _getExtent( details->capExtent() )->lastRecord) { ret = _getPrevRecord( details->capFirstNewRecord() ); } return ret; } }