summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2016-09-14 18:02:10 -0400
committerDavid Storch <david.storch@10gen.com>2016-09-20 17:40:43 -0400
commit2ac0e07e7f82406e989fa272c68d1205ced81d78 (patch)
treeeece2e1323d243c48e10304181a8678884035acd
parent585edf79040ed44db42e174b8659ca7290fa48cf (diff)
downloadmongo-2ac0e07e7f82406e989fa272c68d1205ced81d78.tar.gz
SERVER-25969 make slaves and secondaries always use BSON 1.1 validation
This allows secondaries and slaves to sync NumberDecimal even while in featureCompatibilityVersion:"3.2" mode.
-rw-r--r--jstests/repl/slave_sync_decimal.js46
-rw-r--r--jstests/replsets/initial_sync_decimal.js52
-rw-r--r--src/mongo/db/catalog/database.cpp6
-rw-r--r--src/mongo/db/catalog/index_catalog.cpp2
-rw-r--r--src/mongo/db/catalog/index_catalog.h2
-rw-r--r--src/mongo/db/catalog/index_key_validate.cpp2
-rw-r--r--src/mongo/db/catalog/index_key_validate.h2
-rw-r--r--src/mongo/db/catalog/index_spec_validate_test.cpp81
-rw-r--r--src/mongo/db/cloner.cpp2
-rw-r--r--src/mongo/db/commands/count_cmd.cpp8
-rw-r--r--src/mongo/db/commands/create_indexes.cpp4
-rw-r--r--src/mongo/db/commands/dbcommands.cpp4
-rw-r--r--src/mongo/db/commands/distinct.cpp8
-rw-r--r--src/mongo/db/commands/drop_indexes.cpp2
-rw-r--r--src/mongo/db/commands/feature_compatibility_version.cpp32
-rw-r--r--src/mongo/db/commands/feature_compatibility_version.h2
-rw-r--r--src/mongo/db/commands/find_cmd.cpp8
-rw-r--r--src/mongo/db/commands/geo_near_cmd.cpp4
-rw-r--r--src/mongo/db/commands/group_cmd.cpp4
-rw-r--r--src/mongo/db/commands/mr.cpp4
-rw-r--r--src/mongo/db/commands/pipeline_command.cpp4
-rw-r--r--src/mongo/db/db.cpp6
-rw-r--r--src/mongo/db/index/index_descriptor.cpp7
-rw-r--r--src/mongo/db/index/index_descriptor.h4
-rw-r--r--src/mongo/db/ops/parsed_delete.cpp4
-rw-r--r--src/mongo/db/ops/parsed_update.cpp4
-rw-r--r--src/mongo/db/repl/replication_coordinator_external_state_impl.cpp3
-rw-r--r--src/mongo/db/repl/replication_coordinator_impl.cpp1
-rw-r--r--src/mongo/db/server_options.h41
-rw-r--r--src/mongo/db/views/view_catalog.cpp8
-rw-r--r--src/mongo/dbtests/jstests.cpp16
-rw-r--r--src/mongo/rpc/object_check.h17
-rw-r--r--src/mongo/s/catalog/replset/sharding_catalog_manager_impl.cpp4
-rw-r--r--src/mongo/s/server.cpp4
-rw-r--r--src/mongo/shell/dbshell.cpp4
35 files changed, 265 insertions, 137 deletions
diff --git a/jstests/repl/slave_sync_decimal.js b/jstests/repl/slave_sync_decimal.js
new file mode 100644
index 00000000000..dba3792cf1a
--- /dev/null
+++ b/jstests/repl/slave_sync_decimal.js
@@ -0,0 +1,46 @@
+/**
+ * Tests that we can initial sync decimal128 data to a slave, even when the cluster is in 3.2
+ * feature compatibility mode.
+ */
+(function() {
+ "use strict";
+
+ var replTest = new ReplTest("slave_sync_decimal");
+
+ var master = replTest.start(true);
+ var masterDB = master.getDB("test");
+ var masterColl = masterDB.slave_sync_decimal;
+
+ // Since the master started fresh, it should be in 3.4 feature compatibility mode.
+ var fcv = assert.commandWorked(
+ masterDB.adminCommand({getParameter: 1, featureCompatibilityVersion: 1}));
+ assert.eq(fcv.featureCompatibilityVersion, "3.4");
+
+ // Make sure we can insert decimal data in 3.4 mode.
+ assert.writeOK(masterColl.insert({a: 1, b: NumberDecimal(1)}));
+
+ // Set 3.2 feature compatibility mode.
+ assert.commandWorked(masterDB.adminCommand({setFeatureCompatibilityVersion: "3.2"}));
+ fcv = assert.commandWorked(
+ masterDB.adminCommand({getParameter: 1, featureCompatibilityVersion: 1}));
+ assert.eq(fcv.featureCompatibilityVersion, "3.2");
+
+ // We shouldn't be able to insert decimal data in 3.2 mode.
+ assert.writeError(masterColl.insert({a: 1, b: NumberDecimal(1)}));
+
+ var slave = replTest.start(false);
+ var slaveDB = slave.getDB("test");
+ var slaveColl = slaveDB.slave_sync_decimal;
+
+ fcv = assert.commandWorked(
+ slaveDB.adminCommand({getParameter: 1, featureCompatibilityVersion: 1}));
+ assert.eq(fcv.featureCompatibilityVersion, "3.2");
+
+ slave.setSlaveOk(true);
+
+ assert.soon(function() {
+ return slaveColl.find({b: NumberDecimal(1)}).itcount() === 1;
+ }, 5 * 60 * 1000, "Slave failed to sync document containing NumberDecimal");
+
+ replTest.stop();
+})();
diff --git a/jstests/replsets/initial_sync_decimal.js b/jstests/replsets/initial_sync_decimal.js
new file mode 100644
index 00000000000..2d4e22db3a1
--- /dev/null
+++ b/jstests/replsets/initial_sync_decimal.js
@@ -0,0 +1,52 @@
+/**
+ * Tests that we can initial sync decimal128 data to secondaries, even when the cluster is in 3.2
+ * feature compatibility mode.
+ */
+(function() {
+ "use strict";
+
+ var replTest = new ReplSetTest({name: 'testSet', nodes: 2});
+
+ var nodes = replTest.startSet();
+ replTest.initiate();
+
+ var primary = replTest.getPrimary();
+ var primaryDB = primary.getDB("test");
+ var primaryColl = primaryDB.initial_sync_decimal;
+
+ var secondary = replTest.getSecondary();
+
+ // Since we started a fresh replica set, we should be in 3.4 feature compatibility mode.
+ var fcv = assert.commandWorked(
+ primaryDB.adminCommand({getParameter: 1, featureCompatibilityVersion: 1}));
+ assert.eq(fcv.featureCompatibilityVersion, "3.4");
+
+ // Make sure we can insert decimal data in 3.4 mode.
+ assert.writeOK(primaryColl.insert({a: 1, b: NumberDecimal(1)}));
+
+ // Set 3.2 feature compatibility mode.
+ assert.commandWorked(primaryDB.adminCommand({setFeatureCompatibilityVersion: "3.2"}));
+ fcv = assert.commandWorked(
+ primaryDB.adminCommand({getParameter: 1, featureCompatibilityVersion: 1}));
+ assert.eq(fcv.featureCompatibilityVersion, "3.2");
+
+ // Ensure 3.2 feature compatibility version has synced to admin.system.version.
+ fcv = secondary.getDB("admin")
+ .system.version.find({_id: "featureCompatibilityVersion"})
+ .toArray();
+ assert.eq(1, fcv.length);
+ assert.eq("3.2", fcv[0].version);
+
+ // We shouldn't be able to insert decimal data in 3.2 mode.
+ assert.writeError(primaryColl.insert({a: 1, b: NumberDecimal(1)}));
+
+ // We should, however, be able to initial sync decimal data.
+ assert.commandWorked(secondary.getDB("admin").runCommand({resync: 1}));
+ replTest.awaitSecondaryNodes();
+
+ // Ensure that secondary is still up and has the data.
+ var secondaryColl = secondary.getDB("test").initial_sync_decimal;
+ assert.eq(1, secondaryColl.find({b: NumberDecimal(1)}).itcount());
+
+ replTest.stopSet();
+})();
diff --git a/src/mongo/db/catalog/database.cpp b/src/mongo/db/catalog/database.cpp
index 85d3eab7f34..65201aca807 100644
--- a/src/mongo/db/catalog/database.cpp
+++ b/src/mongo/db/catalog/database.cpp
@@ -393,8 +393,8 @@ Status Database::dropCollection(OperationContext* txn, StringData fullns) {
return Status(ErrorCodes::IllegalOperation,
"turn off profiling before dropping system.profile collection");
} else if (nss.isSystemDotViews()) {
- if (serverGlobalParams.featureCompatibilityVersion.load() !=
- ServerGlobalParams::FeatureCompatibilityVersion_32) {
+ if (serverGlobalParams.featureCompatibility.version.load() !=
+ ServerGlobalParams::FeatureCompatibility::Version::k32) {
return Status(ErrorCodes::IllegalOperation,
"The featureCompatibilityVersion must be 3.2 to drop the "
"system.views collection. See "
@@ -590,7 +590,7 @@ Collection* Database::createCollection(OperationContext* txn,
// "setFeatureCompatibilityVersion" command either happens entirely before the
// collection creation or it happens entirely after.
const auto featureCompatibilityVersion =
- serverGlobalParams.featureCompatibilityVersion.load();
+ serverGlobalParams.featureCompatibility.version.load();
IndexCatalog* ic = collection->getIndexCatalog();
uassertStatusOK(ic->createIndexOnEmptyCollection(
txn, ic->getDefaultIdIndexSpec(featureCompatibilityVersion)));
diff --git a/src/mongo/db/catalog/index_catalog.cpp b/src/mongo/db/catalog/index_catalog.cpp
index 123f7722024..e48040cb591 100644
--- a/src/mongo/db/catalog/index_catalog.cpp
+++ b/src/mongo/db/catalog/index_catalog.cpp
@@ -784,7 +784,7 @@ Status IndexCatalog::_doesSpecConflictWithExisting(OperationContext* txn,
}
BSONObj IndexCatalog::getDefaultIdIndexSpec(
- ServerGlobalParams::FeatureCompatibilityVersions featureCompatibilityVersion) const {
+ ServerGlobalParams::FeatureCompatibility::Version featureCompatibilityVersion) const {
dassert(_idObj["_id"].type() == NumberInt);
const auto indexVersion = IndexDescriptor::getDefaultIndexVersion(featureCompatibilityVersion);
diff --git a/src/mongo/db/catalog/index_catalog.h b/src/mongo/db/catalog/index_catalog.h
index 4ff19ddd60f..446a949ff2f 100644
--- a/src/mongo/db/catalog/index_catalog.h
+++ b/src/mongo/db/catalog/index_catalog.h
@@ -83,7 +83,7 @@ public:
* Returns the spec for the id index to create by default for this collection.
*/
BSONObj getDefaultIdIndexSpec(
- ServerGlobalParams::FeatureCompatibilityVersions featureCompatibilityVersion) const;
+ ServerGlobalParams::FeatureCompatibility::Version featureCompatibilityVersion) const;
IndexDescriptor* findIdIndex(OperationContext* txn) const;
diff --git a/src/mongo/db/catalog/index_key_validate.cpp b/src/mongo/db/catalog/index_key_validate.cpp
index c211d22b1d4..986454911cc 100644
--- a/src/mongo/db/catalog/index_key_validate.cpp
+++ b/src/mongo/db/catalog/index_key_validate.cpp
@@ -141,7 +141,7 @@ Status validateKeyPattern(const BSONObj& key) {
StatusWith<BSONObj> validateIndexSpec(
const BSONObj& indexSpec,
const NamespaceString& expectedNamespace,
- ServerGlobalParams::FeatureCompatibilityVersions featureCompatibilityVersion) {
+ ServerGlobalParams::FeatureCompatibility::Version featureCompatibilityVersion) {
bool hasKeyPatternField = false;
bool hasNamespaceField = false;
bool hasVersionField = false;
diff --git a/src/mongo/db/catalog/index_key_validate.h b/src/mongo/db/catalog/index_key_validate.h
index bbbdfe9671f..036eaa4103d 100644
--- a/src/mongo/db/catalog/index_key_validate.h
+++ b/src/mongo/db/catalog/index_key_validate.h
@@ -50,5 +50,5 @@ Status validateKeyPattern(const BSONObj& key);
StatusWith<BSONObj> validateIndexSpec(
const BSONObj& indexSpec,
const NamespaceString& expectedNamespace,
- ServerGlobalParams::FeatureCompatibilityVersions featureCompatibilityVersion);
+ ServerGlobalParams::FeatureCompatibility::Version featureCompatibilityVersion);
} // namespace mongo
diff --git a/src/mongo/db/catalog/index_spec_validate_test.cpp b/src/mongo/db/catalog/index_spec_validate_test.cpp
index 8a07010ab68..c41bc920cad 100644
--- a/src/mongo/db/catalog/index_spec_validate_test.cpp
+++ b/src/mongo/db/catalog/index_spec_validate_test.cpp
@@ -61,45 +61,46 @@ TEST(IndexSpecValidateTest, ReturnsAnErrorIfKeyPatternIsNotAnObject) {
ASSERT_EQ(ErrorCodes::TypeMismatch,
validateIndexSpec(BSON("key" << 1),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
ASSERT_EQ(ErrorCodes::TypeMismatch,
validateIndexSpec(BSON("key"
<< "not an object"),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
ASSERT_EQ(ErrorCodes::TypeMismatch,
validateIndexSpec(BSON("key" << BSONArray()),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
}
TEST(IndexSpecValidateTest, ReturnsAnErrorIfFieldRepeatedInKeyPattern) {
ASSERT_EQ(ErrorCodes::BadValue,
validateIndexSpec(BSON("key" << BSON("field" << 1 << "field" << 1)),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
ASSERT_EQ(ErrorCodes::BadValue,
validateIndexSpec(BSON("key" << BSON("field" << 1 << "otherField" << -1 << "field"
<< "2dsphere")),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
}
TEST(IndexSpecValidateTest, ReturnsAnErrorIfKeyPatternIsNotPresent) {
ASSERT_EQ(ErrorCodes::FailedToParse,
- validateIndexSpec(
- BSONObj(), kTestNamespace, ServerGlobalParams::FeatureCompatibilityVersion_34));
+ validateIndexSpec(BSONObj(),
+ kTestNamespace,
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
}
TEST(IndexSpecValidateTest, ReturnsAnErrorIfNamespaceIsNotAString) {
ASSERT_EQ(ErrorCodes::TypeMismatch,
validateIndexSpec(BSON("key" << BSON("field" << 1) << "ns" << 1),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
ASSERT_EQ(ErrorCodes::TypeMismatch,
validateIndexSpec(BSON("key" << BSON("field" << 1) << "ns" << BSONObj()),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
}
TEST(IndexSpecValidateTest, ReturnsAnErrorIfNamespaceIsEmptyString) {
@@ -107,7 +108,7 @@ TEST(IndexSpecValidateTest, ReturnsAnErrorIfNamespaceIsEmptyString) {
validateIndexSpec(BSON("key" << BSON("field" << 1) << "ns"
<< ""),
NamespaceString(),
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
}
TEST(IndexSpecValidateTest, ReturnsAnErrorIfNamespaceDoesNotMatch) {
@@ -115,20 +116,20 @@ TEST(IndexSpecValidateTest, ReturnsAnErrorIfNamespaceDoesNotMatch) {
validateIndexSpec(BSON("key" << BSON("field" << 1) << "ns"
<< "some string"),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
// Verify that we reject the index specification when the "ns" field only contains the
// collection name.
ASSERT_EQ(ErrorCodes::BadValue,
validateIndexSpec(BSON("key" << BSON("field" << 1) << "ns" << kTestNamespace.coll()),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
}
TEST(IndexSpecValidateTest, ReturnsIndexSpecWithNamespaceFilledInIfItIsNotPresent) {
auto result = validateIndexSpec(BSON("key" << BSON("field" << 1) << "v" << 1),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34);
+ ServerGlobalParams::FeatureCompatibility::Version::k34);
ASSERT_OK(result.getStatus());
// We don't care about the order of the fields in the resulting index specification.
@@ -138,14 +139,14 @@ TEST(IndexSpecValidateTest, ReturnsIndexSpecWithNamespaceFilledInIfItIsNotPresen
// Verify that the index specification we returned is still considered valid.
ASSERT_OK(validateIndexSpec(
- result.getValue(), kTestNamespace, ServerGlobalParams::FeatureCompatibilityVersion_34));
+ result.getValue(), kTestNamespace, ServerGlobalParams::FeatureCompatibility::Version::k34));
}
TEST(IndexSpecValidateTest, ReturnsIndexSpecUnchangedIfNamespaceAndVersionArePresent) {
auto result = validateIndexSpec(
BSON("key" << BSON("field" << 1) << "ns" << kTestNamespace.ns() << "v" << 1),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34);
+ ServerGlobalParams::FeatureCompatibility::Version::k34);
ASSERT_OK(result.getStatus());
// We don't care about the order of the fields in the resulting index specification.
@@ -161,39 +162,39 @@ TEST(IndexSpecValidateTest, ReturnsAnErrorIfVersionIsNotANumber) {
validateIndexSpec(BSON("key" << BSON("field" << 1) << "v"
<< "not a number"),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
ASSERT_EQ(ErrorCodes::TypeMismatch,
validateIndexSpec(BSON("key" << BSON("field" << 1) << "v" << BSONObj()),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
}
TEST(IndexSpecValidateTest, ReturnsAnErrorIfVersionIsNotRepresentableAsInt) {
ASSERT_EQ(ErrorCodes::BadValue,
validateIndexSpec(BSON("key" << BSON("field" << 1) << "v" << 2.2),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
ASSERT_EQ(ErrorCodes::BadValue,
validateIndexSpec(BSON("key" << BSON("field" << 1) << "v" << std::nan("1")),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
ASSERT_EQ(ErrorCodes::BadValue,
validateIndexSpec(BSON("key" << BSON("field" << 1) << "v"
<< std::numeric_limits<double>::infinity()),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
ASSERT_EQ(ErrorCodes::BadValue,
validateIndexSpec(
BSON("key" << BSON("field" << 1) << "v" << std::numeric_limits<long long>::max()),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
}
TEST(IndexSpecValidateTest, ReturnsAnErrorIfVersionIsV0) {
ASSERT_EQ(ErrorCodes::CannotCreateIndex,
validateIndexSpec(BSON("key" << BSON("field" << 1) << "v" << 0),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
}
TEST(IndexSpecValidateTest, ReturnsAnErrorIfVersionIsUnsupported) {
@@ -202,25 +203,25 @@ TEST(IndexSpecValidateTest, ReturnsAnErrorIfVersionIsUnsupported) {
BSON("key" << BSON("field" << 1) << "v" << 3 << "collation" << BSON("locale"
<< "en")),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
ASSERT_EQ(ErrorCodes::CannotCreateIndex,
validateIndexSpec(BSON("key" << BSON("field" << 1) << "v" << -3LL),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
}
TEST(IndexSpecValidateTest, ReturnsAnErrorIfIndexVersionIsV2AndFeatureCompatibilityVersionIs32) {
ASSERT_EQ(ErrorCodes::CannotCreateIndex,
validateIndexSpec(BSON("key" << BSON("field" << 1) << "v" << 2),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_32));
+ ServerGlobalParams::FeatureCompatibility::Version::k32));
}
TEST(IndexSpecValidateTest, AcceptsIndexVersionsThatAreAllowedForCreation) {
auto result = validateIndexSpec(BSON("key" << BSON("field" << 1) << "v" << 1),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34);
+ ServerGlobalParams::FeatureCompatibility::Version::k34);
ASSERT_OK(result.getStatus());
// We don't care about the order of the fields in the resulting index specification.
@@ -230,7 +231,7 @@ TEST(IndexSpecValidateTest, AcceptsIndexVersionsThatAreAllowedForCreation) {
result = validateIndexSpec(BSON("key" << BSON("field" << 1) << "v" << 2LL),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34);
+ ServerGlobalParams::FeatureCompatibility::Version::k34);
ASSERT_OK(result.getStatus());
// We don't care about the order of the fields in the resulting index specification.
@@ -243,7 +244,7 @@ TEST(IndexSpecValidateTest, DefaultIndexVersionIsV1IfFeatureCompatibilityVersion
auto result =
validateIndexSpec(BSON("key" << BSON("field" << 1) << "ns" << kTestNamespace.ns()),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_32);
+ ServerGlobalParams::FeatureCompatibility::Version::k32);
ASSERT_OK(result.getStatus());
// We don't care about the order of the fields in the resulting index specification.
@@ -253,14 +254,14 @@ TEST(IndexSpecValidateTest, DefaultIndexVersionIsV1IfFeatureCompatibilityVersion
// Verify that the index specification we returned is still considered valid.
ASSERT_OK(validateIndexSpec(
- result.getValue(), kTestNamespace, ServerGlobalParams::FeatureCompatibilityVersion_32));
+ result.getValue(), kTestNamespace, ServerGlobalParams::FeatureCompatibility::Version::k32));
}
TEST(IndexSpecValidateTest, DefaultIndexVersionIsV2IfFeatureCompatibilityVersionIs34) {
auto result =
validateIndexSpec(BSON("key" << BSON("field" << 1) << "ns" << kTestNamespace.ns()),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34);
+ ServerGlobalParams::FeatureCompatibility::Version::k34);
ASSERT_OK(result.getStatus());
// We don't care about the order of the fields in the resulting index specification.
@@ -270,13 +271,13 @@ TEST(IndexSpecValidateTest, DefaultIndexVersionIsV2IfFeatureCompatibilityVersion
// Verify that the index specification we returned is still considered valid.
ASSERT_OK(validateIndexSpec(
- result.getValue(), kTestNamespace, ServerGlobalParams::FeatureCompatibilityVersion_34));
+ result.getValue(), kTestNamespace, ServerGlobalParams::FeatureCompatibility::Version::k34));
}
TEST(IndexSpecValidateTest, AcceptsIndexVersionV1WhenFeatureCompatibilityVersionIs34) {
auto result = validateIndexSpec(BSON("key" << BSON("field" << 1) << "v" << 1),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34);
+ ServerGlobalParams::FeatureCompatibility::Version::k34);
ASSERT_OK(result.getStatus());
// We don't care about the order of the fields in the resulting index specification.
@@ -289,16 +290,16 @@ TEST(IndexSpecValidateTest, ReturnsAnErrorIfCollationIsNotAnObject) {
ASSERT_EQ(ErrorCodes::TypeMismatch,
validateIndexSpec(BSON("key" << BSON("field" << 1) << "collation" << 1),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
ASSERT_EQ(ErrorCodes::TypeMismatch,
validateIndexSpec(BSON("key" << BSON("field" << 1) << "collation"
<< "not an object"),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
ASSERT_EQ(ErrorCodes::TypeMismatch,
validateIndexSpec(BSON("key" << BSON("field" << 1) << "collation" << BSONArray()),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
}
TEST(IndexSpecValidateTest, ReturnsAnErrorIfCollationIsPresentAndVersionIsLessThanV2) {
@@ -306,7 +307,7 @@ TEST(IndexSpecValidateTest, ReturnsAnErrorIfCollationIsPresentAndVersionIsLessTh
ErrorCodes::CannotCreateIndex,
validateIndexSpec(BSON("key" << BSON("field" << 1) << "collation" << BSONObj() << "v" << 1),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34));
+ ServerGlobalParams::FeatureCompatibility::Version::k34));
}
TEST(IndexSpecValidateTest, AcceptsAnyObjectValueForCollation) {
@@ -314,7 +315,7 @@ TEST(IndexSpecValidateTest, AcceptsAnyObjectValueForCollation) {
BSON("key" << BSON("field" << 1) << "v" << 2 << "collation" << BSON("locale"
<< "simple")),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34);
+ ServerGlobalParams::FeatureCompatibility::Version::k34);
ASSERT_OK(result.getStatus());
// We don't care about the order of the fields in the resulting index specification.
@@ -328,7 +329,7 @@ TEST(IndexSpecValidateTest, AcceptsAnyObjectValueForCollation) {
result =
validateIndexSpec(BSON("key" << BSON("field" << 1) << "v" << 2 << "collation" << BSONObj()),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34);
+ ServerGlobalParams::FeatureCompatibility::Version::k34);
ASSERT_OK(result.getStatus());
// We don't care about the order of the fields in the resulting index specification.
@@ -341,7 +342,7 @@ TEST(IndexSpecValidateTest, AcceptsAnyObjectValueForCollation) {
result = validateIndexSpec(BSON("key" << BSON("field" << 1) << "v" << 2 << "collation"
<< BSON("unknownCollationOption" << true)),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34);
+ ServerGlobalParams::FeatureCompatibility::Version::k34);
ASSERT_OK(result.getStatus());
// We don't care about the order of the fields in the resulting index specification.
@@ -357,7 +358,7 @@ TEST(IndexSpecValidateTest, AcceptsIndexSpecIfCollationIsPresentAndVersionIsEqua
BSON("key" << BSON("field" << 1) << "v" << 2 << "collation" << BSON("locale"
<< "en")),
kTestNamespace,
- ServerGlobalParams::FeatureCompatibilityVersion_34);
+ ServerGlobalParams::FeatureCompatibility::Version::k34);
ASSERT_OK(result.getStatus());
// We don't care about the order of the fields in the resulting index specification.
diff --git a/src/mongo/db/cloner.cpp b/src/mongo/db/cloner.cpp
index e935e38b9f7..9d854b8e705 100644
--- a/src/mongo/db/cloner.cpp
+++ b/src/mongo/db/cloner.cpp
@@ -675,7 +675,7 @@ Status Cloner::copyDb(OperationContext* txn,
indexer.allowInterruption();
const auto featureCompatibilityVersion =
- serverGlobalParams.featureCompatibilityVersion.load();
+ serverGlobalParams.featureCompatibility.version.load();
auto indexInfoObjs = uassertStatusOK(indexer.init(
c->getIndexCatalog()->getDefaultIdIndexSpec(featureCompatibilityVersion)));
invariant(indexInfoObjs.size() == 1);
diff --git a/src/mongo/db/commands/count_cmd.cpp b/src/mongo/db/commands/count_cmd.cpp
index 9631cc9a51d..65b02e1ba88 100644
--- a/src/mongo/db/commands/count_cmd.cpp
+++ b/src/mongo/db/commands/count_cmd.cpp
@@ -114,8 +114,8 @@ public:
}
if (!request.getValue().getCollation().isEmpty() &&
- serverGlobalParams.featureCompatibilityVersion.load() ==
- ServerGlobalParams::FeatureCompatibilityVersion_32) {
+ serverGlobalParams.featureCompatibility.version.load() ==
+ ServerGlobalParams::FeatureCompatibility::Version::k32) {
return Status(ErrorCodes::InvalidOptions,
"The featureCompatibilityVersion must be 3.4 to use collation. See "
"http://dochub.mongodb.org/core/3.4-feature-compatibility.");
@@ -171,8 +171,8 @@ public:
}
if (!request.getValue().getCollation().isEmpty() &&
- serverGlobalParams.featureCompatibilityVersion.load() ==
- ServerGlobalParams::FeatureCompatibilityVersion_32) {
+ serverGlobalParams.featureCompatibility.version.load() ==
+ ServerGlobalParams::FeatureCompatibility::Version::k32) {
return appendCommandStatus(
result,
Status(ErrorCodes::InvalidOptions,
diff --git a/src/mongo/db/commands/create_indexes.cpp b/src/mongo/db/commands/create_indexes.cpp
index 176b6a84b6d..5d660f024ce 100644
--- a/src/mongo/db/commands/create_indexes.cpp
+++ b/src/mongo/db/commands/create_indexes.cpp
@@ -74,7 +74,7 @@ const StringData kIndexesFieldName = "indexes"_sd;
StatusWith<std::vector<BSONObj>> parseAndValidateIndexSpecs(
const NamespaceString& ns,
const BSONObj& cmdObj,
- ServerGlobalParams::FeatureCompatibilityVersions featureCompatibilityVersion) {
+ ServerGlobalParams::FeatureCompatibility::Version featureCompatibilityVersion) {
bool hasIndexesField = false;
std::vector<BSONObj> indexSpecs;
@@ -238,7 +238,7 @@ public:
return appendCommandStatus(result, status);
const auto featureCompatibilityVersion =
- serverGlobalParams.featureCompatibilityVersion.load();
+ serverGlobalParams.featureCompatibility.version.load();
auto specsWithStatus = parseAndValidateIndexSpecs(ns, cmdObj, featureCompatibilityVersion);
if (!specsWithStatus.isOK()) {
return appendCommandStatus(result, specsWithStatus.getStatus());
diff --git a/src/mongo/db/commands/dbcommands.cpp b/src/mongo/db/commands/dbcommands.cpp
index f73166e42fa..3b5f16ce52d 100644
--- a/src/mongo/db/commands/dbcommands.cpp
+++ b/src/mongo/db/commands/dbcommands.cpp
@@ -539,8 +539,8 @@ public:
result.append("note", deprecationWarning);
}
- auto featureCompatibilityVersion = serverGlobalParams.featureCompatibilityVersion.load();
- if (ServerGlobalParams::FeatureCompatibilityVersion_32 == featureCompatibilityVersion &&
+ auto featureCompatibilityVersion = serverGlobalParams.featureCompatibility.version.load();
+ if (ServerGlobalParams::FeatureCompatibility::Version::k32 == featureCompatibilityVersion &&
cmdObj.hasField("collation")) {
return appendCommandStatus(
result,
diff --git a/src/mongo/db/commands/distinct.cpp b/src/mongo/db/commands/distinct.cpp
index e86a204e488..d580f4059f4 100644
--- a/src/mongo/db/commands/distinct.cpp
+++ b/src/mongo/db/commands/distinct.cpp
@@ -127,8 +127,8 @@ public:
}
if (!parsedDistinct.getValue().getQuery()->getQueryRequest().getCollation().isEmpty() &&
- serverGlobalParams.featureCompatibilityVersion.load() ==
- ServerGlobalParams::FeatureCompatibilityVersion_32) {
+ serverGlobalParams.featureCompatibility.version.load() ==
+ ServerGlobalParams::FeatureCompatibility::Version::k32) {
return Status(ErrorCodes::InvalidOptions,
"The featureCompatibilityVersion must be 3.4 to use collation. See "
"http://dochub.mongodb.org/core/3.4-feature-compatibility.");
@@ -176,8 +176,8 @@ public:
}
if (!parsedDistinct.getValue().getQuery()->getQueryRequest().getCollation().isEmpty() &&
- serverGlobalParams.featureCompatibilityVersion.load() ==
- ServerGlobalParams::FeatureCompatibilityVersion_32) {
+ serverGlobalParams.featureCompatibility.version.load() ==
+ ServerGlobalParams::FeatureCompatibility::Version::k32) {
return appendCommandStatus(
result,
Status(ErrorCodes::InvalidOptions,
diff --git a/src/mongo/db/commands/drop_indexes.cpp b/src/mongo/db/commands/drop_indexes.cpp
index cdca8e10bcb..fc18cdd3c86 100644
--- a/src/mongo/db/commands/drop_indexes.cpp
+++ b/src/mongo/db/commands/drop_indexes.cpp
@@ -145,7 +145,7 @@ public:
BackgroundOperation::assertNoBgOpInProgForNs(toReIndexNs.ns());
const auto featureCompatibilityVersion =
- serverGlobalParams.featureCompatibilityVersion.load();
+ serverGlobalParams.featureCompatibility.version.load();
const auto defaultIndexVersion =
IndexDescriptor::getDefaultIndexVersion(featureCompatibilityVersion);
diff --git a/src/mongo/db/commands/feature_compatibility_version.cpp b/src/mongo/db/commands/feature_compatibility_version.cpp
index cabbbb8c754..2ebc3b89354 100644
--- a/src/mongo/db/commands/feature_compatibility_version.cpp
+++ b/src/mongo/db/commands/feature_compatibility_version.cpp
@@ -48,10 +48,10 @@ constexpr StringData FeatureCompatibilityVersion::kVersionField;
constexpr StringData FeatureCompatibilityVersion::kVersion34;
constexpr StringData FeatureCompatibilityVersion::kVersion32;
-StatusWith<ServerGlobalParams::FeatureCompatibilityVersions> FeatureCompatibilityVersion::parse(
+StatusWith<ServerGlobalParams::FeatureCompatibility::Version> FeatureCompatibilityVersion::parse(
const BSONObj& featureCompatibilityVersionDoc) {
bool foundVersionField = false;
- ServerGlobalParams::FeatureCompatibilityVersions version;
+ ServerGlobalParams::FeatureCompatibility::Version version;
for (auto&& elem : featureCompatibilityVersionDoc) {
auto fieldName = elem.fieldNameStringData();
@@ -72,9 +72,9 @@ StatusWith<ServerGlobalParams::FeatureCompatibilityVersions> FeatureCompatibilit
<< featureCompatibilityVersionDoc);
}
if (elem.String() == FeatureCompatibilityVersion::kVersion34) {
- version = ServerGlobalParams::FeatureCompatibilityVersion_34;
+ version = ServerGlobalParams::FeatureCompatibility::Version::k34;
} else if (elem.String() == FeatureCompatibilityVersion::kVersion32) {
- version = ServerGlobalParams::FeatureCompatibilityVersion_32;
+ version = ServerGlobalParams::FeatureCompatibility::Version::k32;
} else {
return Status(ErrorCodes::BadValue,
str::stream() << "Invalid value for "
@@ -146,11 +146,11 @@ void FeatureCompatibilityVersion::set(OperationContext* txn, StringData version)
// Update server parameter.
if (version == FeatureCompatibilityVersion::kVersion34) {
- serverGlobalParams.featureCompatibilityVersion.store(
- ServerGlobalParams::FeatureCompatibilityVersion_34);
+ serverGlobalParams.featureCompatibility.version.store(
+ ServerGlobalParams::FeatureCompatibility::Version::k34);
} else if (version == FeatureCompatibilityVersion::kVersion32) {
- serverGlobalParams.featureCompatibilityVersion.store(
- ServerGlobalParams::FeatureCompatibilityVersion_32);
+ serverGlobalParams.featureCompatibility.version.store(
+ ServerGlobalParams::FeatureCompatibility::Version::k32);
}
}
@@ -180,8 +180,8 @@ void FeatureCompatibilityVersion::setIfCleanStartup(OperationContext* txn,
<< FeatureCompatibilityVersion::kVersion34)));
// Update server parameter.
- serverGlobalParams.featureCompatibilityVersion.store(
- ServerGlobalParams::FeatureCompatibilityVersion_34);
+ serverGlobalParams.featureCompatibility.version.store(
+ ServerGlobalParams::FeatureCompatibility::Version::k34);
}
}
@@ -191,7 +191,7 @@ void FeatureCompatibilityVersion::onInsertOrUpdate(const BSONObj& doc) {
idElement.String() != FeatureCompatibilityVersion::kParameterName) {
return;
}
- serverGlobalParams.featureCompatibilityVersion.store(
+ serverGlobalParams.featureCompatibility.version.store(
uassertStatusOK(FeatureCompatibilityVersion::parse(doc)));
}
@@ -201,8 +201,8 @@ void FeatureCompatibilityVersion::onDelete(const BSONObj& doc) {
idElement.String() != FeatureCompatibilityVersion::kParameterName) {
return;
}
- serverGlobalParams.featureCompatibilityVersion.store(
- ServerGlobalParams::FeatureCompatibilityVersion_32);
+ serverGlobalParams.featureCompatibility.version.store(
+ ServerGlobalParams::FeatureCompatibility::Version::k32);
}
/**
@@ -218,10 +218,10 @@ public:
) {}
StringData featureCompatibilityVersionStr() {
- switch (serverGlobalParams.featureCompatibilityVersion.load()) {
- case ServerGlobalParams::FeatureCompatibilityVersion_34:
+ switch (serverGlobalParams.featureCompatibility.version.load()) {
+ case ServerGlobalParams::FeatureCompatibility::Version::k34:
return FeatureCompatibilityVersion::kVersion34;
- case ServerGlobalParams::FeatureCompatibilityVersion_32:
+ case ServerGlobalParams::FeatureCompatibility::Version::k32:
return FeatureCompatibilityVersion::kVersion32;
default:
MONGO_UNREACHABLE;
diff --git a/src/mongo/db/commands/feature_compatibility_version.h b/src/mongo/db/commands/feature_compatibility_version.h
index bea195f73ed..ed1d82d7423 100644
--- a/src/mongo/db/commands/feature_compatibility_version.h
+++ b/src/mongo/db/commands/feature_compatibility_version.h
@@ -52,7 +52,7 @@ public:
* Parses the featureCompatibilityVersion document from admin.system.version, and returns the
* version.
*/
- static StatusWith<ServerGlobalParams::FeatureCompatibilityVersions> parse(
+ static StatusWith<ServerGlobalParams::FeatureCompatibility::Version> parse(
const BSONObj& featureCompatibilityVersionDoc);
/**
diff --git a/src/mongo/db/commands/find_cmd.cpp b/src/mongo/db/commands/find_cmd.cpp
index 5df8ba41e75..e86f3aa9cc6 100644
--- a/src/mongo/db/commands/find_cmd.cpp
+++ b/src/mongo/db/commands/find_cmd.cpp
@@ -149,8 +149,8 @@ public:
}
if (!qrStatus.getValue()->getCollation().isEmpty() &&
- serverGlobalParams.featureCompatibilityVersion.load() ==
- ServerGlobalParams::FeatureCompatibilityVersion_32) {
+ serverGlobalParams.featureCompatibility.version.load() ==
+ ServerGlobalParams::FeatureCompatibility::Version::k32) {
return Status(ErrorCodes::InvalidOptions,
"The featureCompatibilityVersion must be 3.4 to use collation. See "
"http://dochub.mongodb.org/core/3.4-feature-compatibility.");
@@ -253,8 +253,8 @@ public:
auto& qr = qrStatus.getValue();
if (!qr->getCollation().isEmpty() &&
- serverGlobalParams.featureCompatibilityVersion.load() ==
- ServerGlobalParams::FeatureCompatibilityVersion_32) {
+ serverGlobalParams.featureCompatibility.version.load() ==
+ ServerGlobalParams::FeatureCompatibility::Version::k32) {
return appendCommandStatus(
result,
Status(ErrorCodes::InvalidOptions,
diff --git a/src/mongo/db/commands/geo_near_cmd.cpp b/src/mongo/db/commands/geo_near_cmd.cpp
index 04bec8f0b1c..6e291e65f58 100644
--- a/src/mongo/db/commands/geo_near_cmd.cpp
+++ b/src/mongo/db/commands/geo_near_cmd.cpp
@@ -185,8 +185,8 @@ public:
}
}
if (!collation.isEmpty() &&
- serverGlobalParams.featureCompatibilityVersion.load() ==
- ServerGlobalParams::FeatureCompatibilityVersion_32) {
+ serverGlobalParams.featureCompatibility.version.load() ==
+ ServerGlobalParams::FeatureCompatibility::Version::k32) {
return appendCommandStatus(
result,
Status(ErrorCodes::InvalidOptions,
diff --git a/src/mongo/db/commands/group_cmd.cpp b/src/mongo/db/commands/group_cmd.cpp
index c7453865900..809ef8d2d1c 100644
--- a/src/mongo/db/commands/group_cmd.cpp
+++ b/src/mongo/db/commands/group_cmd.cpp
@@ -268,8 +268,8 @@ private:
request->collation = collationElt.embeddedObject().getOwned();
}
if (!request->collation.isEmpty() &&
- serverGlobalParams.featureCompatibilityVersion.load() ==
- ServerGlobalParams::FeatureCompatibilityVersion_32) {
+ serverGlobalParams.featureCompatibility.version.load() ==
+ ServerGlobalParams::FeatureCompatibility::Version::k32) {
return Status(ErrorCodes::InvalidOptions,
"The featureCompatibilityVersion must be 3.4 to use collation. See "
"http://dochub.mongodb.org/core/3.4-feature-compatibility.");
diff --git a/src/mongo/db/commands/mr.cpp b/src/mongo/db/commands/mr.cpp
index eb304a56f49..ab6329b76d2 100644
--- a/src/mongo/db/commands/mr.cpp
+++ b/src/mongo/db/commands/mr.cpp
@@ -1364,8 +1364,8 @@ public:
Config config(dbname, cmd);
if (!config.collation.isEmpty() &&
- serverGlobalParams.featureCompatibilityVersion.load() ==
- ServerGlobalParams::FeatureCompatibilityVersion_32) {
+ serverGlobalParams.featureCompatibility.version.load() ==
+ ServerGlobalParams::FeatureCompatibility::Version::k32) {
return appendCommandStatus(
result,
Status(ErrorCodes::InvalidOptions,
diff --git a/src/mongo/db/commands/pipeline_command.cpp b/src/mongo/db/commands/pipeline_command.cpp
index 66ab66b55e9..46cc4e8a40d 100644
--- a/src/mongo/db/commands/pipeline_command.cpp
+++ b/src/mongo/db/commands/pipeline_command.cpp
@@ -644,8 +644,8 @@ public:
// collection metadata. So the merger needs to accept a collation, and we rely on the shards
// to reject collations from the user.
if (!request.getValue().getCollation().isEmpty() &&
- serverGlobalParams.featureCompatibilityVersion.load() ==
- ServerGlobalParams::FeatureCompatibilityVersion_32 &&
+ serverGlobalParams.featureCompatibility.version.load() ==
+ ServerGlobalParams::FeatureCompatibility::Version::k32 &&
!isMergePipeline(request.getValue().getPipeline())) {
return appendCommandStatus(
result,
diff --git a/src/mongo/db/db.cpp b/src/mongo/db/db.cpp
index c8780261ec6..72e4c0ed240 100644
--- a/src/mongo/db/db.cpp
+++ b/src/mongo/db/db.cpp
@@ -440,7 +440,7 @@ void repairDatabasesAndCheckVersion(OperationContext* txn) {
severe() << version.getStatus();
fassertFailedNoTrace(40283);
}
- serverGlobalParams.featureCompatibilityVersion.store(version.getValue());
+ serverGlobalParams.featureCompatibility.version.store(version.getValue());
}
}
}
@@ -800,6 +800,10 @@ ExitCode _initAndListen(int listenPort) {
FeatureCompatibilityVersion::setIfCleanStartup(
startupOpCtx.get(), repl::StorageInterface::get(getGlobalServiceContext()));
}
+
+ if (replSettings.usingReplSets() || (!replSettings.isMaster() && replSettings.isSlave())) {
+ serverGlobalParams.featureCompatibility.validateFeaturesAsMaster.store(false);
+ }
}
startClientCursorMonitor();
diff --git a/src/mongo/db/index/index_descriptor.cpp b/src/mongo/db/index/index_descriptor.cpp
index d86ee74498b..1f9e901dde6 100644
--- a/src/mongo/db/index/index_descriptor.cpp
+++ b/src/mongo/db/index/index_descriptor.cpp
@@ -95,7 +95,7 @@ bool IndexDescriptor::isIndexVersionSupported(IndexVersion indexVersion) {
Status IndexDescriptor::isIndexVersionAllowedForCreation(
IndexVersion indexVersion,
- ServerGlobalParams::FeatureCompatibilityVersions featureCompatibilityVersion,
+ ServerGlobalParams::FeatureCompatibility::Version featureCompatibilityVersion,
const BSONObj& indexSpec) {
switch (indexVersion) {
case IndexVersion::kV0:
@@ -103,7 +103,8 @@ Status IndexDescriptor::isIndexVersionAllowedForCreation(
case IndexVersion::kV1:
return Status::OK();
case IndexVersion::kV2: {
- if (ServerGlobalParams::FeatureCompatibilityVersion_32 == featureCompatibilityVersion) {
+ if (ServerGlobalParams::FeatureCompatibility::Version::k32 ==
+ featureCompatibilityVersion) {
return {ErrorCodes::CannotCreateIndex,
str::stream() << "Invalid index specification " << indexSpec
<< "; cannot create an index with v="
@@ -122,7 +123,7 @@ Status IndexDescriptor::isIndexVersionAllowedForCreation(
}
IndexVersion IndexDescriptor::getDefaultIndexVersion(
- ServerGlobalParams::FeatureCompatibilityVersions featureCompatibilityVersion) {
+ ServerGlobalParams::FeatureCompatibility::Version featureCompatibilityVersion) {
// We pass in an empty object for the index specification because it is only used within the
// error reason.
if (!IndexDescriptor::isIndexVersionAllowedForCreation(
diff --git a/src/mongo/db/index/index_descriptor.h b/src/mongo/db/index/index_descriptor.h
index 581548b8b34..8263641958b 100644
--- a/src/mongo/db/index/index_descriptor.h
+++ b/src/mongo/db/index/index_descriptor.h
@@ -107,14 +107,14 @@ public:
*/
static Status isIndexVersionAllowedForCreation(
IndexVersion indexVersion,
- ServerGlobalParams::FeatureCompatibilityVersions featureCompatibilityVersion,
+ ServerGlobalParams::FeatureCompatibility::Version featureCompatibilityVersion,
const BSONObj& indexSpec);
/**
* Returns the index version to use if it isn't specified in the index specification.
*/
static IndexVersion getDefaultIndexVersion(
- ServerGlobalParams::FeatureCompatibilityVersions featureCompatibilityVersion);
+ ServerGlobalParams::FeatureCompatibility::Version featureCompatibilityVersion);
//
// Information about the key pattern.
diff --git a/src/mongo/db/ops/parsed_delete.cpp b/src/mongo/db/ops/parsed_delete.cpp
index 31d049ec248..6508c99c120 100644
--- a/src/mongo/db/ops/parsed_delete.cpp
+++ b/src/mongo/db/ops/parsed_delete.cpp
@@ -62,8 +62,8 @@ Status ParsedDelete::parseRequest() {
invariant(_request->getProj().isEmpty() || _request->shouldReturnDeleted());
if (!_request->getCollation().isEmpty() &&
- serverGlobalParams.featureCompatibilityVersion.load() ==
- ServerGlobalParams::FeatureCompatibilityVersion_32) {
+ serverGlobalParams.featureCompatibility.version.load() ==
+ ServerGlobalParams::FeatureCompatibility::Version::k32) {
return Status(ErrorCodes::InvalidOptions,
"The featureCompatibilityVersion must be 3.4 to use collation. See "
"http://dochub.mongodb.org/core/3.4-feature-compatibility.");
diff --git a/src/mongo/db/ops/parsed_update.cpp b/src/mongo/db/ops/parsed_update.cpp
index d7fe607a855..da9eba4bd93 100644
--- a/src/mongo/db/ops/parsed_update.cpp
+++ b/src/mongo/db/ops/parsed_update.cpp
@@ -52,8 +52,8 @@ Status ParsedUpdate::parseRequest() {
invariant(_request->getProj().isEmpty() || _request->shouldReturnAnyDocs());
if (!_request->getCollation().isEmpty()) {
- if (serverGlobalParams.featureCompatibilityVersion.load() ==
- ServerGlobalParams::FeatureCompatibilityVersion_32) {
+ if (serverGlobalParams.featureCompatibility.version.load() ==
+ ServerGlobalParams::FeatureCompatibility::Version::k32) {
return Status(ErrorCodes::InvalidOptions,
"The featureCompatibilityVersion must be 3.4 to use collation. See "
"http://dochub.mongodb.org/core/3.4-feature-compatibility.");
diff --git a/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp b/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp
index a0f0104a5f7..220d66b2636 100644
--- a/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp
+++ b/src/mongo/db/repl/replication_coordinator_external_state_impl.cpp
@@ -67,6 +67,7 @@
#include "mongo/db/repl/sync_tail.h"
#include "mongo/db/s/sharding_state.h"
#include "mongo/db/s/sharding_state_recovery.h"
+#include "mongo/db/server_options.h"
#include "mongo/db/server_parameters.h"
#include "mongo/db/service_context.h"
#include "mongo/db/storage/storage_engine.h"
@@ -404,6 +405,8 @@ OpTime ReplicationCoordinatorExternalStateImpl::onTransitionToPrimary(OperationC
_shardingOnTransitionToPrimaryHook(txn);
_dropAllTempCollections(txn);
+ serverGlobalParams.featureCompatibility.validateFeaturesAsMaster.store(true);
+
return opTimeToReturn;
}
diff --git a/src/mongo/db/repl/replication_coordinator_impl.cpp b/src/mongo/db/repl/replication_coordinator_impl.cpp
index 006d15bfc38..fc11d0d3fe4 100644
--- a/src/mongo/db/repl/replication_coordinator_impl.cpp
+++ b/src/mongo/db/repl/replication_coordinator_impl.cpp
@@ -2629,6 +2629,7 @@ ReplicationCoordinatorImpl::_updateMemberStateFromTopologyCoordinator_inlock() {
// Wake up the optime waiter that is waiting for primary catch-up to finish.
_opTimeWaiterList.signalAndRemoveAll_inlock();
_canAcceptNonLocalWrites = false;
+ serverGlobalParams.featureCompatibility.validateFeaturesAsMaster.store(false);
result = kActionCloseAllConnections;
} else {
result = kActionFollowerModeStateChange;
diff --git a/src/mongo/db/server_options.h b/src/mongo/db/server_options.h
index 3c1b524f250..6f555e39ffd 100644
--- a/src/mongo/db/server_options.h
+++ b/src/mongo/db/server_options.h
@@ -138,21 +138,32 @@ struct ServerGlobalParams {
// queryableBackupMode.
BSONObj overrideShardIdentity;
- enum FeatureCompatibilityVersions {
- /**
- * There may be 3.2 nodes in the cluster, so some 3.4 features are not allowed. Default
- * value.
- */
- FeatureCompatibilityVersion_32,
-
- /**
- * All nodes in the cluster should be 3.4, so all 3.4 features are allowed.
- */
- FeatureCompatibilityVersion_34
- };
-
- // Read-only parameter featureCompatibilityVersion.
- AtomicWord<FeatureCompatibilityVersions> featureCompatibilityVersion;
+ struct FeatureCompatibility {
+ enum class Version {
+ /**
+ * In this mode, the cluster will expose a 3.2-like API. Attempts by a client to use new
+ * features in 3.4, such as read-only views, collation, or the decimal128 BSON type,
+ * will be rejected.
+ */
+ k32,
+
+ /**
+ * In this mode, new features in 3.4 are allowed. The system should guarantee that no
+ * 3.2 node can participate in a cluster whose feature compatibility version is 3.4.
+ */
+ k34,
+ };
+
+ // Read-only parameter featureCompatibilityVersion.
+ AtomicWord<Version> version{Version::k32};
+
+ // Feature validation differs depending on the role of a mongod in a replica set or
+ // master/slave configuration. Masters/primaries can accept user-initiated writes and
+ // validate based on the feature compatibility version. A secondary/slave (which is not also
+ // a master) always validates in "3.4" mode so that it can sync 3.4 features, even when in
+ // "3.2" feature compatibility mode.
+ AtomicWord<bool> validateFeaturesAsMaster{true};
+ } featureCompatibility;
};
extern ServerGlobalParams serverGlobalParams;
diff --git a/src/mongo/db/views/view_catalog.cpp b/src/mongo/db/views/view_catalog.cpp
index 68880a1a70c..a8be7f54290 100644
--- a/src/mongo/db/views/view_catalog.cpp
+++ b/src/mongo/db/views/view_catalog.cpp
@@ -227,8 +227,8 @@ Status ViewCatalog::createView(OperationContext* txn,
const BSONObj& collation) {
stdx::lock_guard<stdx::mutex> lk(_mutex);
- if (serverGlobalParams.featureCompatibilityVersion.load() ==
- ServerGlobalParams::FeatureCompatibilityVersion_32) {
+ if (serverGlobalParams.featureCompatibility.version.load() ==
+ ServerGlobalParams::FeatureCompatibility::Version::k32) {
return Status(ErrorCodes::CommandNotSupported,
"Cannot create view when the featureCompatibilityVersion is 3.2. See "
"http://dochub.mongodb.org/core/3.4-feature-compatibility.");
@@ -259,8 +259,8 @@ Status ViewCatalog::modifyView(OperationContext* txn,
const BSONArray& pipeline) {
stdx::lock_guard<stdx::mutex> lk(_mutex);
- if (serverGlobalParams.featureCompatibilityVersion.load() ==
- ServerGlobalParams::FeatureCompatibilityVersion_32) {
+ if (serverGlobalParams.featureCompatibility.version.load() ==
+ ServerGlobalParams::FeatureCompatibility::Version::k32) {
return Status(ErrorCodes::CommandNotSupported,
"Cannot modify view when the featureCompatibilityVersion is 3.2. See "
"http://dochub.mongodb.org/core/3.4-feature-compatibility.");
diff --git a/src/mongo/dbtests/jstests.cpp b/src/mongo/dbtests/jstests.cpp
index d9dd6b69ce7..e04a178ecdf 100644
--- a/src/mongo/dbtests/jstests.cpp
+++ b/src/mongo/dbtests/jstests.cpp
@@ -791,8 +791,8 @@ public:
void run() {
// Set the featureCompatibilityVersion to 3.4 so that BSON validation always uses
// BSONVersion::kLatest.
- serverGlobalParams.featureCompatibilityVersion.store(
- ServerGlobalParams::FeatureCompatibilityVersion_34);
+ serverGlobalParams.featureCompatibility.version.store(
+ ServerGlobalParams::FeatureCompatibility::Version::k34);
unique_ptr<Scope> s(globalScriptEngine->newScope());
BSONObjBuilder b;
@@ -825,8 +825,8 @@ public:
void run() {
// Set the featureCompatibilityVersion to 3.4 so that BSON validation always uses
// BSONVersion::kLatest.
- serverGlobalParams.featureCompatibilityVersion.store(
- ServerGlobalParams::FeatureCompatibilityVersion_34);
+ serverGlobalParams.featureCompatibility.version.store(
+ ServerGlobalParams::FeatureCompatibility::Version::k34);
unique_ptr<Scope> s(globalScriptEngine->newScope());
ASSERT(s->exec("a = 5;", "a", false, true, false));
@@ -839,8 +839,8 @@ public:
void run() {
// Set the featureCompatibilityVersion to 3.4 so that BSON validation always uses
// BSONVersion::kLatest.
- serverGlobalParams.featureCompatibilityVersion.store(
- ServerGlobalParams::FeatureCompatibilityVersion_34);
+ serverGlobalParams.featureCompatibility.version.store(
+ ServerGlobalParams::FeatureCompatibility::Version::k34);
unique_ptr<Scope> s(globalScriptEngine->newScope());
@@ -1138,8 +1138,8 @@ public:
// Set the featureCompatibilityVersion to 3.4 so that BSON validation always uses
// BSONVersion::kLatest.
- serverGlobalParams.featureCompatibilityVersion.store(
- ServerGlobalParams::FeatureCompatibilityVersion_34);
+ serverGlobalParams.featureCompatibility.version.store(
+ ServerGlobalParams::FeatureCompatibility::Version::k34);
// Drop the collection
const ServiceContext::UniqueOperationContext txnPtr = cc().makeOperationContext();
diff --git a/src/mongo/rpc/object_check.h b/src/mongo/rpc/object_check.h
index c4f999fde20..7c7741ada62 100644
--- a/src/mongo/rpc/object_check.h
+++ b/src/mongo/rpc/object_check.h
@@ -45,10 +45,19 @@ class Status;
template <>
struct Validator<BSONObj> {
inline static BSONVersion enabledBSONVersion() {
- return serverGlobalParams.featureCompatibilityVersion.load() ==
- ServerGlobalParams::FeatureCompatibilityVersion_34
- ? BSONVersion::kV1_1
- : BSONVersion::kV1_0;
+ // If we're in the primary/master role accepting writes, but our feature compatibility
+ // version is 3.2, then we want to reject insertion of the decimal data type. Therefore, we
+ // perform BSON 1.0 validation.
+ if (serverGlobalParams.featureCompatibility.validateFeaturesAsMaster.load() &&
+ serverGlobalParams.featureCompatibility.version.load() ==
+ ServerGlobalParams::FeatureCompatibility::Version::k32) {
+ return BSONVersion::kV1_0;
+ }
+
+ // Except for the special case above, we want to accept any BSON version which we know
+ // about. For instance, if we are a slave/secondary syncing from a primary/master and we are
+ // in 3.2 feature compatibility mode, we still want to be able to sync NumberDecimal data.
+ return BSONVersion::kV1_1;
}
inline static Status validateLoad(const char* ptr, size_t length) {
diff --git a/src/mongo/s/catalog/replset/sharding_catalog_manager_impl.cpp b/src/mongo/s/catalog/replset/sharding_catalog_manager_impl.cpp
index b71af9ea0d5..6a962b33e66 100644
--- a/src/mongo/s/catalog/replset/sharding_catalog_manager_impl.cpp
+++ b/src/mongo/s/catalog/replset/sharding_catalog_manager_impl.cpp
@@ -810,8 +810,8 @@ StatusWith<string> ShardingCatalogManagerImpl::addShard(
// If the minimum allowed version for the cluster is 3.4, set the featureCompatibilityVersion to
// 3.4 on the shard.
- if (serverGlobalParams.featureCompatibilityVersion.load() ==
- ServerGlobalParams::FeatureCompatibilityVersion_34) {
+ if (serverGlobalParams.featureCompatibility.version.load() ==
+ ServerGlobalParams::FeatureCompatibility::Version::k34) {
auto versionResponse =
_runCommandForAddShard(txn,
targeter.get(),
diff --git a/src/mongo/s/server.cpp b/src/mongo/s/server.cpp
index 92475b6d31c..aafdfcb7502 100644
--- a/src/mongo/s/server.cpp
+++ b/src/mongo/s/server.cpp
@@ -339,8 +339,8 @@ MONGO_INITIALIZER_GENERAL(ForkServer, ("EndStartupOptionHandling"), ("default"))
// BSONVersion::kLatest.
MONGO_INITIALIZER_WITH_PREREQUISITES(SetFeatureCompatibilityVersion34, ("EndStartupOptionStorage"))
(InitializerContext* context) {
- mongo::serverGlobalParams.featureCompatibilityVersion.store(
- ServerGlobalParams::FeatureCompatibilityVersion_34);
+ mongo::serverGlobalParams.featureCompatibility.version.store(
+ ServerGlobalParams::FeatureCompatibility::Version::k34);
return Status::OK();
}
diff --git a/src/mongo/shell/dbshell.cpp b/src/mongo/shell/dbshell.cpp
index 06dac12f49c..7b91a93dddd 100644
--- a/src/mongo/shell/dbshell.cpp
+++ b/src/mongo/shell/dbshell.cpp
@@ -94,8 +94,8 @@ const auto kDefaultMongoURL = "mongodb://127.0.0.1:27017"_sd;
// uses BSONVersion::kLatest.
MONGO_INITIALIZER_WITH_PREREQUISITES(SetFeatureCompatibilityVersion34, ("EndStartupOptionSetup"))
(InitializerContext* context) {
- mongo::serverGlobalParams.featureCompatibilityVersion.store(
- ServerGlobalParams::FeatureCompatibilityVersion_34);
+ mongo::serverGlobalParams.featureCompatibility.version.store(
+ ServerGlobalParams::FeatureCompatibility::Version::k34);
return Status::OK();
}
}