mongodb源码分析(二十一)mongos 查询与添加

        本来简单讲讲mongos对于查询 添加 的流程,修改和删除的处理流程简单其也与添加差不多不再分析,对于添加 修改和删除,mongos都只是将其发往正确的mongod服务器让其处理,对于查询稍微麻烦点,因为查询多个mongod服务器的结果回来时汇总需要mongos自身完成其排序.下面来看具体代码吧,在mongos的初始化部分我们已经知道向mongos发送的请求,其处理函数是Request::process函数,下面来看看这个函数.

    void Request::process( int attempt ) {
        init();//初始化,加载要操作的数据库的DBConfig,对于sharded collection还要加载其chunkmanager
        int op = _m.operation();
        if ( op == dbKillCursors ) {
            cursorCache.gotKillCursors( _m );
            return;
        }
        int msgId = (int)(_m.header()->id);
        Timer t;
        Strategy * s = SHARDED;
        _counter = &opsNonSharded;
        _d.markSet();
        bool iscmd = false;
        if ( op == dbQuery ) {
            iscmd = isCommand();
            s->queryOp( *this );
        }
        else if ( op == dbGetMore ) {
            checkAuth( Auth::READ ); // this is important so someone can't steal a cursor
            s->getMore( *this );
        }
        else {
            checkAuth( Auth::WRITE );
            s->writeOp( op, *this );
        }
        globalOpCounters.gotOp( op , iscmd );
        _counter->gotOp( op , iscmd );
    }
首先来看查询dbQuery部分.这里查询调用的是ShardStrategy::queryOp

        virtual void queryOp( Request& r ) {
            // TODO: These probably should just be handled here.
            if ( r.isCommand() ) {//对于mongos的命令请求,不再分析
                SINGLE->queryOp( r );
                return;
            }
            QueryMessage q( r.d() );
            r.checkAuth( Auth::READ );
            QuerySpec qSpec( (string)q.ns, q.query, q.fields, q.ntoskip, q.ntoreturn, q.queryOptions );
            if ( _isSystemIndexes( q.ns ) && q.query["ns"].type() == String && r.getConfig()->isSharded( q.query["ns"].String() ) ) {
                // if you are querying on system.indexes, we need to make sure we go to a shard that actually has chunks
                // this is not a perfect solution (what if you just look at all indexes)
                // but better than doing nothing
                ShardPtr myShard;//查询的是xx.system.indexes这个collection,这个collection保存了所有索引信息.
                ChunkManagerPtr cm;//每一个ns得到的要么是chunkManager(对应ns分片了),要么是shard(对应的ns未分片)
                r.getConfig()->getChunkManagerOrPrimary( q.query["ns"].String(), cm, myShard );
                if ( cm ) {
                    set shards;
                    cm->getAllShards( shards );
                    verify( shards.size() > 0 );
                    myShard.reset( new Shard( *shards.begin() ) );
                }
                doQuery( r, *myShard );//将查询发往myShard
                return;
            }//并行cursor的初始化
            ParallelSortClusteredCursor * cursor = new ParallelSortClusteredCursor( qSpec, CommandInfo() );
            // TODO:  Move out to Request itself, not strategy based
             {
                long long start_millis = 0;
                if ( qSpec.isExplain() ) start_millis = curTimeMillis64();
                cursor->init();//这里内部多cursor的建立,每一个shard一个cursor
                shardedCursorTypes.hit( cursor->type() );
                if ( qSpec.isExplain() ) {
                    // fetch elapsed time for the query
                    long long elapsed_millis = curTimeMillis64() - start_millis;
                    BSONObjBuilder explain_builder;
                    cursor->explain( explain_builder );
                    explain_builder.appendNumber( "millis", elapsed_millis );
                    BSONObj b = explain_builder.obj();
                    replyToQuery( 0 , r.p() , r.m() , b );
                    delete( cursor );
                    return;
                }
            }
            if( cursor->isSharded() ){
                ShardedClientCursorPtr cc (new ShardedClientCursor( q , cursor ));
                BufBuilder buffer( ShardedClientCursor::INIT_REPLY_BUFFER_SIZE );
                int docCount = 0;
                const int startFrom = cc->getTotalSent();//从cursor中读取数据填充buffer
                bool hasMore = cc->sendNextBatch( r, q.ntoreturn, buffer, docCount );
                if ( hasMore ) {//有更多数据则先将其保存起来,下次再用.一直不操作600s后将被清除
                    cursorCache.store( cc );
                }
                replyToQuery( 0, r.p(), r.m(), buffer.buf(), buffer.len(), docCount,
                        startFrom, hasMore ? cc->getId() : 0 );
            }
            else{//该collection未分片,则其在在一台服务器上.
                // Remote cursors are stored remotely, we shouldn't need this around.
                // TODO: we should probably just make cursor an auto_ptr
                scoped_ptr cursorDeleter( cursor );
                // TODO:  Better merge this logic.  We potentially can now use the same cursor logic for everything.
                ShardPtr primary = cursor->getPrimary();//得到其所在的服务器
                DBClientCursorPtr shar

你可能感兴趣的:(mongodb源码分析)