virtual void process( Message& m , AbstractMessagingPort* port , LastError * le) { while ( true ) { if ( inShutdown() ) { log() << "got request after shutdown()" << endl; break; } lastError.startRequest( m , le ); DbResponse dbresponse; try { assembleResponse( m, dbresponse, port->remote() ); } catch ( const ClockSkewException & ) { log() << "ClockSkewException - shutting down" << endl; exitCleanly( EXIT_CLOCK_SKEW ); } if ( dbresponse.response ) { port->reply(m, *dbresponse.response, dbresponse.responseTo); if( dbresponse.exhaust ) { MsgData *header = dbresponse.response->header(); QueryResult *qr = (QueryResult *) header; long long cursorid = qr->cursorId; if( cursorid ) { verify( dbresponse.exhaust && *dbresponse.exhaust != 0 ); string ns = dbresponse.exhaust; // before reset() free's it... m.reset(); BufBuilder b(512); b.appendNum((int) 0 /*size set later in appendData()*/); b.appendNum(header->id); b.appendNum(header->responseTo); b.appendNum((int) dbGetMore); b.appendNum((int) 0); b.appendStr(ns); b.appendNum((int) 0); // ntoreturn b.appendNum(cursorid); m.appendData(b.buf(), b.len()); b.decouple(); DEV log() << "exhaust=true sending more" << endl; beNice(); continue; // this goes back to top loop } } } break; } }
virtual void process( Message& m , AbstractMessagingPort* port , LastError * le) { OperationContextImpl txn; while ( true ) { if ( inShutdown() ) { log() << "got request after shutdown()" << endl; break; } lastError.startRequest( m , le ); DbResponse dbresponse; assembleResponse( &txn, m, dbresponse, port->remote() ); if ( dbresponse.response ) { port->reply(m, *dbresponse.response, dbresponse.responseTo); if( dbresponse.exhaustNS.size() > 0 ) { MsgData *header = dbresponse.response->header(); QueryResult *qr = (QueryResult *) header; long long cursorid = qr->cursorId; if( cursorid ) { verify( dbresponse.exhaustNS.size() && dbresponse.exhaustNS[0] ); string ns = dbresponse.exhaustNS; // before reset() free's it... m.reset(); BufBuilder b(512); b.appendNum((int) 0 /*size set later in appendData()*/); b.appendNum(header->id); b.appendNum(header->responseTo); b.appendNum((int) dbGetMore); b.appendNum((int) 0); b.appendStr(ns); b.appendNum((int) 0); // ntoreturn b.appendNum(cursorid); m.appendData(b.buf(), b.len()); b.decouple(); DEV log() << "exhaust=true sending more" << endl; beNice(); continue; // this goes back to top loop } } } break; } }
/* we create one thread for each connection from an app server database. app server will open a pool of threads. todo: one day, asio... */ void connThread( MessagingPort * inPort ) { TicketHolderReleaser connTicketReleaser( &connTicketHolder ); /* todo: move to Client object */ LastError *le = new LastError(); lastError.reset(le); inPort->_logLevel = 1; auto_ptr<MessagingPort> dbMsgPort( inPort ); Client& c = Client::initThread("conn", inPort); try { c.getAuthenticationInfo()->isLocalHost = dbMsgPort->farEnd.isLocalHost(); Message m; while ( 1 ) { if ( !dbMsgPort->recv(m) ) { if( !cmdLine.quiet ) log() << "end connection " << dbMsgPort->farEnd.toString() << endl; dbMsgPort->shutdown(); break; } sendmore: if ( inShutdown() ) { log() << "got request after shutdown()" << endl; break; } lastError.startRequest( m , le ); DbResponse dbresponse; if ( !assembleResponse( m, dbresponse, dbMsgPort->farEnd ) ) { log() << curTimeMillis() % 10000 << " end msg " << dbMsgPort->farEnd.toString() << endl; /* todo: we may not wish to allow this, even on localhost: very low priv accounts could stop us. */ if ( dbMsgPort->farEnd.isLocalHost() ) { dbMsgPort->shutdown(); sleepmillis(50); problem() << "exiting end msg" << endl; dbexit(EXIT_CLEAN); } else { log() << " (not from localhost, ignoring end msg)" << endl; } } if ( dbresponse.response ) { dbMsgPort->reply(m, *dbresponse.response, dbresponse.responseTo); if( dbresponse.exhaust ) { MsgData *header = dbresponse.response->header(); QueryResult *qr = (QueryResult *) header; long long cursorid = qr->cursorId; if( cursorid ) { assert( dbresponse.exhaust && *dbresponse.exhaust != 0 ); string ns = dbresponse.exhaust; // before reset() free's it... m.reset(); BufBuilder b(512); b.appendNum((int) 0 /*size set later in appendData()*/); b.appendNum(header->id); b.appendNum(header->responseTo); b.appendNum((int) dbGetMore); b.appendNum((int) 0); b.appendStr(ns); b.appendNum((int) 0); // ntoreturn b.appendNum(cursorid); m.appendData(b.buf(), b.len()); b.decouple(); DEV log() << "exhaust=true sending more" << endl; beNice(); goto sendmore; } } } m.reset(); } } catch ( AssertionException& e ) { log() << "AssertionException in connThread, closing client connection" << endl; log() << ' ' << e.what() << endl; dbMsgPort->shutdown(); } catch ( SocketException& ) { problem() << "SocketException in connThread, closing client connection" << endl; dbMsgPort->shutdown(); } catch ( const ClockSkewException & ) { exitCleanly( EXIT_CLOCK_SKEW ); } catch ( std::exception &e ) { problem() << "Uncaught std::exception: " << e.what() << ", terminating" << endl; dbexit( EXIT_UNCAUGHT ); } catch ( ... ) { problem() << "Uncaught exception, terminating" << endl; dbexit( EXIT_UNCAUGHT ); } // thread ending... { Client * c = currentClient.get(); if( c ) c->shutdown(); } globalScriptEngine->threadDone(); }