summaryrefslogtreecommitdiff
path: root/src/mongo/db/catalog/multi_index_block.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/catalog/multi_index_block.cpp')
-rw-r--r--src/mongo/db/catalog/multi_index_block.cpp73
1 files changed, 31 insertions, 42 deletions
diff --git a/src/mongo/db/catalog/multi_index_block.cpp b/src/mongo/db/catalog/multi_index_block.cpp
index a0e8382959e..324f6e489ae 100644
--- a/src/mongo/db/catalog/multi_index_block.cpp
+++ b/src/mongo/db/catalog/multi_index_block.cpp
@@ -41,7 +41,7 @@
#include "mongo/db/catalog/collection_catalog.h"
#include "mongo/db/catalog/multi_index_block_gen.h"
#include "mongo/db/client.h"
-#include "mongo/db/concurrency/exception_util.h"
+#include "mongo/db/concurrency/write_conflict_exception.h"
#include "mongo/db/index/multikey_paths.h"
#include "mongo/db/multi_key_path_tracker.h"
#include "mongo/db/op_observer.h"
@@ -185,7 +185,7 @@ StatusWith<std::vector<BSONObj>> MultiIndexBlock::init(OperationContext* opCtx,
const BSONObj& spec,
OnInitFn onInit) {
const auto indexes = std::vector<BSONObj>(1, spec);
- return init(opCtx, collection, indexes, onInit, /*forRecovery=*/false, boost::none);
+ return init(opCtx, collection, indexes, onInit, boost::none);
}
StatusWith<std::vector<BSONObj>> MultiIndexBlock::init(
@@ -193,7 +193,6 @@ StatusWith<std::vector<BSONObj>> MultiIndexBlock::init(
CollectionWriter& collection,
const std::vector<BSONObj>& indexSpecs,
OnInitFn onInit,
- bool forRecovery,
const boost::optional<ResumeIndexInfo>& resumeInfo) {
invariant(opCtx->lockState()->isCollectionLockedForMode(collection->ns(), MODE_X),
str::stream() << "Collection " << collection->ns() << " with UUID "
@@ -247,31 +246,27 @@ StatusWith<std::vector<BSONObj>> MultiIndexBlock::init(
for (size_t i = 0; i < indexSpecs.size(); i++) {
BSONObj info = indexSpecs[i];
- if (!forRecovery) {
- // We skip this step when initializing unfinished index builds during startup
- // recovery as they are already in the index catalog.
- StatusWith<BSONObj> statusWithInfo =
- collection->getIndexCatalog()->prepareSpecForCreate(
- opCtx, collection.get(), info, resumeInfo);
- Status status = statusWithInfo.getStatus();
- if (!status.isOK()) {
- // If we were given two identical indexes to build, we will run into an error
- // trying to set up the same index a second time in this for-loop. This is the
- // only way to encounter this error because callers filter out ready/in-progress
- // indexes and start the build while holding a lock throughout.
- if (status == ErrorCodes::IndexBuildAlreadyInProgress) {
- invariant(indexSpecs.size() > 1,
- str::stream() << "Collection: " << collection->ns() << " ("
- << _collectionUUID
- << "), Index spec: " << indexSpecs.front());
- return {ErrorCodes::OperationFailed,
- "Cannot build two identical indexes. Try again without duplicate "
- "indexes."};
- }
- return status;
+ StatusWith<BSONObj> statusWithInfo =
+ collection->getIndexCatalog()->prepareSpecForCreate(
+ opCtx, collection.get(), info, resumeInfo);
+ Status status = statusWithInfo.getStatus();
+ if (!status.isOK()) {
+ // If we were given two identical indexes to build, we will run into an error trying
+ // to set up the same index a second time in this for-loop. This is the only way to
+ // encounter this error because callers filter out ready/in-progress indexes and
+ // start the build while holding a lock throughout.
+ if (status == ErrorCodes::IndexBuildAlreadyInProgress) {
+ invariant(indexSpecs.size() > 1,
+ str::stream()
+ << "Collection: " << collection->ns() << " (" << _collectionUUID
+ << "), Index spec: " << indexSpecs.front());
+ return {
+ ErrorCodes::OperationFailed,
+ "Cannot build two identical indexes. Try again without duplicate indexes."};
}
- info = statusWithInfo.getValue();
+ return status;
}
+ info = statusWithInfo.getValue();
indexInfoObjs.push_back(info);
boost::optional<TimeseriesOptions> options = collection->getTimeseriesOptions();
@@ -307,7 +302,7 @@ StatusWith<std::vector<BSONObj>> MultiIndexBlock::init(
status = index.block->initForResume(
opCtx, collection.getWritableCollection(), *stateInfo, resumeInfo->getPhase());
} else {
- status = index.block->init(opCtx, collection.getWritableCollection(), forRecovery);
+ status = index.block->init(opCtx, collection.getWritableCollection());
}
if (!status.isOK())
return status;
@@ -443,7 +438,7 @@ Status MultiIndexBlock::insertAllDocumentsInCollection(
// Unlock before hanging so replication recognizes we've completed.
collection.yield();
Locker::LockSnapshot lockInfo;
- opCtx->lockState()->saveLockStateAndUnlock(&lockInfo);
+ invariant(opCtx->lockState()->saveLockStateAndUnlock(&lockInfo));
LOGV2(4585201,
"Hanging index build with no locks due to "
@@ -563,7 +558,7 @@ Status MultiIndexBlock::insertAllDocumentsInCollection(
// Unlock before hanging so replication recognizes we've completed.
collection.yield();
Locker::LockSnapshot lockInfo;
- opCtx->lockState()->saveLockStateAndUnlock(&lockInfo);
+ invariant(opCtx->lockState()->saveLockStateAndUnlock(&lockInfo));
LOGV2(20390,
"Hanging index build with no locks due to "
@@ -690,10 +685,10 @@ Status MultiIndexBlock::_insert(OperationContext* opCtx,
// collection to have it.
if (_containsIndexBuildOnTimeseriesMeasurement &&
*collection->getTimeseriesBucketsMayHaveMixedSchemaData()) {
- auto docHasMixedSchemaData =
+ bool docHasMixedSchemaData =
collection->doesTimeseriesBucketsDocContainMixedSchemaData(doc);
- if (docHasMixedSchemaData.isOK() && docHasMixedSchemaData.getValue()) {
+ if (docHasMixedSchemaData) {
LOGV2(6057700,
"Detected mixed-schema data in time-series bucket collection",
logAttrs(collection->ns()),
@@ -709,8 +704,7 @@ Status MultiIndexBlock::_insert(OperationContext* opCtx,
auto replCoord = repl::ReplicationCoordinator::get(opCtx);
const bool replSetAndNotPrimary = !replCoord->canAcceptWritesFor(opCtx, collection->ns());
- if (docHasMixedSchemaData.isOK() && docHasMixedSchemaData.getValue() &&
- !replSetAndNotPrimary) {
+ if (docHasMixedSchemaData && !replSetAndNotPrimary) {
return timeseriesMixedSchemaDataFailure(collection.get());
}
}
@@ -727,6 +721,7 @@ Status MultiIndexBlock::_insert(OperationContext* opCtx,
try {
idxStatus = _indexes[i].bulk->insert(opCtx,
collection,
+ _indexes[i].block->getPooledBuilder(),
doc,
loc,
_indexes[i].options,
@@ -978,21 +973,15 @@ Status MultiIndexBlock::commit(OperationContext* opCtx,
onCommit();
- // We can't update the 'timeseriesBucketsMayHaveMixedSchemaData' catalog entry flag here as it
- // requires the change to be driven by the router role. It means that subsequent index builds
- // and other systems needs to treat this collection as-if it contains mixed-schema data even if
- // it might not. We log a warning that can be used to initiate changing the flag. Note: just
- // because this node doesn't contain mixed-schema it doesn't mean that other shards can't have
- // mixed schema data. This flag needs to be consistent across the shards.
+ // Update the 'timeseriesBucketsMayHaveMixedSchemaData' catalog entry flag to false in order to
+ // allow subsequent index builds to skip checking bucket documents for mixed-schema data.
if (_containsIndexBuildOnTimeseriesMeasurement && !_timeseriesBucketContainsMixedSchemaData) {
boost::optional<bool> mayContainMixedSchemaData =
collection->getTimeseriesBucketsMayHaveMixedSchemaData();
invariant(mayContainMixedSchemaData);
if (*mayContainMixedSchemaData) {
- LOGV2_WARNING(9301400,
- "Index build finished for time-series collection marked as containing "
- "mixed schema buckets without detecting any buckets with mixed schema.");
+ collection->setTimeseriesBucketsMayHaveMixedSchemaData(opCtx, false);
}
}