diff options
| author | Lucas de Castro Borges <lucas@gnuabordo.com.br> | 2025-02-11 15:07:35 -0300 |
|---|---|---|
| committer | Lucas de Castro Borges <lucas@gnuabordo.com.br> | 2025-02-11 15:07:35 -0300 |
| commit | 4cb8841196d0625dfa3825aa326f071cd27c7b8b (patch) | |
| tree | 1682a647d4463397c119183369ae6f750d5fdcff /src/mongo/db/repl/collection_bulk_loader_impl.cpp | |
| parent | aa03c6362cbaa767638e6eed9b031d86dd2643d1 (diff) | |
| parent | 8f0827553e09872941945a093b647a4211a9db7f (diff) | |
Update upstream source from tag 'upstream/6.0.0'master
Update to upstream version '6.0.0'
with Debian dir 5604a80ec1c96ca76f25f40d78e6ef855abec322
Diffstat (limited to 'src/mongo/db/repl/collection_bulk_loader_impl.cpp')
| -rw-r--r-- | src/mongo/db/repl/collection_bulk_loader_impl.cpp | 151 |
1 files changed, 60 insertions, 91 deletions
diff --git a/src/mongo/db/repl/collection_bulk_loader_impl.cpp b/src/mongo/db/repl/collection_bulk_loader_impl.cpp index eb39fdadd55..c0b3365621e 100644 --- a/src/mongo/db/repl/collection_bulk_loader_impl.cpp +++ b/src/mongo/db/repl/collection_bulk_loader_impl.cpp @@ -39,7 +39,7 @@ #include "mongo/db/catalog/index_catalog.h" #include "mongo/db/client.h" #include "mongo/db/concurrency/d_concurrency.h" -#include "mongo/db/concurrency/exception_util.h" +#include "mongo/db/concurrency/write_conflict_exception.h" #include "mongo/db/curop.h" #include "mongo/db/jsobj.h" #include "mongo/db/operation_context.h" @@ -82,54 +82,49 @@ Status CollectionBulkLoaderImpl::init(const std::vector<BSONObj>& secondaryIndex // locks as yielding a MODE_X/MODE_S lock isn't allowed. _secondaryIndexesBlock->setIndexBuildMethod(IndexBuildMethod::kForeground); _idIndexBlock->setIndexBuildMethod(IndexBuildMethod::kForeground); - return writeConflictRetry(_opCtx.get(), - "CollectionBulkLoader::init", - _collection->getNss().ns(), - [&secondaryIndexSpecs, this] { - WriteUnitOfWork wuow(_opCtx.get()); - // All writes in CollectionBulkLoaderImpl should be - // unreplicated. The opCtx is accessed indirectly through - // _secondaryIndexesBlock. - UnreplicatedWritesBlock uwb(_opCtx.get()); - // This enforces the buildIndexes setting in the replica set - // configuration. - CollectionWriter collWriter(_opCtx.get(), *_collection); - auto indexCatalog = - collWriter.getWritableCollection()->getIndexCatalog(); - auto specs = indexCatalog->removeExistingIndexesNoChecks( - _opCtx.get(), collWriter.get(), secondaryIndexSpecs); - if (specs.size()) { - _secondaryIndexesBlock->ignoreUniqueConstraint(); - auto status = _secondaryIndexesBlock - ->init(_opCtx.get(), - collWriter, - specs, - MultiIndexBlock::kNoopOnInitFn, - /*forRecovery=*/false) - .getStatus(); - if (!status.isOK()) { - return status; - } - } else { - _secondaryIndexesBlock.reset(); - } - if (!_idIndexSpec.isEmpty()) { - auto status = _idIndexBlock - ->init(_opCtx.get(), - collWriter, - _idIndexSpec, - MultiIndexBlock::kNoopOnInitFn) - .getStatus(); - if (!status.isOK()) { - return status; - } - } else { - _idIndexBlock.reset(); - } - - wuow.commit(); - return Status::OK(); - }); + return writeConflictRetry( + _opCtx.get(), + "CollectionBulkLoader::init", + _collection->getNss().ns(), + [&secondaryIndexSpecs, this] { + WriteUnitOfWork wuow(_opCtx.get()); + // All writes in CollectionBulkLoaderImpl should be unreplicated. + // The opCtx is accessed indirectly through _secondaryIndexesBlock. + UnreplicatedWritesBlock uwb(_opCtx.get()); + // This enforces the buildIndexes setting in the replica set configuration. + CollectionWriter collWriter(_opCtx.get(), *_collection); + auto indexCatalog = collWriter.getWritableCollection()->getIndexCatalog(); + auto specs = indexCatalog->removeExistingIndexesNoChecks( + _opCtx.get(), collWriter.get(), secondaryIndexSpecs); + if (specs.size()) { + _secondaryIndexesBlock->ignoreUniqueConstraint(); + auto status = + _secondaryIndexesBlock + ->init(_opCtx.get(), collWriter, specs, MultiIndexBlock::kNoopOnInitFn) + .getStatus(); + if (!status.isOK()) { + return status; + } + } else { + _secondaryIndexesBlock.reset(); + } + if (!_idIndexSpec.isEmpty()) { + auto status = _idIndexBlock + ->init(_opCtx.get(), + collWriter, + _idIndexSpec, + MultiIndexBlock::kNoopOnInitFn) + .getStatus(); + if (!status.isOK()) { + return status; + } + } else { + _idIndexBlock.reset(); + } + + wuow.commit(); + return Status::OK(); + }); }); } @@ -276,52 +271,26 @@ Status CollectionBulkLoaderImpl::commit() { if (_idIndexBlock) { // Do not do inside a WriteUnitOfWork (required by dumpInsertsFromBulk). auto status = _idIndexBlock->dumpInsertsFromBulk( - _opCtx.get(), **_collection, [&](const RecordId& rid) { - writeConflictRetry( + _opCtx.get(), _collection->getCollection(), [&](const RecordId& rid) { + return writeConflictRetry( _opCtx.get(), "CollectionBulkLoaderImpl::commit", _nss.ns(), [this, &rid] { WriteUnitOfWork wunit(_opCtx.get()); - - auto doc = (*_collection)->docFor(_opCtx.get(), rid); - - // Delete the document before committing the index. If we were to delete - // the document after committing the index, it's possible that the we - // may unindex a record with the same key but a different RecordId. - (*_collection)->getRecordStore()->deleteRecord(_opCtx.get(), rid); - - auto indexIt = - (*_collection) - ->getIndexCatalog() - ->getIndexIterator(_opCtx.get(), - IndexCatalog::InclusionPolicy::kReady); - while (auto entry = indexIt->next()) { - if (entry->descriptor()->isIdIndex()) { - continue; - } - - SharedBufferFragmentBuilder pooledBuilder{ - KeyString::HeapBuilder::kHeapAllocatorDefaultBytes}; - - InsertDeleteOptions options; - options.dupsAllowed = !entry->descriptor()->unique(); - - entry->accessMethod()->remove( - _opCtx.get(), - pooledBuilder, - **_collection, - doc.value(), - rid, - false /* logIfError */, - options, - nullptr /* numDeleted */, - // Initial sync can build an index over a collection with - // duplicates, so we need to check the RecordId of the docuemnt - // we are unindexing. See SERVER-17487 for more details. - CheckRecordId::On); - } - + // If we were to delete the document after committing the index build, + // it's possible that the storage engine unindexes a different record + // with the same key, but different RecordId. By deleting the document + // before committing the index build, the index removal code uses + // 'dupsAllowed', which forces the storage engine to only unindex + // records that match the same key and RecordId. + (*_collection) + ->deleteDocument(_opCtx.get(), + kUninitializedStmtId, + rid, + nullptr /** OpDebug **/, + false /* fromMigrate */, + true /* noWarn */); wunit.commit(); + return Status::OK(); }); - return Status::OK(); }); if (!status.isOK()) { return status; |
