diff --git a/proxy/ParentConsistentHash.cc b/proxy/ParentConsistentHash.cc index dbb42eb7577..1ff1f31da22 100644 --- a/proxy/ParentConsistentHash.cc +++ b/proxy/ParentConsistentHash.cc @@ -235,7 +235,7 @@ ParentConsistentHash::selectParent(bool first_call, ParentResult *result, Reques Debug("parent_select", "Parent.failedAt = %u, retry = %u, xact_start = %u", static_cast(pRec->failedAt.load()), static_cast(retry_time), static_cast(request_info->xact_start)); if ((pRec->failedAt.load() + retry_time) < request_info->xact_start) { - if (pRec->retriers.fetch_add(1, std::memory_order_relaxed) < max_retriers) { + if (pRec->inc_retriers(max_retriers)) { parentRetry = true; // make sure that the proper state is recorded in the result structure result->last_parent = pRec->idx; @@ -243,10 +243,8 @@ ParentConsistentHash::selectParent(bool first_call, ParentResult *result, Reques result->retry = parentRetry; result->result = PARENT_SPECIFIED; Debug("parent_select", "Down parent %s is now retryable, retriers = %d, max_retriers = %d", pRec->hostname, - pRec->retriers.load(), max_retriers); + pRec->retriers(), max_retriers); break; - } else { - pRec->retriers--; } } } @@ -395,7 +393,7 @@ ParentConsistentHash::markParentUp(ParentResult *result) pRec->failedAt = static_cast(0); int old_count = pRec->failCount.exchange(0, std::memory_order_relaxed); - pRec->retriers = 0; + pRec->clear_retriers(); if (old_count > 0) { Note("http parent proxy %s:%d restored", pRec->hostname, pRec->port); diff --git a/proxy/ParentRoundRobin.cc b/proxy/ParentRoundRobin.cc index a0e80eef8ab..4cac51faeba 100644 --- a/proxy/ParentRoundRobin.cc +++ b/proxy/ParentRoundRobin.cc @@ -157,18 +157,15 @@ ParentRoundRobin::selectParent(bool first_call, ParentResult *result, RequestDat } else { if ((result->wrap_around) || (((parents[cur_index].failedAt + retry_time) < request_info->xact_start) && host_stat == TS_HOST_STATUS_UP)) { - if (parents[cur_index].retriers.fetch_add(1, std::memory_order_relaxed) < max_retriers) { + if (parents[cur_index].inc_retriers(max_retriers)) { Debug("parent_select", "Parent[%d].failedAt = %u, retry = %u, retriers = %d, max_retriers = %u, xact_start = %" PRId64 " but wrap = %d", - cur_index, static_cast(parents[cur_index].failedAt.load()), retry_time, - parents[cur_index].retriers.load(), max_retriers, static_cast(request_info->xact_start), - result->wrap_around); + cur_index, static_cast(parents[cur_index].failedAt.load()), retry_time, parents[cur_index].retriers(), + max_retriers, static_cast(request_info->xact_start), result->wrap_around); // Reuse the parent parentUp = true; parentRetry = true; Debug("parent_select", "Parent marked for retry %s:%d", parents[cur_index].hostname, parents[cur_index].port); - } else { - parents[cur_index].retriers--; } } else { parentUp = false; diff --git a/proxy/ParentSelection.cc b/proxy/ParentSelection.cc index f39686aa815..b57162c8ae0 100644 --- a/proxy/ParentSelection.cc +++ b/proxy/ParentSelection.cc @@ -539,7 +539,7 @@ ParentRecord::ProcessParents(char *val, bool isPrimary) this->parents[i].name = this->parents[i].hostname; this->parents[i].available = true; this->parents[i].weight = weight; - this->parents[i].retriers = 0; + this->parents[i].clear_retriers(); if (tmp3) { memcpy(this->parents[i].hash_string, tmp3 + 1, strlen(tmp3)); this->parents[i].name = this->parents[i].hash_string; @@ -555,7 +555,7 @@ ParentRecord::ProcessParents(char *val, bool isPrimary) this->secondary_parents[i].name = this->secondary_parents[i].hostname; this->secondary_parents[i].available = true; this->secondary_parents[i].weight = weight; - this->secondary_parents[i].retriers = 0; + this->secondary_parents[i].clear_retriers(); if (tmp3) { memcpy(this->secondary_parents[i].hash_string, tmp3 + 1, strlen(tmp3)); this->secondary_parents[i].name = this->secondary_parents[i].hash_string; diff --git a/proxy/ParentSelection.h b/proxy/ParentSelection.h index 82c5b2ea33d..dc10b52aef1 100644 --- a/proxy/ParentSelection.h +++ b/proxy/ParentSelection.h @@ -109,7 +109,9 @@ struct SimpleRetryResponseCodes { // // A record for an individual parent // -struct pRecord : ATSConsistentHashNode { +class pRecord : public ATSConsistentHashNode +{ +public: char hostname[MAXDNAME + 1]; int port; std::atomic failedAt = 0; @@ -119,7 +121,46 @@ struct pRecord : ATSConsistentHashNode { int idx; float weight; char hash_string[MAXDNAME + 1]; - std::atomic retriers = 0; + + int + retriers() const + { + return _retriers.load(std::memory_order_relaxed); + } + + void + clear_retriers() + { + _retriers.store(0, std::memory_order_relaxed); + } + + bool + inc_retriers(int max_retriers) + { + ink_assert(max_retriers > 0); + + int r = _retriers.load(std::memory_order_relaxed); + while (r < max_retriers) { + if (_retriers.compare_exchange_weak(r, r + 1, std::memory_order_relaxed, std::memory_order_relaxed)) { + return true; + } + } + return false; + } + + void + dec_retriers() + { + int r = _retriers.load(std::memory_order_relaxed); + while (r > 0) { + if (_retriers.compare_exchange_weak(r, r - 1, std::memory_order_relaxed, std::memory_order_relaxed)) { + break; + } + } + } + +private: + std::atomic _retriers = 0; }; typedef ControlMatcher P_table; diff --git a/proxy/ParentSelectionStrategy.cc b/proxy/ParentSelectionStrategy.cc index 1c1c3a7e4e7..a923112f044 100644 --- a/proxy/ParentSelectionStrategy.cc +++ b/proxy/ParentSelectionStrategy.cc @@ -67,9 +67,7 @@ ParentSelectionStrategy::markParentDown(ParentResult *result, unsigned int fail_ new_fail_count = pRec->failCount = 1; } else { // this was a retry that failed, decrement the retriers count - if ((pRec->retriers--) < 0) { - pRec->retriers = 0; - } + pRec->dec_retriers(); } Note("Parent %s marked as down %s:%d", (result->retry) ? "retry" : "initially", pRec->hostname, pRec->port); @@ -128,7 +126,7 @@ ParentSelectionStrategy::markParentUp(ParentResult *result) pRec->failedAt = static_cast(0); int old_count = pRec->failCount.exchange(0, std::memory_order_relaxed); // a retry succeeded, just reset retriers - pRec->retriers = 0; + pRec->clear_retriers(); if (old_count > 0) { Note("http parent proxy %s:%d restored", pRec->hostname, pRec->port);