CommandÔÚMongodbÖÐÊÇÒ»ÀàÌØÊâ²Ù×÷£¬ËüÌṩÁËÇ¿´óµÄ¹ÜÀí¼°¸÷Ïî²Ù×÷£¨±ÈÈ罨¿â£¬Ë÷Òý£¬É¾³ý¼¯ºÏµÈ£©¡£¿ÉÒÔ˵ͨ¹ýCommand¿ÉÒÔÍê³É¼¸ºõËùÓÐÏë×öµÄÊÂÇ顣ͬʱMongodb¿ª·¢ÕßÔÚCommandÉÏÓÖ×öÁ˷dz£ÇåÎúÌåϵ¼Ü¹¹ºÍÉè¼Æ£¬±ãÓÚ¹ÜÀíºÍ¸ßЧִÐи÷ÖÖÀàÐ͵ÄCommand¡£
½ñÌì¾ÍרÃÅÓÃһƪƪ·ùÀ´×ÅÖØ½éÉÜÒ»ÏÂÆäCommandµÄÌåϵ¼Ü¹¹£¬²¢ÓÃÀý×ÓÀ´½éÉÜmongodÊÇÈçºÎ½«CommandÒýÈëÆäÖеġ£
ΪÁË¶ÔÆäÖд󲿷Öcommand¶ÔÒ»¸ö´óÖµÄÁ˽⣬ÎÒÃÇ¿ÉÒÔÓÃÏÂÃæÖ¸ÁîÀ´ÏÔʾһ¸öcommandÁÐ±í£º
1.mongod --dbpath d:\mongodb\db --port 27017 --rest 2.ÔÚä¯ÀÀÆ÷ÉÏÊäÈëÁ´½ÓµØÖ·£ºhttp://localhost:28017/_commands |
ÕâÀïmongod¾Í»áΪÎÒÃÇÏÔʾcommandÁÐ±í£¬´óÔ¼ÓÐ90¶à¸ö£¬ÕâÊÇÏÔʾ½ØÍ¼£º

ÉÏÃæ90¶à¸öÀàÖУ¬°´ÆäʹÓó¡¾°¿ÉÒÔΪ·ÖÈçϼ¸À࣬·Ö±ðÊÇ£º
dbcommand.cpp£ºÒ»°ãÊý¾Ý¿âÖ¸ÁÈçÊý¾Ý¿â£¬Ë÷ÒýµÄ´´½¨£¬Öؽ¨£¬´ò¿ª/¹Ø±ÕµÈ
dbcommands_admin.cpp£º¹ÜÀíÖ¸ÁÈçCleanCmd£¬JournalLatencyTestCmd£¬ValidateCmd£¬FSyncCommand
dbcommands_generic.cpp£º³£ÓÃÖ¸Áî,ListCommandsCmd,LogRotateCmd,PingCommand,CmdSet,CmdGetµÈ
replset_commands.cpp£º¸´ÖƼ¯Ö¸ÁCmdReplSetTest£¬CmdReplSetGetStatus,CmdReplSetReconfigµÈ
security_commands.cpp£º°²È«Ö¸Áî,CmdGetNonce,CmdLogout,CmdAuthenticate
commands_admin.cpp£ºshard¹ÜÀí²Ù×÷£¬ÒòÆäλÓÚmongosÏîÄ¿£¬ÕâÀïÔݲ»½éÉÜ
commands_public.cpp£ºshard¹«ÓòÙ×÷£¬ÒòÆäλÓÚmongosÏîÄ¿£¬ÕâÀïÔݲ»½éÉÜ
ÏÂÃæÊÇÏà¹ØÀàͼ£º





Ê×ÏÈÎÒÃÇ¿´Ò»ÏÂÔÚCommandµÄ»ùÀ࣬ÆäÓÃÓÚ¶¨Òå×ÓÀàҪʵÏֵķ½·¨¼°ÊôÐÔ£¬×ÔÉíҲʵÏÖÁËһЩͨÓ÷½·¨£¬±ÈÈçhtmlHelp(ÓÃÓÚÒÔhtml·½·¨ÏÔʾ¸ÃcommandµÄ°ïÖúÐÅÏ¢),¹¹Ôì·½·¨£¬findCommand(²éѯÃüÁî)µÈ£¬ÆäÉùÃ÷ÈçÏ£º
//commands.h
class Command {
public:
//Ö´Ðе±Ç°CommandʱËùʹÓõÄËøÀàÐÍ
enum LockType { READ = -1/*¶Á*/ , NONE = 0 /*ÎÞËø*/, WRITE = 1 /*д*/};
const string name;
/* ÔËÐÐÖ¸¶¨µÄÃüÁÐèÒª×ÓÀàʵÏÖ
fromRepl - command is being invoked as part of replication syncing. In this situation you
normally do not want to log the command to the local oplog.
ÈçÖ´Ðгɹ¦·µ»Øtrue,·ñÔòΪfalse, errmsg¼Ç¼´íÎóÐÅÏ¢
*/
virtual bool run(const string& db, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool fromRepl) = 0;
/*
note: logTheTop() MUST be false if READ
if NONE, can't use Client::Context setup
use with caution
*/
virtual LockType locktype() const = 0;
/* ÊÇ·ñÓйÜÀíÌØÈ¨²Å¿ÉÔËÐиÃÃüÁî has privileges to run this command. */
virtual bool adminOnly() const {
return false;
}
//html¸ñʽµÄ°ïÖúÐÅÏ¢
void htmlHelp(stringstream&) const;
/* ÓëadminOnlyÏàËÆ,µ«¸üÑϸñ: Ҫô±»ÑéÖ¤£¬ÒªÃ´Ö»ÔËÐÐÔÚ±¾µØ½Ó¿Ú£¨local interface£©
×¢£ºµ±±¾ÊôÐÔΪtrueʱ£¬adminOnly()Ò²±ØÐëΪtrue.
*/
virtual bool localHostOnlyIfNoAuth(const BSONObj& cmdObj) { return false; }
/* Èç¹ûreplication pair µÄslaves¿ÉÒÔÔËÐÐÃüÁîµÄ£¬Ôò·µ»Øtrue
(the command directly from a client -- if fromRepl, always allowed).
*/
virtual bool slaveOk() const = 0;
/* ͨ¹ýÔÚ²éѯÃüÁîÖдò¿ª 'slaveok'Ñ¡Ï¿Í»§¶ËÇ¿ÖÆÔÚÒ»¸öslaveÉÏÔËÐÐÒ»¸öÃüÁîʱ£¬·µ»Øtrue.
*/
virtual bool slaveOverrideOk() {
return false;
}
/* Override and return true to if true,log the operation (logOp()) to the replication log.
(not done if fromRepl of course)
Note if run() returns false, we do NOT log.
*/
virtual bool logTheOp() { return false; }
virtual void help( stringstream& help ) const;
/* Return true if authentication and security applies to the commands. Some commands
(e.g., getnonce, authenticate) can be done by anyone even unauthorized.
*/
virtual bool requiresAuth() { return true; }
/** @param webUI£ºÔÚwebÉϱ©Â¶µ±Ç°command£¬ÐÎÈç localhost:28017/
@param oldName£º ¾ÉÑ¡Ï±íʾµ±Ç°commandµÄ¾É(ÒÑÆúÓÃ)Ãû³Æ
*/
Command(const char *_name, bool webUI = false, const char *oldName = 0);
virtual ~Command() {}
protected:
BSONObj getQuery( const BSONObj& cmdObj ) {
if ( cmdObj["query"].type() == Object )
return cmdObj["query"].embeddedObject();
if ( cmdObj["q"].type() == Object )
return cmdObj["q"].embeddedObject();
return BSONObj();
}
static void logIfSlow( const Timer& cmdTimer, const string& msg);
//command map,Æä°üº¬ÏµÍ³ÊµÏÖµÄËùÓÐcommand¶ÔÏó£¬ÒÔ±ãfindCommand²éѯʱʹÓÃ
//×¢ÒâÒ²°üº¬¸ÃcommandµÄ¾ÉÃû³Æ£¨¹¹Ôì·½·¨ÖеÄoldName²ÎÊý£©Ëù¶ÔÓ¦µÄ¶ÔÏó£¬
static map<string,Command*> * _commands;
//ÓëÉÏÃæÐÎͬ£¬µ«²»º¬¾ÉÃû³ÆµÄcommand map
static map<string,Command*> * _commandsByBestName;
//½«webÀàÐ͵Äcommand·Åµ½¸ÃmapÖÐ
static map<string,Command*> * _webCommands;
public:
static const map<string,Command*>* commandsByBestName() { return _commandsByBestName; }
static const map<string,Command*>* webCommands() { return _webCommands; }
/** @return ·µ»ØÊÇ·ñÕÒµ½»òÒÑÖ´ÐÐcommand */
static bool runAgainstRegistered(const char *ns, BSONObj& jsobj, BSONObjBuilder& anObjBuilder);
static LockType locktype( const string& name );
//¸ù¾ÝÃüÁîÃû³ÆÔÚ¼¯ºÏÖÐÕÒµ½ÏàÓ¦Command¶ÔÏó
static Command * findCommand( const string& name );
}; |
Command»ùÀàÖÐÌṩÁ˼¸¸ömap<string,Command*>ÀàÐ͵ļ¯ºÏmap£¬ÓÃÓÚ½«ÏµÍ³ÊµÏÖµÄCommand½øÐÐÊÕ¼¯£¬ÒÔ±ãºóÃæfindCommand½øÐбãÀú²éѯʱʹÓá£ÈçÏ£º
//commands.cpp Command* Command::findCommand( const string& name ) { //´Ó_commands mapÖÐÕÒµ½Ö¸¶¨nameµÄCommand¶ÔÏó map<string,Command*>::iterator i = _commands->find( name ); if ( i == _commands->end() )//Èç¹ûÒѵ½½á⣬±íʾδÕÒµ½ return 0; return i->second;//·µ»ØCommand¶ÔÏó } |
¿´µ½ÉÏÃæ´úÂëÖеÄ_commands´ó¼Ò¿ÉÄÜÒªÎÊ£¬¸ÃmapÊÇÈçºÎ³õʼ»¯²¢½«ÏµÍ³ÊµÏֵĸ÷¸öCommand×¢²áµ½ÆäÖÐÄØ£¿´ð°¸¾ÍÔÚCommandµÄ¹¹Ôì·½·¨ÖУ¬ÈçÏ£º
//command.cpp Command::Command(const char *_name, bool web, const char *oldName) : name(_name) { // register ourself. //ÈçΪ¿Õ£¨ÏµÍ³¸ÕÆô¶¯Ê±£©ÔòʵÀý»¯_commands if ( _commands == 0 ) _commands = new map<string,Command*>; //ÈçΪ¿Õ£¨ÏµÍ³¸ÕÆô¶¯Ê±£©ÔòʵÀý»¯_commandsByBestName if( _commandsByBestName == 0 ) _commandsByBestName = new map<string,Command*>; Command*& c = (*_commands)[name];//»ñȡָ¶¨Ãû³ÆµÄcommand¶ÔÏó if ( c )//ÈçÓУ¬±íʾ֮ǰÒÑ×¢²áÁ˸Ãcommand log() << "warning: 2 commands with name: " << _name << endl; //½«µ±Ç°command£¨this£©¸³Öµµ½mapÖÐÏàÓ¦nameµÄcommandÉÏ c = this; //°ó¶¨µ½_commandsByBestNameÖеÄÏàÓ¦nameÉÏ (*_commandsByBestName)[name] = this; //Èç¹ûÃüÁîÖ§³Öweb·½Ê½ if( web ) { //ÈçΪ¿Õ£¨ÏµÍ³¸ÕÆô¶¯Ê±£©ÔòʵÀý»¯_webCommands if( _webCommands == 0 ) _webCommands = new map<string,Command*>; //°ó¶¨µ½_webCommandsÖеÄÏàÓ¦nameÉÏ (*_webCommands)[name] = this; } //ÈçÓоÉÃû³Æ£¬ÔòÒ²°óµ½_commandsµÄoldNameËùÖ¸ÏòµÄcommand if( oldName ) (*_commands)[oldName] = this; } |
ÓÐÁËÕâЩ»¹²»¹»£¬ÎÒÃÇ»¹Òª´Ó90¶à¸öcommand×ÓÀàÖÐÕÒ³öÒ»¸öÀ´Êµ¼Ê·ÖÎöÆäʵÏֵķ½Ê½£¬ÕâÀïÒÔ×î¾³£Ê¹ÓõÄcount(»ñȡָ¶¨Ìõ¼þµÄ¼Ç¼Êý)À´·ÖÎöÆäÏòmapÖÐ×¢²ácommandµÄÁ÷³Ì£¬²Î¼ûÏÂÃæ´úÂë¶Î£º
//dbcommands.cpp /* select count(*) */ class CmdCount : public Command { public: virtual LockType locktype() const { return READ; } //µ÷ÓûùÀàµÄ¹¹Ôì·½·¨ CmdCount() : Command("count") { }
virtual bool logTheOp() { return false; } virtual bool slaveOk() const { // ok on --slave setups, not ok for nonmaster of a repl pair (unless override) return replSettings.slave == SimpleSlave; } virtual bool slaveOverrideOk() { return true; } virtual bool adminOnly() const { return false; } virtual void help( stringstream& help ) const { help << "count objects in collection"; } virtual bool run(const string& dbname, BSONObj& cmdObj, string& errmsg, BSONObjBuilder& result, bool) { string ns = dbname + '.' + cmdObj.firstElement().valuestr(); string err; long long n = runCount(ns.c_str(), cmdObj, err);//Ö´Ðвéѯ long long nn = n; bool ok = true; if ( n == -1 ) { nn = 0; result.appendBool( "missing" , true ); } else if ( n < 0 ) { nn = 0; ok = false; if ( !err.empty() ) errmsg = err; } result.append("n", (double) nn); return ok; } } cmdCount;
|
ÉÏÃæµÄCmdCountÀ༴ÊÇÔÚÃüÁîÐÐģʽÏÂʹÓÃcountÖ¸Áîʱ¶ÔÓ¦µÄ´úÂë¿é£¬Æä×ÔÉíµÄ¹¹Ô캯Êý¾ÍÖ±½Óµ÷ÓÃÁË»ùÀà(Command)µÄ¹¹Ôì·½·¨¡£µ«ÕâÀïÖ»ÊǶ¨ÒåÁË»¹²»¹»£¬»¹ÐèÒªÒ»¸ö¶¨ÒåÀàʵÀý´úÂ루ÓÃÓÚÆô¶¯¹¹Ô캯Êý£©£¬¶øÕâ¸öÈÎÎñ¾Í½»¸øÁ˸ÃÀඨÒåµÄ´úÂë½áβ´¦µÄÏÂÃæ´úÂëÀ´ÊµÏÖÁË£º
¿ÉÒÔ¿´µ½£¬ÕâÀïʹÓõÄÊÇÔÚÀàÉùÃ÷ºó¶¨Òå¶ÔÏóµÄ·½Ê½À´Ö´Ðй¹Ôì·½·¨£¨Õâʱ²¢Î´Ê¹ÓÃnewʵÀý»¯·½Ê½À´´´½¨¶ÔÏóÖ¸Õ룩£¬½ø¶ø×¢²á¸Ãcommandµ½map¡£µ±È»¼Ì³Ð×ÔCommandµÄ×ÓÀà±ØÐëҪʵÏÖÆäÖеÄrun()·½·¨,ÒòΪֻÓÐËüÊǾßÌåcommandÒªÖ´ÐеľßÌåÂß¼£¨¿É²Î¼ûÉÏÃæCmdCountµÄ¾ßÌåʵÏÖ£©¡£
µ½ÕâÀïÖ»ÄÜ˵mongodÔÚϵͳÆô¶¯µ½ÊµÊ¼»¯ÁËÏàÓ¦µÄCommand¼¯ºÏmapÐÅÏ¢£¬µ«mongodÊÇÈçºÎ½«client·¢À´µÄ²Ù×÷ÇëÇó½øÐÐת»»²¢½ø¶øÖ´ÐÐÏàÓ¦µÄcommandÖ¸ÁîµÄÄØ£¿ÎÒÃǽÓÏÂÀ´¼ÌÐø·ÖÎö¡£
֮ǰ¿´¹ýÎÒµÄÕâÆªÎÄÕµÄÅóÓÑ¿ÉÄÜ»¹ÓÐÓ¡Ïó£¬ÔÚmongodÆô¶¯Ö®ºó£¬»áÑ»·ÕìÌýÖ¸Ïò¶Ë¿ÚÉϵÄÓû§(client)ÇëÇó£¬ÕâЩÇëÇóÔÚmongodÖб»¸Ä×°³ÉÁËmessageÔÚ¸÷¸ö¹¦ÄÜÀàÖд«µÝ¡£µ±Óû§·¢ËÍÒ»¸öcountÖ¸Áî²Ù×÷ʱ£¬Æä»áÔÚquery.cppÖÐÖ´ÐÐÏÂÃæ·½·¨£¨ÒÔcount²éѯָÁîµÄÖ´ÐÐÁ÷³ÌΪÀýÀ´½øÐзÖÎö£©£º
//query.cpp const char *runQuery(Message& m, QueryMessage& q, CurOp& curop, Message &result) { StringBuilder& ss = curop.debug().str; //¹¹ÔìParsedQuery²éѯ¶ÔÏ󣬸öÔÏó°üÀ¨²éѯ¼Ç¼Êý×Ö£¬ÒÔ¼°¼ÇÂ¼Ìø×ªÆ«ÒÆÁ¿µÈÐÅÏ¢£¬
//ÕâЩֵ»áÔÚ·ÃÎÊ´ÅÅ̲éѯʱʹÓã¬Ó÷¨²Î¼û:query.cpp 662ÐеÄvirtual void _init()·½·¨ shared_ptr<ParsedQuery> pq_shared( new ParsedQuery(q) ); ParsedQuery& pq( *pq_shared ); ...... //¶Ô²éѯÃüÁîÅжϣ¬Ö¸ÁîÐÎÈçabc.$cmd.findOne( { ismaster:1 } ) if ( pq.couldBeCommand() ) {//_nsÖаüÀ¨$cmd×Ö·û´® BufBuilder bb; bb.skip(sizeof(QueryResult)); BSONObjBuilder cmdResBuf; //¶Ô²éѯȨÏÞÅжϣ¬²¢Ö´ÐÐÏàÓ¦²éѯָÁî if ( runCommands(ns, jsobj, curop, bb, cmdResBuf, false, queryOptions) ) { ss << " command: "; jsobj.toString( ss ); curop.markCommand(); auto_ptr< QueryResult > qr; qr.reset( (QueryResult *) bb.buf() ); bb.decouple(); qr->setResultFlagsToOk(); qr->len = bb.len(); ss << " reslen:" << bb.len(); qr->setOperation(opReply); qr->cursorId = 0; qr->startingFrom = 0; qr->nReturned = 1; result.setData( qr.release(), true );//ÉèÖ÷µ»Ø½á¹û } else { uasserted(13530, "bad or malformed command request?"); } return 0; } ..... } |
ÉÏÃæ´úÂë¶Ô´«µÝÀ´µÄ²éѯÏûÏ¢QueryMessage£¨ÓйØÏûÏ¢»úÖÆ²Î¼ûÎÒµÄÕâÆªÎÄÕ£©½øÐзÖÎöÖ®ºó£¬Èç¹û·¢ÏÖÆäΪcommandʱ£¬Ö´ÐÐrunCommands·½·¨£º
//query.cpp bool runCommands(const char *ns, BSONObj& jsobj, CurOp& curop, BufBuilder &b,
BSONObjBuilder& anObjBuilder, bool fromRepl, int queryOptions) { try { return _runCommands(ns, jsobj, b, anObjBuilder, fromRepl, queryOptions); } catch ( AssertionException& e ) { e.getInfo().append( anObjBuilder , "assertion" , "assertionCode" ); } curop.debug().str << " assertion "; anObjBuilder.append("errmsg", "db assertion failure"); anObjBuilder.append("ok", 0.0); BSONObj x = anObjBuilder.done(); b.appendBuf((void*) x.objdata(), x.objsize()); return true; } |
½Ó×ÅÆä»áÖ´ÐÐdbcommands.cppÖеÄ_runCommands()·½·¨
//dbcommands.cpp bool _runCommands(const char *ns, BSONObj& _cmdobj, BufBuilder &b,
BSONObjBuilder& anObjBuilder, bool fromRepl, int queryOptions) { cc().curop()->ensureStarted(); string dbname = nsToDatabase( ns );
if( logLevel >= 1 ) log() << "run command " << ns << ' ' << _cmdobj << endl;
const char *p = strchr(ns, '.'); if ( !p ) return false; //ÔٴνøÐÐcmdÅжϣ¬ÒÔÈ·¶¨ÊÇcommand if ( strcmp(p, ".$cmd") != 0 ) return false;
BSONObj jsobj; { BSONElement e = _cmdobj.firstElement(); if ( e.type() == Object && string("query") == e.fieldName() ) { jsobj = e.embeddedObject(); } else { jsobj = _cmdobj; } }
Client& client = cc(); bool ok = false;
BSONElement e = jsobj.firstElement(); //¸ù¾ÝcommandÃû³Æ´ÓmapÖÐÕÒ³öÏàÓ¦µÄcommand¶ÔÏó Command * c = e.type() ? Command::findCommand( e.fieldName() ) : 0;
if ( c ) { //Ö´ÐиöÔÏó ok = execCommand( c , client , queryOptions , ns , jsobj , anObjBuilder , fromRepl ); } else { anObjBuilder.append("errmsg", str::stream() << "no such cmd: " << e.fieldName() ); anObjBuilder.append("bad cmd" , _cmdobj ); }
// switch to bool, but wait a bit longer before switching? // anObjBuilder.append("ok", ok); anObjBuilder.append("ok", ok?1.0:0.0); BSONObj x = anObjBuilder.done(); b.appendBuf((void*) x.objdata(), x.objsize());
return true; }
|
ÉÏÃæ´úÂëÖ÷ÒªÊÇ´ÓmapÖÐÕÒ³öÏàÓ¦µÄcommand¶ÔÏ󣬲¢½«¸Ã¶ÔÏó¼°²Ù×÷ÃüÁî²ÎÊýºÍclient(ÓÃÓÚ»ñÈ¡ÆäÖеÄÈÏÖ¤ÐÅÏ¢£¬ÒÔÈ·¶¨ÆäÖ´ÐÐȨÏÞ)×÷Ϊ²ÎÊý£¬À´µ÷ÓÃ
execCommand·½·¨£º
//dbcommands.cpp
bool execCommand( Command * c ,
Client& client , int queryOptions ,
const char *cmdns, BSONObj& cmdObj ,
BSONObjBuilder& result /*·µ»ØcommandÖ´Ðнá¹û*/,
bool fromRepl ) {
string dbname = nsToDatabase( cmdns );
AuthenticationInfo *ai = client.getAuthenticationInfo();
if( c->adminOnly() /*Èç¹ûÐèÒªÓйÜÀíÌØÈ¨¿ª¿ÉÔËÐÐ*/
&& c->localHostOnlyIfNoAuth( cmdObj ) /*Ҫô±»ÑéÖ¤£¬ÒªÃ´Ö»ÔËÐÐÔÚ±¾µØ½Ó¿Ú*/
&& noauth && !ai->isLocalHost ) {//δÈÏÖ¤ ÇÒ ²»ÊÇÔÚ±¾µØÔËÐÐ
result.append( "errmsg" ,
"unauthorized: this command must run from localhost when running db without auth" );
log() << "command denied: " << cmdObj.toString() << endl;
return false;
}
if ( c->adminOnly() && ! fromRepl && dbname != "admin" ) {
result.append( "errmsg" , "access denied; use admin db" );
log() << "command denied: " << cmdObj.toString() << endl;
return false;
}
if ( cmdObj["help"].trueValue() ) {
stringstream ss;
ss << "help for: " << c->name << " ";
c->help( ss );
result.append( "help" , ss.str() );
result.append( "lockType" , c->locktype() );
return true;
}
bool canRunHere =
isMaster( dbname.c_str() ) /*ÈçΪmaster¿â*/||
c->slaveOk() /*Èç¹ûreplication pair µÄslaves¿ÉÒÔÔËÐÐÃüÁî*/||
( c->slaveOverrideOk() && ( queryOptions & QueryOption_SlaveOk ) ) ||
fromRepl;
if ( ! canRunHere ) {
result.append( "errmsg" , "not master" );
return false;
}
if ( c->adminOnly() )
log( 2 ) << "command: " << cmdObj << endl;
//È統ǰcommandÎÞÐëËøÊ±
if ( c->locktype() == Command::NONE ) {
// we also trust that this won't crash
string errmsg;
//ÔËÐе±Ç°command
int ok = c->run( dbname , cmdObj , errmsg , result , fromRepl );
if ( ! ok )
result.append( "errmsg" , errmsg );
return ok;
}
//ÅжÏÖ´Ðе±Ç°commandÊÇ·ñÐèÒª'Ð´Ëø'(ÿ¸öcommand×ÓÀà¶¼ÓиÃÊôÐÔ)£¬Ã¶¾Ù¶¨ÒåÈçÏÂ(command.h)£º
//enum LockType { READ = -1/*¶Á*/ , NONE = 0 /*ÎÞËø*/, WRITE = 1 /*д*/};
bool needWriteLock = c->locktype() == Command::WRITE;
if ( ! needWriteLock ) {
assert( ! c->logTheOp() );
}
mongolock lk( needWriteLock );//ÉùÃ÷Ëø¶ÔÏó
Client::Context ctx( dbname , dbpath , &lk , c->requiresAuth() );
try {
string errmsg;
//ÔËÐе±Ç°command(±¾ÎÄÖÐÌáµ½µÄcountÃüÁî)
if ( ! c->run(dbname, cmdObj, errmsg, result, fromRepl ) ) {
result.append( "errmsg" , errmsg );
return false;
}
}
catch ( DBException& e ) {
stringstream ss;
ss << "exception: " << e.what();
result.append( "errmsg" , ss.str() );
result.append( "code" , e.getCode() );
return false;
}
if ( c->logTheOp() && ! fromRepl ) {
logOp("c", cmdns, cmdObj);
}
return true;
} |
µ½ÕâÀÁ÷³Ì»ù±¾¾ÍÖ´ÐÐÍê±ÏÁË£¬Ö®ºóËü»á½«½á¹û´«¸øresult£¨Æä´«²ÎΪÒýÓÃÀàÐÍ£¬¼´£º"&
result"·½Ê½£©.
×îºóÓÃÒ»ÕÅʱ¼äÐòÀ´´óÌ廨¹ËÒ»ÏÂÕâÒ»Á÷³Ì£º

ºÃÁË£¬½ñÌìµÄÄÚÈݵ½ÕâÀï¾Í¸æÒ»¶ÎÂäÁË¡£
|