diff options
author | Louis Williams <louis.williams@mongodb.com> | 2018-11-29 17:54:05 -0500 |
---|---|---|
committer | Louis Williams <louis.williams@mongodb.com> | 2018-12-06 12:04:01 -0500 |
commit | 621f411f07f110992eb6a09ba44a5cc0b4af8a3e (patch) | |
tree | d35f794a7e6e9f52e4fb2444f3a73bfb7644bf67 /src/mongo/db/index/index_build_interceptor.cpp | |
parent | e64df72bb1cbc4b9296577d9a5ac6864ac41a292 (diff) | |
download | mongo-621f411f07f110992eb6a09ba44a5cc0b4af8a3e.tar.gz |
SERVER-38036 Turn on hybrid builds for background, unique indexes
Diffstat (limited to 'src/mongo/db/index/index_build_interceptor.cpp')
-rw-r--r-- | src/mongo/db/index/index_build_interceptor.cpp | 74 |
1 files changed, 50 insertions, 24 deletions
diff --git a/src/mongo/db/index/index_build_interceptor.cpp b/src/mongo/db/index/index_build_interceptor.cpp index 6b74def0c44..b2975218c6e 100644 --- a/src/mongo/db/index/index_build_interceptor.cpp +++ b/src/mongo/db/index/index_build_interceptor.cpp @@ -47,13 +47,30 @@ namespace mongo { -IndexBuildInterceptor::IndexBuildInterceptor(OperationContext* opCtx) - : _sideWritesTable( - opCtx->getServiceContext()->getStorageEngine()->makeTemporaryRecordStore(opCtx)){}; +IndexBuildInterceptor::IndexBuildInterceptor(OperationContext* opCtx, IndexCatalogEntry* entry) + : _indexCatalogEntry(entry), + _sideWritesTable( + opCtx->getServiceContext()->getStorageEngine()->makeTemporaryRecordStore(opCtx)) { + + if (entry->descriptor()->unique()) { + _duplicateKeyTracker = std::make_unique<DuplicateKeyTracker>(opCtx, entry); + } +} + +Status IndexBuildInterceptor::recordDuplicateKeys(OperationContext* opCtx, + const std::vector<BSONObj>& keys) { + invariant(_indexCatalogEntry->descriptor()->unique()); + return _duplicateKeyTracker->recordKeys(opCtx, keys); +} + +Status IndexBuildInterceptor::checkDuplicateKeyConstraints(OperationContext* opCtx) const { + if (!_duplicateKeyTracker) { + return Status::OK(); + } + return _duplicateKeyTracker->checkConstraints(opCtx); +} Status IndexBuildInterceptor::drainWritesIntoIndex(OperationContext* opCtx, - IndexAccessMethod* indexAccessMethod, - const IndexDescriptor* indexDescriptor, const InsertDeleteOptions& options) { invariant(!opCtx->lockState()->inAWriteUnitOfWork()); @@ -136,8 +153,8 @@ Status IndexBuildInterceptor::drainWritesIntoIndex(OperationContext* opCtx, // writes table. WriteUnitOfWork wuow(opCtx); for (auto& operation : batch) { - auto status = _applyWrite( - opCtx, indexAccessMethod, operation.second, options, &totalInserted, &totalDeleted); + auto status = + _applyWrite(opCtx, operation.second, options, &totalInserted, &totalDeleted); if (!status.isOK()) { return status; } @@ -159,15 +176,15 @@ Status IndexBuildInterceptor::drainWritesIntoIndex(OperationContext* opCtx, progress->finished(); - log() << "index build for " << indexDescriptor->indexName() << ": drain applied " - << (_numApplied - appliedAtStart) << " side writes. i: " << totalInserted - << ", d: " << totalDeleted << ", total: " << _numApplied; + log() << "index build for " << _indexCatalogEntry->descriptor()->indexName() + << ": drain applied " << (_numApplied - appliedAtStart) + << " side writes. i: " << totalInserted << ", d: " << totalDeleted + << ", total: " << _numApplied; return Status::OK(); } Status IndexBuildInterceptor::_applyWrite(OperationContext* opCtx, - IndexAccessMethod* indexAccessMethod, const BSONObj& operation, const InsertDeleteOptions& options, int64_t* const keysInserted, @@ -178,28 +195,34 @@ Status IndexBuildInterceptor::_applyWrite(OperationContext* opCtx, (strcmp(operation.getStringField("op"), "i") == 0) ? Op::kInsert : Op::kDelete; const BSONObjSet keySet = SimpleBSONObjComparator::kInstance.makeBSONObjSet({key}); + auto accessMethod = _indexCatalogEntry->accessMethod(); if (opType == Op::kInsert) { InsertResult result; - Status s = - indexAccessMethod->insertKeys(opCtx, - keySet, - SimpleBSONObjComparator::kInstance.makeBSONObjSet(), - MultikeyPaths{}, - opRecordId, - options, - &result); - if (!s.isOK()) { - return s; + auto status = accessMethod->insertKeys(opCtx, + keySet, + SimpleBSONObjComparator::kInstance.makeBSONObjSet(), + MultikeyPaths{}, + opRecordId, + options, + &result); + if (!status.isOK()) { + return status; + } + + if (result.dupsInserted.size()) { + status = recordDuplicateKeys(opCtx, result.dupsInserted); + if (!status.isOK()) { + return status; + } } - invariant(!result.dupsInserted.size()); *keysInserted += result.numInserted; } else { invariant(opType == Op::kDelete); DEV invariant(strcmp(operation.getStringField("op"), "d") == 0); int64_t numDeleted; - Status s = indexAccessMethod->removeKeys(opCtx, keySet, opRecordId, options, &numDeleted); + Status s = accessMethod->removeKeys(opCtx, keySet, opRecordId, options, &numDeleted); if (!s.isOK()) { return s; } @@ -298,7 +321,9 @@ Status IndexBuildInterceptor::sideWrite(OperationContext* opCtx, std::vector<Record> records; for (auto& doc : toInsert) { - records.emplace_back(Record{RecordId(), RecordData(doc.objdata(), doc.objsize())}); + records.emplace_back(Record{RecordId(), // The storage engine will assign its own RecordId + // when we pass one that is null. + RecordData(doc.objdata(), doc.objsize())}); } // By passing a vector of null timestamps, these inserts are not timestamped individually, but @@ -306,4 +331,5 @@ Status IndexBuildInterceptor::sideWrite(OperationContext* opCtx, std::vector<Timestamp> timestamps(records.size()); return _sideWritesTable->rs()->insertRecords(opCtx, &records, timestamps); } + } // namespace mongo |