You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2020/01/23 22:02:59 UTC

[trafficserver] 08/12: Fixes a corner case where the NextHop consistent hash ring may not be searched in it's entirety for an available host due to a premature wrapped ring indication.

This is an automated email from the ASF dual-hosted git repository.

zwoop pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git

commit 0c9f08c2b6f66e7afc8229e41211f16994673936
Author: John Rushford <jr...@apache.org>
AuthorDate: Mon Jan 6 17:51:16 2020 +0000

    Fixes a corner case where the NextHop consistent hash ring may not
    be searched in it's entirety for an available host due to a premature
    wrapped ring indication.
    
    (cherry picked from commit 62e4cb18d61b77558a7c2e4fba5ac61f12451be7)
---
 proxy/http/remap/NextHopConsistentHash.cc                 | 13 ++++++++++---
 proxy/http/remap/unit-tests/test_NextHopConsistentHash.cc |  8 ++++----
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/proxy/http/remap/NextHopConsistentHash.cc b/proxy/http/remap/NextHopConsistentHash.cc
index ca90038..f36605c 100644
--- a/proxy/http/remap/NextHopConsistentHash.cc
+++ b/proxy/http/remap/NextHopConsistentHash.cc
@@ -36,7 +36,7 @@ constexpr std::string_view hash_key_cache         = "cache_key";
 
 static HostRecord *
 chash_lookup(std::shared_ptr<ATSConsistentHash> ring, uint64_t hash_key, ATSConsistentHashIter *iter, bool *wrapped,
-             ATSHash64Sip24 *hash, bool *hash_init, uint64_t sm_id)
+             ATSHash64Sip24 *hash, bool *hash_init, bool *mapWrapped, uint64_t sm_id)
 {
   HostRecord *host_rec = nullptr;
 
@@ -46,6 +46,11 @@ chash_lookup(std::shared_ptr<ATSConsistentHash> ring, uint64_t hash_key, ATSCons
   } else {
     host_rec = static_cast<HostRecord *>(ring->lookup(nullptr, iter, wrapped, hash));
   }
+  bool wrap_around = *wrapped;
+  *wrapped         = (*mapWrapped && *wrapped) ? true : false;
+  if (!*mapWrapped && wrap_around) {
+    *mapWrapped = true;
+  }
 
   return host_rec;
 }
@@ -261,7 +266,8 @@ NextHopConsistentHash::findNextHop(const uint64_t sm_id, ParentResult &result, R
 
   do { // search until we've selected a different parent if !firstcall
     std::shared_ptr<ATSConsistentHash> r = rings[cur_ring];
-    hostRec = chash_lookup(r, hash_key, &result.chashIter[cur_ring], &wrapped, &hash, &result.chash_init[cur_ring], sm_id);
+    hostRec               = chash_lookup(r, hash_key, &result.chashIter[cur_ring], &wrapped, &hash, &result.chash_init[cur_ring],
+                           &result.mapWrapped[cur_ring], sm_id);
     wrap_around[cur_ring] = wrapped;
     lookups++;
     // the 'available' flag is maintained in 'host_groups' and not the hash ring.
@@ -322,7 +328,8 @@ NextHopConsistentHash::findNextHop(const uint64_t sm_id, ParentResult &result, R
         break;
       }
       std::shared_ptr<ATSConsistentHash> r = rings[cur_ring];
-      hostRec = chash_lookup(r, hash_key, &result.chashIter[cur_ring], &wrapped, &hash, &result.chash_init[cur_ring], sm_id);
+      hostRec               = chash_lookup(r, hash_key, &result.chashIter[cur_ring], &wrapped, &hash, &result.chash_init[cur_ring],
+                             &result.mapWrapped[cur_ring], sm_id);
       wrap_around[cur_ring] = wrapped;
       lookups++;
       if (hostRec) {
diff --git a/proxy/http/remap/unit-tests/test_NextHopConsistentHash.cc b/proxy/http/remap/unit-tests/test_NextHopConsistentHash.cc
index cbd29bd..08f1179 100644
--- a/proxy/http/remap/unit-tests/test_NextHopConsistentHash.cc
+++ b/proxy/http/remap/unit-tests/test_NextHopConsistentHash.cc
@@ -257,17 +257,17 @@ SCENARIO("Testing NextHopConsistentHash class (all firstcalls), using policy 'co
         result.reset();
         strategy->findNextHop(20004, result, request, fail_threshold, retry_time);
         CHECK(result.result == ParentResultType::PARENT_SPECIFIED);
-        CHECK(strcmp(result.hostname, "q1.bar.com") == 0);
+        CHECK(strcmp(result.hostname, "s1.bar.com") == 0);
 
-        // mark down q1.bar.com
+        // mark down s1.bar.com
         strategy->markNextHopDown(20004, result, 1, fail_threshold);
 
         // fifth request
         br(&request, "rabbit.net/asset1");
         result.reset();
         strategy->findNextHop(20005, result, request, fail_threshold, retry_time);
-        CHECK(result.result == ParentResultType::PARENT_DIRECT);
-        CHECK(result.hostname == nullptr);
+        CHECK(result.result == ParentResultType::PARENT_SPECIFIED);
+        CHECK(strcmp(result.hostname, "q1.bar.com") == 0);
 
         // sixth request - wait and p1 should now become available
         time_t now = time(nullptr) + 5;