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/vector_clock_mongod.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/vector_clock_mongod.cpp')
| -rw-r--r-- | src/mongo/db/vector_clock_mongod.cpp | 124 |
1 files changed, 28 insertions, 96 deletions
diff --git a/src/mongo/db/vector_clock_mongod.cpp b/src/mongo/db/vector_clock_mongod.cpp index c951daf3258..6ef97de2b27 100644 --- a/src/mongo/db/vector_clock_mongod.cpp +++ b/src/mongo/db/vector_clock_mongod.cpp @@ -31,7 +31,6 @@ #include "mongo/platform/basic.h" -#include "mongo/db/concurrency/lock_state.h" #include "mongo/db/logical_time_validator.h" #include "mongo/db/persistent_task_store.h" #include "mongo/db/repl/replica_set_aware_service.h" @@ -49,15 +48,14 @@ namespace mongo { namespace { class VectorClockMongoD : public VectorClockMutable, - public ReplicaSetAwareService<VectorClockMongoD>, - public std::enable_shared_from_this<VectorClockMongoD> { + public ReplicaSetAwareService<VectorClockMongoD> { VectorClockMongoD(const VectorClockMongoD&) = delete; VectorClockMongoD& operator=(const VectorClockMongoD&) = delete; public: static VectorClockMongoD* get(ServiceContext* serviceContext); - VectorClockMongoD(ServiceContext* ctx); + VectorClockMongoD(); virtual ~VectorClockMongoD(); private: @@ -97,7 +95,7 @@ private: void onStartup(OperationContext* opCtx) override {} void onInitialDataAvailable(OperationContext* opCtx, bool isMajorityDataAvailable) override; - void onShutdown() override; + void onShutdown() override {} void onStepUpBegin(OperationContext* opCtx, long long term) override; void onStepUpComplete(OperationContext* opCtx, long long term) override {} void onStepDown() override; @@ -141,7 +139,7 @@ private: */ SharedSemiFuture<void> _enqueueWaiterAndScheduleLoopIfNeeded(stdx::unique_lock<Mutex> ul, VectorTime time); - Future<void> _doWhileQueueNotEmptyOrError(); + Future<void> _doWhileQueueNotEmptyOrError(ServiceContext* service); // Protects the shared state below Mutex _mutex = MONGO_MAKE_LATCH("VectorClockMongoD::_mutex"); @@ -162,14 +160,9 @@ private: // Queue ordered in increasing order of the VectorTimes, which are waiting to be persisted using Queue = std::map<ComparableVectorTime, std::unique_ptr<SharedPromise<void>>>; Queue _queue; - - ServiceContext* _serviceContext; - - AtomicWord<bool> _shutdownInitiated{false}; }; -const auto vectorClockMongoDDecoration = - ServiceContext::declareDecoration<std::shared_ptr<VectorClockMongoD>>(); +const auto vectorClockMongoDDecoration = ServiceContext::declareDecoration<VectorClockMongoD>(); const ReplicaSetAwareServiceRegistry::Registerer<VectorClockMongoD> vectorClockMongoDServiceRegisterer("VectorClockMongoD-ReplicaSetAwareServiceRegistration"); @@ -178,20 +171,16 @@ const ServiceContext::ConstructorActionRegisterer vectorClockMongoDRegisterer( "VectorClockMongoD-VectorClockRegistration", {}, [](ServiceContext* service) { - VectorClockMongoD::registerVectorClockOnServiceContext(service, - VectorClockMongoD::get(service)); + VectorClockMongoD::registerVectorClockOnServiceContext( + service, &vectorClockMongoDDecoration(service)); }, {}); VectorClockMongoD* VectorClockMongoD::get(ServiceContext* serviceContext) { - auto& clock = vectorClockMongoDDecoration(serviceContext); - if (!clock) { - clock = std::make_shared<VectorClockMongoD>(serviceContext); - } - return clock.get(); + return &vectorClockMongoDDecoration(serviceContext); } -VectorClockMongoD::VectorClockMongoD(ServiceContext* ctx) : _serviceContext(ctx) {} +VectorClockMongoD::VectorClockMongoD() = default; VectorClockMongoD::~VectorClockMongoD() = default; @@ -243,16 +232,6 @@ void VectorClockMongoD::onInitialDataAvailable(OperationContext* opCtx, } } -void VectorClockMongoD::onShutdown() { - stdx::lock_guard lg(_mutex); - _shutdownInitiated.store(true); - for (auto& [_, promise] : _queue) { - promise->setError( - Status(ErrorCodes::ShutdownInProgress, "Not persisting vector clock due to shutdown")); - } - _queue.clear(); -} - void VectorClockMongoD::onBecomeArbiter() { // The node has become an arbiter, hence will not need logical clock for external operations. _disable(); @@ -318,60 +297,28 @@ VectorClock::VectorTime VectorClockMongoD::recoverDirect(OperationContext* opCtx SharedSemiFuture<void> VectorClockMongoD::_enqueueWaiterAndScheduleLoopIfNeeded( stdx::unique_lock<Mutex> ul, VectorTime time) { - if (_shutdownInitiated.load()) { - return Future<void>().makeReady( - Status(ErrorCodes::ShutdownInProgress, "Not persisting vector clock due to shutdown")); - } - auto [it, unusedEmplaced] = _queue.try_emplace({std::move(time)}, std::make_unique<SharedPromise<void>>()); - auto future = it->second->getFuture(); - if (!_loopScheduled) { _loopScheduled = true; auto joinPreviousLoop(_currentWhileLoop ? std::move(*_currentWhileLoop) : Future<void>::makeReady()); - _currentWhileLoop.emplace( - std::move(joinPreviousLoop).onCompletion([this, _ = shared_from_this()](auto) { - return _doWhileQueueNotEmptyOrError(); - })); + _currentWhileLoop.emplace(std::move(joinPreviousLoop).onCompletion([this](auto) { + return _doWhileQueueNotEmptyOrError(vectorClockMongoDDecoration.owner(this)); + })); } - return future; + return it->second->getFuture(); } -Future<void> VectorClockMongoD::_doWhileQueueNotEmptyOrError() { - if (_shutdownInitiated.load()) { - return Future<void>::makeReady( - Status(ErrorCodes::ShutdownInProgress, "Not persisting vector clock due to shutdown")); - } - - // This lambda is only called from the .then and .onError functions. - // The only possible way we can lock the mutex if the _shutdownInitiated is true when the - // setting of _shutdownInitiated runs parallel with the .then or .onError. - // That means the .then or .onError is already scheduled when the onShutdown happens. - // Since the threadpool stops later then the onShutdown, the already scheduled tasks will run - // on different thread, so it is safe to lock the mutex here. - const auto checkShutdownStatusAndLockMutex = - [this, _ = shared_from_this()]() -> boost::optional<stdx::unique_lock<Mutex>> { - if (_shutdownInitiated.load()) { - return boost::none; - } - return stdx::unique_lock(_mutex); - }; - +Future<void> VectorClockMongoD::_doWhileQueueNotEmptyOrError(ServiceContext* service) { auto [p, f] = makePromiseFuture<VectorTime>(); auto future = std::move(f) - .then([this, _ = shared_from_this(), checkShutdownStatusAndLockMutex]( - VectorTime newDurableTime) { - auto ul = checkShutdownStatusAndLockMutex(); - if (!ul) { - return; - } - + .then([this](VectorTime newDurableTime) { + stdx::unique_lock ul(_mutex); _durableTime.emplace(newDurableTime); ComparableVectorTime time{*_durableTime}; @@ -383,34 +330,24 @@ Future<void> VectorClockMongoD::_doWhileQueueNotEmptyOrError() { promises.emplace_back(std::move(it->second)); it = _queue.erase(it); } - ul->unlock(); + ul.unlock(); for (auto& p : promises) p->emplaceValue(); }) - .onError([this, _ = shared_from_this(), checkShutdownStatusAndLockMutex]( - Status status) { - auto ul = checkShutdownStatusAndLockMutex(); - if (!ul) { - return; - } - + .onError([this](Status status) { + stdx::unique_lock ul(_mutex); std::vector<Queue::value_type::second_type> promises; for (auto it = _queue.begin(); it != _queue.end();) { promises.emplace_back(std::move(it->second)); it = _queue.erase(it); } - ul->unlock(); + ul.unlock(); for (auto& p : promises) p->setError(status); }) - .onCompletion([this, _ = shared_from_this()](auto) { - if (_shutdownInitiated.load()) { - return Future<void>::makeReady( - Status(ErrorCodes::ShutdownInProgress, - "Not persisting vector clock due to shutdown")); - } + .onCompletion([this, service](auto) { { stdx::lock_guard lg(_mutex); if (_queue.empty()) { @@ -418,18 +355,18 @@ Future<void> VectorClockMongoD::_doWhileQueueNotEmptyOrError() { return Future<void>::makeReady(); } } - return _doWhileQueueNotEmptyOrError(); + return _doWhileQueueNotEmptyOrError(service); }); // Blocking work to recover and/or persist the current vector time - ExecutorFuture<void>(Grid::get(_serviceContext)->getExecutorPool()->getFixedExecutor()) - .then([this, _ = shared_from_this()] { + ExecutorFuture<void>(Grid::get(service)->getExecutorPool()->getFixedExecutor()) + .then([this, service] { auto mustRecoverDurableTime = [&] { stdx::lock_guard lg(_mutex); return !_durableTime; }(); - ThreadClient tc("VectorClockStateOperation", _serviceContext); + ThreadClient tc("VectorClockStateOperation", service); { stdx::lock_guard<Client> lk(*tc.get()); @@ -439,11 +376,6 @@ Future<void> VectorClockMongoD::_doWhileQueueNotEmptyOrError() { const auto opCtxHolder = tc->makeOperationContext(); auto* const opCtx = opCtxHolder.get(); - // This code is used by the TransactionCoordinator. As a result, we need to skip ticket - // acquisition in order to prevent possible deadlock when participants are in the - // prepared state. See SERVER-82883 and SERVER-60682. - SkipTicketAcquisitionForLock skipTicketAcquisition(opCtx); - if (mustRecoverDurableTime) { return recoverDirect(opCtx); } @@ -462,9 +394,9 @@ Future<void> VectorClockMongoD::_doWhileQueueNotEmptyOrError() { return vectorTime; }) - .getAsync( - [this, _ = shared_from_this(), promise = std::move(p)]( - StatusWith<VectorTime> swResult) mutable { promise.setFrom(std::move(swResult)); }); + .getAsync([this, promise = std::move(p)](StatusWith<VectorTime> swResult) mutable { + promise.setFrom(std::move(swResult)); + }); return future; } |
