summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaMont Nelson <lamont.nelson@mongodb.com>2021-09-21 14:06:46 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-09-22 02:36:20 +0000
commit75ea17705d4e385f12b0a7b576e03359c23d6982 (patch)
treeb448b0cef312852588e09a1f805c87f2a461c308
parentfb8adfb14a8a4bf2f75c2797a0cfb48c07a7edf3 (diff)
downloadmongo-75ea17705d4e385f12b0a7b576e03359c23d6982.tar.gz
SERVER-60062 Fix cloning of server description and uuid in RSM's topology description
(cherry picked from commit ed6372937bb6d10c440f016333ed41ccb67e9139)
-rw-r--r--src/mongo/client/sdam/server_selector_test.cpp2
-rw-r--r--src/mongo/client/sdam/topology_description.cpp25
-rw-r--r--src/mongo/client/sdam/topology_description.h8
-rw-r--r--src/mongo/client/sdam/topology_description_test.cpp33
-rw-r--r--src/mongo/client/sdam/topology_manager.cpp4
5 files changed, 49 insertions, 23 deletions
diff --git a/src/mongo/client/sdam/server_selector_test.cpp b/src/mongo/client/sdam/server_selector_test.cpp
index fa7593d31f5..25994d1603e 100644
--- a/src/mongo/client/sdam/server_selector_test.cpp
+++ b/src/mongo/client/sdam/server_selector_test.cpp
@@ -228,7 +228,7 @@ TEST_F(ServerSelectorTestFixture, ShouldBeAbleToSelectWithMaxStalenessFromCloned
.withMaxWireVersion(WireVersion::LATEST_WIRE_VERSION)
.instance();
stateMachine.onServerDescription(*topologyDescription, primary);
- topologyDescription = TopologyDescription::clone(topologyDescription);
+ topologyDescription = TopologyDescription::clone(*topologyDescription);
const auto ninetySeconds = Seconds(90);
const auto readPref =
diff --git a/src/mongo/client/sdam/topology_description.cpp b/src/mongo/client/sdam/topology_description.cpp
index 2c576557a94..90f7f259343 100644
--- a/src/mongo/client/sdam/topology_description.cpp
+++ b/src/mongo/client/sdam/topology_description.cpp
@@ -50,14 +50,21 @@ TopologyDescription::TopologyDescription(SdamConfiguration config)
TopologyDescriptionPtr TopologyDescription::create(SdamConfiguration config) {
auto result = std::make_shared<TopologyDescription>(config);
- TopologyDescription::associateServerDescriptions(result);
+ for (auto& server : result->_servers) {
+ server->_topologyDescription = result;
+ }
return result;
}
-TopologyDescriptionPtr TopologyDescription::clone(TopologyDescriptionPtr source) {
- invariant(source);
- auto result = std::make_shared<TopologyDescription>(*source);
- TopologyDescription::associateServerDescriptions(result);
+TopologyDescriptionPtr TopologyDescription::clone(const TopologyDescription& source) {
+ auto result = std::make_shared<TopologyDescription>(source);
+ result->_id = UUID::gen();
+
+ for (auto& server : result->_servers) {
+ server = std::make_shared<ServerDescription>(*server);
+ server->_topologyDescription = result;
+ }
+
return result;
}
@@ -286,14 +293,6 @@ std::string TopologyDescription::toString() {
return toBSON().toString();
}
-void TopologyDescription::associateServerDescriptions(
- const TopologyDescriptionPtr& topologyDescription) {
- auto& servers = topologyDescription->_servers;
- for (auto& server : servers) {
- server->_topologyDescription = topologyDescription;
- }
-}
-
boost::optional<ServerDescriptionPtr> TopologyDescription::getPrimary() {
if (getType() != TopologyType::kReplicaSetWithPrimary) {
return boost::none;
diff --git a/src/mongo/client/sdam/topology_description.h b/src/mongo/client/sdam/topology_description.h
index 2c1d75dc43c..4d41c7b8726 100644
--- a/src/mongo/client/sdam/topology_description.h
+++ b/src/mongo/client/sdam/topology_description.h
@@ -58,10 +58,10 @@ public:
static TopologyDescriptionPtr create(SdamConfiguration config);
/**
- * Copy the given TopologyDescription and set the topologyDescription of all contained server
- * descriptions to point to this instance.
+ * Deep copy the given TopologyDescription. The copy constructor won't work in this scenario
+ * because shared_from_this cannot be used from within a constructor.
*/
- static TopologyDescriptionPtr clone(TopologyDescriptionPtr source);
+ static TopologyDescriptionPtr clone(const TopologyDescription& source);
const UUID& getId() const;
TopologyType getType() const;
@@ -144,8 +144,6 @@ private:
*/
void calculateLogicalSessionTimeout();
- static void associateServerDescriptions(const TopologyDescriptionPtr& topologyDescription);
-
// unique id for this topology
UUID _id = UUID::gen();
diff --git a/src/mongo/client/sdam/topology_description_test.cpp b/src/mongo/client/sdam/topology_description_test.cpp
index 85bb1ed62a1..ac670f39846 100644
--- a/src/mongo/client/sdam/topology_description_test.cpp
+++ b/src/mongo/client/sdam/topology_description_test.cpp
@@ -341,5 +341,34 @@ TEST_F(TopologyDescriptionTestFixture, ShouldNotUpdateTopologyVersionOnError) {
auto topologyVersion = topologyDescription->getServers()[1]->getTopologyVersion();
ASSERT(topologyVersion == boost::none);
}
-}; // namespace sdam
-}; // namespace mongo
+
+TEST_F(TopologyDescriptionTestFixture, ShouldMakeNewUUIDWhenCloning) {
+ const auto config = SdamConfiguration(kThreeServers);
+ const auto topologyDescription = std::make_shared<TopologyDescription>(config);
+ const auto newTopologyDescription = TopologyDescription::clone(*topologyDescription);
+ ASSERT(topologyDescription->getId() != newTopologyDescription->getId());
+}
+
+TEST_F(TopologyDescriptionTestFixture, ShouldNotShareServerDescriptionsWhenCloning) {
+ const auto config = SdamConfiguration(kThreeServers);
+ const auto topologyDescription = std::make_shared<TopologyDescription>(config);
+ const auto newTopologyDescription = TopologyDescription::clone(*topologyDescription);
+
+ const auto& newServers = newTopologyDescription->getServers();
+ ASSERT_EQUALS(newServers.size(), topologyDescription->getServers().size());
+ for (const auto& server : newServers) {
+ auto resultPtr = topologyDescription->findServers(
+ [server](const ServerDescriptionPtr& s) { return s.get() == server.get(); });
+ ASSERT_EQUALS(resultPtr.size(), 0);
+
+ auto resultAddress =
+ topologyDescription->findServers([server](const ServerDescriptionPtr& s) {
+ return s->getAddress() == server->getAddress();
+ });
+ ASSERT_EQUALS(resultAddress.size(), 1);
+ ASSERT_EQUALS(*resultAddress[0], *server);
+ ASSERT_EQUALS(server->getTopologyDescription(), newTopologyDescription);
+ }
+}
+} // namespace sdam
+} // namespace mongo
diff --git a/src/mongo/client/sdam/topology_manager.cpp b/src/mongo/client/sdam/topology_manager.cpp
index 2c5125b1a14..1ce47be7ae3 100644
--- a/src/mongo/client/sdam/topology_manager.cpp
+++ b/src/mongo/client/sdam/topology_manager.cpp
@@ -101,7 +101,7 @@ bool TopologyManager::onServerDescription(const IsMasterOutcome& isMasterOutcome
_clockSource, isMasterOutcome, lastRTT, newTopologyVersion);
auto oldTopologyDescription = _topologyDescription;
- _topologyDescription = TopologyDescription::clone(oldTopologyDescription);
+ _topologyDescription = TopologyDescription::clone(*oldTopologyDescription);
// if we are equal to the old description, just install the new description without
// performing any actions on the state machine.
@@ -131,7 +131,7 @@ void TopologyManager::onServerRTTUpdated(HostAndPort hostAndPort, IsMasterRTT rt
auto newServerDescription = (*oldServerDescription)->cloneWithRTT(rtt);
auto oldTopologyDescription = _topologyDescription;
- _topologyDescription = TopologyDescription::clone(oldTopologyDescription);
+ _topologyDescription = TopologyDescription::clone(*oldTopologyDescription);
_topologyDescription->installServerDescription(newServerDescription);
_publishTopologyDescriptionChanged(oldTopologyDescription, _topologyDescription);