diff options
author | Benety Goh <benety@mongodb.com> | 2021-06-15 18:35:51 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-06-15 23:30:07 +0000 |
commit | db7e21b3f2ff986a4e78b583dfed41dd83596f8a (patch) | |
tree | 4d777774c384bbc3296f39dea70752c0682443fc | |
parent | 2b7d1168d19abc570e00c337ba05e66a98d7fb83 (diff) | |
download | mongo-db7e21b3f2ff986a4e78b583dfed41dd83596f8a.tar.gz |
SERVER-57385 Collection::isIndexMultikey() and Collection::setIndexIsMultikey() accept optional index offset
-rw-r--r-- | src/mongo/db/catalog/collection.h | 6 | ||||
-rw-r--r-- | src/mongo/db/catalog/collection_impl.cpp | 148 | ||||
-rw-r--r-- | src/mongo/db/catalog/collection_impl.h | 6 | ||||
-rw-r--r-- | src/mongo/db/catalog/collection_mock.h | 6 |
4 files changed, 100 insertions, 66 deletions
diff --git a/src/mongo/db/catalog/collection.h b/src/mongo/db/catalog/collection.h index cbf0bfae225..e2f487df323 100644 --- a/src/mongo/db/catalog/collection.h +++ b/src/mongo/db/catalog/collection.h @@ -599,7 +599,8 @@ public: */ virtual bool isIndexMultikey(OperationContext* opCtx, StringData indexName, - MultikeyPaths* multikeyPaths) const = 0; + MultikeyPaths* multikeyPaths, + int indexOffset = -1) const = 0; /** * Sets the index identified by 'indexName' to be multikey. @@ -612,7 +613,8 @@ public: */ virtual bool setIndexIsMultikey(OperationContext* opCtx, StringData indexName, - const MultikeyPaths& multikeyPaths) const = 0; + const MultikeyPaths& multikeyPaths, + int indexOffset = -1) const = 0; /** * Sets the index to be multikey with the provided paths. This performs minimal validation of diff --git a/src/mongo/db/catalog/collection_impl.cpp b/src/mongo/db/catalog/collection_impl.cpp index b24d87af894..80a7d913351 100644 --- a/src/mongo/db/catalog/collection_impl.cpp +++ b/src/mongo/db/catalog/collection_impl.cpp @@ -1763,22 +1763,37 @@ boost::optional<UUID> CollectionImpl::getIndexBuildUUID(StringData indexName) co bool CollectionImpl::isIndexMultikey(OperationContext* opCtx, StringData indexName, - MultikeyPaths* multikeyPaths) const { - auto isMultikey = - [this, multikeyPaths, indexName](const BSONCollectionCatalogEntry::MetaData& metadata) { - int offset = metadata.findIndexOffset(indexName); + MultikeyPaths* multikeyPaths, + int indexOffset) const { + auto isMultikey = [this, multikeyPaths, indexName, indexOffset]( + const BSONCollectionCatalogEntry::MetaData& metadata) { + int offset = indexOffset; + if (offset < 0) { + offset = metadata.findIndexOffset(indexName); invariant(offset >= 0, str::stream() << "cannot get multikey for index " << indexName << " @ " << getCatalogId() << " : " << metadata.toBSON()); + } else { + invariant(offset < int(metadata.indexes.size()), + str::stream() + << "out of bounds index offset for multikey info " << indexName << " @ " + << getCatalogId() << " : " << metadata.toBSON() << "; offset : " << offset + << " ; actual : " << metadata.findIndexOffset(indexName)); + invariant(indexName == metadata.indexes[offset].nameStringData(), + str::stream() + << "invalid index offset for multikey info " << indexName << " @ " + << getCatalogId() << " : " << metadata.toBSON() << "; offset : " << offset + << " ; actual : " << metadata.findIndexOffset(indexName)); + } - const auto& index = metadata.indexes[offset]; - stdx::lock_guard lock(index.multikeyMutex); - if (multikeyPaths && !index.multikeyPaths.empty()) { - *multikeyPaths = index.multikeyPaths; - } + const auto& index = metadata.indexes[offset]; + stdx::lock_guard lock(index.multikeyMutex); + if (multikeyPaths && !index.multikeyPaths.empty()) { + *multikeyPaths = index.multikeyPaths; + } - return index.multikey; - }; + return index.multikey; + }; const auto& uncommittedMultikeys = UncommittedMultikey::get(opCtx).resources(); if (uncommittedMultikeys) { @@ -1792,63 +1807,76 @@ bool CollectionImpl::isIndexMultikey(OperationContext* opCtx, bool CollectionImpl::setIndexIsMultikey(OperationContext* opCtx, StringData indexName, - const MultikeyPaths& multikeyPaths) const { + const MultikeyPaths& multikeyPaths, + int indexOffset) const { - auto setMultikey = [this, name = indexName.toString(), multikeyPaths]( + auto setMultikey = [this, indexName, multikeyPaths, indexOffset]( const BSONCollectionCatalogEntry::MetaData& metadata) { - int offset = metadata.findIndexOffset(name); - invariant(offset >= 0, - str::stream() << "cannot set index " << name << " as multikey @ " - << getCatalogId() << " : " << metadata.toBSON()); + int offset = indexOffset; + if (offset < 0) { + offset = metadata.findIndexOffset(indexName); + invariant(offset >= 0, + str::stream() << "cannot set multikey for index " << indexName << " @ " + << getCatalogId() << " : " << metadata.toBSON()); + } else { + invariant(offset < int(metadata.indexes.size()), + str::stream() + << "out of bounds index offset for multikey update" << indexName << " @ " + << getCatalogId() << " : " << metadata.toBSON() << "; offset : " << offset + << " ; actual : " << metadata.findIndexOffset(indexName)); + invariant(indexName == metadata.indexes[offset].nameStringData(), + str::stream() + << "invalid index offset for multikey update " << indexName << " @ " + << getCatalogId() << " : " << metadata.toBSON() << "; offset : " << offset + << " ; actual : " << metadata.findIndexOffset(indexName)); + } - { - const auto& index = metadata.indexes[offset]; - stdx::lock_guard lock(index.multikeyMutex); + auto* index = &metadata.indexes[offset]; + stdx::lock_guard lock(index->multikeyMutex); - const bool tracksPathLevelMultikeyInfo = - !metadata.indexes[offset].multikeyPaths.empty(); - if (tracksPathLevelMultikeyInfo) { - invariant(!multikeyPaths.empty()); - invariant(multikeyPaths.size() == metadata.indexes[offset].multikeyPaths.size()); - } else { - invariant(multikeyPaths.empty()); - - if (metadata.indexes[offset].multikey) { - // The index is already set as multikey and we aren't tracking path-level - // multikey information for it. We return false to indicate that the index - // metadata is unchanged. - return false; - } + auto tracksPathLevelMultikeyInfo = !metadata.indexes[offset].multikeyPaths.empty(); + if (!tracksPathLevelMultikeyInfo) { + invariant(multikeyPaths.empty()); + + if (index->multikey) { + // The index is already set as multikey and we aren't tracking path-level + // multikey information for it. We return false to indicate that the index + // metadata is unchanged. + return false; } + index->multikey = true; + return true; + } + + // We are tracking path-level multikey information for this index. + invariant(!multikeyPaths.empty()); + invariant(multikeyPaths.size() == metadata.indexes[offset].multikeyPaths.size()); + + index->multikey = true; - index.multikey = true; - - if (tracksPathLevelMultikeyInfo) { - bool newPathIsMultikey = false; - bool somePathIsMultikey = false; - - // Store new path components that cause this index to be multikey in catalog's - // index metadata. - for (size_t i = 0; i < multikeyPaths.size(); ++i) { - MultikeyComponents& indexMultikeyComponents = index.multikeyPaths[i]; - for (const auto multikeyComponent : multikeyPaths[i]) { - auto result = indexMultikeyComponents.insert(multikeyComponent); - newPathIsMultikey = newPathIsMultikey || result.second; - somePathIsMultikey = true; - } - } - - // If all of the sets in the multikey paths vector were empty, then no component - // of any indexed field caused the index to be multikey. setIndexIsMultikey() - // therefore shouldn't have been called. - invariant(somePathIsMultikey); - - if (!newPathIsMultikey) { - // We return false to indicate that the index metadata is unchanged. - return false; - } + bool newPathIsMultikey = false; + bool somePathIsMultikey = false; + + // Store new path components that cause this index to be multikey in catalog's + // index metadata. + for (size_t i = 0; i < multikeyPaths.size(); ++i) { + auto& indexMultikeyComponents = index->multikeyPaths[i]; + for (const auto multikeyComponent : multikeyPaths[i]) { + auto result = indexMultikeyComponents.insert(multikeyComponent); + newPathIsMultikey = newPathIsMultikey || result.second; + somePathIsMultikey = true; } } + + // If all of the sets in the multikey paths vector were empty, then no component + // of any indexed field caused the index to be multikey. setIndexIsMultikey() + // therefore shouldn't have been called. + invariant(somePathIsMultikey); + + if (!newPathIsMultikey) { + // We return false to indicate that the index metadata is unchanged. + return false; + } return true; }; diff --git a/src/mongo/db/catalog/collection_impl.h b/src/mongo/db/catalog/collection_impl.h index 446bc06b76c..a16d0938310 100644 --- a/src/mongo/db/catalog/collection_impl.h +++ b/src/mongo/db/catalog/collection_impl.h @@ -431,11 +431,13 @@ public: bool isIndexMultikey(OperationContext* opCtx, StringData indexName, - MultikeyPaths* multikeyPaths) const final; + MultikeyPaths* multikeyPaths, + int indexOffset) const final; bool setIndexIsMultikey(OperationContext* opCtx, StringData indexName, - const MultikeyPaths& multikeyPaths) const final; + const MultikeyPaths& multikeyPaths, + int indexOffset) const final; void forceSetIndexIsMultikey(OperationContext* opCtx, const IndexDescriptor* desc, diff --git a/src/mongo/db/catalog/collection_mock.h b/src/mongo/db/catalog/collection_mock.h index 8ca6290fd1f..8d7ed7e6f06 100644 --- a/src/mongo/db/catalog/collection_mock.h +++ b/src/mongo/db/catalog/collection_mock.h @@ -398,13 +398,15 @@ public: bool isIndexMultikey(OperationContext* opCtx, StringData indexName, - MultikeyPaths* multikeyPaths) const { + MultikeyPaths* multikeyPaths, + int indexOffset) const { std::abort(); } bool setIndexIsMultikey(OperationContext* opCtx, StringData indexName, - const MultikeyPaths& multikeyPaths) const { + const MultikeyPaths& multikeyPaths, + int indexOffset) const { std::abort(); } |