MongoDB源码分析——mongod程序源码入口分析

 

Edit
说明:第一次写笔记,之前都是看别人写的,觉得很简单,开始写了之后才发现真的很难,不知道该怎么分析,这篇文章也参考了很多前辈对MongoDB源码的分析,也有一些自己的理解,后续将会继续分析其他部分,如果有什么错误请大家指出,谢谢。
 
源码版本为MongoDB 2.6分支
 

mongod程序源码入口分析

为了理解MongoDB的运行机制,首先要对主要运行流程有个大概理解,我们首先从main函数开始。mongod项目的main函数位于db.cpp文件中,出于跨平台的需求,对Windows和Linux平台提供了两个main函数:

#if defined(_WIN32)
int wmain(int argc, wchar_t* argvW[], wchar_t* envpW[]) {
    WindowsCommandLine wcl(argc, argvW, envpW);
    int exitCode = mongoDbMain(argc, wcl.argv(), wcl.envp());
    ::_exit(exitCode);
}
#else
int main(int argc, char* argv[], char** envp) {
    int exitCode = mongoDbMain(argc, argv, envp);
    ::_exit(exitCode);
}
#endif

上面代码中wmain代码对命令行做了编码转换,然后统一调用了mongoDbMain函数,进入流程处理,下面具体分析mongoDbMain函数:

static int mongoDbMain(int argc, char* argv[], char **envp) {
    //静态观察,大概作用是main函数结束时候局部static staticObserver会首先释放
    //其他地方通过观察StaticObserver 的成员变量_destroyingStatics来判断mongoDbMain结束。
    static StaticObserver staticObserver;

    #if defined(_WIN32)
    mongo::reportEventToSystem = &mongo::reportEventToSystemImpl;
    #endif

    getcurns = ourgetns;

    setupSignalHandlers();

    dbExecCommand = argv[0];

    srand(curTimeMicros());
    {
        //判断是否为系统是否为小端模式,MongoDB暂时不支持大端模式服务器。
        unsigned x = 0x12345678;
        unsigned char& b = (unsigned char&) x;
        if ( b != 0x78 ) {
            out() << "big endian cpus not yet supported" << endl;
            return 33;
        }
    }

    if( argc == 1 )
        cout << dbExecCommand << " --help for help and startup options" << endl;
    //主要解析命令行,其中会读取配置文件,并赋值给变量,这一块设计比较巧妙,日后可以单独开篇研究。
    Status status = mongo::runGlobalInitializers(argc, argv, envp);
    if (!status.isOK()) {
        severe() << "Failed global initialization: " << status;
        ::_exit(EXIT_FAILURE);
    }

    startupConfigActions(std::vector<std::string>(argv, argv + argc));
    cmdline_utils::censorArgvArray(argc, argv);
    //初始化服务器认证配置
    if (!initializeServerGlobalState())
        ::_exit(EXIT_FAILURE);

    //启动一个线程处理系统信号
    startSignalProcessingThread();
    //定时同步文件
    dataFileSync.go();

    #if defined(_WIN32)
    if (ntservice::shouldStartService()) {
        ntservice::startService();
        // exits directly and so never reaches here either.
    }
    #endif
    //进行一些测试
    StartupTest::runTests();
    //初始化各模块,并开始监听客户端请求,服务端开始运行
    initAndListen(serverGlobalParams.port);
    dbexit(EXIT_CLEAN);
    return 0;
}

dataFileSync是DataFileSync对象

class DataFileSync : public BackgroundJob , public ServerStatusSection {
public:
    ...
    void run() {
    ...
}

void BackgroundJob::go() {
    scoped_lock l( _status->mutex );
    massert( 17234, mongoutils::str::stream()
             << "backgroundJob already running: " << name(),
             _status->state != Running );

    // If the job is already 'done', for instance because it was cancelled or already
    // finished, ignore additional requests to run the job.
    if (_status->state == NotStarted) {
        //BackgroundJob::jobBody函数中执行子类run函数,所以文件同步将在后台线程中执行。
        boost::thread t( boost::bind( &BackgroundJob::jobBody , this ) );
        _status->state = Running;
    }
}

Client::initThread(…)函数在之后很多地方还会用到,源码中的注释是“each thread which does db operations has a Client object in TLS. call this when your thread starts.”

Client& Client::initThread(const char *desc, AbstractMessagingPort *mp) {
    verify( currentClient.get() == 0 );

    string fullDesc = desc;
    if ( str::equals( "conn" , desc ) && mp != NULL )
        fullDesc = str::stream() << desc << mp->connectionId();
    //设置线程名称,该名称保存在线程全局变量_threadName中
    setThreadName( fullDesc.c_str() );

    // Create the client obj, attach to thread
    Client *c = new Client( fullDesc, mp );
    currentClient.reset(c);
    mongo::lastError.initThread();
    c->setAuthorizationSession(new AuthorizationSession(new AuthzSessionExternalStateMongod(
            getGlobalAuthorizationManager())));
    return *c;
}

上面的代码中setThreadName(), currentClient.reset(c), mongo::lastError.initThread()这三个地方刚开始让我比较疑惑,因为_threadName,currentClient,lastError都是全局变量,但是每个线程都去设置一次是不是会改变其他之前设置的值呢?后来自习分析源码后发现他们都使用了线程本地存储技术,mongodb中是直接用 boost::thread_specific_ptr 来实现,在每个线程中,都各自new一个对象交给全局的threah_specific_ptr进行管理,当线程退出后,他会自动释放这个对象。

下面对initAndListen函数单独进行分析:

void initAndListen(int listenPort) {    
    try {
        _initAndListen(listenPort);
    } 
    ...
}

以下是对_initAndListen主要代码的分析:

void _initAndListen(int listenPort ) {
    //设置线程名称,为当前线程创建数据库操作的Client对象
    Client::initThread("initandlisten");
    //判断当前是否为32位系统
    bool is32bit = sizeof(int*) == 4;
    ....
    // Read storage engine metadata file (introduced in 2.8) if present.
    // Do not start server if storage engine in metadata is not 'mmapv1'.
    StorageEngineMetadata::validate(storageGlobalParams.dbpath, "mmapv1");

    // TODO check non-journal subdirs if using directory-per-db
    checkReadAhead(storageGlobalParams.dbpath);
    //文件锁
    //保证当前dbpath目录下只有一个mongodb实例,如果当前dbpath目录已经有mongodb运行
    //则获取文件锁失败。
    acquirePathLock(mongodGlobalParams.repair);
    //删除所有临时文件
    boost::filesystem::remove_all(storageGlobalParams.dbpath + "/_tmp/");
    //文件
    FileAllocator::get()->start();

    ...

    MONGO_ASSERT_ON_EXCEPTION_WITH_MSG( clearTmpFiles(), "clear tmp files" );
    //开启journal线程,创建持久化目录和文件
    dur::startup();
    ...
    //创建v8脚本引擎
    if (mongodGlobalParams.scriptingEnabled) {
        ScriptEngine::setup();
        globalScriptEngine->setCheckInterruptCallback( jsInterruptCallback );
        globalScriptEngine->setGetCurrentOpIdCallback( jsGetCurrentOpIdCallback );
    }

    ...
    //启动线程快照,定时拍照,默认4秒
    if (serverGlobalParams.isHttpInterfaceEnabled)
        snapshotThread.go();

    d.clientCursorMonitor.go();
    //报告内存使用情况和过时过时删除客户端游标的线程
    PeriodicTask::startRunningPeriodicTasks();
    //启动定期执行任务的线程,创建PeriodicTaskRunner,检测shutdown信号,没有就等待,默认60秒。
    if (missingRepl) {
        // a warning was logged earlier
    }
    else {
        startTTLBackgroundJob();
    }

#ifndef _WIN32
    mongo::signalForkSuccess();
#endif

    if(getGlobalAuthorizationManager()->isAuthEnabled()) {
        // open admin db in case we need to use it later. TODO this is not the right way to
        // resolve this.
        Client::WriteContext c("admin", storageGlobalParams.dbpath);
    }

    authindex::configureSystemIndexes("admin");

    getDeleter()->startWorkers();

    // Starts a background thread that rebuilds all incomplete indices. 
    indexRebuilder.go(); 
    //开始监听
    listen(listenPort);

    // listen() will return when exit code closes its socket.
    exitCleanly(EXIT_NET_ERROR);
}

从上面的_initAndListen函数中可以看到,并没有开始监听客户端请求,只是做了一些数据库准备工作,最后才调用listen(listenPort)函数对端口进行监听,下面继续分析listen函数:

void listen(int port) {
    //testTheDb();
    MessageServer::Options options;
    options.port = port;
    options.ipList = serverGlobalParams.bind_ip;

    MessageServer * server = createServer( options , new MyMessageHandler() );
    server->setAsTimeTracker();
    // we must setupSockets prior to logStartup() to avoid getting too high
    // a file descriptor for our calls to select()
    //初始化Socket,然后调用listen函数开始监听
    server->setupSockets();

    logStartup();
    //后台启动数据分片线程
    startReplication();
    //如果设置了--httpinterface参数,则会启动web线程线程监听http请求
    if (serverGlobalParams.isHttpInterfaceEnabled)
        boost::thread web( boost::bind(&webServerThread, new RestAdminAccess() /* takes ownership */));

    server->run();
}

MessageServer 是消息服务的基类,createServer返回的是他的子类PortMessageServer的对象,PortMessageServer中重写了虚函数run,客户端连接处理又被延迟到了PortMessageServer::run()函数中。

class MessageServer {
public:
    struct Options {
        int port;                   // port to bind to
        string ipList;             // addresses to bind to

        Options() : port(0), ipList("") {}
    };

    virtual ~MessageServer() {}
    virtual void run() = 0;
    virtual void setAsTimeTracker() = 0;
    virtual void setupSockets() = 0;
};

class Listener : boost::noncopyable {
public:
    void initAndListen(); // never returns unless error (start a thread)

    /* spawn a thread, etc., then return */
    virtual void accepted(boost::shared_ptr<Socket> psocket, long long connectionId );
    virtual void acceptedMP(MessagingPort *mp);
    ...
}

 class PortMessageServer : public MessageServer , public Listener {
    ...
}

下面继续分析PortMessageServer::run()函数:

void run() {
        initAndListen();
    }

由于initAndListen函数在mongodb中Windows和Linux两部分分开来实现,我们只分析Linux部分,两部分原来相同,都是使用select来监听客户端请求。下面代码我删除部分,只保留处理逻辑。

#if !defined(_WIN32)
void Listener::initAndListen() {
    if (!_setupSocketsSuccessful) {
        return;
    }

    SOCKET maxfd = 0; // needed for select()
    for (unsigned i = 0; i < _socks.size(); i++) {
        if (_socks[i] > maxfd)
            maxfd = _socks[i];
    }

    ...
    struct timeval maxSelectTime;
    while ( ! inShutdown() ) {
        fd_set fds[1];
        FD_ZERO(fds);

        for (vector<SOCKET>::iterator it=_socks.begin(), end=_socks.end(); it != end; ++it) {
            FD_SET(*it, fds);
        }

        maxSelectTime.tv_sec = 0;
        maxSelectTime.tv_usec = 10000;
        const int ret = select(maxfd+1, fds, NULL, NULL, &maxSelectTime);
        ...

        for (vector<SOCKET>::iterator it=_socks.begin(), end=_socks.end(); it != end; ++it) {
            if (! (FD_ISSET(*it, fds)))
                continue;
            SockAddr from;
            int s = accept(*it, from.raw(), &from.addressSize);
            ...
            long long myConnectionNumber = globalConnectionNumber.addAndFetch(1);

            ...

            boost::shared_ptr<Socket> pnewSock( new Socket(s, from) );
#ifdef MONGO_SSL
            if (_ssl) {
                pnewSock->secureAccepted(_ssl);
            }
#endif
            accepted( pnewSock , myConnectionNumber );
        }
    }
}

#else 

上面是一个标准的服务端socket select模型,每当有客户端socket连接时,accept成功后调用accepted函数处理。

void Listener::accepted(boost::shared_ptr<Socket> psocket, long long connectionId ) {
    MessagingPort* port = new MessagingPort(psocket);
    port->setConnectionId( connectionId );
    acceptedMP( port );
}

此处调用的PortMessageServer对象的acceptedMP成员函数(PortMessageServer是Listener的子类),这里我们看到了一个新的类MessagingPort,MessagingPort封装了Message的发送、接收等操作,若有需求以后再具体分析。

virtual void acceptedMP(MessagingPort * p) {
    ...
    pthread_attr_t attrs;
    pthread_attr_init(&attrs);
    pthread_attr_setdetachstate(&attrs, PTHREAD_CREATE_DETACHED);

    static const size_t STACK_SIZE = 1024*1024; // if we change this we need to update the warning

    struct rlimit limits;
    pthread_t thread;
    HandleIncomingMsgParam* himParam = new HandleIncomingMsgParam(p, _handler);
    int failed = pthread_create(&thread, &attrs, &handleIncomingMsg, himParam);

    pthread_attr_destroy(&attrs);
}

acceptedMP接收到消息后建立一个后台线程,在后台线程中执行handleIncomingMsg函数,处理客户端连接。

  static void* handleIncomingMsg(void* arg) {
        TicketHolderReleaser connTicketReleaser( &Listener::globalTicketHolder );

        scoped_ptr<HandleIncomingMsgParam> himArg(static_cast<HandleIncomingMsgParam*>(arg));
        MessagingPort* inPort = himArg->inPort;
        MessageHandler* handler = himArg->handler;
        ...
        inPort->psock->setLogLevel(logger::LogSeverity::Debug(1));
        scoped_ptr<MessagingPort> p( inPort );

        string otherSide;

        Message m;
        try {
            LastError * le = new LastError();
            lastError.reset( le ); // lastError now has ownership
            handler->connected( p.get() );

            while ( ! inShutdown() ) {
                m.reset();
                p->psock->clearCounters();

                if ( ! p->recv(m) ) {
                    ...
                }
                handler->process( m , p.get() , le );
                networkCounter.hit( p->psock->getBytesIn() , p->psock->getBytesOut() );
            }
        }
        ...
        handler->disconnected( p.get() );
        return NULL;
    }
};

以上代码可以看出,服务端在接收到客户端连接请求后建立连接,然后创建后台线程,在线程中使用while循环不断的接收Message,然后调用handler的process处理。handler->connected里面只是再次调用Client::initThread(“conn”, p),这个问题之前已经分析过。
最后一个问题,handler对象其实就是createServer时候传入的第二个参数new MyMessageHandler();

class MessageHandler {
public:
    virtual ~MessageHandler() {}

    /**
     * called once when a socket is connected
     */
    virtual void connected( AbstractMessagingPort* p ) = 0;

    /**
     * called every time a message comes in
     * handler is responsible for responding to client
     */
    virtual void process( Message& m , AbstractMessagingPort* p , LastError * err ) = 0;

    /**
     * called once when a socket is disconnected
     */
    virtual void disconnected( AbstractMessagingPort* p ) = 0;
};

 class MyMessageHandler : public MessageHandler {
         ...
}

至此mongod的整个消息处理轮廓已经出来了,其他的部分将会在后续的部分中继续分析

 
%23%23%20mongod%u7A0B%u5E8F%u5165%u53E3%u5206%u6790%0A%20%20%0A%20%20%u4E3A%u4E86%u7406%u89E3MongoDB%u7684%u8FD0%u884C%u673A%u5236%uFF0C%u9996%u5148%u8981%u5BF9%u4E3B%u8981%u8FD0%u884C%u6D41%u7A0B%u6709%u4E2A%u5927%u6982%u7406%u89E3%uFF0C%u6211%u4EEC%u9996%u5148%u4ECEmain%u51FD%u6570%u5F00%u59CB%u3002mongod%u9879%u76EE%u7684main%u51FD%u6570%u4F4D%u4E8Edb.cpp%u6587%u4EF6%u4E2D%uFF0C%u51FA%u4E8E%u8DE8%u5E73%u53F0%u7684%u9700%u6C42%uFF0C%u5BF9Windows%u548CLinux%u5E73%u53F0%u63D0%u4F9B%u4E86%u4E24%u4E2Amain%u51FD%u6570%uFF1A%0A%09%0A%0A%20%20%20%20%23if%20defined%28_WIN32%29%0A%09int%20wmain%28int%20argc%2C%20wchar_t*%20argvW%5B%5D%2C%20wchar_t*%20envpW%5B%5D%29%20%7B%0A%09%20%20%20%20WindowsCommandLine%20wcl%28argc%2C%20argvW%2C%20envpW%29%3B%0A%09%20%20%20%20int%20exitCode%20%3D%20mongoDbMain%28argc%2C%20wcl.argv%28%29%2C%20wcl.envp%28%29%29%3B%0A%09%20%20%20%20%3A%3A_exit%28exitCode%29%3B%0A%09%7D%0A%09%23else%0A%09int%20main%28int%20argc%2C%20char*%20argv%5B%5D%2C%20char**%20envp%29%20%7B%0A%09%20%20%20%20int%20exitCode%20%3D%20mongoDbMain%28argc%2C%20argv%2C%20envp%29%3B%0A%09%20%20%20%20%3A%3A_exit%28exitCode%29%3B%0A%09%7D%0A%09%23endif%0A%0A%u4E0A%u9762%u4EE3%u7801%u4E2Dwmain%u4EE3%u7801%u5BF9%u547D%u4EE4%u884C%u505A%u4E86%u7F16%u7801%u8F6C%u6362%uFF0C%u7136%u540E%u7EDF%u4E00%u8C03%u7528%u4E86mongoDbMain%u51FD%u6570%uFF0C%u8FDB%u5165%u6D41%u7A0B%u5904%u7406%uFF0C%u4E0B%u9762%u5177%u4F53%u5206%u6790mongoDbMain%u51FD%u6570%3A%0A%0A%20%20%20%20static%20int%20mongoDbMain%28int%20argc%2C%20char*%20argv%5B%5D%2C%20char%20**envp%29%20%7B%0A%09%20%20%20%20//%u9759%u6001%u89C2%u5BDF%uFF0C%u5927%u6982%u4F5C%u7528%u662Fmain%u51FD%u6570%u7ED3%u675F%u65F6%u5019%u5C40%u90E8static%20staticObserver%u4F1A%u9996%u5148%u91CA%u653E%0A%09%20%20%20%20//%u5176%u4ED6%u5730%u65B9%u901A%u8FC7%u89C2%u5BDFStaticObserver%20%u7684%u6210%u5458%u53D8%u91CF_destroyingStatics%u6765%u5224%u65ADmongoDbMain%u7ED3%u675F%u3002%0A%09%20%20%20%20static%20StaticObserver%20staticObserver%3B%0A%0A%09%09%23if%20defined%28_WIN32%29%0A%09%20%20%20%20mongo%3A%3AreportEventToSystem%20%3D%20%26mongo%3A%3AreportEventToSystemImpl%3B%0A%09%09%23endif%0A%0A%09%20%20%20%20getcurns%20%3D%20ourgetns%3B%0A%0A%09%20%20%20%20setupSignalHandlers%28%29%3B%0A%0A%09%20%20%20%20dbExecCommand%20%3D%20argv%5B0%5D%3B%0A%0A%09%20%20%20%20srand%28curTimeMicros%28%29%29%3B%0A%09%20%20%20%20%7B%0A%09%09%20%20%20%20//%u5224%u65AD%u662F%u5426%u4E3A%u7CFB%u7EDF%u662F%u5426%u4E3A%u5C0F%u7AEF%u6A21%u5F0F%uFF0CMongoDB%u6682%u65F6%u4E0D%u652F%u6301%u5927%u7AEF%u6A21%u5F0F%u670D%u52A1%u5668%u3002%0A%09%20%20%20%20%20%20%20%20unsigned%20x%20%3D%200x12345678%3B%0A%09%20%20%20%20%20%20%20%20unsigned%20char%26%20b%20%3D%20%28unsigned%20char%26%29%20x%3B%0A%09%20%20%20%20%20%20%20%20if%20%28%20b%20%21%3D%200x78%20%29%20%7B%0A%09%20%20%20%20%20%20%20%20%20%20%20%20out%28%29%20%3C%3C%20%22big%20endian%20cpus%20not%20yet%20supported%22%20%3C%3C%20endl%3B%0A%09%20%20%20%20%20%20%20%20%20%20%20%20return%2033%3B%0A%09%20%20%20%20%20%20%20%20%7D%0A%09%20%20%20%20%7D%0A%0A%09%20%20%20%20if%28%20argc%20%3D%3D%201%20%29%0A%09%20%20%20%20%20%20%20%20cout%20%3C%3C%20dbExecCommand%20%3C%3C%20%22%20--help%20for%20help%20and%20startup%20options%22%20%3C%3C%20endl%3B%0A%09%09//%u4E3B%u8981%u89E3%u6790%u547D%u4EE4%u884C%uFF0C%u5176%u4E2D%u4F1A%u8BFB%u53D6%u914D%u7F6E%u6587%u4EF6%uFF0C%u5E76%u8D4B%u503C%u7ED9%u53D8%u91CF%uFF0C%u8FD9%u4E00%u5757%u8BBE%u8BA1%u6BD4%u8F83%u5DE7%u5999%uFF0C%u65E5%u540E%u53EF%u4EE5%u5355%u72EC%u5F00%u7BC7%u7814%u7A76%u3002%0A%09%20%20%20%20Status%20status%20%3D%20mongo%3A%3ArunGlobalInitializers%28argc%2C%20argv%2C%20envp%29%3B%0A%09%20%20%20%20if%20%28%21status.isOK%28%29%29%20%7B%0A%09%20%20%20%20%20%20%20%20severe%28%29%20%3C%3C%20%22Failed%20global%20initialization%3A%20%22%20%3C%3C%20status%3B%0A%09%20%20%20%20%20%20%20%20%3A%3A_exit%28EXIT_FAILURE%29%3B%0A%09%20%20%20%20%7D%0A%0A%09%20%20%20%20startupConfigActions%28std%3A%3Avector%3Cstd%3A%3Astring%3E%28argv%2C%20argv%20+%20argc%29%29%3B%0A%09%20%20%20%20cmdline_utils%3A%3AcensorArgvArray%28argc%2C%20argv%29%3B%0A%09%09//%u521D%u59CB%u5316%u670D%u52A1%u5668%u8BA4%u8BC1%u914D%u7F6E%0A%09%20%20%20%20if%20%28%21initializeServerGlobalState%28%29%29%0A%09%20%20%20%20%20%20%20%20%3A%3A_exit%28EXIT_FAILURE%29%3B%0A%0A%09%20%20%20%20//%u542F%u52A8%u4E00%u4E2A%u7EBF%u7A0B%u5904%u7406%u7CFB%u7EDF%u4FE1%u53F7%0A%09%20%20%20%20startSignalProcessingThread%28%29%3B%0A%09%09//%u5B9A%u65F6%u540C%u6B65%u6587%u4EF6%0A%09%20%20%20%20dataFileSync.go%28%29%3B%0A%0A%09%09%23if%20defined%28_WIN32%29%0A%09%20%20%20%20if%20%28ntservice%3A%3AshouldStartService%28%29%29%20%7B%0A%09%20%20%20%20%20%20%20%20ntservice%3A%3AstartService%28%29%3B%0A%09%20%20%20%20%20%20%20%20//%20exits%20directly%20and%20so%20never%20reaches%20here%20either.%0A%09%20%20%20%20%7D%0A%09%09%23endif%0A%09%09//%u8FDB%u884C%u4E00%u4E9B%u6D4B%u8BD5%0A%09%20%20%20%20StartupTest%3A%3ArunTests%28%29%3B%0A%09%20%20%20%20//%u521D%u59CB%u5316%u5404%u6A21%u5757%uFF0C%u5E76%u5F00%u59CB%u76D1%u542C%u5BA2%u6237%u7AEF%u8BF7%u6C42%uFF0C%u670D%u52A1%u7AEF%u5F00%u59CB%u8FD0%u884C%0A%09%20%20%20%20initAndListen%28serverGlobalParams.port%29%3B%0A%09%20%20%20%20dbexit%28EXIT_CLEAN%29%3B%0A%09%20%20%20%20return%200%3B%0A%09%7D%0A%20%0A%0AdataFileSync%u662FDataFileSync%u5BF9%u8C61%0A%0A%20%20%20%20class%20DataFileSync%20%3A%20public%20BackgroundJob%20%2C%20public%20ServerStatusSection%20%7B%0A%09public%3A%0A%09%09...%0A%09%09void%20run%28%29%20%7B%0A%09%09...%0A%09%7D%0A%0A%09void%20BackgroundJob%3A%3Ago%28%29%20%7B%0A%20%20%20%20%20%20%20%20scoped_lock%20l%28%20_status-%3Emutex%20%29%3B%0A%20%20%20%20%20%20%20%20massert%28%2017234%2C%20mongoutils%3A%3Astr%3A%3Astream%28%29%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%3C%20%22backgroundJob%20already%20running%3A%20%22%20%3C%3C%20name%28%29%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20_status-%3Estate%20%21%3D%20Running%20%29%3B%0A%0A%20%20%20%20%20%20%20%20//%20If%20the%20job%20is%20already%20%27done%27%2C%20for%20instance%20because%20it%20was%20cancelled%20or%20already%0A%20%20%20%20%20%20%20%20//%20finished%2C%20ignore%20additional%20requests%20to%20run%20the%20job.%0A%20%20%20%20%20%20%20%20if%20%28_status-%3Estate%20%3D%3D%20NotStarted%29%20%7B%0A%09%20%20%20%20%20%20%20%20//BackgroundJob%3A%3AjobBody%u51FD%u6570%u4E2D%u6267%u884C%u5B50%u7C7Brun%u51FD%u6570%uFF0C%u6240%u4EE5%u6587%u4EF6%u540C%u6B65%u5C06%u5728%u540E%u53F0%u7EBF%u7A0B%u4E2D%u6267%u884C%u3002%0A%20%20%20%20%20%20%20%20%20%20%20%20boost%3A%3Athread%20t%28%20boost%3A%3Abind%28%20%26BackgroundJob%3A%3AjobBody%20%2C%20this%20%29%20%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20_status-%3Estate%20%3D%20Running%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0AClient%3A%3AinitThread%28...%29%u51FD%u6570%u5728%u4E4B%u540E%u5F88%u591A%u5730%u65B9%u8FD8%u4F1A%u7528%u5230%uFF0C%u6E90%u7801%u4E2D%u7684%u6CE8%u91CA%u662F%u201Ceach%20thread%20which%20does%20db%20operations%20has%20a%20Client%20object%20in%20TLS.%20%20call%20this%20when%20your%20thread%20starts.%u201D%0A%0A%20%20%20%20Client%26%20Client%3A%3AinitThread%28const%20char%20*desc%2C%20AbstractMessagingPort%20*mp%29%20%7B%0A%20%20%20%20%20%20%20%20verify%28%20currentClient.get%28%29%20%3D%3D%200%20%29%3B%0A%0A%20%20%20%20%20%20%20%20string%20fullDesc%20%3D%20desc%3B%0A%20%20%20%20%20%20%20%20if%20%28%20str%3A%3Aequals%28%20%22conn%22%20%2C%20desc%20%29%20%26%26%20mp%20%21%3D%20NULL%20%29%0A%20%20%20%20%20%20%20%20%20%20%20%20fullDesc%20%3D%20str%3A%3Astream%28%29%20%3C%3C%20desc%20%3C%3C%20mp-%3EconnectionId%28%29%3B%0A%09%09//%u8BBE%u7F6E%u7EBF%u7A0B%u540D%u79F0%uFF0C%u8BE5%u540D%u79F0%u4FDD%u5B58%u5728%u7EBF%u7A0B%u5168%u5C40%u53D8%u91CF_threadName%u4E2D%0A%20%20%20%20%20%20%20%20setThreadName%28%20fullDesc.c_str%28%29%20%29%3B%0A%0A%20%20%20%20%20%20%20%20//%20Create%20the%20client%20obj%2C%20attach%20to%20thread%0A%20%20%20%20%20%20%20%20Client%20*c%20%3D%20new%20Client%28%20fullDesc%2C%20mp%20%29%3B%0A%20%20%20%20%20%20%20%20currentClient.reset%28c%29%3B%0A%20%20%20%20%20%20%20%20mongo%3A%3AlastError.initThread%28%29%3B%0A%20%20%20%20%20%20%20%20c-%3EsetAuthorizationSession%28new%20AuthorizationSession%28new%20AuthzSessionExternalStateMongod%28%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20getGlobalAuthorizationManager%28%29%29%29%29%3B%0A%20%20%20%20%20%20%20%20return%20*c%3B%0A%20%20%20%20%7D%0A%u4E0A%u9762%u7684%u4EE3%u7801%u4E2DsetThreadName%28%29%2C%20currentClient.reset%28c%29%2C%20%20mongo%3A%3AlastError.initThread%28%29%u8FD9%u4E09%u4E2A%u5730%u65B9%u521A%u5F00%u59CB%u8BA9%u6211%u6BD4%u8F83%u7591%u60D1%uFF0C%u56E0%u4E3A_threadName%uFF0CcurrentClient%uFF0ClastError%u90FD%u662F%u5168%u5C40%u53D8%u91CF%uFF0C%u4F46%u662F%u6BCF%u4E2A%u7EBF%u7A0B%u90FD%u53BB%u8BBE%u7F6E%u4E00%u6B21%u662F%u4E0D%u662F%u4F1A%u6539%u53D8%u5176%u4ED6%u4E4B%u524D%u8BBE%u7F6E%u7684%u503C%u5462%uFF1F%u540E%u6765%u81EA%u4E60%u5206%u6790%u6E90%u7801%u540E%u53D1%u73B0%u4ED6%u4EEC%u90FD%u4F7F%u7528%u4E86%u7EBF%u7A0B%u672C%u5730%u5B58%u50A8%u6280%u672F%uFF0Cmongodb%u4E2D%u662F%u76F4%u63A5%u7528%20boost%3A%3Athread_specific_ptr%20%u6765%u5B9E%u73B0%uFF0C%u5728%u6BCF%u4E2A%u7EBF%u7A0B%u4E2D%uFF0C%u90FD%u5404%u81EAnew%u4E00%u4E2A%u5BF9%u8C61%u4EA4%u7ED9%u5168%u5C40%u7684threah_specific_ptr%u8FDB%u884C%u7BA1%u7406%uFF0C%u5F53%u7EBF%u7A0B%u9000%u51FA%u540E%uFF0C%u4ED6%u4F1A%u81EA%u52A8%u91CA%u653E%u8FD9%u4E2A%u5BF9%u8C61%u3002%0A%0A%u4E0B%u9762%u5BF9initAndListen%u51FD%u6570%u5355%u72EC%u8FDB%u884C%u5206%u6790%3A%0A%0A%20%20%20%20void%20initAndListen%28int%20listenPort%29%20%7B%09%0A%20%20%20%20%20%20%20%20try%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20_initAndListen%28listenPort%29%3B%0A%20%20%20%20%20%20%20%20%7D%20%0A%20%20%20%20%20%20%20%20...%0A%20%20%20%20%7D%0A%0A%u4EE5%u4E0B%u662F%u5BF9_initAndListen%u4E3B%u8981%u4EE3%u7801%u7684%u5206%u6790%3A%0A%0A%09void%20_initAndListen%28int%20listenPort%20%29%20%7B%0A%20%20%20%20%20%20%20%20//%u8BBE%u7F6E%u7EBF%u7A0B%u540D%u79F0%uFF0C%u4E3A%u5F53%u524D%u7EBF%u7A0B%u521B%u5EFA%u6570%u636E%u5E93%u64CD%u4F5C%u7684Client%u5BF9%u8C61%0A%20%20%20%20%20%20%20%20Client%3A%3AinitThread%28%22initandlisten%22%29%3B%0A%09%09//%u5224%u65AD%u5F53%u524D%u662F%u5426%u4E3A32%u4F4D%u7CFB%u7EDF%0A%20%20%20%20%20%20%20%20bool%20is32bit%20%3D%20sizeof%28int*%29%20%3D%3D%204%3B%0A%09%09....%0A%20%20%20%20%20%20%20%20//%20Read%20storage%20engine%20metadata%20file%20%28introduced%20in%202.8%29%20if%20present.%0A%20%20%20%20%20%20%20%20//%20Do%20not%20start%20server%20if%20storage%20engine%20in%20metadata%20is%20not%20%27mmapv1%27.%0A%20%20%20%20%20%20%20%20StorageEngineMetadata%3A%3Avalidate%28storageGlobalParams.dbpath%2C%20%22mmapv1%22%29%3B%0A%0A%20%20%20%20%20%20%20%20//%20TODO%20check%20non-journal%20subdirs%20if%20using%20directory-per-db%0A%20%20%20%20%20%20%20%20checkReadAhead%28storageGlobalParams.dbpath%29%3B%0A%09%09//%u6587%u4EF6%u9501%0A%09%09//%u4FDD%u8BC1%u5F53%u524Ddbpath%u76EE%u5F55%u4E0B%u53EA%u6709%u4E00%u4E2Amongodb%u5B9E%u4F8B%uFF0C%u5982%u679C%u5F53%u524Ddbpath%u76EE%u5F55%u5DF2%u7ECF%u6709mongodb%u8FD0%u884C%0A%09%09//%u5219%u83B7%u53D6%u6587%u4EF6%u9501%u5931%u8D25%u3002%0A%20%20%20%20%20%20%20%20acquirePathLock%28mongodGlobalParams.repair%29%3B%0A%20%20%20%20%20%20%20%20//%u5220%u9664%u6240%u6709%u4E34%u65F6%u6587%u4EF6%0A%20%20%20%20%20%20%20%20boost%3A%3Afilesystem%3A%3Aremove_all%28storageGlobalParams.dbpath%20+%20%22/_tmp/%22%29%3B%0A%09%09//%u6587%u4EF6%0A%20%20%20%20%20%20%20%20FileAllocator%3A%3Aget%28%29-%3Estart%28%29%3B%0A%0A%20%20%20%20%20%20%20%20...%0A%0A%20%20%20%20%20%20%20%20MONGO_ASSERT_ON_EXCEPTION_WITH_MSG%28%20clearTmpFiles%28%29%2C%20%22clear%20tmp%20files%22%20%29%3B%0A%09%09//%u5F00%u542Fjournal%u7EBF%u7A0B%uFF0C%u521B%u5EFA%u6301%u4E45%u5316%u76EE%u5F55%u548C%u6587%u4EF6%0A%20%20%20%20%20%20%20%20dur%3A%3Astartup%28%29%3B%0A%20%20%20%20%20%20%20%20...%0A%09%09//%u521B%u5EFAv8%u811A%u672C%u5F15%u64CE%0A%20%20%20%20%20%20%20%20if%20%28mongodGlobalParams.scriptingEnabled%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20ScriptEngine%3A%3Asetup%28%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20globalScriptEngine-%3EsetCheckInterruptCallback%28%20jsInterruptCallback%20%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20globalScriptEngine-%3EsetGetCurrentOpIdCallback%28%20jsGetCurrentOpIdCallback%20%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20...%0A%20%20%20%20%20%20%20%20//%u542F%u52A8%u7EBF%u7A0B%u5FEB%u7167%uFF0C%u5B9A%u65F6%u62CD%u7167%uFF0C%u9ED8%u8BA44%u79D2%0A%20%20%20%20%20%20%20%20if%20%28serverGlobalParams.isHttpInterfaceEnabled%29%0A%20%20%20%20%20%20%20%20%20%20%20%20snapshotThread.go%28%29%3B%0A%0A%20%20%20%20%20%20%20%20d.clientCursorMonitor.go%28%29%3B%0A%20%20%20%20%20%20%20%20//%u62A5%u544A%u5185%u5B58%u4F7F%u7528%u60C5%u51B5%u548C%u8FC7%u65F6%u8FC7%u65F6%u5220%u9664%u5BA2%u6237%u7AEF%u6E38%u6807%u7684%u7EBF%u7A0B%0A%20%20%20%20%20%20%20%20PeriodicTask%3A%3AstartRunningPeriodicTasks%28%29%3B%0A%20%20%20%20%20%20%20%20//%u542F%u52A8%u5B9A%u671F%u6267%u884C%u4EFB%u52A1%u7684%u7EBF%u7A0B%uFF0C%u521B%u5EFAPeriodicTaskRunner%2C%u68C0%u6D4Bshutdown%u4FE1%u53F7%uFF0C%u6CA1%u6709%u5C31%u7B49%u5F85%uFF0C%u9ED8%u8BA460%u79D2%u3002%0A%20%20%20%20%20%20%20%20if%20%28missingRepl%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20a%20warning%20was%20logged%20earlier%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%20startTTLBackgroundJob%28%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%09%23ifndef%20_WIN32%0A%20%20%20%20%20%20%20%20mongo%3A%3AsignalForkSuccess%28%29%3B%0A%09%23endif%0A%0A%20%20%20%20%20%20%20%20if%28getGlobalAuthorizationManager%28%29-%3EisAuthEnabled%28%29%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20open%20admin%20db%20in%20case%20we%20need%20to%20use%20it%20later.%20TODO%20this%20is%20not%20the%20right%20way%20to%0A%20%20%20%20%20%20%20%20%20%20%20%20//%20resolve%20this.%0A%20%20%20%20%20%20%20%20%20%20%20%20Client%3A%3AWriteContext%20c%28%22admin%22%2C%20storageGlobalParams.dbpath%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20authindex%3A%3AconfigureSystemIndexes%28%22admin%22%29%3B%0A%0A%20%20%20%20%20%20%20%20getDeleter%28%29-%3EstartWorkers%28%29%3B%0A%0A%20%20%20%20%20%20%20%20//%20Starts%20a%20background%20thread%20that%20rebuilds%20all%20incomplete%20indices.%20%0A%20%20%20%20%20%20%20%20indexRebuilder.go%28%29%3B%20%0A%09%09//%u5F00%u59CB%u76D1%u542C%0A%20%20%20%20%20%20%20%20listen%28listenPort%29%3B%0A%0A%20%20%20%20%20%20%20%20//%20listen%28%29%20will%20return%20when%20exit%20code%20closes%20its%20socket.%0A%20%20%20%20%20%20%20%20exitCleanly%28EXIT_NET_ERROR%29%3B%0A%20%20%20%20%7D%0A%0A%u4ECE%u4E0A%u9762%u7684_initAndListen%u51FD%u6570%u4E2D%u53EF%u4EE5%u770B%u5230%uFF0C%u5E76%u6CA1%u6709%u5F00%u59CB%u76D1%u542C%u5BA2%u6237%u7AEF%u8BF7%u6C42%uFF0C%u53EA%u662F%u505A%u4E86%u4E00%u4E9B%u6570%u636E%u5E93%u51C6%u5907%u5DE5%u4F5C%uFF0C%u6700%u540E%u624D%u8C03%u7528listen%28listenPort%29%u51FD%u6570%u5BF9%u7AEF%u53E3%u8FDB%u884C%u76D1%u542C%uFF0C%u4E0B%u9762%u7EE7%u7EED%u5206%u6790listen%u51FD%u6570%uFF1A%0A%0A%20%20%20%20void%20listen%28int%20port%29%20%7B%0A%20%20%20%20%20%20%20%20//testTheDb%28%29%3B%0A%20%20%20%20%20%20%20%20MessageServer%3A%3AOptions%20options%3B%0A%20%20%20%20%20%20%20%20options.port%20%3D%20port%3B%0A%20%20%20%20%20%20%20%20options.ipList%20%3D%20serverGlobalParams.bind_ip%3B%0A%0A%20%20%20%20%20%20%20%20MessageServer%20*%20server%20%3D%20createServer%28%20options%20%2C%20new%20MyMessageHandler%28%29%20%29%3B%0A%20%20%20%20%20%20%20%20server-%3EsetAsTimeTracker%28%29%3B%0A%20%20%20%20%20%20%20%20//%20we%20must%20setupSockets%20prior%20to%20logStartup%28%29%20to%20avoid%20getting%20too%20high%0A%20%20%20%20%20%20%20%20//%20a%20file%20descriptor%20for%20our%20calls%20to%20select%28%29%0A%20%20%20%20%20%20%20%20//%u521D%u59CB%u5316Socket%uFF0C%u7136%u540E%u8C03%u7528listen%u51FD%u6570%u5F00%u59CB%u76D1%u542C%0A%20%20%20%20%20%20%20%20server-%3EsetupSockets%28%29%3B%0A%0A%20%20%20%20%20%20%20%20logStartup%28%29%3B%0A%20%20%20%20%20%20%20%20//%u540E%u53F0%u542F%u52A8%u6570%u636E%u5206%u7247%u7EBF%u7A0B%0A%20%20%20%20%20%20%20%20startReplication%28%29%3B%0A%20%20%20%20%20%20%20%20//%u5982%u679C%u8BBE%u7F6E%u4E86--httpinterface%u53C2%u6570%uFF0C%u5219%u4F1A%u542F%u52A8web%u7EBF%u7A0B%u7EBF%u7A0B%u76D1%u542Chttp%u8BF7%u6C42%0A%20%20%20%20%20%20%20%20if%20%28serverGlobalParams.isHttpInterfaceEnabled%29%0A%20%20%20%20%20%20%20%20%20%20%20%20boost%3A%3Athread%20web%28%20boost%3A%3Abind%28%26webServerThread%2C%20new%20RestAdminAccess%28%29%20/*%20takes%20ownership%20*/%29%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20server-%3Erun%28%29%3B%0A%09%7D%0AMessageServer%20%u662F%u6D88%u606F%u670D%u52A1%u7684%u57FA%u7C7B%uFF0CcreateServer%u8FD4%u56DE%u7684%u662F%u4ED6%u7684%u5B50%u7C7BPortMessageServer%u7684%u5BF9%u8C61%uFF0CPortMessageServer%u4E2D%u91CD%u5199%u4E86%u865A%u51FD%u6570run%uFF0C%u5BA2%u6237%u7AEF%u8FDE%u63A5%u5904%u7406%u53C8%u88AB%u5EF6%u8FDF%u5230%u4E86PortMessageServer%3A%3Arun%28%29%u51FD%u6570%u4E2D%u3002%0A%0A%20%20%20%20class%20MessageServer%20%7B%0A%20%20%20%20public%3A%0A%20%20%20%20%20%20%20%20struct%20Options%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20int%20port%3B%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20port%20to%20bind%20to%0A%20%20%20%20%20%20%20%20%20%20%20%20string%20ipList%3B%20%20%20%20%20%20%20%20%20%20%20%20%20//%20addresses%20to%20bind%20to%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Options%28%29%20%3A%20port%280%29%2C%20ipList%28%22%22%29%20%7B%7D%0A%20%20%20%20%20%20%20%20%7D%3B%0A%0A%20%20%20%20%20%20%20%20virtual%20%7EMessageServer%28%29%20%7B%7D%0A%20%20%20%20%20%20%20%20virtual%20void%20run%28%29%20%3D%200%3B%0A%20%20%20%20%20%20%20%20virtual%20void%20setAsTimeTracker%28%29%20%3D%200%3B%0A%20%20%20%20%20%20%20%20virtual%20void%20setupSockets%28%29%20%3D%200%3B%0A%20%20%20%20%7D%3B%0A%20%20%20%20%0A%20%20%20%20class%20Listener%20%3A%20boost%3A%3Anoncopyable%20%7B%0A%20%20%20%20public%3A%0A%20%20%20%20%20%20%20%20void%20initAndListen%28%29%3B%20//%20never%20returns%20unless%20error%20%28start%20a%20thread%29%0A%0A%20%20%20%20%20%20%20%20/*%20spawn%20a%20thread%2C%20etc.%2C%20then%20return%20*/%0A%20%20%20%20%20%20%20%20virtual%20void%20accepted%28boost%3A%3Ashared_ptr%3CSocket%3E%20psocket%2C%20long%20long%20connectionId%20%29%3B%0A%20%20%20%20%20%20%20%20virtual%20void%20acceptedMP%28MessagingPort%20*mp%29%3B%0A%20%20%20%20%20%20%20%20...%0A%20%20%20%20%7D%0A%0A%20%20%20%20%20class%20PortMessageServer%20%3A%20public%20MessageServer%20%2C%20public%20Listener%20%7B%0A%09%09...%0A%09%7D%0A%0A%u4E0B%u9762%u7EE7%u7EED%u5206%u6790PortMessageServer%3A%3Arun%28%29%u51FD%u6570%3A%0A%0A%20%20%20%20void%20run%28%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20initAndListen%28%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%u7531%u4E8EinitAndListen%u51FD%u6570%u5728mongodb%u4E2DWindows%u548CLinux%u4E24%u90E8%u5206%u5206%u5F00%u6765%u5B9E%u73B0%uFF0C%u6211%u4EEC%u53EA%u5206%u6790Linux%u90E8%u5206%uFF0C%u4E24%u90E8%u5206%u539F%u6765%u76F8%u540C%uFF0C%u90FD%u662F%u4F7F%u7528select%u6765%u76D1%u542C%u5BA2%u6237%u7AEF%u8BF7%u6C42%u3002%u4E0B%u9762%u4EE3%u7801%u6211%u5220%u9664%u90E8%u5206%uFF0C%u53EA%u4FDD%u7559%u5904%u7406%u903B%u8F91%u3002%0A%0A%20%20%20%20%23if%20%21defined%28_WIN32%29%0A%20%20%20%20void%20Listener%3A%3AinitAndListen%28%29%20%7B%0A%20%20%20%20%20%20%20%20if%20%28%21_setupSocketsSuccessful%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20SOCKET%20maxfd%20%3D%200%3B%20//%20needed%20for%20select%28%29%0A%20%20%20%20%20%20%20%20for%20%28unsigned%20i%20%3D%200%3B%20i%20%3C%20_socks.size%28%29%3B%20i++%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20%28_socks%5Bi%5D%20%3E%20maxfd%29%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20maxfd%20%3D%20_socks%5Bi%5D%3B%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20...%0A%20%20%20%20%20%20%20%20struct%20timeval%20maxSelectTime%3B%0A%20%20%20%20%20%20%20%20while%20%28%20%21%20inShutdown%28%29%20%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20fd_set%20fds%5B1%5D%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20FD_ZERO%28fds%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20%28vector%3CSOCKET%3E%3A%3Aiterator%20it%3D_socks.begin%28%29%2C%20end%3D_socks.end%28%29%3B%20it%20%21%3D%20end%3B%20++it%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20FD_SET%28*it%2C%20fds%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%20maxSelectTime.tv_sec%20%3D%200%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20maxSelectTime.tv_usec%20%3D%2010000%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20const%20int%20ret%20%3D%20select%28maxfd+1%2C%20fds%2C%20NULL%2C%20NULL%2C%20%26maxSelectTime%29%3B%0A%09%09%09...%0A%09%09%09%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20%28vector%3CSOCKET%3E%3A%3Aiterator%20it%3D_socks.begin%28%29%2C%20end%3D_socks.end%28%29%3B%20it%20%21%3D%20end%3B%20++it%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20%28%21%20%28FD_ISSET%28*it%2C%20fds%29%29%29%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20continue%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20SockAddr%20from%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20int%20s%20%3D%20accept%28*it%2C%20from.raw%28%29%2C%20%26from.addressSize%29%3B%0A%09%09%09%09...%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20long%20long%20myConnectionNumber%20%3D%20globalConnectionNumber.addAndFetch%281%29%3B%0A%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%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20boost%3A%3Ashared_ptr%3CSocket%3E%20pnewSock%28%20new%20Socket%28s%2C%20from%29%20%29%3B%0A%09%23ifdef%20MONGO_SSL%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20%28_ssl%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pnewSock-%3EsecureAccepted%28_ssl%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%09%23endif%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20accepted%28%20pnewSock%20%2C%20myConnectionNumber%20%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%0A%09%23else%20%0A%u4E0A%u9762%u662F%u4E00%u4E2A%u6807%u51C6%u7684%u670D%u52A1%u7AEFsocket%20select%u6A21%u578B%uFF0C%u6BCF%u5F53%u6709%u5BA2%u6237%u7AEFsocket%u8FDE%u63A5%u65F6%uFF0Caccept%u6210%u529F%u540E%u8C03%u7528accepted%u51FD%u6570%u5904%u7406%u3002%0A%0A%20%20%20%20void%20Listener%3A%3Aaccepted%28boost%3A%3Ashared_ptr%3CSocket%3E%20psocket%2C%20long%20long%20connectionId%20%29%20%7B%0A%20%20%20%20%20%20%20%20MessagingPort*%20port%20%3D%20new%20MessagingPort%28psocket%29%3B%0A%20%20%20%20%20%20%20%20port-%3EsetConnectionId%28%20connectionId%20%29%3B%0A%20%20%20%20%20%20%20%20acceptedMP%28%20port%20%29%3B%0A%20%20%20%20%7D%0A%u6B64%u5904%u8C03%u7528%u7684PortMessageServer%u5BF9%u8C61%u7684acceptedMP%u6210%u5458%u51FD%u6570%28PortMessageServer%u662FListener%u7684%u5B50%u7C7B%29%uFF0C%u8FD9%u91CC%u6211%u4EEC%u770B%u5230%u4E86%u4E00%u4E2A%u65B0%u7684%u7C7BMessagingPort%uFF0CMessagingPort%u5C01%u88C5%u4E86Message%u7684%u53D1%u9001%u3001%u63A5%u6536%u7B49%u64CD%u4F5C%uFF0C%u82E5%u6709%u9700%u6C42%u4EE5%u540E%u518D%u5177%u4F53%u5206%u6790%u3002%0A%0A%20%20%20%20virtual%20void%20acceptedMP%28MessagingPort%20*%20p%29%20%7B%0A%09%20%20%20%20...%0A%20%20%20%20%20%20%20%20pthread_attr_t%20attrs%3B%0A%20%20%20%20%20%20%20%20pthread_attr_init%28%26attrs%29%3B%0A%20%20%20%20%20%20%20%20pthread_attr_setdetachstate%28%26attrs%2C%20PTHREAD_CREATE_DETACHED%29%3B%0A%0A%20%20%20%20%20%20%20%20static%20const%20size_t%20STACK_SIZE%20%3D%201024*1024%3B%20//%20if%20we%20change%20this%20we%20need%20to%20update%20the%20warning%0A%0A%20%20%20%20%20%20%20%20struct%20rlimit%20limits%3B%0A%20%20%20%20%20%20%20%20pthread_t%20thread%3B%0A%20%20%20%20%20%20%20%20HandleIncomingMsgParam*%20himParam%20%3D%20new%20HandleIncomingMsgParam%28p%2C%20_handler%29%3B%0A%20%20%20%20%20%20%20%20int%20failed%20%3D%20pthread_create%28%26thread%2C%20%26attrs%2C%20%26handleIncomingMsg%2C%20himParam%29%3B%0A%0A%20%20%20%20%20%20%20%20pthread_attr_destroy%28%26attrs%29%3B%0A%20%20%20%20%7D%0AacceptedMP%u63A5%u6536%u5230%u6D88%u606F%u540E%u5EFA%u7ACB%u4E00%u4E2A%u540E%u53F0%u7EBF%u7A0B%uFF0C%u5728%u540E%u53F0%u7EBF%u7A0B%u4E2D%u6267%u884ChandleIncomingMsg%u51FD%u6570%uFF0C%u5904%u7406%u5BA2%u6237%u7AEF%u8FDE%u63A5%u3002%0A%0A%20%20%20%20%20%20static%20void*%20handleIncomingMsg%28void*%20arg%29%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20TicketHolderReleaser%20connTicketReleaser%28%20%26Listener%3A%3AglobalTicketHolder%20%29%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20scoped_ptr%3CHandleIncomingMsgParam%3E%20himArg%28static_cast%3CHandleIncomingMsgParam*%3E%28arg%29%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20MessagingPort*%20inPort%20%3D%20himArg-%3EinPort%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20MessageHandler*%20handler%20%3D%20himArg-%3Ehandler%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20...%0A%20%20%20%20%20%20%20%20%20%20%20%20inPort-%3Epsock-%3EsetLogLevel%28logger%3A%3ALogSeverity%3A%3ADebug%281%29%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20scoped_ptr%3CMessagingPort%3E%20p%28%20inPort%20%29%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20string%20otherSide%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Message%20m%3B%0A%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%20LastError%20*%20le%20%3D%20new%20LastError%28%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lastError.reset%28%20le%20%29%3B%20//%20lastError%20now%20has%20ownership%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20handler-%3Econnected%28%20p.get%28%29%20%29%3B%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%20%20%20%20while%20%28%20%21%20inShutdown%28%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%20m.reset%28%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20p-%3Epsock-%3EclearCounters%28%29%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20%28%20%21%20p-%3Erecv%28m%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%20...%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%20handler-%3Eprocess%28%20m%20%2C%20p.get%28%29%20%2C%20le%20%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20networkCounter.hit%28%20p-%3Epsock-%3EgetBytesIn%28%29%20%2C%20p-%3Epsock-%3EgetBytesOut%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%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20...%0A%20%20%20%20%20%20%20%20%20%20%20%20handler-%3Edisconnected%28%20p.get%28%29%20%29%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20NULL%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%3B%0A%0A%u4EE5%u4E0A%u4EE3%u7801%u53EF%u4EE5%u770B%u51FA%uFF0C%u670D%u52A1%u7AEF%u5728%u63A5%u6536%u5230%u5BA2%u6237%u7AEF%u8FDE%u63A5%u8BF7%u6C42%u540E%u5EFA%u7ACB%u8FDE%u63A5%uFF0C%u7136%u540E%u521B%u5EFA%u540E%u53F0%u7EBF%u7A0B%uFF0C%u5728%u7EBF%u7A0B%u4E2D%u4F7F%u7528while%u5FAA%u73AF%u4E0D%u65AD%u7684%u63A5%u6536Message%uFF0C%u7136%u540E%u8C03%u7528handler%u7684process%u5904%u7406%u3002handler-%3Econnected%u91CC%u9762%u53EA%u662F%u518D%u6B21%u8C03%u7528Client%3A%3AinitThread%28%22conn%22%2C%20p%29%uFF0C%u8FD9%u4E2A%u95EE%u9898%u4E4B%u524D%u5DF2%u7ECF%u5206%u6790%u8FC7%u3002%0A%u6700%u540E%u4E00%u4E2A%u95EE%u9898%uFF0Chandler%u5BF9%u8C61%u5176%u5B9E%u5C31%u662FcreateServer%u65F6%u5019%u4F20%u5165%u7684%u7B2C%u4E8C%u4E2A%u53C2%u6570new%20MyMessageHandler%28%29%3B%0A%0A%20%20%20%20class%20MessageHandler%20%7B%0A%20%20%20%20public%3A%0A%20%20%20%20%20%20%20%20virtual%20%7EMessageHandler%28%29%20%7B%7D%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20called%20once%20when%20a%20socket%20is%20connected%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20virtual%20void%20connected%28%20AbstractMessagingPort*%20p%20%29%20%3D%200%3B%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20called%20every%20time%20a%20message%20comes%20in%0A%20%20%20%20%20%20%20%20%20*%20handler%20is%20responsible%20for%20responding%20to%20client%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20virtual%20void%20process%28%20Message%26%20m%20%2C%20AbstractMessagingPort*%20p%20%2C%20LastError%20*%20err%20%29%20%3D%200%3B%0A%0A%20%20%20%20%20%20%20%20/**%0A%20%20%20%20%20%20%20%20%20*%20called%20once%20when%20a%20socket%20is%20disconnected%0A%20%20%20%20%20%20%20%20%20*/%0A%20%20%20%20%20%20%20%20virtual%20void%20disconnected%28%20AbstractMessagingPort*%20p%20%29%20%3D%200%3B%0A%20%20%20%20%7D%3B%0A%0A%20%20%20%20%20class%20MyMessageHandler%20%3A%20public%20MessageHandler%20%7B%0A%09%09%20%20%20%20%20...%0A%20%20%20%20%7D%0A%0A%u81F3%u6B64mongod%u7684%u6574%u4E2A%u6D88%u606F%u5904%u7406%u8F6E%u5ED3%u5DF2%u7ECF%u51FA%u6765%u4E86%uFF0C%u5176%u4ED6%u7684%u90E8%u5206%u5C06%u4F1A%u5728%u540E%u7EED%u7684%u90E8%u5206%u4E2D%u7EE7%u7EED%u5206%u6790
posted @ 2015-03-26 14:29  _ccx  阅读(1914)  评论(2编辑  收藏  举报