diff options
author | Xiangyu Yao <xiangyu.yao@mongodb.com> | 2019-07-29 17:08:44 -0400 |
---|---|---|
committer | Xiangyu Yao <xiangyu.yao@mongodb.com> | 2019-08-07 14:29:56 -0400 |
commit | 455b66c00bc5f885621477b63a7bfb2997ef59ae (patch) | |
tree | 5e462a40a31c3211d95c4fe91edea7a636bbe764 | |
parent | 590f4e148ac14bda1fc1e21b4d173c3bc2d25da2 (diff) | |
download | mongo-455b66c00bc5f885621477b63a7bfb2997ef59ae.tar.gz |
SERVER-40714 Change CollectionInfoCache to be a decoration (rather than a member) on Collection object
40 files changed, 186 insertions, 308 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript index fe54c0c35bc..c3d8fbb223d 100644 --- a/src/mongo/db/SConscript +++ b/src/mongo/db/SConscript @@ -1026,6 +1026,7 @@ env.Library( 'background', 'bson/dotted_path_support', 'catalog/collection', + 'catalog/collection_query_info', 'catalog/document_validation', 'catalog/index_catalog_entry', 'catalog/index_catalog', diff --git a/src/mongo/db/catalog/SConscript b/src/mongo/db/catalog/SConscript index 7998b28b160..103da73e09f 100644 --- a/src/mongo/db/catalog/SConscript +++ b/src/mongo/db/catalog/SConscript @@ -174,6 +174,7 @@ env.Library( ], LIBDEPS=[ '$BUILD_DIR/mongo/base', + '$BUILD_DIR/mongo/db/catalog/collection_query_info', '$BUILD_DIR/mongo/db/index/index_descriptor', '$BUILD_DIR/mongo/db/index_names', '$BUILD_DIR/mongo/db/ttl_collection_cache', @@ -281,7 +282,6 @@ env.Library( target='catalog_impl', source=[ "collection_impl.cpp", - "collection_info_cache_impl.cpp", "database_holder_impl.cpp", "database_impl.cpp", "index_catalog_entry_impl.cpp", @@ -371,6 +371,22 @@ env.Library( ], ) +env.Library( + target="collection_query_info", + source=[ + "$BUILD_DIR/mongo/db/query/collection_query_info.cpp", + ], + LIBDEPS=[ + '$BUILD_DIR/mongo/base', + '$BUILD_DIR/mongo/db/collection_index_usage_tracker', + '$BUILD_DIR/mongo/db/concurrency/lock_manager', + '$BUILD_DIR/mongo/db/curop', + '$BUILD_DIR/mongo/db/query/query_planner', + '$BUILD_DIR/mongo/db/update_index_data', + '$BUILD_DIR/mongo/db/service_context', + ], +) + env.CppUnitTest( target='db_catalog_test', source=[ diff --git a/src/mongo/db/catalog/collection.h b/src/mongo/db/catalog/collection.h index 3f025bacf25..9ae46ba6647 100644 --- a/src/mongo/db/catalog/collection.h +++ b/src/mongo/db/catalog/collection.h @@ -40,7 +40,6 @@ #include "mongo/base/string_data.h" #include "mongo/bson/mutable/damage_vector.h" #include "mongo/bson/timestamp.h" -#include "mongo/db/catalog/collection_info_cache.h" #include "mongo/db/catalog/collection_options.h" #include "mongo/db/concurrency/d_concurrency.h" #include "mongo/db/logical_session_id.h" @@ -54,6 +53,7 @@ #include "mongo/db/storage/snapshot.h" #include "mongo/stdx/condition_variable.h" #include "mongo/stdx/mutex.h" +#include "mongo/util/decorable.h" namespace mongo { class CappedCallback; @@ -148,7 +148,7 @@ private: bool _dead = false; }; -class Collection { +class Collection : public Decorable<Collection> { public: enum class StoreDeletedDoc { Off, On }; @@ -192,9 +192,6 @@ public: virtual bool ok() const = 0; - virtual CollectionInfoCache* infoCache() = 0; - virtual const CollectionInfoCache* infoCache() const = 0; - virtual const NamespaceString& ns() const = 0; /** diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp index 2d441c2b2f6..ae27627493c 100644 --- a/src/mongo/db/catalog/collection_impl.cpp +++ b/src/mongo/db/catalog/collection_impl.cpp @@ -41,7 +41,6 @@ #include "mongo/bson/simple_bsonobj_comparator.h" #include "mongo/db/background.h" #include "mongo/db/catalog/collection_catalog.h" -#include "mongo/db/catalog/collection_info_cache_impl.h" #include "mongo/db/catalog/collection_options.h" #include "mongo/db/catalog/document_validation.h" #include "mongo/db/catalog/index_catalog_impl.h" @@ -61,6 +60,7 @@ #include "mongo/db/ops/update_request.h" #include "mongo/db/query/collation/collator_factory_interface.h" #include "mongo/db/query/collation/collator_interface.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/query/internal_plans.h" #include "mongo/db/repl/oplog.h" #include "mongo/db/repl/replication_coordinator.h" @@ -200,7 +200,6 @@ CollectionImpl::CollectionImpl(OperationContext* opCtx, _recordStore(std::move(recordStore)), _needCappedLock(supportsDocLocking() && _recordStore && _recordStore->isCapped() && _ns.db() != "local"), - _infoCache(std::make_unique<CollectionInfoCacheImpl>(this, _ns)), _indexCatalog(std::make_unique<IndexCatalogImpl>(this)), _cappedNotifier(_recordStore && _recordStore->isCapped() ? std::make_unique<CappedInsertNotifier>() @@ -241,7 +240,6 @@ void CollectionImpl::init(OperationContext* opCtx) { _validationLevel = uassertStatusOK(_parseValidationLevel(collectionOptions.validationLevel)); getIndexCatalog()->init(opCtx).transitional_ignore(); - infoCache()->init(opCtx); _initialized = true; } @@ -1051,7 +1049,6 @@ std::unique_ptr<PlanExecutor, PlanExecutor::Deleter> CollectionImpl::makePlanExe void CollectionImpl::setNs(NamespaceString nss) { _ns = std::move(nss); - _infoCache->setNs(_ns); _recordStore.get()->setNs(_ns); } diff --git a/src/mongo/db/catalog/collection_impl.h b/src/mongo/db/catalog/collection_impl.h index 9f561c77693..c87a3cf6352 100644 --- a/src/mongo/db/catalog/collection_impl.h +++ b/src/mongo/db/catalog/collection_impl.h @@ -64,14 +64,6 @@ public: return _magic == kMagicNumber; } - CollectionInfoCache* infoCache() final { - return _infoCache.get(); - } - - const CollectionInfoCache* infoCache() const final { - return _infoCache.get(); - } - const NamespaceString& ns() const final { return _ns; } @@ -387,7 +379,6 @@ private: // The RecordStore may be null during a repair operation. std::unique_ptr<RecordStore> _recordStore; // owned const bool _needCappedLock; - std::unique_ptr<CollectionInfoCache> _infoCache; std::unique_ptr<IndexCatalog> _indexCatalog; diff --git a/src/mongo/db/catalog/collection_info_cache.h b/src/mongo/db/catalog/collection_info_cache.h deleted file mode 100644 index 8ae84fb3eec..00000000000 --- a/src/mongo/db/catalog/collection_info_cache.h +++ /dev/null @@ -1,118 +0,0 @@ -/** - * Copyright (C) 2018-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. - */ - -#pragma once - -#include "mongo/db/collection_index_usage_tracker.h" -#include "mongo/db/query/plan_cache.h" -#include "mongo/db/query/plan_summary_stats.h" -#include "mongo/db/query/query_settings.h" -#include "mongo/db/update_index_data.h" - -namespace mongo { -class Collection; -class IndexDescriptor; -class OperationContext; - -/** - * this is for storing things that you want to cache about a single collection - * life cycle is managed for you from inside Collection. - */ -class CollectionInfoCache { -public: - virtual ~CollectionInfoCache() = default; - - /** - * Builds internal cache state based on the current state of the Collection's IndexCatalog. - */ - virtual void init(OperationContext* const opCtx) = 0; - - /** - * Get the PlanCache for this collection. - */ - virtual PlanCache* getPlanCache() const = 0; - - /** - * Get the QuerySettings for this collection. - */ - virtual QuerySettings* getQuerySettings() const = 0; - - /* get set of index keys for this namespace. handy to quickly check if a given - field is indexed (Note it might be a secondary component of a compound index.) - */ - virtual const UpdateIndexData& getIndexKeys(OperationContext* const opCtx) const = 0; - - /** - * Returns cached index usage statistics for this collection. The map returned will contain - * entry for each index in the collection along with both a usage counter and a timestamp - * representing the date/time the counter is valid from. - * - * Note for performance that this method returns a copy of a StringMap. - */ - virtual CollectionIndexUsageMap getIndexUsageStats() const = 0; - - /** - * Returns a struct containing information on the number of collection scans that have been - * performed. - */ - virtual CollectionIndexUsageTracker::CollectionScanStats getCollectionScanStats() const = 0; - - /** - * Register a newly-created index with the cache. Must be called whenever an index is - * built on the associated collection. - * - * Must be called under exclusive collection lock. - */ - virtual void addedIndex(OperationContext* const opCtx, const IndexDescriptor* const desc) = 0; - - /** - * Deregister a newly-dropped index with the cache. Must be called whenever an index is - * dropped on the associated collection. - * - * Must be called under exclusive collection lock. - */ - virtual void droppedIndex(OperationContext* const opCtx, const StringData indexName) = 0; - - /** - * Removes all cached query plans. - */ - virtual void clearQueryCache() = 0; - - /** - * Signal to the cache that a query operation has completed. 'indexesUsed' should list the - * set of indexes used by the winning plan, if any. 'summaryStats.collectionScans' and - * 'summaryStats.collectionScansNonTailable' should be the number of collections scans and - * non-tailable collection scans that occured while executing the winning plan. - */ - virtual void notifyOfQuery(OperationContext* const opCtx, - const PlanSummaryStats& summaryStats) = 0; - - virtual void setNs(NamespaceString ns) = 0; -}; -} // namespace mongo diff --git a/src/mongo/db/catalog/collection_mock.h b/src/mongo/db/catalog/collection_mock.h index af1bc78c578..d18881c2501 100644 --- a/src/mongo/db/catalog/collection_mock.h +++ b/src/mongo/db/catalog/collection_mock.h @@ -60,12 +60,6 @@ public: std::abort(); } - CollectionInfoCache* infoCache() { - std::abort(); - } - const CollectionInfoCache* infoCache() const { - std::abort(); - } const IndexCatalog* getIndexCatalog() const { return _indexCatalog.get(); } diff --git a/src/mongo/db/catalog/index_build_block.cpp b/src/mongo/db/catalog/index_build_block.cpp index f30fc612272..b04e358d670 100644 --- a/src/mongo/db/catalog/index_build_block.cpp +++ b/src/mongo/db/catalog/index_build_block.cpp @@ -41,6 +41,7 @@ #include "mongo/db/index/index_descriptor.h" #include "mongo/db/logical_clock.h" #include "mongo/db/operation_context.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/storage/durable_catalog.h" #include "mongo/db/ttl_collection_cache.h" #include "mongo/util/assert_util.h" @@ -135,10 +136,10 @@ Status IndexBuildBlock::init(OperationContext* opCtx, Collection* collection) { }); } - // Register this index with the CollectionInfoCache to regenerate the cache. This way, updates + // Register this index with the CollectionQueryInfo to regenerate the cache. This way, updates // occurring while an index is being build in the background will be aware of whether or not // they need to modify any indexes. - collection->infoCache()->addedIndex(opCtx, _indexCatalogEntry->descriptor()); + CollectionQueryInfo::get(collection).addedIndex(opCtx, _indexCatalogEntry->descriptor()); return Status::OK(); } diff --git a/src/mongo/db/catalog/index_catalog_entry.h b/src/mongo/db/catalog/index_catalog_entry.h index 863718a57fc..6a5d1212ece 100644 --- a/src/mongo/db/catalog/index_catalog_entry.h +++ b/src/mongo/db/catalog/index_catalog_entry.h @@ -46,7 +46,6 @@ namespace mongo { class CollatorInterface; class CollectionCatalogEntry; -class CollectionInfoCache; class IndexAccessMethod; class IndexBuildInterceptor; class IndexDescriptor; diff --git a/src/mongo/db/catalog/index_catalog_entry_impl.cpp b/src/mongo/db/catalog/index_catalog_entry_impl.cpp index 1cd68cd0900..5b5523ce7c1 100644 --- a/src/mongo/db/catalog/index_catalog_entry_impl.cpp +++ b/src/mongo/db/catalog/index_catalog_entry_impl.cpp @@ -38,7 +38,6 @@ #include "mongo/base/init.h" #include "mongo/db/catalog/collection.h" -#include "mongo/db/catalog/collection_info_cache_impl.h" #include "mongo/db/concurrency/d_concurrency.h" #include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/index/index_access_method.h" @@ -49,6 +48,7 @@ #include "mongo/db/multi_key_path_tracker.h" #include "mongo/db/operation_context.h" #include "mongo/db/query/collation/collator_factory_interface.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/service_context.h" #include "mongo/db/storage/durable_catalog.h" #include "mongo/db/transaction_participant.h" @@ -61,9 +61,9 @@ using std::string; IndexCatalogEntryImpl::IndexCatalogEntryImpl(OperationContext* const opCtx, std::unique_ptr<IndexDescriptor> descriptor, - CollectionInfoCache* const infoCache) + CollectionQueryInfo* const queryInfo) : _descriptor(std::move(descriptor)), - _infoCache(infoCache), + _queryInfo(queryInfo), _ordering(Ordering::make(_descriptor->keyPattern())), _isReady(false), _prefix(DurableCatalog::get(opCtx)->getIndexPrefix( @@ -282,10 +282,10 @@ void IndexCatalogEntryImpl::setMultikey(OperationContext* opCtx, } } - if (indexMetadataHasChanged && _infoCache) { + if (indexMetadataHasChanged && _queryInfo) { LOG(1) << ns() << ": clearing plan cache - index " << _descriptor->keyPattern() << " set to multi key."; - _infoCache->clearQueryCache(); + _queryInfo->clearQueryCache(); } }; diff --git a/src/mongo/db/catalog/index_catalog_entry_impl.h b/src/mongo/db/catalog/index_catalog_entry_impl.h index 525b003b878..4e011e98b33 100644 --- a/src/mongo/db/catalog/index_catalog_entry_impl.h +++ b/src/mongo/db/catalog/index_catalog_entry_impl.h @@ -46,7 +46,7 @@ namespace mongo { class CollatorInterface; -class CollectionInfoCache; +class CollectionQueryInfo; class IndexAccessMethod; class IndexDescriptor; class MatchExpression; @@ -57,10 +57,9 @@ class IndexCatalogEntryImpl : public IndexCatalogEntry { IndexCatalogEntryImpl& operator=(const IndexCatalogEntryImpl&) = delete; public: - explicit IndexCatalogEntryImpl( - OperationContext* opCtx, - std::unique_ptr<IndexDescriptor> descriptor, // ownership passes to me - CollectionInfoCache* infoCache); // not owned, optional + IndexCatalogEntryImpl(OperationContext* opCtx, + std::unique_ptr<IndexDescriptor> descriptor, // ownership passes to me + CollectionQueryInfo* queryInfo); // not owned, optional ~IndexCatalogEntryImpl() final; @@ -189,7 +188,7 @@ private: std::unique_ptr<IndexDescriptor> _descriptor; // owned here - CollectionInfoCache* _infoCache; // not owned here + CollectionQueryInfo* _queryInfo; // not owned here std::unique_ptr<IndexAccessMethod> _accessMethod; diff --git a/src/mongo/db/catalog/index_catalog_impl.cpp b/src/mongo/db/catalog/index_catalog_impl.cpp index 261f656d77c..f5181ffe234 100644 --- a/src/mongo/db/catalog/index_catalog_impl.cpp +++ b/src/mongo/db/catalog/index_catalog_impl.cpp @@ -61,6 +61,7 @@ #include "mongo/db/ops/delete.h" #include "mongo/db/query/collation/collation_spec.h" #include "mongo/db/query/collation/collator_factory_interface.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/query/internal_plans.h" #include "mongo/db/repl/replication_coordinator.h" #include "mongo/db/server_options.h" @@ -127,6 +128,8 @@ Status IndexCatalogImpl::init(OperationContext* opCtx) { fassert(17340, entry->isReady(opCtx)); } + CollectionQueryInfo::get(_collection).init(opCtx); + _magic = INDEX_CATALOG_INIT; return Status::OK(); } @@ -372,7 +375,7 @@ IndexCatalogEntry* IndexCatalogImpl::createIndexEntry(OperationContext* opCtx, auto* const descriptorPtr = descriptor.get(); auto entry = std::make_shared<IndexCatalogEntryImpl>( - opCtx, std::move(descriptor), _collection->infoCache()); + opCtx, std::move(descriptor), &CollectionQueryInfo::get(_collection)); IndexDescriptor* desc = entry->descriptor(); @@ -404,7 +407,7 @@ IndexCatalogEntry* IndexCatalogImpl::createIndexEntry(OperationContext* opCtx, } else { _buildingIndexes.remove(descriptor); } - _collection->infoCache()->droppedIndex(opCtx, indexName); + CollectionQueryInfo::get(_collection).droppedIndex(opCtx, indexName); }); } @@ -917,10 +920,10 @@ public: auto indexDescriptor = _entry->descriptor(); _entries->add(std::move(_entry)); - // Refresh the CollectionInfoCache's knowledge of what indices are present. This must be + // Refresh the CollectionQueryInfo's knowledge of what indices are present. This must be // done after re-adding our IndexCatalogEntry to the '_entries' list, since 'addedIndex()' // refreshes its knowledge by iterating the list of indices currently in the catalog. - _collection->infoCache()->addedIndex(_opCtx, indexDescriptor); + CollectionQueryInfo::get(_collection).addedIndex(_opCtx, indexDescriptor); } private: @@ -954,7 +957,7 @@ Status IndexCatalogImpl::dropIndexEntry(OperationContext* opCtx, IndexCatalogEnt new IndexRemoveChange(opCtx, _collection, &_buildingIndexes, std::move(released))); } - _collection->infoCache()->droppedIndex(opCtx, indexName); + CollectionQueryInfo::get(_collection).droppedIndex(opCtx, indexName); entry = nullptr; deleteIndexFromDisk(opCtx, indexName); @@ -1195,19 +1198,19 @@ const IndexDescriptor* IndexCatalogImpl::refreshEntry(OperationContext* opCtx, // Delete the IndexCatalogEntry that owns this descriptor. After deletion, 'oldDesc' is // invalid and should not be dereferenced. Also, invalidate the index from the - // CollectionInfoCache. + // CollectionQueryInfo. auto oldEntry = _readyIndexes.release(oldDesc); invariant(oldEntry); opCtx->recoveryUnit()->registerChange( new IndexRemoveChange(opCtx, _collection, &_readyIndexes, std::move(oldEntry))); - _collection->infoCache()->droppedIndex(opCtx, indexName); + CollectionQueryInfo::get(_collection).droppedIndex(opCtx, indexName); // Ask the CollectionCatalogEntry for the new index spec. BSONObj spec = durableCatalog->getIndexSpec(opCtx, _collection->ns(), indexName).getOwned(); BSONObj keyPattern = spec.getObjectField("key"); // Re-register this index in the index catalog with the new spec. Also, add the new index - // to the CollectionInfoCache. + // to the CollectionQueryInfo. auto newDesc = std::make_unique<IndexDescriptor>(_collection, _getAccessMethodName(keyPattern), spec); const bool initFromDisk = false; @@ -1215,7 +1218,7 @@ const IndexDescriptor* IndexCatalogImpl::refreshEntry(OperationContext* opCtx, const IndexCatalogEntry* newEntry = createIndexEntry(opCtx, std::move(newDesc), initFromDisk, isReadyIndex); invariant(newEntry->isReady(opCtx)); - _collection->infoCache()->addedIndex(opCtx, newEntry->descriptor()); + CollectionQueryInfo::get(_collection).addedIndex(opCtx, newEntry->descriptor()); // Return the new descriptor. return newEntry->descriptor(); diff --git a/src/mongo/db/catalog/multi_index_block.cpp b/src/mongo/db/catalog/multi_index_block.cpp index 05068e4a89f..999bafd1286 100644 --- a/src/mongo/db/catalog/multi_index_block.cpp +++ b/src/mongo/db/catalog/multi_index_block.cpp @@ -47,6 +47,7 @@ #include "mongo/db/multi_key_path_tracker.h" #include "mongo/db/op_observer.h" #include "mongo/db/operation_context.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/repl/repl_set_config.h" #include "mongo/db/repl/replication_coordinator.h" #include "mongo/db/storage/storage_options.h" @@ -82,7 +83,7 @@ void MultiIndexBlock::cleanUpAfterBuild(OperationContext* opCtx, Collection* col } if (!_needToCleanup && !_indexes.empty()) { - collection->infoCache()->clearQueryCache(); + CollectionQueryInfo::get(collection).clearQueryCache(); } // Make lock acquisition uninterruptible. diff --git a/src/mongo/db/commands/SConscript b/src/mongo/db/commands/SConscript index cbfdc088df9..2d57cb8e0ed 100644 --- a/src/mongo/db/commands/SConscript +++ b/src/mongo/db/commands/SConscript @@ -280,6 +280,7 @@ env.Library( '$BUILD_DIR/mongo/base', '$BUILD_DIR/mongo/db/catalog/catalog_helpers', '$BUILD_DIR/mongo/db/catalog/collection_catalog_helper', + '$BUILD_DIR/mongo/db/catalog/collection_query_info', '$BUILD_DIR/mongo/db/catalog/collection_validation', '$BUILD_DIR/mongo/db/catalog/database_holder', '$BUILD_DIR/mongo/db/catalog/index_key_validate', diff --git a/src/mongo/db/commands/count_cmd.cpp b/src/mongo/db/commands/count_cmd.cpp index 4afc346ce0c..295ec9f4f38 100644 --- a/src/mongo/db/commands/count_cmd.cpp +++ b/src/mongo/db/commands/count_cmd.cpp @@ -39,6 +39,7 @@ #include "mongo/db/curop_failpoint_helpers.h" #include "mongo/db/db_raii.h" #include "mongo/db/exec/count.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/query/count_command_as_aggregation_command.h" #include "mongo/db/query/explain.h" #include "mongo/db/query/get_executor.h" @@ -243,7 +244,7 @@ public: PlanSummaryStats summaryStats; Explain::getSummaryStats(*exec, &summaryStats); if (collection) { - collection->infoCache()->notifyOfQuery(opCtx, summaryStats); + CollectionQueryInfo::get(collection).notifyOfQuery(opCtx, summaryStats); } curOp->debug().setPlanSummaryMetrics(summaryStats); diff --git a/src/mongo/db/commands/distinct.cpp b/src/mongo/db/commands/distinct.cpp index ac156b32c30..cb84a6e71d9 100644 --- a/src/mongo/db/commands/distinct.cpp +++ b/src/mongo/db/commands/distinct.cpp @@ -46,6 +46,7 @@ #include "mongo/db/jsobj.h" #include "mongo/db/matcher/extensions_callback_real.h" #include "mongo/db/namespace_string.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/query/cursor_response.h" #include "mongo/db/query/explain.h" #include "mongo/db/query/find_common.h" @@ -285,7 +286,7 @@ public: PlanSummaryStats stats; Explain::getSummaryStats(*executor.getValue(), &stats); if (collection) { - collection->infoCache()->notifyOfQuery(opCtx, stats); + CollectionQueryInfo::get(collection).notifyOfQuery(opCtx, stats); } curOp->debug().setPlanSummaryMetrics(stats); diff --git a/src/mongo/db/commands/find_and_modify.cpp b/src/mongo/db/commands/find_and_modify.cpp index 2e6af9a3f13..b12ccc69717 100644 --- a/src/mongo/db/commands/find_and_modify.cpp +++ b/src/mongo/db/commands/find_and_modify.cpp @@ -57,6 +57,7 @@ #include "mongo/db/ops/parsed_update.h" #include "mongo/db/ops/update_request.h" #include "mongo/db/ops/write_ops_retryability.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/query/explain.h" #include "mongo/db/query/find_and_modify_request.h" #include "mongo/db/query/get_executor.h" @@ -409,7 +410,7 @@ public: PlanSummaryStats summaryStats; Explain::getSummaryStats(*exec, &summaryStats); if (collection) { - collection->infoCache()->notifyOfQuery(opCtx, summaryStats); + CollectionQueryInfo::get(collection).notifyOfQuery(opCtx, summaryStats); } opDebug->setPlanSummaryMetrics(summaryStats); @@ -509,7 +510,7 @@ public: PlanSummaryStats summaryStats; Explain::getSummaryStats(*exec, &summaryStats); if (collection) { - collection->infoCache()->notifyOfQuery(opCtx, summaryStats); + CollectionQueryInfo::get(collection).notifyOfQuery(opCtx, summaryStats); } UpdateStage::recordUpdateStatsInOpDebug(UpdateStage::getUpdateStats(exec.get()), opDebug); diff --git a/src/mongo/db/commands/index_filter_commands.cpp b/src/mongo/db/commands/index_filter_commands.cpp index 48901a6ae58..1f7214ad1c0 100644 --- a/src/mongo/db/commands/index_filter_commands.cpp +++ b/src/mongo/db/commands/index_filter_commands.cpp @@ -49,6 +49,7 @@ #include "mongo/db/matcher/expression_parser.h" #include "mongo/db/matcher/extensions_callback_real.h" #include "mongo/db/namespace_string.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/stdx/unordered_set.h" #include "mongo/util/log.h" @@ -73,15 +74,12 @@ static Status getQuerySettingsAndPlanCache(OperationContext* opCtx, return Status(ErrorCodes::BadValue, "no such collection"); } - CollectionInfoCache* infoCache = collection->infoCache(); - invariant(infoCache); - - QuerySettings* querySettings = infoCache->getQuerySettings(); + QuerySettings* querySettings = CollectionQueryInfo::get(collection).getQuerySettings(); invariant(querySettings); *querySettingsOut = querySettings; - PlanCache* planCache = infoCache->getPlanCache(); + PlanCache* planCache = CollectionQueryInfo::get(collection).getPlanCache(); invariant(planCache); *planCacheOut = planCache; diff --git a/src/mongo/db/commands/mr.cpp b/src/mongo/db/commands/mr.cpp index b7da9aaf4bf..805ea654158 100644 --- a/src/mongo/db/commands/mr.cpp +++ b/src/mongo/db/commands/mr.cpp @@ -55,6 +55,7 @@ #include "mongo/db/matcher/extensions_callback_real.h" #include "mongo/db/op_observer.h" #include "mongo/db/ops/insert.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/query/get_executor.h" #include "mongo/db/query/plan_summary_stats.h" #include "mongo/db/query/query_planner.h" @@ -1564,7 +1565,7 @@ bool runMapReduce(OperationContext* opCtx, // TODO SERVER-23261: Confirm whether this is the correct place to gather all // metrics. There is no harm adding here for the time being. curOp->debug().setPlanSummaryMetrics(stats); - scopedAutoColl->getCollection()->infoCache()->notifyOfQuery(opCtx, stats); + CollectionQueryInfo::get(scopedAutoColl->getCollection()).notifyOfQuery(opCtx, stats); if (curOp->shouldDBProfile()) { BSONObjBuilder execStatsBob; diff --git a/src/mongo/db/commands/plan_cache_commands.cpp b/src/mongo/db/commands/plan_cache_commands.cpp index 6f821a7c50a..43163e7a88b 100644 --- a/src/mongo/db/commands/plan_cache_commands.cpp +++ b/src/mongo/db/commands/plan_cache_commands.cpp @@ -45,6 +45,7 @@ #include "mongo/db/jsobj.h" #include "mongo/db/matcher/extensions_callback_real.h" #include "mongo/db/namespace_string.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/query/explain.h" #include "mongo/db/query/plan_ranker.h" #include "mongo/util/hex.h" @@ -70,10 +71,7 @@ static Status getPlanCache(OperationContext* opCtx, return Status(ErrorCodes::BadValue, "no such collection"); } - CollectionInfoCache* infoCache = collection->infoCache(); - invariant(infoCache); - - PlanCache* planCache = infoCache->getPlanCache(); + PlanCache* planCache = CollectionQueryInfo::get(collection).getPlanCache(); invariant(planCache); *planCacheOut = planCache; diff --git a/src/mongo/db/commands/run_aggregate.cpp b/src/mongo/db/commands/run_aggregate.cpp index 3287294783c..5189946cd36 100644 --- a/src/mongo/db/commands/run_aggregate.cpp +++ b/src/mongo/db/commands/run_aggregate.cpp @@ -57,6 +57,7 @@ #include "mongo/db/pipeline/pipeline.h" #include "mongo/db/pipeline/pipeline_d.h" #include "mongo/db/query/collation/collator_factory_interface.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/query/cursor_response.h" #include "mongo/db/query/find_common.h" #include "mongo/db/query/get_executor.h" @@ -788,7 +789,7 @@ Status runAggregate(OperationContext* opCtx, // For an optimized away pipeline, signal the cache that a query operation has completed. // For normal pipelines this is done in DocumentSourceCursor. if (ctx && ctx->getCollection()) { - ctx->getCollection()->infoCache()->notifyOfQuery(opCtx, stats); + CollectionQueryInfo::get(ctx->getCollection()).notifyOfQuery(opCtx, stats); } } diff --git a/src/mongo/db/exec/cached_plan.cpp b/src/mongo/db/exec/cached_plan.cpp index 07df67a7c77..a3e6c4d3935 100644 --- a/src/mongo/db/exec/cached_plan.cpp +++ b/src/mongo/db/exec/cached_plan.cpp @@ -40,6 +40,7 @@ #include "mongo/db/exec/multi_plan.h" #include "mongo/db/exec/scoped_timer.h" #include "mongo/db/exec/working_set_common.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/query/explain.h" #include "mongo/db/query/plan_cache.h" #include "mongo/db/query/plan_ranker.h" @@ -192,7 +193,7 @@ Status CachedPlanStage::replan(PlanYieldPolicy* yieldPolicy, bool shouldCache) { if (shouldCache) { // Deactivate the current cache entry. - PlanCache* cache = collection()->infoCache()->getPlanCache(); + PlanCache* cache = CollectionQueryInfo::get(collection()).getPlanCache(); cache->deactivate(*_canonicalQuery); } @@ -302,7 +303,7 @@ const SpecificStats* CachedPlanStage::getSpecificStats() const { void CachedPlanStage::updatePlanCache() { const double score = PlanRanker::scoreTree(getStats()->children[0].get()); - PlanCache* cache = collection()->infoCache()->getPlanCache(); + PlanCache* cache = CollectionQueryInfo::get(collection()).getPlanCache(); Status fbs = cache->feedback(*_canonicalQuery, score); if (!fbs.isOK()) { LOG(5) << _canonicalQuery->ns() << ": Failed to update cache with feedback: " << redact(fbs) diff --git a/src/mongo/db/exec/multi_plan.cpp b/src/mongo/db/exec/multi_plan.cpp index 9cb692efa55..dc56d8d9b51 100644 --- a/src/mongo/db/exec/multi_plan.cpp +++ b/src/mongo/db/exec/multi_plan.cpp @@ -44,6 +44,7 @@ #include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/exec/scoped_timer.h" #include "mongo/db/exec/working_set_common.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/query/explain.h" #include "mongo/db/query/plan_cache.h" #include "mongo/db/query/plan_ranker.h" @@ -125,7 +126,10 @@ PlanStage::StageState MultiPlanStage::doWork(WorkingSetID* out) { // if the best solution fails. Alternatively we could try to // defer cache insertion to be after the first produced result. - collection()->infoCache()->getPlanCache()->remove(*_query).transitional_ignore(); + CollectionQueryInfo::get(collection()) + .getPlanCache() + ->remove(*_query) + .transitional_ignore(); _bestPlanIdx = _backupPlanIdx; _backupPlanIdx = kNoSuchPlan; @@ -328,9 +332,8 @@ Status MultiPlanStage::pickBestPlan(PlanYieldPolicy* yieldPolicy) { } if (validSolutions) { - collection() - ->infoCache() - ->getPlanCache() + CollectionQueryInfo::get(collection()) + .getPlanCache() ->set(*_query, solutions, std::move(ranking), diff --git a/src/mongo/db/exec/subplan.cpp b/src/mongo/db/exec/subplan.cpp index 889ea82428f..97fb663f7c6 100644 --- a/src/mongo/db/exec/subplan.cpp +++ b/src/mongo/db/exec/subplan.cpp @@ -39,6 +39,7 @@ #include "mongo/db/exec/multi_plan.h" #include "mongo/db/exec/scoped_timer.h" #include "mongo/db/matcher/extensions_callback_real.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/query/get_executor.h" #include "mongo/db/query/plan_executor.h" #include "mongo/db/query/planner_access.h" @@ -133,7 +134,7 @@ Status SubplanStage::planSubqueries() { // Plan the i-th child. We might be able to find a plan for the i-th child in the plan // cache. If there's no cached plan, then we generate and rank plans using the MPS. - const auto* planCache = collection()->infoCache()->getPlanCache(); + const auto* planCache = CollectionQueryInfo::get(collection()).getPlanCache(); // Populate branchResult->cachedSolution if an active cachedSolution entry exists. if (planCache->shouldCacheQuery(*branchResult->canonicalQuery)) { diff --git a/src/mongo/db/exec/update_stage.cpp b/src/mongo/db/exec/update_stage.cpp index ea314b78ab6..6236e45a6a0 100644 --- a/src/mongo/db/exec/update_stage.cpp +++ b/src/mongo/db/exec/update_stage.cpp @@ -45,6 +45,7 @@ #include "mongo/db/exec/working_set_common.h" #include "mongo/db/exec/write_stage_common.h" #include "mongo/db/op_observer.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/query/explain.h" #include "mongo/db/repl/replication_coordinator.h" #include "mongo/db/s/operation_sharding_state.h" @@ -857,7 +858,7 @@ void UpdateStage::doRestoreStateRequiresCollection() { // The set of indices may have changed during yield. Make sure that the update driver has up to // date index information. - const auto& updateIndexData = collection()->infoCache()->getIndexKeys(getOpCtx()); + const auto& updateIndexData = CollectionQueryInfo::get(collection()).getIndexKeys(getOpCtx()); _params.driver->refreshIndexKeys(&updateIndexData); } diff --git a/src/mongo/db/ops/write_ops_exec.cpp b/src/mongo/db/ops/write_ops_exec.cpp index dcb4f13b950..6dd5bca5b4c 100644 --- a/src/mongo/db/ops/write_ops_exec.cpp +++ b/src/mongo/db/ops/write_ops_exec.cpp @@ -59,6 +59,7 @@ #include "mongo/db/ops/write_ops_exec.h" #include "mongo/db/ops/write_ops_gen.h" #include "mongo/db/ops/write_ops_retryability.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/query/get_executor.h" #include "mongo/db/query/plan_summary_stats.h" #include "mongo/db/repl/repl_client_info.h" @@ -649,7 +650,7 @@ static SingleWriteResult performSingleUpdateOp(OperationContext* opCtx, PlanSummaryStats summary; Explain::getSummaryStats(*exec, &summary); if (collection->getCollection()) { - collection->getCollection()->infoCache()->notifyOfQuery(opCtx, summary); + CollectionQueryInfo::get(collection->getCollection()).notifyOfQuery(opCtx, summary); } if (curOp.shouldDBProfile()) { @@ -890,7 +891,7 @@ static SingleWriteResult performSingleDeleteOp(OperationContext* opCtx, PlanSummaryStats summary; Explain::getSummaryStats(*exec, &summary); if (collection.getCollection()) { - collection.getCollection()->infoCache()->notifyOfQuery(opCtx, summary); + CollectionQueryInfo::get(collection.getCollection()).notifyOfQuery(opCtx, summary); } curOp.debug().setPlanSummaryMetrics(summary); diff --git a/src/mongo/db/pipeline/document_source_cursor.cpp b/src/mongo/db/pipeline/document_source_cursor.cpp index 22d263741c2..934f37d2d1d 100644 --- a/src/mongo/db/pipeline/document_source_cursor.cpp +++ b/src/mongo/db/pipeline/document_source_cursor.cpp @@ -36,6 +36,7 @@ #include "mongo/db/catalog/collection.h" #include "mongo/db/exec/working_set_common.h" #include "mongo/db/pipeline/document.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/query/explain.h" #include "mongo/db/query/find_common.h" #include "mongo/db/storage/storage_options.h" @@ -324,7 +325,7 @@ DocumentSourceCursor::DocumentSourceCursor( } if (collection) { - collection->infoCache()->notifyOfQuery(pExpCtx->opCtx, _planSummaryStats); + CollectionQueryInfo::get(collection).notifyOfQuery(pExpCtx->opCtx, _planSummaryStats); } } diff --git a/src/mongo/db/pipeline/process_interface_standalone.cpp b/src/mongo/db/pipeline/process_interface_standalone.cpp index 0cb6ebc6ec9..ea3b28b50a9 100644 --- a/src/mongo/db/pipeline/process_interface_standalone.cpp +++ b/src/mongo/db/pipeline/process_interface_standalone.cpp @@ -47,6 +47,7 @@ #include "mongo/db/pipeline/document_source_cursor.h" #include "mongo/db/pipeline/lite_parsed_pipeline.h" #include "mongo/db/pipeline/pipeline_d.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/repl/speculative_majority_read_info.h" #include "mongo/db/s/collection_sharding_state.h" #include "mongo/db/s/sharding_state.h" @@ -259,7 +260,7 @@ CollectionIndexUsageMap MongoInterfaceStandalone::getIndexStats(OperationContext return CollectionIndexUsageMap(); } - return collection->infoCache()->getIndexUsageStats(); + return CollectionQueryInfo::get(collection).getIndexUsageStats(); } void MongoInterfaceStandalone::appendLatencyStats(OperationContext* opCtx, @@ -299,7 +300,7 @@ Status MongoInterfaceStandalone::appendQueryExecStats(OperationContext* opCtx, str::stream() << "Collection [" << nss.toString() << "] not found."}; } - auto collectionScanStats = collection->infoCache()->getCollectionScanStats(); + auto collectionScanStats = CollectionQueryInfo::get(collection).getCollectionScanStats(); dassert(collectionScanStats.collectionScans <= static_cast<unsigned long long>(std::numeric_limits<long long>::max())); @@ -531,9 +532,7 @@ std::vector<BSONObj> MongoInterfaceStandalone::getMatchingPlanCacheEntryStats( uassert( 50933, str::stream() << "collection '" << nss.toString() << "' does not exist", collection); - const auto infoCache = collection->infoCache(); - invariant(infoCache); - const auto planCache = infoCache->getPlanCache(); + const auto planCache = CollectionQueryInfo::get(collection).getPlanCache(); invariant(planCache); return planCache->getMatchingStats(serializer, predicate); diff --git a/src/mongo/db/catalog/collection_info_cache_impl.cpp b/src/mongo/db/query/collection_query_info.cpp index 9416ed37320..b0e5685d7ad 100644 --- a/src/mongo/db/catalog/collection_info_cache_impl.cpp +++ b/src/mongo/db/query/collection_query_info.cpp @@ -31,7 +31,7 @@ #include "mongo/platform/basic.h" -#include "mongo/db/catalog/collection_info_cache_impl.h" +#include "mongo/db/query/collection_query_info.h" #include <memory> @@ -52,26 +52,48 @@ namespace mongo { -CollectionInfoCacheImpl::CollectionInfoCacheImpl(Collection* collection, const NamespaceString& ns) - : _collection(collection), - _ns(ns), - _keysComputed(false), - _planCache(std::make_unique<PlanCache>(ns.ns())), +namespace { +CoreIndexInfo indexInfoFromIndexCatalogEntry(const IndexCatalogEntry& ice) { + auto desc = ice.descriptor(); + invariant(desc); + + auto accessMethod = ice.accessMethod(); + invariant(accessMethod); + + const ProjectionExecAgg* projExec = nullptr; + if (desc->getIndexType() == IndexType::INDEX_WILDCARD) + projExec = static_cast<const WildcardAccessMethod*>(accessMethod)->getProjectionExec(); + + return {desc->keyPattern(), + desc->getIndexType(), + desc->isSparse(), + IndexEntry::Identifier{desc->indexName()}, + ice.getFilterExpression(), + ice.getCollator(), + projExec}; +} +} // namespace + +CollectionQueryInfo::CollectionQueryInfo() + : _keysComputed(false), + _planCache(std::make_unique<PlanCache>()), _querySettings(std::make_unique<QuerySettings>()), _indexUsageTracker(getGlobalServiceContext()->getPreciseClockSource()) {} -const UpdateIndexData& CollectionInfoCacheImpl::getIndexKeys(OperationContext* opCtx) const { +const UpdateIndexData& CollectionQueryInfo::getIndexKeys(OperationContext* opCtx) const { + const Collection* coll = get.owner(this); // This requires "some" lock, and MODE_IS is an expression for that, for now. - dassert(opCtx->lockState()->isCollectionLockedForMode(_collection->ns(), MODE_IS)); + dassert(opCtx->lockState()->isCollectionLockedForMode(coll->ns(), MODE_IS)); invariant(_keysComputed); return _indexedPaths; } -void CollectionInfoCacheImpl::computeIndexKeys(OperationContext* opCtx) { +void CollectionQueryInfo::computeIndexKeys(OperationContext* opCtx) { _indexedPaths.clear(); + const Collection* coll = get.owner(this); std::unique_ptr<IndexCatalog::IndexIterator> it = - _collection->getIndexCatalog()->getIndexIterator(opCtx, true); + coll->getIndexCatalog()->getIndexIterator(opCtx, true); while (it->more()) { const IndexCatalogEntry* entry = it->next(); const IndexDescriptor* descriptor = entry->descriptor(); @@ -136,45 +158,48 @@ void CollectionInfoCacheImpl::computeIndexKeys(OperationContext* opCtx) { _keysComputed = true; } -void CollectionInfoCacheImpl::notifyOfQuery(OperationContext* opCtx, - const PlanSummaryStats& summaryStats) { +void CollectionQueryInfo::notifyOfQuery(OperationContext* opCtx, + const PlanSummaryStats& summaryStats) { _indexUsageTracker.recordCollectionScans(summaryStats.collectionScans); _indexUsageTracker.recordCollectionScansNonTailable(summaryStats.collectionScansNonTailable); const auto& indexesUsed = summaryStats.indexesUsed; + const Collection* coll = get.owner(this); // Record indexes used to fulfill query. for (auto it = indexesUsed.begin(); it != indexesUsed.end(); ++it) { // This index should still exist, since the PlanExecutor would have been killed if the // index was dropped (and we would not get here). - dassert(nullptr != _collection->getIndexCatalog()->findIndexByName(opCtx, *it)); + dassert(nullptr != coll->getIndexCatalog()->findIndexByName(opCtx, *it)); _indexUsageTracker.recordIndexAccess(*it); } } -void CollectionInfoCacheImpl::clearQueryCache() { - LOG(1) << _collection->ns() << ": clearing plan cache - collection info cache reset"; +void CollectionQueryInfo::clearQueryCache() { + const Collection* coll = get.owner(this); + LOG(1) << coll->ns() << ": clearing plan cache - collection info cache reset"; if (nullptr != _planCache.get()) { _planCache->clear(); } } -PlanCache* CollectionInfoCacheImpl::getPlanCache() const { +PlanCache* CollectionQueryInfo::getPlanCache() const { return _planCache.get(); } -QuerySettings* CollectionInfoCacheImpl::getQuerySettings() const { +QuerySettings* CollectionQueryInfo::getQuerySettings() const { return _querySettings.get(); } -void CollectionInfoCacheImpl::updatePlanCacheIndexEntries(OperationContext* opCtx) { +void CollectionQueryInfo::updatePlanCacheIndexEntries(OperationContext* opCtx) { std::vector<CoreIndexInfo> indexCores; // TODO We shouldn't need to include unfinished indexes, but we must here because the index // catalog may be in an inconsistent state. SERVER-18346. const bool includeUnfinishedIndexes = true; + const Collection* coll = get.owner(this); std::unique_ptr<IndexCatalog::IndexIterator> ii = - _collection->getIndexCatalog()->getIndexIterator(opCtx, includeUnfinishedIndexes); + coll->getIndexCatalog()->getIndexIterator(opCtx, includeUnfinishedIndexes); while (ii->more()) { const IndexCatalogEntry* ice = ii->next(); indexCores.emplace_back(indexInfoFromIndexCatalogEntry(*ice)); @@ -183,13 +208,14 @@ void CollectionInfoCacheImpl::updatePlanCacheIndexEntries(OperationContext* opCt _planCache->notifyOfIndexUpdates(indexCores); } -void CollectionInfoCacheImpl::init(OperationContext* opCtx) { +void CollectionQueryInfo::init(OperationContext* opCtx) { + const Collection* coll = get.owner(this); // Requires exclusive collection lock. - invariant(opCtx->lockState()->isCollectionLockedForMode(_collection->ns(), MODE_X)); + invariant(opCtx->lockState()->isCollectionLockedForMode(coll->ns(), MODE_X)); const bool includeUnfinishedIndexes = false; std::unique_ptr<IndexCatalog::IndexIterator> ii = - _collection->getIndexCatalog()->getIndexIterator(opCtx, includeUnfinishedIndexes); + coll->getIndexCatalog()->getIndexIterator(opCtx, includeUnfinishedIndexes); while (ii->more()) { const IndexDescriptor* desc = ii->next()->descriptor(); _indexUsageTracker.registerIndex(desc->indexName(), desc->keyPattern()); @@ -198,9 +224,10 @@ void CollectionInfoCacheImpl::init(OperationContext* opCtx) { rebuildIndexData(opCtx); } -void CollectionInfoCacheImpl::addedIndex(OperationContext* opCtx, const IndexDescriptor* desc) { +void CollectionQueryInfo::addedIndex(OperationContext* opCtx, const IndexDescriptor* desc) { + const Collection* coll = get.owner(this); // Requires exclusive collection lock. - invariant(opCtx->lockState()->isCollectionLockedForMode(_collection->ns(), MODE_X)); + invariant(opCtx->lockState()->isCollectionLockedForMode(coll->ns(), MODE_X)); invariant(desc); rebuildIndexData(opCtx); @@ -208,15 +235,16 @@ void CollectionInfoCacheImpl::addedIndex(OperationContext* opCtx, const IndexDes _indexUsageTracker.registerIndex(desc->indexName(), desc->keyPattern()); } -void CollectionInfoCacheImpl::droppedIndex(OperationContext* opCtx, StringData indexName) { +void CollectionQueryInfo::droppedIndex(OperationContext* opCtx, StringData indexName) { + const Collection* coll = get.owner(this); // Requires exclusive collection lock. - invariant(opCtx->lockState()->isCollectionLockedForMode(_collection->ns(), MODE_X)); + invariant(opCtx->lockState()->isCollectionLockedForMode(coll->ns(), MODE_X)); rebuildIndexData(opCtx); _indexUsageTracker.unregisterIndex(indexName); } -void CollectionInfoCacheImpl::rebuildIndexData(OperationContext* opCtx) { +void CollectionQueryInfo::rebuildIndexData(OperationContext* opCtx) { clearQueryCache(); _keysComputed = false; @@ -224,18 +252,11 @@ void CollectionInfoCacheImpl::rebuildIndexData(OperationContext* opCtx) { updatePlanCacheIndexEntries(opCtx); } -CollectionIndexUsageMap CollectionInfoCacheImpl::getIndexUsageStats() const { +CollectionIndexUsageMap CollectionQueryInfo::getIndexUsageStats() const { return _indexUsageTracker.getUsageStats(); } -void CollectionInfoCacheImpl::setNs(NamespaceString ns) { - auto oldNs = _ns; - _ns = std::move(ns); - - _planCache->setNs(_ns); -} - -CollectionIndexUsageTracker::CollectionScanStats CollectionInfoCacheImpl::getCollectionScanStats() +CollectionIndexUsageTracker::CollectionScanStats CollectionQueryInfo::getCollectionScanStats() const { return _indexUsageTracker.getCollectionScanStats(); } diff --git a/src/mongo/db/catalog/collection_info_cache_impl.h b/src/mongo/db/query/collection_query_info.h index ea5cf2dce00..12b7ceecda7 100644 --- a/src/mongo/db/catalog/collection_info_cache_impl.h +++ b/src/mongo/db/query/collection_query_info.h @@ -1,5 +1,5 @@ /** - * Copyright (C) 2018-present MongoDB, Inc. + * Copyright (C) 2019-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, @@ -29,16 +29,17 @@ #pragma once -#include "mongo/db/catalog/collection_info_cache.h" +#include "mongo/db/query/collection_query_info.h" +#include "mongo/db/catalog/collection.h" #include "mongo/db/collection_index_usage_tracker.h" #include "mongo/db/query/plan_cache.h" +#include "mongo/db/query/plan_summary_stats.h" #include "mongo/db/query/query_settings.h" #include "mongo/db/update_index_data.h" namespace mongo { -class Collection; class IndexDescriptor; class OperationContext; @@ -46,9 +47,11 @@ class OperationContext; * this is for storing things that you want to cache about a single collection * life cycle is managed for you from inside Collection */ -class CollectionInfoCacheImpl : public CollectionInfoCache { +class CollectionQueryInfo { public: - explicit CollectionInfoCacheImpl(Collection* collection, const NamespaceString& ns); + CollectionQueryInfo(); + + inline static const auto get = Collection::declareDecoration<CollectionQueryInfo>(); /** * Get the PlanCache for this collection. @@ -74,10 +77,10 @@ public: */ CollectionIndexUsageMap getIndexUsageStats() const; - CollectionIndexUsageTracker::CollectionScanStats getCollectionScanStats() const override; + CollectionIndexUsageTracker::CollectionScanStats getCollectionScanStats() const; /** - * Builds internal cache state based on the current state of the Collection's IndexCatalog + * Builds internal cache state based on the current state of the Collection's IndexCatalog. */ void init(OperationContext* opCtx); @@ -104,8 +107,6 @@ public: void notifyOfQuery(OperationContext* opCtx, const PlanSummaryStats& summaryStats); - void setNs(NamespaceString ns) override; - private: void computeIndexKeys(OperationContext* opCtx); void updatePlanCacheIndexEntries(OperationContext* opCtx); @@ -116,10 +117,6 @@ private: */ void rebuildIndexData(OperationContext* opCtx); - Collection* _collection; // not owned - - NamespaceString _ns; - // --- index keys cache bool _keysComputed; UpdateIndexData _indexedPaths; diff --git a/src/mongo/db/query/explain.cpp b/src/mongo/db/query/explain.cpp index be8a1c95cdd..df15b11e94d 100644 --- a/src/mongo/db/query/explain.cpp +++ b/src/mongo/db/query/explain.cpp @@ -46,6 +46,7 @@ #include "mongo/db/exec/working_set_common.h" #include "mongo/db/keypattern.h" #include "mongo/db/query/canonical_query_encoder.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/query/get_executor.h" #include "mongo/db/query/plan_executor.h" #include "mongo/db/query/plan_summary_stats.h" @@ -657,10 +658,11 @@ void Explain::generatePlannerInfo(PlanExecutor* exec, boost::optional<uint32_t> queryHash; boost::optional<uint32_t> planCacheKeyHash; if (collection && exec->getCanonicalQuery()) { - const CollectionInfoCache* infoCache = collection->infoCache(); - const QuerySettings* querySettings = infoCache->getQuerySettings(); - PlanCacheKey planCacheKey = - infoCache->getPlanCache()->computeKey(*exec->getCanonicalQuery()); + const QuerySettings* querySettings = + CollectionQueryInfo::get(collection).getQuerySettings(); + PlanCacheKey planCacheKey = CollectionQueryInfo::get(collection) + .getPlanCache() + ->computeKey(*exec->getCanonicalQuery()); planCacheKeyHash = canonical_query_encoder::computeHash(planCacheKey.toString()); queryHash = canonical_query_encoder::computeHash(planCacheKey.getStableKeyStringData()); diff --git a/src/mongo/db/query/find.cpp b/src/mongo/db/query/find.cpp index 97b0640289c..30f38b598e2 100644 --- a/src/mongo/db/query/find.cpp +++ b/src/mongo/db/query/find.cpp @@ -49,6 +49,7 @@ #include "mongo/db/exec/working_set_common.h" #include "mongo/db/keypattern.h" #include "mongo/db/matcher/extensions_callback_real.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/query/explain.h" #include "mongo/db/query/find_common.h" #include "mongo/db/query/get_executor.h" @@ -150,7 +151,7 @@ void endQueryOp(OperationContext* opCtx, curOp->debug().setPlanSummaryMetrics(summaryStats); if (collection) { - collection->infoCache()->notifyOfQuery(opCtx, summaryStats); + CollectionQueryInfo::get(collection).notifyOfQuery(opCtx, summaryStats); } if (curOp->shouldDBProfile()) { diff --git a/src/mongo/db/query/find.h b/src/mongo/db/query/find.h index 3c41c27f101..0a1e1a15078 100644 --- a/src/mongo/db/query/find.h +++ b/src/mongo/db/query/find.h @@ -76,7 +76,7 @@ void beginQueryOp(OperationContext* opCtx, /** * 1) Fills out CurOp for "opCtx" with information regarding this query's execution. - * 2) Reports index usage to the CollectionInfoCache. + * 2) Reports index usage to the CollectionQueryInfo. * * Uses explain functionality to extract stats from 'exec'. */ diff --git a/src/mongo/db/query/get_executor.cpp b/src/mongo/db/query/get_executor.cpp index 7b20d39a033..178821fb880 100644 --- a/src/mongo/db/query/get_executor.cpp +++ b/src/mongo/db/query/get_executor.cpp @@ -61,6 +61,7 @@ #include "mongo/db/query/canonical_query.h" #include "mongo/db/query/canonical_query_encoder.h" #include "mongo/db/query/collation/collator_factory_interface.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/query/explain.h" #include "mongo/db/query/index_bounds_builder.h" #include "mongo/db/query/internal_plans.h" @@ -204,26 +205,6 @@ IndexEntry indexEntryFromIndexCatalogEntry(OperationContext* opCtx, projExec}; } -CoreIndexInfo indexInfoFromIndexCatalogEntry(const IndexCatalogEntry& ice) { - auto desc = ice.descriptor(); - invariant(desc); - - auto accessMethod = ice.accessMethod(); - invariant(accessMethod); - - const ProjectionExecAgg* projExec = nullptr; - if (desc->getIndexType() == IndexType::INDEX_WILDCARD) - projExec = static_cast<const WildcardAccessMethod*>(accessMethod)->getProjectionExec(); - - return {desc->keyPattern(), - desc->getIndexType(), - desc->isSparse(), - IndexEntry::Identifier{desc->indexName()}, - ice.getFilterExpression(), - ice.getCollator(), - projExec}; -} - /** * If query supports index filters, filter params.indices according to any index filters that have * been configured. In addition, sets that there were indeed index filters applied. @@ -232,7 +213,7 @@ void applyIndexFilters(Collection* collection, const CanonicalQuery& canonicalQuery, QueryPlannerParams* plannerParams) { if (!IDHackStage::supportsQuery(collection, canonicalQuery)) { - QuerySettings* querySettings = collection->infoCache()->getQuerySettings(); + QuerySettings* querySettings = CollectionQueryInfo::get(collection).getQuerySettings(); const auto key = canonicalQuery.encodeKey(); // Filter index catalog if index filters are specified for query. @@ -452,18 +433,19 @@ StatusWith<PrepareExecutionResult> prepareExecution(OperationContext* opCtx, } // Check that the query should be cached. - if (collection->infoCache()->getPlanCache()->shouldCacheQuery(*canonicalQuery)) { + if (CollectionQueryInfo::get(collection).getPlanCache()->shouldCacheQuery(*canonicalQuery)) { // Fill in opDebug information. const auto planCacheKey = - collection->infoCache()->getPlanCache()->computeKey(*canonicalQuery); + CollectionQueryInfo::get(collection).getPlanCache()->computeKey(*canonicalQuery); CurOp::get(opCtx)->debug().queryHash = canonical_query_encoder::computeHash(planCacheKey.getStableKeyStringData()); CurOp::get(opCtx)->debug().planCacheKey = canonical_query_encoder::computeHash(planCacheKey.toString()); // Try to look up a cached solution for the query. - if (auto cs = - collection->infoCache()->getPlanCache()->getCacheEntryIfActive(planCacheKey)) { + if (auto cs = CollectionQueryInfo::get(collection) + .getPlanCache() + ->getCacheEntryIfActive(planCacheKey)) { // We have a CachedSolution. Have the planner turn it into a QuerySolution. auto statusWithQs = QueryPlanner::planFromCache(*canonicalQuery, plannerParams, *cs); @@ -890,7 +872,7 @@ StatusWith<unique_ptr<PlanExecutor, PlanExecutor::Deleter>> getExecutorUpdate( // Pass index information to the update driver, so that it can determine for us whether the // update affects indices. - const auto& updateIndexData = collection->infoCache()->getIndexKeys(opCtx); + const auto& updateIndexData = CollectionQueryInfo::get(collection).getIndexKeys(opCtx); driver->refreshIndexKeys(&updateIndexData); if (!parsedUpdate->hasParsedQuery()) { diff --git a/src/mongo/db/query/get_executor.h b/src/mongo/db/query/get_executor.h index 6f4117e31cb..78fec8c6a45 100644 --- a/src/mongo/db/query/get_executor.h +++ b/src/mongo/db/query/get_executor.h @@ -91,13 +91,6 @@ IndexEntry indexEntryFromIndexCatalogEntry(OperationContext* opCtx, const CanonicalQuery* canonicalQuery = nullptr); /** - * Converts the catalog metadata for an index into a CoreIndexInfo, which is a format that is meant - * to be used to update the plan cache. This function has no side effects and is safe to call in - * all contexts. - */ -CoreIndexInfo indexInfoFromIndexCatalogEntry(const IndexCatalogEntry& ice); - -/** * Determines whether or not to wait for oplog visibility for a query. This is only used for * collection scans on the oplog. */ diff --git a/src/mongo/db/query/plan_cache.cpp b/src/mongo/db/query/plan_cache.cpp index 171d227bc32..3773b140b3e 100644 --- a/src/mongo/db/query/plan_cache.cpp +++ b/src/mongo/db/query/plan_cache.cpp @@ -362,8 +362,6 @@ PlanCache::PlanCache() : PlanCache(internalQueryCacheSize.load()) {} PlanCache::PlanCache(size_t size) : _cache(size) {} -PlanCache::PlanCache(const std::string& ns) : _cache(internalQueryCacheSize.load()), _ns(ns) {} - PlanCache::~PlanCache() {} std::unique_ptr<CachedSolution> PlanCache::getCacheEntryIfActive(const PlanCacheKey& key) const { @@ -545,7 +543,7 @@ Status PlanCache::set(const CanonicalQuery& query, std::unique_ptr<PlanCacheEntry> evictedEntry = _cache.add(key, newEntry.release()); if (nullptr != evictedEntry.get()) { - LOG(1) << _ns << ": plan cache maximum size exceeded - " + LOG(1) << query.nss() << ": plan cache maximum size exceeded - " << "removed least recently used entry " << redact(evictedEntry->toString()); } diff --git a/src/mongo/db/query/plan_cache.h b/src/mongo/db/query/plan_cache.h index 3c904ec3794..224ab51e6fc 100644 --- a/src/mongo/db/query/plan_cache.h +++ b/src/mongo/db/query/plan_cache.h @@ -401,8 +401,6 @@ public: PlanCache(size_t size); - PlanCache(const std::string& ns); - ~PlanCache(); /** @@ -529,10 +527,6 @@ public: const std::function<BSONObj(const PlanCacheEntry&)>& serializationFunc, const std::function<bool(const BSONObj&)>& filterFunc) const; - void setNs(NamespaceString ns) { - _ns = ns.toString(); - } - private: struct NewEntryState { bool shouldBeCreated = false; @@ -551,9 +545,6 @@ private: // Protects _cache. mutable stdx::mutex _cacheMutex; - // Full namespace of collection. - std::string _ns; - // Holds computed information about the collection's indexes. Used for generating plan // cache keys. // diff --git a/src/mongo/dbtests/plan_ranking.cpp b/src/mongo/dbtests/plan_ranking.cpp index 1433e8a2558..dddeb46e162 100644 --- a/src/mongo/dbtests/plan_ranking.cpp +++ b/src/mongo/dbtests/plan_ranking.cpp @@ -46,6 +46,7 @@ #include "mongo/db/index/index_descriptor.h" #include "mongo/db/json.h" #include "mongo/db/namespace_string.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/query/get_executor.h" #include "mongo/db/query/query_knobs_gen.h" #include "mongo/db/query/query_planner.h" @@ -243,7 +244,7 @@ public: Collection* collection = ctx.getCollection(); StatusWith<std::unique_ptr<PlanCacheEntry>> planCacheEntryWithStatus = - collection->infoCache()->getPlanCache()->getEntry(*(cq.get())); + CollectionQueryInfo::get(collection).getPlanCache()->getEntry(*(cq.get())); ASSERT_OK(planCacheEntryWithStatus.getStatus()); // We assert that there was only one plan scored, implying that there was only one diff --git a/src/mongo/dbtests/query_stage_cached_plan.cpp b/src/mongo/dbtests/query_stage_cached_plan.cpp index 29677d86e8c..22da16dd594 100644 --- a/src/mongo/dbtests/query_stage_cached_plan.cpp +++ b/src/mongo/dbtests/query_stage_cached_plan.cpp @@ -44,6 +44,7 @@ #include "mongo/db/json.h" #include "mongo/db/namespace_string.h" #include "mongo/db/query/canonical_query.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/query/get_executor.h" #include "mongo/db/query/plan_cache.h" #include "mongo/db/query/plan_yield_policy.h" @@ -189,7 +190,7 @@ TEST_F(QueryStageCachedPlan, QueryStageCachedPlanFailure) { const std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue()); // We shouldn't have anything in the plan cache for this shape yet. - PlanCache* cache = collection->infoCache()->getPlanCache(); + PlanCache* cache = CollectionQueryInfo::get(collection).getPlanCache(); ASSERT(cache); ASSERT_EQ(cache->get(*cq).state, PlanCache::CacheEntryState::kNotPresent); @@ -235,7 +236,7 @@ TEST_F(QueryStageCachedPlan, QueryStageCachedPlanHitMaxWorks) { const std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue()); // We shouldn't have anything in the plan cache for this shape yet. - PlanCache* cache = collection->infoCache()->getPlanCache(); + PlanCache* cache = CollectionQueryInfo::get(collection).getPlanCache(); ASSERT(cache); ASSERT_EQ(cache->get(*cq).state, PlanCache::CacheEntryState::kNotPresent); @@ -286,7 +287,7 @@ TEST_F(QueryStageCachedPlan, QueryStageCachedPlanAddsActiveCacheEntries) { canonicalQueryFromFilterObj(opCtx(), nss, fromjson("{a: {$gte: 11}, b: {$gte: 11}}")); // We shouldn't have anything in the plan cache for this shape yet. - PlanCache* cache = collection->infoCache()->getPlanCache(); + PlanCache* cache = CollectionQueryInfo::get(collection).getPlanCache(); ASSERT(cache); ASSERT_EQ(cache->get(*shapeCq).state, PlanCache::CacheEntryState::kNotPresent); @@ -345,7 +346,7 @@ TEST_F(QueryStageCachedPlan, DeactivatesEntriesOnReplan) { canonicalQueryFromFilterObj(opCtx(), nss, fromjson("{a: {$gte: 11}, b: {$gte: 11}}")); // We shouldn't have anything in the plan cache for this shape yet. - PlanCache* cache = collection->infoCache()->getPlanCache(); + PlanCache* cache = CollectionQueryInfo::get(collection).getPlanCache(); ASSERT(cache); ASSERT_EQ(cache->get(*shapeCq).state, PlanCache::CacheEntryState::kNotPresent); @@ -404,7 +405,7 @@ TEST_F(QueryStageCachedPlan, EntriesAreNotDeactivatedWhenInactiveEntriesDisabled canonicalQueryFromFilterObj(opCtx(), nss, fromjson("{a: {$gte: 11}, b: {$gte: 11}}")); // We shouldn't have anything in the plan cache for this shape yet. - PlanCache* cache = collection->infoCache()->getPlanCache(); + PlanCache* cache = CollectionQueryInfo::get(collection).getPlanCache(); ASSERT(cache); ASSERT_EQ(cache->get(*shapeCq).state, PlanCache::CacheEntryState::kNotPresent); @@ -444,7 +445,7 @@ TEST_F(QueryStageCachedPlan, ThrowsOnYieldRecoveryWhenIndexIsDroppedBeforePlanSe const std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue()); // We shouldn't have anything in the plan cache for this shape yet. - PlanCache* cache = collection->infoCache()->getPlanCache(); + PlanCache* cache = CollectionQueryInfo::get(collection).getPlanCache(); ASSERT(cache); // Get planner params. @@ -486,7 +487,7 @@ TEST_F(QueryStageCachedPlan, DoesNotThrowOnYieldRecoveryWhenIndexIsDroppedAferPl const std::unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue()); // We shouldn't have anything in the plan cache for this shape yet. - PlanCache* cache = collection->infoCache()->getPlanCache(); + PlanCache* cache = CollectionQueryInfo::get(collection).getPlanCache(); ASSERT(cache); // Get planner params. diff --git a/src/mongo/dbtests/query_stage_multiplan.cpp b/src/mongo/dbtests/query_stage_multiplan.cpp index 97c50d74952..7c15a206988 100644 --- a/src/mongo/dbtests/query_stage_multiplan.cpp +++ b/src/mongo/dbtests/query_stage_multiplan.cpp @@ -46,6 +46,7 @@ #include "mongo/db/json.h" #include "mongo/db/matcher/expression_parser.h" #include "mongo/db/namespace_string.h" +#include "mongo/db/query/collection_query_info.h" #include "mongo/db/query/get_executor.h" #include "mongo/db/query/mock_yield_policies.h" #include "mongo/db/query/plan_executor.h" @@ -294,7 +295,7 @@ TEST_F(QueryStageMultiPlanTest, MPSDoesNotCreateActiveCacheEntryImmediately) { auto mps = runMultiPlanner(_opCtx.get(), nss, coll, 7); // Be sure that an inactive cache entry was added. - PlanCache* cache = coll->infoCache()->getPlanCache(); + PlanCache* cache = CollectionQueryInfo::get(coll).getPlanCache(); ASSERT_EQ(cache->size(), 1U); auto entry = assertGet(cache->getEntry(*cq)); ASSERT_FALSE(entry->isActive); @@ -349,7 +350,7 @@ TEST_F(QueryStageMultiPlanTest, MPSDoesCreatesActiveEntryWhenInactiveEntriesDisa auto mps = runMultiPlanner(_opCtx.get(), nss, coll, 7); // Be sure that an _active_ cache entry was added. - PlanCache* cache = coll->infoCache()->getPlanCache(); + PlanCache* cache = CollectionQueryInfo::get(coll).getPlanCache(); ASSERT_EQ(cache->get(*cq).state, PlanCache::CacheEntryState::kPresentActive); // Run the multi-planner again. The entry should still be active. |