std::unique_ptr<Message> LegacyReplyBuilder::done() { invariant(_state == State::kOutputDocs); BSONObj reply = uassertStatusOK(rpc::downconvertReplyMetadata(_commandReply, _metadata)); BufBuilder bufBuilder; bufBuilder.skip(sizeof(QueryResult::Value)); if (_allowAddingOutputDocs) { BSONObjBuilder topBuilder(bufBuilder); for (const auto& el : reply) { if (kCursorTag != el.fieldNameStringData()) { topBuilder.append(el); continue; } invariant(el.isABSONObj()); BSONObjBuilder curBuilder(topBuilder.subobjStart(kCursorTag)); for (const auto& insideEl : el.Obj()) { if (kFirstBatchTag != insideEl.fieldNameStringData()) { curBuilder.append(insideEl); continue; } invariant(insideEl.isABSONObj()); BSONArrayBuilder arrBuilder(curBuilder.subarrayStart(kFirstBatchTag)); for (const auto& doc : _outputDocs) { arrBuilder.append(doc); } arrBuilder.doneFast(); } curBuilder.doneFast(); } topBuilder.doneFast(); } else { reply.appendSelfToBufBuilder(bufBuilder); } auto msgHeaderSz = static_cast<std::size_t>(MsgData::MsgDataHeaderSize); invariant(static_cast<std::size_t>(bufBuilder.len()) + msgHeaderSz <= mongol::MaxMessageSizeBytes); QueryResult::View qr = bufBuilder.buf(); qr.setResultFlagsToOk(); qr.msgdata().setLen(bufBuilder.len()); qr.msgdata().setOperation(opReply); qr.setCursorId(0); qr.setStartingFrom(0); qr.setNReturned(1); _message->setData(qr.view2ptr(), true); bufBuilder.decouple(); _state = State::kDone; return std::move(_message); }
void DBClientBase::insert( const string & ns , BSONObj obj , int flags) { Message toSend; BufBuilder b; b.appendNum( flags ); b.appendStr( ns ); obj.appendSelfToBufBuilder( b ); toSend.setData( dbInsert , b.buf() , b.len() ); say( toSend ); }
Status CommandReplyBuilder::addOutputDoc(const BSONObj& outputDoc) { invariant(_state == State::kOutputDocs); auto dataSize = static_cast<std::size_t>(outputDoc.objsize()); auto hasSpace = _hasSpaceFor(dataSize); if (!hasSpace.isOK()) { return hasSpace; } outputDoc.appendSelfToBufBuilder(_builder); return Status::OK(); }
void DBClientBase::insert( const string & ns , BSONObj obj ) { Message toSend; BufBuilder b; int opts = 0; b.append( opts ); b.append( ns ); obj.appendSelfToBufBuilder( b ); toSend.setData( dbInsert , b.buf() , b.len() ); say( toSend ); }
void assembleRequest( const string &ns, BSONObj query, int nToReturn, int nToSkip, const BSONObj *fieldsToReturn, int queryOptions, Message &toSend ) { CHECK_OBJECT( query , "assembleRequest query" ); // see query.h for the protocol we are using here. BufBuilder b; int opts = queryOptions; b.append(opts); b.append(ns.c_str()); b.append(nToSkip); b.append(nToReturn); query.appendSelfToBufBuilder(b); if ( fieldsToReturn ) fieldsToReturn->appendSelfToBufBuilder(b); toSend.setData(dbQuery, b.buf(), b.len()); }
LegacyReply::LegacyReply(const Message* message) : _message(std::move(message)) { invariant(message->operation() == opReply); QueryResult::View qr = _message->singleData().view2ptr(); // should be checked by caller. invariant(qr.msgdata().getNetworkOp() == opReply); uassert(ErrorCodes::BadValue, str::stream() << "Got legacy command reply with a bad cursorId field," << " expected a value of 0 but got " << qr.getCursorId(), qr.getCursorId() == 0); uassert(ErrorCodes::BadValue, str::stream() << "Got legacy command reply with a bad nReturned field," << " expected a value of 1 but got " << qr.getNReturned(), qr.getNReturned() == 1); uassert(ErrorCodes::BadValue, str::stream() << "Got legacy command reply with a bad startingFrom field," << " expected a value of 0 but got " << qr.getStartingFrom(), qr.getStartingFrom() == 0); std::tie(_commandReply, _metadata) = uassertStatusOK(rpc::upconvertReplyMetadata(BSONObj(qr.data()))); // Copy the bson array of documents from the message into // a contiguous area of memory owned by _docBuffer so // DocumentRange can be used to iterate over documents auto cursorElem = _commandReply[LegacyReplyBuilder::kCursorTag]; if (cursorElem.eoo()) return; BSONObj cursorObj = cursorElem.Obj(); auto firstBatchElem = cursorObj[LegacyReplyBuilder::kFirstBatchTag]; if (firstBatchElem.eoo()) return; for (BSONObjIterator it(firstBatchElem.Obj()); it.more(); it.next()) { invariant((*it).isABSONObj()); BSONObj doc = (*it).Obj(); doc.appendSelfToBufBuilder(_docBuffer); } const char* dataBegin = _docBuffer.buf(); const char* dataEnd = dataBegin + _docBuffer.len(); _outputDocs = DocumentRange(dataBegin, dataEnd); return; }
// THROWS static void sayAsCmd( DBClientBase* conn, const StringData& dbName, const BSONObj& cmdObj ) { Message toSend; // see query.h for the protocol we are using here. BufBuilder bufB; bufB.appendNum( 0 ); // command/query options bufB.appendStr( dbName.toString() + ".$cmd" ); // write command ns bufB.appendNum( 0 ); // ntoskip (0 for command) bufB.appendNum( 1 ); // ntoreturn (1 for command) cmdObj.appendSelfToBufBuilder( bufB ); toSend.setData( dbQuery, bufB.buf(), bufB.len() ); // Send our command conn->say( toSend ); }
void DBClientBase::update( const string & ns , Query query , BSONObj obj , bool upsert ) { BufBuilder b; b.append( (int)0 ); // reserverd b.append( ns ); b.append( (int)upsert ); query.obj.appendSelfToBufBuilder( b ); obj.appendSelfToBufBuilder( b ); Message toSend; toSend.setData( dbUpdate , b.buf() , b.len() ); say( toSend ); }
LegacyRequestBuilder& LegacyRequestBuilder::setCommandArgs(BSONObj commandArgs) { invariant(_state == State::kCommandArgs); BSONObj legacyCommandArgs; int queryOptions; std::tie(legacyCommandArgs, queryOptions) = uassertStatusOK( rpc::downconvertRequestMetadata(std::move(commandArgs), std::move(_metadata))); _builder.appendNum(queryOptions); // queryOptions _builder.appendStr(_ns); _builder.appendNum(0); // nToSkip _builder.appendNum(1); // nToReturn legacyCommandArgs.appendSelfToBufBuilder(_builder); _state = State::kInputDocs; return *this; }
void DBClientBase::update( const string & ns , Query query , BSONObj obj , bool upsert , bool multi ) { BufBuilder b; b.append( (int)0 ); // reserved b.append( ns ); int flags = 0; if ( upsert ) flags |= UpdateOption_Upsert; if ( multi ) flags |= UpdateOption_Multi; b.append( flags ); query.obj.appendSelfToBufBuilder( b ); obj.appendSelfToBufBuilder( b ); Message toSend; toSend.setData( dbUpdate , b.buf() , b.len() ); say( toSend ); }
// Test a basic good insert, and an extra read TEST(DBMessage1, GoodInsert2) { BufBuilder b; string ns("test"); b.appendNum(static_cast<int>(1)); b.appendStr(ns); b.appendNum(static_cast<int>(3)); b.appendNum(static_cast<int>(39)); BSONObj bo = BSON("ts" << 0); bo.appendSelfToBufBuilder(b); Message toSend; toSend.setData(dbInsert, b.buf(), b.len()); DbMessage d1(toSend); ASSERT_EQUALS(3, d1.pullInt()); ASSERT_EQUALS(39, d1.pullInt()); BSONObj bo2 = d1.nextJsObj(); ASSERT_THROWS(d1.nextJsObj(), MsgAssertionException); }
void assembleQueryRequest(const string& ns, BSONObj query, int nToReturn, int nToSkip, const BSONObj* fieldsToReturn, int queryOptions, Message& toSend) { if (kDebugBuild) { massert(10337, (string) "object not valid assembleRequest query", query.isValid()); } // see query.h for the protocol we are using here. BufBuilder b; int opts = queryOptions; b.appendNum(opts); b.appendStr(ns); b.appendNum(nToSkip); b.appendNum(nToReturn); query.appendSelfToBufBuilder(b); if (fieldsToReturn) fieldsToReturn->appendSelfToBufBuilder(b); toSend.setData(dbQuery, b.buf(), b.len()); }
void NetworkInterfaceASIO::_messageFromRequest(const RemoteCommandRequest& request, Message* toSend, bool useOpCommand) { BSONObj query = request.cmdObj; invariant(query.isValid()); // TODO: Once OP_COMMAND work is complete, // look at client to see if it supports OP_COMMAND. // TODO: Investigate whether we can use CommandRequestBuilder here. BufBuilder b; b.appendNum(0); // opts b.appendStr(request.dbname + ".$cmd"); b.appendNum(0); // toSkip b.appendNum(1); // toReturn, don't care about responses query.appendSelfToBufBuilder(b); // TODO: If AsyncOp can own this buffer, we can avoid copying it in setData(). toSend->setData(dbQuery, b.buf(), b.len()); toSend->header().setId(nextMessageId()); toSend->header().setResponseTo(0); }
void replyToQuery(int queryResultFlags, Message& response, const BSONObj& resultObj) { OpQueryReplyBuilder reply; resultObj.appendSelfToBufBuilder(reply.bufBuilderForResults()); reply.putInMessage(&response, queryResultFlags, /*nReturned*/ 1); }
Status CommandReplyBuilder::addOutputDoc(const BSONObj& outputDoc) { invariant(_state == State::kOutputDocs); outputDoc.appendSelfToBufBuilder(_builder); return Status::OK(); }