DiskLoc RocksRecordStore::Iterator::getNext() {
        if ( !_iterator->Valid() ) {
            return DiskLoc();
        }

        DiskLoc toReturn = curr();

        if ( _forward() )
            _iterator->Next();
        else
            _iterator->Prev();

        return toReturn;
    }
Esempio n. 2
0
 /* fetch a single object from collection ns that matches query
    set your db SavedContext first
 */
 DiskLoc Helpers::findOne(const StringData& ns, const BSONObj &query, bool requireIndex) {
     shared_ptr<Cursor> c =
         NamespaceDetailsTransient::getCursor( ns.data() , query, BSONObj(),
                                               requireIndex ?
                                               QueryPlanSelectionPolicy::indexOnly() :
                                               QueryPlanSelectionPolicy::any() );
     while( c->ok() ) {
         if ( c->currentMatches() && !c->getsetdup( c->currLoc() ) ) {
             return c->currLoc();
         }
         c->advance();
     }
     return DiskLoc();
 }
Esempio n. 3
0
    /* fetch a single object from collection ns that matches query
       set your db SavedContext first
    */
    DiskLoc Helpers::findOne(Collection* collection, const BSONObj &query, bool requireIndex) {
        if ( !collection )
            return DiskLoc();

        CanonicalQuery* cq;
        const WhereCallbackReal whereCallback(collection->ns().db());

        massert(17244, "Could not canonicalize " + query.toString(),
            CanonicalQuery::canonicalize(collection->ns(), query, &cq, whereCallback).isOK());

        Runner* rawRunner;
        size_t options = requireIndex ? QueryPlannerParams::NO_TABLE_SCAN : QueryPlannerParams::DEFAULT;
        massert(17245, "Could not get runner for query " + query.toString(),
                getRunner(collection, cq, &rawRunner, options).isOK());

        auto_ptr<Runner> runner(rawRunner);
        Runner::RunnerState state;
        DiskLoc loc;
        if (Runner::RUNNER_ADVANCED == (state = runner->getNext(NULL, &loc))) {
            return loc;
        }
        return DiskLoc();
    }
Esempio n. 4
0
    int64_t Collection::countTableScan( const MatchExpression* expression ) {
        scoped_ptr<RecordIterator> iterator( getIterator( DiskLoc(),
                                                              false,
                                                              CollectionScanParams::FORWARD ) );
        int64_t count = 0;
        while ( !iterator->isEOF() ) {
            DiskLoc loc = iterator->getNext();
            BSONObj obj = docFor( loc );
            if ( expression->matchesBSON( obj ) )
                count++;
        }

        return count;
    }
 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() );
     }
 }
Esempio n. 6
0
 void CappedIterator::invalidate(const DiskLoc& dl) {
     if ((_tailable && _curr.isNull() && dl == _prev) || (dl == _curr)) {
         // In the _tailable case, we're about to kill the DiskLoc that we're tailing.  Nothing
         // that we can possibly do to survive that.
         //
         // In the _curr case, we *could* move to the next thing, since there is actually a next
         // thing, but according to clientcursor.cpp:
         // "note we cannot advance here. if this condition occurs, writes to the oplog
         //  have "caught" the reader.  skipping ahead, the reader would miss postentially
         //  important data."
         _curr = _prev = DiskLoc();
         _killedByInvalidate = true;
     }
 }
Esempio n. 7
0
        virtual void keyAt(DiskLoc thisLoc, int pos, BSONObj& key, DiskLoc& recordLoc) {
            recordLoc = DiskLoc();
            const BtreeBucket<V>* bucket = thisLoc.btree<V>();
            int n = bucket->nKeys();

            if( pos < 0 || pos >= n || n == 0xffff /* bucket deleted */ || ! bucket->isUsed( pos ) ){
                // log() << "Pos: " << pos << " n " << n << endl;
                return;
            }

            typename BtreeBucket<V>::KeyNode kn = bucket->keyNode(pos);
            key = kn.key.toBson();
            recordLoc = kn.recordLoc;
        }
Esempio n. 8
0
    virtual RecordStore* newCappedRecordStore( int64_t cappedMaxSize,
            int64_t cappedMaxDocs ) {
        OperationContextNoop txn;
        DummyRecordStoreV1MetaData* md = new DummyRecordStoreV1MetaData( true, 0 );
        CappedRecordStoreV1* rs = new CappedRecordStoreV1( &txn,
                NULL,
                "a.b",
                md,
                &_em,
                false );

        LocAndSize records[] = {
            {}
        };
        LocAndSize drecs[] = {
            {DiskLoc(0, 1000), 1000},
            {}
        };
        md->setCapExtent(&txn, DiskLoc(0, 0));
        md->setCapFirstNewRecord(&txn, DiskLoc().setInvalid());
        initializeV1RS(&txn, records, drecs, NULL, &_em, md);

        return rs;
    }
Esempio n. 9
0
    BSONObjExternalSorter::Iterator::Iterator( BSONObjExternalSorter * sorter ) :
        _cmp( sorter->_order ) , _in( 0 ){
        
        for ( list<string>::iterator i=sorter->_files.begin(); i!=sorter->_files.end(); i++ ){
            _files.push_back( new FileIterator( *i ) );
            _stash.push_back( pair<Data,bool>( Data( BSONObj() , DiskLoc() ) , false ) );
        }
        
        if ( _files.size() == 0 && sorter->_cur ){
            _in = sorter->_cur;
            _it = sorter->_cur->begin();
        }

        
    }
Esempio n. 10
0
    void OplogStart::invalidate(const DiskLoc& dl, InvalidationType type) {
        if (_needInit) { return; }

        if (INVALIDATION_DELETION != type) { return; }

        if (_backwardsScanning) {
            _cs->invalidate(dl, type);
        }
        else {
            verify(_extentHopping);
            if (dl == _curloc) {
                _curloc = DiskLoc();
            }
        }
    }
Esempio n. 11
0
 virtual void customLocate(const BSONObj& keyBegin,
                           int keyBeginLen,
                           bool afterKey,
                           const vector<const BSONElement*>& keyEnd,
                           const vector<bool>& keyEndInclusive) {
     // makeQueryObject handles stripping of fieldnames for us.
     _it = lower_bound(IndexEntry(IndexEntryComparison::makeQueryObject(
                                       keyBegin,
                                       keyBeginLen,
                                       afterKey,
                                       keyEnd,
                                       keyEndInclusive,
                                       -1), // reverse
                                  DiskLoc()));
 }
Esempio n. 12
0
    // static
    Status ProjectionExecutor::applyFindSyntax(const FindProjection* proj, WorkingSetMember* wsm) {
        BSONObjBuilder bob;
        if (proj->_includeID) {
            BSONElement elt;
            if (!wsm->getFieldDotted("_id", &elt)) {
                return Status(ErrorCodes::BadValue, "Couldn't get _id field in proj");
            }
            bob.append(elt);
        }

        if (proj->_includedFields.size() > 0) {
            // We only want stuff in _fields.
            const vector<string>& fields = proj->_includedFields;
            for (size_t i = 0; i < fields.size(); ++i) {
                BSONElement elt;
                // We can project a field that doesn't exist.  We just ignore it.
                // UNITTEST 11738048
                if (wsm->getFieldDotted(fields[i], &elt) && !elt.eoo()) {
                    // TODO: This fails utterly for dotted fields.  Fix.
                    bob.appendAs(elt, fields[i]);
                }
            }
        }
        else if (proj->_excludedFields.size() > 0) {
            // We want stuff NOT in _fields.  This can't be covered, so we expect an obj.
            if (!wsm->hasObj()) {
                return Status(ErrorCodes::BadValue,
                        "exclusion specified for projection but no obj to iter over");
            }
            const unordered_set<string>& fields = proj->_excludedFields;
            BSONObjIterator it(wsm->obj);
            while (it.more()) {
                BSONElement elt = it.next();
                if (!mongoutils::str::equals("_id", elt.fieldName())) {
                    if (fields.end() == fields.find(elt.fieldName())) {
                        bob.append(elt);
                    }
                }
            }
        }

        wsm->state = WorkingSetMember::OWNED_OBJ;
        wsm->obj = bob.obj();
        wsm->keyData.clear();
        wsm->loc = DiskLoc();
        return Status::OK();
    }
Esempio n. 13
0
    Status ProjectionStage::transform(WorkingSetMember* member) {
        // The default no-fast-path case.
        if (ProjectionStageParams::NO_FAST_PATH == _projImpl) {
            return _exec->transform(member);
        }

        BSONObjBuilder bob;

        // Note that even if our fast path analysis is bug-free something that is
        // covered might be invalidated and just be an obj.  In this case we just go
        // through the SIMPLE_DOC path which is still correct if the covered data
        // is not available.
        //
        // SIMPLE_DOC implies that we expect an object so it's kind of redundant.
        if ((ProjectionStageParams::SIMPLE_DOC == _projImpl) || member->hasObj()) {
            // If we got here because of SIMPLE_DOC the planner shouldn't have messed up.
            invariant(member->hasObj());

            // Apply the SIMPLE_DOC projection.
            transformSimpleInclusion(member->obj, _includedFields, bob);
        }
        else {
            invariant(ProjectionStageParams::COVERED_ONE_INDEX == _projImpl);
            // We're pulling data out of the key.
            invariant(1 == member->keyData.size());
            size_t keyIndex = 0;

            // Look at every key element...
            BSONObjIterator keyIterator(member->keyData[0].keyData);
            while (keyIterator.more()) {
                BSONElement elt = keyIterator.next();
                // If we're supposed to include it...
                if (_includeKey[keyIndex]) {
                    // Do so.
                    bob.appendAs(elt, _keyFieldNames[keyIndex]);
                }
                ++keyIndex;
            }
        }

        member->state = WorkingSetMember::OWNED_OBJ;
        member->keyData.clear();
        member->loc = DiskLoc();
        member->obj = bob.obj();
        return Status::OK();
    }
Esempio n. 14
0
 bool BtreeCursor::skipOutOfRangeKeysAndCheckEnd() {
     if ( !ok() ) {
         return false;
     }
     int ret = _boundsIterator->advance( currKey() );
     if ( ret == -2 ) {
         bucket = DiskLoc();
         return false;
     }
     else if ( ret == -1 ) {
         ++_nscanned;
         return false;
     }
     ++_nscanned;
     advanceTo( currKey(), ret, _boundsIterator->after(), _boundsIterator->cmp(), _boundsIterator->inc() );
     return true;
 }
Esempio n. 15
0
    ClientCursor::~ClientCursor() {
        if( _pos == -2 ) {
            // defensive: destructor called twice
            wassert(false);
            return;
        }

        {
            recursive_scoped_lock lock(ccmutex);
            setLastLoc_inlock( DiskLoc() ); // removes us from bylocation multimap
            clientCursorsById.erase(_cursorid);

            // defensive:
            (CursorId&)_cursorid = -1;
            _pos = -2;
        }
    }
Esempio n. 16
0
 virtual void keyAndRecordAt(DiskLoc bucket, int keyOffset, BSONObj* keyOut,
                             DiskLoc* recordOut) const {
     verify(!bucket.isNull());
     const BtreeBucket<Version> *b = bucket.btree<Version>();
     int n = b->getN();
     if (n == b->INVALID_N_SENTINEL) {
         throw UserException(deletedBucketCode, "keyAt bucket deleted");
     }
     dassert( n >= 0 && n < 10000 );
     if (keyOffset >= n) {
         *keyOut = BSONObj();
         *recordOut = DiskLoc();
     } else {
         *keyOut = b->keyNode(keyOffset).key.toBson();
         *recordOut = b->keyNode(keyOffset).recordLoc;
     }
 }
Esempio n. 17
0
    DiskLoc RecordStoreV1Base::getNextRecord( const DiskLoc& loc ) const {
        DiskLoc next = getNextRecordInExtent( loc );
        if ( !next.isNull() )
            return next;

        // now traverse extents

        Extent* e = _getExtent( _getExtentLocForRecord(loc) );
        while ( 1 ) {
            if ( e->xnext.isNull() )
                return DiskLoc(); // end of collection
            e = _getExtent( e->xnext );
            if ( !e->firstRecord.isNull() )
                break;
            // entire extent could be empty, keep looking
        }
        return e->firstRecord;
    }
Esempio n. 18
0
 int nRecords() const {
     int count = 0;
     const Extent* ext;
     for ( DiskLoc extLoc = nsd()->firstExtent();
             !extLoc.isNull();
             extLoc = ext->xnext) {
         ext = extentManager()->getExtent(extLoc);
         int fileNo = ext->firstRecord.a();
         if ( fileNo == -1 )
             continue;
         for ( int recOfs = ext->firstRecord.getOfs(); recOfs != DiskLoc::NullOfs;
               recOfs = recordStore()->recordFor(DiskLoc(fileNo, recOfs))->nextOfs() ) {
             ++count;
         }
     }
     ASSERT_EQUALS( count, nsd()->numRecords() );
     return count;
 }
Esempio n. 19
0
 DiskLoc FindingStartCursor::prevLoc( const DiskLoc &rec ) {
     Extent *e = rec.rec()->myExtent( rec );
     if ( _qp.nsd()->capLooped() ) {
         if ( e->xprev.isNull() )
             e = _qp.nsd()->lastExtent.ext();
         else
             e = e->xprev.ext();
         if ( e->myLoc != _qp.nsd()->capExtent )
             return e->firstRecord;
     }
     else {
         if ( !e->xprev.isNull() ) {
             e = e->xprev.ext();
             return e->firstRecord;
         }
     }
     return DiskLoc(); // reached beginning of collection
 }
Esempio n. 20
0
    DiskLoc ExtentManager::getNextRecord( const DiskLoc& loc ) {
        DiskLoc next = getNextRecordInExtent( loc );
        if ( !next.isNull() )
            return next;

        // now traverse extents

        Extent *e = extentFor(loc);
        while ( 1 ) {
            if ( e->xnext.isNull() )
                return DiskLoc(); // end of collection
            e = e->xnext.ext();
            if ( !e->firstRecord.isNull() )
                break;
            // entire extent could be empty, keep looking
        }
        return e->firstRecord;
    }
    void RocksCollectionCatalogEntry::MetaData::parse( const BSONObj& obj ) {
        ns = obj["ns"].valuestrsafe();

        BSONElement e = obj["indexes"];
        if ( e.isABSONObj() ) {
            std::vector<BSONElement> entries = e.Array();
            for ( unsigned i = 0; i < entries.size(); i++ ) {
                BSONObj idx = entries[i].Obj();
                IndexMetaData imd;
                imd.spec = idx["spec"].Obj();
                imd.ready = idx["ready"].trueValue();
                imd.head = DiskLoc( idx["head_a"].Int(),
                                    idx["head_b"].Int() );
                imd.multikey = idx["multikey"].trueValue();
                indexes.push_back( imd );
            }
        }
    }
Esempio n. 22
0
    DiskLoc ExtentManager::getPrevRecord( const DiskLoc& loc ) const {
        DiskLoc prev = getPrevRecordInExtent( loc );
        if ( !prev.isNull() )
            return prev;

        // now traverse extents

        Extent *e = extentFor(loc);
        while ( 1 ) {
            if ( e->xprev.isNull() )
                return DiskLoc(); // end of collection
            e = e->xprev.ext();
            if ( !e->firstRecord.isNull() )
                break;
            // entire extent could be empty, keep looking
        }
        return e->firstRecord;
    }
Esempio n. 23
0
    /* fetch a single object from collection ns that matches query
       set your db SavedContext first
    */
    DiskLoc Helpers::findOne(const StringData& ns, const BSONObj &query, bool requireIndex) {
        CanonicalQuery* cq;
        massert(17244, "Could not canonicalize " + query.toString(),
                CanonicalQuery::canonicalize(ns.toString(), query, &cq).isOK());

        Runner* rawRunner;
        size_t options = requireIndex ? QueryPlannerParams::NO_TABLE_SCAN : QueryPlannerParams::DEFAULT;
        massert(17245, "Could not get runner for query " + query.toString(),
                getRunner(cq, &rawRunner, options).isOK());

        auto_ptr<Runner> runner(rawRunner);
        Runner::RunnerState state;
        DiskLoc loc;
        if (Runner::RUNNER_ADVANCED == (state = runner->getNext(NULL, &loc))) {
            return loc;
        }
        return DiskLoc();
    }
Esempio n. 24
0
            void run() {
                create();
                nsd()->deletedList[ 2 ] = nsd()->deletedList[ 0 ].drec()->nextDeleted.drec()->nextDeleted;
                nsd()->deletedList[ 0 ].drec()->nextDeleted.drec()->nextDeleted = DiskLoc();
                nsd()->deletedList[ 1 ].Null();
                NamespaceDetails *d = nsd();
                zero( &d->capExtent );
                zero( &d->capFirstNewRecord );

                nsd();

                ASSERT( nsd()->firstExtent == nsd()->capExtent );
                ASSERT( nsd()->capExtent.getOfs() != 0 );
                ASSERT( !nsd()->capFirstNewRecord.isValid() );
                int nDeleted = 0;
                for ( DiskLoc i = nsd()->deletedList[ 0 ]; !i.isNull(); i = i.drec()->nextDeleted, ++nDeleted );
                ASSERT_EQUALS( 10, nDeleted );
                ASSERT( nsd()->deletedList[ 1 ].isNull() );
            }
Esempio n. 25
0
DiskLoc RecordStoreV1Base::getPrevRecord(OperationContext* txn, const DiskLoc& loc) const {
    DiskLoc prev = getPrevRecordInExtent(txn, loc);
    if (!prev.isNull()) {
        return prev;
    }

    // now traverse extents

    Extent* e = _getExtent(txn, _getExtentLocForRecord(txn, loc));
    while (1) {
        if (e->xprev.isNull())
            return DiskLoc();  // end of collection
        e = _getExtent(txn, e->xprev);
        if (!e->firstRecord.isNull())
            break;
        // entire extent could be empty, keep looking
    }
    return e->lastRecord;
}
    // Call advance() on a reverse cursor until it is exhausted.
    // When a cursor positioned at EOF is advanced, it stays at EOF.
    TEST( SortedDataInterface, ExhaustCursorReversed ) {
        scoped_ptr<HarnessHelper> harnessHelper( newHarnessHelper() );
        scoped_ptr<SortedDataInterface> sorted( harnessHelper->newSortedDataInterface( false ) );

        {
            scoped_ptr<OperationContext> opCtx( harnessHelper->newOperationContext() );
            ASSERT( sorted->isEmpty( opCtx.get() ) );
        }

        int nToInsert = 10;
        for ( int i = 0; i < nToInsert; i++ ) {
            scoped_ptr<OperationContext> opCtx( harnessHelper->newOperationContext() );
            {
                WriteUnitOfWork uow( opCtx.get() );
                BSONObj key = BSON( "" << i );
                DiskLoc loc( 42, i * 2 );
                ASSERT_OK( sorted->insert( opCtx.get(), key, loc, true ) );
                uow.commit();
            }
        }

        {
            scoped_ptr<OperationContext> opCtx( harnessHelper->newOperationContext() );
            ASSERT_EQUALS( nToInsert, sorted->numEntries( opCtx.get() ) );
        }

        {
            scoped_ptr<OperationContext> opCtx( harnessHelper->newOperationContext() );
            scoped_ptr<SortedDataInterface::Cursor> cursor( sorted->newCursor( opCtx.get(), -1 ) );
            ASSERT( !cursor->locate( maxKey, maxDiskLoc ) );
            for ( int i = nToInsert - 1; i >= 0; i-- ) {
                ASSERT( !cursor->isEOF() );
                ASSERT_EQUALS( BSON( "" << i ), cursor->getKey() );
                ASSERT_EQUALS( DiskLoc( 42, i * 2 ), cursor->getDiskLoc() );
                cursor->advance();
            }
            ASSERT( cursor->isEOF() );

            // Cursor at EOF should remain at EOF when advanced
            cursor->advance();
            ASSERT( cursor->isEOF() );
        }
    }
Esempio n. 27
0
        virtual void keyAndRecordAt(DiskLoc bucket, int keyOffset, BSONObj* keyOut,
                                    DiskLoc* recordOut) const {
            verify(!bucket.isNull());
            const BtreeBucket<Version> *b = bucket.btree<Version>();

            int n = b->getN();

            // If n is 0xffff the bucket was deleted.
            if (keyOffset < 0 || keyOffset >= n || n == 0xffff || !b->isUsed(keyOffset)) {
                return;
            }

            if (keyOffset >= n) {
                *keyOut = BSONObj();
                *recordOut = DiskLoc();
            } else {
                *keyOut = b->keyNode(keyOffset).key.toBson();
                *recordOut = b->keyNode(keyOffset).recordLoc;
            }
        }
    // Insert multiple keys and try to iterate through all of them
    // using a forward cursor while calling savePosition() and
    // restorePosition() in succession.
    TEST( SortedDataInterface, SaveAndRestorePositionWhileIterateCursor ) {
        scoped_ptr<HarnessHelper> harnessHelper( newHarnessHelper() );
        scoped_ptr<SortedDataInterface> sorted( harnessHelper->newSortedDataInterface( false ) );

        {
            scoped_ptr<OperationContext> opCtx( harnessHelper->newOperationContext() );
            ASSERT( sorted->isEmpty( opCtx.get() ) );
        }

        int nToInsert = 10;
        for ( int i = 0; i < nToInsert; i++ ) {
            scoped_ptr<OperationContext> opCtx( harnessHelper->newOperationContext() );
            {
                WriteUnitOfWork uow( opCtx.get() );
                BSONObj key = BSON( "" << i );
                DiskLoc loc( 42, i * 2 );
                ASSERT_OK( sorted->insert( opCtx.get(), key, loc, true ) );
                uow.commit();
            }
        }

        {
            scoped_ptr<OperationContext> opCtx( harnessHelper->newOperationContext() );
            ASSERT_EQUALS( nToInsert, sorted->numEntries( opCtx.get() ) );
        }

        {
            scoped_ptr<OperationContext> opCtx( harnessHelper->newOperationContext() );
            scoped_ptr<SortedDataInterface::Cursor> cursor( sorted->newCursor( opCtx.get(), 1 ) );
            ASSERT( !cursor->locate( minKey, minDiskLoc ) );
            for ( int i = 0; i < nToInsert; i++ ) {
                ASSERT( !cursor->isEOF() );
                ASSERT_EQUALS( BSON( "" << i ), cursor->getKey() );
                ASSERT_EQUALS( DiskLoc( 42, i * 2 ), cursor->getDiskLoc() );
                cursor->advance();
                cursor->savePosition();
                cursor->restorePosition( opCtx.get() );
            }
            ASSERT( cursor->isEOF() );
        }
    }
    // Insert the same key multiple times and try to iterate through each
    // occurrence using a reverse cursor while calling savePosition() and
    // restorePosition() in succession. Verify that the DiskLoc is saved
    // as part of the current position of the cursor.
    TEST( SortedDataInterface, SaveAndRestorePositionWhileIterateCursorWithDupKeysReversed ) {
        scoped_ptr<HarnessHelper> harnessHelper( newHarnessHelper() );
        scoped_ptr<SortedDataInterface> sorted( harnessHelper->newSortedDataInterface( false ) );

        {
            scoped_ptr<OperationContext> opCtx( harnessHelper->newOperationContext() );
            ASSERT( sorted->isEmpty( opCtx.get() ) );
        }

        int nToInsert = 10;
        for ( int i = 0; i < nToInsert; i++ ) {
            scoped_ptr<OperationContext> opCtx( harnessHelper->newOperationContext() );
            {
                WriteUnitOfWork uow( opCtx.get() );
                DiskLoc loc( 42, i * 2 );
                ASSERT_OK( sorted->insert( opCtx.get(), key1, loc, true /* allow duplicates */ ) );
                uow.commit();
            }
        }

        {
            scoped_ptr<OperationContext> opCtx( harnessHelper->newOperationContext() );
            ASSERT_EQUALS( nToInsert, sorted->numEntries( opCtx.get() ) );
        }

        {
            scoped_ptr<OperationContext> opCtx( harnessHelper->newOperationContext() );
            scoped_ptr<SortedDataInterface::Cursor> cursor( sorted->newCursor( opCtx.get(), -1 ) );
            ASSERT( !cursor->locate( maxKey, maxDiskLoc ) );
            for ( int i = nToInsert - 1; i >= 0; i-- ) {
                ASSERT( !cursor->isEOF() );
                ASSERT_EQUALS( key1, cursor->getKey() );
                ASSERT_EQUALS( DiskLoc( 42, i * 2 ), cursor->getDiskLoc() );
                cursor->advance();
                cursor->savePosition();
                cursor->restorePosition( opCtx.get() );
            }
            ASSERT( cursor->isEOF() );
        }
    }
Esempio n. 30
0
    ClientCursor::~ClientCursor() {
        if( _pos == -2 ) {
            // defensive: destructor called twice
            wassert(false);
            return;
        }

        {
            recursive_scoped_lock lock(ccmutex);
            if (NULL != _c.get()) {
                // Removes 'this' from bylocation map
                setLastLoc_inlock( DiskLoc() );
            }

            clientCursorsById.erase(_cursorid);

            // defensive:
            _cursorid = INVALID_CURSOR_ID;
            _pos = -2;
            _pinValue = 0;
        }
    }