diff --git a/src/mongo/db/mongod_main.cpp b/src/mongo/db/mongod_main.cpp index 51f12129501..99d47ce5a1e 100644 --- a/src/mongo/db/mongod_main.cpp +++ b/src/mongo/db/mongod_main.cpp @@ -158,7 +158,6 @@ #include "mongo/db/s/ddl_lock_manager.h" #include "mongo/db/s/migration_blocking_operation/multi_update_coordinator.h" #include "mongo/db/s/migration_chunk_cloner_source_op_observer.h" -#include "mongo/db/s/migration_util.h" #include "mongo/db/s/periodic_replica_set_configshard_maintenance_mode_checker.h" #include "mongo/db/s/periodic_sharded_index_consistency_checker.h" #include "mongo/db/s/query_analysis_op_observer_configsvr.h" @@ -235,6 +234,7 @@ #include "mongo/s/resource_yielders.h" #include "mongo/s/routing_information_cache.h" #include "mongo/s/service_entry_point_router_role.h" +#include "mongo/s/sharding_feature_flags_gen.h" #include "mongo/scripting/dbdirectclient_factory.h" #include "mongo/scripting/engine.h" #include "mongo/stdx/mutex.h" diff --git a/src/mongo/db/s/metadata_manager.cpp b/src/mongo/db/s/metadata_manager.cpp index c8fa5d3ee63..eff7b905fa2 100644 --- a/src/mongo/db/s/metadata_manager.cpp +++ b/src/mongo/db/s/metadata_manager.cpp @@ -30,6 +30,7 @@ #include "mongo/db/s/metadata_manager.h" #include "mongo/db/s/migration_util.h" +#include "mongo/db/s/shard_key_util.h" #include "mongo/logv2/log.h" #include "mongo/s/chunk_manager.h" @@ -53,7 +54,7 @@ bool metadataOverlapsRange(const CollectionMetadata& metadata, const ChunkRange& return true; } auto chunkRangeToCompareToMetadata = - migrationutil::extendOrTruncateBoundsForMetadata(metadata, range); + shardkeyutil::extendOrTruncateBoundsForMetadata(metadata, range); return metadata.rangeOverlapsChunk(chunkRangeToCompareToMetadata); } diff --git a/src/mongo/db/s/migration_util.cpp b/src/mongo/db/s/migration_util.cpp index af24d3f9a41..ed643326bff 100644 --- a/src/mongo/db/s/migration_util.cpp +++ b/src/mongo/db/s/migration_util.cpp @@ -240,44 +240,6 @@ BSONObj makeMigrationStatusDocumentDestination( return builder.obj(); } -ChunkRange extendOrTruncateBoundsForMetadata(const CollectionMetadata& metadata, - const ChunkRange& range) { - auto metadataShardKeyPattern = KeyPattern(metadata.getKeyPattern()); - - // If the input range is shorter than the range in the ChunkManager inside - // 'metadata', we must extend its bounds to get a correct comparison. If the input - // range is longer than the range in the ChunkManager, we likewise must shorten it. - // We make sure to match what's in the ChunkManager instead of the other way around, - // since the ChunkManager only stores ranges and compares overlaps using a string version of the - // key, rather than a BSONObj. This logic is necessary because the _metadata list can - // contain ChunkManagers with different shard keys if the shard key has been refined. - // - // Note that it's safe to use BSONObj::nFields() (which returns the number of top level - // fields in the BSONObj) to compare the two, since shard key refine operations can only add - // top-level fields. - // - // Using extractFieldsUndotted to shorten the input range is correct because the ChunkRange and - // the shard key pattern will both already store nested shard key fields as top-level dotted - // fields, and extractFieldsUndotted uses the top-level fields verbatim rather than treating - // dots as accessors for subfields. - auto metadataShardKeyPatternBson = metadataShardKeyPattern.toBSON(); - auto numFieldsInMetadataShardKey = metadataShardKeyPatternBson.nFields(); - auto numFieldsInInputRangeShardKey = range.getMin().nFields(); - if (numFieldsInInputRangeShardKey < numFieldsInMetadataShardKey) { - auto extendedRangeMin = metadataShardKeyPattern.extendRangeBound( - range.getMin(), false /* makeUpperInclusive */); - auto extendedRangeMax = metadataShardKeyPattern.extendRangeBound( - range.getMax(), false /* makeUpperInclusive */); - return ChunkRange(extendedRangeMin, extendedRangeMax); - } else if (numFieldsInInputRangeShardKey > numFieldsInMetadataShardKey) { - auto shortenedRangeMin = range.getMin().extractFieldsUndotted(metadataShardKeyPatternBson); - auto shortenedRangeMax = range.getMax().extractFieldsUndotted(metadataShardKeyPatternBson); - return ChunkRange(shortenedRangeMin, shortenedRangeMax); - } else { - return range; - } -} - bool deletionTaskUuidMatchesFilteringMetadataUuid( OperationContext* opCtx, const boost::optional& optCollDescr, diff --git a/src/mongo/db/s/migration_util.h b/src/mongo/db/s/migration_util.h index 06f1672261a..faab7c9fa7d 100644 --- a/src/mongo/db/s/migration_util.h +++ b/src/mongo/db/s/migration_util.h @@ -108,13 +108,6 @@ BSONObj makeMigrationStatusDocumentDestination( const BSONObj& max, boost::optional sessionOplogEntriesMigrated); -/** - * Returns a chunk range with extended or truncated boundaries to match the number of fields in the - * given metadata's shard key pattern. - */ -ChunkRange extendOrTruncateBoundsForMetadata(const CollectionMetadata& metadata, - const ChunkRange& range); - /** * Writes the migration coordinator document to config.migrationCoordinators and waits for majority * write concern. diff --git a/src/mongo/db/s/range_deletion_util_test.cpp b/src/mongo/db/s/range_deletion_util_test.cpp index 48bd09c2172..7e8fd4f24bd 100644 --- a/src/mongo/db/s/range_deletion_util_test.cpp +++ b/src/mongo/db/s/range_deletion_util_test.cpp @@ -47,7 +47,6 @@ #include "mongo/db/repl/wait_for_majority_service.h" #include "mongo/db/s/collection_metadata.h" #include "mongo/db/s/collection_sharding_runtime.h" -#include "mongo/db/s/migration_util.h" #include "mongo/db/s/operation_sharding_state.h" #include "mongo/db/s/range_deletion_task_gen.h" #include "mongo/db/s/shard_server_test_fixture.h" diff --git a/src/mongo/db/s/shard_filtering_metadata_refresh.cpp b/src/mongo/db/s/shard_filtering_metadata_refresh.cpp index 7146f5620a7..e71a908ca99 100644 --- a/src/mongo/db/s/shard_filtering_metadata_refresh.cpp +++ b/src/mongo/db/s/shard_filtering_metadata_refresh.cpp @@ -54,6 +54,7 @@ #include "mongo/db/s/read_only_catalog_cache_loader.h" #include "mongo/db/s/resharding/resharding_donor_recipient_common.h" #include "mongo/db/s/shard_filtering_util.h" +#include "mongo/db/s/shard_key_util.h" #include "mongo/db/s/sharding_migration_critical_section.h" #include "mongo/db/s/sharding_state.h" #include "mongo/db/service_context.h" @@ -603,7 +604,7 @@ void FilteringMetadataCache::_recoverMigrationCoordinations(OperationContext* op // Note this should only extend the range boundaries (if there has been a shard key // refine since the migration began) and never truncate them. auto chunkRangeToCompareToMetadata = - migrationutil::extendOrTruncateBoundsForMetadata(currentMetadata, doc.getRange()); + shardkeyutil::extendOrTruncateBoundsForMetadata(currentMetadata, doc.getRange()); if (currentMetadata.keyBelongsToMe(chunkRangeToCompareToMetadata.getMin())) { coordinator.setMigrationDecision(DecisionEnum::kAborted); } else { diff --git a/src/mongo/db/s/shard_key_util.cpp b/src/mongo/db/s/shard_key_util.cpp index 35340fbe423..f41ddf2b464 100644 --- a/src/mongo/db/s/shard_key_util.cpp +++ b/src/mongo/db/s/shard_key_util.cpp @@ -568,5 +568,43 @@ boost::optional ValidationBehaviorsReshardingBulkIndex::getShardKeyInde return _shardKeyIndexSpec; } +ChunkRange extendOrTruncateBoundsForMetadata(const CollectionMetadata& metadata, + const ChunkRange& range) { + auto metadataShardKeyPattern = KeyPattern(metadata.getKeyPattern()); + + // If the input range is shorter than the range in the ChunkManager inside + // 'metadata', we must extend its bounds to get a correct comparison. If the input + // range is longer than the range in the ChunkManager, we likewise must shorten it. + // We make sure to match what's in the ChunkManager instead of the other way around, + // since the ChunkManager only stores ranges and compares overlaps using a string version of the + // key, rather than a BSONObj. This logic is necessary because the _metadata list can + // contain ChunkManagers with different shard keys if the shard key has been refined. + // + // Note that it's safe to use BSONObj::nFields() (which returns the number of top level + // fields in the BSONObj) to compare the two, since shard key refine operations can only add + // top-level fields. + // + // Using extractFieldsUndotted to shorten the input range is correct because the ChunkRange and + // the shard key pattern will both already store nested shard key fields as top-level dotted + // fields, and extractFieldsUndotted uses the top-level fields verbatim rather than treating + // dots as accessors for subfields. + auto metadataShardKeyPatternBson = metadataShardKeyPattern.toBSON(); + auto numFieldsInMetadataShardKey = metadataShardKeyPatternBson.nFields(); + auto numFieldsInInputRangeShardKey = range.getMin().nFields(); + if (numFieldsInInputRangeShardKey < numFieldsInMetadataShardKey) { + auto extendedRangeMin = metadataShardKeyPattern.extendRangeBound( + range.getMin(), false /* makeUpperInclusive */); + auto extendedRangeMax = metadataShardKeyPattern.extendRangeBound( + range.getMax(), false /* makeUpperInclusive */); + return ChunkRange(extendedRangeMin, extendedRangeMax); + } else if (numFieldsInInputRangeShardKey > numFieldsInMetadataShardKey) { + auto shortenedRangeMin = range.getMin().extractFieldsUndotted(metadataShardKeyPatternBson); + auto shortenedRangeMax = range.getMax().extractFieldsUndotted(metadataShardKeyPatternBson); + return ChunkRange(shortenedRangeMin, shortenedRangeMax); + } else { + return range; + } +} + } // namespace shardkeyutil } // namespace mongo diff --git a/src/mongo/db/s/shard_key_util.h b/src/mongo/db/s/shard_key_util.h index cc693c9f7b0..5b8a1c62369 100644 --- a/src/mongo/db/s/shard_key_util.h +++ b/src/mongo/db/s/shard_key_util.h @@ -242,5 +242,12 @@ void validateTimeseriesShardKey(StringData timeFieldName, boost::optional metaFieldName, const BSONObj& shardKeyPattern); +/** + * Returns a chunk range with extended or truncated boundaries to match the number of fields in the + * given metadata's shard key pattern. + */ +ChunkRange extendOrTruncateBoundsForMetadata(const CollectionMetadata& metadata, + const ChunkRange& range); + } // namespace shardkeyutil } // namespace mongo