void AsyncMockStreamFactory::MockStream::simulateServer( rpc::Protocol proto, const stdx::function<RemoteCommandResponse(RemoteCommandRequest)> replyFunc) { std::exception_ptr ex; uint32_t messageId = 0; RemoteCommandResponse resp; { WriteEvent write{this}; std::vector<uint8_t> messageData = popWrite(); Message msg(messageData.data(), false); auto parsedRequest = rpc::makeRequest(&msg); ASSERT(parsedRequest->getProtocol() == proto); RemoteCommandRequest rcr(target(), *parsedRequest); messageId = msg.header().getId(); // So we can allow ASSERTs in replyFunc, we capture any exceptions, but rethrow // them later to prevent deadlock try { resp = replyFunc(std::move(rcr)); } catch (...) { ex = std::current_exception(); } } auto replyBuilder = rpc::makeReplyBuilder(proto); replyBuilder->setMetadata(resp.metadata); replyBuilder->setCommandReply(resp.data); auto replyMsg = replyBuilder->done(); replyMsg->header().setResponseTo(messageId); { // The first read will be for the header. ReadEvent read{this}; auto hdrBytes = reinterpret_cast<const uint8_t*>(replyMsg->header().view2ptr()); pushRead({hdrBytes, hdrBytes + sizeof(MSGHEADER::Value)}); } { // The second read will be for the message data. ReadEvent read{this}; auto dataBytes = reinterpret_cast<const uint8_t*>(replyMsg->buf()); auto pastHeader = dataBytes; std::advance(pastHeader, sizeof(MSGHEADER::Value)); pushRead({pastHeader, dataBytes + static_cast<std::size_t>(replyMsg->size())}); } if (ex) { // Rethrow ASSERTS after the NIA completes it's Write-Read-Read sequence. std::rethrow_exception(ex); } }
MockRemoteDBServer::MockRemoteDBServer(const string& hostAndPort) : _isRunning(true), _hostAndPort(hostAndPort), _delayMilliSec(0), _cmdCount(0), _queryCount(0), _instanceID(0) { insert(IdentityNS, BSON(HostField(hostAndPort)), 0); setCommandReply("dbStats", BSON(HostField(hostAndPort))); }
void MockRemoteDBServer::setCommandReply(const string& cmdName, const mongo::BSONObj& replyObj) { vector<BSONObj> replySequence; replySequence.push_back(replyObj); setCommandReply(cmdName, replySequence); }