diff options
4 files changed, 108 insertions, 3 deletions
diff --git a/jstests/multiVersion/targetedTestsLastLtsFeatures/recordPreImages_option_upgrade.js b/jstests/multiVersion/targetedTestsLastLtsFeatures/recordPreImages_option_upgrade.js new file mode 100644 index 00000000000..6f86dcb202c --- /dev/null +++ b/jstests/multiVersion/targetedTestsLastLtsFeatures/recordPreImages_option_upgrade.js @@ -0,0 +1,69 @@ +/** + * Verifies that the server ignores collection option "recordPreImages" on binary upgrade from the + * last LTS version to the current, as well as removes the option from collection attributes on + * FCV upgrade. + */ +(function() { +"use strict"; +load('jstests/multiVersion/libs/multi_rs.js'); + +const lastLTSVersion = "last-lts"; +const latestVersion = "latest"; + +// Setup a two-node replica set with last LTS binaries, so it is possible to create a collection +// with "recordPreImages" option. +const rst = new ReplSetTest( + {name: jsTestName(), nodes: [{binVersion: lastLTSVersion}, {binVersion: lastLTSVersion}]}); +rst.startSet(); +rst.initiate(); +const testDB = rst.getPrimary().getDB("test"); +const primaryNode = rst.getPrimary(); +const secondaryNode = rst.getSecondary(); + +// Create the collection. +const collectionName = "coll"; +assert.commandWorked(testDB.createCollection(collectionName, {recordPreImages: true})); +let coll = testDB[collectionName]; + +// Insert a test document which will be updated to trigger recording of change stream pre-images. +assert.commandWorked(coll.insert({_id: 1, a: 1})); +assert.commandWorked(coll.updateOne({_id: 1}, {$inc: {a: 1}})); +rst.awaitReplication(); + +// Upgrade the binary of the secondary node to the current version to setup a mixed binary cluster. +rst.upgradeMembers([secondaryNode], {binVersion: latestVersion}); + +// Make sure the primary node did not change. +rst.stepUp(primaryNode); + +// Verify that recording of change stream pre-images succeeds. +assert.commandWorked(coll.updateOne({_id: 1}, {$inc: {a: 1}})); +rst.awaitReplication(); + +// Finally upgrade the binary of the primary node to the current version. +rst.upgradePrimary(rst.getPrimary(), {binVersion: latestVersion}); + +// Update a document on the collection with inactive "recordPreImages" collection option. +coll = rst.getPrimary().getDB("test")[collectionName]; +assert.commandWorked(coll.updateOne({_id: 1}, {$inc: {a: 1}})); +rst.awaitReplication(); + +// Upgrade the FCV to the latest to trigger removal of "recordPreImages" collection option from +// persistent catalog entries. +assert.commandWorked(rst.getPrimary().adminCommand({setFeatureCompatibilityVersion: latestFCV})); + +// To check the collection options, downgrade FCV to later replace the binary of the server with +// the last LTS binary version. +assert.commandWorked(rst.getPrimary().adminCommand({setFeatureCompatibilityVersion: lastLTSFCV})); +rst.upgradeSet({binVersion: lastLTSVersion}); + +// Verify that collection option "recordPreImages" was removed. +const result = + assert.commandWorked(rst.getPrimary().getDB("test").runCommand({listCollections: 1})); +assert.eq(result.cursor.firstBatch[0].name, collectionName); +assert.docEq( + {}, + result.cursor.firstBatch[0].options, + `Collection option "recordPreImages" was not removed. Got response: ${tojson(result)}`); +rst.stopSet(); +})();
\ No newline at end of file diff --git a/src/mongo/db/catalog/collection_options.cpp b/src/mongo/db/catalog/collection_options.cpp index 4e235d62a71..297c4d45bef 100644 --- a/src/mongo/db/catalog/collection_options.cpp +++ b/src/mongo/db/catalog/collection_options.cpp @@ -174,6 +174,10 @@ StatusWith<CollectionOptions> CollectionOptions::parse(const BSONObj& options, P } else if (fieldName == "flags") { // Ignoring this field as it is deprecated. continue; + } else if (fieldName == "recordPreImages") { + // Ignoring this field as it is not supported. + collectionOptions.recordPreImagesOptionUsed = true; + continue; } else if (fieldName == "temp") { collectionOptions.temp = e.trueValue(); } else if (fieldName == "changeStreamPreAndPostImages") { diff --git a/src/mongo/db/catalog/collection_options.h b/src/mongo/db/catalog/collection_options.h index 2e1d06aa190..f5dc1dd0c55 100644 --- a/src/mongo/db/catalog/collection_options.h +++ b/src/mongo/db/catalog/collection_options.h @@ -124,6 +124,12 @@ struct CollectionOptions { bool temp = false; + // Indicates whether "recordPreImages" collection option was used in the collection definition. + // This needs to be remembered to make it possible to efficiently remove the option upon FCV + // upgrade. Otherwise, this option is not supported. + // TODO SERVER-74036: Remove once FCV 7.0 becomes last-LTS. + bool recordPreImagesOptionUsed{false}; + // Change stream options define whether or not to store the pre-images of the documents affected // by update and delete operations in a dedicated collection, that will be used for reading data // via changeStreams. 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 e7789ea0eea..58c5121c2dd 100644 --- a/src/mongo/db/commands/set_feature_compatibility_version_command.cpp +++ b/src/mongo/db/commands/set_feature_compatibility_version_command.cpp @@ -499,10 +499,9 @@ private: if (serverGlobalParams.clusterRole == ClusterRole::ConfigServer) { _cleanupConfigVersionOnUpgrade(opCtx, requestedVersion); _createSchemaOnConfigSettings(opCtx, requestedVersion); - } else if (serverGlobalParams.clusterRole == ClusterRole::ShardServer) { - } else { - return; } + + _removeRecordPreImagesCollectionOption(opCtx); } // TODO SERVER-68889 remove once 7.0 becomes last LTS @@ -592,6 +591,33 @@ private: } } + // Removes collection option "recordPreImages" from all collection definitions. + // TODO SERVER-74036: Remove once FCV 7.0 becomes last-LTS. + void _removeRecordPreImagesCollectionOption(OperationContext* opCtx) { + for (const auto& dbName : DatabaseHolder::get(opCtx)->getNames()) { + Lock::DBLock dbLock(opCtx, dbName, MODE_IX); + catalog::forEachCollectionFromDb( + opCtx, + dbName, + MODE_X, + [&](const CollectionPtr& collection) { + // To remove collection option "recordPreImages" from persistent storage, issue + // the "collMod" command with none of the parameters set. + BSONObjBuilder responseBuilder; + uassertStatusOK(processCollModCommand( + opCtx, collection->ns(), CollMod{collection->ns()}, &responseBuilder)); + LOGV2(7383300, + "Removed 'recordPreImages' collection option", + "ns"_attr = collection->ns(), + "collModResponse"_attr = responseBuilder.obj()); + return true; + }, + [&](const CollectionPtr& collection) { + return collection->getCollectionOptions().recordPreImagesOptionUsed; + }); + } + } + // _runUpgrade performs all the upgrade specific code for setFCV. Any new feature specific // upgrade code should be placed in the _runUpgrade helper functions: // * _prepareForUpgrade: for any upgrade actions that should be done before taking the FCV full |