diff options
Diffstat (limited to 'src/mongo/db/catalog/multi_index_block.cpp')
| -rw-r--r-- | src/mongo/db/catalog/multi_index_block.cpp | 73 |
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); } } |
