Skip to content

Commit 171fe80

Browse files
committed
SERVER-41910 Make RSM return mulitple hosts in the presence of tags
1 parent 3206241 commit 171fe80

File tree

2 files changed

+133
-106
lines changed

2 files changed

+133
-106
lines changed

src/mongo/client/replica_set_monitor.cpp

Lines changed: 38 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,7 @@ std::vector<HostAndPort> SetState::getMatchingHosts(const ReadPreferenceSetting&
11411141
}
11421142
}
11431143

1144+
std::vector<const Node*> allMatchingNodes;
11441145
BSONForEach(tagElem, criteria.tags.getTagBSON()) {
11451146
uassert(16358, "Tags should be a BSON object", tagElem.isABSONObj());
11461147
BSONObj tag = tagElem.Obj();
@@ -1153,14 +1154,6 @@ std::vector<HostAndPort> SetState::getMatchingHosts(const ReadPreferenceSetting&
11531154
}
11541155
}
11551156

1156-
// don't do more complicated selection if not needed
1157-
if (matchingNodes.empty()) {
1158-
continue;
1159-
}
1160-
if (matchingNodes.size() == 1) {
1161-
return {matchingNodes.front()->host};
1162-
}
1163-
11641157
// Only consider nodes that satisfy the minOpTime
11651158
if (!criteria.minOpTime.isNull()) {
11661159
std::sort(matchingNodes.begin(), matchingNodes.end(), opTimeGreater);
@@ -1175,45 +1168,50 @@ std::vector<HostAndPort> SetState::getMatchingHosts(const ReadPreferenceSetting&
11751168
break;
11761169
}
11771170
}
1178-
1179-
if (matchingNodes.size() == 1) {
1180-
return {matchingNodes.front()->host};
1181-
}
11821171
}
11831172

1184-
// If there are multiple nodes satisfying the minOpTime, next order by latency
1185-
// and don't consider hosts further than a threshold from the closest.
1186-
std::sort(matchingNodes.begin(), matchingNodes.end(), compareLatencies);
1187-
for (size_t i = 1; i < matchingNodes.size(); i++) {
1188-
int64_t distance =
1189-
matchingNodes[i]->latencyMicros - matchingNodes[0]->latencyMicros;
1190-
if (distance >= latencyThresholdMicros) {
1191-
// this node and all remaining ones are too far away
1192-
matchingNodes.erase(matchingNodes.begin() + i, matchingNodes.end());
1193-
break;
1194-
}
1195-
}
1173+
allMatchingNodes.insert(
1174+
allMatchingNodes.end(), matchingNodes.begin(), matchingNodes.end());
1175+
}
1176+
1177+
// don't do more complicated selection if not needed
1178+
if (allMatchingNodes.empty()) {
1179+
return {};
1180+
}
1181+
if (allMatchingNodes.size() == 1) {
1182+
return {allMatchingNodes.front()->host};
1183+
}
11961184

1197-
std::vector<HostAndPort> hosts;
1198-
std::transform(matchingNodes.begin(),
1199-
matchingNodes.end(),
1200-
std::back_inserter(hosts),
1201-
[](const auto& node) { return node->host; });
1202-
1203-
// Note that the host list is only deterministic (or random) for the first node.
1204-
// The rest of the list is in matchingNodes order (latency) with one element swapped
1205-
// for the first element.
1206-
if (auto bestHostIdx = ReplicaSetMonitor::useDeterministicHostSelection
1207-
? roundRobin++ % hosts.size()
1208-
: rand.nextInt32(hosts.size())) {
1209-
using std::swap;
1210-
swap(hosts[0], hosts[bestHostIdx]);
1185+
// If there are multiple nodes satisfying the minOpTime, next order by latency
1186+
// and don't consider hosts further than a threshold from the closest.
1187+
std::sort(allMatchingNodes.begin(), allMatchingNodes.end(), compareLatencies);
1188+
for (size_t i = 1; i < allMatchingNodes.size(); i++) {
1189+
int64_t distance =
1190+
allMatchingNodes[i]->latencyMicros - allMatchingNodes[0]->latencyMicros;
1191+
if (distance >= latencyThresholdMicros) {
1192+
// this node and all remaining ones are too far away
1193+
allMatchingNodes.erase(allMatchingNodes.begin() + i, allMatchingNodes.end());
1194+
break;
12111195
}
1196+
}
12121197

1213-
return hosts;
1198+
std::vector<HostAndPort> hosts;
1199+
std::transform(allMatchingNodes.begin(),
1200+
allMatchingNodes.end(),
1201+
std::back_inserter(hosts),
1202+
[](const auto& node) { return node->host; });
1203+
1204+
// Note that the host list is only deterministic (or random) for the first node.
1205+
// The rest of the list is in matchingNodes order (latency) with one element swapped
1206+
// for the first element.
1207+
if (auto bestHostIdx = ReplicaSetMonitor::useDeterministicHostSelection
1208+
? roundRobin++ % hosts.size()
1209+
: rand.nextInt32(hosts.size())) {
1210+
using std::swap;
1211+
swap(hosts[0], hosts[bestHostIdx]);
12141212
}
12151213

1216-
return {};
1214+
return hosts;
12171215
}
12181216

12191217
default:

0 commit comments

Comments
 (0)