summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBlake Oler <blake.oler@mongodb.com>2018-10-10 10:48:11 -0400
committerBlake Oler <blake.oler@mongodb.com>2018-10-23 13:41:16 -0400
commit3bf02defe2e16b9de339fca4717d3d65ee779eac (patch)
treea78ef143579f90335ebb5e46cca353b7c05d2213
parent9be23c49029e66765df3ff4569998e28ad75d2ee (diff)
downloadmongo-3bf02defe2e16b9de339fca4717d3d65ee779eac.tar.gz
SERVER-36964 Prevent secondaries in SessionsCollectionRS from attempting to set up the sessions collection.
(cherry picked from commit c388d2db35d576862ebf42758686df340bc0bb9f)
-rw-r--r--jstests/replsets/refresh_sessions_rs.js6
-rw-r--r--jstests/replsets/sessions_collection_auto_healing.js14
-rw-r--r--src/mongo/db/logical_session_cache_impl.cpp23
-rw-r--r--src/mongo/db/sessions_collection.cpp4
-rw-r--r--src/mongo/db/sessions_collection.h6
-rw-r--r--src/mongo/db/sessions_collection_config_server.cpp4
-rw-r--r--src/mongo/db/sessions_collection_config_server.h5
-rw-r--r--src/mongo/db/sessions_collection_mock.h4
-rw-r--r--src/mongo/db/sessions_collection_rs.cpp30
-rw-r--r--src/mongo/db/sessions_collection_rs.h5
-rw-r--r--src/mongo/db/sessions_collection_sharded.cpp6
-rw-r--r--src/mongo/db/sessions_collection_sharded.h6
-rw-r--r--src/mongo/db/sessions_collection_standalone.cpp21
-rw-r--r--src/mongo/db/sessions_collection_standalone.h5
14 files changed, 112 insertions, 27 deletions
diff --git a/jstests/replsets/refresh_sessions_rs.js b/jstests/replsets/refresh_sessions_rs.js
index caae49a5801..1574a18fc49 100644
--- a/jstests/replsets/refresh_sessions_rs.js
+++ b/jstests/replsets/refresh_sessions_rs.js
@@ -26,9 +26,13 @@
var res;
- // Trigger an initial refresh on all members, as a sanity check.
+ // The primary needs to create the sessions collection so that the secondaries can act upon it.
+ // This is done by an initial refresh of the primary.
res = db1.runCommand(refresh);
assert.commandWorked(res, "failed to refresh");
+ replTest.awaitReplication();
+
+ // Trigger an initial refresh on secondaries as a sanity check.
res = db2.runCommand(refresh);
assert.commandWorked(res, "failed to refresh");
res = db3.runCommand(refresh);
diff --git a/jstests/replsets/sessions_collection_auto_healing.js b/jstests/replsets/sessions_collection_auto_healing.js
index c56fb24639a..ed332241921 100644
--- a/jstests/replsets/sessions_collection_auto_healing.js
+++ b/jstests/replsets/sessions_collection_auto_healing.js
@@ -45,7 +45,7 @@ load('jstests/libs/sessions_collection.js');
validateSessionsCollection(secondary, false, false);
}
- // Test that a refresh on a secondary creates the sessions collection.
+ // Test that a refresh on a secondary does not create the sessions collection.
{
validateSessionsCollection(primary, false, false);
@@ -54,15 +54,13 @@ load('jstests/libs/sessions_collection.js');
assert.commandWorked(secondaryAdmin.runCommand({refreshLogicalSessionCacheNow: 1}));
- validateSessionsCollection(primary, true, true);
+ validateSessionsCollection(primary, false, false);
replTest.awaitReplication();
- validateSessionsCollection(secondary, true, true);
+ validateSessionsCollection(secondary, false, false);
}
// Test that a refresh on the primary creates the sessions collection.
{
- assert.commandWorked(primary.getDB("config").runCommand(
- {drop: "system.sessions", writeConcern: {w: "majority"}}));
validateSessionsCollection(primary, false, false);
replTest.awaitReplication();
@@ -73,7 +71,7 @@ load('jstests/libs/sessions_collection.js');
validateSessionsCollection(primary, true, true);
}
- // Test that a refresh on a secondary will create the TTL index on the sessions collection.
+ // Test that a refresh on a secondary will not create the TTL index on the sessions collection.
{
assert.commandWorked(primary.getDB("config").system.sessions.dropIndex({lastUse: 1}));
@@ -81,13 +79,11 @@ load('jstests/libs/sessions_collection.js');
assert.commandWorked(secondaryAdmin.runCommand({refreshLogicalSessionCacheNow: 1}));
- validateSessionsCollection(primary, true, true);
+ validateSessionsCollection(primary, true, false);
}
// Test that a refresh on the primary will create the TTL index on the sessions collection.
{
- assert.commandWorked(primary.getDB("config").system.sessions.dropIndex({lastUse: 1}));
-
validateSessionsCollection(primary, true, false);
assert.commandWorked(primaryAdmin.runCommand({refreshLogicalSessionCacheNow: 1}));
diff --git a/src/mongo/db/logical_session_cache_impl.cpp b/src/mongo/db/logical_session_cache_impl.cpp
index 69876f5aa92..33fc16209d3 100644
--- a/src/mongo/db/logical_session_cache_impl.cpp
+++ b/src/mongo/db/logical_session_cache_impl.cpp
@@ -220,10 +220,18 @@ Status LogicalSessionCacheImpl::_reap(Client* client) {
return uniqueCtx->get();
}();
- auto res = _sessionsColl->setupSessionsCollection(opCtx);
- if (!res.isOK()) {
- log() << "Sessions collection is not set up; "
- << "waiting until next sessions reap interval: " << res.reason();
+ auto existsStatus = _sessionsColl->checkSessionsCollectionExists(opCtx);
+ if (!existsStatus.isOK()) {
+ StringData notSetUpWarning =
+ "Sessions collection is not set up; "
+ "waiting until next sessions reap interval";
+ if (existsStatus.code() != ErrorCodes::NamespaceNotFound ||
+ existsStatus.code() != ErrorCodes::NamespaceNotSharded) {
+ log() << notSetUpWarning << ": " << existsStatus.reason();
+ } else {
+ log() << notSetUpWarning;
+ }
+
return Status::OK();
}
@@ -291,10 +299,11 @@ void LogicalSessionCacheImpl::_refresh(Client* client) {
return uniqueCtx->get();
}();
- auto res = _sessionsColl->setupSessionsCollection(opCtx);
- if (!res.isOK()) {
+ auto setupStatus = _sessionsColl->setupSessionsCollection(opCtx);
+
+ if (!setupStatus.isOK()) {
log() << "Sessions collection is not set up; "
- << "waiting until next sessions refresh interval: " << res.reason();
+ << "waiting until next sessions refresh interval: " << setupStatus.reason();
return;
}
diff --git a/src/mongo/db/sessions_collection.cpp b/src/mongo/db/sessions_collection.cpp
index eee9445d85c..05b6df1666c 100644
--- a/src/mongo/db/sessions_collection.cpp
+++ b/src/mongo/db/sessions_collection.cpp
@@ -48,6 +48,8 @@
namespace mongo {
+constexpr StringData SessionsCollection::kSessionsTTLIndex;
+
namespace {
// This batch size is chosen to ensure that we don't form requests larger than the 16mb limit.
@@ -304,7 +306,7 @@ StatusWith<LogicalSessionIdSet> SessionsCollection::doFetch(const NamespaceStrin
BSONObj SessionsCollection::generateCreateIndexesCmd() {
NewIndexSpec index;
index.setKey(BSON("lastUse" << 1));
- index.setName("lsidTTLIndex");
+ index.setName(kSessionsTTLIndex);
index.setExpireAfterSeconds(localLogicalSessionTimeoutMinutes * 60);
std::vector<NewIndexSpec> indexes;
diff --git a/src/mongo/db/sessions_collection.h b/src/mongo/db/sessions_collection.h
index 46df9465af8..e592e9a7b5d 100644
--- a/src/mongo/db/sessions_collection.h
+++ b/src/mongo/db/sessions_collection.h
@@ -50,6 +50,7 @@ class SessionsCollection {
public:
static const NamespaceString kSessionsNamespaceString;
+ static constexpr StringData kSessionsTTLIndex = "lsidTTLIndex"_sd;
virtual ~SessionsCollection();
@@ -59,6 +60,11 @@ public:
virtual Status setupSessionsCollection(OperationContext* opCtx) = 0;
/**
+ * Checks if the sessions collection exists and has the proper indexes.
+ */
+ virtual Status checkSessionsCollectionExists(OperationContext* opCtx) = 0;
+
+ /**
* Updates the last-use times on the given sessions to be greater than
* or equal to the given time. Returns an error if a networking issue occurred.
*/
diff --git a/src/mongo/db/sessions_collection_config_server.cpp b/src/mongo/db/sessions_collection_config_server.cpp
index 21d04d409db..251a8e0dc62 100644
--- a/src/mongo/db/sessions_collection_config_server.cpp
+++ b/src/mongo/db/sessions_collection_config_server.cpp
@@ -138,4 +138,8 @@ Status SessionsCollectionConfigServer::setupSessionsCollection(OperationContext*
}
}
+Status SessionsCollectionConfigServer::checkSessionsCollectionExists(OperationContext* opCtx) {
+ return _checkCacheForSessionsCollection(opCtx);
+}
+
} // namespace mongo
diff --git a/src/mongo/db/sessions_collection_config_server.h b/src/mongo/db/sessions_collection_config_server.h
index 65138e94d49..2e80ca90fca 100644
--- a/src/mongo/db/sessions_collection_config_server.h
+++ b/src/mongo/db/sessions_collection_config_server.h
@@ -56,6 +56,11 @@ public:
*/
Status setupSessionsCollection(OperationContext* opCtx) override;
+ /**
+ * Checks if the sessions collection exists.
+ */
+ Status checkSessionsCollectionExists(OperationContext* opCtx) override;
+
private:
Status _shardCollectionIfNeeded(OperationContext* opCtx);
Status _generateIndexesIfNeeded(OperationContext* opCtx);
diff --git a/src/mongo/db/sessions_collection_mock.h b/src/mongo/db/sessions_collection_mock.h
index 7d7c3dfd8d8..c7cb1ff5338 100644
--- a/src/mongo/db/sessions_collection_mock.h
+++ b/src/mongo/db/sessions_collection_mock.h
@@ -110,6 +110,10 @@ public:
return Status::OK();
}
+ Status checkSessionsCollectionExists(OperationContext* opCtx) override {
+ return Status::OK();
+ }
+
Status refreshSessions(OperationContext* opCtx,
const LogicalSessionRecordSet& sessions) override {
return _impl->refreshSessions(sessions);
diff --git a/src/mongo/db/sessions_collection_rs.cpp b/src/mongo/db/sessions_collection_rs.cpp
index 683a2bbadbb..5c7bccf44b5 100644
--- a/src/mongo/db/sessions_collection_rs.cpp
+++ b/src/mongo/db/sessions_collection_rs.cpp
@@ -176,14 +176,28 @@ Status SessionsCollectionRS::setupSessionsCollection(OperationContext* opCtx) {
return Status::OK();
},
- [&](DBClientBase* client) {
- BSONObj info;
- auto cmd = generateCreateIndexesCmd();
- if (!client->runCommand(kSessionsNamespaceString.db().toString(), cmd, info)) {
- return getStatusFromCommandResult(info);
- }
- return Status::OK();
- });
+ [&](DBClientBase*) { return checkSessionsCollectionExists(opCtx); });
+}
+
+Status SessionsCollectionRS::checkSessionsCollectionExists(OperationContext* opCtx) {
+ DBDirectClient client(opCtx);
+
+ auto indexes = client.getIndexSpecs(kSessionsNamespaceString.toString());
+
+ if (indexes.size() == 0u) {
+ return Status{ErrorCodes::NamespaceNotFound, "config.system.sessions does not exist"};
+ }
+
+ auto indexExists = std::find_if(indexes.begin(), indexes.end(), [](const BSONObj& index) {
+ return index.getField("name").String() == kSessionsTTLIndex;
+ });
+
+ if (indexExists == indexes.end()) {
+ return Status{ErrorCodes::IndexNotFound,
+ "config.system.sessions does not have the required TTL index"};
+ }
+
+ return Status::OK();
}
Status SessionsCollectionRS::refreshSessions(OperationContext* opCtx,
diff --git a/src/mongo/db/sessions_collection_rs.h b/src/mongo/db/sessions_collection_rs.h
index 9558f92860b..0dfe92fe301 100644
--- a/src/mongo/db/sessions_collection_rs.h
+++ b/src/mongo/db/sessions_collection_rs.h
@@ -61,6 +61,11 @@ public:
Status setupSessionsCollection(OperationContext* opCtx) override;
/**
+ * Checks if the sessions collection exists and has the proper indexes.
+ */
+ Status checkSessionsCollectionExists(OperationContext* opCtx) override;
+
+ /**
* Updates the last-use times on the given sessions to be greater than
* or equal to the current time.
*
diff --git a/src/mongo/db/sessions_collection_sharded.cpp b/src/mongo/db/sessions_collection_sharded.cpp
index 68ea2dbfcf8..1380ad1c10d 100644
--- a/src/mongo/db/sessions_collection_sharded.cpp
+++ b/src/mongo/db/sessions_collection_sharded.cpp
@@ -75,10 +75,14 @@ Status SessionsCollectionSharded::_checkCacheForSessionsCollection(OperationCont
return Status::OK();
}
- return {ErrorCodes::NamespaceNotFound, "config.system.sessions is not yet sharded"};
+ return {ErrorCodes::NamespaceNotFound, "config.system.sessions does not exist"};
}
Status SessionsCollectionSharded::setupSessionsCollection(OperationContext* opCtx) {
+ return checkSessionsCollectionExists(opCtx);
+}
+
+Status SessionsCollectionSharded::checkSessionsCollectionExists(OperationContext* opCtx) {
return _checkCacheForSessionsCollection(opCtx);
}
diff --git a/src/mongo/db/sessions_collection_sharded.h b/src/mongo/db/sessions_collection_sharded.h
index 333c202337e..39e1ff29087 100644
--- a/src/mongo/db/sessions_collection_sharded.h
+++ b/src/mongo/db/sessions_collection_sharded.h
@@ -52,6 +52,12 @@ public:
Status setupSessionsCollection(OperationContext* opCtx) override;
/**
+ * Checks if the sessions collection exists. Does not check if the index exists in the sharded
+ * version of this function.
+ */
+ virtual Status checkSessionsCollectionExists(OperationContext* opCtx) override;
+
+ /**
* Updates the last-use times on the given sessions to be greater than
* or equal to the current time.
*/
diff --git a/src/mongo/db/sessions_collection_standalone.cpp b/src/mongo/db/sessions_collection_standalone.cpp
index 380f62b357c..b8a39186c60 100644
--- a/src/mongo/db/sessions_collection_standalone.cpp
+++ b/src/mongo/db/sessions_collection_standalone.cpp
@@ -65,6 +65,27 @@ Status SessionsCollectionStandalone::setupSessionsCollection(OperationContext* o
return Status::OK();
}
+Status SessionsCollectionStandalone::checkSessionsCollectionExists(OperationContext* opCtx) {
+ DBDirectClient client(opCtx);
+
+ auto indexes = client.getIndexSpecs(kSessionsNamespaceString.toString());
+
+ if (indexes.size() == 0u) {
+ return Status{ErrorCodes::NamespaceNotFound, "config.system.sessions does not exist"};
+ }
+
+ auto indexExists = std::find_if(indexes.begin(), indexes.end(), [](const BSONObj& index) {
+ return index.getField("name").String() == kSessionsTTLIndex;
+ });
+
+ if (indexExists == indexes.end()) {
+ return Status{ErrorCodes::IndexNotFound,
+ "config.system.sessions does not have the required TTL index"};
+ };
+
+ return Status::OK();
+}
+
Status SessionsCollectionStandalone::refreshSessions(OperationContext* opCtx,
const LogicalSessionRecordSet& sessions) {
DBDirectClient client(opCtx);
diff --git a/src/mongo/db/sessions_collection_standalone.h b/src/mongo/db/sessions_collection_standalone.h
index 53e572b9d28..ac45fe33336 100644
--- a/src/mongo/db/sessions_collection_standalone.h
+++ b/src/mongo/db/sessions_collection_standalone.h
@@ -50,6 +50,11 @@ public:
Status setupSessionsCollection(OperationContext* opCtx) override;
/**
+ * Checks if the sessions collection exists and has the proper indexes.
+ */
+ Status checkSessionsCollectionExists(OperationContext* opCtx) override;
+
+ /**
* Updates the last-use times on the given sessions to be greater than
* or equal to the current time.
*/