diff options
author | Matthew Russotto <matthew.russotto@10gen.com> | 2020-03-17 23:24:28 -0400 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2020-03-18 17:58:52 +0000 |
commit | 7296a460f826c8a618147e09606c5f1935c482a4 (patch) | |
tree | dc9965f86a0ec9bae66636c818a500170dfbd422 /src/mongo/client | |
parent | 03dc2fefa0fb1c77d2caeb6dd166166276bc5b15 (diff) | |
download | mongo-7296a460f826c8a618147e09606c5f1935c482a4.tar.gz |
SERVER-38731 Implement ability to specify sync source read preference in initial sync
Diffstat (limited to 'src/mongo/client')
-rw-r--r-- | src/mongo/client/SConscript | 1 | ||||
-rw-r--r-- | src/mongo/client/read_preference.cpp | 69 | ||||
-rw-r--r-- | src/mongo/client/read_preference.h | 34 | ||||
-rw-r--r-- | src/mongo/client/read_preference.idl | 56 |
4 files changed, 84 insertions, 76 deletions
diff --git a/src/mongo/client/SConscript b/src/mongo/client/SConscript index 8d216c960d5..51c3df426c9 100644 --- a/src/mongo/client/SConscript +++ b/src/mongo/client/SConscript @@ -33,6 +33,7 @@ env.Library( source=[ 'read_preference.cpp', env.Idlc('hedging_mode.idl')[0], + env.Idlc('read_preference.idl')[0], ], LIBDEPS=[ '$BUILD_DIR/mongo/bson/util/bson_extract', diff --git a/src/mongo/client/read_preference.cpp b/src/mongo/client/read_preference.cpp index 5c686a839c6..3d52248f223 100644 --- a/src/mongo/client/read_preference.cpp +++ b/src/mongo/client/read_preference.cpp @@ -50,49 +50,6 @@ const char kTagsFieldName[] = "tags"; const char kMaxStalenessSecondsFieldName[] = "maxStalenessSeconds"; const char kHedgeFieldName[] = "hedge"; -const char kPrimaryOnly[] = "primary"; -const char kPrimaryPreferred[] = "primaryPreferred"; -const char kSecondaryOnly[] = "secondary"; -const char kSecondaryPreferred[] = "secondaryPreferred"; -const char kNearest[] = "nearest"; - -StringData readPreferenceName(ReadPreference pref) { - switch (pref) { - case ReadPreference::PrimaryOnly: - return StringData(kPrimaryOnly); - case ReadPreference::PrimaryPreferred: - return StringData(kPrimaryPreferred); - case ReadPreference::SecondaryOnly: - return StringData(kSecondaryOnly); - case ReadPreference::SecondaryPreferred: - return StringData(kSecondaryPreferred); - case ReadPreference::Nearest: - return StringData(kNearest); - default: - MONGO_UNREACHABLE; - } -} - -StatusWith<ReadPreference> parseReadPreferenceMode(StringData prefStr) { - if (prefStr == kPrimaryOnly) { - return ReadPreference::PrimaryOnly; - } else if (prefStr == kPrimaryPreferred) { - return ReadPreference::PrimaryPreferred; - } else if (prefStr == kSecondaryOnly) { - return ReadPreference::SecondaryOnly; - } else if (prefStr == kSecondaryPreferred) { - return ReadPreference::SecondaryPreferred; - } else if (prefStr == kNearest) { - return ReadPreference::Nearest; - } - return Status(ErrorCodes::FailedToParse, - str::stream() << "Could not parse $readPreference mode '" << prefStr - << "'. Only the modes '" << kPrimaryOnly << "', '" - << kPrimaryPreferred << "', '" << kSecondaryOnly << "', '" - << kSecondaryPreferred << "', and '" << kNearest - << "' are supported."); -} - // Slight kludge here: if we weren't passed a TagSet, we default to the empty // TagSet if ReadPreference is Primary, or the default (wildcard) TagSet otherwise. // This maintains compatibility with existing code, while preserving the ability to round @@ -108,6 +65,14 @@ TagSet defaultTagSetForMode(ReadPreference mode) { } // namespace +Status validateReadPreferenceMode(const std::string& prefStr) { + try { + ReadPreference_parse(IDLParserErrorContext(kModeFieldName), prefStr); + } catch (DBException& e) { + return e.toStatus(); + } + return Status::OK(); +} /** * Replica set refresh period on the task executor. @@ -157,11 +122,19 @@ StatusWith<ReadPreferenceSetting> ReadPreferenceSetting::fromInnerBSON(const BSO } ReadPreference mode; - auto swReadPrefMode = parseReadPreferenceMode(modeStr); - if (!swReadPrefMode.isOK()) { - return swReadPrefMode.getStatus(); + try { + mode = ReadPreference_parse(IDLParserErrorContext(kModeFieldName), modeStr); + } catch (DBException& e) { + return e.toStatus().withContext( + str::stream() << "Could not parse $readPreference mode '" << modeStr + << "'. Only the modes '" + << ReadPreference_serializer(ReadPreference::PrimaryOnly) << "', '" + << ReadPreference_serializer(ReadPreference::PrimaryPreferred) << "', '" + << ReadPreference_serializer(ReadPreference::SecondaryOnly) << "', '" + << ReadPreference_serializer(ReadPreference::SecondaryPreferred) + << "', and '" << ReadPreference_serializer(ReadPreference::Nearest) + << "' are supported."); } - mode = std::move(swReadPrefMode.getValue()); boost::optional<HedgingMode> hedgingMode; if (auto hedgingModeEl = readPrefObj[kHedgeFieldName]) { @@ -261,7 +234,7 @@ StatusWith<ReadPreferenceSetting> ReadPreferenceSetting::fromContainingBSON( } void ReadPreferenceSetting::toInnerBSON(BSONObjBuilder* bob) const { - bob->append(kModeFieldName, readPreferenceName(pref)); + bob->append(kModeFieldName, ReadPreference_serializer(pref)); if (tags != defaultTagSetForMode(pref)) { bob->append(kTagsFieldName, tags.getTagBSON()); } diff --git a/src/mongo/client/read_preference.h b/src/mongo/client/read_preference.h index 5ab06c6f397..5d003ec276a 100644 --- a/src/mongo/client/read_preference.h +++ b/src/mongo/client/read_preference.h @@ -31,6 +31,7 @@ #include "mongo/bson/simple_bsonobj_comparator.h" #include "mongo/client/hedging_mode_gen.h" +#include "mongo/client/read_preference_gen.h" #include "mongo/db/jsobj.h" #include "mongo/db/operation_context.h" #include "mongo/db/repl/optime.h" @@ -40,35 +41,12 @@ namespace mongo { template <typename T> class StatusWith; -enum class ReadPreference { - /** - * Read from primary only. All operations produce an error (throw an exception where - * applicable) if primary is unavailable. Cannot be combined with tags. - */ - PrimaryOnly = 0, - - /** - * Read from primary if available, otherwise a secondary. Tags will only be applied in the - * event that the primary is unavailable and a secondary is read from. In this event only - * secondaries matching the tags provided would be read from. - */ - PrimaryPreferred, - - /** - * Read from secondary if available, otherwise error. - */ - SecondaryOnly, +using ReadPreference = ReadPreferenceEnum; - /** - * Read from a secondary if available, otherwise read from the primary. - */ - SecondaryPreferred, - - /** - * Read from any member. - */ - Nearest, -}; +/** + * Validate a ReadPreference string. This is intended for use as an IDL validator callback. + */ +Status validateReadPreferenceMode(const std::string& prefStr); /** * A simple object for representing the list of tags requested by a $readPreference. diff --git a/src/mongo/client/read_preference.idl b/src/mongo/client/read_preference.idl new file mode 100644 index 00000000000..d98376baef8 --- /dev/null +++ b/src/mongo/client/read_preference.idl @@ -0,0 +1,56 @@ +# Copyright (C) 2020-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" + +enums: + ReadPreference: + description: Enumeration representing Read Preference Modes + type: string + values: + # Read from primary only. All operations produce an error (throw an exception where + # applicable) if primary is unavailable. Cannot be combined with tags. + PrimaryOnly: "primary" + # + # Read from primary if available, otherwise a secondary. Tags will only be applied in the + # event that the primary is unavailable and a secondary is read from. In this event only + # secondaries matching the tags provided would be read from. + PrimaryPreferred: "primaryPreferred" + # + # Read from secondary if available, otherwise error. + SecondaryOnly: "secondary" + # + # Read from a secondary if available, otherwise read from the primary. + SecondaryPreferred: "secondaryPreferred" + # + # Read from any member. + Nearest: "nearest" |