diff options
Diffstat (limited to 'src')
22 files changed, 65 insertions, 362 deletions
diff --git a/src/mongo/db/commands/set_feature_compatibility_version_command.cpp b/src/mongo/db/commands/set_feature_compatibility_version_command.cpp index 9b097faf0a5..1f146fa082f 100644 --- a/src/mongo/db/commands/set_feature_compatibility_version_command.cpp +++ b/src/mongo/db/commands/set_feature_compatibility_version_command.cpp @@ -86,7 +86,6 @@ #include "mongo/logv2/log.h" #include "mongo/rpc/get_status_from_command_result.h" #include "mongo/s/pm2423_feature_flags_gen.h" -#include "mongo/s/pm2583_feature_flags_gen.h" #include "mongo/s/resharding/resharding_feature_flag_gen.h" #include "mongo/s/sharding_feature_flags_gen.h" #include "mongo/stdx/unordered_set.h" @@ -344,14 +343,10 @@ public: // Drain moveChunks if the actualVersion relies on the new migration protocol but // the requestedVersion uses the old one (downgrading). - if ((feature_flags::gFeatureFlagMigrationRecipientCriticalSection - .isEnabledOnVersion(actualVersion) && - !feature_flags::gFeatureFlagMigrationRecipientCriticalSection - .isEnabledOnVersion(requestedVersion)) || - (feature_flags::gFeatureFlagNewPersistedChunkVersionFormat.isEnabledOnVersion( - actualVersion) && - !feature_flags::gFeatureFlagNewPersistedChunkVersionFormat.isEnabledOnVersion( - requestedVersion))) { + if (feature_flags::gFeatureFlagMigrationRecipientCriticalSection.isEnabledOnVersion( + actualVersion) && + !feature_flags::gFeatureFlagMigrationRecipientCriticalSection + .isEnabledOnVersion(requestedVersion)) { drainNewMoveChunks.emplace(opCtx, "setFeatureCompatibilityVersionDowngrade"); // At this point, because we are holding the MigrationBlockingGuard, no new @@ -445,10 +440,6 @@ public: actualVersion) && feature_flags::gFeatureFlagMigrationRecipientCriticalSection.isEnabledOnVersion( requestedVersion)) || - (!feature_flags::gFeatureFlagNewPersistedChunkVersionFormat.isEnabledOnVersion( - actualVersion) && - feature_flags::gFeatureFlagNewPersistedChunkVersionFormat.isEnabledOnVersion( - requestedVersion)) || orphanTrackingCondition) { drainOldMoveChunks.emplace(opCtx, "setFeatureCompatibilityVersionUpgrade"); diff --git a/src/mongo/db/s/balancer/type_migration.cpp b/src/mongo/db/s/balancer/type_migration.cpp index 1aac063b940..a47fdff6197 100644 --- a/src/mongo/db/s/balancer/type_migration.cpp +++ b/src/mongo/db/s/balancer/type_migration.cpp @@ -113,8 +113,7 @@ StatusWith<MigrationType> MigrationType::fromBSON(const BSONObj& source) { } try { - auto chunkVersionStatus = - ChunkVersion::fromBSONPositionalOrNewerFormat(source[chunkVersion.name()]); + auto chunkVersionStatus = ChunkVersion::parse(source[chunkVersion.name()]); migrationType._chunkVersion = chunkVersionStatus; } catch (const DBException& ex) { return ex.toStatus(); diff --git a/src/mongo/db/s/config/configsvr_merge_chunks_command.cpp b/src/mongo/db/s/config/configsvr_merge_chunks_command.cpp index ea2823dcdf0..db155fa6bea 100644 --- a/src/mongo/db/s/config/configsvr_merge_chunks_command.cpp +++ b/src/mongo/db/s/config/configsvr_merge_chunks_command.cpp @@ -96,8 +96,8 @@ public: request().getChunkRange(), request().getShard(), request().getValidAfter())); - return ConfigSvrMergeResponse{ChunkVersion::fromBSONPositionalOrNewerFormat( - shardAndCollVers[ChunkVersion::kShardVersionField])}; + return ConfigSvrMergeResponse{ + ChunkVersion::parse(shardAndCollVers[ChunkVersion::kShardVersionField])}; } private: diff --git a/src/mongo/db/s/config/sharding_catalog_manager_chunk_operations.cpp b/src/mongo/db/s/config/sharding_catalog_manager_chunk_operations.cpp index 0cf64cc5288..83daf277078 100644 --- a/src/mongo/db/s/config/sharding_catalog_manager_chunk_operations.cpp +++ b/src/mongo/db/s/config/sharding_catalog_manager_chunk_operations.cpp @@ -87,7 +87,7 @@ void appendShortVersion(BufBuilder* out, const ChunkType& chunk) { bb.append(ChunkType::min(), chunk.getMin()); bb.append(ChunkType::max(), chunk.getMax()); if (chunk.isVersionSet()) { - chunk.getVersion().appendLegacyWithField(&bb, ChunkType::lastmod()); + chunk.getVersion().serializeToBSON(ChunkType::lastmod(), &bb); } bb.done(); } @@ -684,7 +684,7 @@ StatusWith<BSONObj> ShardingCatalogManager::commitChunkSplit( BSONObjBuilder b(logDetail.subobjStart("before")); b.append(ChunkType::min(), range.getMin()); b.append(ChunkType::max(), range.getMax()); - collVersion.appendLegacyWithField(&b, ChunkType::lastmod()); + collVersion.serializeToBSON(ChunkType::lastmod(), &b); } if (splitChunkResult.newChunks->size() == 2) { @@ -960,8 +960,8 @@ StatusWith<BSONObj> ShardingCatalogManager::commitChunksMerge( b.append(chunkToMerge.toConfigBSON()); } } - initialVersion.appendLegacyWithField(&logDetail, "prevShardVersion"); - mergeVersion.appendLegacyWithField(&logDetail, "mergedVersion"); + initialVersion.serializeToBSON("prevShardVersion", &logDetail); + mergeVersion.serializeToBSON("mergedVersion", &logDetail); logDetail.append("owningShard", shardId); ShardingLogging::get(opCtx)->logChange( diff --git a/src/mongo/db/s/config/sharding_catalog_manager_commit_chunk_migration_test.cpp b/src/mongo/db/s/config/sharding_catalog_manager_commit_chunk_migration_test.cpp index 235954c5d5d..8452740c17e 100644 --- a/src/mongo/db/s/config/sharding_catalog_manager_commit_chunk_migration_test.cpp +++ b/src/mongo/db/s/config/sharding_catalog_manager_commit_chunk_migration_test.cpp @@ -140,7 +140,7 @@ TEST_F(CommitChunkMigrate, ChunksUpdatedCorrectly) { validAfter)); // Verify the versions returned match expected values. - auto mver = ChunkVersion::fromBSONPositionalOrNewerFormat(versions["shardVersion"]); + auto mver = ChunkVersion::parse(versions["shardVersion"]); ASSERT_EQ(ChunkVersion(migratedChunk.getVersion().majorVersion() + 1, 1, migratedChunk.getVersion().epoch(), @@ -148,7 +148,7 @@ TEST_F(CommitChunkMigrate, ChunksUpdatedCorrectly) { mver); // Verify that a collection version is returned - auto cver = ChunkVersion::fromBSONPositionalOrNewerFormat(versions["collectionVersion"]); + auto cver = ChunkVersion::parse(versions["collectionVersion"]); ASSERT_TRUE(mver.isOlderOrEqualThan(cver)); // Verify the chunks ended up in the right shards. @@ -222,11 +222,11 @@ TEST_F(CommitChunkMigrate, ChunksUpdatedCorrectlyWithoutControlChunk) { // Verify the version returned matches expected value. BSONObj versions = resultBSON.getValue(); - auto mver = ChunkVersion::fromBSONPositionalOrNewerFormat(versions["shardVersion"]); + auto mver = ChunkVersion::parse(versions["shardVersion"]); ASSERT_EQ(ChunkVersion(0, 0, origVersion.epoch(), origVersion.getTimestamp()), mver); // Verify that a collection version is returned - auto cver = ChunkVersion::fromBSONPositionalOrNewerFormat(versions["collectionVersion"]); + auto cver = ChunkVersion::parse(versions["collectionVersion"]); ASSERT_EQ(ChunkVersion(origMajorVersion + 1, 0, collEpoch, collTimestamp), cver); // Verify the chunk ended up in the right shard. @@ -288,7 +288,7 @@ TEST_F(CommitChunkMigrate, CheckCorrectOpsCommandNoCtlTrimHistory) { // Verify the version returned matches expected value. BSONObj versions = resultBSON.getValue(); - auto mver = ChunkVersion::fromBSONPositionalOrNewerFormat(versions["shardVersion"]); + auto mver = ChunkVersion::parse(versions["shardVersion"]); ASSERT_EQ(ChunkVersion(0, 0, origVersion.epoch(), origVersion.getTimestamp()), mver); // Verify the chunk ended up in the right shard. @@ -525,7 +525,7 @@ TEST_F(CommitChunkMigrate, CommitWithLastChunkOnShardShouldNotAffectOtherChunks) // Verify the versions returned match expected values. BSONObj versions = resultBSON.getValue(); - auto mver = ChunkVersion::fromBSONPositionalOrNewerFormat(versions["shardVersion"]); + auto mver = ChunkVersion::parse(versions["shardVersion"]); ASSERT_EQ(ChunkVersion(0, 0, origVersion.epoch(), origVersion.getTimestamp()), mver); // Verify the chunks ended up in the right shards. diff --git a/src/mongo/db/s/config/sharding_catalog_manager_merge_chunks_test.cpp b/src/mongo/db/s/config/sharding_catalog_manager_merge_chunks_test.cpp index 3b5951cd82e..15ae1c5eb5c 100644 --- a/src/mongo/db/s/config/sharding_catalog_manager_merge_chunks_test.cpp +++ b/src/mongo/db/s/config/sharding_catalog_manager_merge_chunks_test.cpp @@ -119,8 +119,8 @@ TEST_F(MergeChunkTest, MergeExistingChunksCorrectlyShouldSucceed) { _shardId, validAfter)); - auto collVersion = ChunkVersion::fromBSONPositionalOrNewerFormat(versions["collectionVersion"]); - auto shardVersion = ChunkVersion::fromBSONPositionalOrNewerFormat(versions["shardVersion"]); + auto collVersion = ChunkVersion::parse(versions["collectionVersion"]); + auto shardVersion = ChunkVersion::parse(versions["shardVersion"]); ASSERT_TRUE(origVersion.isOlderThan(shardVersion)); ASSERT_EQ(collVersion, shardVersion); diff --git a/src/mongo/db/s/config/sharding_catalog_manager_split_chunk_test.cpp b/src/mongo/db/s/config/sharding_catalog_manager_split_chunk_test.cpp index 1cc5f1c677d..bcb5557ff53 100644 --- a/src/mongo/db/s/config/sharding_catalog_manager_split_chunk_test.cpp +++ b/src/mongo/db/s/config/sharding_catalog_manager_split_chunk_test.cpp @@ -105,9 +105,8 @@ TEST_F(SplitChunkTest, SplitExistingChunkCorrectlyShouldSucceed) { splitPoints, "shard0000", false /* fromChunkSplitter*/)); - auto collVersion = - ChunkVersion::fromBSONPositionalOrNewerFormat(versions["collectionVersion"]); - auto shardVersion = ChunkVersion::fromBSONPositionalOrNewerFormat(versions["shardVersion"]); + auto collVersion = ChunkVersion::parse(versions["collectionVersion"]); + auto shardVersion = ChunkVersion::parse(versions["shardVersion"]); ASSERT_TRUE(origVersion.isOlderThan(shardVersion)); ASSERT_EQ(collVersion, shardVersion); diff --git a/src/mongo/db/s/shardsvr_merge_chunks_command.cpp b/src/mongo/db/s/shardsvr_merge_chunks_command.cpp index c3971e7afd6..8b3892a907b 100644 --- a/src/mongo/db/s/shardsvr_merge_chunks_command.cpp +++ b/src/mongo/db/s/shardsvr_merge_chunks_command.cpp @@ -149,8 +149,7 @@ void mergeChunks(OperationContext* opCtx, auto shardVersionReceived = [&]() -> boost::optional<ChunkVersion> { // Old versions might not have the shardVersion field if (cmdResponse.response[ChunkVersion::kShardVersionField]) { - return ChunkVersion::fromBSONPositionalOrNewerFormat( - cmdResponse.response[ChunkVersion::kShardVersionField]); + return ChunkVersion::parse(cmdResponse.response[ChunkVersion::kShardVersionField]); } return boost::none; }(); diff --git a/src/mongo/db/s/split_chunk.cpp b/src/mongo/db/s/split_chunk.cpp index 062f5b47752..964871d3740 100644 --- a/src/mongo/db/s/split_chunk.cpp +++ b/src/mongo/db/s/split_chunk.cpp @@ -255,8 +255,7 @@ StatusWith<boost::optional<ChunkRange>> splitChunk( boost::optional<ChunkVersion> shardVersionReceived = [&]() -> boost::optional<ChunkVersion> { // old versions might not have the shardVersion field if (cmdResponse.response[ChunkVersion::kShardVersionField]) { - return ChunkVersion::fromBSONPositionalOrNewerFormat( - cmdResponse.response[ChunkVersion::kShardVersionField]); + return ChunkVersion::parse(cmdResponse.response[ChunkVersion::kShardVersionField]); } return boost::none; }(); diff --git a/src/mongo/db/service_entry_point_common.cpp b/src/mongo/db/service_entry_point_common.cpp index 7b64af3ef83..bc167fba693 100644 --- a/src/mongo/db/service_entry_point_common.cpp +++ b/src/mongo/db/service_entry_point_common.cpp @@ -1683,7 +1683,7 @@ void ExecCommandDatabase::_initiateCommand() { boost::optional<ChunkVersion> shardVersion; if (auto shardVersionElem = request.body[ChunkVersion::kShardVersionField]) { - shardVersion = ChunkVersion::fromBSONPositionalOrNewerFormat(shardVersionElem); + shardVersion = ChunkVersion::parse(shardVersionElem); } boost::optional<DatabaseVersion> databaseVersion; diff --git a/src/mongo/s/SConscript b/src/mongo/s/SConscript index f08489a5a6b..b8873a4e131 100644 --- a/src/mongo/s/SConscript +++ b/src/mongo/s/SConscript @@ -183,7 +183,6 @@ env.Library( 'database_version.idl', 'mongod_and_mongos_server_parameters.idl', 'pm2423_feature_flags.idl', - 'pm2583_feature_flags.idl', 'request_types/abort_reshard_collection.idl', 'request_types/add_shard_request_type.cpp', 'request_types/get_stats_for_balancing.idl', diff --git a/src/mongo/s/catalog/type_chunk.cpp b/src/mongo/s/catalog/type_chunk.cpp index 0b1e431e04c..8ce3d377491 100644 --- a/src/mongo/s/catalog/type_chunk.cpp +++ b/src/mongo/s/catalog/type_chunk.cpp @@ -64,8 +64,6 @@ const BSONField<BSONObj> ChunkType::max("max"); const BSONField<std::string> ChunkType::shard("shard"); const BSONField<bool> ChunkType::jumbo("jumbo"); const BSONField<Date_t> ChunkType::lastmod("lastmod"); -const BSONField<OID> ChunkType::epoch("lastmodEpoch"); -const BSONField<Timestamp> ChunkType::timestamp("lastmodTimestamp"); const BSONField<BSONObj> ChunkType::history("history"); const BSONField<int64_t> ChunkType::estimatedSizeBytes("estimatedDataSizeBytes"); const BSONField<bool> ChunkType::historyIsAt40("historyIsAt40"); @@ -444,7 +442,7 @@ StatusWith<ChunkType> ChunkType::parseFromNetworkRequest(const BSONObj& source) } // Parse version. - chunk._version = ChunkVersion::fromBSONLegacyOrNewerFormat(source, ChunkType::lastmod()); + chunk._version = ChunkVersion::parse(source[ChunkType::lastmod()]); return chunk; } diff --git a/src/mongo/s/catalog/type_chunk.h b/src/mongo/s/catalog/type_chunk.h index c073009ba71..30de46edf3a 100644 --- a/src/mongo/s/catalog/type_chunk.h +++ b/src/mongo/s/catalog/type_chunk.h @@ -207,8 +207,6 @@ public: static const BSONField<std::string> shard; static const BSONField<bool> jumbo; static const BSONField<Date_t> lastmod; - static const BSONField<OID> epoch; - static const BSONField<Timestamp> timestamp; static const BSONField<BSONObj> history; static const BSONField<int64_t> estimatedSizeBytes; static const BSONField<bool> historyIsAt40; diff --git a/src/mongo/s/catalog/type_chunk_test.cpp b/src/mongo/s/catalog/type_chunk_test.cpp index f734ce07bf5..bc8d012f290 100644 --- a/src/mongo/s/catalog/type_chunk_test.cpp +++ b/src/mongo/s/catalog/type_chunk_test.cpp @@ -27,19 +27,15 @@ * it in the license file. */ -#include "mongo/platform/basic.h" - -#include "mongo/s/catalog/type_chunk.h" - #include "mongo/base/status_with.h" #include "mongo/db/jsobj.h" +#include "mongo/s/catalog/type_chunk.h" #include "mongo/unittest/unittest.h" #include "mongo/util/time_support.h" namespace mongo { namespace { -using std::string; using unittest::assertGet; const BSONObj kMin = BSON("a" << 10); @@ -56,24 +52,21 @@ TEST(ChunkType, MissingConfigRequiredFields) { BSONObj objModNS = BSON(ChunkType::name(OID::gen()) << ChunkType::min(BSON("a" << 10 << "b" << 10)) << ChunkType::max(BSON("a" << 20)) - << "lastmod" << Timestamp(chunkVersion.toLong()) << "lastmodEpoch" - << chunkVersion.epoch() << ChunkType::shard("shard0001")); + << "lastmod" << Timestamp(chunkVersion.toLong()) << ChunkType::shard("shard0001")); StatusWith<ChunkType> chunkRes = ChunkType::parseFromConfigBSON(objModNS, collEpoch, collTimestamp); ASSERT_FALSE(chunkRes.isOK()); - BSONObj objModKeys = - BSON(ChunkType::name(OID::gen()) << ChunkType::collectionUUID() << collUuid << "lastmod" - << Timestamp(chunkVersion.toLong()) << "lastmodEpoch" - << chunkVersion.epoch() << ChunkType::shard("shard0001")); + BSONObj objModKeys = BSON(ChunkType::name(OID::gen()) + << ChunkType::collectionUUID() << collUuid << "lastmod" + << Timestamp(chunkVersion.toLong()) << ChunkType::shard("shard0001")); chunkRes = ChunkType::parseFromConfigBSON(objModKeys, collEpoch, collTimestamp); ASSERT_FALSE(chunkRes.isOK()); BSONObj objModShard = BSON( ChunkType::name(OID::gen()) << ChunkType::collectionUUID() << collUuid << ChunkType::min(BSON("a" << 10 << "b" << 10)) - << ChunkType::max(BSON("a" << 20)) << "lastmod" << Timestamp(chunkVersion.toLong()) - << "lastmodEpoch" << chunkVersion.epoch()); + << ChunkType::max(BSON("a" << 20)) << "lastmod" << Timestamp(chunkVersion.toLong())); chunkRes = ChunkType::parseFromConfigBSON(objModShard, collEpoch, collTimestamp); ASSERT_FALSE(chunkRes.isOK()); @@ -255,32 +248,20 @@ TEST(ChunkType, UUIDPresentAndNsMissing) { ASSERT_TRUE(chunkRes.isOK()); } -TEST(ChunkType, NewAndOldChunkVersionFormat) { - const auto collEpoch = OID::gen(); - const auto collTimestamp = Timestamp(1); - - ChunkVersion chunkVersion(1, 2, collEpoch, collTimestamp); +TEST(ChunkType, ParseFromNetworkRequest) { + ChunkVersion chunkVersion(1, 2, OID::gen(), Timestamp(1, 0)); - BSONObj objModOldCVFormat = + auto chunk = assertGet(ChunkType::parseFromNetworkRequest( BSON(ChunkType::name(OID::gen()) << ChunkType::collectionUUID() << mongo::UUID::gen() << ChunkType::min(BSON("a" << 10 << "b" << 10)) << ChunkType::max(BSON("a" << 20)) << "lastmod" - << BSON("v" << Timestamp(chunkVersion.toLong()) << "e" << chunkVersion.epoch() << "t" - << chunkVersion.getTimestamp()) - << ChunkType::shard("shard0001")); - StatusWith<ChunkType> chunkRes = ChunkType::parseFromNetworkRequest(objModOldCVFormat); + << BSON("e" << chunkVersion.epoch() << "t" << chunkVersion.getTimestamp() << "v" + << Timestamp(chunkVersion.toLong())) + << ChunkType::shard("shard0001")))); - ASSERT_TRUE(chunkRes.isOK()); - - BSONObj objModNewCVFormat = BSON( - ChunkType::name(OID::gen()) - << ChunkType::collectionUUID() << mongo::UUID::gen() - << ChunkType::min(BSON("a" << 10 << "b" << 10)) << ChunkType::max(BSON("a" << 20)) - << "lastmod" << Timestamp(chunkVersion.toLong()) << "lastmodEpoch" << chunkVersion.epoch() - << "lastmodTimestamp" << chunkVersion.getTimestamp() << ChunkType::shard("shard0001")); - chunkRes = ChunkType::parseFromNetworkRequest(objModNewCVFormat); - ASSERT_TRUE(chunkRes.isOK()); + ASSERT_EQ("shard0001", chunk.getShard()); + ASSERT_EQ(chunkVersion, chunk.getVersion()); } TEST(ChunkRange, BasicBSONParsing) { diff --git a/src/mongo/s/chunk_version.cpp b/src/mongo/s/chunk_version.cpp index 8da764c2080..c63214daf8e 100644 --- a/src/mongo/s/chunk_version.cpp +++ b/src/mongo/s/chunk_version.cpp @@ -30,7 +30,6 @@ #include "mongo/s/chunk_version.h" #include "mongo/s/chunk_version_gen.h" -#include "mongo/s/pm2583_feature_flags_gen.h" #include "mongo/util/str.h" namespace mongo { @@ -57,157 +56,6 @@ std::string CollectionGeneration::toString() const { return str::stream() << _epoch << "|" << _timestamp; } -ChunkVersion ChunkVersion::_parseArrayOrObjectPositionalFormat(const BSONObj& obj) { - BSONObjIterator it(obj); - uassert(ErrorCodes::BadValue, "Unexpected empty version array", it.more()); - - // Expect the major and minor versions (must be present) - uint64_t combined; - { - BSONElement tsPart = it.next(); - uassert(ErrorCodes::TypeMismatch, - str::stream() << "Invalid type " << tsPart.type() - << " for version major and minor part.", - tsPart.type() == bsonTimestamp); - combined = tsPart.timestamp().asULL(); - } - - // Expect the epoch OID (must be present) - boost::optional<OID> epoch; - { - BSONElement epochPart = it.next(); - uassert(ErrorCodes::TypeMismatch, - str::stream() << "Invalid type " << epochPart.type() << " for version epoch part.", - epochPart.type() == jstOID); - epoch = epochPart.OID(); - } - - BSONElement nextElem = it.next(); - - // TODO SERVER-59105: remove once 6.0 is last-lts. For backward compatibility reasons 5.0 - // routers sends canThrowSSVOnIgnored even though it is not used, so we attempt to parse and - // ignore it. - if (nextElem.type() == BSONType::Bool) { - nextElem = it.next(); - } - - // Check for timestamp - boost::optional<Timestamp> timestamp; - if (nextElem.type() == bsonTimestamp) { - timestamp = nextElem.timestamp(); - } else if (nextElem.eoo() && (epoch == UNSHARDED().epoch() || epoch == IGNORED().epoch())) { - // In 5.0 binaries, the timestamp is not present in UNSHARDED and IGNORED versions - timestamp = - (epoch == UNSHARDED().epoch() ? UNSHARDED().getTimestamp() : IGNORED().getTimestamp()); - } else { - uasserted(ErrorCodes::TypeMismatch, - str::stream() << "Invalid type " << nextElem.type() - << " for version timestamp part."); - } - - ChunkVersion version; - version._combined = combined; - version._epoch = *epoch; - version._timestamp = *timestamp; - return version; -} - -StatusWith<ChunkVersion> ChunkVersion::_parseLegacyWithField(const BSONObj& obj, StringData field) { - // Expect the major and minor (must always exist) - uint64_t combined; - { - auto versionElem = obj[field]; - if (versionElem.eoo()) - return {ErrorCodes::NoSuchKey, - str::stream() << "Expected field " << field << " not found."}; - - if (versionElem.type() == bsonTimestamp || versionElem.type() == Date) { - combined = versionElem._numberLong(); - } else { - return {ErrorCodes::TypeMismatch, - str::stream() << "Invalid type " << versionElem.type() - << " for version major and minor part."}; - } - } - - // Expect the epoch OID - // - // TODO: Confirm whether the epoch can still be missing in upgrade chains that started from - // pre-2.4 versions anymore (after FCV 4.4 -> 5.0 upgrade) ? - boost::optional<OID> epoch; - { - const auto epochField = field + "Epoch"; - auto epochElem = obj[epochField]; - if (epochElem.type() == jstOID) { - epoch = epochElem.OID(); - } else if (!epochElem.eoo()) { - return {ErrorCodes::TypeMismatch, - str::stream() << "Invalid type " << epochElem.type() - << " for version epoch part."}; - } - } - - // Expect the timestamp (can be missing only in the case of pre-5.0 UNSHARDED and IGNORED - // versions) - boost::optional<Timestamp> timestamp; - { - const auto timestampField = field + "Timestamp"; - auto timestampElem = obj[timestampField]; - if (timestampElem.type() == bsonTimestamp) { - timestamp = timestampElem.timestamp(); - } else if (!timestampElem.eoo()) { - return {ErrorCodes::TypeMismatch, - str::stream() << "Invalid type " << timestampElem.type() - << " for version timestamp part."}; - } - } - - if (epoch && timestamp) { - // Expected situation - } else if (epoch && !timestamp) { - if (epoch == UNSHARDED().epoch() || epoch == IGNORED().epoch()) { - // In 5.0 binaries, the timestamp is not present in UNSHARDED and IGNORED versions - timestamp = (epoch == UNSHARDED().epoch() ? UNSHARDED().getTimestamp() - : IGNORED().getTimestamp()); - } else { - uasserted(6278300, "Timestamp must be present if epoch exists."); - } - } else if (!epoch && timestamp) { - uasserted(6278301, "Epoch must be present if timestamp exists."); - } else { - // Can happen in upgrade chains that started from pre-2.4 versions or in the case of - // persistence for ShardCollectionType - } - - ChunkVersion version; - version._combined = combined; - version._epoch = epoch.value_or(OID()); - version._timestamp = timestamp.value_or(Timestamp()); - return version; -} - -ChunkVersion ChunkVersion::fromBSONLegacyOrNewerFormat(const BSONObj& obj, StringData field) { - // New format. - if (obj[field].isABSONObj()) { - return parse(obj[field]); - } - - // Legacy format. - return uassertStatusOK(ChunkVersion::_parseLegacyWithField(obj, field)); -} - -ChunkVersion ChunkVersion::fromBSONPositionalOrNewerFormat(const BSONElement& element) { - auto obj = element.Obj(); - - // Positional or wrongly encoded format. - if (obj.couldBeArray()) { - return ChunkVersion::_parseArrayOrObjectPositionalFormat(obj); - } - - // New format. - return parse(element); -} - ChunkVersion ChunkVersion::parse(const BSONElement& element) { auto parsedVersion = ChunkVersion60Format::parse(IDLParserErrorContext("ChunkVersion"), element.Obj()); @@ -225,20 +73,6 @@ void ChunkVersion::serializeToBSON(StringData field, BSONObjBuilder* builder) co builder->append(field, version.toBSON()); } -void ChunkVersion::appendLegacyWithField(BSONObjBuilder* out, StringData field) const { - if (feature_flags::gFeatureFlagNewPersistedChunkVersionFormat.isEnabled( - serverGlobalParams.featureCompatibility)) { - ChunkVersion60Format version; - version.setGeneration({_epoch, _timestamp}); - version.setPlacement(Timestamp(majorVersion(), minorVersion())); - out->append(field, version.toBSON()); - } else { - out->appendTimestamp(field, _combined); - out->append(field + "Epoch", _epoch); - out->append(field + "Timestamp", _timestamp); - } -} - std::string ChunkVersion::toString() const { return str::stream() << majorVersion() << "|" << minorVersion() << "||" << _epoch << "||" << _timestamp.toString(); diff --git a/src/mongo/s/chunk_version.h b/src/mongo/s/chunk_version.h index 212b1218f41..79ff6c94c75 100644 --- a/src/mongo/s/chunk_version.h +++ b/src/mongo/s/chunk_version.h @@ -67,8 +67,6 @@ protected: * 2. (0, n), n > 0 - applicable only to shardVersion; shard has no chunk. * 3. (n, 0), n > 0 - invalid configuration. * 4. (n, m), n > 0, m > 0 - normal sharded collection version. - * - * TODO (SERVER-65530): Get rid of all the legacy format parsers/serialisers */ class ChunkVersion : public CollectionGeneration { public: @@ -85,23 +83,6 @@ public: ChunkVersion() : ChunkVersion(0, 0, OID(), Timestamp()) {} /** - * Allow parsing a chunk version with the following formats: - * {<field>:(major, minor), <fieldEpoch>:epoch, <fieldTimestmap>:timestamp} - * {<field>: {t:timestamp, e:epoch, v:(major, minor) }} - * TODO SERVER-63403: remove this function and only parse the new format. - */ - static ChunkVersion fromBSONLegacyOrNewerFormat(const BSONObj& obj, StringData field = ""); - - /** - * Allow parsing a chunk version with the following formats: - * [major, minor, epoch, <optional canThrowSSVOnIgnored>, timestamp] - * {0:major, 1:minor, 2:epoch, 3:<optional canThrowSSVOnIgnored>, 4:timestamp} - * {t:timestamp, e:epoch, v:(major, minor)} - * TODO SERVER-63403: remove this function and only parse the new format. - */ - static ChunkVersion fromBSONPositionalOrNewerFormat(const BSONElement& element); - - /** * Indicates that the collection is not sharded. */ static ChunkVersion UNSHARDED() { @@ -216,20 +197,6 @@ public: static ChunkVersion parse(const BSONElement& element); void serializeToBSON(StringData field, BSONObjBuilder* builder) const; - /** - * NOTE: This format is being phased out. Use serializeToBSON instead. - * - * Serializes the version held by this object to 'out' in the legacy form: - * { ..., <field>: [ <combined major/minor> ], - * <field>Epoch: [ <OID epoch> ], - * <field>Timestamp: [ <Timestamp> ] ... } - * or - * { ..., <field> : {t: <Timestamp>, e: <OID>, v: <major/minor>}}. - * - * Depending on the FCV version - */ - void appendLegacyWithField(BSONObjBuilder* out, StringData field) const; - std::string toString() const; // Methods that are here for the purposes of parsing of ShardCollectionType only @@ -239,28 +206,6 @@ public: BSONObjBuilder* builder) const; private: - // The following static functions will be deprecated. Only one function should be used to parse - // ChunkVersion and is fromBSON. - /** - * The method below parse the "positional" formats of: - * - * [major, minor, epoch, <optional canThrowSSVOnIgnored> timestamp] - * OR - * {0: major, 1:minor, 2:epoch, 3:<optional canThrowSSVOnIgnored>, 4:timestamp} - * - * The latter format was introduced by mistake in 4.4 and is no longer generated from 5.3 - * onwards, but it is backwards compatible with the 5.2 and older binaries. - */ - static ChunkVersion _parseArrayOrObjectPositionalFormat(const BSONObj& obj); - - /** - * Parses the BSON formatted by appendLegacyWithField. If the field is missing, returns - * 'NoSuchKey', otherwise if the field is not properly formatted can return any relevant parsing - * error (BadValue, TypeMismatch, etc). - */ - static StatusWith<ChunkVersion> _parseLegacyWithField(const BSONObj& obj, StringData field); - -private: // The combined major/minor version, which exists as subordinate to the collection generation uint64_t _combined; }; diff --git a/src/mongo/s/pm2583_feature_flags.idl b/src/mongo/s/pm2583_feature_flags.idl deleted file mode 100644 index 2fe34ddf7a3..00000000000 --- a/src/mongo/s/pm2583_feature_flags.idl +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (C) 2022-present MongoDB, Inc. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the Server Side Public License, version 1, -# as published by MongoDB, Inc. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# Server Side Public License for more details. -# -# You should have received a copy of the Server Side Public License -# along with this program. If not, see -# <http://www.mongodb.com/licensing/server-side-public-license>. -# -# As a special exception, the copyright holders give permission to link the -# code of portions of this program with the OpenSSL library under certain -# conditions as described in each individual source file and distribute -# linked combinations including the program with the OpenSSL library. You -# must comply with the Server Side Public License in all respects for -# all of the code used other than as permitted herein. If you modify file(s) -# with this exception, you may extend this exception to your version of the -# file(s), but you are not obligated to do so. If you do not wish to do so, -# delete this exception statement from your version. If you delete this -# exception statement from all source files in the program, then also delete -# it in the license file. -# - -# Feature flag for PM-2583 - -global: - cpp_namespace: "mongo::feature_flags" - -imports: - - "mongo/idl/basic_types.idl" - -feature_flags: - featureFlagNewPersistedChunkVersionFormat: - description: Feature flag for enabling the new persisted chunk version format. - cpp_varname: gFeatureFlagNewPersistedChunkVersionFormat - default: true - version: 6.0 diff --git a/src/mongo/s/request_types/balance_chunk_request_test.cpp b/src/mongo/s/request_types/balance_chunk_request_test.cpp index e58494d03e2..12ac80a5c09 100644 --- a/src/mongo/s/request_types/balance_chunk_request_test.cpp +++ b/src/mongo/s/request_types/balance_chunk_request_test.cpp @@ -66,9 +66,9 @@ TEST(BalanceChunkRequest, ParseFromConfigCommandNoSecondaryThrottle) { << "uuid" << uuid << "min" << BSON("a" << -100LL) << "max" << BSON("a" << 100LL) << "shard" << "TestShard0000" - << "lastmod" << Date_t::fromMillisSinceEpoch(version.toLong()) - << "lastmodEpoch" << version.epoch() << "lastmodTimestamp" - << version.getTimestamp()))); + << "lastmod" + << BSON("e" << version.epoch() << "t" << version.getTimestamp() + << "v" << Timestamp(version.toLong()))))); const auto& chunk = request.getChunk(); ASSERT_EQ("TestDB.TestColl", request.getNss().ns()); ASSERT_BSONOBJ_EQ(BSON("a" << -100LL), chunk.getMin()); @@ -81,7 +81,7 @@ TEST(BalanceChunkRequest, ParseFromConfigCommandNoSecondaryThrottle) { secondaryThrottle.getSecondaryThrottle()); } -TEST(BalanceChunkRequest, ParseFromConfigCommandWithUUID) { +TEST(BalanceChunkRequest, ParseFromConfigCommandWithUUIDNoSecondaryThrottle) { const auto uuid = UUID::gen(); const ChunkVersion version(1, 0, OID::gen(), Timestamp(1, 1)); auto request = assertGet(BalanceChunkRequest::parseFromConfigCommand( @@ -90,9 +90,9 @@ TEST(BalanceChunkRequest, ParseFromConfigCommandWithUUID) { << "uuid" << uuid << "min" << BSON("a" << -100LL) << "max" << BSON("a" << 100LL) << "shard" << "TestShard0000" - << "lastmod" << Date_t::fromMillisSinceEpoch(version.toLong()) - << "lastmodEpoch" << version.epoch() << "lastmodTimestamp" - << version.getTimestamp()))); + << "lastmod" + << BSON("e" << version.epoch() << "t" << version.getTimestamp() + << "v" << Timestamp(version.toLong()))))); const auto& chunk = request.getChunk(); ASSERT_EQ(uuid, chunk.getCollectionUUID()); ASSERT_BSONOBJ_EQ(BSON("a" << -100LL), chunk.getMin()); @@ -108,15 +108,18 @@ TEST(BalanceChunkRequest, ParseFromConfigCommandWithUUID) { TEST(BalanceChunkRequest, ParseFromConfigCommandWithSecondaryThrottle) { const auto uuid{UUID::gen()}; const ChunkVersion version(1, 0, OID::gen(), Timestamp(1, 1)); - auto request = assertGet(BalanceChunkRequest::parseFromConfigCommand(BSON( - "_configsvrMoveChunk" - << 1 << "ns" - << "TestDB.TestColl" - << "uuid" << uuid << "min" << BSON("a" << -100LL) << "max" << BSON("a" << 100LL) << "shard" - << "TestShard0000" - << "lastmod" << Date_t::fromMillisSinceEpoch(version.toLong()) << "lastmodEpoch" - << version.epoch() << "lastmodTimestamp" << version.getTimestamp() << "secondaryThrottle" - << BSON("_secondaryThrottle" << true << "writeConcern" << BSON("w" << 2))))); + auto request = assertGet(BalanceChunkRequest::parseFromConfigCommand( + BSON("_configsvrMoveChunk" + << 1 << "ns" + << "TestDB.TestColl" + << "uuid" << uuid << "min" << BSON("a" << -100LL) << "max" << BSON("a" << 100LL) + << "shard" + << "TestShard0000" + << "lastmod" + << BSON("e" << version.epoch() << "t" << version.getTimestamp() << "v" + << Timestamp(version.toLong())) + << "secondaryThrottle" + << BSON("_secondaryThrottle" << true << "writeConcern" << BSON("w" << 2))))); const auto& chunk = request.getChunk(); ASSERT_EQ("TestDB.TestColl", request.getNss().ns()); ASSERT_BSONOBJ_EQ(BSON("a" << -100LL), chunk.getMin()); diff --git a/src/mongo/s/request_types/balance_chunk_request_type.cpp b/src/mongo/s/request_types/balance_chunk_request_type.cpp index 78852c4450a..f94b61db12e 100644 --- a/src/mongo/s/request_types/balance_chunk_request_type.cpp +++ b/src/mongo/s/request_types/balance_chunk_request_type.cpp @@ -153,7 +153,7 @@ BSONObj BalanceChunkRequest::serializeToRebalanceCommandForConfig( range.append(&cmdBuilder); cmdBuilder.append(ChunkType::shard(), owningShard); collectionUUID.appendToBuilder(&cmdBuilder, ChunkType::collectionUUID()); - expectedChunkVersion.appendLegacyWithField(&cmdBuilder, ChunkType::lastmod()); + expectedChunkVersion.serializeToBSON(ChunkType::lastmod(), &cmdBuilder); cmdBuilder.append(WriteConcernOptions::kWriteConcernField, kMajorityWriteConcernNoTimeout.toBSON()); diff --git a/src/mongo/s/request_types/commit_chunk_migration_request_type.cpp b/src/mongo/s/request_types/commit_chunk_migration_request_type.cpp index 00c2f90f65b..15cb397a2af 100644 --- a/src/mongo/s/request_types/commit_chunk_migration_request_type.cpp +++ b/src/mongo/s/request_types/commit_chunk_migration_request_type.cpp @@ -123,8 +123,7 @@ StatusWith<CommitChunkMigrationRequest> CommitChunkMigrationRequest::createFromC } try { - auto fromShardVersion = - ChunkVersion::fromBSONPositionalOrNewerFormat(obj[kFromShardCollectionVersion]); + auto fromShardVersion = ChunkVersion::parse(obj[kFromShardCollectionVersion]); request._collectionEpoch = fromShardVersion.epoch(); request._collectionTimestamp = fromShardVersion.getTimestamp(); } catch (const DBException& ex) { @@ -164,7 +163,7 @@ void CommitChunkMigrationRequest::appendAsCommand(BSONObjBuilder* builder, { BSONObjBuilder migrateChunk(builder->subobjStart(kMigratedChunk)); migratedChunk.getRange().append(&migrateChunk); - migratedChunk.getVersion().appendLegacyWithField(&migrateChunk, ChunkType::lastmod()); + migratedChunk.getVersion().serializeToBSON(ChunkType::lastmod(), &migrateChunk); } fromShardCollectionVersion.serializeToBSON(kFromShardCollectionVersion, builder); builder->append(kValidAfter, validAfter); diff --git a/src/mongo/s/write_ops/batched_command_request.cpp b/src/mongo/s/write_ops/batched_command_request.cpp index 107f1a49204..c33280790d2 100644 --- a/src/mongo/s/write_ops/batched_command_request.cpp +++ b/src/mongo/s/write_ops/batched_command_request.cpp @@ -46,7 +46,7 @@ BatchedCommandRequest constructBatchedCommandRequest(const OpMsgRequest& request auto shardVersionField = request.body[ChunkVersion::kShardVersionField]; if (!shardVersionField.eoo()) { - auto shardVersion = ChunkVersion::fromBSONPositionalOrNewerFormat(shardVersionField); + auto shardVersion = ChunkVersion::parse(shardVersionField); if (shardVersion == ChunkVersion::UNSHARDED()) { batchRequest.setDbVersion(DatabaseVersion(request.body)); } diff --git a/src/mongo/s/write_ops/batched_command_request_test.cpp b/src/mongo/s/write_ops/batched_command_request_test.cpp index 9a5e968f10d..baa0c786e2a 100644 --- a/src/mongo/s/write_ops/batched_command_request_test.cpp +++ b/src/mongo/s/write_ops/batched_command_request_test.cpp @@ -60,14 +60,15 @@ TEST(BatchedCommandRequest, InsertWithShardVersion) { BSONArray insertArray = BSON_ARRAY(BSON("a" << 1) << BSON("b" << 1)); const OID epoch = OID::gen(); - const Timestamp majorAndMinor(1, 2); const Timestamp timestamp(2, 2); + const Timestamp majorAndMinor(1, 2); BSONObj origInsertRequestObj = BSON("insert" << "test" << "documents" << insertArray << "writeConcern" << BSON("w" << 1) << "ordered" << true << "shardVersion" - << BSON_ARRAY(majorAndMinor << epoch << timestamp)); + << BSON("e" << epoch << "t" << timestamp << "v" + << majorAndMinor)); for (auto docSeq : {false, true}) { const auto opMsgRequest(toOpMsg("TestDB", origInsertRequestObj, docSeq)); |