summaryrefslogtreecommitdiff
path: root/src/mongo/db/commands/find_cmd.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/commands/find_cmd.cpp')
-rw-r--r--src/mongo/db/commands/find_cmd.cpp34
1 files changed, 34 insertions, 0 deletions
diff --git a/src/mongo/db/commands/find_cmd.cpp b/src/mongo/db/commands/find_cmd.cpp
index 4120b38cd6d..39dee1b5f29 100644
--- a/src/mongo/db/commands/find_cmd.cpp
+++ b/src/mongo/db/commands/find_cmd.cpp
@@ -59,10 +59,13 @@
#include "mongo/db/transaction_participant.h"
#include "mongo/logv2/log.h"
#include "mongo/rpc/get_status_from_command_result.h"
+#include "mongo/util/fail_point.h"
namespace mongo {
namespace {
+MONGO_FAIL_POINT_DEFINE(allowExternalReadsForReverseOplogScanRule);
+
const auto kTermField = "term"_sd;
// Older client code before FCV 5.1 could still send 'ntoreturn' to mean a 'limit' or 'batchSize'.
@@ -424,6 +427,37 @@ public:
opCtx->lockState()->skipAcquireTicket();
}
+ // If this read represents a reverse oplog scan, we want to bypass oplog visibility
+ // rules in the case of secondaries. We normally only read from these nodes at batch
+ // boundaries, but in this specific case we should fetch all new entries, to be
+ // consistent with any catalog changes that might be observable before the batch is
+ // finalized. This special rule for reverse oplog scans is needed by replication
+ // initial sync, for the purposes of calculating the stopTimestamp correctly.
+ boost::optional<PinReadSourceBlock> pinReadSourceBlock;
+ if (isOplogNss) {
+ auto reverseScan = false;
+
+ auto cmdSort = findCommand->getSort();
+ if (!cmdSort.isEmpty()) {
+ BSONElement natural = cmdSort[query_request_helper::kNaturalSortField];
+ if (natural) {
+ reverseScan = natural.safeNumberInt() < 0;
+ }
+ }
+
+ auto isInternal = (opCtx->getClient()->session() &&
+ (opCtx->getClient()->session()->getTags() &
+ transport::Session::kInternalClient));
+
+ if (MONGO_unlikely(allowExternalReadsForReverseOplogScanRule.shouldFail())) {
+ isInternal = true;
+ }
+
+ if (reverseScan && isInternal) {
+ pinReadSourceBlock.emplace(opCtx->recoveryUnit());
+ }
+ }
+
// Acquire locks. If the query is on a view, we release our locks and convert the query
// request into an aggregation command.
boost::optional<AutoGetCollectionForReadCommandMaybeLockFree> ctx;