diff options
author | Eliot Horowitz <eliot@10gen.com> | 2011-12-24 15:33:26 -0500 |
---|---|---|
committer | Eliot Horowitz <eliot@10gen.com> | 2011-12-24 15:33:45 -0500 |
commit | ae1ecd9c786911f9f1f0242f0f7d702b3e5dfeba (patch) | |
tree | 92f8e1649e6f080b251ff5f1763679a72eb59b34 /src/mongo/db/cursor.cpp | |
parent | dfa4cd7e2cf109b072440155fabc08a93c8045a0 (diff) | |
download | mongo-ae1ecd9c786911f9f1f0242f0f7d702b3e5dfeba.tar.gz |
bulk move of code to src/ SERVER-4551
Diffstat (limited to 'src/mongo/db/cursor.cpp')
-rw-r--r-- | src/mongo/db/cursor.cpp | 166 |
1 files changed, 166 insertions, 0 deletions
diff --git a/src/mongo/db/cursor.cpp b/src/mongo/db/cursor.cpp new file mode 100644 index 00000000000..ac7afc1532b --- /dev/null +++ b/src/mongo/db/cursor.cpp @@ -0,0 +1,166 @@ +/** + * Copyright (C) 2008 10gen Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License, version 3, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "pch.h" +#include "pdfile.h" +#include "curop-inl.h" + +namespace mongo { + + bool BasicCursor::advance() { + killCurrentOp.checkForInterrupt(); + if ( eof() ) { + if ( tailable_ && !last.isNull() ) { + curr = s->next( last ); + } + else { + return false; + } + } + else { + last = curr; + curr = s->next( curr ); + } + incNscanned(); + return ok(); + } + + /* these will be used outside of mutexes - really functors - thus the const */ + class Forward : public AdvanceStrategy { + virtual DiskLoc next( const DiskLoc &prev ) const { + return prev.rec()->getNext( prev ); + } + } _forward; + + class Reverse : public AdvanceStrategy { + virtual DiskLoc next( const DiskLoc &prev ) const { + return prev.rec()->getPrev( prev ); + } + } _reverse; + + const AdvanceStrategy *forward() { + return &_forward; + } + const AdvanceStrategy *reverse() { + return &_reverse; + } + + DiskLoc nextLoop( NamespaceDetails *nsd, const DiskLoc &prev ) { + assert( nsd->capLooped() ); + DiskLoc next = forward()->next( prev ); + if ( !next.isNull() ) + return next; + return nsd->firstRecord(); + } + + DiskLoc prevLoop( NamespaceDetails *nsd, const DiskLoc &curr ) { + assert( nsd->capLooped() ); + DiskLoc prev = reverse()->next( curr ); + if ( !prev.isNull() ) + return prev; + return nsd->lastRecord(); + } + + ForwardCappedCursor::ForwardCappedCursor( NamespaceDetails *_nsd, const DiskLoc &startLoc ) : + nsd( _nsd ) { + if ( !nsd ) + return; + DiskLoc start = startLoc; + if ( start.isNull() ) { + if ( !nsd->capLooped() ) + start = nsd->firstRecord(); + else { + start = nsd->capExtent.ext()->firstRecord; + if ( !start.isNull() && start == nsd->capFirstNewRecord ) { + start = nsd->capExtent.ext()->lastRecord; + start = nextLoop( nsd, start ); + } + } + } + curr = start; + s = this; + incNscanned(); + } + + DiskLoc ForwardCappedCursor::next( const DiskLoc &prev ) const { + assert( nsd ); + if ( !nsd->capLooped() ) + return forward()->next( prev ); + + DiskLoc i = prev; + // Last record + if ( i == nsd->capExtent.ext()->lastRecord ) + return DiskLoc(); + i = nextLoop( nsd, i ); + // If we become capFirstNewRecord from same extent, advance to next extent. + if ( i == nsd->capFirstNewRecord && + i != nsd->capExtent.ext()->firstRecord ) + i = nextLoop( nsd, nsd->capExtent.ext()->lastRecord ); + // If we have just gotten to beginning of capExtent, skip to capFirstNewRecord + if ( i == nsd->capExtent.ext()->firstRecord ) + i = nsd->capFirstNewRecord; + return i; + } + + ReverseCappedCursor::ReverseCappedCursor( NamespaceDetails *_nsd, const DiskLoc &startLoc ) : + nsd( _nsd ) { + if ( !nsd ) + return; + DiskLoc start = startLoc; + if ( start.isNull() ) { + if ( !nsd->capLooped() ) { + start = nsd->lastRecord(); + } + else { + start = nsd->capExtent.ext()->lastRecord; + } + } + curr = start; + s = this; + incNscanned(); + } + + DiskLoc ReverseCappedCursor::next( const DiskLoc &prev ) const { + assert( nsd ); + if ( !nsd->capLooped() ) + return reverse()->next( prev ); + + DiskLoc i = prev; + // Last record + if ( nsd->capFirstNewRecord == nsd->capExtent.ext()->firstRecord ) { + if ( i == nextLoop( nsd, nsd->capExtent.ext()->lastRecord ) ) { + return DiskLoc(); + } + } + else { + if ( i == nsd->capExtent.ext()->firstRecord ) { + return DiskLoc(); + } + } + // If we are capFirstNewRecord, advance to prev extent, otherwise just get prev. + if ( i == nsd->capFirstNewRecord ) + i = prevLoop( nsd, nsd->capExtent.ext()->firstRecord ); + else + i = prevLoop( nsd, i ); + // 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 ( i == nsd->capExtent.ext()->lastRecord ) + i = reverse()->next( nsd->capFirstNewRecord ); + + return i; + } +} // namespace mongo |