diff options
Diffstat (limited to 'src/mongo/db/repl/oplog.cpp')
-rw-r--r-- | src/mongo/db/repl/oplog.cpp | 63 |
1 files changed, 37 insertions, 26 deletions
diff --git a/src/mongo/db/repl/oplog.cpp b/src/mongo/db/repl/oplog.cpp index 232b7a5b4ae..31b8fd82d85 100644 --- a/src/mongo/db/repl/oplog.cpp +++ b/src/mongo/db/repl/oplog.cpp @@ -165,24 +165,6 @@ void applyImportCollectionDefault(OperationContext* opCtx, "isDryRun"_attr = isDryRun); } -/** - * Remove this function when proper lifetime of the config.image_collection is in place. - */ -void createConfigImagesIfNecessary_temporary(OperationContext* opCtx) { - AutoGetCollection configImages( - opCtx, NamespaceString::kConfigImagesNamespace, LockMode::MODE_IX); - if (configImages.getCollection()) { - return; - } - - repl::UnreplicatedWritesBlock unreplicated(opCtx); - CollectionOptions options; - options.uuid = UUID::gen(); - invariant(DatabaseHolder::get(opCtx) - ->getDb(opCtx, NamespaceString::kConfigImagesNamespace.db()) - ->createCollection(opCtx, NamespaceString::kConfigImagesNamespace, options)); -} - } // namespace ApplyImportCollectionFn applyImportCollection = applyImportCollectionDefault; @@ -256,19 +238,28 @@ void createIndexForApplyOps(OperationContext* opCtx, opCtx->recoveryUnit()->abandonSnapshot(); } +/** + * @param dataImage can be BSONObj::isEmpty to signal the node is in initial sync and must + * invalidate relevant image collection data. + */ void writeToImageCollection(OperationContext* opCtx, const LogicalSessionId& sessionId, + const TxnNumber txnNum, const Timestamp timestamp, repl::RetryImageEnum imageKind, const BSONObj& dataImage, bool* upsertConfigImage) { - createConfigImagesIfNecessary_temporary(opCtx); AutoGetCollection autoColl(opCtx, NamespaceString::kConfigImagesNamespace, LockMode::MODE_IX); repl::ImageEntry imageEntry; imageEntry.set_id(sessionId); + imageEntry.setTxnNumber(txnNum); imageEntry.setTs(timestamp); imageEntry.setImageKind(imageKind); imageEntry.setImage(dataImage); + if (dataImage.isEmpty()) { + imageEntry.setInvalidated(true); + imageEntry.setInvalidatedReason("initial sync"_sd); + } UpdateRequest request; request.setNamespaceString(NamespaceString::kConfigImagesNamespace); @@ -1437,10 +1428,12 @@ Status applyOperation_inlock(OperationContext* opCtx, request.setUpdateModification(std::move(updateMod)); request.setUpsert(upsert); request.setFromOplogApplication(true); - if (op.getNeedsRetryImage() == repl::RetryImageEnum::kPreImage) { - request.setReturnDocs(UpdateRequest::ReturnDocOption::RETURN_OLD); - } else if (op.getNeedsRetryImage() == repl::RetryImageEnum::kPostImage) { - request.setReturnDocs(UpdateRequest::ReturnDocOption::RETURN_NEW); + if (mode != OplogApplication::Mode::kInitialSync) { + if (op.getNeedsRetryImage() == repl::RetryImageEnum::kPreImage) { + request.setReturnDocs(UpdateRequest::ReturnDocOption::RETURN_OLD); + } else if (op.getNeedsRetryImage() == repl::RetryImageEnum::kPostImage) { + request.setReturnDocs(UpdateRequest::ReturnDocOption::RETURN_NEW); + } } Timestamp timestamp; @@ -1556,8 +1549,12 @@ Status applyOperation_inlock(OperationContext* opCtx, if (op.getNeedsRetryImage()) { writeToImageCollection(opCtx, op.getSessionId().get(), + op.getTxnNumber().get(), op.getTimestamp(), op.getNeedsRetryImage().get(), + // If we did not request an image because we're in + // initial sync, the value passed in here is conveniently + // the empty BSONObj. ur.requestedDocImage, &upsertConfigImage); } @@ -1609,17 +1606,31 @@ Status applyOperation_inlock(OperationContext* opCtx, DeleteRequest request; request.setNsString(requestNss); request.setQuery(deleteCriteria); - if (op.getNeedsRetryImage() == repl::RetryImageEnum::kPreImage) { + if (mode != OplogApplication::Mode::kInitialSync && + op.getNeedsRetryImage() == repl::RetryImageEnum::kPreImage) { + // When in initial sync, we'll pass an empty image into + // `writeToImageCollection`. request.setReturnDeleted(true); } DeleteResult result = deleteObject(opCtx, collection, request); - if (result.nDeleted == 1 && op.getNeedsRetryImage()) { + if (op.getNeedsRetryImage()) { + // Even if `result.nDeleted` is 0, we want to perform a write to the + // imageCollection to advance the txnNumber/ts and invalidate the image. This + // isn't strictly necessary for correctness -- the `config.transactions` table + // is responsible for whether to retry. The motivation here is to simply reduce + // the number of states related documents in the two collections can be in. + BSONObj imageDoc; + if (result.nDeleted > 0 && mode != OplogApplication::Mode::kInitialSync) { + imageDoc = result.requestedPreImage.get(); + } + writeToImageCollection(opCtx, op.getSessionId().get(), + op.getTxnNumber().get(), op.getTimestamp(), repl::RetryImageEnum::kPreImage, - result.requestedPreImage.get(), + imageDoc, &upsertConfigImage); } |