summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaloian Manassiev <kaloian.manassiev@mongodb.com>2019-07-08 07:05:06 -0400
committerKaloian Manassiev <kaloian.manassiev@mongodb.com>2019-07-09 05:59:16 -0400
commit08d395bc9e66e5be6caa5ae59d1eb50c5b053193 (patch)
tree02b40889b8a93b3b930f0bc85c9f50e50950d1f2
parent649a497253bb9d2c81a67209319a0846de1a98f6 (diff)
downloadmongo-08d395bc9e66e5be6caa5ae59d1eb50c5b053193.tar.gz
SERVER-41866 On term mismatch do not invoke the getDatabase callback under mutex`
(cherry picked from commit 75dc5684d4c6be0e8ac7c653f5389df9f45f1baf)
-rw-r--r--src/mongo/db/s/shard_server_catalog_cache_loader.cpp47
1 files changed, 19 insertions, 28 deletions
diff --git a/src/mongo/db/s/shard_server_catalog_cache_loader.cpp b/src/mongo/db/s/shard_server_catalog_cache_loader.cpp
index 81f8adef9cf..3eb28c2c9c7 100644
--- a/src/mongo/db/s/shard_server_catalog_cache_loader.cpp
+++ b/src/mongo/db/s/shard_server_catalog_cache_loader.cpp
@@ -440,44 +440,35 @@ void ShardServerCatalogCacheLoader::getDatabase(
return;
}
- long long currentTerm;
bool isPrimary;
-
- {
- // Take the mutex so that we can discern whether we're primary or secondary and schedule a
- // task with the corresponding _term value.
+ long long term;
+ std::tie(isPrimary, term) = [&] {
stdx::lock_guard<stdx::mutex> lock(_mutex);
- invariant(_role != ReplicaSetRole::None);
-
- currentTerm = _term;
- isPrimary = (_role == ReplicaSetRole::Primary);
- }
+ return std::make_tuple(_role == ReplicaSetRole::Primary, _term);
+ }();
uassertStatusOK(_threadPool.schedule(
- [ this, name = dbName.toString(), callbackFn, isPrimary, currentTerm ]() noexcept {
+ [ this, name = dbName.toString(), callbackFn, isPrimary, term ]() noexcept {
auto context = _contexts.makeOperationContext(*Client::getCurrent());
+ auto const opCtx = context.opCtx();
- {
- stdx::lock_guard<stdx::mutex> lock(_mutex);
-
- // We may have missed an OperationContextGroup interrupt since this operation began
- // but before the OperationContext was added to the group. So we'll check that
- // we're still in the same _term.
- if (_term != currentTerm) {
- callbackFn(context.opCtx(),
- Status{ErrorCodes::Interrupted,
- "Unable to refresh routing table because replica set state "
- "changed or node is shutting down."});
- return;
+ try {
+ {
+ // We may have missed an OperationContextGroup interrupt since this operation
+ // began but before the OperationContext was added to the group. So we'll check
+ // that we're still in the same _term.
+ stdx::lock_guard<stdx::mutex> lock(_mutex);
+ uassert(
+ ErrorCodes::InterruptedDueToReplStateChange,
+ "Unable to refresh database because replica set state changed or the node "
+ "is shutting down.",
+ _term == term);
}
- }
- try {
if (isPrimary) {
- _schedulePrimaryGetDatabase(
- context.opCtx(), StringData(name), currentTerm, callbackFn);
+ _schedulePrimaryGetDatabase(opCtx, name, term, callbackFn);
} else {
- _runSecondaryGetDatabase(context.opCtx(), StringData(name), callbackFn);
+ _runSecondaryGetDatabase(opCtx, name, callbackFn);
}
} catch (const DBException& ex) {
callbackFn(context.opCtx(), ex.toStatus());