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


The following commit(s) were added to refs/heads/9.0.x by this push:
     new e95503f  Add support for a simple_server_retry_responses list (#6605)
e95503f is described below

commit e95503f1c6c7311d5f7ba9dda5466512b1bb54b4
Author: Evan Zelkowitz <e...@apache.org>
AuthorDate: Thu Apr 2 08:15:35 2020 -0700

    Add support for a simple_server_retry_responses list (#6605)
    
     This adds support for simple_server_retry_responses to allow the user to 
set a list of 4xx reponse codes which trigger a simple retry, instead of the 
current functionality which will only trigger on a 404.  This mimics the 
unavailable responses list in the same manner except for the 4xx simple retry 
case
    
    (cherry picked from commit 0d22ab057a42cf3fbc0b782479e964df2c1c8047)
---
 doc/admin-guide/files/parent.config.en.rst | 10 ++++++-
 proxy/ParentSelection.cc                   | 42 ++++++++++++++++++++++++++++++
 proxy/ParentSelection.h                    | 29 ++++++++++++++++++++-
 proxy/http/HttpTransact.cc                 | 29 +++++++++++++++++----
 4 files changed, 103 insertions(+), 7 deletions(-)

diff --git a/doc/admin-guide/files/parent.config.en.rst 
b/doc/admin-guide/files/parent.config.en.rst
index 83584ea..c7fc123 100644
--- a/doc/admin-guide/files/parent.config.en.rst
+++ b/doc/admin-guide/files/parent.config.en.rst
@@ -207,7 +207,8 @@ The following list shows the possible actions and their 
allowed values.
 .. _parent-config-format-parent-retry:
 
 ``parent_retry``
-    - ``simple_retry`` - If the parent origin server returns a 404 response on 
a request
+    - ``simple_retry`` - If the parent returns a 404 response or if the 
response matches
+      a list of http 4xx responses defined in 
``simple_server_retry_responses`` on a request
       a new parent is selected and the request is retried.  The number of 
retries is controlled
       by ``max_simple_retries`` which is set to 1 by default.
     - ``unavailable_server_retry`` - If the parent returns a 503 response or 
if the response matches
@@ -216,6 +217,13 @@ The following list shows the possible actions and their 
allowed values.
       retries is controlled by ``max_unavailable_server_retries`` which is set 
to 1 by default.
     - ``both`` - This enables both ``simple_retry`` and 
``unavailable_server_retry`` as described above.
 
+.. _parent-config-format-simple-server-retry-responses:
+
+``simple_server_retry_responses``
+   If ``parent_retry`` is set to either ``simple_retry`` or ``both``, this 
parameter is a comma separated list of
+   http 4xx response codes that will invoke the ``simple_retry`` described in 
the ``parent_retry`` section. By
+   default, ``simple_server_retry_responses`` is set to 404.
+
 .. _parent-config-format-unavailable-server-retry-responses:
 
 ``unavailable_server_retry_responses``
diff --git a/proxy/ParentSelection.cc b/proxy/ParentSelection.cc
index 2589ce9..1b6a861 100644
--- a/proxy/ParentSelection.cc
+++ b/proxy/ParentSelection.cc
@@ -350,6 +350,33 @@ 
UnavailableServerResponseCodes::UnavailableServerResponseCodes(char *val)
   std::sort(codes.begin(), codes.end());
 }
 
+SimpleRetryResponseCodes::SimpleRetryResponseCodes(char *val)
+{
+  Tokenizer pTok(", \t\r");
+  int numTok = 0, c;
+
+  if (val == nullptr) {
+    Warning("SimpleRetryResponseCodes - simple_server_retry_responses is null 
loading default 404 code.");
+    codes.push_back(HTTP_STATUS_NOT_FOUND);
+    return;
+  }
+  numTok = pTok.Initialize(val, SHARE_TOKS);
+  if (numTok == 0) {
+    c = atoi(val);
+    if (c > 399 && c < 500) {
+      codes.push_back(HTTP_STATUS_NOT_FOUND);
+    }
+  }
+  for (int i = 0; i < numTok; i++) {
+    c = atoi(pTok[i]);
+    if (c > 399 && c < 500) {
+      Debug("parent_select", "loading simple response code: %d", c);
+      codes.push_back(c);
+    }
+  }
+  std::sort(codes.begin(), codes.end());
+}
+
 void
 ParentRecord::PreProcessParents(const char *val, const int line_num, char 
*buf, size_t len)
 {
@@ -694,6 +721,9 @@ ParentRecord::Init(matcher_line *line_info)
     } else if (strcasecmp(label, "unavailable_server_retry_responses") == 0 && 
unavailable_server_retry_responses == nullptr) {
       unavailable_server_retry_responses = new 
UnavailableServerResponseCodes(val);
       used                               = true;
+    } else if (strcasecmp(label, "simple_server_retry_responses") == 0 && 
simple_server_retry_responses == nullptr) {
+      simple_server_retry_responses = new SimpleRetryResponseCodes(val);
+      used                          = true;
     } else if (strcasecmp(label, "max_simple_retries") == 0) {
       int v = atoi(val);
       if (v >= 1 && v < MAX_SIMPLE_RETRIES) {
@@ -750,6 +780,18 @@ ParentRecord::Init(matcher_line *line_info)
     unavailable_server_retry_responses = new 
UnavailableServerResponseCodes(nullptr);
   }
 
+  // delete simple_server_retry_responses if simple_retry is not enabled.
+  if (simple_server_retry_responses != nullptr && !(parent_retry & 
PARENT_RETRY_SIMPLE)) {
+    Warning("%s ignore simple_server_Retry_responses directive on line %d, as 
simple_server_retry is not enabled.", modulePrefix,
+            line_num);
+    delete simple_server_retry_responses;
+    simple_server_retry_responses = nullptr;
+  } else if (simple_server_retry_responses == nullptr && (parent_retry & 
PARENT_RETRY_SIMPLE)) {
+    // initialize simple server respones codes to the default value if 
simple_retry is enabled.
+    Warning("%s initializing SimpleRetryResponseCodes on line %d to 404 
default.", modulePrefix, line_num);
+    simple_server_retry_responses = new SimpleRetryResponseCodes(nullptr);
+  }
+
   if (this->parents == nullptr && go_direct == false) {
     return Result::failure("%s No parent specified in %s at line %d", 
modulePrefix, ts::filename::PARENT, line_num);
   }
diff --git a/proxy/ParentSelection.h b/proxy/ParentSelection.h
index 7d1d621..1e46485 100644
--- a/proxy/ParentSelection.h
+++ b/proxy/ParentSelection.h
@@ -92,6 +92,19 @@ private:
   std::vector<int> codes;
 };
 
+struct SimpleRetryResponseCodes {
+  SimpleRetryResponseCodes(char *val);
+  ~SimpleRetryResponseCodes(){};
+
+  bool
+  contains(int code)
+  {
+    return binary_search(codes.begin(), codes.end(), code);
+  }
+
+private:
+  std::vector<int> codes;
+};
 // struct pRecord
 //
 //    A record for an individual parent
@@ -145,6 +158,7 @@ public:
   bool parent_is_proxy                                               = true;
   ParentSelectionStrategy *selection_strategy                        = nullptr;
   UnavailableServerResponseCodes *unavailable_server_retry_responses = nullptr;
+  SimpleRetryResponseCodes *simple_server_retry_responses            = nullptr;
   ParentRetry_t parent_retry                                         = 
PARENT_RETRY_NONE;
   int max_simple_retries                                             = 1;
   int max_unavailable_server_retries                                 = 1;
@@ -242,7 +256,20 @@ struct ParentResult {
   bool
   response_is_retryable(HTTPStatus response_code) const
   {
-    return (retry_type() & PARENT_RETRY_UNAVAILABLE_SERVER) && 
rec->unavailable_server_retry_responses->contains(response_code);
+    Debug("parent_select", "In response_is_retryable, code: %d", 
response_code);
+    if (retry_type() == PARENT_RETRY_BOTH) {
+      Debug("parent_select", "Saw retry both");
+      return (rec->unavailable_server_retry_responses->contains(response_code) 
||
+              rec->simple_server_retry_responses->contains(response_code));
+    } else if (retry_type() == PARENT_RETRY_UNAVAILABLE_SERVER) {
+      Debug("parent_select", "Saw retry unavailable server");
+      return rec->unavailable_server_retry_responses->contains(response_code);
+    } else if (retry_type() == PARENT_RETRY_SIMPLE) {
+      Debug("parent_select", "Saw retry simple retry");
+      return rec->simple_server_retry_responses->contains(response_code);
+    } else {
+      return false;
+    }
   }
 
   bool
diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc
index 8bfa521..d9997cd 100644
--- a/proxy/http/HttpTransact.cc
+++ b/proxy/http/HttpTransact.cc
@@ -280,6 +280,26 @@ is_localhost(const char *name, int len)
   return (len == (sizeof(local) - 1)) && (memcmp(name, local, len) == 0);
 }
 
+inline static bool
+is_response_simple_code(HTTPStatus response_code)
+{
+  if (static_cast<unsigned int>(response_code) < 400 || static_cast<unsigned 
int>(response_code) > 499) {
+    return false;
+  }
+
+  return true;
+}
+
+inline static bool
+is_response_unavailable_code(HTTPStatus response_code)
+{
+  if (static_cast<unsigned int>(response_code) < 500 || static_cast<unsigned 
int>(response_code) > 599) {
+    return false;
+  }
+
+  return true;
+}
+
 inline static void
 simple_or_unavailable_server_retry(HttpTransact::State *s)
 {
@@ -288,11 +308,10 @@ simple_or_unavailable_server_retry(HttpTransact::State *s)
 
   TxnDebug("http_trans", "[simple_or_unavailabe_server_retry] server_response 
= %d, simple_retry_attempts: %d, numParents:%d ",
            server_response, s->current.simple_retry_attempts, numParents(s));
-
   // simple retry is enabled, 0x1
-  if ((retry_type(s) & PARENT_RETRY_SIMPLE) && 
s->current.simple_retry_attempts < max_retries(s, PARENT_RETRY_SIMPLE) &&
-      server_response == HTTP_STATUS_NOT_FOUND) {
-    TxnDebug("http_trans", "RECEIVED A SIMPLE RETRY RESPONSE");
+  if ((retry_type(s) & PARENT_RETRY_SIMPLE) && 
is_response_simple_code(server_response) &&
+      s->current.simple_retry_attempts < max_retries(s, PARENT_RETRY_SIMPLE) 
&& response_is_retryable(s, server_response)) {
+    TxnDebug("parent_select", "RECEIVED A SIMPLE RETRY RESPONSE");
     if (s->current.simple_retry_attempts < numParents(s)) {
       s->current.state      = HttpTransact::PARENT_RETRY;
       s->current.retry_type = PARENT_RETRY_SIMPLE;
@@ -303,7 +322,7 @@ simple_or_unavailable_server_retry(HttpTransact::State *s)
     }
   }
   // unavailable server retry is enabled 0x2
-  else if ((retry_type(s) & PARENT_RETRY_UNAVAILABLE_SERVER) &&
+  else if ((retry_type(s) & PARENT_RETRY_UNAVAILABLE_SERVER) && 
is_response_unavailable_code(server_response) &&
            s->current.unavailable_server_retry_attempts < max_retries(s, 
PARENT_RETRY_UNAVAILABLE_SERVER) &&
            response_is_retryable(s, server_response)) {
     TxnDebug("parent_select", "RECEIVED A PARENT_RETRY_UNAVAILABLE_SERVER 
RESPONSE");

Reply via email to