diff options
author | LaMont Nelson <lamont.nelson@mongodb.com> | 2021-09-21 14:06:46 +0000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2021-09-22 02:36:20 +0000 |
commit | 75ea17705d4e385f12b0a7b576e03359c23d6982 (patch) | |
tree | b448b0cef312852588e09a1f805c87f2a461c308 | |
parent | fb8adfb14a8a4bf2f75c2797a0cfb48c07a7edf3 (diff) | |
download | mongo-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.cpp | 2 | ||||
-rw-r--r-- | src/mongo/client/sdam/topology_description.cpp | 25 | ||||
-rw-r--r-- | src/mongo/client/sdam/topology_description.h | 8 | ||||
-rw-r--r-- | src/mongo/client/sdam/topology_description_test.cpp | 33 | ||||
-rw-r--r-- | src/mongo/client/sdam/topology_manager.cpp | 4 |
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); |