summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Schultz <william.schultz@mongodb.com>2020-02-04 21:49:45 +0000
committerevergreen <evergreen@mongodb.com>2020-02-04 21:49:45 +0000
commit7fa0a642fa7e99740b83e61040b01498dfb889eb (patch)
tree39c84b3c1a2deae115193c7471a93450f9e950ad
parente79dc5d3c154e1cbc5d071f5e3725ea7c9563179 (diff)
downloadmongo-7fa0a642fa7e99740b83e61040b01498dfb889eb.tar.gz
SERVER-45082 Add ConfigVersionAndTerm structure for comparing replica set configs
-rw-r--r--src/mongo/db/repl/repl_set_config.h61
-rw-r--r--src/mongo/db/repl/repl_set_config_test.cpp21
2 files changed, 82 insertions, 0 deletions
diff --git a/src/mongo/db/repl/repl_set_config.h b/src/mongo/db/repl/repl_set_config.h
index d5f065d5f7b..b82f0ed5e22 100644
--- a/src/mongo/db/repl/repl_set_config.h
+++ b/src/mongo/db/repl/repl_set_config.h
@@ -48,6 +48,67 @@ class BSONObj;
namespace repl {
/**
+ * A structure that stores a ReplSetConfig (version, term) pair.
+ *
+ * This can be used to compare two ReplSetConfig objects to determine which is logically newer.
+ */
+class ConfigVersionAndTerm {
+public:
+ ConfigVersionAndTerm() : _version(0), _term(OpTime::kUninitializedTerm) {}
+ ConfigVersionAndTerm(int version, long long term) : _version(version), _term(term) {}
+
+ inline bool operator==(const ConfigVersionAndTerm& rhs) const {
+ // If term of either item is uninitialized (-1), then we ignore terms entirely and only
+ // compare versions.
+ if (_term == OpTime::kUninitializedTerm || rhs._term == OpTime::kUninitializedTerm) {
+ return _version == rhs._version;
+ }
+ // Compare term first, then the versions.
+ return std::tie(_term, _version) == std::tie(rhs._term, rhs._version);
+ }
+
+ inline bool operator<(const ConfigVersionAndTerm& rhs) const {
+ // If term of either item is uninitialized (-1), then we ignore terms entirely and only
+ // compare versions. This allows force reconfigs, which set the config term to -1, to
+ // override other configs by using a high config version.
+ if (_term == OpTime::kUninitializedTerm || rhs._term == OpTime::kUninitializedTerm) {
+ return _version < rhs._version;
+ }
+ // Compare term first, then the versions.
+ return std::tie(_term, _version) < std::tie(rhs._term, rhs._version);
+ }
+
+ inline bool operator!=(const ConfigVersionAndTerm& rhs) const {
+ return !(*this == rhs);
+ }
+
+ inline bool operator<=(const ConfigVersionAndTerm& rhs) const {
+ return *this < rhs || *this == rhs;
+ }
+
+ inline bool operator>(const ConfigVersionAndTerm& rhs) const {
+ return !(*this <= rhs);
+ }
+
+ inline bool operator>=(const ConfigVersionAndTerm& rhs) const {
+ return !(*this < rhs);
+ }
+
+ // TODO (SERVER-45082): Implement string conversion.
+ std::string toString() const {
+ return "";
+ };
+
+ friend std::ostream& operator<<(std::ostream& out, const ConfigVersionAndTerm& cvt) {
+ return out << cvt.toString();
+ }
+
+private:
+ long long _version;
+ long long _term;
+};
+
+/**
* Representation of the configuration information about a particular replica set.
*/
class ReplSetConfig {
diff --git a/src/mongo/db/repl/repl_set_config_test.cpp b/src/mongo/db/repl/repl_set_config_test.cpp
index ddebd5f25f9..bdb4770bfa2 100644
--- a/src/mongo/db/repl/repl_set_config_test.cpp
+++ b/src/mongo/db/repl/repl_set_config_test.cpp
@@ -1714,6 +1714,27 @@ TEST(ReplSetConfig, ReplSetId) {
"\"replicaSetId\" had the wrong type. Expected objectId, found int");
}
+TEST(ReplSetConfig, ConfigVersionAndTermComparison) {
+ // Test equality.
+ ASSERT_EQ(ConfigVersionAndTerm(1, 1), ConfigVersionAndTerm(1, 1));
+ ASSERT_EQ(ConfigVersionAndTerm(1, 2), ConfigVersionAndTerm(1, 2));
+ ASSERT_EQ(ConfigVersionAndTerm(2, 2), ConfigVersionAndTerm(2, 2));
+ ASSERT_EQ(ConfigVersionAndTerm(1, -1), ConfigVersionAndTerm(1, 1));
+ ASSERT_EQ(ConfigVersionAndTerm(1, 1), ConfigVersionAndTerm(1, -1));
+ ASSERT_EQ(ConfigVersionAndTerm(1, -1), ConfigVersionAndTerm(1, -1));
+ // Test greater/less than or equal to.
+ ASSERT_GT(ConfigVersionAndTerm(2, 1), ConfigVersionAndTerm(1, 1));
+ ASSERT_GTE(ConfigVersionAndTerm(2, 1), ConfigVersionAndTerm(1, 1));
+ ASSERT_GT(ConfigVersionAndTerm(1, 2), ConfigVersionAndTerm(1, 1));
+ ASSERT_GTE(ConfigVersionAndTerm(1, 2), ConfigVersionAndTerm(1, 1));
+ ASSERT_LT(ConfigVersionAndTerm(1, 1), ConfigVersionAndTerm(2, 1));
+ ASSERT_LTE(ConfigVersionAndTerm(1, 1), ConfigVersionAndTerm(2, 1));
+ ASSERT_LT(ConfigVersionAndTerm(1, 1), ConfigVersionAndTerm(1, 2));
+ ASSERT_LTE(ConfigVersionAndTerm(1, 1), ConfigVersionAndTerm(1, 2));
+ ASSERT_GT(ConfigVersionAndTerm(2, 1), ConfigVersionAndTerm(1, -1));
+ ASSERT_GT(ConfigVersionAndTerm(2, -1), ConfigVersionAndTerm(1, 1));
+ ASSERT_GT(ConfigVersionAndTerm(2, -1), ConfigVersionAndTerm(1, -1));
+}
} // namespace
} // namespace repl
} // namespace mongo