~evarlast/ubuntu/utopic/mongodb/upstart-workaround-debian-bug-718702

« back to all changes in this revision

Viewing changes to src/mongo/db/ops/query.cpp

  • Committer: Package Import Robot
  • Author(s): James Page, James Page, Robie Basak
  • Date: 2013-05-29 17:44:42 UTC
  • mfrom: (44.1.7 sid)
  • Revision ID: package-import@ubuntu.com-20130529174442-z0a4qmoww4y0t458
Tags: 1:2.4.3-1ubuntu1
[ James Page ]
* Merge from Debian unstable, remaining changes:
  - Enable SSL support:
    + d/control: Add libssl-dev to BD's.
    + d/rules: Enabled --ssl option.
    + d/mongodb.conf: Add example SSL configuration options.
  - d/mongodb-server.mongodb.upstart: Add upstart configuration.
  - d/rules: Don't strip binaries during scons build for Ubuntu.
  - d/control: Add armhf to target archs.
  - d/p/SConscript.client.patch: fixup install of client libraries.
  - d/p/0010-install-libs-to-usr-lib-not-usr-lib64-Closes-588557.patch:
    Install libraries to lib not lib64.
* Dropped changes:
  - d/p/arm-support.patch: Included in Debian.
  - d/p/double-alignment.patch: Included in Debian.
  - d/rules,control: Debian also builds with avaliable system libraries
    now.
* Fix FTBFS due to gcc and boost upgrades in saucy:
  - d/p/0008-ignore-unused-local-typedefs.patch: Add -Wno-unused-typedefs
    to unbreak building with g++-4.8.
  - d/p/0009-boost-1.53.patch: Fixup signed/unsigned casting issue.

[ Robie Basak ]
* d/p/0011-Use-a-signed-char-to-store-BSONType-enumerations.patch: Fixup
  build failure on ARM due to missing signed'ness of char cast.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 */
18
18
 
19
19
#include "pch.h"
20
 
#include "query.h"
21
 
#include "../pdfile.h"
22
 
#include "../clientcursor.h"
23
 
#include "../oplog.h"
24
 
#include "../../bson/util/builder.h"
25
 
#include "../replutil.h"
26
 
#include "../scanandorder.h"
27
 
#include "../commands.h"
28
 
#include "../queryoptimizer.h"
29
 
#include "../../s/d_logic.h"
30
 
#include "../../server.h"
31
 
#include "../queryoptimizercursor.h"
32
 
#include "../pagefault.h"
 
20
 
 
21
#include "mongo/db/ops/query.h"
 
22
 
 
23
#include "mongo/bson/util/builder.h"
 
24
#include "mongo/db/clientcursor.h"
 
25
#include "mongo/db/commands.h"
 
26
#include "mongo/db/oplog.h"
 
27
#include "mongo/db/pagefault.h"
 
28
#include "mongo/db/pdfile.h"
 
29
#include "mongo/db/queryoptimizer.h"
 
30
#include "mongo/db/queryoptimizercursor.h"
 
31
#include "mongo/db/replutil.h"
 
32
#include "mongo/db/scanandorder.h"
 
33
#include "mongo/s/d_logic.h"
 
34
#include "mongo/s/stale_exception.h"  // for SendStaleConfigException
 
35
#include "mongo/server.h"
33
36
 
34
37
namespace mongo {
35
38
 
80
83
        return qr;
81
84
    }
82
85
 
83
 
    QueryResult* processGetMore(const char *ns, int ntoreturn, long long cursorid , CurOp& curop, int pass, bool& exhaust ) {
 
86
    QueryResult* processGetMore(const char* ns,
 
87
                                int ntoreturn,
 
88
                                long long cursorid,
 
89
                                CurOp& curop,
 
90
                                int pass,
 
91
                                bool& exhaust,
 
92
                                bool* isCursorAuthorized ) {
84
93
        exhaust = false;
85
 
        ClientCursor::Pin p(cursorid);
86
 
        ClientCursor *cc = p.c();
87
94
 
88
95
        int bufSize = 512 + sizeof( QueryResult ) + MaxBytesToReturnToClientAtOnce;
89
96
 
93
100
        int start = 0;
94
101
        int n = 0;
95
102
 
 
103
        Client::ReadContext ctx(ns);
 
104
        // call this readlocked so state can't change
 
105
        replVerifyReadsOk();
 
106
 
 
107
        ClientCursor::Pin p(cursorid);
 
108
        ClientCursor *cc = p.c();
 
109
 
 
110
 
96
111
        if ( unlikely(!cc) ) {
97
112
            LOGSOME << "getMore: cursorid not found " << ns << " " << cursorid << endl;
98
113
            cursorid = 0;
102
117
            // check for spoofing of the ns such that it does not match the one originally there for the cursor
103
118
            uassert(14833, "auth error", str::equals(ns, cc->ns().c_str()));
104
119
 
 
120
            *isCursorAuthorized = true;
 
121
 
105
122
            if ( pass == 0 )
106
123
                cc->updateSlaveLocation( curop );
107
124
 
108
125
            int queryOptions = cc->queryOptions();
109
126
            
110
127
            curop.debug().query = cc->query();
 
128
            curop.setQuery( cc->query() );
111
129
 
112
130
            start = cc->pos();
113
131
            Cursor *c = cc->c();
207
225
        return qr;
208
226
    }
209
227
 
 
228
    ResultDetails::ResultDetails() :
 
229
        match(),
 
230
        orderedMatch(),
 
231
        loadedRecord(),
 
232
        chunkSkip() {
 
233
    }
 
234
 
210
235
    ExplainRecordingStrategy::ExplainRecordingStrategy
211
236
    ( const ExplainQueryInfo::AncillaryInfo &ancillaryInfo ) :
212
237
    _ancillaryInfo( ancillaryInfo ) {
233
258
    _orderedMatches() {
234
259
    }
235
260
    
236
 
    void MatchCountingExplainStrategy::noteIterate( bool match, bool orderedMatch,
237
 
                                                   bool loadedRecord, bool chunkSkip ) {
238
 
        _noteIterate( match, orderedMatch, loadedRecord, chunkSkip );
239
 
        if ( orderedMatch ) {
 
261
    void MatchCountingExplainStrategy::noteIterate( const ResultDetails& resultDetails ) {
 
262
        _noteIterate( resultDetails );
 
263
        if ( resultDetails.orderedMatch ) {
240
264
            ++_orderedMatches;
241
265
        }
242
266
    }
253
277
        _explainInfo->notePlan( *_cursor, scanAndOrder, indexOnly );
254
278
    }
255
279
 
256
 
    void SimpleCursorExplainStrategy::_noteIterate( bool match, bool orderedMatch,
257
 
                                                   bool loadedRecord, bool chunkSkip ) {
258
 
        _explainInfo->noteIterate( match, loadedRecord, chunkSkip, *_cursor );
 
280
    void SimpleCursorExplainStrategy::_noteIterate( const ResultDetails& resultDetails ) {
 
281
        _explainInfo->noteIterate( resultDetails.match,
 
282
                                   resultDetails.loadedRecord,
 
283
                                   resultDetails.chunkSkip,
 
284
                                   *_cursor );
259
285
    }
260
286
 
261
287
    void SimpleCursorExplainStrategy::noteYield() {
274
300
    _cursor( cursor ) {
275
301
    }
276
302
    
277
 
    void QueryOptimizerCursorExplainStrategy::_noteIterate( bool match, bool orderedMatch,
278
 
                                                           bool loadedRecord, bool chunkSkip ) {
 
303
    void QueryOptimizerCursorExplainStrategy::_noteIterate( const ResultDetails& resultDetails ) {
279
304
        // Note ordered matches only; if an unordered plan is selected, the explain result will
280
305
        // be updated with reviseN().
281
 
        _cursor->noteIterate( orderedMatch, loadedRecord, chunkSkip );
 
306
        _cursor->noteIterate( resultDetails.orderedMatch,
 
307
                              resultDetails.loadedRecord,
 
308
                              resultDetails.chunkSkip );
282
309
    }
283
310
 
284
311
    void QueryOptimizerCursorExplainStrategy::noteYield() {
303
330
        _buf.skip( sizeof( QueryResult ) );
304
331
    }
305
332
 
306
 
    BSONObj ResponseBuildStrategy::current( bool allowCovered ) const {
 
333
    BSONObj ResponseBuildStrategy::current( bool allowCovered,
 
334
                                            ResultDetails* resultDetails ) const {
307
335
        if ( _parsedQuery.returnKey() ) {
308
336
            BSONObjBuilder bob;
309
337
            bob.appendKeys( _cursor->indexKeyPattern(), _cursor->currKey() );
315
343
                return keyFieldsOnly->hydrate( _cursor->currKey() );
316
344
            }
317
345
        }
 
346
        resultDetails->loadedRecord = true;
318
347
        BSONObj ret = _cursor->current();
319
348
        verify( ret.isValid() );
320
349
        return ret;
328
357
    _bufferedMatches() {
329
358
    }
330
359
    
331
 
    bool OrderedBuildStrategy::handleMatch( bool &orderedMatch, MatchDetails& details ) {
 
360
    bool OrderedBuildStrategy::handleMatch( ResultDetails* resultDetails ) {
332
361
        DiskLoc loc = _cursor->currLoc();
333
362
        if ( _cursor->getsetdup( loc ) ) {
334
 
            return orderedMatch = false;
 
363
            return false;
335
364
        }
336
365
        if ( _skip > 0 ) {
337
366
            --_skip;
338
 
            return orderedMatch = false;
 
367
            return false;
339
368
        }
 
369
        BSONObj currentDocument = current( true, resultDetails );
340
370
        // Explain does not obey soft limits, so matches should not be buffered.
341
371
        if ( !_parsedQuery.isExplain() ) {
342
372
            fillQueryResultFromObj( _buf, _parsedQuery.getFields(),
343
 
                                    current( true ), &details,
 
373
                                    currentDocument, &resultDetails->matchDetails,
344
374
                                   ( _parsedQuery.showDiskLoc() ? &loc : 0 ) );
345
375
            ++_bufferedMatches;
346
376
        }
347
 
        return orderedMatch = true;
 
377
        resultDetails->match = true;
 
378
        resultDetails->orderedMatch = true;
 
379
        return true;
348
380
    }
349
381
 
350
382
    ReorderBuildStrategy* ReorderBuildStrategy::make( const ParsedQuery& parsedQuery,
367
399
        _scanAndOrder.reset( newScanAndOrder( queryPlan ) );
368
400
    }
369
401
 
370
 
    bool ReorderBuildStrategy::handleMatch( bool &orderedMatch, MatchDetails& details ) {
371
 
        orderedMatch = false;
 
402
    bool ReorderBuildStrategy::handleMatch( ResultDetails* resultDetails ) {
372
403
        if ( _cursor->getsetdup( _cursor->currLoc() ) ) {
373
404
            return false;
374
405
        }
375
 
        _handleMatchNoDedup();
 
406
        _handleMatchNoDedup( resultDetails );
 
407
        resultDetails->match = true;
376
408
        return true;
377
409
    }
378
410
    
379
 
    void ReorderBuildStrategy::_handleMatchNoDedup() {
 
411
    void ReorderBuildStrategy::_handleMatchNoDedup( ResultDetails* resultDetails ) {
380
412
        DiskLoc loc = _cursor->currLoc();
381
 
        _scanAndOrder->add( current( false ), _parsedQuery.showDiskLoc() ? &loc : 0 );
 
413
        _scanAndOrder->add( current( false, resultDetails ),
 
414
                            _parsedQuery.showDiskLoc() ? &loc : 0 );
382
415
    }
383
416
 
384
417
    int ReorderBuildStrategy::rewriteMatches() {
429
462
                                                         QueryPlanSummary() ) );
430
463
    }
431
464
 
432
 
    bool HybridBuildStrategy::handleMatch( bool &orderedMatch, MatchDetails& details ) {
 
465
    bool HybridBuildStrategy::handleMatch( ResultDetails* resultDetails ) {
433
466
        if ( !_queryOptimizerCursor->currentPlanScanAndOrderRequired() ) {
434
 
            return _orderedBuild.handleMatch( orderedMatch, details );
 
467
            return _orderedBuild.handleMatch( resultDetails );
435
468
        }
436
 
        orderedMatch = false;
437
 
        return handleReorderMatch();
 
469
        return handleReorderMatch( resultDetails );
438
470
    }
439
471
    
440
 
    bool HybridBuildStrategy::handleReorderMatch() {
 
472
    bool HybridBuildStrategy::handleReorderMatch( ResultDetails* resultDetails ) {
441
473
        DiskLoc loc = _cursor->currLoc();
442
474
        if ( _scanAndOrderDups.getsetdup( loc ) ) {
443
475
            return false;
444
476
        }
 
477
        resultDetails->match = true;
445
478
        try {
446
 
            _reorderBuild->_handleMatchNoDedup();
 
479
            _reorderBuild->_handleMatchNoDedup( resultDetails );
447
480
        } catch ( const UserException &e ) {
448
481
            if ( e.getCode() == ScanAndOrderMemoryLimitExceededAssertionCode ) {
449
482
                if ( _queryOptimizerCursor->hasPossiblyExcludedPlans() ) {
504
537
    }
505
538
 
506
539
    bool QueryResponseBuilder::addMatch() {
507
 
        MatchDetails details;
 
540
        ResultDetails resultDetails;
508
541
 
509
542
        if ( _parsedQuery.getFields() && _parsedQuery.getFields()->getArrayOpType() == Projection::ARRAY_OP_POSITIONAL ) {
510
543
            // field projection specified, and contains an array operator
511
 
            details.requestElemMatchKey();
512
 
        }
513
 
 
514
 
        if ( !currentMatches( details ) ) {
515
 
            return false;
516
 
        }
517
 
        if ( !chunkMatches() ) {
518
 
            return false;
519
 
        }
520
 
        bool orderedMatch = false;
521
 
        bool match = _builder->handleMatch( orderedMatch, details );
522
 
        _explain->noteIterate( match, orderedMatch, true, false );
 
544
            resultDetails.matchDetails.requestElemMatchKey();
 
545
        }
 
546
 
 
547
        bool match =
 
548
                currentMatches( &resultDetails ) &&
 
549
                chunkMatches( &resultDetails ) &&
 
550
                _builder->handleMatch( &resultDetails );
 
551
 
 
552
        _explain->noteIterate( resultDetails );
523
553
        return match;
524
554
    }
525
555
 
615
645
        ( HybridBuildStrategy::make( _parsedQuery, _queryOptimizerCursor, _buf ) );
616
646
    }
617
647
 
618
 
    bool QueryResponseBuilder::currentMatches( MatchDetails& details ) {
619
 
        if ( _cursor->currentMatches( &details ) ) {
620
 
            return true;
 
648
    bool QueryResponseBuilder::currentMatches( ResultDetails* resultDetails ) {
 
649
        bool matches = _cursor->currentMatches( &resultDetails->matchDetails );
 
650
        if ( resultDetails->matchDetails.hasLoadedRecord() ) {
 
651
            resultDetails->loadedRecord = true;
621
652
        }
622
 
        _explain->noteIterate( false, false, details.hasLoadedRecord(), false );
623
 
        return false;
 
653
        return matches;
624
654
    }
625
655
 
626
 
    bool QueryResponseBuilder::chunkMatches() {
 
656
    bool QueryResponseBuilder::chunkMatches( ResultDetails* resultDetails ) {
627
657
        if ( !_chunkManager ) {
628
658
            return true;
629
659
        }
630
660
        // TODO: should make this covered at some point
 
661
        resultDetails->loadedRecord = true;
631
662
        if ( _chunkManager->belongsToMe( _cursor->current() ) ) {
632
663
            return true;
633
664
        }
634
 
        _explain->noteIterate( false, false, true, true );
 
665
        resultDetails->chunkSkip = true;
635
666
        return false;
636
667
    }
637
668
    
658
689
        }
659
690
        else {
660
691
            cursor =
661
 
                NamespaceDetailsTransient::getCursor( ns.c_str(), query, order, QueryPlanSelectionPolicy::any(),
662
 
                                                      0, pq_shared, false, &queryPlan );
 
692
                NamespaceDetailsTransient::getCursor( ns.c_str(),
 
693
                                                      query,
 
694
                                                      order,
 
695
                                                      QueryPlanSelectionPolicy::any(),
 
696
                                                      pq_shared,
 
697
                                                      false,
 
698
                                                      &queryPlan );
663
699
        }
664
700
        verify( cursor );
665
701
        
796
832
        qr->setOperation(opReply);
797
833
        qr->startingFrom = 0;
798
834
        qr->nReturned = nReturned;
799
 
        
800
 
        int duration = curop.elapsedMillis();
801
 
        bool dbprofile = curop.shouldDBProfile( duration );
802
 
        if ( dbprofile || duration >= cmdLine.slowMS ) {
803
 
            curop.debug().nscanned = ( cursor ? cursor->nscanned() : 0LL );
804
 
            curop.debug().ntoskip = pq.getSkip();
805
 
        }
 
835
 
 
836
        curop.debug().nscanned = ( cursor ? cursor->nscanned() : 0LL );
 
837
        curop.debug().ntoskip = pq.getSkip();
806
838
        curop.debug().nreturned = nReturned;
807
839
 
808
840
        return curop.debug().exhaust ? ns : "";