summaryrefslogtreecommitdiff
path: root/src/mongo/db
diff options
context:
space:
mode:
authorKevin Pulo <kevin.pulo@mongodb.com>2019-09-26 19:53:04 +0000
committerevergreen <evergreen@mongodb.com>2019-09-26 19:53:04 +0000
commitae006f4586f21e294bdb14709d2610af681c592a (patch)
treebdeb6a9f7991cf9f779a9c4e7580a11ef98e4793 /src/mongo/db
parent68d5310c76cb589ad4ab1ea1775fa861277b0615 (diff)
downloadmongo-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')
-rw-r--r--src/mongo/db/SConscript13
-rw-r--r--src/mongo/db/commands/SConscript2
-rw-r--r--src/mongo/db/commands/rwc_defaults_commands.cpp126
-rw-r--r--src/mongo/db/commands/rwc_defaults_commands.idl54
-rw-r--r--src/mongo/db/read_write_concern_defaults.cpp158
-rw-r--r--src/mongo/db/read_write_concern_defaults.h102
-rw-r--r--src/mongo/db/repl/read_concern_args.cpp33
-rw-r--r--src/mongo/db/repl/read_concern_args.h23
-rw-r--r--src/mongo/db/repl/read_concern_args.idl44
-rw-r--r--src/mongo/db/rw_concern_default.idl61
-rw-r--r--src/mongo/db/write_concern_options.cpp31
-rw-r--r--src/mongo/db/write_concern_options.idl44
12 files changed, 658 insertions, 33 deletions
diff --git a/src/mongo/db/SConscript b/src/mongo/db/SConscript
index 08aa289e870..3546d8ca650 100644
--- a/src/mongo/db/SConscript
+++ b/src/mongo/db/SConscript
@@ -59,6 +59,7 @@ env.Library(
'$BUILD_DIR/mongo/base',
'$BUILD_DIR/mongo/db/index_names',
'$BUILD_DIR/mongo/db/write_concern_options',
+ '$BUILD_DIR/mongo/db/read_write_concern_defaults',
]
)
@@ -370,6 +371,18 @@ env.Library(
)
env.Library(
+ target="read_write_concern_defaults",
+ source=[
+ "read_write_concern_defaults.cpp",
+ env.Idlc('rw_concern_default.idl')[0],
+ ],
+ LIBDEPS=[
+ 'write_concern_options',
+ 'repl/read_concern_args',
+ ],
+)
+
+env.Library(
target='service_context',
source=[
'baton.cpp',
diff --git a/src/mongo/db/commands/SConscript b/src/mongo/db/commands/SConscript
index c46add8de57..34ab19d0b46 100644
--- a/src/mongo/db/commands/SConscript
+++ b/src/mongo/db/commands/SConscript
@@ -142,9 +142,11 @@ env.Library(
'logical_session_server_status_section.cpp',
'mr_common.cpp',
'reap_logical_session_cache_now.cpp',
+ 'rwc_defaults_commands.cpp',
'traffic_recording_cmds.cpp',
'user_management_commands_common.cpp',
env.Idlc('drop_connections.idl')[0],
+ env.Idlc('rwc_defaults_commands.idl')[0],
],
LIBDEPS_PRIVATE=[
'$BUILD_DIR/mongo/client/clientdriver_minimal',
diff --git a/src/mongo/db/commands/rwc_defaults_commands.cpp b/src/mongo/db/commands/rwc_defaults_commands.cpp
new file mode 100644
index 00000000000..d3b0a9d072d
--- /dev/null
+++ b/src/mongo/db/commands/rwc_defaults_commands.cpp
@@ -0,0 +1,126 @@
+/**
+ * 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/commands.h"
+#include "mongo/db/commands/rwc_defaults_commands_gen.h"
+#include "mongo/db/read_write_concern_defaults.h"
+
+namespace mongo {
+namespace {
+
+class SetDefaultRWConcernCommand : public TypedCommand<SetDefaultRWConcernCommand> {
+public:
+ AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
+ return AllowedOnSecondary::kNever;
+ }
+ bool adminOnly() const override {
+ return true;
+ }
+ std::string help() const override {
+ return "set the current read/write concern defaults (cluster-wide)";
+ }
+
+public:
+ using Request = SetDefaultRWConcern;
+
+ class Invocation final : public InvocationBase {
+ public:
+ using InvocationBase::InvocationBase;
+
+ auto typedRun(OperationContext* opCtx) {
+ auto rc = request().getDefaultReadConcern();
+ auto wc = request().getDefaultWriteConcern();
+ uassert(ErrorCodes::BadValue,
+ str::stream() << "At least one of the \""
+ << SetDefaultRWConcern::kDefaultReadConcernFieldName << "\" or \""
+ << SetDefaultRWConcern::kDefaultWriteConcernFieldName
+ << "\" fields must be present",
+ rc || wc);
+
+ auto& rwcDefaults = ReadWriteConcernDefaults::get(opCtx->getServiceContext());
+ return rwcDefaults.setConcerns(opCtx, rc, wc);
+ }
+
+ private:
+ bool supportsWriteConcern() const override {
+ return true;
+ }
+
+ void doCheckAuthorization(OperationContext*) const override {
+ // TODO: add and use privilege action
+ }
+
+ NamespaceString ns() const override {
+ return NamespaceString(request().getDbName(), "");
+ }
+ };
+} setDefaultRWConcernCommand;
+
+class GetDefaultRWConcernCommand : public TypedCommand<GetDefaultRWConcernCommand> {
+public:
+ AllowedOnSecondary secondaryAllowed(ServiceContext*) const override {
+ return AllowedOnSecondary::kAlways;
+ }
+ bool adminOnly() const override {
+ return true;
+ }
+ std::string help() const override {
+ return "get the current read/write concern defaults being applied by this node";
+ }
+
+public:
+ using Request = GetDefaultRWConcern;
+
+ class Invocation final : public InvocationBase {
+ public:
+ using InvocationBase::InvocationBase;
+
+ auto typedRun(OperationContext* opCtx) {
+ auto& rwcDefaults = ReadWriteConcernDefaults::get(opCtx->getServiceContext());
+ return rwcDefaults.getDefault();
+ }
+
+ private:
+ bool supportsWriteConcern() const override {
+ return false;
+ }
+
+ void doCheckAuthorization(OperationContext*) const override {
+ // TODO: add and use privilege action
+ }
+
+ NamespaceString ns() const override {
+ return NamespaceString(request().getDbName(), "");
+ }
+ };
+} getDefaultRWConcernCommand;
+} // namespace
+} // namespace mongo
diff --git a/src/mongo/db/commands/rwc_defaults_commands.idl b/src/mongo/db/commands/rwc_defaults_commands.idl
new file mode 100644
index 00000000000..e4f2c2bb1b5
--- /dev/null
+++ b/src/mongo/db/commands/rwc_defaults_commands.idl
@@ -0,0 +1,54 @@
+# 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.
+#
+global:
+ cpp_namespace: "mongo"
+
+
+imports:
+ - "mongo/idl/basic_types.idl"
+ - "mongo/db/repl/read_concern_args.idl"
+ - "mongo/db/write_concern_options.idl"
+
+
+commands:
+ setDefaultRWConcern:
+ description: "set the current read/write concern defaults (cluster-wide)"
+ namespace: ignored
+ fields:
+ defaultReadConcern:
+ description: "The new default read concern"
+ type: ReadConcern
+ optional: true
+ defaultWriteConcern:
+ description: "The new default write concern"
+ type: WriteConcern
+ optional: true
+
+ getDefaultRWConcern:
+ description: "get the current read/write concern defaults being applied by this node"
+ namespace: ignored
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
diff --git a/src/mongo/db/read_write_concern_defaults.h b/src/mongo/db/read_write_concern_defaults.h
new file mode 100644
index 00000000000..f7ce2f9bfee
--- /dev/null
+++ b/src/mongo/db/read_write_concern_defaults.h
@@ -0,0 +1,102 @@
+/**
+ * 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.
+ */
+
+#pragma once
+
+#include <map>
+
+#include "mongo/db/operation_context.h"
+#include "mongo/db/repl/read_concern_args.h"
+#include "mongo/db/rw_concern_default_gen.h"
+#include "mongo/db/service_context.h"
+#include "mongo/db/write_concern_options.h"
+#include "mongo/platform/mutex.h"
+#include "mongo/util/concurrency/with_lock.h"
+
+namespace mongo {
+
+/**
+ * Class to manage Read Concern and Write Concern (RWC) defaults.
+ */
+class ReadWriteConcernDefaults {
+public:
+ /**
+ * Consistent names for the classes that define a ReadConcern and a WriteConcern.
+ */
+ using ReadConcern = repl::ReadConcernArgs;
+ using WriteConcern = WriteConcernOptions;
+
+ static constexpr StringData readConcernFieldName = ReadConcern::kReadConcernFieldName;
+ static constexpr StringData writeConcernFieldName = WriteConcern::kWriteConcernField;
+
+ static ReadWriteConcernDefaults& get(ServiceContext* service);
+ static ReadWriteConcernDefaults& get(ServiceContext& service);
+
+ ReadWriteConcernDefaults() = default;
+ ~ReadWriteConcernDefaults() = default;
+
+ static void checkSuitabilityAsDefault(const ReadConcern& rc);
+ static void checkSuitabilityAsDefault(const WriteConcern& wc);
+
+ /**
+ * Interface when an admin has run the command to change the defaults.
+ * At least one of the `rc` or `wc` params must be set.
+ * Will generate and use a new epoch and setTime for the updated defaults, which are returned.
+ */
+ RWConcernDefault setConcerns(OperationContext* opCtx,
+ const boost::optional<ReadConcern>& rc,
+ const boost::optional<WriteConcern>& wc);
+
+ /**
+ * Invalidates the cached RWC defaults, causing them to be refreshed.
+ *
+ * After this call returns, the read methods below (getDefault, getDefaultReadConcern,
+ * getDefaultWriteConcern) may continue returning the invalidated defaults, until they have been
+ * replaced by the refreshed values. This is to avoid stalling CRUD ops (and other ops that
+ * need RC/WC) during refresh.
+ */
+ void invalidate();
+
+ RWConcernDefault getDefault() const;
+ boost::optional<ReadConcern> getDefaultReadConcern() const;
+ boost::optional<WriteConcern> getDefaultWriteConcern() const;
+
+private:
+ enum Type { kReadWriteConcernEntry };
+
+ void _setDefault(WithLock, RWConcernDefault&& rwc);
+ boost::optional<RWConcernDefault> _getDefault(WithLock) const;
+
+ // Protects access to the private members below.
+ mutable Mutex _mutex = MONGO_MAKE_LATCH("ReadWriteConcernDefaults::_mutex");
+
+ std::map<Type, RWConcernDefault> _defaults;
+};
+
+} // namespace mongo
diff --git a/src/mongo/db/repl/read_concern_args.cpp b/src/mongo/db/repl/read_concern_args.cpp
index bb060b5a4dc..772ceeb76da 100644
--- a/src/mongo/db/repl/read_concern_args.cpp
+++ b/src/mongo/db/repl/read_concern_args.cpp
@@ -45,23 +45,6 @@ using std::string;
namespace mongo {
namespace repl {
-namespace {
-
-constexpr StringData kLocalReadConcernStr = "local"_sd;
-constexpr StringData kMajorityReadConcernStr = "majority"_sd;
-constexpr StringData kLinearizableReadConcernStr = "linearizable"_sd;
-constexpr StringData kAvailableReadConcernStr = "available"_sd;
-constexpr StringData kSnapshotReadConcernStr = "snapshot"_sd;
-
-} // unnamed namespace
-
-const string ReadConcernArgs::kReadConcernFieldName("readConcern");
-const string ReadConcernArgs::kAfterOpTimeFieldName("afterOpTime");
-const string ReadConcernArgs::kAfterClusterTimeFieldName("afterClusterTime");
-const string ReadConcernArgs::kAtClusterTimeFieldName("atClusterTime");
-
-const string ReadConcernArgs::kLevelFieldName("level");
-
const OperationContext::Decoration<ReadConcernArgs> handle =
OperationContext::declareDecoration<ReadConcernArgs>();
@@ -122,8 +105,6 @@ boost::optional<LogicalTime> ReadConcernArgs::getArgsAtClusterTime() const {
}
Status ReadConcernArgs::initialize(const BSONElement& readConcernElem) {
- invariant(isEmpty()); // only legal to call on uninitialized object.
-
if (readConcernElem.eoo()) {
return Status::OK();
}
@@ -135,7 +116,11 @@ Status ReadConcernArgs::initialize(const BSONElement& readConcernElem) {
str::stream() << kReadConcernFieldName << " field should be an object");
}
- BSONObj readConcernObj = readConcernElem.Obj();
+ return parse(readConcernElem.Obj());
+}
+
+Status ReadConcernArgs::parse(const BSONObj& readConcernObj) {
+ invariant(isEmpty()); // only legal to call on uninitialized object.
for (auto&& field : readConcernObj) {
auto fieldName = field.fieldNameStringData();
if (fieldName == kAfterOpTimeFieldName) {
@@ -248,6 +233,12 @@ Status ReadConcernArgs::initialize(const BSONElement& readConcernElem) {
return Status::OK();
}
+ReadConcernArgs ReadConcernArgs::fromBSONThrows(const BSONObj& readConcernObj) {
+ ReadConcernArgs rc;
+ uassertStatusOK(rc.parse(readConcernObj));
+ return rc;
+}
+
void ReadConcernArgs::setMajorityReadMechanism(MajorityReadMechanism mechanism) {
invariant(*_level == ReadConcernLevel::kMajorityReadConcern);
_majorityReadMechanism = mechanism;
@@ -297,7 +288,7 @@ void ReadConcernArgs::appendInfo(BSONObjBuilder* builder) const {
}
if (_opTime) {
- _opTime->append(&rcBuilder, kAfterOpTimeFieldName);
+ _opTime->append(&rcBuilder, kAfterOpTimeFieldName.toString());
}
if (_afterClusterTime) {
diff --git a/src/mongo/db/repl/read_concern_args.h b/src/mongo/db/repl/read_concern_args.h
index 775877f9b34..310cfc59432 100644
--- a/src/mongo/db/repl/read_concern_args.h
+++ b/src/mongo/db/repl/read_concern_args.h
@@ -48,11 +48,17 @@ namespace repl {
class ReadConcernArgs {
public:
- static const std::string kReadConcernFieldName;
- static const std::string kAfterOpTimeFieldName;
- static const std::string kAfterClusterTimeFieldName;
- static const std::string kAtClusterTimeFieldName;
- static const std::string kLevelFieldName;
+ static constexpr StringData kReadConcernFieldName = "readConcern"_sd;
+ static constexpr StringData kAfterOpTimeFieldName = "afterOpTime"_sd;
+ static constexpr StringData kAfterClusterTimeFieldName = "afterClusterTime"_sd;
+ static constexpr StringData kAtClusterTimeFieldName = "atClusterTime"_sd;
+ static constexpr StringData kLevelFieldName = "level"_sd;
+
+ static constexpr StringData kLocalReadConcernStr = "local"_sd;
+ static constexpr StringData kMajorityReadConcernStr = "majority"_sd;
+ static constexpr StringData kLinearizableReadConcernStr = "linearizable"_sd;
+ static constexpr StringData kAvailableReadConcernStr = "available"_sd;
+ static constexpr StringData kSnapshotReadConcernStr = "snapshot"_sd;
/**
* Represents the internal mechanism an operation uses to satisfy 'majority' read concern.
@@ -104,6 +110,13 @@ public:
Status initialize(const BSONElement& readConcernElem);
/**
+ * Initializes the object by parsing the actual readConcern sub-object.
+ */
+ Status parse(const BSONObj& readConcernObj);
+
+ static ReadConcernArgs fromBSONThrows(const BSONObj& readConcernObj);
+
+ /**
* Sets the mechanism we should use to satisfy 'majority' reads.
*
* Invalid to call unless the read concern level is 'kMajorityReadConcern'.
diff --git a/src/mongo/db/repl/read_concern_args.idl b/src/mongo/db/repl/read_concern_args.idl
new file mode 100644
index 00000000000..1954f6dddf2
--- /dev/null
+++ b/src/mongo/db/repl/read_concern_args.idl
@@ -0,0 +1,44 @@
+# 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.
+#
+global:
+ cpp_namespace: "mongo"
+ cpp_includes:
+ - "mongo/db/repl/read_concern_args.h"
+
+
+imports:
+ - "mongo/idl/basic_types.idl"
+
+
+types:
+ ReadConcern:
+ description: "An object representing a read concern."
+ bson_serialization_type: object
+ cpp_type: "mongo::repl::ReadConcernArgs"
+ serializer: "mongo::repl::ReadConcernArgs::toBSON"
+ deserializer: "mongo::repl::ReadConcernArgs::fromBSONThrows"
diff --git a/src/mongo/db/rw_concern_default.idl b/src/mongo/db/rw_concern_default.idl
new file mode 100644
index 00000000000..396c12264c1
--- /dev/null
+++ b/src/mongo/db/rw_concern_default.idl
@@ -0,0 +1,61 @@
+# 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.
+#
+global:
+ cpp_namespace: "mongo"
+
+
+imports:
+ - "mongo/idl/basic_types.idl"
+ - "mongo/db/repl/read_concern_args.idl"
+ - "mongo/db/write_concern_options.idl"
+
+
+structs:
+ RWConcernDefault:
+ description: "Represents a set of read/write concern defaults, and associated metadata"
+ fields:
+ defaultReadConcern:
+ description: "The default read concern"
+ type: ReadConcern
+ optional: true
+ defaultWriteConcern:
+ description: "The default write concern"
+ type: WriteConcern
+ optional: true
+ epoch:
+ description: "The epoch (unique generation id) of when the default read or write concern was last set"
+ type: timestamp
+ optional: true
+ setTime:
+ description: "The wallclock time when the default read or write concern was last set by an administrator"
+ type: date
+ optional: true
+ localSetTime:
+ description: "The wallclock time when this node updated its understanding of the default read or write concern"
+ type: date
+ optional: true
diff --git a/src/mongo/db/write_concern_options.cpp b/src/mongo/db/write_concern_options.cpp
index 055fa23a5ee..d92dbfed25c 100644
--- a/src/mongo/db/write_concern_options.cpp
+++ b/src/mongo/db/write_concern_options.cpp
@@ -159,20 +159,37 @@ Status WriteConcernOptions::parse(const BSONObj& obj) {
return Status::OK();
}
-WriteConcernOptions WriteConcernOptions::deserializerForIDL(const BSONObj& obj) {
- WriteConcernOptions writeConcernOptions;
- uassertStatusOK(writeConcernOptions.parse(obj));
- return writeConcernOptions;
-}
+namespace {
-StatusWith<WriteConcernOptions> WriteConcernOptions::extractWCFromCommand(
- const BSONObj& cmdObj, const WriteConcernOptions& defaultWC) {
+/**
+ * Construct a WriteConcernOptions based on an optional default WC object, in preparation for
+ * parsing out of a command object or IDL.
+ */
+WriteConcernOptions constructWCFromDefault(
+ const WriteConcernOptions& defaultWC = WriteConcernOptions()) {
WriteConcernOptions writeConcern = defaultWC;
writeConcern.usedDefault = true;
writeConcern.usedDefaultW = true;
if (writeConcern.wNumNodes == 0 && writeConcern.wMode.empty()) {
writeConcern.wNumNodes = 1;
}
+ return writeConcern;
+}
+
+} // namespace
+
+
+WriteConcernOptions WriteConcernOptions::deserializerForIDL(const BSONObj& obj) {
+ WriteConcernOptions writeConcern = constructWCFromDefault();
+ if (!obj.isEmpty()) {
+ uassertStatusOK(writeConcern.parse(obj));
+ }
+ return writeConcern;
+}
+
+StatusWith<WriteConcernOptions> WriteConcernOptions::extractWCFromCommand(
+ const BSONObj& cmdObj, const WriteConcernOptions& defaultWC) {
+ WriteConcernOptions writeConcern = constructWCFromDefault(defaultWC);
// Return the default write concern if no write concern is provided. We check for the existence
// of the write concern field up front in order to avoid the expense of constructing an error
diff --git a/src/mongo/db/write_concern_options.idl b/src/mongo/db/write_concern_options.idl
new file mode 100644
index 00000000000..07c3cdbffc4
--- /dev/null
+++ b/src/mongo/db/write_concern_options.idl
@@ -0,0 +1,44 @@
+# 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.
+#
+global:
+ cpp_namespace: "mongo"
+ cpp_includes:
+ - "mongo/db/write_concern_options.h"
+
+
+imports:
+ - "mongo/idl/basic_types.idl"
+
+
+types:
+ WriteConcern:
+ description: "An object representing a write concern."
+ bson_serialization_type: object
+ cpp_type: "mongo::WriteConcernOptions"
+ serializer: "mongo::WriteConcernOptions::toBSON"
+ deserializer: "mongo::WriteConcernOptions::deserializerForIDL"