StatusWith<Shard::QueryResponse> ShardLocal::_exhaustiveFindOnConfig( OperationContext* txn, const ReadPreferenceSetting& readPref, const repl::ReadConcernLevel& readConcernLevel, const NamespaceString& nss, const BSONObj& query, const BSONObj& sort, boost::optional<long long> limit) { auto replCoord = repl::ReplicationCoordinator::get(txn); if (readConcernLevel == repl::ReadConcernLevel::kMajorityReadConcern) { // Set up operation context with majority read snapshot so correct optime can be retrieved. Status status = txn->recoveryUnit()->setReadFromMajorityCommittedSnapshot(); // Wait for any writes performed by this ShardLocal instance to be committed and visible. Status readConcernStatus = replCoord->waitUntilOpTimeForRead( txn, repl::ReadConcernArgs{_getLastOpTime(), readConcernLevel}); if (!readConcernStatus.isOK()) { return readConcernStatus; } // Inform the storage engine to read from the committed snapshot for the rest of this // operation. status = txn->recoveryUnit()->setReadFromMajorityCommittedSnapshot(); if (!status.isOK()) { return status; } } else { invariant(readConcernLevel == repl::ReadConcernLevel::kLocalReadConcern); } DBDirectClient client(txn); Query fullQuery(query); if (!sort.isEmpty()) { fullQuery.sort(sort); } fullQuery.readPref(readPref.pref, BSONArray()); try { std::unique_ptr<DBClientCursor> cursor = client.query(nss.ns().c_str(), fullQuery, limit.get_value_or(0)); if (!cursor) { return {ErrorCodes::OperationFailed, str::stream() << "Failed to establish a cursor for reading " << nss.ns() << " from local storage"}; } std::vector<BSONObj> documentVector; while (cursor->more()) { BSONObj document = cursor->nextSafe().getOwned(); documentVector.push_back(std::move(document)); } return Shard::QueryResponse{std::move(documentVector), replCoord->getCurrentCommittedSnapshotOpTime()}; } catch (const DBException& ex) { return ex.toStatus(); } }
StatusWith<Shard::QueryResponse> ShardLocal::_exhaustiveFindOnConfig( OperationContext* txn, const ReadPreferenceSetting& readPref, const NamespaceString& nss, const BSONObj& query, const BSONObj& sort, boost::optional<long long> limit) { // Set up operation context with majority read snapshot so correct optime can be retrieved. Status status = txn->recoveryUnit()->setReadFromMajorityCommittedSnapshot(); auto replCoord = repl::ReplicationCoordinator::get(txn); // Ensure timeout is set on the txn so we don't wait forever for the snapshot. // TODO (SERVER-18277): Remove this CurOp::get(txn)->ensureStarted(); // Wait until a snapshot is available. while (status == ErrorCodes::ReadConcernMajorityNotAvailableYet) { LOG(1) << "Waiting for ReadFromMajorityCommittedSnapshot to become available"; replCoord->waitUntilSnapshotCommitted(txn, SnapshotName::min()); status = txn->recoveryUnit()->setReadFromMajorityCommittedSnapshot(); } if (!status.isOK()) { return status; } DBDirectClient client(txn); Query fullQuery(query); if (!sort.isEmpty()) { fullQuery.sort(sort); } fullQuery.readPref(readPref.pref, BSONArray()); try { std::unique_ptr<DBClientCursor> cursor = client.query(nss.ns().c_str(), fullQuery, limit.get_value_or(0)); if (!cursor) { return {ErrorCodes::OperationFailed, str::stream() << "Failed to establish a cursor for reading " << nss.ns() << " from local storage"}; } std::vector<BSONObj> documentVector; while (cursor->more()) { BSONObj document = cursor->nextSafe().getOwned(); documentVector.push_back(std::move(document)); } return Shard::QueryResponse{std::move(documentVector), replCoord->getCurrentCommittedSnapshotOpTime()}; } catch (const DBException& ex) { return ex.toStatus(); } }