diff options
Diffstat (limited to 'src')
25 files changed, 188 insertions, 66 deletions
diff --git a/src/mongo/db/catalog/coll_mod.cpp b/src/mongo/db/catalog/coll_mod.cpp index 67ed3baa474..c541785e748 100644 --- a/src/mongo/db/catalog/coll_mod.cpp +++ b/src/mongo/db/catalog/coll_mod.cpp @@ -468,8 +468,15 @@ Status _collModInternal(OperationContext* opCtx, .throwIfReshardingInProgress(nss); } + // If db/collection/view does not exist, short circuit and return. if (!db || (!coll && !view)) { + if (nss.isTimeseriesBucketsCollection()) { + // If a sharded time-series collection is dropped, it's possible that a stale mongos + // sends the request on the buckets namespace instead of the view namespace. Ensure that + // the shardVersion is upto date before throwing an error. + CollectionShardingState::get(opCtx, nss)->checkShardVersionOrThrow(opCtx); + } return Status(ErrorCodes::NamespaceNotFound, "ns does not exist"); } diff --git a/src/mongo/db/coll_mod.idl b/src/mongo/db/coll_mod.idl index 54671dcde46..49a367f7729 100644 --- a/src/mongo/db/coll_mod.idl +++ b/src/mongo/db/coll_mod.idl @@ -146,4 +146,10 @@ commands: description: "Adjusts parameters for timeseries collections" optional: true type: CollModTimeseries + isTimeseriesNamespace: + description: "This flag is set to true when the command was originally sent to + mongos on the time-series view, but got rewritten to target + time-series buckets namespace before being sent to shards." + optional: true + type: bool reply_type: CollModReply diff --git a/src/mongo/db/commands/create_indexes.cpp b/src/mongo/db/commands/create_indexes.cpp index 7e7ececf79a..593d525a333 100644 --- a/src/mongo/db/commands/create_indexes.cpp +++ b/src/mongo/db/commands/create_indexes.cpp @@ -651,7 +651,10 @@ public: // If the request namespace refers to a time-series collection, transforms the user // time-series index request to one on the underlying bucket. boost::optional<CreateIndexesCommand> timeseriesCmdOwnership; - if (auto options = timeseries::getTimeseriesOptions(opCtx, origCmd.getNamespace())) { + auto isCommandOnTimeseriesBucketNamespace = + origCmd.getIsTimeseriesNamespace() && *origCmd.getIsTimeseriesNamespace(); + if (auto options = timeseries::getTimeseriesOptions( + opCtx, origCmd.getNamespace(), !isCommandOnTimeseriesBucketNamespace)) { timeseriesCmdOwnership = timeseries::makeTimeseriesCreateIndexesCommand(opCtx, origCmd, *options); cmd = ×eriesCmdOwnership.get(); diff --git a/src/mongo/db/commands/dbcommands.cpp b/src/mongo/db/commands/dbcommands.cpp index 3fd34d369e0..6271aa58417 100644 --- a/src/mongo/db/commands/dbcommands.cpp +++ b/src/mongo/db/commands/dbcommands.cpp @@ -116,7 +116,10 @@ std::unique_ptr<CollMod> makeTimeseriesBucketsCollModCommand(OperationContext* o const CollMod& origCmd) { const auto& origNs = origCmd.getNamespace(); - auto timeseriesOptions = timeseries::getTimeseriesOptions(opCtx, origNs); + auto isCommandOnTimeseriesBucketNamespace = + origCmd.getIsTimeseriesNamespace() && *origCmd.getIsTimeseriesNamespace(); + auto timeseriesOptions = + timeseries::getTimeseriesOptions(opCtx, origNs, !isCommandOnTimeseriesBucketNamespace); // Return early with null if we are not working with a time-series collection. if (!timeseriesOptions) { @@ -136,7 +139,8 @@ std::unique_ptr<CollMod> makeTimeseriesBucketsCollModCommand(OperationContext* o index->setKeyPattern(std::move(bucketsIndexSpecWithStatus.getValue())); } - auto ns = origNs.makeTimeseriesBucketsNamespace(); + auto ns = + isCommandOnTimeseriesBucketNamespace ? origNs : origNs.makeTimeseriesBucketsNamespace(); auto cmd = std::make_unique<CollMod>(ns); cmd->setIndex(index); cmd->setValidator(origCmd.getValidator()); @@ -160,7 +164,10 @@ std::unique_ptr<CollMod> makeTimeseriesViewCollModCommand(OperationContext* opCt const CollMod& origCmd) { const auto& ns = origCmd.getNamespace(); - auto timeseriesOptions = timeseries::getTimeseriesOptions(opCtx, ns); + auto isCommandOnTimeseriesBucketNamespace = + origCmd.getIsTimeseriesNamespace() && *origCmd.getIsTimeseriesNamespace(); + auto timeseriesOptions = + timeseries::getTimeseriesOptions(opCtx, ns, !isCommandOnTimeseriesBucketNamespace); // Return early with null if we are not working with a time-series collection. if (!timeseriesOptions) { diff --git a/src/mongo/db/commands/drop_indexes.cpp b/src/mongo/db/commands/drop_indexes.cpp index 4cdc3f46086..6718b518516 100644 --- a/src/mongo/db/commands/drop_indexes.cpp +++ b/src/mongo/db/commands/drop_indexes.cpp @@ -96,7 +96,10 @@ public: Reply typedRun(OperationContext* opCtx) final { // If the request namespace refers to a time-series collection, transform the user // time-series index request to one on the underlying bucket. - if (auto options = timeseries::getTimeseriesOptions(opCtx, request().getNamespace())) { + auto isCommandOnTimeseriesBucketNamespace = + request().getIsTimeseriesNamespace() && *request().getIsTimeseriesNamespace(); + if (auto options = timeseries::getTimeseriesOptions( + opCtx, request().getNamespace(), !isCommandOnTimeseriesBucketNamespace)) { auto timeseriesCmd = timeseries::makeTimeseriesDropIndexesCommand(opCtx, request(), *options); return dropIndexes(opCtx, timeseriesCmd.getNamespace(), timeseriesCmd.getIndex()); diff --git a/src/mongo/db/commands/list_indexes.cpp b/src/mongo/db/commands/list_indexes.cpp index a0a43160c67..fd140bf25db 100644 --- a/src/mongo/db/commands/list_indexes.cpp +++ b/src/mongo/db/commands/list_indexes.cpp @@ -74,8 +74,13 @@ IndexSpecsWithNamespaceString getIndexSpecsWithNamespaceString(OperationContext* // Since time-series collections don't have UUIDs, we skip the time-series lookup // if the target collection is specified as a UUID. if (const auto& origNss = origNssOrUUID.nss()) { - if (auto timeseriesOptions = timeseries::getTimeseriesOptions(opCtx, *origNss)) { - auto bucketsNss = origNss->makeTimeseriesBucketsNamespace(); + auto isCommandOnTimeseriesBucketNamespace = + cmd.getIsTimeseriesNamespace() && *cmd.getIsTimeseriesNamespace(); + if (auto timeseriesOptions = timeseries::getTimeseriesOptions( + opCtx, *origNss, !isCommandOnTimeseriesBucketNamespace)) { + auto bucketsNss = isCommandOnTimeseriesBucketNamespace + ? *origNss + : origNss->makeTimeseriesBucketsNamespace(); AutoGetCollectionForReadCommandMaybeLockFree autoColl(opCtx, bucketsNss); const CollectionPtr& coll = autoColl.getCollection(); diff --git a/src/mongo/db/commands/write_commands.cpp b/src/mongo/db/commands/write_commands.cpp index e45b7876c8a..d021b9bacc4 100644 --- a/src/mongo/db/commands/write_commands.cpp +++ b/src/mongo/db/commands/write_commands.cpp @@ -117,6 +117,9 @@ bool isTimeseries(OperationContext* opCtx, const Request& request) { "system.buckets namespace", !request.getIsTimeseriesNamespace() || request.getNamespace().isTimeseriesBucketsCollection()); + const auto bucketNss = request.getIsTimeseriesNamespace() + ? request.getNamespace() + : request.getNamespace().makeTimeseriesBucketsNamespace(); // If the buckets collection exists now, the time-series insert path will check for the // existence of the buckets collection later on with a lock. @@ -124,11 +127,9 @@ bool isTimeseries(OperationContext* opCtx, const Request& request) { // collection does not yet exist, this check may return false unnecessarily. As a result, an // insert attempt into the time-series namespace will either succeed or fail, depending on who // wins the race. - return request.getIsTimeseriesNamespace() || - CollectionCatalog::get(opCtx) - ->lookupCollectionByNamespaceForRead( - opCtx, request.getNamespace().makeTimeseriesBucketsNamespace()) - .get(); + return CollectionCatalog::get(opCtx) + ->lookupCollectionByNamespaceForRead(opCtx, bucketNss) + .get(); } NamespaceString makeTimeseriesBucketsNamespace(const NamespaceString& nss) { diff --git a/src/mongo/db/create_indexes.idl b/src/mongo/db/create_indexes.idl index 12f629ed7e2..e7b60e73790 100644 --- a/src/mongo/db/create_indexes.idl +++ b/src/mongo/db/create_indexes.idl @@ -183,3 +183,9 @@ commands: description: 'Commit Quorum options' type: CommitQuorum optional: true + isTimeseriesNamespace: + description: "This flag is set to true when the command was originally sent to + mongos on the time-series view, but got rewritten to target + time-series buckets namespace before being sent to shards." + type: bool + optional: true diff --git a/src/mongo/db/drop_indexes.idl b/src/mongo/db/drop_indexes.idl index 76d17a53e9e..cb4ea9eddb2 100644 --- a/src/mongo/db/drop_indexes.idl +++ b/src/mongo/db/drop_indexes.idl @@ -71,4 +71,10 @@ commands: - string - array<string> - object + isTimeseriesNamespace: + description: "This flag is set to true when the command was originally sent to + mongos on the time-series view, but got rewritten to target + time-series buckets namespace before being sent to shards." + type: bool + optional: true reply_type: DropIndexesReply diff --git a/src/mongo/db/list_indexes.idl b/src/mongo/db/list_indexes.idl index 684321a91e2..a9706a45628 100644 --- a/src/mongo/db/list_indexes.idl +++ b/src/mongo/db/list_indexes.idl @@ -176,4 +176,10 @@ commands: type: safeBool optional: true unstable: true + isTimeseriesNamespace: + description: "This flag is set to true when the command was originally sent to + mongos on the time-series view, but got rewritten to target + time-series buckets namespace before being sent to shards." + type: bool + optional: true reply_type: ListIndexesReply diff --git a/src/mongo/db/s/create_collection_coordinator.cpp b/src/mongo/db/s/create_collection_coordinator.cpp index e2bc62aa983..dca61f1644e 100644 --- a/src/mongo/db/s/create_collection_coordinator.cpp +++ b/src/mongo/db/s/create_collection_coordinator.cpp @@ -628,7 +628,7 @@ void CreateCollectionCoordinator::_checkCommandArguments(OperationContext* opCtx str::stream() << "can't shard time-series collection " << nss(), feature_flags::gFeatureFlagShardedTimeSeries.isEnabled( serverGlobalParams.featureCompatibility) || - !timeseries::getTimeseriesOptions(opCtx, nss().getTimeseriesViewNamespace())); + !timeseries::getTimeseriesOptions(opCtx, nss(), false)); } // Ensure the namespace is valid. diff --git a/src/mongo/db/s/shardsvr_create_collection_command.cpp b/src/mongo/db/s/shardsvr_create_collection_command.cpp index 193f8873df3..80123b0c82c 100644 --- a/src/mongo/db/s/shardsvr_create_collection_command.cpp +++ b/src/mongo/db/s/shardsvr_create_collection_command.cpp @@ -127,7 +127,7 @@ CreateCollectionResponse createCollectionLegacy(OperationContext* opCtx, // Ensure that a time-series collection cannot be sharded uassert(ErrorCodes::IllegalOperation, str::stream() << "can't shard time-series collection " << nss, - !timeseries::getTimeseriesOptions(opCtx, nss)); + !timeseries::getTimeseriesOptions(opCtx, nss, true)); // Ensure the namespace is valid. uassert(ErrorCodes::IllegalOperation, diff --git a/src/mongo/db/service_entry_point_common.cpp b/src/mongo/db/service_entry_point_common.cpp index 15d8de7fdc4..cd0e50f1d3b 100644 --- a/src/mongo/db/service_entry_point_common.cpp +++ b/src/mongo/db/service_entry_point_common.cpp @@ -1570,7 +1570,18 @@ void ExecCommandDatabase::_initiateCommand() { if (!opCtx->getClient()->isInDirectClient() && readConcernArgs.getLevel() != repl::ReadConcernLevel::kAvailableReadConcern && (iAmPrimary || (readConcernArgs.hasLevel() || readConcernArgs.getArgsAfterClusterTime()))) { - oss.initializeClientRoutingVersionsFromCommand(_invocation->ns(), request.body); + // If a timeseries collection is sharded, only the buckets collection would be sharded. We + // expect all versioned commands to be sent over 'system.buckets' namespace. But it is + // possible that a stale mongos may send the request over a view namespace. In this case, we + // initialize the 'OperationShardingState' with buckets namespace. + auto bucketNss = _invocation->ns().makeTimeseriesBucketsNamespace(); + auto namespaceForSharding = CollectionCatalog::get(opCtx) + ->lookupCollectionByNamespaceForRead(opCtx, bucketNss) + .get() + ? bucketNss + : _invocation->ns(); + + oss.initializeClientRoutingVersionsFromCommand(namespaceForSharding, request.body); auto const shardingState = ShardingState::get(opCtx); if (OperationShardingState::isOperationVersioned(opCtx) || oss.hasDbVersion()) { diff --git a/src/mongo/db/timeseries/catalog_helper.cpp b/src/mongo/db/timeseries/catalog_helper.cpp index 5ac55527f1a..4b577d55d30 100644 --- a/src/mongo/db/timeseries/catalog_helper.cpp +++ b/src/mongo/db/timeseries/catalog_helper.cpp @@ -38,8 +38,9 @@ namespace mongo { namespace timeseries { boost::optional<TimeseriesOptions> getTimeseriesOptions(OperationContext* opCtx, - const NamespaceString& nss) { - auto bucketsNs = nss.makeTimeseriesBucketsNamespace(); + const NamespaceString& nss, + bool convertToBucketsNamespace) { + auto bucketsNs = convertToBucketsNamespace ? nss.makeTimeseriesBucketsNamespace() : nss; auto bucketsColl = CollectionCatalog::get(opCtx)->lookupCollectionByNamespaceForRead(opCtx, bucketsNs); if (!bucketsColl) { diff --git a/src/mongo/db/timeseries/catalog_helper.h b/src/mongo/db/timeseries/catalog_helper.h index 969410d1c45..14cc681b4c3 100644 --- a/src/mongo/db/timeseries/catalog_helper.h +++ b/src/mongo/db/timeseries/catalog_helper.h @@ -46,7 +46,8 @@ namespace timeseries { * collection. Otherwise returns boost::none. */ boost::optional<TimeseriesOptions> getTimeseriesOptions(OperationContext* opCtx, - const NamespaceString& nss); + const NamespaceString& nss, + bool convertToBucketsNamespace); } // namespace timeseries } // namespace mongo diff --git a/src/mongo/db/timeseries/timeseries_commands_conversion_helper.cpp b/src/mongo/db/timeseries/timeseries_commands_conversion_helper.cpp index dde4edba15b..8f746fcfef2 100644 --- a/src/mongo/db/timeseries/timeseries_commands_conversion_helper.cpp +++ b/src/mongo/db/timeseries/timeseries_commands_conversion_helper.cpp @@ -41,9 +41,17 @@ namespace mongo::timeseries { +namespace { +NamespaceString makeTimeseriesBucketsNamespace(const NamespaceString& nss) { + return nss.isTimeseriesBucketsCollection() ? nss : nss.makeTimeseriesBucketsNamespace(); +} +} // namespace + + BSONObj makeTimeseriesCommand(const BSONObj& origCmd, const NamespaceString& ns, - const StringData nsFieldName) { + const StringData nsFieldName, + boost::optional<StringData> appendTimeSeriesFlag) { // Translate time-series collection view namespace to bucket namespace. const auto bucketNs = ns.makeTimeseriesBucketsNamespace(); BSONObjBuilder builder; @@ -54,6 +62,10 @@ BSONObj makeTimeseriesCommand(const BSONObj& origCmd, builder.append(entry); } } + + if (appendTimeSeriesFlag) { + builder.append(*appendTimeSeriesFlag, true); + } return builder.obj(); } @@ -100,7 +112,7 @@ CreateIndexesCommand makeTimeseriesCreateIndexesCommand(OperationContext* opCtx, indexes.push_back(builder.obj()); } - auto ns = origNs.makeTimeseriesBucketsNamespace(); + auto ns = makeTimeseriesBucketsNamespace(origNs); auto cmd = CreateIndexesCommand(ns, std::move(indexes)); cmd.setV(origCmd.getV()); cmd.setIgnoreUnknownIndexOptions(origCmd.getIgnoreUnknownIndexOptions()); @@ -113,7 +125,7 @@ DropIndexes makeTimeseriesDropIndexesCommand(OperationContext* opCtx, const DropIndexes& origCmd, const TimeseriesOptions& options) { const auto& origNs = origCmd.getNamespace(); - auto ns = origNs.makeTimeseriesBucketsNamespace(); + auto ns = makeTimeseriesBucketsNamespace(origNs); const auto& origIndex = origCmd.getIndex(); if (auto keyPtr = stdx::get_if<BSONObj>(&origIndex)) { diff --git a/src/mongo/db/timeseries/timeseries_commands_conversion_helper.h b/src/mongo/db/timeseries/timeseries_commands_conversion_helper.h index eef1de61621..d2641a17d65 100644 --- a/src/mongo/db/timeseries/timeseries_commands_conversion_helper.h +++ b/src/mongo/db/timeseries/timeseries_commands_conversion_helper.h @@ -43,7 +43,8 @@ namespace mongo::timeseries { */ BSONObj makeTimeseriesCommand(const BSONObj& origCmd, const NamespaceString& ns, - StringData nsFieldName); + StringData nsFieldName, + boost::optional<StringData> appendTimeSeriesFlag); /* * Returns a CreateIndexesCommand for creating indexes on the bucket collection. diff --git a/src/mongo/s/chunk_manager_targeter.cpp b/src/mongo/s/chunk_manager_targeter.cpp index a084d0e211a..f170e835034 100644 --- a/src/mongo/s/chunk_manager_targeter.cpp +++ b/src/mongo/s/chunk_manager_targeter.cpp @@ -235,29 +235,60 @@ bool isMetadataDifferent(const ChunkManager& managerA, const ChunkManager& manag ChunkManagerTargeter::ChunkManagerTargeter(OperationContext* opCtx, const NamespaceString& nss, boost::optional<OID> targetEpoch) - : _nss(nss), _targetEpoch(std::move(targetEpoch)), _cm(_init(opCtx)) {} + : _nss(nss), _targetEpoch(std::move(targetEpoch)), _cm(_init(opCtx, false)) {} -ChunkManager ChunkManagerTargeter::_init(OperationContext* opCtx) { +/** + * Initializes and returns the ChunkManger which needs to be used for targeting. + * If 'refresh' is true, additionally fetches the latest routing info from the config servers. + * + * Note: For sharded time-series collections, we use the buckets collection for targeting. If the + * user request is on the view namespace, we implicity tranform the request to the buckets namepace. + */ +ChunkManager ChunkManagerTargeter::_init(OperationContext* opCtx, bool refresh) { cluster::createDatabase(opCtx, _nss.db()); - // Check if we target sharded time-series collection. For such collections we target write - // operations to the underlying buckets collection. - // - // A sharded time-series collection by definition is a view, which has underlying sharded - // buckets collection. We know that 'ChunkManager::isSharded()' is false for all views. Checking - // this condition first can potentially save us extra cache lookup. After that, we lookup - // routing info for the underlying buckets collection. The absense of this routing info means - // that this collection does not exist. Finally, we check if this underlying collection is - // sharded. If all these conditions pass, we are targeting sharded time-series collection. + if (refresh) { + uassertStatusOK( + Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfoWithRefresh(opCtx, _nss)); + } auto cm = uassertStatusOK(getCollectionRoutingInfoForTxnCmd(opCtx, _nss)); - if (!cm.isSharded()) { + + // For a sharded time-series collection, only the underlying buckets collection is stored on the + // config servers. If the user operation is on the time-series view namespace, we should check + // if the buckets namespace is sharded. There are a few cases that we need to take care of, + // 1. The request is on the view namespace. We check if the buckets collection is sharded. If + // it is, we use the buckets collection namespace for the purpose of trageting. Additionally, + // we set the '_isRequestOnTimeseriesViewNamespace' to true for this case. + // 2. If request is on the buckets namespace, we don't need to execute any additional + // time-series logic. We can treat the request as though it was a request on a regular + // collection. + // 3. During a cache refresh a the buckets collection changes from sharded to unsharded. In this + // case, if the original request is on the view namespace, then we should reset the namespace + // back to the view namespace and reset '_isRequestOnTimeseriesViewNamespace'. + if (!cm.isSharded() && !_nss.isTimeseriesBucketsCollection()) { auto bucketsNs = _nss.makeTimeseriesBucketsNamespace(); + if (refresh) { + uassertStatusOK(Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfoWithRefresh( + opCtx, bucketsNs)); + } auto bucketsRoutingInfo = uassertStatusOK(getCollectionRoutingInfoForTxnCmd(opCtx, bucketsNs)); if (bucketsRoutingInfo.isSharded()) { _nss = bucketsNs; cm = std::move(bucketsRoutingInfo); + _isRequestOnTimeseriesViewNamespace = true; } + } else if (!cm.isSharded() && _isRequestOnTimeseriesViewNamespace) { + // This can happen if a sharded time-series collection is dropped and re-created. Then we + // need to reset the namepace to the original namespace. + _nss = _nss.getTimeseriesViewNamespace(); + + if (refresh) { + uassertStatusOK( + Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfoWithRefresh(opCtx, _nss)); + } + cm = uassertStatusOK(getCollectionRoutingInfoForTxnCmd(opCtx, _nss)); + _isRequestOnTimeseriesViewNamespace = false; } if (_targetEpoch) { @@ -312,7 +343,7 @@ ShardEndpoint ChunkManagerTargeter::targetInsert(OperationContext* opCtx, if (_cm.isSharded()) { const auto& shardKeyPattern = _cm.getShardKeyPattern(); - if (_nss.isTimeseriesBucketsCollection()) { + if (_isRequestOnTimeseriesViewNamespace) { auto tsFields = _cm.getTimeseriesFields(); tassert(5743701, "Missing timeseriesFields on buckets collection", tsFields); shardKey = extractBucketsShardKeyFromTimeseriesDoc( @@ -559,7 +590,16 @@ void ChunkManagerTargeter::noteStaleShardResponse(OperationContext* opCtx, const StaleConfigInfo& staleInfo) { dassert(!_lastError || _lastError.get() == LastErrorType::kStaleShardVersion); Grid::get(opCtx)->catalogCache()->invalidateShardOrEntireCollectionEntryForShardedCollection( - _nss, staleInfo.getVersionWanted(), endpoint.shardName); + staleInfo.getNss(), staleInfo.getVersionWanted(), endpoint.shardName); + + if (staleInfo.getNss() != _nss) { + // This can happen when a time-series collection becomes sharded. + Grid::get(opCtx) + ->catalogCache() + ->invalidateShardOrEntireCollectionEntryForShardedCollection( + _nss, staleInfo.getVersionWanted(), endpoint.shardName); + } + _lastError = LastErrorType::kStaleShardVersion; } @@ -590,14 +630,12 @@ bool ChunkManagerTargeter::refreshIfNeeded(OperationContext* opCtx) { // Get the latest metadata information from the cache if there were issues auto lastManager = _cm; - _cm = _init(opCtx); + _cm = _init(opCtx, false); auto metadataChanged = isMetadataDifferent(lastManager, _cm); if (_lastError.get() == LastErrorType::kCouldNotTarget && !metadataChanged) { // If we couldn't target and we dind't already update the metadata we must force a refresh - uassertStatusOK( - Grid::get(opCtx)->catalogCache()->getCollectionRoutingInfoWithRefresh(opCtx, _nss)); - _cm = _init(opCtx); + _cm = _init(opCtx, true); metadataChanged = isMetadataDifferent(lastManager, _cm); } diff --git a/src/mongo/s/chunk_manager_targeter.h b/src/mongo/s/chunk_manager_targeter.h index 57e9fc2a55d..0aef3ecbf52 100644 --- a/src/mongo/s/chunk_manager_targeter.h +++ b/src/mongo/s/chunk_manager_targeter.h @@ -122,7 +122,7 @@ public: const TimeseriesOptions& timeseriesOptions); private: - ChunkManager _init(OperationContext* opCtx); + ChunkManager _init(OperationContext* opCtx, bool refresh); /** * Returns a vector of ShardEndpoints for a potentially multi-shard query. @@ -150,6 +150,9 @@ private: // Full namespace of the collection for this targeter NamespaceString _nss; + // Used to identify the original namespace that the user has requested. + bool _isRequestOnTimeseriesViewNamespace = false; + // Stores last error occurred boost::optional<LastErrorType> _lastError; diff --git a/src/mongo/s/commands/cluster_coll_stats_cmd.cpp b/src/mongo/s/commands/cluster_coll_stats_cmd.cpp index c03c83279ff..f85ae09aeb2 100644 --- a/src/mongo/s/commands/cluster_coll_stats_cmd.cpp +++ b/src/mongo/s/commands/cluster_coll_stats_cmd.cpp @@ -216,7 +216,8 @@ public: // Translate command collection namespace for time-series collection. if (targeter.timeseriesNamespaceNeedsRewrite(nss)) { - cmdObjToSend = timeseries::makeTimeseriesCommand(cmdObjToSend, nss, getName()); + cmdObjToSend = + timeseries::makeTimeseriesCommand(cmdObjToSend, nss, getName(), boost::none); } // Unscaled individual shard results. This is required to apply scaling after summing the diff --git a/src/mongo/s/commands/cluster_collection_mod_cmd.cpp b/src/mongo/s/commands/cluster_collection_mod_cmd.cpp index ac369c6a8ba..e2e56136543 100644 --- a/src/mongo/s/commands/cluster_collection_mod_cmd.cpp +++ b/src/mongo/s/commands/cluster_collection_mod_cmd.cpp @@ -36,6 +36,7 @@ #include "mongo/db/coll_mod_gen.h" #include "mongo/db/coll_mod_reply_validation.h" #include "mongo/db/commands.h" +#include "mongo/db/timeseries/timeseries_commands_conversion_helper.h" #include "mongo/logv2/log.h" #include "mongo/s/chunk_manager_targeter.h" #include "mongo/s/cluster_commands_helpers.h" @@ -94,15 +95,19 @@ public: const auto targeter = ChunkManagerTargeter(opCtx, nss); const auto& routingInfo = targeter.getRoutingInfo(); + auto cmdToBeSent = cmdObj; + if (targeter.timeseriesNamespaceNeedsRewrite(nss)) { + cmdToBeSent = timeseries::makeTimeseriesCommand( + cmdToBeSent, nss, getName(), CollMod::kIsTimeseriesNamespaceFieldName); + } + auto shardResponses = scatterGatherVersionedTargetByRoutingTable( opCtx, cmd.getDbName(), targeter.getNS(), routingInfo, applyReadWriteConcern( - opCtx, - this, - CommandHelpers::filterCommandRequestForPassthrough(cmd.toBSON(BSONObj()))), + opCtx, this, CommandHelpers::filterCommandRequestForPassthrough(cmdToBeSent)), ReadPreferenceSetting::get(opCtx), Shard::RetryPolicy::kNoRetry, BSONObj() /* query */, diff --git a/src/mongo/s/commands/cluster_create_indexes_cmd.cpp b/src/mongo/s/commands/cluster_create_indexes_cmd.cpp index 05cec36eef0..8c4c8af8784 100644 --- a/src/mongo/s/commands/cluster_create_indexes_cmd.cpp +++ b/src/mongo/s/commands/cluster_create_indexes_cmd.cpp @@ -95,14 +95,8 @@ public: auto routingInfo = targeter.getRoutingInfo(); auto cmdToBeSent = cmdObj; if (targeter.timeseriesNamespaceNeedsRewrite(nss)) { - auto timeseriesCmd = timeseries::makeTimeseriesCreateIndexesCommand( - opCtx, - CreateIndexesCommand::parse( - IDLParserErrorContext("createIndexes", - APIParameters::get(opCtx).getAPIStrict().value_or(false)), - cmdObj), - routingInfo.getTimeseriesFields()->getTimeseriesOptions()); - cmdToBeSent = timeseriesCmd.toBSON(cmdObj); + cmdToBeSent = timeseries::makeTimeseriesCommand( + cmdToBeSent, nss, getName(), CreateIndexesCommand::kIsTimeseriesNamespaceFieldName); } auto shardResponses = scatterGatherVersionedTargetByRoutingTable( diff --git a/src/mongo/s/commands/cluster_drop_indexes_cmd.cpp b/src/mongo/s/commands/cluster_drop_indexes_cmd.cpp index d0cd02051fd..24f2f507137 100644 --- a/src/mongo/s/commands/cluster_drop_indexes_cmd.cpp +++ b/src/mongo/s/commands/cluster_drop_indexes_cmd.cpp @@ -146,16 +146,11 @@ public: // chunks for the collection. auto targeter = ChunkManagerTargeter(opCtx, nss); auto routingInfo = targeter.getRoutingInfo(); + auto cmdToBeSent = cmdObj; if (targeter.timeseriesNamespaceNeedsRewrite(nss)) { - auto timeseriesCmd = timeseries::makeTimeseriesDropIndexesCommand( - opCtx, - DropIndexes::parse( - IDLParserErrorContext("dropIndexes", - APIParameters::get(opCtx).getAPIStrict().value_or(false)), - cmdObj), - routingInfo.getTimeseriesFields()->getTimeseriesOptions()); - cmdToBeSent = timeseriesCmd.toBSON(cmdObj); + cmdToBeSent = timeseries::makeTimeseriesCommand( + cmdToBeSent, nss, getName(), DropIndexes::kIsTimeseriesNamespaceFieldName); } auto shardResponses = diff --git a/src/mongo/s/commands/cluster_list_indexes_cmd.cpp b/src/mongo/s/commands/cluster_list_indexes_cmd.cpp index 12bfd1e8800..3ae4cea812b 100644 --- a/src/mongo/s/commands/cluster_list_indexes_cmd.cpp +++ b/src/mongo/s/commands/cluster_list_indexes_cmd.cpp @@ -34,6 +34,7 @@ #include "mongo/db/auth/authorization_session.h" #include "mongo/db/commands.h" #include "mongo/db/list_indexes_gen.h" +#include "mongo/db/timeseries/timeseries_commands_conversion_helper.h" #include "mongo/rpc/get_status_from_command_result.h" #include "mongo/s/chunk_manager_targeter.h" #include "mongo/s/cluster_commands_helpers.h" @@ -115,14 +116,22 @@ public: // The command's IDL definition permits namespace or UUID, but mongos requires a // namespace. - auto targetter = ChunkManagerTargeter(opCtx, ns()); - auto cm = targetter.getRoutingInfo(); + auto targeter = ChunkManagerTargeter(opCtx, ns()); + auto cm = targeter.getRoutingInfo(); + auto cmdToBeSent = request().toBSON({}); + if (targeter.timeseriesNamespaceNeedsRewrite(ns())) { + cmdToBeSent = + timeseries::makeTimeseriesCommand(cmdToBeSent, + ns(), + ListIndexes::kCommandName, + ListIndexes::kIsTimeseriesNamespaceFieldName); + } return cursorCommandPassthroughShardWithMinKeyChunk( opCtx, - targetter.getNS(), + targeter.getNS(), cm, - applyReadWriteConcern(opCtx, this, request().toBSON({})), + applyReadWriteConcern(opCtx, this, cmdToBeSent), {Privilege(ResourcePattern::forExactNamespace(ns()), ActionType::listIndexes)}); } }; diff --git a/src/mongo/s/write_ops/batch_write_op.cpp b/src/mongo/s/write_ops/batch_write_op.cpp index 20e183e5ca6..85520f7d3a6 100644 --- a/src/mongo/s/write_ops/batch_write_op.cpp +++ b/src/mongo/s/write_ops/batch_write_op.cpp @@ -546,7 +546,8 @@ BatchedCommandRequest BatchWriteOp::buildBatchRequest(const TargetedWriteBatch& _clientRequest.getWriteCommandRequestBase().getBypassDocumentValidation()); wcb.setOrdered(_clientRequest.getWriteCommandRequestBase().getOrdered()); - if (targeter.isShardedTimeSeriesBucketsNamespace()) { + if (targeter.isShardedTimeSeriesBucketsNamespace() && + !_clientRequest.getNS().isTimeseriesBucketsCollection()) { wcb.setIsTimeseriesNamespace(true); } |