0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-30 09:06:21 +01:00
mongodb/db/cursor.cpp

143 lines
4.7 KiB
C++
Raw Normal View History

2009-01-13 16:32:34 +01:00
/**
* 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/>.
*/
2009-01-18 17:53:33 +01:00
#include "stdafx.h"
2009-01-13 16:32:34 +01:00
#include "pdfile.h"
2009-01-14 23:09:51 +01:00
namespace mongo {
class Forward : public AdvanceStrategy {
virtual DiskLoc next( const DiskLoc &prev ) const {
return prev.rec()->getNext( prev );
}
} _forward;
2009-01-13 16:32:34 +01:00
class Reverse : public AdvanceStrategy {
virtual DiskLoc next( const DiskLoc &prev ) const {
return prev.rec()->getPrev( prev );
}
} _reverse;
2009-01-13 16:32:34 +01:00
AdvanceStrategy *forward() {
return &_forward;
}
AdvanceStrategy *reverse() {
return &_reverse;
}
2009-01-13 16:32:34 +01:00
DiskLoc nextLoop( NamespaceDetails *nsd, const DiskLoc &prev ) {
assert( nsd->capLooped() );
DiskLoc next = forward()->next( prev );
if ( !next.isNull() )
return next;
return nsd->firstRecord();
}
2009-01-13 16:32:34 +01:00
DiskLoc prevLoop( NamespaceDetails *nsd, const DiskLoc &curr ) {
assert( nsd->capLooped() );
DiskLoc prev = reverse()->next( curr );
if ( !prev.isNull() )
return prev;
return nsd->lastRecord();
}
2009-01-13 16:32:34 +01:00
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 );
}
}
2009-01-13 16:32:34 +01:00
}
curr = start;
2009-01-19 15:51:38 +01:00
s = this;
2009-01-13 16:32:34 +01:00
}
DiskLoc ForwardCappedCursor::next( const DiskLoc &prev ) const {
assert( nsd );
if ( !nsd->capLooped() )
return forward()->next( prev );
2009-01-13 16:32:34 +01:00
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;
}
2009-01-13 16:32:34 +01:00
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;
2009-01-19 15:51:38 +01:00
s = this;
}
2009-01-13 16:32:34 +01:00
DiskLoc ReverseCappedCursor::next( const DiskLoc &prev ) const {
assert( nsd );
if ( !nsd->capLooped() )
return reverse()->next( prev );
2009-01-14 23:17:24 +01:00
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();
}
2009-01-13 16:32:34 +01:00
}
// 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 );
2009-01-13 16:32:34 +01:00
return i;
}
2009-01-14 23:09:51 +01:00
} // namespace mongo