summaryrefslogtreecommitdiff
path: root/db/oplog.h
diff options
context:
space:
mode:
authorAaron <aaron@10gen.com>2011-04-25 11:13:52 -0700
committerAaron <aaron@10gen.com>2011-04-25 13:29:50 -0700
commit2df2fe89910ae0c0c78f85e1533c49dfb765a2d0 (patch)
tree355ae260655312287110e261b24fba783d081123 /db/oplog.h
parent1733f391c97e8aba5db5c5803bf98691c939f961 (diff)
downloadmongo-2df2fe89910ae0c0c78f85e1533c49dfb765a2d0.tar.gz
reduce queryutil dependencies a bit
Diffstat (limited to 'db/oplog.h')
-rw-r--r--db/oplog.h116
1 files changed, 8 insertions, 108 deletions
diff --git a/db/oplog.h b/db/oplog.h
index 4b859ecc1e4..601b0a1a0e0 100644
--- a/db/oplog.h
+++ b/db/oplog.h
@@ -27,7 +27,6 @@
#include "db.h"
#include "dbhelpers.h"
#include "query.h"
-#include "queryoptimizer.h"
#include "../client/dbclient.h"
#include "../util/optime.h"
#include "../util/timer.h"
@@ -64,72 +63,14 @@ namespace mongo {
extern int __findingStartInitialTimeout; // configurable for testing
+ class QueryPlan;
+
class FindingStartCursor {
public:
- FindingStartCursor( const QueryPlan & qp ) :
- _qp( qp ),
- _findingStart( true ),
- _findingStartMode(),
- _findingStartTimer( 0 )
- { init(); }
+ FindingStartCursor( const QueryPlan & qp );
bool done() const { return !_findingStart; }
shared_ptr<Cursor> cRelease() { return _c; }
- void next() {
- if ( !_findingStartCursor || !_findingStartCursor->ok() ) {
- _findingStart = false;
- _c = _qp.newCursor(); // on error, start from beginning
- destroyClientCursor();
- return;
- }
- switch( _findingStartMode ) {
- case Initial: {
- if ( !_matcher->matches( _findingStartCursor->currKey(), _findingStartCursor->currLoc() ) ) {
- _findingStart = false; // found first record out of query range, so scan normally
- _c = _qp.newCursor( _findingStartCursor->currLoc() );
- destroyClientCursor();
- return;
- }
- _findingStartCursor->advance();
- RARELY {
- if ( _findingStartTimer.seconds() >= __findingStartInitialTimeout ) {
- createClientCursor( startLoc( _findingStartCursor->currLoc() ) );
- _findingStartMode = FindExtent;
- return;
- }
- }
- return;
- }
- case FindExtent: {
- if ( !_matcher->matches( _findingStartCursor->currKey(), _findingStartCursor->currLoc() ) ) {
- _findingStartMode = InExtent;
- return;
- }
- DiskLoc prev = prevLoc( _findingStartCursor->currLoc() );
- if ( prev.isNull() ) { // hit beginning, so start scanning from here
- createClientCursor();
- _findingStartMode = InExtent;
- return;
- }
- // There might be a more efficient implementation than creating new cursor & client cursor each time,
- // not worrying about that for now
- createClientCursor( prev );
- return;
- }
- case InExtent: {
- if ( _matcher->matches( _findingStartCursor->currKey(), _findingStartCursor->currLoc() ) ) {
- _findingStart = false; // found first record in query range, so scan normally
- _c = _qp.newCursor( _findingStartCursor->currLoc() );
- destroyClientCursor();
- return;
- }
- _findingStartCursor->advance();
- return;
- }
- default: {
- massert( 14038, "invalid _findingStartMode", false );
- }
- }
- }
+ void next();
bool prepareToYield() {
if ( _findingStartCursor ) {
return _findingStartCursor->prepareToYield( _yieldData );
@@ -153,56 +94,15 @@ namespace mongo {
ClientCursor::CleanupPointer _findingStartCursor;
shared_ptr<Cursor> _c;
ClientCursor::YieldData _yieldData;
- DiskLoc startLoc( const DiskLoc &rec ) {
- Extent *e = rec.rec()->myExtent( rec );
- if ( !_qp.nsd()->capLooped() || ( e->myLoc != _qp.nsd()->capExtent ) )
- return e->firstRecord;
- // Likely we are on the fresh side of capExtent, so return first fresh record.
- // If we are on the stale side of capExtent, then the collection is small and it
- // doesn't matter if we start the extent scan with capFirstNewRecord.
- return _qp.nsd()->capFirstNewRecord;
- }
+ DiskLoc startLoc( const DiskLoc &rec );
// should never have an empty extent in the oplog, so don't worry about that case
- DiskLoc 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
- }
- void createClientCursor( const DiskLoc &startLoc = DiskLoc() ) {
- shared_ptr<Cursor> c = _qp.newCursor( startLoc );
- _findingStartCursor.reset( new ClientCursor(QueryOption_NoCursorTimeout, c, _qp.ns()) );
- }
+ DiskLoc prevLoc( const DiskLoc &rec );
+ void createClientCursor( const DiskLoc &startLoc = DiskLoc() );
void destroyClientCursor() {
_findingStartCursor.reset( 0 );
}
- void init() {
- // Use a ClientCursor here so we can release db mutex while scanning
- // oplog (can take quite a while with large oplogs).
- shared_ptr<Cursor> c = _qp.newReverseCursor();
- _findingStartCursor.reset( new ClientCursor(QueryOption_NoCursorTimeout, c, _qp.ns(), BSONObj()) );
- _findingStartTimer.reset();
- _findingStartMode = Initial;
- BSONElement tsElt = _qp.originalQuery()[ "ts" ];
- massert( 13044, "no ts field in query", !tsElt.eoo() );
- BSONObjBuilder b;
- b.append( tsElt );
- BSONObj tsQuery = b.obj();
- _matcher.reset(new CoveredIndexMatcher(tsQuery, _qp.indexKey()));
- }
+ void init();
};
void pretouchOperation(const BSONObj& op);