zoukankan      html  css  js  c++  java
  • MongoDB源码分析——mongod数据查询操作

    源码版本为MongoDB 2.6分支

    Edit

    mongod数据查询操作

    在mongod的初始化过程中说过,服务端接收到客户端消息后调用MyMessageHandler::process函数处理消息。

    class MyMessageHandler : public MessageHandler {
    public:
        ...
        virtual void process( Message& m , AbstractMessagingPort* port , LastError * le) {
            while ( true ) {
                ...
    
                DbResponse dbresponse;
                try {
                    assembleResponse( m, dbresponse, port->remote() );
                }
                catch ( const ClockSkewException & ) {
                    log() << "ClockSkewException - shutting down" << endl;
                    exitCleanly( EXIT_CLOCK_SKEW );
                }
                ...
            }
        }
    };
    

    DbResponse dbresponse;封装了服务器处理消息后的响应数据。在进入数据处理分析之前先看一个枚举类型Operations ,Operations表示了所有MongoDB的操作 类型 :

    enum Operations {
        opReply = 1,     /* reply. responseTo is set. */
        dbMsg = 1000,    /* generic msg command followed by a string */
        dbUpdate = 2001, /* update object */
        dbInsert = 2002, //数据插入
        //dbGetByOID = 2003,
        dbQuery = 2004,  //数据查询
        dbGetMore = 2005, //可能是数据同步
        dbDelete = 2006, //数据删除
        dbKillCursors = 2007 //关闭cursor
    };
    

    Message对象中封装了当前message的操作类型。之后本篇文章只分析dbQuery 部分,其他部分将会在其他文章中分析。
    可以看到process中调用了assembleResponse来处理消息并封装响应对象(DbResponse dbresponse),下面部分我们将分析assembleResponse函数:

    int op = m.operation();
        bool isCommand = false;
    
        DbMessage dbmsg(m);
    
        if ( op == dbQuery ) {
            const char *ns = dbmsg.getns();
    
            if (strstr(ns, ".$cmd")) {
                isCommand = true;
                opwrite(m);
                if( strstr(ns, ".$cmd.sys.") ) {
                    if( strstr(ns, "$cmd.sys.inprog") ) {
                        inProgCmd(m, dbresponse);
                        return;
                    }
                    if( strstr(ns, "$cmd.sys.killop") ) {
                        killOp(m, dbresponse);
                        return;
                    }
                    if( strstr(ns, "$cmd.sys.unlock") ) {
                        unlockFsync(ns, m, dbresponse);
                        return;
                    }
                }
            }
            else {
                opread(m); //如果不是命令则记录日志
            }
        }
        ...
    

    在阅读上面的代码之前首先要了解MongoDB源码里面的一个概念——namespace(缩写ns),一个ns代表一个collection和对应的db,一般表示为:”db name” + “.” + “collection name”,如果ns名称中包含“.$cmd”则表示当前操作为一个命令。所以上面代码先判断了是否为数据库命令,如果是则处理,然后返回。

        // Increment op counters.
        switch (op) {
        case dbQuery:
            if (!isCommand) {
                //增加查询操作计数,暂时没发现有什么作用~
                globalOpCounters.gotQuery();
            }
            else {
                // Command counting is deferred, since it is not known yet whether the command
                // needs counting.
            }
            break;
            ...
        }
    
        ...
        //进入正题,查询数据
        if ( op == dbQuery ) {
            if ( handlePossibleShardedMessage( m , &dbresponse ) )
                return;
            receivedQuery(c , dbresponse, m );
        }
    

    之前的这些代码都只是做了一下操作分发操作,就是把不同的操作请求分配给相应的函数去处理,而查询请求则由receivedQuery函数处理。

    static bool receivedQuery(Client& c, DbResponse& dbresponse, Message& m ) {
        ...
        DbMessage d(m);
        QueryMessage q(d);
        auto_ptr< Message > resp( new Message() );
    
        CurOp& op = *(c.curop());
    
        try {
            NamespaceString ns(d.getns());
            cout << "receivedQuery NamespaceString : " << d.getns() << endl;
    
            if (!ns.isCommand()) {
                //查询权限认证
                // Auth checking for Commands happens later.
                Client* client = &cc();
                Status status = client->getAuthorizationSession()->checkAuthForQuery(ns, q.query);
                audit::logQueryAuthzCheck(client, ns, q.query, status.code());
                uassertStatusOK(status);
            }
            dbresponse.exhaustNS = newRunQuery(m, q, op, *resp);
            verify( !resp->empty() );
        }
        catch (...)
        {
            ...
        }
        ...
    
        return ok;
    }
    

    receivedQuery主要分为两部分,第一部分是查询操作,第二部分是操作结果处理(这一部分我给省略了),可以看到,进行查询操作前先进行了查询操作认证,如果当前用户对这个集合没有权限则会抛出异常。如果认证通过则会调用newRunQuery函数进行查询。

    /**
      * Run the query 'q' and place the result in 'result'.
      */
    std::string newRunQuery(Message& m, QueryMessage& q, CurOp& curop, Message &result);
    

    接下来才是查询操作的重头戏,整个过程包括数据的加载,查询命令解析,集合数据扫描匹配等步骤,由于目前对MongoDB的还不是很熟悉,很多地方我个人还是理解不了,所以具体的数据扫描匹配细节会暂时略过,先分析查找流程,具体细节以后深入之后再学习。

        const NamespaceString nsString(ns);
        uassert(16256, str::stream() << "Invalid ns [" << ns << "]", nsString.isValid());
    
        // Set curop information.
        curop.debug().ns = ns;
        curop.debug().ntoreturn = q.ntoreturn;
        curop.debug().query = q.query;
        curop.setQuery(q.query);
    
        // If the query is really a command, run it.
        if (nsString.isCommand()) {
            int nToReturn = q.ntoreturn;
            uassert(16979, str::stream() << "bad numberToReturn (" << nToReturn
                                         << ") for $cmd type ns - can only be 1 or -1",
                    nToReturn == 1 || nToReturn == -1);
    
            curop.markCommand();
    
            BufBuilder bb;
            bb.skip(sizeof(QueryResult));
    
            BSONObjBuilder cmdResBuf;
            if (!runCommands(ns, q.query, curop, bb, cmdResBuf, false, q.queryOptions)) {
                uasserted(13530, "bad or malformed command request?");
            }
    
            curop.debug().iscommand = true;
            // TODO: Does this get overwritten/do we really need to set this twice?
            curop.debug().query = q.query;
    
            QueryResult* qr = reinterpret_cast<QueryResult*>(bb.buf());
            bb.decouple();
            qr->setResultFlagsToOk();
            qr->len = bb.len();
            curop.debug().responseLength = bb.len();
            qr->setOperation(opReply);
            qr->cursorId = 0;
            qr->startingFrom = 0;
            qr->nReturned = 1;
            result.setData(qr, true);
            return "";
        }
    

    之前的代码中已经对部分killop,unlock等部分命令进行了处理,这个地方对之前没有处理的命令再次进行处理,然后直接返回。如果不是命令则继续往下执行,下面就是整个算法最核心的部分:

        // This is a read lock.  We require this because if we're parsing a $where, the
        // where-specific parsing code assumes we have a lock and creates execution machinery that
        // requires it.
        Client::ReadContext ctx(q.ns);
        Collection* collection = ctx.ctx().db()->getCollection( ns );
    
        // Parse the qm into a CanonicalQuery.
        CanonicalQuery* cq;
        Status canonStatus = CanonicalQuery::canonicalize(q, &cq);
        if (!canonStatus.isOK()) {
            uasserted(17287, str::stream() << "Can't canonicalize query: " << canonStatus.toString());
        }
        verify(cq);
    
        QLOG() << "Running query:
    " << cq->toString();
        LOG(2) << "Running query: " << cq->toStringShort();
    
        // Parse, canonicalize, plan, transcribe, and get a runner.
        Runner* rawRunner = NULL;
    
        // We use this a lot below.
        const LiteParsedQuery& pq = cq->getParsed();
    
        // We'll now try to get the query runner that will execute this query for us. There
        // are a few cases in which we know upfront which runner we should get and, therefore,
        // we shortcut the selection process here.
        //
        // (a) If the query is over a collection that doesn't exist, we get a special runner
        // that's is so (a runner) which doesn't return results, the EOFRunner.
        //
        // (b) if the query is a replication's initial sync one, we get a SingleSolutinRunner
        // that uses a specifically designed stage that skips extents faster (see details in
        // exec/oplogstart.h)
        //
        // Otherwise we go through the selection of which runner is most suited to the
        // query + run-time context at hand.
        Status status = Status::OK();
        if (collection == NULL) {
            rawRunner = new EOFRunner(cq, cq->ns());
        }
        else if (pq.hasOption(QueryOption_OplogReplay)) {
            status = getOplogStartHack(collection, cq, &rawRunner);
        }
        else {
            // Takes ownership of cq.
            size_t options = QueryPlannerParams::DEFAULT;
            if (shardingState.needCollectionMetadata(pq.ns())) {
                options |= QueryPlannerParams::INCLUDE_SHARD_FILTER;
            }
            status = getRunner(cq, &rawRunner, options);
        }
    
        if (!status.isOK()) {
            // NOTE: Do not access cq as getRunner has deleted it.
            uasserted(17007, "Unable to execute query: " + status.reason());
        }
    

    上面部分代码包含数据加载,查询数据解析,查询算法匹配等过程,下面稍微详细的分析一下过程。

        // This is a read lock.  We require this because if we're parsing a $where, the
        // where-specific parsing code assumes we have a lock and creates execution machinery that
        // requires it.
        Client::ReadContext ctx(q.ns);
    

    从注释中可以看着,这是一个“读锁”,但是他实际的功能并不止这些。

     /** "read lock, and set my context, all in one operation" 
         *  This handles (if not recursively locked) opening an unopened database.
         */
        class ReadContext : boost::noncopyable { 
        public:
            ReadContext(const std::string& ns, const std::string& path=storageGlobalParams.dbpath);
            Context& ctx() { return *c.get(); }
        private:
            scoped_ptr<Lock::DBRead> lk;
            scoped_ptr<Context> c;
        };
    

    ReadContext 有点像一个代理或者是适配器,实际包含了一个Context对象,然后利用Lock::DBRead添加“读锁”操作。

    /** "read lock, and set my context, all in one operation" 
     *  This handles (if not recursively locked) opening an unopened database.
     */
    Client::ReadContext::ReadContext(const string& ns, const std::string& path) {
        {
            lk.reset( new Lock::DBRead(ns) );
            Database *db = dbHolder().get(ns, path);
            if( db ) {
                c.reset( new Context(path, ns, db) );
                return;
            }
        }
    
        // we usually don't get here, so doesn't matter how fast this part is
        {
            if( Lock::isW() ) { 
                // write locked already
                DEV RARELY log() << "write locked on ReadContext construction " << ns << endl;
                c.reset(new Context(ns, path));
            }
            else if( !Lock::nested() ) { 
                lk.reset(0);
                {
                    Lock::GlobalWrite w;
                    Context c(ns, path);
                }
                // db could be closed at this interim point -- that is ok, we will throw, and don't mind throwing.
                lk.reset( new Lock::DBRead(ns) );
                c.reset(new Context(ns, path));
            }
            else { 
                uasserted(15928, str::stream() << "can't open a database from a nested read lock " << ns);
            }
        }
    }
    

    可以看到在ReadContext构造函数中先根据ns来锁住数据库(之前已经说过,ns包含数据库名称和集合名称),然后在根据ns和数据库路径来获取Database对象,一个Database对象代表一个数据库(这部分包含数据库数据加载,暂时不分析),如果获取到db对象,则设置上下文信息。

    如果没有获取到db对象,则会进入到下面:

    lk.reset( new Lock::DBRead(ns) );
    c.reset(new Context(ns, path));
    

    Context提供了多个构造函数,这个构造函数中会去创建db对象,并加载数据。锁住数据库之后将进入核心查询部分。

     // Parse the qm into a CanonicalQuery.
        CanonicalQuery* cq;
        Status canonStatus = CanonicalQuery::canonicalize(q, &cq);
    

    首先会解析查询消息为标准化的查询对象,主要是将BSON结构数据转换为MatchExpression方便使用。
    之后会获取一个Runner对象来执行查询:

        Runner* rawRunner = NULL;
    
        // We use this a lot below.
        const LiteParsedQuery& pq = cq->getParsed();
    
        // We'll now try to get the query runner that will execute this query for us. There
        // are a few cases in which we know upfront which runner we should get and, therefore,
        // we shortcut the selection process here.
        //
        // (a) If the query is over a collection that doesn't exist, we get a special runner
        // that's is so (a runner) which doesn't return results, the EOFRunner.
        //
        // (b) if the query is a replication's initial sync one, we get a SingleSolutinRunner
        // that uses a specifically designed stage that skips extents faster (see details in
        // exec/oplogstart.h)
        //
        // Otherwise we go through the selection of which runner is most suited to the
        // query + run-time context at hand.
        Status status = Status::OK();
        if (collection == NULL) {
            rawRunner = new EOFRunner(cq, cq->ns());
        }
        else if (pq.hasOption(QueryOption_OplogReplay)) {
            status = getOplogStartHack(collection, cq, &rawRunner);
        }
        else {
            // Takes ownership of cq.
            size_t options = QueryPlannerParams::DEFAULT;
            if (shardingState.needCollectionMetadata(pq.ns())) {
                options |= QueryPlannerParams::INCLUDE_SHARD_FILTER;
            }
            status = getRunner(cq, &rawRunner, options);
        }
    

    上面代码调用getRunner函数来返回一个Runner对象,该Runner对象会对集合进行遍历,然后找到符合查询条件的结果并返回。

    一个Runner就代表一种数据查询方式,mongo会根据之前的查询BSON解析结果来判断应该使用哪一种Runner来执行查询,有点类似策略模式。
    IDHackRunner : 当前集合是以“_id”作为索引或者查询条件中包含”_id”时就使用此来查询。
    CachedPlanRunner:如果之前已经有缓存plan,则使用此来查询。
    MultiPlanRunner:使用QueryPlanner来plan 查询条件,如果结果为多个QuerySolution,则使用此来执行查询。
    SingleSolutionRunner:和multi相对应,对应一些简单的查询则使用此来执行。
    SubPlanRunner:没搞明白…

    上面这些Runner都比较复杂,详细分析的话每一个都能需要耗费很多时间,其中包含了对集合的扫描算法,对查询的分段处理等等,整个mongod的核心查询算法都封装在这里面,暂时就不深入研究了。

        // Run the query.
        // bb is used to hold query results
        // this buffer should contain either requested documents per query or
        // explain information, but not both
        BufBuilder bb(32768);
        bb.skip(sizeof(QueryResult));
    
          ...
    
        while (Runner::RUNNER_ADVANCED == (state = runner->getNext(&obj, NULL))) {
            // Add result to output buffer. This is unnecessary if explain info is requested
            if (!isExplain) {
                bb.appendBuf((void*)obj.objdata(), obj.objsize());
            }
    
            // Count the result.
            ++numResults;
            ...
        }
    

    获取Runner对象后当然是使用该对象来获取查询结果,Runner提供一个getNext函数来获取下一个结果,之后的就是将查询结果放到result中,然后返回给客户端。

    至此,整个数据查询的轮廓已经出来了,其中数据加载和查询算法部分我都很只是提了一下然后略过,主要是水平有限,很多东西我自己还没弄明白,写出来也都是错的,MongoDB的每一个版本代码改动都很大,参考了很多前辈对其他版本的分析,真是很佩服他们,很多东西都分析很透彻,但是对照来看这个版本的源码还是有很多迷惑的地方,所以数据加载和查询算法两个部分之研究明白之后再单独开篇吧。

     
    %23%23%20mongod%u6570%u636E%u67E5%u8BE2%u64CD%u4F5C%0A%u5728mongod%u7684%u521D%u59CB%u5316%u8FC7%u7A0B%u4E2D%u8BF4%u8FC7%uFF0C%u670D%u52A1%u7AEF%u63A5%u6536%u5230%u5BA2%u6237%u7AEF%u6D88%u606F%u540E%u8C03%u7528MyMessageHandler%3A%3Aprocess%u51FD%u6570%u5904%u7406%u6D88%u606F%u3002%0A%0A%20%20%20%20class%20MyMessageHandler%20%3A%20public%20MessageHandler%20%7B%0A%20%20%20%20public%3A%0A%09%20%20%20%20...%0A%20%20%20%20%20%20%20%20virtual%20void%20process%28%20Message%26%20m%20%2C%20AbstractMessagingPort*%20port%20%2C%20LastError%20*%20le%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20while%20%28%20true%20%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20...%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20DbResponse%20dbresponse%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20assembleResponse%28%20m%2C%20dbresponse%2C%20port-%3Eremote%28%29%20%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20catch%20%28%20const%20ClockSkewException%20%26%20%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20log%28%29%20%3C%3C%20%22ClockSkewException%20-%20shutting%20down%22%20%3C%3C%20endl%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20exitCleanly%28%20EXIT_CLOCK_SKEW%20%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20...%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%3B%0A%0A%20DbResponse%20dbresponse%3B%u5C01%u88C5%u4E86%u670D%u52A1%u5668%u5904%u7406%u6D88%u606F%u540E%u7684%u54CD%u5E94%u6570%u636E%u3002%u5728%u8FDB%u5165%u6570%u636E%u5904%u7406%u5206%u6790%u4E4B%u524D%u5148%u770B%u4E00%u4E2A%u679A%u4E3E%u7C7B%u578BOperations%20%uFF0COperations%u8868%u793A%u4E86%u6240%u4EE5MongoDB%u7684%u64CD%u4F5C%20%u7C7B%u578B%20%3A%20%0A%0A%20%20%20%20enum%20Operations%20%7B%0A%20%20%20%20%20%20%20%20opReply%20%3D%201%2C%20%20%20%20%20/*%20reply.%20responseTo%20is%20set.%20*/%0A%20%20%20%20%20%20%20%20dbMsg%20%3D%201000%2C%20%20%20%20/*%20generic%20msg%20command%20followed%20by%20a%20string%20*/%0A%20%20%20%20%20%20%20%20dbUpdate%20%3D%202001%2C%20/*%20update%20object%20*/%0A%20%20%20%20%20%20%20%20dbInsert%20%3D%202002%2C%20//%u6570%u636E%u63D2%u5165%0A%20%20%20%20%20%20%20%20//dbGetByOID%20%3D%202003%2C%0A%20%20%20%20%20%20%20%20dbQuery%20%3D%202004%2C%20%20//%u6570%u636E%u67E5%u8BE2%0A%20%20%20%20%20%20%20%20dbGetMore%20%3D%202005%2C%20//%u53EF%u80FD%u662F%u6570%u636E%u540C%u6B65%0A%20%20%20%20%20%20%20%20dbDelete%20%3D%202006%2C%20//%u6570%u636E%u5220%u9664%0A%20%20%20%20%20%20%20%20dbKillCursors%20%3D%202007%20//%u5173%u95EDcursor%0A%20%20%20%20%7D%3B%0AMessage%u5BF9%u8C61%u4E2D%u5C01%u88C5%u4E86%u5F53%u524Dmessage%u7684%u64CD%u4F5C%u7C7B%u578B%u3002%u4E4B%u540E%u672C%u7BC7%u6587%u7AE0%u53EA%u5206%u6790dbQuery%20%u90E8%u5206%uFF0C%u5176%u4ED6%u90E8%u5206%u5C06%u4F1A%u5728%u5176%u4ED6%u6587%u7AE0%u4E2D%u5206%u6790%u3002%0A%u53EF%u4EE5%u770B%u5230process%u4E2D%u8C03%u7528%u4E86assembleResponse%u6765%u5904%u7406%u6D88%u606F%u5E76%u5C01%u88C5%u54CD%u5E94%u5BF9%u8C61%uFF08DbResponse%20dbresponse%uFF09%2C%u4E0B%u9762%u90E8%u5206%u6211%u4EEC%u5C06%u5206%u6790assembleResponse%u51FD%u6570%3A%0A%0A%20%20%20%20int%20op%20%3D%20m.operation%28%29%3B%0A%20%20%20%20%20%20%20%20bool%20isCommand%20%3D%20false%3B%0A%0A%20%20%20%20%20%20%20%20DbMessage%20dbmsg%28m%29%3B%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20if%20%28%20op%20%3D%3D%20dbQuery%20%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20char%20*ns%20%3D%20dbmsg.getns%28%29%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20%28strstr%28ns%2C%20%22.%24cmd%22%29%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20isCommand%20%3D%20true%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20opwrite%28m%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%28%20strstr%28ns%2C%20%22.%24cmd.sys.%22%29%20%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%28%20strstr%28ns%2C%20%22%24cmd.sys.inprog%22%29%20%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20inProgCmd%28m%2C%20dbresponse%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%28%20strstr%28ns%2C%20%22%24cmd.sys.killop%22%29%20%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20killOp%28m%2C%20dbresponse%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%28%20strstr%28ns%2C%20%22%24cmd.sys.unlock%22%29%20%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unlockFsync%28ns%2C%20m%2C%20dbresponse%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20opread%28m%29%3B%20//%u5982%u679C%u4E0D%u662F%u547D%u4EE4%u5219%u8BB0%u5F55%u65E5%u5FD7%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20...%0A%u5728%u9605%u8BFB%u4E0A%u9762%u7684%u4EE3%u7801%u4E4B%u524D%u9996%u5148%u8981%u4E86%u89E3MongoDB%u6E90%u7801%u91CC%u9762%u7684%u4E00%u4E2A%u6982%u5FF5%u2014%u2014namespace%28%u7F29%u5199ns%29%uFF0C%u4E00%u4E2Ans%u4EE3%u8868%u4E00%u4E2Acollection%u548C%u5BF9%u5E94%u7684db%uFF0C%u4E00%u822C%u8868%u793A%u4E3A%3A%22db%20name%22%20+%20%22.%22%20+%20%22collection%20name%22%uFF0C%u5982%u679Cns%u540D%u79F0%u4E2D%u5305%u542B%u201C.%24cmd%u201D%u5219%u8868%u793A%u5F53%u524D%u64CD%u4F5C%u4E3A%u4E00%u4E2A%u547D%u4EE4%u3002%u6240%u4EE5%u4E0A%u9762%u4EE3%u7801%u5148%u5224%u65AD%u4E86%u662F%u5426%u4E3A%u6570%u636E%u5E93%u547D%u4EE4%uFF0C%u5982%u679C%u662F%u5219%u5904%u7406%uFF0C%u7136%u540E%u8FD4%u56DE%u3002%0A%0A%20%20%20%20%20%20%20%20//%20Increment%20op%20counters.%0A%20%20%20%20%20%20%20%20switch%20%28op%29%20%7B%0A%20%20%20%20%20%20%20%20case%20dbQuery%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20%28%21isCommand%29%20%7B%0A%09%20%20%20%20%20%20%20%20%20%20%20%20//%u589E%u52A0%u67E5%u8BE2%u64CD%u4F5C%u8BA1%u6570%uFF0C%u6682%u65F6%u6CA1%u53D1%u73B0%u6709%u4EC0%u4E48%u4F5C%u7528%7E%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20globalOpCounters.gotQuery%28%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Command%20counting%20is%20deferred%2C%20since%20it%20is%20not%20known%20yet%20whether%20the%20command%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20needs%20counting.%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20break%3B%0A%09%20%20%20%20%20%20%20%20...%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20...%0A%09%09//%u8FDB%u5165%u6B63%u9898%uFF0C%u67E5%u8BE2%u6570%u636E%0A%20%20%20%20%20%20%20%20if%20%28%20op%20%3D%3D%20dbQuery%20%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20%28%20handlePossibleShardedMessage%28%20m%20%2C%20%26dbresponse%20%29%20%29%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20receivedQuery%28c%20%2C%20dbresponse%2C%20m%20%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%u4E4B%u524D%u7684%u8FD9%u4E9B%u4EE3%u7801%u90FD%u53EA%u662F%u505A%u4E86%u4E00%u4E0B%u64CD%u4F5C%u5206%u53D1%u64CD%u4F5C%uFF0C%u5C31%u662F%u628A%u4E0D%u540C%u7684%u64CD%u4F5C%u8BF7%u6C42%u5206%u914D%u7ED9%u76F8%u5E94%u7684%u51FD%u6570%u53BB%u5904%u7406%uFF0C%u800C%u67E5%u8BE2%u8BF7%u6C42%u5219%u7531receivedQuery%u51FD%u6570%u5904%u7406%u3002%0A%0A%20%20%20%20static%20bool%20receivedQuery%28Client%26%20c%2C%20DbResponse%26%20dbresponse%2C%20Message%26%20m%20%29%20%7B%0A%09%20%20%20%20...%0A%20%20%20%20%20%20%20%20DbMessage%20d%28m%29%3B%0A%20%20%20%20%20%20%20%20QueryMessage%20q%28d%29%3B%0A%20%20%20%20%20%20%20%20auto_ptr%3C%20Message%20%3E%20resp%28%20new%20Message%28%29%20%29%3B%0A%0A%20%20%20%20%20%20%20%20CurOp%26%20op%20%3D%20*%28c.curop%28%29%29%3B%0A%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20NamespaceString%20ns%28d.getns%28%29%29%3B%0A%09%09%09cout%20%3C%3C%20%22receivedQuery%20NamespaceString%20%3A%20%22%20%3C%3C%20d.getns%28%29%20%3C%3C%20endl%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20%28%21ns.isCommand%28%29%29%20%7B%0A%09%20%20%20%20%20%20%20%20%20%20%20%20//%u67E5%u8BE2%u6743%u9650%u8BA4%u8BC1%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20Auth%20checking%20for%20Commands%20happens%20later.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Client*%20client%20%3D%20%26cc%28%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Status%20status%20%3D%20client-%3EgetAuthorizationSession%28%29-%3EcheckAuthForQuery%28ns%2C%20q.query%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20audit%3A%3AlogQueryAuthzCheck%28client%2C%20ns%2C%20q.query%2C%20status.code%28%29%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20uassertStatusOK%28status%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20dbresponse.exhaustNS%20%3D%20newRunQuery%28m%2C%20q%2C%20op%2C%20*resp%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20verify%28%20%21resp-%3Eempty%28%29%20%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20catch%20%28...%29%0A%20%20%20%20%20%20%20%20%7B%0A%09%20%20%20%20%20%20%20%20...%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20...%0A%0A%20%20%20%20%20%20%20%20return%20ok%3B%0A%20%20%20%20%7D%0AreceivedQuery%u4E3B%u8981%u5206%u4E3A%u4E24%u90E8%u5206%uFF0C%u7B2C%u4E00%u90E8%u5206%u662F%u67E5%u8BE2%u64CD%u4F5C%uFF0C%u7B2C%u4E8C%u90E8%u5206%u662F%u64CD%u4F5C%u7ED3%u679C%u5904%u7406%28%u8FD9%u4E00%u90E8%u5206%u6211%u7ED9%u7701%u7565%u4E86%29%uFF0C%u53EF%u4EE5%u770B%u5230%uFF0C%u8FDB%u884C%u67E5%u8BE2%u64CD%u4F5C%u524D%u5148%u8FDB%u884C%u4E86%u67E5%u8BE2%u64CD%u4F5C%u8BA4%u8BC1%uFF0C%u5982%u679C%u5F53%u524D%u7528%u6237%u5BF9%u8FD9%u4E2A%u96C6%u5408%u6CA1%u6709%u6743%u9650%u5219%u4F1A%u629B%u51FA%u5F02%u5E38%u3002%u5982%u679C%u8BA4%u8BC1%u901A%u8FC7%u5219%u4F1A%u8C03%u7528newRunQuery%u51FD%u6570%u8FDB%u884C%u67E5%u8BE2%u3002%0A%0A%20%20%20%20/**%0A%20%20%20%20%20%20*%20Run%20the%20query%20%27q%27%20and%20place%20the%20result%20in%20%27result%27.%0A%20%20%20%20%20%20*/%0A%20%20%20%20std%3A%3Astring%20newRunQuery%28Message%26%20m%2C%20QueryMessage%26%20q%2C%20CurOp%26%20curop%2C%20Message%20%26result%29%3B%0A%u63A5%u4E0B%u6765%u624D%u662F%u67E5%u8BE2%u64CD%u4F5C%u7684%u91CD%u5934%u620F%uFF0C%u6574%u4E2A%u8FC7%u7A0B%u5305%u62EC%u6570%u636E%u7684%u52A0%u8F7D%uFF0C%u67E5%u8BE2%u547D%u4EE4%u89E3%u6790%uFF0C%u96C6%u5408%u6570%u636E%u626B%u63CF%u5339%u914D%u7B49%u6B65%u9AA4%uFF0C%u7531%u4E8E%u76EE%u524D%u5BF9MongoDB%u7684%u8FD8%u4E0D%u662F%u5F88%u719F%u6089%uFF0C%u5F88%u591A%u5730%u65B9%u6211%u4E2A%u4EBA%u8FD8%u662F%u7406%u89E3%u4E0D%u4E86%uFF0C%u6240%u4EE5%u5177%u4F53%u7684%u6570%u636E%u626B%u63CF%u5339%u914D%u7EC6%u8282%u4F1A%u6682%u65F6%u7565%u8FC7%uFF0C%u5148%u5206%u6790%u67E5%u627E%u6D41%u7A0B%uFF0C%u5177%u4F53%u7EC6%u8282%u4EE5%u540E%u6DF1%u5165%u4E4B%u540E%u518D%u5B66%u4E60%u3002%0A%0A%09%20%20%20%20const%20NamespaceString%20nsString%28ns%29%3B%0A%20%20%20%20%20%20%20%20uassert%2816256%2C%20str%3A%3Astream%28%29%20%3C%3C%20%22Invalid%20ns%20%5B%22%20%3C%3C%20ns%20%3C%3C%20%22%5D%22%2C%20nsString.isValid%28%29%29%3B%0A%0A%20%20%20%20%20%20%20%20//%20Set%20curop%20information.%0A%20%20%20%20%20%20%20%20curop.debug%28%29.ns%20%3D%20ns%3B%0A%20%20%20%20%20%20%20%20curop.debug%28%29.ntoreturn%20%3D%20q.ntoreturn%3B%0A%20%20%20%20%20%20%20%20curop.debug%28%29.query%20%3D%20q.query%3B%0A%20%20%20%20%20%20%20%20curop.setQuery%28q.query%29%3B%0A%0A%20%20%20%20%20%20%20%20//%20If%20the%20query%20is%20really%20a%20command%2C%20run%20it.%0A%20%20%20%20%20%20%20%20if%20%28nsString.isCommand%28%29%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20int%20nToReturn%20%3D%20q.ntoreturn%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20uassert%2816979%2C%20str%3A%3Astream%28%29%20%3C%3C%20%22bad%20numberToReturn%20%28%22%20%3C%3C%20nToReturn%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%3C%20%22%29%20for%20%24cmd%20type%20ns%20-%20can%20only%20be%201%20or%20-1%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20nToReturn%20%3D%3D%201%20%7C%7C%20nToReturn%20%3D%3D%20-1%29%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20curop.markCommand%28%29%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20BufBuilder%20bb%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20bb.skip%28sizeof%28QueryResult%29%29%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20BSONObjBuilder%20cmdResBuf%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20%28%21runCommands%28ns%2C%20q.query%2C%20curop%2C%20bb%2C%20cmdResBuf%2C%20false%2C%20q.queryOptions%29%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20uasserted%2813530%2C%20%22bad%20or%20malformed%20command%20request%3F%22%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20curop.debug%28%29.iscommand%20%3D%20true%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20TODO%3A%20Does%20this%20get%20overwritten/do%20we%20really%20need%20to%20set%20this%20twice%3F%0A%20%20%20%20%20%20%20%20%20%20%20%20curop.debug%28%29.query%20%3D%20q.query%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20QueryResult*%20qr%20%3D%20reinterpret_cast%3CQueryResult*%3E%28bb.buf%28%29%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20bb.decouple%28%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20qr-%3EsetResultFlagsToOk%28%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20qr-%3Elen%20%3D%20bb.len%28%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20curop.debug%28%29.responseLength%20%3D%20bb.len%28%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20qr-%3EsetOperation%28opReply%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20qr-%3EcursorId%20%3D%200%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20qr-%3EstartingFrom%20%3D%200%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20qr-%3EnReturned%20%3D%201%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20result.setData%28qr%2C%20true%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20%22%22%3B%0A%20%20%20%20%20%20%20%20%7D%0A%u4E4B%u524D%u7684%u4EE3%u7801%u4E2D%u5DF2%u7ECF%u5BF9%u90E8%u5206killop%uFF0Cunlock%u7B49%u90E8%u5206%u547D%u4EE4%u8FDB%u884C%u4E86%u5904%u7406%uFF0C%u8FD9%u4E2A%u5730%u65B9%u5BF9%u4E4B%u524D%u6CA1%u6709%u5904%u7406%u7684%u547D%u4EE4%u518D%u6B21%u8FDB%u884C%u5904%u7406%uFF0C%u7136%u540E%u76F4%u63A5%u8FD4%u56DE%u3002%u5982%u679C%u4E0D%u662F%u547D%u4EE4%u5219%u7EE7%u7EED%u5F80%u4E0B%u6267%u884C%uFF0C%u4E0B%u9762%u5C31%u662F%u6574%u4E2A%u7B97%u6CD5%u6700%u6838%u5FC3%u7684%u90E8%u5206%3A%0A%0A%20%20%20%20%20%20%20%20//%20This%20is%20a%20read%20lock.%20%20We%20require%20this%20because%20if%20we%27re%20parsing%20a%20%24where%2C%20the%0A%20%20%20%20%20%20%20%20//%20where-specific%20parsing%20code%20assumes%20we%20have%20a%20lock%20and%20creates%20execution%20machinery%20that%0A%20%20%20%20%20%20%20%20//%20requires%20it.%0A%20%20%20%20%20%20%20%20Client%3A%3AReadContext%20ctx%28q.ns%29%3B%0A%20%20%20%20%20%20%20%20Collection*%20collection%20%3D%20ctx.ctx%28%29.db%28%29-%3EgetCollection%28%20ns%20%29%3B%0A%0A%20%20%20%20%20%20%20%20//%20Parse%20the%20qm%20into%20a%20CanonicalQuery.%0A%20%20%20%20%20%20%20%20CanonicalQuery*%20cq%3B%0A%20%20%20%20%20%20%20%20Status%20canonStatus%20%3D%20CanonicalQuery%3A%3Acanonicalize%28q%2C%20%26cq%29%3B%0A%20%20%20%20%20%20%20%20if%20%28%21canonStatus.isOK%28%29%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20uasserted%2817287%2C%20str%3A%3Astream%28%29%20%3C%3C%20%22Can%27t%20canonicalize%20query%3A%20%22%20%3C%3C%20canonStatus.toString%28%29%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20verify%28cq%29%3B%0A%0A%20%20%20%20%20%20%20%20QLOG%28%29%20%3C%3C%20%22Running%20query%3A%5Cn%22%20%3C%3C%20cq-%3EtoString%28%29%3B%0A%20%20%20%20%20%20%20%20LOG%282%29%20%3C%3C%20%22Running%20query%3A%20%22%20%3C%3C%20cq-%3EtoStringShort%28%29%3B%0A%0A%20%20%20%20%20%20%20%20//%20Parse%2C%20canonicalize%2C%20plan%2C%20transcribe%2C%20and%20get%20a%20runner.%0A%20%20%20%20%20%20%20%20Runner*%20rawRunner%20%3D%20NULL%3B%0A%0A%20%20%20%20%20%20%20%20//%20We%20use%20this%20a%20lot%20below.%0A%20%20%20%20%20%20%20%20const%20LiteParsedQuery%26%20pq%20%3D%20cq-%3EgetParsed%28%29%3B%0A%0A%20%20%20%20%20%20%20%20//%20We%27ll%20now%20try%20to%20get%20the%20query%20runner%20that%20will%20execute%20this%20query%20for%20us.%20There%0A%20%20%20%20%20%20%20%20//%20are%20a%20few%20cases%20in%20which%20we%20know%20upfront%20which%20runner%20we%20should%20get%20and%2C%20therefore%2C%0A%20%20%20%20%20%20%20%20//%20we%20shortcut%20the%20selection%20process%20here.%0A%20%20%20%20%20%20%20%20//%0A%20%20%20%20%20%20%20%20//%20%28a%29%20If%20the%20query%20is%20over%20a%20collection%20that%20doesn%27t%20exist%2C%20we%20get%20a%20special%20runner%0A%20%20%20%20%20%20%20%20//%20that%27s%20is%20so%20%28a%20runner%29%20which%20doesn%27t%20return%20results%2C%20the%20EOFRunner.%0A%20%20%20%20%20%20%20%20//%0A%20%20%20%20%20%20%20%20//%20%28b%29%20if%20the%20query%20is%20a%20replication%27s%20initial%20sync%20one%2C%20we%20get%20a%20SingleSolutinRunner%0A%20%20%20%20%20%20%20%20//%20that%20uses%20a%20specifically%20designed%20stage%20that%20skips%20extents%20faster%20%28see%20details%20in%0A%20%20%20%20%20%20%20%20//%20exec/oplogstart.h%29%0A%20%20%20%20%20%20%20%20//%0A%20%20%20%20%20%20%20%20//%20Otherwise%20we%20go%20through%20the%20selection%20of%20which%20runner%20is%20most%20suited%20to%20the%0A%20%20%20%20%20%20%20%20//%20query%20+%20run-time%20context%20at%20hand.%0A%20%20%20%20%20%20%20%20Status%20status%20%3D%20Status%3A%3AOK%28%29%3B%0A%20%20%20%20%20%20%20%20if%20%28collection%20%3D%3D%20NULL%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20rawRunner%20%3D%20new%20EOFRunner%28cq%2C%20cq-%3Ens%28%29%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20else%20if%20%28pq.hasOption%28QueryOption_OplogReplay%29%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20status%20%3D%20getOplogStartHack%28collection%2C%20cq%2C%20%26rawRunner%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Takes%20ownership%20of%20cq.%0A%20%20%20%20%20%20%20%20%20%20%20%20size_t%20options%20%3D%20QueryPlannerParams%3A%3ADEFAULT%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20%28shardingState.needCollectionMetadata%28pq.ns%28%29%29%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20options%20%7C%3D%20QueryPlannerParams%3A%3AINCLUDE_SHARD_FILTER%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20status%20%3D%20getRunner%28cq%2C%20%26rawRunner%2C%20options%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20if%20%28%21status.isOK%28%29%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20NOTE%3A%20Do%20not%20access%20cq%20as%20getRunner%20has%20deleted%20it.%0A%20%20%20%20%20%20%20%20%20%20%20%20uasserted%2817007%2C%20%22Unable%20to%20execute%20query%3A%20%22%20+%20status.reason%28%29%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%u4E0A%u9762%u90E8%u5206%u4EE3%u7801%u5305%u542B%u6570%u636E%u52A0%u8F7D%uFF0C%u67E5%u8BE2%u6570%u636E%u89E3%u6790%uFF0C%u67E5%u8BE2%u7B97%u6CD5%u5339%u914D%u7B49%u8FC7%u7A0B%uFF0C%u4E0B%u9762%u7A0D%u5FAE%u8BE6%u7EC6%u7684%u5206%u6790%u4E00%u4E0B%u8FC7%u7A0B%u3002%0A%0A%09%20%20%20%20//%20This%20is%20a%20read%20lock.%20%20We%20require%20this%20because%20if%20we%27re%20parsing%20a%20%24where%2C%20the%0A%20%20%20%20%20%20%20%20//%20where-specific%20parsing%20code%20assumes%20we%20have%20a%20lock%20and%20creates%20execution%20machinery%20that%0A%20%20%20%20%20%20%20%20//%20requires%20it.%0A%20%20%20%20%20%20%20%20Client%3A%3AReadContext%20ctx%28q.ns%29%3B%0A%u4ECE%u6CE8%u91CA%u4E2D%u53EF%u4EE5%u770B%u7740%uFF0C%u8FD9%u662F%u4E00%u4E2A%u201C%u8BFB%u9501%u201D%uFF0C%u4F46%u662F%u4ED6%u5B9E%u9645%u7684%u529F%u80FD%u5E76%u4E0D%u6B62%u8FD9%u4E9B%u3002%0A%0A%20%20%20%20%20/**%20%22read%20lock%2C%20and%20set%20my%20context%2C%20all%20in%20one%20operation%22%20%0A%20%20%20%20%20%20%20%20%20*%20%20This%20handles%20%28if%20not%20recursively%20locked%29%20opening%20an%20unopened%20database.%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20class%20ReadContext%20%3A%20boost%3A%3Anoncopyable%20%7B%20%0A%20%20%20%20%20%20%20%20public%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20ReadContext%28const%20std%3A%3Astring%26%20ns%2C%20const%20std%3A%3Astring%26%20path%3DstorageGlobalParams.dbpath%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20Context%26%20ctx%28%29%20%7B%20return%20*c.get%28%29%3B%20%7D%0A%20%20%20%20%20%20%20%20private%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20scoped_ptr%3CLock%3A%3ADBRead%3E%20lk%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20scoped_ptr%3CContext%3E%20c%3B%0A%20%20%20%20%20%20%20%20%7D%3B%0AReadContext%20%u6709%u70B9%u50CF%u4E00%u4E2A%u4EE3%u7406%u6216%u8005%u662F%u9002%u914D%u5668%uFF0C%u5B9E%u9645%u5305%u542B%u4E86%u4E00%u4E2AContext%u5BF9%u8C61%uFF0C%u7136%u540E%u5229%u7528Lock%3A%3ADBRead%u6DFB%u52A0%u201C%u8BFB%u9501%u201D%u64CD%u4F5C%u3002%0A%0A%20%20%20%20/**%20%22read%20lock%2C%20and%20set%20my%20context%2C%20all%20in%20one%20operation%22%20%0A%20%20%20%20%20*%20%20This%20handles%20%28if%20not%20recursively%20locked%29%20opening%20an%20unopened%20database.%0A%20%20%20%20%20*/%0A%20%20%20%20Client%3A%3AReadContext%3A%3AReadContext%28const%20string%26%20ns%2C%20const%20std%3A%3Astring%26%20path%29%20%7B%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20lk.reset%28%20new%20Lock%3A%3ADBRead%28ns%29%20%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20Database%20*db%20%3D%20dbHolder%28%29.get%28ns%2C%20path%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%28%20db%20%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20c.reset%28%20new%20Context%28path%2C%20ns%2C%20db%29%20%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20//%20we%20usually%20don%27t%20get%20here%2C%20so%20doesn%27t%20matter%20how%20fast%20this%20part%20is%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%28%20Lock%3A%3AisW%28%29%20%29%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20write%20locked%20already%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20DEV%20RARELY%20log%28%29%20%3C%3C%20%22write%20locked%20on%20ReadContext%20construction%20%22%20%3C%3C%20ns%20%3C%3C%20endl%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20c.reset%28new%20Context%28ns%2C%20path%29%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20else%20if%28%20%21Lock%3A%3Anested%28%29%20%29%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lk.reset%280%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Lock%3A%3AGlobalWrite%20w%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20Context%20c%28ns%2C%20path%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20db%20could%20be%20closed%20at%20this%20interim%20point%20--%20that%20is%20ok%2C%20we%20will%20throw%2C%20and%20don%27t%20mind%20throwing.%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lk.reset%28%20new%20Lock%3A%3ADBRead%28ns%29%20%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20c.reset%28new%20Context%28ns%2C%20path%29%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20else%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20uasserted%2815928%2C%20str%3A%3Astream%28%29%20%3C%3C%20%22can%27t%20open%20a%20database%20from%20a%20nested%20read%20lock%20%22%20%3C%3C%20ns%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%u53EF%u4EE5%u770B%u5230%u5728ReadContext%u6784%u9020%u51FD%u6570%u4E2D%u5148%u6839%u636Ens%u6765%u9501%u4F4F%u6570%u636E%u5E93%28%u4E4B%u524D%u5DF2%u7ECF%u8BF4%u8FC7%uFF0Cns%u5305%u542B%u6570%u636E%u5E93%u540D%u79F0%u548C%u96C6%u5408%u540D%u79F0%29%uFF0C%u7136%u540E%u5728%u6839%u636Ens%u548C%u6570%u636E%u5E93%u8DEF%u5F84%u6765%u83B7%u53D6Database%u5BF9%u8C61%uFF0C%u4E00%u4E2ADatabase%u5BF9%u8C61%u4EE3%u8868%u4E00%u4E2A%u6570%u636E%u5E93%28%u8FD9%u90E8%u5206%u5305%u542B%u6570%u636E%u5E93%u6570%u636E%u52A0%u8F7D%uFF0C%u6682%u65F6%u4E0D%u5206%u6790%29%uFF0C%u5982%u679C%u83B7%u53D6%u5230db%u5BF9%u8C61%uFF0C%u5219%u8BBE%u7F6E%u4E0A%u4E0B%u6587%u4FE1%u606F%u3002%0A%0A%u5982%u679C%u6CA1%u6709%u83B7%u53D6%u5230db%u5BF9%u8C61%uFF0C%u5219%u4F1A%u8FDB%u5165%u5230%u4E0B%u9762%3A%0A%0A%20%20%20%20lk.reset%28%20new%20Lock%3A%3ADBRead%28ns%29%20%29%3B%0A%20%20%20%20c.reset%28new%20Context%28ns%2C%20path%29%29%3B%0AContext%u63D0%u4F9B%u4E86%u591A%u4E2A%u6784%u9020%u51FD%u6570%uFF0C%u8FD9%u4E2A%u6784%u9020%u51FD%u6570%u4E2D%u4F1A%u53BB%u521B%u5EFAdb%u5BF9%u8C61%uFF0C%u5E76%u52A0%u8F7D%u6570%u636E%u3002%u9501%u4F4F%u6570%u636E%u5E93%u4E4B%u540E%u5C06%u8FDB%u5165%u6838%u5FC3%u67E5%u8BE2%u90E8%u5206%u3002%0A%0A%20%20%20%20%20//%20Parse%20the%20qm%20into%20a%20CanonicalQuery.%0A%20%20%20%20%20%20%20%20CanonicalQuery*%20cq%3B%0A%20%20%20%20%20%20%20%20Status%20canonStatus%20%3D%20CanonicalQuery%3A%3Acanonicalize%28q%2C%20%26cq%29%3B%0A%20%u9996%u5148%u4F1A%u89E3%u6790%u67E5%u8BE2%u6D88%u606F%u4E3A%u6807%u51C6%u5316%u7684%u67E5%u8BE2%u5BF9%u8C61%uFF0C%u4E3B%u8981%u662F%u5C06BSON%u7ED3%u6784%u6570%u636E%u8F6C%u6362%u4E3AMatchExpression%u65B9%u4FBF%u4F7F%u7528%u3002%0A%20%u4E4B%u540E%u4F1A%u83B7%u53D6%u4E00%u4E2ARunner%u5BF9%u8C61%u6765%u6267%u884C%u67E5%u8BE2%3A%0A%20%0A%0A%09%20%20%20%20Runner*%20rawRunner%20%3D%20NULL%3B%0A%0A%20%20%20%20%20%20%20%20//%20We%20use%20this%20a%20lot%20below.%0A%20%20%20%20%20%20%20%20const%20LiteParsedQuery%26%20pq%20%3D%20cq-%3EgetParsed%28%29%3B%0A%0A%20%20%20%20%20%20%20%20//%20We%27ll%20now%20try%20to%20get%20the%20query%20runner%20that%20will%20execute%20this%20query%20for%20us.%20There%0A%20%20%20%20%20%20%20%20//%20are%20a%20few%20cases%20in%20which%20we%20know%20upfront%20which%20runner%20we%20should%20get%20and%2C%20therefore%2C%0A%20%20%20%20%20%20%20%20//%20we%20shortcut%20the%20selection%20process%20here.%0A%20%20%20%20%20%20%20%20//%0A%20%20%20%20%20%20%20%20//%20%28a%29%20If%20the%20query%20is%20over%20a%20collection%20that%20doesn%27t%20exist%2C%20we%20get%20a%20special%20runner%0A%20%20%20%20%20%20%20%20//%20that%27s%20is%20so%20%28a%20runner%29%20which%20doesn%27t%20return%20results%2C%20the%20EOFRunner.%0A%20%20%20%20%20%20%20%20//%0A%20%20%20%20%20%20%20%20//%20%28b%29%20if%20the%20query%20is%20a%20replication%27s%20initial%20sync%20one%2C%20we%20get%20a%20SingleSolutinRunner%0A%20%20%20%20%20%20%20%20//%20that%20uses%20a%20specifically%20designed%20stage%20that%20skips%20extents%20faster%20%28see%20details%20in%0A%20%20%20%20%20%20%20%20//%20exec/oplogstart.h%29%0A%20%20%20%20%20%20%20%20//%0A%20%20%20%20%20%20%20%20//%20Otherwise%20we%20go%20through%20the%20selection%20of%20which%20runner%20is%20most%20suited%20to%20the%0A%20%20%20%20%20%20%20%20//%20query%20+%20run-time%20context%20at%20hand.%0A%20%20%20%20%20%20%20%20Status%20status%20%3D%20Status%3A%3AOK%28%29%3B%0A%20%20%20%20%20%20%20%20if%20%28collection%20%3D%3D%20NULL%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20rawRunner%20%3D%20new%20EOFRunner%28cq%2C%20cq-%3Ens%28%29%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20else%20if%20%28pq.hasOption%28QueryOption_OplogReplay%29%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20status%20%3D%20getOplogStartHack%28collection%2C%20cq%2C%20%26rawRunner%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20else%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Takes%20ownership%20of%20cq.%0A%20%20%20%20%20%20%20%20%20%20%20%20size_t%20options%20%3D%20QueryPlannerParams%3A%3ADEFAULT%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20%28shardingState.needCollectionMetadata%28pq.ns%28%29%29%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20options%20%7C%3D%20QueryPlannerParams%3A%3AINCLUDE_SHARD_FILTER%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20status%20%3D%20getRunner%28cq%2C%20%26rawRunner%2C%20options%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%u4E0A%u9762%u4EE3%u7801%u8C03%u7528getRunner%u51FD%u6570%u6765%u8FD4%u56DE%u4E00%u4E2ARunner%u5BF9%u8C61%uFF0C%u8BE5Runner%u5BF9%u8C61%u4F1A%u5BF9%u96C6%u5408%u8FDB%u884C%u904D%u5386%uFF0C%u7136%u540E%u627E%u5230%u7B26%u5408%u67E5%u8BE2%u6761%u4EF6%u7684%u7ED3%u679C%u5E76%u8FD4%u56DE%u3002%0A%0A%21%5BAlt%20text%5D%28./%u672A%u547D%u540D.jpg%29%0A%0A%u4E00%u4E2ARunner%u5C31%u4EE3%u8868%u4E00%u79CD%u6570%u636E%u67E5%u8BE2%u65B9%u5F0F%uFF0Cmongo%u4F1A%u6839%u636E%u4E4B%u524D%u7684%u67E5%u8BE2BSON%u89E3%u6790%u7ED3%u679C%u6765%u5224%u65AD%u5E94%u8BE5%u4F7F%u7528%u54EA%u4E00%u79CDRunner%u6765%u6267%u884C%u67E5%u8BE2%uFF0C%u6709%u70B9%u7C7B%u4F3C%u7B56%u7565%u6A21%u5F0F%u3002%0AIDHackRunner%20%uFF1A%20%u5F53%u524D%u96C6%u5408%u662F%u4EE5%u201C_id%u201D%u4F5C%u4E3A%u7D22%u5F15%u6216%u8005%u67E5%u8BE2%u6761%u4EF6%u4E2D%u5305%u542B%22_id%22%u65F6%u5C31%u4F7F%u7528%u6B64%u6765%u67E5%u8BE2%u3002%0ACachedPlanRunner%uFF1A%u5982%u679C%u4E4B%u524D%u5DF2%u7ECF%u6709%u7F13%u5B58plan%uFF0C%u5219%u4F7F%u7528%u6B64%u6765%u67E5%u8BE2%u3002%0AMultiPlanRunner%uFF1A%u4F7F%u7528QueryPlanner%u6765plan%20%u67E5%u8BE2%u6761%u4EF6%uFF0C%u5982%u679C%u7ED3%u679C%u4E3A%u591A%u4E2AQuerySolution%uFF0C%u5219%u4F7F%u7528%u6B64%u6765%u6267%u884C%u67E5%u8BE2%u3002%0ASingleSolutionRunner%uFF1A%u548Cmulti%u76F8%u5BF9%u5E94%uFF0C%u5BF9%u5E94%u4E00%u4E9B%u7B80%u5355%u7684%u67E5%u8BE2%u5219%u4F7F%u7528%u6B64%u6765%u6267%u884C%u3002%0ASubPlanRunner%uFF1A%u6CA1%u641E%u660E%u767D...%0A%0A%u4E0A%u9762%u8FD9%u4E9BRunner%u90FD%u6BD4%u8F83%u590D%u6742%uFF0C%u8BE6%u7EC6%u5206%u6790%u7684%u8BDD%u6BCF%u4E00%u4E2A%u90FD%u80FD%u9700%u8981%u8017%u8D39%u5F88%u591A%u65F6%u95F4%uFF0C%u5176%u4E2D%u5305%u542B%u4E86%u5BF9%u96C6%u5408%u7684%u626B%u63CF%u7B97%u6CD5%uFF0C%u5BF9%u67E5%u8BE2%u7684%u5206%u6BB5%u5904%u7406%u7B49%u7B49%uFF0C%u6574%u4E2Amongod%u7684%u6838%u5FC3%u67E5%u8BE2%u7B97%u6CD5%u90FD%u5C01%u88C5%u5728%u8FD9%u91CC%u9762%uFF0C%u6682%u65F6%u5C31%u4E0D%u6DF1%u5165%u7814%u7A76%u4E86%u3002%0A%0A%20%20%20%20%20%20%20%20//%20Run%20the%20query.%0A%20%20%20%20%20%20%20%20//%20bb%20is%20used%20to%20hold%20query%20results%0A%20%20%20%20%20%20%20%20//%20this%20buffer%20should%20contain%20either%20requested%20documents%20per%20query%20or%0A%20%20%20%20%20%20%20%20//%20explain%20information%2C%20but%20not%20both%0A%20%20%20%20%20%20%20%20BufBuilder%20bb%2832768%29%3B%0A%20%20%20%20%20%20%20%20bb.skip%28sizeof%28QueryResult%29%29%3B%0A%0A%09%20%20%20%20%20%20...%0A%0A%20%20%20%20%20%20%20%20while%20%28Runner%3A%3ARUNNER_ADVANCED%20%3D%3D%20%28state%20%3D%20runner-%3EgetNext%28%26obj%2C%20NULL%29%29%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Add%20result%20to%20output%20buffer.%20This%20is%20unnecessary%20if%20explain%20info%20is%20requested%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20%28%21isExplain%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20bb.appendBuf%28%28void*%29obj.objdata%28%29%2C%20obj.objsize%28%29%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20Count%20the%20result.%0A%20%20%20%20%20%20%20%20%20%20%20%20++numResults%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20...%0A%20%20%20%20%20%20%20%20%7D%0A%u83B7%u53D6Runner%u5BF9%u8C61%u540E%u5F53%u7136%u662F%u4F7F%u7528%u8BE5%u5BF9%u8C61%u6765%u83B7%u53D6%u67E5%u8BE2%u7ED3%u679C%uFF0CRunner%u63D0%u4F9B%u4E00%u4E2AgetNext%u51FD%u6570%u6765%u83B7%u53D6%u4E0B%u4E00%u4E2A%u7ED3%u679C%uFF0C%u4E4B%u540E%u7684%u5C31%u662F%u5C06%u67E5%u8BE2%u7ED3%u679C%u653E%u5230result%u4E2D%uFF0C%u7136%u540E%u8FD4%u56DE%u7ED9%u5BA2%u6237%u7AEF%u3002%0A%0A%u81F3%u6B64%uFF0C%u6574%u4E2A%u6570%u636E%u67E5%u8BE2%u7684%u8F6E%u5ED3%u5DF2%u7ECF%u51FA%u6765%u4E86%uFF0C%u5176%u4E2D%u6570%u636E%u52A0%u8F7D%u548C%u67E5%u8BE2%u7B97%u6CD5%u90E8%u5206%u6211%u90FD%u5F88%u53EA%u662F%u63D0%u4E86%u4E00%u4E0B%u7136%u540E%u7565%u8FC7%uFF0C%u4E3B%u8981%u662F%u6C34%u5E73%u6709%u9650%uFF0C%u5F88%u591A%u4E1C%u897F%u6211%u81EA%u5DF1%u8FD8%u6CA1%u5F04%u660E%u767D%uFF0C%u5199%u51FA%u6765%u4E5F%u90FD%u662F%u9519%u7684%uFF0CMongoDB%u7684%u6BCF%u4E00%u4E2A%u7248%u672C%u4EE3%u7801%u6539%u52A8%u90FD%u5F88%u5927%uFF0C%u53C2%u8003%u4E86%u5F88%u591A%u524D%u8F88%u5BF9%u5176%u4ED6%u7248%u672C%u7684%u5206%u6790%uFF0C%u771F%u662F%u5F88%u4F69%u670D%u4ED6%u4EEC%uFF0C%u5F88%u591A%u4E1C%u897F%u90FD%u5206%u6790%u5F88%u900F%u5F7B%uFF0C%u4F46%u662F%u5BF9%u7167%u6765%u770B%u8FD9%u4E2A%u7248%u672C%u7684%u6E90%u7801%u8FD8%u662F%u6709%u5F88%u591A%u8FF7%u60D1%u7684%u5730%u65B9%uFF0C%u6240%u4EE5%u6570%u636E%u52A0%u8F7D%u548C%u67E5%u8BE2%u7B97%u6CD5%u4E24%u4E2A%u90E8%u5206%u4E4B%u7814%u7A76%u660E%u767D%u4E4B%u540E%u518D%u5355%u72EC%u5F00%u7BC7%u5427%u3002%0A
  • 相关阅读:
    SSM之Mybatis整合及使用
    软件设计师08-法律法规与标准化知识
    Spring MVC体系结构
    Spring MVC异常友好展示
    Spring MVC Web.xml配置
    编译型语言解释型语言
    软件设计师07-程序设计语言与语言处理程序基础
    flex布局注意点:
    常见的PC端和移动端表单组件
    js文件的装载和执行
  • 原文地址:https://www.cnblogs.com/chunxi/p/4390251.html
Copyright © 2011-2022 走看看