summaryrefslogtreecommitdiff
path: root/src/mongo/db/repl/oplog_fetcher.cpp
diff options
context:
space:
mode:
authorVesselina Ratcheva <vesselina.ratcheva@10gen.com>2019-04-02 19:33:45 -0400
committerVesselina Ratcheva <vesselina.ratcheva@10gen.com>2019-04-10 14:23:52 -0400
commit6aeb04caaf4470a067e4c589bc09ddb70c9411c3 (patch)
tree2d3116fef08b17a33cfba0530d8990df9230d28b /src/mongo/db/repl/oplog_fetcher.cpp
parent5f60f56987ac81e1190c16ba574200303fffc256 (diff)
downloadmongo-6aeb04caaf4470a067e4c589bc09ddb70c9411c3.tar.gz
SERVER-39608 Prevent the OplogFetcher from enqueing a document twice when using StartingPoint::kEnqueueFirstDoc
Diffstat (limited to 'src/mongo/db/repl/oplog_fetcher.cpp')
-rw-r--r--src/mongo/db/repl/oplog_fetcher.cpp16
1 files changed, 14 insertions, 2 deletions
diff --git a/src/mongo/db/repl/oplog_fetcher.cpp b/src/mongo/db/repl/oplog_fetcher.cpp
index 8828d7f5e4b..84ebd79b4da 100644
--- a/src/mongo/db/repl/oplog_fetcher.cpp
+++ b/src/mongo/db/repl/oplog_fetcher.cpp
@@ -439,8 +439,16 @@ StatusWith<BSONObj> OplogFetcher::_onSuccessfulBatch(const Fetcher::QueryRespons
LOG(1) << "oplog fetcher successfully fetched from " << _getSource();
- // If this is the first batch, no rollback is needed and we don't want to enqueue the first
- // document, skip it.
+ // We do not always enqueue the first document. We elect to skip it for the following
+ // reasons:
+ // 1. This is the first batch and no rollback is needed. Callers specify
+ // StartingPoint::kSkipFirstDoc when they want this behavior.
+ // 2. We have already enqueued that document in a previous attempt. We can get into
+ // this situation if we had a batch with StartingPoint::kEnqueueFirstDoc that failed
+ // right after that first document was enqueued. In such a scenario, we would not
+ // have advanced the lastFetched opTime, so we skip past that document to avoid
+ // duplicating it.
+
if (_startingPoint == StartingPoint::kSkipFirstDoc) {
firstDocToApply++;
}
@@ -488,6 +496,10 @@ StatusWith<BSONObj> OplogFetcher::_onSuccessfulBatch(const Fetcher::QueryRespons
return status;
}
+ // Start skipping the first doc after at least one doc has been enqueued in the lifetime
+ // of this fetcher.
+ _startingPoint = StartingPoint::kSkipFirstDoc;
+
if (_dataReplicatorExternalState->shouldStopFetching(
_getSource(), replSetMetadata, oqMetadata)) {
str::stream errMsg;