diff options
author | Kevin Pulo <kevin.pulo@mongodb.com> | 2019-09-26 19:53:04 +0000 |
---|---|---|
committer | evergreen <evergreen@mongodb.com> | 2019-09-26 19:53:04 +0000 |
commit | ae006f4586f21e294bdb14709d2610af681c592a (patch) | |
tree | bdeb6a9f7991cf9f779a9c4e7580a11ef98e4793 /src/mongo/db/read_write_concern_defaults.cpp | |
parent | 68d5310c76cb589ad4ab1ea1775fa861277b0615 (diff) | |
download | mongo-ae006f4586f21e294bdb14709d2610af681c592a.tar.gz |
SERVER-43120 SERVER-43121 SERVER-43122 ReadWriteConcernDefaults component, setDefaultRWConcern and getDefaultRWConcern commands, check RWC default suitability
Diffstat (limited to 'src/mongo/db/read_write_concern_defaults.cpp')
-rw-r--r-- | src/mongo/db/read_write_concern_defaults.cpp | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/src/mongo/db/read_write_concern_defaults.cpp b/src/mongo/db/read_write_concern_defaults.cpp new file mode 100644 index 00000000000..828160e2e41 --- /dev/null +++ b/src/mongo/db/read_write_concern_defaults.cpp @@ -0,0 +1,158 @@ +/** + * Copyright (C) 2019-present MongoDB, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the Server Side Public License, version 1, + * as published by MongoDB, Inc. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * Server Side Public License for more details. + * + * You should have received a copy of the Server Side Public License + * along with this program. If not, see + * <http://www.mongodb.com/licensing/server-side-public-license>. + * + * As a special exception, the copyright holders give permission to link the + * code of portions of this program with the OpenSSL library under certain + * conditions as described in each individual source file and distribute + * linked combinations including the program with the OpenSSL library. You + * must comply with the Server Side Public License in all respects for + * all of the code used other than as permitted herein. If you modify file(s) + * with this exception, you may extend this exception to your version of the + * file(s), but you are not obligated to do so. If you do not wish to do so, + * delete this exception statement from your version. If you delete this + * exception statement from all source files in the program, then also delete + * it in the license file. + */ + +#include "mongo/platform/basic.h" + +#include "mongo/db/read_write_concern_defaults.h" + +#include "mongo/db/logical_clock.h" + +namespace mongo { + +void ReadWriteConcernDefaults::checkSuitabilityAsDefault(const ReadConcern& rc) { + uassert(ErrorCodes::BadValue, + str::stream() << "level: '" << ReadConcern::kSnapshotReadConcernStr + << "' is not suitable for the default read concern", + rc.getLevel() != repl::ReadConcernLevel::kSnapshotReadConcern); + uassert(ErrorCodes::BadValue, + str::stream() << "level: '" << ReadConcern::kLinearizableReadConcernStr + << "' is not suitable for the default read concern", + rc.getLevel() != repl::ReadConcernLevel::kLinearizableReadConcern); + uassert(ErrorCodes::BadValue, + str::stream() << "'" << ReadConcern::kAfterOpTimeFieldName + << "' is not suitable for the default read concern", + !rc.getArgsOpTime()); + uassert(ErrorCodes::BadValue, + str::stream() << "'" << ReadConcern::kAfterClusterTimeFieldName + << "' is not suitable for the default read concern", + !rc.getArgsAfterClusterTime()); + uassert(ErrorCodes::BadValue, + str::stream() << "'" << ReadConcern::kAtClusterTimeFieldName + << "' is not suitable for the default read concern", + !rc.getArgsAtClusterTime()); +} + +void ReadWriteConcernDefaults::checkSuitabilityAsDefault(const WriteConcern& wc) { + uassert(ErrorCodes::BadValue, + "Unacknowledged write concern is not suitable for the default write concern", + !(wc.wMode.empty() && wc.wNumNodes < 1)); +} + +void ReadWriteConcernDefaults::_setDefault(WithLock, RWConcernDefault&& rwc) { + _defaults.erase(kReadWriteConcernEntry); + _defaults.emplace(kReadWriteConcernEntry, rwc); +} + +RWConcernDefault ReadWriteConcernDefaults::setConcerns(OperationContext* opCtx, + const boost::optional<ReadConcern>& rc, + const boost::optional<WriteConcern>& wc) { + invariant(rc || wc); + + if (rc) { + checkSuitabilityAsDefault(*rc); + } + if (wc) { + checkSuitabilityAsDefault(*wc); + } + + auto now = opCtx->getServiceContext()->getFastClockSource()->now(); + auto epoch = LogicalClock::get(opCtx->getServiceContext())->getClusterTime().asTimestamp(); + + RWConcernDefault rwc; + rwc.setDefaultReadConcern(rc); + rwc.setDefaultWriteConcern(wc); + rwc.setEpoch(epoch); + rwc.setSetTime(now); + rwc.setLocalSetTime(now); + + stdx::lock_guard<Latch> lk(_mutex); + + auto current = _getDefault(lk); + if (!rc && current) { + rwc.setDefaultReadConcern(current->getDefaultReadConcern()); + } + if (!wc && current) { + rwc.setDefaultWriteConcern(current->getDefaultWriteConcern()); + } + _setDefault(lk, std::move(rwc)); + return *_getDefault(lk); +} + +void ReadWriteConcernDefaults::invalidate() { + stdx::lock_guard<Latch> lk(_mutex); + _defaults.erase(kReadWriteConcernEntry); +} + +boost::optional<RWConcernDefault> ReadWriteConcernDefaults::_getDefault(WithLock) const { + if (_defaults.find(kReadWriteConcernEntry) == _defaults.end()) { + return boost::none; + } + return _defaults.at(kReadWriteConcernEntry); +} + +RWConcernDefault ReadWriteConcernDefaults::getDefault() const { + auto current = ([&]() { + stdx::lock_guard<Latch> lk(_mutex); + return _getDefault(lk); + })(); + if (!current) { + return RWConcernDefault{}; + } + return *current; +} + +boost::optional<ReadWriteConcernDefaults::ReadConcern> +ReadWriteConcernDefaults::getDefaultReadConcern() const { + auto current = getDefault(); + return current.getDefaultReadConcern(); +} + +boost::optional<ReadWriteConcernDefaults::WriteConcern> +ReadWriteConcernDefaults::getDefaultWriteConcern() const { + auto current = getDefault(); + return current.getDefaultWriteConcern(); +} + + +namespace { + +const auto getReadWriteConcernDefaults = + ServiceContext::declareDecoration<ReadWriteConcernDefaults>(); + +} // namespace + +ReadWriteConcernDefaults& ReadWriteConcernDefaults::get(ServiceContext* service) { + return getReadWriteConcernDefaults(service); +} + +ReadWriteConcernDefaults& ReadWriteConcernDefaults::get(ServiceContext& service) { + return getReadWriteConcernDefaults(service); +} + +} // namespace mongo |