summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenety Goh <benety@mongodb.com>2021-06-15 18:35:51 -0400
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-06-15 23:30:07 +0000
commitdb7e21b3f2ff986a4e78b583dfed41dd83596f8a (patch)
tree4d777774c384bbc3296f39dea70752c0682443fc
parent2b7d1168d19abc570e00c337ba05e66a98d7fb83 (diff)
downloadmongo-db7e21b3f2ff986a4e78b583dfed41dd83596f8a.tar.gz
SERVER-57385 Collection::isIndexMultikey() and Collection::setIndexIsMultikey() accept optional index offset
-rw-r--r--src/mongo/db/catalog/collection.h6
-rw-r--r--src/mongo/db/catalog/collection_impl.cpp148
-rw-r--r--src/mongo/db/catalog/collection_impl.h6
-rw-r--r--src/mongo/db/catalog/collection_mock.h6
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();
}