diff options
37 files changed, 96 insertions, 93 deletions
diff --git a/jstests/core/max_time_ms.js b/jstests/core/max_time_ms.js index 7597084430d..5c5ad508805 100644 --- a/jstests/core/max_time_ms.js +++ b/jstests/core/max_time_ms.js @@ -33,7 +33,7 @@ cursor.maxTimeMS(100); error = assert.throws(function() { cursor.itcount(); }, [], "expected query to abort due to time limit"); -assert.eq(ErrorCodes.ExceededTimeLimit, error.code); +assert.eq(ErrorCodes.MaxTimeMSExpired, error.code); // // Simple negative test for query: a ~300ms query with a 10s time limit should not hit the time @@ -83,7 +83,7 @@ error = assert.throws(function() { cursor.next(); cursor.next(); }, [], "expected batch 2 (getmore) to abort due to time limit"); -assert.eq(ErrorCodes.ExceededTimeLimit, error.code); +assert.eq(ErrorCodes.MaxTimeMSExpired, error.code); // // Simple negative test for getmore: @@ -139,7 +139,7 @@ cursor.maxTimeMS(6 * 1000); error = assert.throws(function() { cursor.itcount(); }, [], "expected find() to abort due to time limit"); -assert.eq(ErrorCodes.ExceededTimeLimit, error.code); +assert.eq(ErrorCodes.MaxTimeMSExpired, error.code); // // Many-batch negative test for getmore: @@ -171,7 +171,7 @@ assert.doesNotThrow(function() { t.drop(); res = t.getDB().adminCommand({sleep: 1, millis: 300, maxTimeMS: 100}); -assert(res.ok == 0 && res.code == ErrorCodes.ExceededTimeLimit, +assert(res.ok == 0 && res.code == ErrorCodes.MaxTimeMSExpired, "expected sleep command to abort due to time limit, ok=" + res.ok + ", code=" + res.code); // @@ -299,7 +299,7 @@ t.drop(); assert.eq( 1, t.getDB().adminCommand({configureFailPoint: "maxTimeAlwaysTimeOut", mode: "alwaysOn"}).ok); res = t.getDB().runCommand({ping: 1, maxTimeMS: 10 * 1000}); -assert(res.ok == 0 && res.code == ErrorCodes.ExceededTimeLimit, +assert(res.ok == 0 && res.code == ErrorCodes.MaxTimeMSExpired, "expected command to trigger maxTimeAlwaysTimeOut fail point, ok=" + res.ok + ", code=" + res.code); assert.eq(1, t.getDB().adminCommand({configureFailPoint: "maxTimeAlwaysTimeOut", mode: "off"}).ok); @@ -412,7 +412,7 @@ assert.commandWorked( error = assert.throws(function() { cursor.itcount(); }, [], "expected query to abort due to time limit"); -assert.eq(ErrorCodes.ExceededTimeLimit, error.code); +assert.eq(ErrorCodes.MaxTimeMSExpired, error.code); assert.commandWorked( t.getDB().adminCommand({configureFailPoint: "maxTimeAlwaysTimeOut", mode: "off"})); diff --git a/jstests/core/txns/abort_transaction_thread_does_not_block_on_locks.js b/jstests/core/txns/abort_transaction_thread_does_not_block_on_locks.js index 2708f5a6d37..b6b6b6e5bc8 100644 --- a/jstests/core/txns/abort_transaction_thread_does_not_block_on_locks.js +++ b/jstests/core/txns/abort_transaction_thread_does_not_block_on_locks.js @@ -91,7 +91,7 @@ // Wait for the drop to have a pending MODE_X lock on the database, which will block // MODE_IS lock requests behind it. return testDB.runCommand({find: collName, maxTimeMS: 100}).code === - ErrorCodes.ExceededTimeLimit; + ErrorCodes.MaxTimeMSExpired; }); // Should take 'transactionLifeTime' plus the period of the transaction aborter thread, diff --git a/jstests/core/txns/abort_transactions_on_FCV_downgrade.js b/jstests/core/txns/abort_transactions_on_FCV_downgrade.js index e398066e425..46ade87dcd7 100644 --- a/jstests/core/txns/abort_transactions_on_FCV_downgrade.js +++ b/jstests/core/txns/abort_transactions_on_FCV_downgrade.js @@ -23,7 +23,7 @@ jsTestLog("Attempt to drop the collection. This should fail due to the open transaction."); assert.commandFailedWithCode(testDB.runCommand({drop: collName, maxTimeMS: 1000}), - ErrorCodes.ExceededTimeLimit); + ErrorCodes.MaxTimeMSExpired); jsTestLog("Downgrade the featureCompatibilityVersion."); assert.commandWorked(testDB.adminCommand({setFeatureCompatibilityVersion: lastStableFCV})); diff --git a/jstests/core/txns/transactions_block_ddl.js b/jstests/core/txns/transactions_block_ddl.js index 0d6c4d1aa56..298795d004f 100644 --- a/jstests/core/txns/transactions_block_ddl.js +++ b/jstests/core/txns/transactions_block_ddl.js @@ -27,7 +27,7 @@ assert.commandWorked(sessionColl.insert({a: 5, b: 6})); assert.commandFailedWithCode( testDB.getSiblingDB(cmdDBName).runCommand(Object.assign({}, ddlCmd, {maxTimeMS: 500})), - ErrorCodes.ExceededTimeLimit); + ErrorCodes.MaxTimeMSExpired); assert.commandWorked(session.commitTransaction_forTesting()); } diff --git a/jstests/core/txns/write_conflicts_with_non_txns.js b/jstests/core/txns/write_conflicts_with_non_txns.js index 5fcf7cdaad6..1ea9535b9ae 100644 --- a/jstests/core/txns/write_conflicts_with_non_txns.js +++ b/jstests/core/txns/write_conflicts_with_non_txns.js @@ -70,7 +70,7 @@ jsTestLog("Do a conflicting single document insert outside of transaction with maxTimeMS."); assert.commandFailedWithCode( testColl.runCommand({insert: collName, documents: [nonTxnDoc], maxTimeMS: 100}), - ErrorCodes.ExceededTimeLimit); + ErrorCodes.MaxTimeMSExpired); jsTestLog("Doing conflicting single document write in separate thread."); let thread = new ScopedThread(singleDocWrite, dbName, collName, nonTxnDoc); diff --git a/jstests/noPassthrough/afterClusterTime_committed_reads.js b/jstests/noPassthrough/afterClusterTime_committed_reads.js index 0f9bc1480c7..5c488ca69f4 100644 --- a/jstests/noPassthrough/afterClusterTime_committed_reads.js +++ b/jstests/noPassthrough/afterClusterTime_committed_reads.js @@ -45,7 +45,7 @@ writeConcern: {w: "majority"}, maxTimeMS: 1000 }), - ErrorCodes.ExceededTimeLimit); + ErrorCodes.MaxTimeMSExpired); // Restart replication. restartReplicationOnSecondaries(rst); diff --git a/jstests/noPassthrough/readConcern_atClusterTime_snapshot_selection.js b/jstests/noPassthrough/readConcern_atClusterTime_snapshot_selection.js index 91a754a595a..6c650a2cded 100644 --- a/jstests/noPassthrough/readConcern_atClusterTime_snapshot_selection.js +++ b/jstests/noPassthrough/readConcern_atClusterTime_snapshot_selection.js @@ -73,7 +73,7 @@ primarySession.startTransaction( {readConcern: {level: "snapshot", atClusterTime: clusterTimeAfter}}); assert.commandFailedWithCode(primaryDB.runCommand({find: collName, maxTimeMS: 1000}), - ErrorCodes.ExceededTimeLimit); + ErrorCodes.MaxTimeMSExpired); primarySession.abortTransaction(); // Restart replication on one of the secondaries. @@ -101,7 +101,7 @@ secondarySession.startTransaction( {readConcern: {level: "snapshot", atClusterTime: clusterTimeAfter}}); assert.commandFailedWithCode(secondaryDB0.runCommand({find: collName, maxTimeMS: 1000}), - ErrorCodes.ExceededTimeLimit); + ErrorCodes.MaxTimeMSExpired); secondarySession.abortTransaction(); // Restart replication on the lagged secondary. diff --git a/jstests/noPassthrough/read_majority.js b/jstests/noPassthrough/read_majority.js index a8e1b9f4221..2aa9c826a65 100644 --- a/jstests/noPassthrough/read_majority.js +++ b/jstests/noPassthrough/read_majority.js @@ -51,7 +51,7 @@ load("jstests/libs/analyze_plan.js"); var res = t.runCommand('find', {batchSize: 2, readConcern: {level: level}, maxTimeMS: 1000}); assert.commandFailed(res); - assert.eq(res.code, ErrorCodes.ExceededTimeLimit); + assert.eq(res.code, ErrorCodes.MaxTimeMSExpired); } function getCursorForReadConcernLevel() { diff --git a/jstests/noPassthroughWithMongod/validate_interrupt.js b/jstests/noPassthroughWithMongod/validate_interrupt.js index 758eaa6839b..7b76551f4e4 100644 --- a/jstests/noPassthroughWithMongod/validate_interrupt.js +++ b/jstests/noPassthroughWithMongod/validate_interrupt.js @@ -29,7 +29,7 @@ if (res.ok === 0) { assert.eq(res.code, - ErrorCodes.ExceededTimeLimit, + ErrorCodes.MaxTimeMSExpired, 'validate command did not time out:\n' + tojson(res)); } else { // validate() should only succeed if it EBUSY'd. See SERVER-23131. diff --git a/jstests/replsets/await_replication_timeout.js b/jstests/replsets/await_replication_timeout.js index 93600d2ca81..2fb4e6e9471 100644 --- a/jstests/replsets/await_replication_timeout.js +++ b/jstests/replsets/await_replication_timeout.js @@ -32,8 +32,7 @@ // Test maxTimeMS timeout res = testDB.runCommand( {insert: collName, documents: [{a: 1}], writeConcern: {w: 3}, maxTimeMS: 1000}); - assert.commandFailedWithCode(res, ErrorCodes.ExceededTimeLimit); - assert.eq(ErrorCodes.ExceededTimeLimit, res.writeConcernError.code); + assert.commandFailedWithCode(res, ErrorCodes.MaxTimeMSExpired); // Test with wtimeout < maxTimeMS res = testDB.runCommand({ @@ -52,8 +51,7 @@ writeConcern: {w: 3, wtimeout: 10 * 1000}, maxTimeMS: 1000 }); - assert.commandFailedWithCode(res, ErrorCodes.ExceededTimeLimit); - assert.eq(ErrorCodes.ExceededTimeLimit, res.writeConcernError.code); + assert.commandFailedWithCode(res, ErrorCodes.MaxTimeMSExpired); // dropDatabase respects the 'w' field when it is stronger than the default of majority. res = testDB.runCommand({dropDatabase: 1, writeConcern: {w: 3, wtimeout: 1000}}); diff --git a/jstests/replsets/dbhash_at_cluster_time.js b/jstests/replsets/dbhash_at_cluster_time.js index d2a77899003..27f4e0f79db 100644 --- a/jstests/replsets/dbhash_at_cluster_time.js +++ b/jstests/replsets/dbhash_at_cluster_time.js @@ -98,7 +98,7 @@ // However, the "dbHash" command should block behind the transaction if "atClusterTime" // wasn't specified. res = assert.commandFailedWithCode(db.runCommand({dbHash: 1, maxTimeMS: 1000}), - ErrorCodes.ExceededTimeLimit); + ErrorCodes.MaxTimeMSExpired); otherSession.abortTransaction(); otherSession.endSession(); diff --git a/jstests/replsets/linearizable_read_concern.js b/jstests/replsets/linearizable_read_concern.js index da544cc9e55..64ccaa32bc9 100644 --- a/jstests/replsets/linearizable_read_concern.js +++ b/jstests/replsets/linearizable_read_concern.js @@ -87,7 +87,7 @@ load('jstests/libs/write_concern_util.js'); var result = primary.getDB("test").runCommand( {"find": "foo", "readConcern": {level: "linearizable"}, "maxTimeMS": 3000}); - assert.commandFailedWithCode(result, ErrorCodes.ExceededTimeLimit); + assert.commandFailedWithCode(result, ErrorCodes.MaxTimeMSExpired); jsTestLog("Testing to make sure linearizable read command does not block forever."); diff --git a/jstests/replsets/read_after_optime.js b/jstests/replsets/read_after_optime.js index 1059d5b1c62..c9369074fee 100644 --- a/jstests/replsets/read_after_optime.js +++ b/jstests/replsets/read_after_optime.js @@ -28,7 +28,7 @@ readConcern: {afterOpTime: {ts: twoKSecTS, t: term}}, maxTimeMS: 5000, }), - ErrorCodes.ExceededTimeLimit); + ErrorCodes.MaxTimeMSExpired); }; // Run the time out test 3 times with replication debug log level increased to 2 diff --git a/jstests/replsets/read_committed_after_rollback.js b/jstests/replsets/read_committed_after_rollback.js index a4e6ffdacbd..bdb83b144a8 100644 --- a/jstests/replsets/read_committed_after_rollback.js +++ b/jstests/replsets/read_committed_after_rollback.js @@ -15,7 +15,7 @@ load("jstests/replsets/rslib.js"); // For startSetIfSupportsReadMajority. coll.runCommand('find', {"readConcern": {"level": "majority"}, "maxTimeMS": 3000}); assert.commandFailedWithCode( res, - ErrorCodes.ExceededTimeLimit, + ErrorCodes.MaxTimeMSExpired, "Expected read of " + coll.getFullName() + ' on ' + coll.getMongo().host + " to block"); } diff --git a/jstests/replsets/read_committed_no_snapshots.js b/jstests/replsets/read_committed_no_snapshots.js index df7ee835fd6..02bec8e69f7 100644 --- a/jstests/replsets/read_committed_no_snapshots.js +++ b/jstests/replsets/read_committed_no_snapshots.js @@ -66,7 +66,7 @@ load("jstests/replsets/rslib.js"); // For reconfig and startSetIfSupportsReadMa assert.commandFailedWithCode( noSnapshotSecondary.getDB(name).foo.runCommand( 'find', {"readConcern": {"level": "majority"}, "maxTimeMS": 1000}), - ErrorCodes.ExceededTimeLimit); + ErrorCodes.MaxTimeMSExpired); // Reconfig to make the no-snapshot secondary the primary var config = primary.getDB("local").system.replset.findOne(); @@ -79,6 +79,6 @@ load("jstests/replsets/rslib.js"); // For reconfig and startSetIfSupportsReadMa assert.commandFailedWithCode( primary.getSiblingDB(name).foo.runCommand( 'find', {"readConcern": {"level": "majority"}, "maxTimeMS": 1000}), - ErrorCodes.ExceededTimeLimit); + ErrorCodes.MaxTimeMSExpired); replTest.stopSet(); })(); diff --git a/jstests/replsets/read_committed_with_catalog_changes.js b/jstests/replsets/read_committed_with_catalog_changes.js index 95322fd3da5..b60fda763f2 100644 --- a/jstests/replsets/read_committed_with_catalog_changes.js +++ b/jstests/replsets/read_committed_with_catalog_changes.js @@ -218,7 +218,7 @@ load("jstests/replsets/rslib.js"); // For startSetIfSupportsReadMajority. var res = coll.runCommand('find', {"readConcern": {"level": "majority"}, "maxTimeMS": 5000}); assert.commandFailedWithCode(res, - ErrorCodes.ExceededTimeLimit, + ErrorCodes.MaxTimeMSExpired, "Expected read of " + coll.getFullName() + " to block"); } diff --git a/jstests/replsets/stepdown_catch_up_opt.js b/jstests/replsets/stepdown_catch_up_opt.js index 48bd11adde1..4fd88748ae4 100644 --- a/jstests/replsets/stepdown_catch_up_opt.js +++ b/jstests/replsets/stepdown_catch_up_opt.js @@ -17,7 +17,7 @@ // Error codes we expect to see. // If the secondary is not caught up. - var noCaughtUpSecondariesCode = 50; + const noCaughtUpSecondariesCode = ErrorCodes.ExceededTimeLimit; // If the stepdown period is shorter than the secondaryCatchUpPeriodSecs argument. var stepDownPeriodTooShortCode = 2; diff --git a/jstests/sharding/linearizable_read_concern.js b/jstests/sharding/linearizable_read_concern.js index 637566e1b2d..1269bc5c4a3 100644 --- a/jstests/sharding/linearizable_read_concern.js +++ b/jstests/sharding/linearizable_read_concern.js @@ -122,7 +122,7 @@ load("jstests/libs/write_concern_util.js"); readConcern: {level: "linearizable"}, maxTimeMS: 3000 }); - assert.commandFailedWithCode(result, ErrorCodes.ExceededTimeLimit); + assert.commandFailedWithCode(result, ErrorCodes.MaxTimeMSExpired); st.stop(); })(); diff --git a/jstests/sharding/max_time_ms_sharded.js b/jstests/sharding/max_time_ms_sharded.js index 8c6e25a3d1f..42179fad314 100644 --- a/jstests/sharding/max_time_ms_sharded.js +++ b/jstests/sharding/max_time_ms_sharded.js @@ -125,8 +125,8 @@ configureMaxTimeAlwaysTimeOut("alwaysOn"); assert.commandFailedWithCode( coll.runCommand("validate", {maxTimeMS: 60 * 1000}), - ErrorCodes.ExceededTimeLimit, - "expected vailidate to fail with code " + ErrorCodes.ExceededTimeLimit + + ErrorCodes.MaxTimeMSExpired, + "expected vailidate to fail with code " + ErrorCodes.MaxTimeMSExpired + " due to maxTimeAlwaysTimeOut fail point, but instead got: " + tojson(res)); // Negative test for "validate". @@ -136,11 +136,11 @@ // Positive test for "count". configureMaxTimeAlwaysTimeOut("alwaysOn"); - assert.commandFailedWithCode( - coll.runCommand("count", {maxTimeMS: 60 * 1000}), - ErrorCodes.ExceededTimeLimit, - "expected count to fail with code " + ErrorCodes.ExceededTimeLimit + - " due to maxTimeAlwaysTimeOut fail point, but instead got: " + tojson(res)); + assert.commandFailedWithCode(coll.runCommand("count", {maxTimeMS: 60 * 1000}), + ErrorCodes.MaxTimeMSExpired, + "expected count to fail with code " + ErrorCodes.MaxTimeMSExpired + + " due to maxTimeAlwaysTimeOut fail point, but instead got: " + + tojson(res)); // Negative test for "count". configureMaxTimeAlwaysTimeOut("off"); @@ -151,8 +151,8 @@ configureMaxTimeAlwaysTimeOut("alwaysOn"); assert.commandFailedWithCode( coll.runCommand("collStats", {maxTimeMS: 60 * 1000}), - ErrorCodes.ExceededTimeLimit, - "expected collStats to fail with code " + ErrorCodes.ExceededTimeLimit + + ErrorCodes.MaxTimeMSExpired, + "expected collStats to fail with code " + ErrorCodes.MaxTimeMSExpired + " due to maxTimeAlwaysTimeOut fail point, but instead got: " + tojson(res)); // Negative test for "collStats". @@ -174,8 +174,8 @@ }); assert.commandFailedWithCode( res, - ErrorCodes.ExceededTimeLimit, - "expected mapReduce to fail with code " + ErrorCodes.ExceededTimeLimit + + ErrorCodes.MaxTimeMSExpired, + "expected mapReduce to fail with code " + ErrorCodes.MaxTimeMSExpired + " due to maxTimeAlwaysTimeOut fail point, but instead got: " + tojson(res)); // Negative test for "mapReduce". @@ -196,8 +196,8 @@ configureMaxTimeAlwaysTimeOut("alwaysOn"); assert.commandFailedWithCode( coll.runCommand("aggregate", {pipeline: [], cursor: {}, maxTimeMS: 60 * 1000}), - ErrorCodes.ExceededTimeLimit, - "expected aggregate to fail with code " + ErrorCodes.ExceededTimeLimit + + ErrorCodes.MaxTimeMSExpired, + "expected aggregate to fail with code " + ErrorCodes.MaxTimeMSExpired + " due to maxTimeAlwaysTimeOut fail point, but instead got: " + tojson(res)); // Negative test for "aggregate". diff --git a/jstests/sharding/max_time_ms_sharded_new_commands.js b/jstests/sharding/max_time_ms_sharded_new_commands.js index 2084f1b711d..c8072359ce1 100644 --- a/jstests/sharding/max_time_ms_sharded_new_commands.js +++ b/jstests/sharding/max_time_ms_sharded_new_commands.js @@ -26,7 +26,7 @@ assert.commandFailedWithCode( admin.runCommand( {setFeatureCompatibilityVersion: lastStableFCV, maxTimeMS: 1000 * 60 * 60 * 24}), - ErrorCodes.ExceededTimeLimit, + ErrorCodes.MaxTimeMSExpired, "expected setFeatureCompatibilityVersion to fail due to maxTimeAlwaysTimeOut fail point"); // Negative test for "setFeatureCompatibilityVersion" diff --git a/jstests/sharding/read_after_optime.js b/jstests/sharding/read_after_optime.js index b174a288834..ce8c5201179 100644 --- a/jstests/sharding/read_after_optime.js +++ b/jstests/sharding/read_after_optime.js @@ -33,7 +33,7 @@ var pingIntervalSeconds = 10; assert.commandFailedWithCode( runFindCommand(new Timestamp(lastOp.ts.getTime() + pingIntervalSeconds * 5, 0)), - ErrorCodes.ExceededTimeLimit); + ErrorCodes.MaxTimeMSExpired); var msg = 'Command on database local timed out waiting for read concern to be satisfied.'; assert.soon(function() { diff --git a/src/mongo/base/error_codes.err b/src/mongo/base/error_codes.err index ed96090d5eb..b7c833248d4 100644 --- a/src/mongo/base/error_codes.err +++ b/src/mongo/base/error_codes.err @@ -49,7 +49,7 @@ error_code("LockBusy", 46) error_code("NoMatchingDocument", 47) error_code("NamespaceExists", 48) error_code("InvalidRoleModification", 49) -error_code("ExceededTimeLimit", 50) +error_code("MaxTimeMSExpired", 50) error_code("ManualInterventionRequired", 51) error_code("DollarPrefixedFieldName", 52) error_code("InvalidIdField", 53) @@ -259,6 +259,7 @@ error_code("UnknownFeatureCompatibilityVersion", 258); error_code("KeyedExecutorRetry", 259); error_code("InvalidResumeToken", 260); error_code("TooManyLogicalSessions", 261); +error_code("ExceededTimeLimit", 266); # Error codes 4000-8999 are reserved. @@ -289,6 +290,7 @@ error_class("Interruption", ["Interrupted", "InterruptedAtShutdown", "InterruptedDueToReplStateChange", "ExceededTimeLimit", + "MaxTimeMSExpired", "CursorKilled", "LockTimeout"]) @@ -316,6 +318,6 @@ error_class("ShutdownError", ["ShutdownInProgress", "InterruptedAtShutdown"]) error_class("ConnectionFatalMessageParseError", ["IllegalOpMsgFlag", "TooManyDocumentSequences"]) -error_class("ExceededTimeLimitError", ["ExceededTimeLimit", "NetworkInterfaceExceededTimeLimit"]) +error_class("ExceededTimeLimitError", ["ExceededTimeLimit", "MaxTimeMSExpired", "NetworkInterfaceExceededTimeLimit"]) error_class("SnapshotError", ["SnapshotTooOld", "SnapshotUnavailable", "StaleChunkHistory"]) diff --git a/src/mongo/db/commands/getmore_cmd.cpp b/src/mongo/db/commands/getmore_cmd.cpp index 71b7f548baf..7859c7b81fe 100644 --- a/src/mongo/db/commands/getmore_cmd.cpp +++ b/src/mongo/db/commands/getmore_cmd.cpp @@ -368,7 +368,8 @@ public: opCtx->getServiceContext()->getPreciseClockSource()->now() + request.awaitDataTimeout.value_or(Seconds{1}); } else if (cursor->getLeftoverMaxTimeMicros() < Microseconds::max()) { - opCtx->setDeadlineAfterNowBy(cursor->getLeftoverMaxTimeMicros()); + opCtx->setDeadlineAfterNowBy(cursor->getLeftoverMaxTimeMicros(), + ErrorCodes::MaxTimeMSExpired); } } if (!cursor->isAwaitData()) { diff --git a/src/mongo/db/exec/cached_plan.h b/src/mongo/db/exec/cached_plan.h index 658312db4a0..9a2ec1a1b81 100644 --- a/src/mongo/db/exec/cached_plan.h +++ b/src/mongo/db/exec/cached_plan.h @@ -112,7 +112,7 @@ private: * * Returns a non-OK status if query planning fails. In particular, this function returns * ErrorCodes::QueryPlanKilled if the query plan was killed during a yield, or - * ErrorCodes::ExceededTimeLimit if the operation exceeded its time limit. + * ErrorCodes::MaxTimeMSExpired if the operation exceeded its time limit. */ Status tryYield(PlanYieldPolicy* yieldPolicy); diff --git a/src/mongo/db/exec/subplan.cpp b/src/mongo/db/exec/subplan.cpp index 0ece253d30b..5d5c85d45fc 100644 --- a/src/mongo/db/exec/subplan.cpp +++ b/src/mongo/db/exec/subplan.cpp @@ -433,13 +433,6 @@ Status SubplanStage::pickBestPlan(PlanYieldPolicy* yieldPolicy) { // Plan each branch of the $or. Status subplanningStatus = planSubqueries(); if (!subplanningStatus.isOK()) { - if (subplanningStatus == ErrorCodes::QueryPlanKilled || - subplanningStatus == ErrorCodes::ExceededTimeLimit) { - // Query planning cannot continue if the plan for one of the subqueries was killed - // because the collection or a candidate index may have been dropped, or if we've - // exceeded the operation's time limit. - return subplanningStatus; - } return choosePlanWholeQuery(yieldPolicy); } @@ -448,7 +441,7 @@ Status SubplanStage::pickBestPlan(PlanYieldPolicy* yieldPolicy) { Status subplanSelectStat = choosePlanForSubqueries(yieldPolicy); if (!subplanSelectStat.isOK()) { if (subplanSelectStat == ErrorCodes::QueryPlanKilled || - subplanSelectStat == ErrorCodes::ExceededTimeLimit) { + subplanSelectStat == ErrorCodes::MaxTimeMSExpired) { // Query planning cannot continue if the plan for one of the subqueries was killed // because the collection or a candidate index may have been dropped, or if we've // exceeded the operation's time limit. diff --git a/src/mongo/db/exec/subplan.h b/src/mongo/db/exec/subplan.h index c61fb3201d4..a05ac4e2955 100644 --- a/src/mongo/db/exec/subplan.h +++ b/src/mongo/db/exec/subplan.h @@ -103,7 +103,7 @@ public: * * Returns a non-OK status if query planning fails. In particular, this function returns * ErrorCodes::QueryPlanKilled if the query plan was killed during a yield, or - * ErrorCodes::ExceededTimeLimit if the operation has exceeded its time limit. + * ErrorCodes::MaxTimeMSExpired if the operation has exceeded its time limit. */ Status pickBestPlan(PlanYieldPolicy* yieldPolicy); diff --git a/src/mongo/db/keys_collection_manager_sharding_test.cpp b/src/mongo/db/keys_collection_manager_sharding_test.cpp index d21db07a5ff..005eaf049d8 100644 --- a/src/mongo/db/keys_collection_manager_sharding_test.cpp +++ b/src/mongo/db/keys_collection_manager_sharding_test.cpp @@ -87,7 +87,8 @@ private: }; TEST_F(KeysManagerShardedTest, GetKeyForValidationTimesOutIfRefresherIsNotRunning) { - operationContext()->setDeadlineAfterNowBy(Microseconds(250 * 1000)); + operationContext()->setDeadlineAfterNowBy(Microseconds(250 * 1000), + ErrorCodes::ExceededTimeLimit); ASSERT_THROWS(keyManager() ->getKeyForValidation(operationContext(), 1, LogicalTime(Timestamp(100, 0))) diff --git a/src/mongo/db/operation_context.cpp b/src/mongo/db/operation_context.cpp index f878eead361..091ffdd1ee4 100644 --- a/src/mongo/db/operation_context.cpp +++ b/src/mongo/db/operation_context.cpp @@ -83,11 +83,15 @@ OperationContext::OperationContext(Client* client, unsigned int opId) _elapsedTime(client ? client->getServiceContext()->getTickSource() : SystemTickSource::get()) {} -void OperationContext::setDeadlineAndMaxTime(Date_t when, Microseconds maxTime) { +void OperationContext::setDeadlineAndMaxTime(Date_t when, + Microseconds maxTime, + ErrorCodes::Error timeoutError) { invariant(!getClient()->isInDirectClient()); + invariant(ErrorCodes::isExceededTimeLimitError(timeoutError)); uassert(40120, "Illegal attempt to change operation deadline", !hasDeadline()); _deadline = when; _maxTime = maxTime; + _timeoutError = timeoutError; } Microseconds OperationContext::computeMaxTimeFromDeadline(Date_t when) { @@ -103,11 +107,11 @@ Microseconds OperationContext::computeMaxTimeFromDeadline(Date_t when) { return maxTime; } -void OperationContext::setDeadlineByDate(Date_t when) { - setDeadlineAndMaxTime(when, computeMaxTimeFromDeadline(when)); +void OperationContext::setDeadlineByDate(Date_t when, ErrorCodes::Error timeoutError) { + setDeadlineAndMaxTime(when, computeMaxTimeFromDeadline(when), timeoutError); } -void OperationContext::setDeadlineAfterNowBy(Microseconds maxTime) { +void OperationContext::setDeadlineAfterNowBy(Microseconds maxTime, ErrorCodes::Error timeoutError) { Date_t when; if (maxTime < Microseconds::zero()) { maxTime = Microseconds::zero(); @@ -121,7 +125,7 @@ void OperationContext::setDeadlineAfterNowBy(Microseconds maxTime) { when += clock->getPrecision() + maxTime; } } - setDeadlineAndMaxTime(when, maxTime); + setDeadlineAndMaxTime(when, maxTime, timeoutError); } bool OperationContext::hasDeadlineExpired() const { @@ -195,8 +199,8 @@ Status OperationContext::checkForInterruptNoAssert() { } if (hasDeadlineExpired()) { - markKilled(ErrorCodes::ExceededTimeLimit); - return Status(ErrorCodes::ExceededTimeLimit, "operation exceeded time limit"); + markKilled(_timeoutError); + return Status(_timeoutError, "operation exceeded time limit"); } MONGO_FAIL_POINT_BLOCK(checkForInterruptFail, scopedFailPoint) { @@ -298,7 +302,7 @@ StatusWith<stdx::cv_status> OperationContext::waitForConditionOrInterruptNoAsser // that we expect to time out at the same time as the existing deadline expires. If, when we // time out, we find that the op's deadline has not expired (as will always be the case if // maxTimeNeverTimeOut is set) then we assume that the incongruity is due to a clock mismatch - // and return ExceededTimeLimit regardless. To prevent this behaviour, only consider the op's + // and return _timeoutError regardless. To prevent this behaviour, only consider the op's // deadline in the event that the maxTimeNeverTimeOut failpoint is not set. bool opHasDeadline = (hasDeadline() && !MONGO_FAIL_POINT(maxTimeNeverTimeOut)); @@ -334,8 +338,8 @@ StatusWith<stdx::cv_status> OperationContext::waitForConditionOrInterruptNoAsser // is slightly ahead of the FastClock used in checkForInterrupt. In this case, // we treat the operation as though it has exceeded its time limit, just as if the // FastClock and system clock had agreed. - markKilled(ErrorCodes::ExceededTimeLimit); - return Status(ErrorCodes::ExceededTimeLimit, "operation exceeded time limit"); + markKilled(_timeoutError); + return Status(_timeoutError, "operation exceeded time limit"); } return waitStatus; } diff --git a/src/mongo/db/operation_context.h b/src/mongo/db/operation_context.h index c188f43c103..96c2fecc76e 100644 --- a/src/mongo/db/operation_context.h +++ b/src/mongo/db/operation_context.h @@ -377,22 +377,22 @@ public: * * To remove a deadline, pass in Date_t::max(). */ - void setDeadlineByDate(Date_t when); + void setDeadlineByDate(Date_t when, ErrorCodes::Error timeoutError); /** * Sets the deadline for this operation to the maxTime plus the current time reported * by the ServiceContext's fast clock source. */ - void setDeadlineAfterNowBy(Microseconds maxTime); + void setDeadlineAfterNowBy(Microseconds maxTime, ErrorCodes::Error timeoutError); template <typename D> - void setDeadlineAfterNowBy(D maxTime) { + void setDeadlineAfterNowBy(D maxTime, ErrorCodes::Error timeoutError) { if (maxTime <= D::zero()) { maxTime = D::zero(); } if (maxTime <= Microseconds::max()) { - setDeadlineAfterNowBy(duration_cast<Microseconds>(maxTime)); + setDeadlineAfterNowBy(duration_cast<Microseconds>(maxTime), timeoutError); } else { - setDeadlineByDate(Date_t::max()); + setDeadlineByDate(Date_t::max(), timeoutError); } } @@ -436,7 +436,7 @@ private: * Sets the deadline and maxTime as described. It is up to the caller to ensure that * these correctly correspond. */ - void setDeadlineAndMaxTime(Date_t when, Microseconds maxTime); + void setDeadlineAndMaxTime(Date_t when, Microseconds maxTime, ErrorCodes::Error timeoutError); /** * Compute maxTime based on the given deadline. @@ -501,6 +501,8 @@ private: Date_t _deadline = Date_t::max(); // The timepoint at which this operation exceeds its time limit. + ErrorCodes::Error _timeoutError = ErrorCodes::ExceededTimeLimit; + // Max operation time requested by the user or by the cursor in the case of a getMore with no // user-specified maxTime. This is tracked with microsecond granularity for the purpose of // assigning unused execution time back to a cursor at the end of an operation, only. The diff --git a/src/mongo/db/operation_context_test.cpp b/src/mongo/db/operation_context_test.cpp index 751aee986cc..f3e25164201 100644 --- a/src/mongo/db/operation_context_test.cpp +++ b/src/mongo/db/operation_context_test.cpp @@ -218,7 +218,7 @@ public: TEST_F(OperationDeadlineTests, OperationDeadlineExpiration) { auto opCtx = client->makeOperationContext(); - opCtx->setDeadlineAfterNowBy(Seconds{1}); + opCtx->setDeadlineAfterNowBy(Seconds{1}, ErrorCodes::ExceededTimeLimit); mockClock->advance(Milliseconds{500}); ASSERT_OK(opCtx->checkForInterruptNoAssert()); @@ -246,7 +246,7 @@ TEST_F(OperationDeadlineTests, OperationDeadlineExpiration) { template <typename D> void assertLargeRelativeDeadlineLikeInfinity(Client& client, D maxTime) { auto opCtx = client.makeOperationContext(); - opCtx->setDeadlineAfterNowBy(maxTime); + opCtx->setDeadlineAfterNowBy(maxTime, ErrorCodes::ExceededTimeLimit); ASSERT_FALSE(opCtx->hasDeadline()) << "Tried to set maxTime to " << maxTime; } @@ -275,7 +275,7 @@ TEST_F(OperationDeadlineTests, VeryLargeRelativeDeadlinesNanoseconds) { // Nanoseconds::max() is less than Microseconds::max(), so it is possible to set // a deadline of that duration. auto opCtx = client->makeOperationContext(); - opCtx->setDeadlineAfterNowBy(Nanoseconds::max()); + opCtx->setDeadlineAfterNowBy(Nanoseconds::max(), ErrorCodes::ExceededTimeLimit); ASSERT_TRUE(opCtx->hasDeadline()); ASSERT_EQ(mockClock->now() + mockClock->getPrecision() + duration_cast<Milliseconds>(Nanoseconds::max()), @@ -284,7 +284,7 @@ TEST_F(OperationDeadlineTests, VeryLargeRelativeDeadlinesNanoseconds) { TEST_F(OperationDeadlineTests, WaitForMaxTimeExpiredCV) { auto opCtx = client->makeOperationContext(); - opCtx->setDeadlineByDate(mockClock->now()); + opCtx->setDeadlineByDate(mockClock->now(), ErrorCodes::ExceededTimeLimit); stdx::mutex m; stdx::condition_variable cv; stdx::unique_lock<stdx::mutex> lk(m); @@ -293,7 +293,7 @@ TEST_F(OperationDeadlineTests, WaitForMaxTimeExpiredCV) { TEST_F(OperationDeadlineTests, WaitForMaxTimeExpiredCVWithWaitUntilSet) { auto opCtx = client->makeOperationContext(); - opCtx->setDeadlineByDate(mockClock->now()); + opCtx->setDeadlineByDate(mockClock->now(), ErrorCodes::ExceededTimeLimit); stdx::mutex m; stdx::condition_variable cv; stdx::unique_lock<stdx::mutex> lk(m); @@ -324,7 +324,7 @@ TEST_F(OperationDeadlineTests, WaitForUntilExpiredCV) { TEST_F(OperationDeadlineTests, WaitForUntilExpiredCVWithMaxTimeSet) { auto opCtx = client->makeOperationContext(); - opCtx->setDeadlineByDate(mockClock->now() + Seconds{10}); + opCtx->setDeadlineByDate(mockClock->now() + Seconds{10}, ErrorCodes::ExceededTimeLimit); stdx::mutex m; stdx::condition_variable cv; stdx::unique_lock<stdx::mutex> lk(m); @@ -344,7 +344,7 @@ TEST_F(OperationDeadlineTests, WaitForDurationExpired) { TEST_F(OperationDeadlineTests, DuringWaitMaxTimeExpirationDominatesUntilExpiration) { auto opCtx = client->makeOperationContext(); - opCtx->setDeadlineByDate(mockClock->now()); + opCtx->setDeadlineByDate(mockClock->now(), ErrorCodes::ExceededTimeLimit); stdx::mutex m; stdx::condition_variable cv; stdx::unique_lock<stdx::mutex> lk(m); @@ -379,7 +379,7 @@ public: auto barrier = std::make_shared<unittest::Barrier>(2); auto task = stdx::packaged_task<bool()>([=] { if (maxTime < Date_t::max()) { - opCtx->setDeadlineByDate(maxTime); + opCtx->setDeadlineByDate(maxTime, ErrorCodes::ExceededTimeLimit); } auto predicate = [state] { return state->isSignaled; }; stdx::unique_lock<stdx::mutex> lk(state->mutex); diff --git a/src/mongo/db/query/find.cpp b/src/mongo/db/query/find.cpp index 249a61349fb..3d17df3f4e7 100644 --- a/src/mongo/db/query/find.cpp +++ b/src/mongo/db/query/find.cpp @@ -368,7 +368,8 @@ Message getMore(OperationContext* opCtx, uassert(40136, "Illegal attempt to set operation deadline within DBDirectClient", !opCtx->getClient()->isInDirectClient()); - opCtx->setDeadlineAfterNowBy(cc->getLeftoverMaxTimeMicros()); + opCtx->setDeadlineAfterNowBy(cc->getLeftoverMaxTimeMicros(), + ErrorCodes::MaxTimeMSExpired); } opCtx->checkForInterrupt(); // May trigger maxTimeAlwaysTimeOut fail point. @@ -589,7 +590,7 @@ std::string runQuery(OperationContext* opCtx, uassert(40116, "Illegal attempt to set operation deadline within DBDirectClient", !opCtx->getClient()->isInDirectClient()); - opCtx->setDeadlineAfterNowBy(Milliseconds{qr.getMaxTimeMS()}); + opCtx->setDeadlineAfterNowBy(Milliseconds{qr.getMaxTimeMS()}, ErrorCodes::MaxTimeMSExpired); } opCtx->checkForInterrupt(); // May trigger maxTimeAlwaysTimeOut fail point. diff --git a/src/mongo/db/query/plan_executor.h b/src/mongo/db/query/plan_executor.h index a85665a8356..a8144c2e9be 100644 --- a/src/mongo/db/query/plan_executor.h +++ b/src/mongo/db/query/plan_executor.h @@ -298,7 +298,7 @@ public: * Returns ErrorCodes::QueryPlanKilled if the PlanExecutor was killed while saved. * * If allowed, will yield and retry if a WriteConflictException is encountered. If the time - * limit is exceeded during this retry process, returns ErrorCodes::ExceededTimeLimit. If this + * limit is exceeded during this retry process, returns ErrorCodes::MaxTimeMSExpired. If this * PlanExecutor is killed during this retry process, returns ErrorCodes::QueryPlanKilled. In * this scenario, locks will have been released, and will not be held when control returns to * the caller. diff --git a/src/mongo/db/s/namespace_metadata_change_notifications_test.cpp b/src/mongo/db/s/namespace_metadata_change_notifications_test.cpp index 155eed7cae3..6f55ce54dd2 100644 --- a/src/mongo/db/s/namespace_metadata_change_notifications_test.cpp +++ b/src/mongo/db/s/namespace_metadata_change_notifications_test.cpp @@ -67,7 +67,7 @@ TEST_F(NamespaceMetadataChangeNotificationsTest, WaitForNotify) { { auto opCtx = client()->makeOperationContext(); - opCtx->setDeadlineAfterNowBy(Milliseconds{0}); + opCtx->setDeadlineAfterNowBy(Milliseconds{0}, ErrorCodes::ExceededTimeLimit); ASSERT_THROWS_CODE( scopedNotif.get(opCtx.get()), AssertionException, ErrorCodes::ExceededTimeLimit); } @@ -85,9 +85,8 @@ TEST_F(NamespaceMetadataChangeNotificationsTest, GiveUpWaitingForNotify) { { auto scopedNotif = notifications.createNotification(kNss); - auto opCtx = client()->makeOperationContext(); - opCtx->setDeadlineAfterNowBy(Milliseconds{0}); + opCtx->setDeadlineAfterNowBy(Milliseconds{0}, ErrorCodes::ExceededTimeLimit); ASSERT_THROWS_CODE( scopedNotif.get(opCtx.get()), AssertionException, ErrorCodes::ExceededTimeLimit); } @@ -103,7 +102,7 @@ TEST_F(NamespaceMetadataChangeNotificationsTest, MoveConstructionWaitForNotify) { auto opCtx = client()->makeOperationContext(); - opCtx->setDeadlineAfterNowBy(Milliseconds{0}); + opCtx->setDeadlineAfterNowBy(Milliseconds{0}, ErrorCodes::ExceededTimeLimit); ASSERT_THROWS_CODE( movedScopedNotif.get(opCtx.get()), AssertionException, ErrorCodes::ExceededTimeLimit); } diff --git a/src/mongo/db/service_entry_point_common.cpp b/src/mongo/db/service_entry_point_common.cpp index d935724a5c4..b6a9e7dad84 100644 --- a/src/mongo/db/service_entry_point_common.cpp +++ b/src/mongo/db/service_entry_point_common.cpp @@ -798,7 +798,7 @@ void execCommandDatabase(OperationContext* opCtx, uassert(40119, "Illegal attempt to set operation deadline within DBDirectClient", !opCtx->getClient()->isInDirectClient()); - opCtx->setDeadlineAfterNowBy(Milliseconds{maxTimeMS}); + opCtx->setDeadlineAfterNowBy(Milliseconds{maxTimeMS}, ErrorCodes::MaxTimeMSExpired); } auto& readConcernArgs = repl::ReadConcernArgs::get(opCtx); diff --git a/src/mongo/db/service_entry_point_mongod.cpp b/src/mongo/db/service_entry_point_mongod.cpp index 4ba450faa74..488bdcba0bc 100644 --- a/src/mongo/db/service_entry_point_mongod.cpp +++ b/src/mongo/db/service_entry_point_mongod.cpp @@ -57,7 +57,7 @@ public: opCtx, repl::ReadConcernArgs::get(opCtx), invocation->allowsAfterClusterTime()); if (!rcStatus.isOK()) { - if (rcStatus == ErrorCodes::ExceededTimeLimit) { + if (ErrorCodes::isExceededTimeLimitError(rcStatus.code())) { const int debugLevel = serverGlobalParams.clusterRole == ClusterRole::ConfigServer ? 0 : 2; LOG(debugLevel) << "Command on database " << request.getDatabase() diff --git a/src/mongo/s/commands/strategy.cpp b/src/mongo/s/commands/strategy.cpp index 2d65a906a3e..d81fa109591 100644 --- a/src/mongo/s/commands/strategy.cpp +++ b/src/mongo/s/commands/strategy.cpp @@ -320,7 +320,7 @@ void runCommand(OperationContext* opCtx, const int maxTimeMS = uassertStatusOK( QueryRequest::parseMaxTimeMS(request.body[QueryRequest::cmdOptionMaxTimeMS])); if (maxTimeMS > 0 && command->getLogicalOp() != LogicalOp::opGetMore) { - opCtx->setDeadlineAfterNowBy(Milliseconds{maxTimeMS}); + opCtx->setDeadlineAfterNowBy(Milliseconds{maxTimeMS}, ErrorCodes::MaxTimeMSExpired); } opCtx->checkForInterrupt(); // May trigger maxTimeAlwaysTimeOut fail point. @@ -478,7 +478,8 @@ DbResponse Strategy::queryOp(OperationContext* opCtx, const NamespaceString& nss uassert(50749, "Illegal attempt to set operation deadline within DBDirectClient", !opCtx->getClient()->isInDirectClient()); - opCtx->setDeadlineAfterNowBy(Milliseconds{queryRequest.getMaxTimeMS()}); + opCtx->setDeadlineAfterNowBy(Milliseconds{queryRequest.getMaxTimeMS()}, + ErrorCodes::MaxTimeMSExpired); } opCtx->checkForInterrupt(); // May trigger maxTimeAlwaysTimeOut fail point. diff --git a/src/mongo/s/query/cluster_find.cpp b/src/mongo/s/query/cluster_find.cpp index 0cc9cc3a336..367c2303be9 100644 --- a/src/mongo/s/query/cluster_find.cpp +++ b/src/mongo/s/query/cluster_find.cpp @@ -397,7 +397,8 @@ Status setUpOperationContextStateForGetMore(OperationContext* opCtx, "maxTimeMS can only be used with getMore for tailable, awaitData cursors"}; } else if (cursor->getLeftoverMaxTimeMicros() < Microseconds::max()) { // Be sure to do this only for non-tailable cursors. - opCtx->setDeadlineAfterNowBy(cursor->getLeftoverMaxTimeMicros()); + opCtx->setDeadlineAfterNowBy(cursor->getLeftoverMaxTimeMicros(), + ErrorCodes::MaxTimeMSExpired); } return Status::OK(); } |