summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Gottlieb <daniel.gottlieb@mongodb.com>2021-03-23 15:29:54 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-10-06 13:51:14 +0000
commit28f46cb15f2ff5bbbd22b45006789bb3edb71872 (patch)
tree708c948e7010396ae2d529378f4c0b21347ce4ad
parentaeb7d315a3e9c8a86dc005cee34a1cc1867b10c8 (diff)
downloadmongo-28f46cb15f2ff5bbbd22b45006789bb3edb71872.tar.gz
SERVER-54064: Periodically clear out the logical session cache on arbiters.
(cherry picked from commit 8b64da4e43b7318a7ab8a7580708195b6de91200)
-rw-r--r--jstests/noPassthrough/server54064.js57
-rw-r--r--src/mongo/db/logical_session_cache_impl.cpp20
-rw-r--r--src/mongo/shell/servers.js4
3 files changed, 67 insertions, 14 deletions
diff --git a/jstests/noPassthrough/server54064.js b/jstests/noPassthrough/server54064.js
new file mode 100644
index 00000000000..e4bbad6e7fd
--- /dev/null
+++ b/jstests/noPassthrough/server54064.js
@@ -0,0 +1,57 @@
+/**
+ * Assert that arbiters periodically clear out their logical session cache. Inability to do so
+ * prohibits new clients from connecting.
+ *
+ * @tags: [requires_replication]
+ */
+(function() {
+const name = "server54064";
+const replSet = new ReplSetTest({
+ name: name,
+ nodes: 2,
+ // `disableLogicalSessionCacheRefresh` is true by default, but is disabled for testing purposes
+ // in servers spawned from the shell.
+ nodeOptions: {
+ setParameter: {
+ // Each refresh on an arbiter will empty the cache.
+ logicalSessionRefreshMillis: 10000,
+ // The number of connections/sessions before the cache is full, prohibiting new clients
+ // from connecting.
+ maxSessions: 3,
+ disableLogicalSessionCacheRefresh: false
+ }
+ }
+});
+const nodes = replSet.nodeList();
+
+replSet.startSet();
+replSet.initiate({
+ _id: name,
+ members: [{_id: 0, host: nodes[0]}, {_id: 1, host: nodes[1], arbiterOnly: true}],
+});
+
+let arbConn = replSet.getArbiter();
+assert.soon(() => {
+ // Connect to mongo in a tight loop to exhaust the number of available logical sessions in the
+ // cache.
+ const result = new Mongo(arbConn.host).adminCommand({hello: 1});
+ if (result['ok'] === 0) {
+ assert.commandFailedWithCode(result, ErrorCodes.TooManyLogicalSessions);
+ return true;
+ }
+ return false;
+});
+
+assert.soon(() => {
+ // Once we observe that the number of sessions is maxed out, loop again to confirm that the
+ // cache eventually does get cleared.
+ const result = new Mongo(arbConn.host).adminCommand({hello: 1});
+ if (result['ok'] === 0) {
+ assert.commandFailedWithCode(result, ErrorCodes.TooManyLogicalSessions);
+ return false;
+ }
+ return true;
+});
+
+replSet.stopSet();
+})();
diff --git a/src/mongo/db/logical_session_cache_impl.cpp b/src/mongo/db/logical_session_cache_impl.cpp
index 857e33b1568..349da7906f9 100644
--- a/src/mongo/db/logical_session_cache_impl.cpp
+++ b/src/mongo/db/logical_session_cache_impl.cpp
@@ -182,19 +182,11 @@ Status LogicalSessionCacheImpl::_reap(Client* client) {
try {
_sessionsColl->checkSessionsCollectionExists(opCtx);
} catch (const DBException& ex) {
- if (ex.code() != ErrorCodes::NamespaceNotFound ||
- ex.code() != ErrorCodes::NamespaceNotSharded) {
- LOGV2(
- 20712,
- "Sessions collection is not set up: {error}; waiting until next sessions reap "
- "interval",
- "Sessions collection is not set up; waiting until next sessions reap interval",
- "error"_attr = redact(ex));
- } else {
- LOGV2(20713,
- "Sessions collection is not set up because the namespace is either not found"
- "or not sharded; waiting until next sessions reap interval");
- }
+ LOGV2(20712,
+ "Sessions collection is not set up: {error}; waiting until next sessions reap "
+ "interval",
+ "Sessions collection is not set up; waiting until next sessions reap interval",
+ "error"_attr = redact(ex));
return Status::OK();
}
numReaped = _reapSessionsOlderThanFn(opCtx,
@@ -235,6 +227,8 @@ void LogicalSessionCacheImpl::_refresh(Client* client) {
const auto replCoord = repl::ReplicationCoordinator::get(opCtx);
if (replCoord && replCoord->isReplEnabled() && replCoord->getMemberState().arbiter()) {
+ stdx::lock_guard<Latch> lk(_mutex);
+ _activeSessions.clear();
return;
}
diff --git a/src/mongo/shell/servers.js b/src/mongo/shell/servers.js
index b5ee35bab4d..a60fcf8fe2a 100644
--- a/src/mongo/shell/servers.js
+++ b/src/mongo/shell/servers.js
@@ -1137,7 +1137,9 @@ function appendSetParameterArgs(argArray) {
}
// Disable background cache refreshing to avoid races in tests
- argArray.push(...['--setParameter', "disableLogicalSessionCacheRefresh=true"]);
+ if (!argArrayContainsSetParameterValue('disableLogicalSessionCacheRefresh=')) {
+ argArray.push(...['--setParameter', "disableLogicalSessionCacheRefresh=true"]);
+ }
}
// Since options may not be backward compatible, mongos options are not