diff --git a/src/mongo/db/exec/collection_scan.cpp b/src/mongo/db/exec/collection_scan.cpp
index 162caf4cf3..7dab48aaa6 100644
--- a/src/mongo/db/exec/collection_scan.cpp
+++ b/src/mongo/db/exec/collection_scan.cpp
@@ -48,6 +48,8 @@
namespace mongo {
+MONGO_FAIL_POINT_DEFINE(cappedPositionLost);
+
using std::unique_ptr;
using std::vector;
using stdx::make_unique;
@@ -78,6 +80,17 @@ CollectionScan::CollectionScan(OperationContext* opCtx,
}
PlanStage::StageState CollectionScan::doWork(WorkingSetID* out) {
+ if (MONGO_FAIL_POINT(cappedPositionLost)) {
+ _isDead = true;
+ Status status(ErrorCodes::CappedPositionLost,
+ str::stream() << "CollectionScan died due to failure to restore "
+ << "tailable cursor position. "
+ << "Last seen record id: "
+ << _lastSeenId);
+ *out = WorkingSetCommon::allocateStatusMember(_workingSet, status);
+ return PlanStage::DEAD;
+ }
+
if (_isDead) {
Status status(
ErrorCodes::CappedPositionLost,
diff --git a/src/mongo/shell/replsettest.js b/src/mongo/shell/replsettest.js
index 97bacd8cdd..0cafca2ad0 100644
--- a/src/mongo/shell/replsettest.js
+++ b/src/mongo/shell/replsettest.js
@@ -2009,7 +2009,7 @@ var ReplSetTest = function(opts) {
*/
function checkOplogs(rst, slaves, msgPrefix = 'checkOplogs') {
slaves = slaves || rst._slaves;
- var OplogReader = function(mongo) {
+ var OplogReader = function(mongo, failOnFirst) {
this.next = function() {
if (!this.cursor)
throw new Error("OplogReader is not open!");
@@ -2024,6 +2024,13 @@ var ReplSetTest = function(opts) {
if (!this.cursor)
throw new Error("OplogReader is not open!");
try {
+ if (this.failOnFirst && this.failed === false) {
+ this.failed = true;
+ assert.commandWorked(this.mongo.adminCommand(
+ {configureFailPoint: "cappedPositionLost", mode: {"times": 1}}));
+ printjson("Called cappedPositionLost.");
+ }
+
return this.cursor.hasNext();
} catch (err) {
print("Error: hasNext threw '" + err.message + "' on " + this.mongo.host);
@@ -2059,6 +2066,8 @@ var ReplSetTest = function(opts) {
this.lastDoc = null;
this.cursor = null;
this.mongo = mongo;
+ this.failOnFirst = failOnFirst;
+ this.failed = false;
};
if (slaves.length >= 1) {
@@ -2080,7 +2089,8 @@ var ReplSetTest = function(opts) {
continue;
}
- readers[i] = new OplogReader(node);
+ print("Creating OplogReader. I==2? " + (i == 2));
+ readers[i] = new OplogReader(node, i == 2);
var currTS = readers[i].getFirstDoc().ts;
@@ -2108,7 +2118,7 @@ var ReplSetTest = function(opts) {
var otherOplogEntry = readers[i].next();
if (!bsonBinaryEqual(oplogEntry, otherOplogEntry)) {
var query = prevOplogEntry ? {ts: {$lte: prevOplogEntry.ts}} : {};
- rst.nodes.forEach(node => this.dumpOplog(node, query, 100));
+ var log = msgPrefix +
", non-matching oplog entries for the following nodes: \n" +
firstReader.mongo.host + ": " + tojsononeline(oplogEntry) + "\n" +