summaryrefslogtreecommitdiff
path: root/src/mongo/db/repl/collection_bulk_loader_impl.cpp
diff options
context:
space:
mode:
authorLucas de Castro Borges <lucas@gnuabordo.com.br>2025-02-11 15:07:35 -0300
committerLucas de Castro Borges <lucas@gnuabordo.com.br>2025-02-11 15:07:35 -0300
commit4cb8841196d0625dfa3825aa326f071cd27c7b8b (patch)
tree1682a647d4463397c119183369ae6f750d5fdcff /src/mongo/db/repl/collection_bulk_loader_impl.cpp
parentaa03c6362cbaa767638e6eed9b031d86dd2643d1 (diff)
parent8f0827553e09872941945a093b647a4211a9db7f (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.cpp151
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;