mongodb源码分析(三)mongo的启动

          mongo是mongodb的一个C++写的javascript交互式的可执行客户端。为了分析mongod对于服务请求的响应,这里分析下mongo。先来看看mongo的启动,mongo的启动代码在mongo/shell/dbshell.cpp中。其支持两个javascript 引擎,因为用visual stdio2012调试时默认编译的是spidermonkey,那么就分析spidermonkey那边吧。

          当我们使用mongodb时最简单的一个保存命令是db.coll.save({a:1}),我们知道db是javascript对象,也是数据库名,coll是数据集collection,这里将{a:1}保存到coll的集合中,但是这里有一个疑问,javascript对象对于未定义的属性的访问不是通过db[coll]访问的吗,coll这里本应该是undefined,但是为什么结果成功的保存了呢。当我在阅读源码时就有这么个疑问,还好终于从源码中找到了答案,好了废话不多说了,直接分析。

    po::options_description shell_options( "options" );//同样是一大堆启动命令,具体含义不说了,自己可以看相关的文档
    po::options_description hidden_options( "Hidden options" );
    po::options_description cmdline_options( "Command line options" );
    po::positional_options_description positional_options;

    shell_options.add_options()
    ( "shell", "run the shell after executing files" )
    ( "nodb", "don't connect to mongod on startup - no 'db address' arg expected" )
    ( "norc", "will not run the \".mongorc.js\" file on start up" )
    ( "quiet", "be less chatty" )
    ( "port", po::value<string>( &port ), "port to connect to" )
    ( "host", po::value<string>( &dbhost ), "server to connect to" )
    ( "eval", po::value<string>( &script ), "evaluate javascript" )
    ( "username,u", po::value<string>(&username), "username for authentication" )
    ( "password,p", new mongo::PasswordValue( &password ), "password for authentication" )
    ( "help,h", "show this usage information" )
    ( "version", "show version information" )
    ( "verbose", "increase verbosity" )
    ( "ipv6", "enable IPv6 support (disabled by default)" )
    if ( !nodb ) { // connect to db
        //if ( ! mongo::cmdLine.quiet ) cout << "url: " << url << endl;
        //如果启动时没有指定nodb,那么这里将生成一串javascript代码,用来连接mongod
        stringstream ss;
        if ( mongo::cmdLine.quiet )
            ss << "__quiet = true;";
        ss << "db = connect( \"" << fixHost( url , dbhost , port ) << "\")";

        mongo::shell_utils::_dbConnect = ss.str();

        if ( params.count( "password" ) && password.empty() )
            password = mongo::askPassword();

        if ( username.size() && password.size()) {
            stringstream ss;
            ss << "if ( ! db.auth( \"" << username << "\" , \"" << password << "\" ) ){ throw 'login failed'; }";
            mongo::shell_utils::_dbAuth = ss.str();
        }
    }
    mongo::ScriptEngine::setConnectCallback( mongo::shell_utils::onConnect );//这个回调函数用来做连接成功后的记录工作
    mongo::ScriptEngine::setup();
    mongo::globalScriptEngine->setScopeInitCallback( mongo::shell_utils::initScope );
    auto_ptr< mongo::Scope > scope( mongo::globalScriptEngine->newScope() );
    shellMainScope = scope.get();

现在来看看mongo::globalScriptEngine->newScope(),在mongo::ScriptEngine::setup()函数中globalScriptEngine=new SMEngine()。

        virtual Scope * newScope() {
            Scope *s = createScope();
            if ( s && _scopeInitCallback )//_scopeInitCallback对应上面的mongo::shell_utils::initScope
                _scopeInitCallback( *s );
            installGlobalUtils( *s );
            return s;
        }
createScope对应spideMonkey则为new SMScope()

        SMScope() ://spideMonkey的初始化
            _this( 0 ),
            _reportError( true ),
            _externalSetup( false ),
            _localConnect( false ) {
            smlock;
            _context = JS_NewContext( globalSMEngine->_runtime , 8192 );
            _convertor = new Convertor( _context );
            massert( 10431 ,  "JS_NewContext failed" , _context );

            JS_SetOptions( _context , JSOPTION_VAROBJFIX);
            //JS_SetVersion( _context , JSVERSION_LATEST); TODO
            JS_SetErrorReporter( _context , errorReporter );

            _global = JS_NewObject( _context , &global_class, NULL, NULL);
            massert( 10432 ,  "JS_NewObject failed for global" , _global );
            JS_SetGlobalObject( _context , _global );
            massert( 10433 ,  "js init failed" , JS_InitStandardClasses( _context , _global ) );

            JS_SetOptions( _context , JS_GetOptions( _context ) | JSOPTION_VAROBJFIX );

            JS_DefineFunctions( _context , _global , globalHelpers );//预先定义的几个函数

            JS_DefineFunctions( _context , _convertor->getGlobalObject( "Object" ), objectHelpers );

            //JS_SetGCCallback( _context , no_gc ); // this is useful for se
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值