You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by jr...@apache.org on 2018/12/05 19:55:10 UTC

[trafficserver] branch master updated: Use optionally provided hash string for hashing

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

jrushford pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new f22b06f  Use optionally provided hash string for hashing
f22b06f is described below

commit f22b06f3f7c2aba5b14d8e633b2aefc7a4a14ef7
Author: Vijay Mamidi <vi...@yahoo.com>
AuthorDate: Thu Nov 29 11:40:24 2018 -0700

    Use optionally provided hash string for hashing
---
 doc/admin-guide/files/parent.config.en.rst |  8 +++
 proxy/ParentSelection.cc                   | 89 ++++++++++++++++++++++++------
 proxy/ParentSelection.h                    |  1 +
 3 files changed, 80 insertions(+), 18 deletions(-)

diff --git a/doc/admin-guide/files/parent.config.en.rst b/doc/admin-guide/files/parent.config.en.rst
index 3a26e95..ca54825 100644
--- a/doc/admin-guide/files/parent.config.en.rst
+++ b/doc/admin-guide/files/parent.config.en.rst
@@ -141,6 +141,14 @@ The following list shows the possible actions and their allowed values.
 
         parent="p1.x.com:8080|2.0, 192.168.0.3:80|3.0, 192.168.0.4:80|5.0"
 
+    If ``round_robin`` is set to ``consistent_hash``, you may add a ``unique hash string``
+    following the ``weight`` for each parent.  The ``hash string`` must start with ``&``
+	  and is used to build both the primary and secondary rings using the ``hash string``
+    for each parent insted of the parents ``hostname`` or ``ip address``. This can be
+    useful so that two different hosts may be used to cache the same requests.  Example::
+
+        parent="p1.x.com:80|1.0&abcdef, p2.x.com:80|1.0&xyzl, p3.x.com:80|1.0&ldffg" round_robin=consistent_hash
+
 .. _parent-config-format-secondary-parent:
 
 ``secondary_parent``
diff --git a/proxy/ParentSelection.cc b/proxy/ParentSelection.cc
index df3f368..882e57e 100644
--- a/proxy/ParentSelection.cc
+++ b/proxy/ParentSelection.cc
@@ -413,7 +413,7 @@ ParentRecord::ProcessParents(char *val, bool isPrimary)
   int numTok          = 0;
   const char *current = nullptr;
   int port            = 0;
-  char *tmp = nullptr, *tmp2 = nullptr;
+  char *tmp = nullptr, *tmp2 = nullptr, *tmp3 = nullptr;
   const char *errPtr = nullptr;
   float weight       = 1.0;
 
@@ -466,23 +466,27 @@ ParentRecord::ProcessParents(char *val, bool isPrimary)
       }
     }
 
+    tmp3 = (char *)strchr(current, '&');
+
     // Make sure that is no garbage beyond the parent
-    //   port or weight
-    char *scan;
-    if (tmp2) {
-      scan = tmp2 + 1;
-    } else {
-      scan = tmp + 1;
-    }
-    for (; *scan != '\0' && (ParseRules::is_digit(*scan) || *scan == '.'); scan++) {
-      ;
-    }
-    for (; *scan != '\0' && ParseRules::is_wslfcr(*scan); scan++) {
-      ;
-    }
-    if (*scan != '\0') {
-      errPtr = "Garbage trailing entry or invalid separator";
-      goto MERROR;
+    //  port or weight
+    if (!tmp3) {
+      char *scan;
+      if (tmp2) {
+        scan = tmp2 + 1;
+      } else {
+        scan = tmp + 1;
+      }
+      for (; *scan != '\0' && (ParseRules::is_digit(*scan) || *scan == '.'); scan++) {
+        ;
+      }
+      for (; *scan != '\0' && ParseRules::is_wslfcr(*scan); scan++) {
+        ;
+      }
+      if (*scan != '\0') {
+        errPtr = "Garbage trailing entry or invalid separator";
+        goto MERROR;
+      }
     }
     // Check to make sure that the string will fit in the
     //  pRecord
@@ -505,6 +509,10 @@ ParentRecord::ProcessParents(char *val, bool isPrimary)
       this->parents[i].name                    = this->parents[i].hostname;
       this->parents[i].available               = true;
       this->parents[i].weight                  = weight;
+      if (tmp3) {
+        memcpy(this->parents[i].hash_string, tmp3 + 1, strlen(tmp3));
+        this->parents[i].name = this->parents[i].hash_string;
+      }
       hs.createHostStat(this->parents[i].hostname);
     } else {
       memcpy(this->secondary_parents[i].hostname, current, tmp - current);
@@ -517,8 +525,13 @@ 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;
+      if (tmp3) {
+        memcpy(this->secondary_parents[i].hash_string, tmp3 + 1, strlen(tmp3));
+        this->secondary_parents[i].name = this->secondary_parents[i].hash_string;
+      }
       hs.createHostStat(this->secondary_parents[i].hostname);
     }
+    tmp3 = nullptr;
   }
 
   if (isPrimary) {
@@ -803,7 +816,7 @@ ParentRecord::Print()
 {
   printf("\t\t");
   for (int i = 0; i < num_parents; i++) {
-    printf(" %s:%d ", parents[i].hostname, parents[i].port);
+    printf(" %s:%d|%f&%s ", parents[i].hostname, parents[i].port, parents[i].weight, parents[i].name);
   }
   printf(" direct=%s\n", (go_direct == true) ? "true" : "false");
   printf(" parent_is_proxy=%s\n", (parent_is_proxy == true) ? "true" : "false");
@@ -1719,6 +1732,46 @@ EXCLUSIVE_REGRESSION_TEST(PARENTSELECTION)(RegressionTest * /* t ATS_UNUSED */,
   sleep(1);
   RE(verify(result, PARENT_FAIL, nullptr, 80), 208);
 
+  // Tests 209 through 211 test that host selection is based upon the hash_string
+
+  // Test 209
+  // fuzzy { curly larry, moe } fluffy
+  tbl[0] = '\0';
+  ST(209);
+  T("dest_domain=stooges.net parent=curly:80|1.0&myhash;joe:80|1.0&hishash;larry:80|1.0&ourhash "
+    "round_robin=consistent_hash go_direct=false\n");
+  REBUILD;
+  REINIT;
+  br(request, "i.am.stooges.net");
+  FP;
+  RE(verify(result, PARENT_SPECIFIED, "larry", 80), 209);
+
+  // Test 210
+  // fuzzy { curly larry, moe } fluffy
+  tbl[0] = '\0';
+  ST(210);
+  T("dest_domain=stooges.net parent=curly:80|1.0&ourhash;joe:80|1.0&hishash;larry:80|1.0&myhash "
+    "round_robin=consistent_hash go_direct=false\n");
+  REBUILD;
+  REINIT;
+  br(request, "i.am.stooges.net");
+  FP;
+  RE(verify(result, PARENT_SPECIFIED, "curly", 80), 210);
+
+  // Test 211
+  // fuzzy { curly larry, moe } fluffy
+  tbl[0] = '\0';
+  ST(211);
+  T("dest_domain=stooges.net parent=curly:80|1.0&ourhash;joe:80|1.0&hishash;larry:80|1.0&myhash "
+    "secondary_parent=carol:80|1.0&ourhash;betty:80|1.0&hishash;donna:80|1.0&myhash "
+    "round_robin=consistent_hash go_direct=false\n");
+  REBUILD;
+  REINIT;
+  _st.setHostStatus("curly", HOST_STATUS_DOWN, 0, Reasons::MANUAL);
+  br(request, "i.am.stooges.net");
+  FP;
+  RE(verify(result, PARENT_SPECIFIED, "carol", 80), 211);
+
   delete request;
   delete result;
   delete params;
diff --git a/proxy/ParentSelection.h b/proxy/ParentSelection.h
index 3b8fbd2..c0f3802 100644
--- a/proxy/ParentSelection.h
+++ b/proxy/ParentSelection.h
@@ -102,6 +102,7 @@ struct pRecord : ATSConsistentHashNode {
   const char *scheme; // for which parent matches (if any)
   int idx;
   float weight;
+  char hash_string[MAXDNAME + 1];
 };
 
 typedef ControlMatcher<ParentRecord, ParentResult> P_table;