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);
}
示例#2
0
    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 );
    }
示例#3
0
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();
}
示例#4
0
    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 );
    }
示例#5
0
 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());
 }
示例#6
0
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 );
}
示例#8
0
    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 );
    }
示例#9
0
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;
}
示例#10
0
文件: dbclient.cpp 项目: mikejs/mongo
    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);
}
示例#12
0
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);
}
示例#14
0
void replyToQuery(int queryResultFlags, Message& response, const BSONObj& resultObj) {
    OpQueryReplyBuilder reply;
    resultObj.appendSelfToBufBuilder(reply.bufBuilderForResults());
    reply.putInMessage(&response, queryResultFlags, /*nReturned*/ 1);
}
示例#15
0
Status CommandReplyBuilder::addOutputDoc(const BSONObj& outputDoc) {
    invariant(_state == State::kOutputDocs);
    outputDoc.appendSelfToBufBuilder(_builder);
    return Status::OK();
}