StatusWith<ShardRegistry::QueryResponse> ShardRegistry::exhaustiveFindOnConfig( OperationContext* txn, const ReadPreferenceSetting& readPref, const NamespaceString& nss, const BSONObj& query, const BSONObj& sort, boost::optional<long long> limit, boost::optional<repl::ReadConcernArgs> readConcern) { const auto targeter = getConfigShard()->getTargeter(); const auto host = targeter->findHost(readPref); if (!host.isOK()) { return host.getStatus(); } // If for some reason the callback never gets invoked, we will return this status Status status = Status(ErrorCodes::InternalError, "Internal error running find command"); QueryResponse response; auto fetcherCallback = [&status, &response](const Fetcher::QueryResponseStatus& dataStatus, Fetcher::NextAction* nextAction) { // Throw out any accumulated results on error if (!dataStatus.isOK()) { status = dataStatus.getStatus(); response.docs.clear(); return; } auto& data = dataStatus.getValue(); if (data.otherFields.metadata.hasField(rpc::kReplSetMetadataFieldName)) { auto replParseStatus = rpc::ReplSetMetadata::readFromMetadata(data.otherFields.metadata); if (!replParseStatus.isOK()) { status = replParseStatus.getStatus(); response.docs.clear(); return; } response.opTime = replParseStatus.getValue().getLastOpVisible(); } for (const BSONObj& doc : data.documents) { response.docs.push_back(doc.getOwned()); } status = Status::OK(); }; BSONObj readConcernObj; if (readConcern) { BSONObjBuilder bob; readConcern->appendInfo(&bob); readConcernObj = bob.done().getObjectField(repl::ReadConcernArgs::kReadConcernFieldName).getOwned(); } auto lpq = LiteParsedQuery::makeAsFindCmd(nss, query, BSONObj(), // projection sort, BSONObj(), // hint readConcernObj, boost::none, // skip limit); BSONObjBuilder findCmdBuilder; lpq->asFindCommand(&findCmdBuilder); Seconds maxTime = kConfigCommandTimeout; Microseconds remainingTxnMaxTime(txn->getRemainingMaxTimeMicros()); if (remainingTxnMaxTime != Microseconds::zero()) { maxTime = duration_cast<Seconds>(remainingTxnMaxTime); } findCmdBuilder.append(LiteParsedQuery::cmdOptionMaxTimeMS, durationCount<Milliseconds>(maxTime)); QueryFetcher fetcher(_executor.get(), host.getValue(), nss, findCmdBuilder.done(), fetcherCallback, readPref.pref == ReadPreference::PrimaryOnly ? kReplMetadata : kReplSecondaryOkMetadata); Status scheduleStatus = fetcher.schedule(); if (!scheduleStatus.isOK()) { return scheduleStatus; } fetcher.wait(); updateReplSetMonitor(targeter, host.getValue(), status); if (!status.isOK()) { return status; } advanceConfigOpTime(response.opTime); return response; }
StatusWith<ShardRegistry::QueryResponse> ShardRegistry::exhaustiveFind( const HostAndPort& host, const NamespaceString& nss, const BSONObj& query, const BSONObj& sort, boost::optional<long long> limit, boost::optional<repl::ReadConcernArgs> readConcern, const BSONObj& metadata) { // If for some reason the callback never gets invoked, we will return this status Status status = Status(ErrorCodes::InternalError, "Internal error running find command"); QueryResponse response; auto fetcherCallback = [&status, &response](const Fetcher::QueryResponseStatus& dataStatus, Fetcher::NextAction* nextAction) { // Throw out any accumulated results on error if (!dataStatus.isOK()) { status = dataStatus.getStatus(); response.docs.clear(); return; } auto& data = dataStatus.getValue(); if (auto replField = data.otherFields.metadata[rpc::kReplicationMetadataFieldName]) { auto replParseStatus = rpc::ReplSetMetadata::readFromMetadata(replField.Obj()); if (!replParseStatus.isOK()) { status = replParseStatus.getStatus(); response.docs.clear(); return; } response.opTime = replParseStatus.getValue().getLastCommittedOptime(); } for (const BSONObj& doc : data.documents) { response.docs.push_back(std::move(doc.getOwned())); } status = Status::OK(); }; auto lpq = LiteParsedQuery::makeAsFindCmd(nss, query, BSONObj(), // projection sort, BSONObj(), // hint boost::none, // skip limit); BSONObjBuilder findCmdBuilder; lpq->asFindCommand(&findCmdBuilder); if (readConcern) { BSONObjBuilder builder; readConcern->appendInfo(&findCmdBuilder); } QueryFetcher fetcher( _executor.get(), host, nss, findCmdBuilder.done(), fetcherCallback, metadata); Status scheduleStatus = fetcher.schedule(); if (!scheduleStatus.isOK()) { return scheduleStatus; } fetcher.wait(); if (!status.isOK()) { return status; } return response; }