summaryrefslogtreecommitdiff
path: root/src/mongo/shell/replsettest.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/shell/replsettest.js')
-rw-r--r--src/mongo/shell/replsettest.js45
1 files changed, 45 insertions, 0 deletions
diff --git a/src/mongo/shell/replsettest.js b/src/mongo/shell/replsettest.js
index dee9b4c75a0..05c4b584ff2 100644
--- a/src/mongo/shell/replsettest.js
+++ b/src/mongo/shell/replsettest.js
@@ -570,6 +570,51 @@ var ReplSetTest = function(opts) {
};
/**
+ * A special version of awaitSecondaryNodes() used exclusively by rollback_test.js.
+ * Wraps around awaitSecondaryNodes() itself and checks for an unrecoverable rollback
+ * if it throws.
+ */
+ this.awaitSecondaryNodesForRollbackTest = function(timeout,
+ connToCheckForUnrecoverableRollback) {
+ try {
+ this.awaitSecondaryNodes(timeout);
+ } catch (originalEx) {
+ // There is a special case where we expect the (rare) possibility of unrecoverable
+ // rollbacks with EMRC:false in rollback suites with unclean shutdowns.
+ jsTestLog("Exception in 'awaitSecondaryNodes', checking for unrecoverable rollback");
+ if (connToCheckForUnrecoverableRollback) {
+ const conn = connToCheckForUnrecoverableRollback;
+
+ const statusRes = assert.commandWorked(conn.adminCommand({replSetGetStatus: 1}));
+ const isRecovering = (statusRes.myState === ReplSetTest.State.RECOVERING);
+ const hasNoSyncSource = (statusRes.syncSourceId === -1);
+
+ const cmdLineOptsRes = assert.commandWorked(conn.adminCommand("getCmdLineOpts"));
+ const hasEMRCFalse =
+ (cmdLineOptsRes.parsed.replication.enableMajorityReadConcern === false);
+
+ if (isRecovering && hasNoSyncSource && hasEMRCFalse) {
+ try {
+ const n = this.getNodeId(conn);
+ const connToCheck = _useBridge ? _unbridgedNodes[n] : this.nodes[n];
+ // Confirm that the node is unable to recover after rolling back.
+ checkLog.contains(
+ connToCheck,
+ "remote oplog does not contain entry with optime matching our required optime ",
+ 60 * 1000);
+ } catch (checkLogEx) {
+ throw originalEx;
+ }
+ // Add this info to the original exception.
+ originalEx.unrecoverableRollbackDetected = true;
+ }
+ }
+ // Re-throw the original exception in all cases.
+ throw originalEx;
+ }
+ };
+
+ /**
* Blocks until the specified node says it's syncing from the given upstream node.
*/
this.awaitSyncSource = function(node, upstreamNode, timeout) {