in mcrouter/routes/FailoverPolicy.h [404:483]
void increment() {
// No need to determine "next" index for passive iterators
if (!active_) {
++id_;
return;
}
uint32_t numAttempts = 0;
const auto nChildren = policy_.children_.size();
// arbitrarily set high number of max attempts so that finding the next
// index does not get into infinite loop
constexpr uint32_t maxAttempts = 100;
// arbitrarily set percent of max attempts as failure domain threshold
// so that we do not consider all the MSB as failed (Remember that we
// do not have direct signal that a TKO is due to MSB failure, so if
// the number failure domains are small and all the failure domains are
// in the set, then we would be skipping all of them. This threshold is
// to get out of skipping all the destinations due to this pathological
// case
constexpr uint32_t failureDomainThreshold = (3 * maxAttempts) / 4;
if (index_ == 0) {
// initialize usedIndexes_ here before it is used
usedIndexes_.resize(nChildren);
usedIndexes_.set(0);
// Use normal_reply_index only if ignore flag is false
if (!policy_.ignore_normal_reply_index_) {
size_t normal_reply_index =
mcrouter::fiber_local<RouterInfo>::getSelectedIndex();
// Skip the destination selected by normal route by adding the
// index of the normal route destination to usedIndexes.
if ((normal_reply_index + 1) < usedIndexes_.size()) {
usedIndexes_.set(normal_reply_index + 1);
} else {
LOG_FAILURE(
"mcrouter",
failure::Category::kInvalidConfig,
"Normal Route and Failover route pool sizes seem to be different."
" ignore_normal_reply_index config flag should be used.");
}
}
}
bool failedDomain = false;
do {
salt_++;
if (funcType_ == Ch3HashFunc::type()) {
Ch3HashFunc ch3Func(nChildren);
index_ = HashSelector<Ch3HashFunc>(std::to_string(salt_), ch3Func)
.select(req_, nChildren);
} else {
WeightedCh3HashFunc wCh3Func{config_, nChildren};
index_ =
HashSelector<WeightedCh3HashFunc>(std::to_string(salt_), wCh3Func)
.select(req_, nChildren);
}
// Use failure domains only in case of non-const iterators
if constexpr (!std::is_const<Policy>{}) {
uint32_t nextFd = getFailureDomain(index_);
failedDomain =
(policy_.enableFailureDomains_ &&
(failedDomains_.find(nextFd) != failedDomains_.end()));
}
// force ignore failure-domain if we have tried more than
// failureDomainThreshold -- FAIL safe mechanism
if (numAttempts > failureDomainThreshold) {
failedDomain = false;
}
if (failedDomain) {
num_failed_domain_collisions_++;
} else {
collisions_++;
}
} while ((usedIndexes_.test(index_) || failedDomain) &&
(numAttempts++ < maxAttempts));
collisions_--;
usedIndexes_.set(index_);
++id_;
}