diff options
Diffstat (limited to 'src/mongo/db/exec/collection_scan.cpp')
| -rw-r--r-- | src/mongo/db/exec/collection_scan.cpp | 41 |
1 files changed, 28 insertions, 13 deletions
diff --git a/src/mongo/db/exec/collection_scan.cpp b/src/mongo/db/exec/collection_scan.cpp index f8550dbe81d..877603a0965 100644 --- a/src/mongo/db/exec/collection_scan.cpp +++ b/src/mongo/db/exec/collection_scan.cpp @@ -275,19 +275,36 @@ void CollectionScan::setLatestOplogEntryTimestamp(const Record& record) { } void CollectionScan::assertTsHasNotFallenOffOplog(const Record& record) { - // If the first entry we see in the oplog is the replset initialization, then it doesn't matter - // if its timestamp is later than the timestamp that should not have fallen off the oplog; no - // events earlier can have fallen off this oplog. Otherwise, verify that the timestamp of the - // first observed oplog entry is earlier than or equal to timestamp that should not have fallen - // off the oplog. - auto oplogEntry = uassertStatusOK(repl::OplogEntry::parse(record.data.toBson())); + const auto oplogEntry = record.data.toBson(); + const repl::OplogEntryParserNonStrict oplogEntryParser{oplogEntry}; invariant(_specificStats.docsTested == 0); - const bool isNewRS = - oplogEntry.getObject().binaryEqual(BSON("msg" << repl::kInitiatingSetMsg)) && - oplogEntry.getOpType() == repl::OpTypeEnum::kNoop; + + // Indicates that 'oplogEntry' means initialization of a replica set. + bool isNewRS{false}; + + // Indicates that the timestamp of the observed oplog entry 'oplogEntry' is earlier than or + // equal to timestamp that should not have fallen off the oplog. + bool tsHasNotFallenOff{false}; + try { + tsHasNotFallenOff = + oplogEntryParser.getOpTime().getTimestamp() <= *_params.assertTsHasNotFallenOffOplog; + + // If the first entry we see in the oplog is the replset initialization, then it doesn't + // matter if its timestamp is later than the timestamp that should not have fallen off the + // oplog; no events earlier can have fallen off this oplog. + // NOTE: A change collection can be created at any moment as such it might not have replset + // initialization message, as such this case is not fully applicable for the change + // collection. + isNewRS = oplogEntryParser.getOpType() == repl::OpTypeEnum::kNoop && + oplogEntryParser.getObject().binaryEqual(BSON("msg" << repl::kInitiatingSetMsg)); + } catch (const AssertionException& exception) { + uasserted(8881102, + str::stream() << "Failed to parse the oldest oplog entry" << causedBy(exception)); + } uassert(ErrorCodes::OplogQueryMinTsMissing, "Specified timestamp has already fallen off the oplog", - isNewRS || oplogEntry.getTimestamp() <= *_params.assertTsHasNotFallenOffOplog); + isNewRS || tsHasNotFallenOff); + // We don't need to check this assertion again after we've confirmed the first oplog event. _params.assertTsHasNotFallenOffOplog = boost::none; } @@ -431,9 +448,7 @@ void CollectionScan::doReattachToOperationContext() { unique_ptr<PlanStageStats> CollectionScan::getStats() { // Add a BSON representation of the filter to the stats tree, if there is one. if (nullptr != _filter) { - BSONObjBuilder bob; - _filter->serialize(&bob); - _commonStats.filter = bob.obj(); + _commonStats.filter = _filter->serialize(); } unique_ptr<PlanStageStats> ret = std::make_unique<PlanStageStats>(_commonStats, STAGE_COLLSCAN); |
