DBClientBase* ConnectionString::connect( std::string& errmsg, double socketTimeout ) const { switch ( _type ) { case MASTER: { DBClientConnection * c = new DBClientConnection(true); c->setSoTimeout( socketTimeout ); LOG(1) << "creating new connection to:" << _servers[0]; if ( ! c->connect( _servers[0] , errmsg ) ) { delete c; return 0; } LOG(1) << "connected connection!"; return c; } case PAIR: case SET: { DBClientReplicaSet * set = new DBClientReplicaSet( _setName , _servers , socketTimeout ); if( ! set->connect() ) { delete set; errmsg = "connect failed to replica set "; errmsg += toString(); return 0; } return set; } case SYNC: { // TODO , don't copy std::list<HostAndPort> l; for ( unsigned i=0; i<_servers.size(); i++ ) l.push_back( _servers[i] ); SyncClusterConnection* c = new SyncClusterConnection( l, socketTimeout ); return c; } case CUSTOM: { // Lock in case other things are modifying this at the same time boost::lock_guard<boost::mutex> lk( _connectHookMutex ); // Allow the replacement of connections with other connections - useful for testing. uassert( 16335, "custom connection to " + this->toString() + " specified with no connection hook", _connectHook ); // Double-checked lock, since this will never be active during normal operation DBClientBase* replacementConn = _connectHook->connect( *this, errmsg, socketTimeout ); log() << "replacing connection to " << this->toString() << " with " << ( replacementConn ? replacementConn->getServerAddress() : "(empty)" ); return replacementConn; } case INVALID: throw UserException( 13421 , "trying to connect to invalid ConnectionString" ); break; } verify( 0 ); return 0; }
inline void kill_wrapper( ProcessId pid, int sig, int port, const BSONObj& opt ) { #ifdef _WIN32 if (sig == SIGKILL || port == 0) { verify( registry._handles.count(pid) ); TerminateProcess(registry._handles[pid], 1); // returns failure for "zombie" processes. return; } std::string eventName = getShutdownSignalName(pid.asUInt32()); HANDLE event = OpenEventA(EVENT_MODIFY_STATE, FALSE, eventName.c_str()); if (event == NULL) { int gle = GetLastError(); if (gle != ERROR_FILE_NOT_FOUND) { warning() << "kill_wrapper OpenEvent failed: " << errnoWithDescription(); } else { log() << "kill_wrapper OpenEvent failed to open event to the process " << pid.asUInt32() << ". It has likely died already or server is running an older version." << " Attempting to shutdown through admin command."; // Back-off to the old way of shutting down the server on Windows, in case we // are managing a pre-2.6.0rc0 service, which did not have the event. // try { DBClientConnection conn; conn.connect("127.0.0.1:" + BSONObjBuilder::numStr(port)); BSONElement authObj = opt["auth"]; if (!authObj.eoo()){ string errMsg; conn.auth("admin", authObj["user"].String(), authObj["pwd"].String(), errMsg); if (!errMsg.empty()) { cout << "Failed to authenticate before shutdown: " << errMsg << endl; } } BSONObj info; BSONObjBuilder b; b.append("shutdown", 1); b.append("force", 1); conn.runCommand("admin", b.done(), info); } catch (...) { // Do nothing. This command never returns data to the client and the driver // doesn't like that. // } } return; } ON_BLOCK_EXIT(CloseHandle, event); bool result = SetEvent(event); if (!result) { error() << "kill_wrapper SetEvent failed: " << errnoWithDescription(); return; } #else int x = kill( pid.toNative(), sig ); if ( x ) { if ( errno == ESRCH ) { } else { log() << "killFailed: " << errnoWithDescription() << endl; verify( x == 0 ); } } #endif }
int main(int argc, char *argv[]) { try { cout << "mongoperf" << endl; if( argc > 1 ) { cout << "\n" "usage:\n" "\n" " mongoperf < myjsonconfigfile\n" "\n" " {\n" " nThreads:<n>, // number of threads (default 1)\n" " fileSizeMB:<n>, // test file size (default 1MB)\n" " sleepMicros:<n>, // pause for sleepMicros/nThreads between each operation (default 0)\n" " mmf:<bool>, // if true do i/o's via memory mapped files (default false)\n" " r:<bool>, // do reads (default false)\n" " w:<bool>, // do writes (default false)\n" " syncDelay:<n> // secs between fsyncs, like --syncdelay in mongod. (default 0/never)\n" " }\n" "\n" "mongoperf is a performance testing tool. the initial tests are of disk subsystem performance; \n" " tests of mongos and mongod will be added later.\n" "most fields are optional.\n" "non-mmf io is direct io (no caching). use a large file size to test making the heads\n" " move significantly and to avoid i/o coalescing\n" "mmf io uses caching (the file system cache).\n" "\n" << endl; return EXIT_SUCCESS; } cout << "use -h for help" << endl; char input[1024]; memset(input, 0, sizeof(input)); cin.read(input, 1000); if( *input == 0 ) { cout << "error no options found on stdin for mongoperf" << endl; return EXIT_FAILURE; } string s = input; mongoutils::str::stripTrailing(s, " \n\r\0x1a"); try { options = fromjson(s); } catch(...) { cout << "couldn't parse json options. input was:\n|" << s << "|" << endl; return EXIT_FAILURE; } cout << "parsed options:\n" << options.toString() << endl; go(); #if 0 cout << "connecting to localhost..." << endl; DBClientConnection c; c.connect("localhost"); cout << "connected ok" << endl; unsigned long long count = c.count("test.foo"); cout << "count of exiting documents in collection test.foo : " << count << endl; bo o = BSON( "hello" << "world" ); c.insert("test.foo", o); string e = c.getLastError(); if( !e.empty() ) { cout << "insert #1 failed: " << e << endl; } // make an index with a unique key constraint c.ensureIndex("test.foo", BSON("hello"<<1), /*unique*/true); c.insert("test.foo", o); // will cause a dup key error on "hello" field cout << "we expect a dup key error here:" << endl; cout << " " << c.getLastErrorDetailed().toString() << endl; #endif } catch(DBException& e) { cout << "caught DBException " << e.toString() << endl; return EXIT_FAILURE; } return EXIT_SUCCESS; }
int main( int argc, const char **argv ) { const char *port = "27017"; if ( argc != 1 ) { if ( argc != 3 ) { std::cout << "need to pass port as second param" << endl; return EXIT_FAILURE; } port = argv[ 2 ]; } DBClientConnection conn; string errmsg; if ( ! conn.connect( string( "127.0.0.1:" ) + port , errmsg ) ) { cout << "couldn't connect : " << errmsg << endl; return EXIT_FAILURE; } const char * ns = "test.test1"; conn.dropCollection(ns); // clean up old data from any previous tests conn.remove( ns, BSONObj() ); verify( conn.findOne( ns , BSONObj() ).isEmpty() ); // test insert conn.insert( ns ,BSON( "name" << "eliot" << "num" << 1 ) ); verify( ! conn.findOne( ns , BSONObj() ).isEmpty() ); // test remove conn.remove( ns, BSONObj() ); verify( conn.findOne( ns , BSONObj() ).isEmpty() ); // insert, findOne testing conn.insert( ns , BSON( "name" << "eliot" << "num" << 1 ) ); { BSONObj res = conn.findOne( ns , BSONObj() ); verify( strstr( res.getStringField( "name" ) , "eliot" ) ); verify( ! strstr( res.getStringField( "name2" ) , "eliot" ) ); verify( 1 == res.getIntField( "num" ) ); } // cursor conn.insert( ns ,BSON( "name" << "sara" << "num" << 2 ) ); { auto_ptr<DBClientCursor> cursor = conn.query( ns , BSONObj() ); int count = 0; while ( cursor->more() ) { count++; BSONObj obj = cursor->next(); } verify( count == 2 ); } { auto_ptr<DBClientCursor> cursor = conn.query( ns , BSON( "num" << 1 ) ); int count = 0; while ( cursor->more() ) { count++; BSONObj obj = cursor->next(); } verify( count == 1 ); } { auto_ptr<DBClientCursor> cursor = conn.query( ns , BSON( "num" << 3 ) ); int count = 0; while ( cursor->more() ) { count++; BSONObj obj = cursor->next(); } verify( count == 0 ); } // update { BSONObj res = conn.findOne( ns , BSONObjBuilder().append( "name" , "eliot" ).obj() ); verify( ! strstr( res.getStringField( "name2" ) , "eliot" ) ); BSONObj after = BSONObjBuilder().appendElements( res ).append( "name2" , "h" ).obj(); conn.update( ns , BSONObjBuilder().append( "name" , "eliot2" ).obj() , after ); res = conn.findOne( ns , BSONObjBuilder().append( "name" , "eliot" ).obj() ); verify( ! strstr( res.getStringField( "name2" ) , "eliot" ) ); verify( conn.findOne( ns , BSONObjBuilder().append( "name" , "eliot2" ).obj() ).isEmpty() ); conn.update( ns , BSONObjBuilder().append( "name" , "eliot" ).obj() , after ); res = conn.findOne( ns , BSONObjBuilder().append( "name" , "eliot" ).obj() ); verify( strstr( res.getStringField( "name" ) , "eliot" ) ); verify( strstr( res.getStringField( "name2" ) , "h" ) ); verify( conn.findOne( ns , BSONObjBuilder().append( "name" , "eliot2" ).obj() ).isEmpty() ); // upsert conn.update( ns , BSONObjBuilder().append( "name" , "eliot2" ).obj() , after , 1 ); verify( ! conn.findOne( ns , BSONObjBuilder().append( "name" , "eliot" ).obj() ).isEmpty() ); } { // ensure index verify( conn.ensureIndex( ns , BSON( "name" << 1 ) ) ); verify( ! conn.ensureIndex( ns , BSON( "name" << 1 ) ) ); } { // 5 second TTL index const char * ttlns = "test.ttltest1"; conn.dropCollection( ttlns ); { mongo::BSONObjBuilder b; b.appendTimeT("ttltime", time(0)); b.append("name", "foo"); conn.insert(ttlns, b.obj()); } conn.ensureIndex(ttlns, BSON("ttltime" << 1), false, false, "", true, false, -1, 5); verify(!conn.findOne(ttlns, BSONObjBuilder().append("name", "foo").obj()).isEmpty()); // Sleep 66 seconds, 60 seconds for the TTL loop, 5 seconds for the TTL and 1 to ensure sleepsecs(66); verify(conn.findOne(ttlns, BSONObjBuilder().append("name", "foo").obj()).isEmpty()); } { // hint related tests // tokumx doesn't reorder documents just because you updated one, what even is that verify( conn.findOne(ns, "{}")["name"].str() == "eliot" ); verify( conn.findOne(ns, "{ name : 'sara' }")["name"].str() == "sara" ); verify( conn.getLastError() == "" ); // nonexistent index test bool asserted = false; try { conn.findOne(ns, Query("{name:\"eliot\"}").hint("{foo:1}")); } catch ( ... ) { asserted = true; } verify( asserted ); //existing index verify( conn.findOne(ns, Query("{name:'eliot'}").hint("{name:1}")).hasElement("name") ); // run validate verify( conn.validate( ns ) ); } { // timestamp test const char * tsns = "test.tstest1"; conn.dropCollection( tsns ); { mongo::BSONObjBuilder b; b.appendTimestamp( "ts" ); conn.insert( tsns , b.obj() ); } mongo::BSONObj out = conn.findOne( tsns , mongo::BSONObj() ); Date_t oldTime = out["ts"].timestampTime(); unsigned int oldInc = out["ts"].timestampInc(); { mongo::BSONObjBuilder b1; b1.append( out["_id"] ); mongo::BSONObjBuilder b2; b2.append( out["_id"] ); b2.appendTimestamp( "ts" ); conn.update( tsns , b1.obj() , b2.obj() ); } BSONObj found = conn.findOne( tsns , mongo::BSONObj() ); cout << "old: " << out << "\nnew: " << found << endl; verify( ( oldTime < found["ts"].timestampTime() ) || ( oldTime == found["ts"].timestampTime() && oldInc < found["ts"].timestampInc() ) ); } { // check that killcursors doesn't affect last error verify( conn.getLastError().empty() ); BufBuilder b; b.appendNum( (int)0 ); // reserved b.appendNum( (int)-1 ); // invalid # of cursors triggers exception b.appendNum( (int)-1 ); // bogus cursor id Message m; m.setData( dbKillCursors, b.buf(), b.len() ); // say() is protected in DBClientConnection, so get superclass static_cast< DBConnector* >( &conn )->say( m ); verify( conn.getLastError().empty() ); } { list<string> l = conn.getDatabaseNames(); for ( list<string>::iterator i = l.begin(); i != l.end(); i++ ) { cout << "db name : " << *i << endl; } l = conn.getCollectionNames( "test" ); for ( list<string>::iterator i = l.begin(); i != l.end(); i++ ) { cout << "coll name : " << *i << endl; } } { //Map Reduce (this mostly just tests that it compiles with all output types) const string ns = "test.mr"; conn.insert(ns, BSON("a" << 1)); conn.insert(ns, BSON("a" << 1)); const char* map = "function() { emit(this.a, 1); }"; const char* reduce = "function(key, values) { return Array.sum(values); }"; const string outcoll = ns + ".out"; BSONObj out; out = conn.mapreduce(ns, map, reduce, BSONObj()); // default to inline //MONGO_PRINT(out); out = conn.mapreduce(ns, map, reduce, BSONObj(), outcoll); //MONGO_PRINT(out); out = conn.mapreduce(ns, map, reduce, BSONObj(), outcoll.c_str()); //MONGO_PRINT(out); out = conn.mapreduce(ns, map, reduce, BSONObj(), BSON("reduce" << outcoll)); //MONGO_PRINT(out); } { // test timeouts DBClientConnection conn( true , 0 , 2 ); if ( ! conn.connect( string( "127.0.0.1:" ) + port , errmsg ) ) { cout << "couldn't connect : " << errmsg << endl; throw -11; } conn.insert( "test.totest" , BSON( "x" << 1 ) ); BSONObj res; bool gotError = false; verify( conn.eval( "test" , "return db.totest.findOne().x" , res ) ); try { conn.eval( "test" , "sleep(5000); return db.totest.findOne().x" , res ); } catch ( std::exception& e ) { gotError = true; log() << e.what() << endl; } verify( gotError ); // sleep so the server isn't locked anymore sleepsecs( 4 ); verify( conn.eval( "test" , "return db.totest.findOne().x" , res ) ); } cout << "client test finished!" << endl; return EXIT_SUCCESS; }
int Tool::main( int argc , char ** argv ){ static StaticObserver staticObserver; cmdLine.prealloc = false; boost::filesystem::path::default_name_check( boost::filesystem::no_check ); _name = argv[0]; /* using the same style as db.cpp */ int command_line_style = (((po::command_line_style::unix_style ^ po::command_line_style::allow_guessing) | po::command_line_style::allow_long_disguise) ^ po::command_line_style::allow_sticky); try { po::options_description all_options("all options"); all_options.add(*_options).add(*_hidden_options); po::store( po::command_line_parser( argc , argv ). options(all_options). positional( _positonalOptions ). style(command_line_style).run() , _params ); po::notify( _params ); } catch (po::error &e) { cerr << "ERROR: " << e.what() << endl << endl; printHelp(cerr); return EXIT_BADOPTIONS; } if ( _params.count( "help" ) ){ printHelp(cerr); return 0; } if ( _params.count( "verbose" ) ) { logLevel = 1; } for (string s = "vv"; s.length() <= 10; s.append("v")) { if (_params.count(s)) { logLevel = s.length(); } } bool useDirectClient = hasParam( "dbpath" ); if ( ! useDirectClient ) { _host = "127.0.0.1"; if ( _params.count( "host" ) ) _host = _params["host"].as<string>(); if ( _host.find( "," ) == string::npos ){ DBClientConnection * c = new DBClientConnection(); _conn = c; string errmsg; if ( ! c->connect( _host , errmsg ) ){ cerr << "couldn't connect to [" << _host << "] " << errmsg << endl; return -1; } } else { log(1) << "using pairing" << endl; DBClientPaired * c = new DBClientPaired(); _paired = true; _conn = c; if ( ! c->connect( _host ) ){ cerr << "couldn't connect to paired server: " << _host << endl; return -1; } } cerr << "connected to: " << _host << endl; } else { if ( _params.count( "directoryperdb" ) ) { directoryperdb = true; } assert( lastError.get( true ) ); Client::initThread("tools"); _conn = new DBDirectClient(); _host = "DIRECT"; static string myDbpath = getParam( "dbpath" ); dbpath = myDbpath.c_str(); try { acquirePathLock(); } catch ( DBException& e ){ cerr << endl << "If you are running a mongod on the same " "path you should connect to that instead of direct data " "file access" << endl << endl; dbexit( EXIT_CLEAN ); return -1; } theFileAllocator().start(); } if ( _params.count( "db" ) ) _db = _params["db"].as<string>(); if ( _params.count( "collection" ) ) _coll = _params["collection"].as<string>(); if ( _params.count( "username" ) ) _username = _params["username"].as<string>(); if ( _params.count( "password" ) ) _password = _params["password"].as<string>(); int ret = -1; try { ret = run(); } catch ( DBException& e ){ cerr << "assertion: " << e.toString() << endl; ret = -1; } if ( currentClient.get() ) currentClient->shutdown(); if ( useDirectClient ) dbexit( EXIT_CLEAN ); return ret; }
FXtoBSON::FXtoBSON(const string &file_, const string &formatt_, const string &pair, const string & source, const char &sep_): file(file_), cols(0), rows(0), formatt(formatt_), sep(sep_){ db = string("FOREX.") + source + string(".") + pair; dbH = db + string(".") + string("Hour"); dbD = db + string(".") + string("Day"); dbM = db + string(".") + string("Month"); dbY = db + string(".") + string("Year"); Hour.setZero(60, 5); Day.setZero(24, 5); Month.setZero(31, 5); Year.setZero(12, 5); mongo::client::initialize(); DBClientConnection c; c.connect("localhost"); string dropheader, line, checkEOF; headers(); getTime0(); csvFile.open(file.c_str()); getline(csvFile, dropheader); projId = BSON("_id" << 1); while(getline(csvFile, line)){ if(!line.empty()){ BSONObj QUOTE = headerQuote(line, time1); BSONObj document = buildQuoteAt(time1.tm_min, QUOTE); addMinToDB(document, c); if(time1.tm_hour == time0.tm_hour && time1.tm_mday == time0.tm_mday && time1.tm_mon == time0.tm_mon && time1.tm_year == time0.tm_year) hourToEigen(time1.tm_min, QUOTE); else { if(time1.tm_hour != time0.tm_hour){ aggregateToDB('h', c); hourToEigen(time1.tm_min, QUOTE); updateDoc('d', c); } if(time1.tm_mday != time0.tm_mday){ aggregateToDB('d', c); hourToEigen(time1.tm_min, QUOTE); updateDoc('m', c); } if(time1.tm_mon != time0.tm_mon){ aggregateToDB('m', c); hourToEigen(time1.tm_min, QUOTE); updateDoc('y', c); } if(time1.tm_year != time0.tm_year){ aggregateToDB('y', c); hourToEigen(time1.tm_min, QUOTE); } } if(csvFile.peek() == -1){ time0 = time1; aggregateToDB('h', c); aggregateToDB('d', c); updateDoc('d', c); aggregateToDB('m', c); updateDoc('m', c); aggregateToDB('y', c); updateDoc('y', c); } time0 = time1; } // if end } // While end; csvFile.close(); }
bool HostAndPort::isSelf() const { int _p = port(); int p = _p == -1 ? CmdLine::DefaultDBPort : _p; if( p != cmdLine.port ) { // shortcut - ports have to match at the very least return false; } string host = str::stream() << this->host() << ":" << p; { // check cache for this host // debatably something _could_ change, but I'm not sure right now (erh 10/14/2010) scoped_lock lk( isSelfCommand._cacheLock ); map<string,bool>::const_iterator i = isSelfCommand._cache.find( host ); if ( i != isSelfCommand._cache.end() ) return i->second; } #if !defined(_WIN32) && !defined(__sunos__) // on linux and os x we can do a quick check for an ip match const vector<string> myaddrs = getMyAddrs(); const vector<string> addrs = getAllIPs(_host); for (vector<string>::const_iterator i=myaddrs.begin(), iend=myaddrs.end(); i!=iend; ++i) { for (vector<string>::const_iterator j=addrs.begin(), jend=addrs.end(); j!=jend; ++j) { string a = *i; string b = *j; if ( a == b || ( str::startsWith( a , "127." ) && str::startsWith( b , "127." ) ) // 127. is all loopback ) { // add to cache scoped_lock lk( isSelfCommand._cacheLock ); isSelfCommand._cache[host] = true; return true; } } } #endif if ( ! Listener::getTimeTracker() ) { // this ensures we are actually running a server // this may return true later, so may want to retry return false; } try { isSelfCommand.init(); DBClientConnection conn; string errmsg; if ( ! conn.connect( host , errmsg ) ) { // should this go in the cache? return false; } if (AuthorizationManager::isAuthEnabled() && !cmdLine.keyFile.empty() ) { if (!authenticateInternalUser(&conn)) { return false; } } BSONObj out; bool ok = conn.simpleCommand( "admin" , &out , "_isSelf" ); bool me = ok && out["id"].type() == jstOID && isSelfCommand._id == out["id"].OID(); // add to cache scoped_lock lk( isSelfCommand._cacheLock ); isSelfCommand._cache[host] = me; return me; } catch ( std::exception& e ) { warning() << "could't check isSelf (" << host << ") " << e.what() << endl; } return false; }
virtual void onLoad() { mongo::client::initialize(); db.connect("localhost"); }
void run() { DBClientConnection c; c.connect("localhost"); }
int mongo::Tool::main( int argc , char ** argv ){ boost::filesystem::path::default_name_check( boost::filesystem::no_check ); _name = argv[0]; /* using the same style as db.cpp */ int command_line_style = (((po::command_line_style::unix_style ^ po::command_line_style::allow_guessing) | po::command_line_style::allow_long_disguise) ^ po::command_line_style::allow_sticky); try { po::options_description all_options("all options"); all_options.add(*_options).add(*_hidden_options); po::store( po::command_line_parser( argc , argv ). options(all_options). positional( _positonalOptions ). style(command_line_style).run() , _params ); po::notify( _params ); } catch (po::error &e) { cout << "ERROR: " << e.what() << endl << endl; printHelp(cout); return EXIT_BADOPTIONS; } if ( _params.count( "help" ) ){ printHelp(cerr); return 0; } if ( _params.count( "verbose" ) ) { logLevel = 1; } for (string s = "vv"; s.length() <= 10; s.append("v")) { if (_params.count(s)) { logLevel = s.length(); } } if ( ! hasParam( "dbpath" ) ) { _host = "127.0.0.1"; if ( _params.count( "host" ) ) _host = _params["host"].as<string>(); if ( _host.find( "," ) == string::npos ){ DBClientConnection * c = new DBClientConnection(); _conn = c; string errmsg; if ( ! c->connect( _host , errmsg ) ){ cerr << "couldn't connect to [" << _host << "] " << errmsg << endl; return -1; } } else { DBClientPaired * c = new DBClientPaired(); _paired = true; _conn = c; if ( ! c->connect( _host ) ){ cerr << "couldn't connect to paired server: " << _host << endl; return -1; } } cerr << "connected to: " << _host << endl; } else { _conn = new DBDirectClient(); _host = "DIRECT"; static string myDbpath = getParam( "dbpath" ); mongo::dbpath = myDbpath.c_str(); mongo::acquirePathLock(); theFileAllocator().start(); } if ( _params.count( "db" ) ) _db = _params["db"].as<string>(); if ( _params.count( "collection" ) ) _coll = _params["collection"].as<string>(); if ( _params.count( "username" ) ) _username = _params["username"].as<string>(); if ( _params.count( "password" ) ) _password = _params["password"].as<string>(); try { return run(); } catch ( DBException& e ){ cerr << "assertion: " << e.toString() << endl; return -1; } }
void operator()() const { DBClientConnection dest; string errmsg; Timer connectTimer; while (!dest.connect(HostAndPort(mongoBridgeGlobalParams.destUri), errmsg)) { // If we can't connect for the configured timeout, give up // if (connectTimer.seconds() >= mongoBridgeGlobalParams.connectTimeoutSec) { cout << "Unable to establish connection from " << mp_.psock->remoteString() << " to " << mongoBridgeGlobalParams.destUri << " after " << connectTimer.seconds() << " seconds. Giving up." << endl; mp_.shutdown(); return; } sleepmillis(500); } Message m; while( 1 ) { try { m.reset(); if ( !mp_.recv( m ) ) { cout << "end connection " << mp_.psock->remoteString() << endl; mp_.shutdown(); break; } sleepmillis(mongoBridgeGlobalParams.delay); int oldId = m.header().getId(); if ( m.operation() == dbQuery || m.operation() == dbMsg || m.operation() == dbGetMore ) { bool exhaust = false; if ( m.operation() == dbQuery ) { DbMessage d( m ); QueryMessage q( d ); exhaust = q.queryOptions & QueryOption_Exhaust; } Message response; dest.port().call( m, response ); // nothing to reply with? if ( response.empty() ) cleanup(0); mp_.reply( m, response, oldId ); while ( exhaust ) { MsgData::View header = response.header(); QueryResult::View qr = header.view2ptr(); if ( qr.getCursorId() ) { response.reset(); dest.port().recv( response ); mp_.reply( m, response ); // m argument is ignored anyway } else { exhaust = false; } } } else { dest.port().say( m, oldId ); } } catch ( ... ) { log() << "caught exception in Forwarder, continuing" << endl; } } }