summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Wlodarek <gregory.wlodarek@mongodb.com>2020-12-09 22:54:38 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2020-12-14 02:16:00 +0000
commitb45c07c6174d3ac6c100453ab6d56ab7ee5dedb6 (patch)
tree2edc13d02d53b875c3675ea6c3964bbdd64faef6
parent5b9cc730aba346d1bbc88bbd17e432c6641a9d6f (diff)
downloadmongo-b45c07c6174d3ac6c100453ab6d56ab7ee5dedb6.tar.gz
SERVER-51333 setFeatureCompatibilityVersion fails when downgrading from FCV 4.4 to FCV 4.2 with long collection names present
-rw-r--r--jstests/hooks/run_validate_collections.js15
-rw-r--r--jstests/hooks/validate_collections.js8
-rw-r--r--jstests/multiVersion/long_collection_names.js33
-rw-r--r--jstests/noPassthroughWithMongod/create_collection.js (renamed from jstests/core/create_collection.js)0
-rw-r--r--src/mongo/db/commands/set_feature_compatibility_version_command.cpp21
5 files changed, 45 insertions, 32 deletions
diff --git a/jstests/hooks/run_validate_collections.js b/jstests/hooks/run_validate_collections.js
index b94c3317c0e..c3ad9af2c72 100644
--- a/jstests/hooks/run_validate_collections.js
+++ b/jstests/hooks/run_validate_collections.js
@@ -49,6 +49,8 @@ const requiredFCV = jsTest.options().forceValidationWithFeatureCompatibilityVers
let originalFCV;
let originalTransactionLifetimeLimitSeconds;
+let skipFCV = false;
+
if (requiredFCV) {
// Running the setFeatureCompatibilityVersion command may implicitly involve running a
// multi-statement transaction. We temporarily raise the transactionLifetimeLimitSeconds to be
@@ -72,13 +74,18 @@ if (requiredFCV) {
}
// Now that we are certain that an upgrade or downgrade of the FCV is not in progress, ensure
- // the 'requiredFCV' is set.
- assert.commandWorked(adminDB.runCommand({setFeatureCompatibilityVersion: requiredFCV}));
+ // the 'requiredFCV' is set. If we're trying to set the FCV to 4.2 while having long collection
+ // name present, we'll get the 'InvalidNamespace' error.
+ const fcvRes = adminDB.runCommand({setFeatureCompatibilityVersion: requiredFCV});
+ if (!fcvRes.ok) {
+ assert.commandFailedWithCode(fcvRes, ErrorCodes.InvalidNamespace);
+ skipFCV = true;
+ }
}
-new CollectionValidator().validateNodes(hostList);
+new CollectionValidator().validateNodes(hostList, skipFCV);
-if (originalFCV && originalFCV.version !== requiredFCV) {
+if (originalFCV && originalFCV.version !== requiredFCV && !skipFCV) {
assert.commandWorked(adminDB.runCommand({setFeatureCompatibilityVersion: originalFCV.version}));
}
diff --git a/jstests/hooks/validate_collections.js b/jstests/hooks/validate_collections.js
index cf7f1be9707..01275869617 100644
--- a/jstests/hooks/validate_collections.js
+++ b/jstests/hooks/validate_collections.js
@@ -84,7 +84,7 @@ function CollectionValidator() {
};
// Run a separate thread to validate collections on each server in parallel.
- const validateCollectionsThread = function(validatorFunc, host) {
+ const validateCollectionsThread = function(validatorFunc, host, skipFCV) {
try {
print('Running validate() on ' + host);
const conn = new Mongo(host);
@@ -98,7 +98,7 @@ function CollectionValidator() {
}
const requiredFCV = jsTest.options().forceValidationWithFeatureCompatibilityVersion;
- if (requiredFCV) {
+ if (requiredFCV && !skipFCV) {
// Make sure this node has the desired FCV as it may take time for the updates to
// replicate to the nodes that weren't part of the w=majority.
assert.soonNoExcept(() => {
@@ -122,7 +122,7 @@ function CollectionValidator() {
}
};
- this.validateNodes = function(hostList) {
+ this.validateNodes = function(hostList, skipFCV) {
// We run the scoped threads in a try/finally block in case any thread throws an exception,
// in which case we want to still join all the threads.
let threads = [];
@@ -130,7 +130,7 @@ function CollectionValidator() {
try {
hostList.forEach(host => {
const thread =
- new Thread(validateCollectionsThread, this.validateCollections, host);
+ new Thread(validateCollectionsThread, this.validateCollections, host, skipFCV);
threads.push(thread);
thread.start();
});
diff --git a/jstests/multiVersion/long_collection_names.js b/jstests/multiVersion/long_collection_names.js
index d72b56b3dcf..b4e81634dc6 100644
--- a/jstests/multiVersion/long_collection_names.js
+++ b/jstests/multiVersion/long_collection_names.js
@@ -67,44 +67,29 @@ conn = MongoRunner.runMongod(restartOpts42);
assert.eq(null, conn, 'mongod was able to start with version ' + tojson(restartOpts42));
/**
- * Restart with the 4.4 binary to set the FCV to 4.2.
+ * Cannot downgrade to FCV 4.2 on a 4.4 binary when long collection names are present.
*/
let restartOpts44 = Object.extend(mongodOptions44, {restart: true});
conn = MongoRunner.runMongod(restartOpts44);
assert.neq(null, conn, 'mongod was unable to start with version ' + tojson(restartOpts44));
testDb = conn.getDB(dbName);
-assert.commandWorked(testDb.adminCommand({setFeatureCompatibilityVersion: lastStableFCV}));
-MongoRunner.stopMongod(conn);
+assert.commandFailedWithCode(testDb.adminCommand({setFeatureCompatibilityVersion: lastStableFCV}),
+ ErrorCodes.InvalidNamespace);
/**
- * Restart with the 4.2 binary while in FCV 4.2 with long collection names present. This shouldn't
- * crash the server.
+ * FCV can be set to 4.2 after removing the long collection name. However, we cannot create any new
+ * collections with long names in FCV 4.2.
*/
-conn = MongoRunner.runMongod(restartOpts42);
-assert.neq(null, conn, 'mongod was unable to start with version ' + tojson(restartOpts42));
-
testDb = conn.getDB(dbName);
+assert.eq(true, testDb.getCollection(longCollName).drop());
-// Ensure we have the proper collections.
-let collNames = testDb.getCollectionNames();
-
-assert.eq(true, collNames.includes(shortCollName));
-assert.eq(true, collNames.includes(longCollName));
-
-MongoRunner.stopMongod(conn);
-
-/**
- * Restart with the 4.4 binary while in FCV 4.2. We shouldn't be able to create any collections with
- * long names.
- */
-conn = MongoRunner.runMongod(restartOpts44);
-assert.neq(null, conn, 'mongod was unable to start with version ' + tojson(restartOpts44));
-
-testDb = conn.getDB(dbName);
+assert.commandWorked(testDb.adminCommand({setFeatureCompatibilityVersion: lastStableFCV}));
// Creating a long collection name on a 4.4 binary with FCV 4.2 should fail.
assert.commandFailedWithCode(testDb.createCollection('c'.repeat(8192)), 4862100);
+assert.commandFailedWithCode(testDb.createCollection(longCollName),
+ ErrorCodes.IncompatibleServerVersion);
// Running rename within the same database or across two databases should fail for long collection
// names.
diff --git a/jstests/core/create_collection.js b/jstests/noPassthroughWithMongod/create_collection.js
index 2c139708e2e..2c139708e2e 100644
--- a/jstests/core/create_collection.js
+++ b/jstests/noPassthroughWithMongod/create_collection.js
diff --git a/src/mongo/db/commands/set_feature_compatibility_version_command.cpp b/src/mongo/db/commands/set_feature_compatibility_version_command.cpp
index 50815f25fa4..a4e63703057 100644
--- a/src/mongo/db/commands/set_feature_compatibility_version_command.cpp
+++ b/src/mongo/db/commands/set_feature_compatibility_version_command.cpp
@@ -33,6 +33,7 @@
#include "mongo/db/auth/authorization_session.h"
#include "mongo/db/catalog/coll_mod.h"
+#include "mongo/db/catalog/collection_catalog_helper.h"
#include "mongo/db/catalog/database.h"
#include "mongo/db/catalog/database_holder.h"
#include "mongo/db/commands.h"
@@ -349,6 +350,26 @@ public:
numIndexBuilds == 0U);
}
+ // Cannot downgrade to FCV 4.2 when long collection names are present.
+ const std::vector<std::string> dbNames = CollectionCatalog::get(opCtx).getAllDbNames();
+ for (const auto& dbName : dbNames) {
+ Lock::DBLock dbLock(opCtx, dbName, MODE_IS);
+ catalog::forEachCollectionFromDb(
+ opCtx, dbName, MODE_IS, [&](const Collection* collection) {
+ const auto collNss = collection->ns();
+ uassert(ErrorCodes::InvalidNamespace,
+ str::stream()
+ << "Cannot downgrade the cluster when there are long "
+ << "collection names present. FCV 4.2 limit: "
+ << NamespaceString::MaxNSCollectionLenFCV42
+ << ". Found: " << collNss
+ << ", but there may be more. Rename or drop the collection",
+ collNss.size() <= NamespaceString::MaxNSCollectionLenFCV42);
+ return true;
+ });
+ }
+
+
FeatureCompatibilityVersion::setTargetDowngrade(opCtx);
// Safe reconfig introduces a new "term" field in the config document. If the user tries