diff options
author | David Storch <david.storch@10gen.com> | 2016-09-14 18:02:10 -0400 |
---|---|---|
committer | David Storch <david.storch@10gen.com> | 2016-09-20 17:40:43 -0400 |
commit | 2ac0e07e7f82406e989fa272c68d1205ced81d78 (patch) | |
tree | eece2e1323d243c48e10304181a8678884035acd /src/mongo/db | |
parent | 585edf79040ed44db42e174b8659ca7290fa48cf (diff) | |
download | mongo-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.
Diffstat (limited to 'src/mongo/db')
28 files changed, 140 insertions, 119 deletions
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."); |