You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by su...@apache.org on 2014/09/23 01:46:18 UTC

git commit: [TS-2314] - New config to allow unsatifiable Range: request to go straight to Origin

Repository: trafficserver
Updated Branches:
  refs/heads/master 2b64392d8 -> 15d3887b0


[TS-2314] - New config to allow unsatifiable Range: request to go straight to Origin


Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/15d3887b
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/15d3887b
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/15d3887b

Branch: refs/heads/master
Commit: 15d3887b03a3f8e70436cd995a3ada0963a77423
Parents: 2b64392
Author: Sudheer Vinukonda <su...@yahoo-inc.com>
Authored: Mon Sep 22 23:45:42 2014 +0000
Committer: Sudheer Vinukonda <su...@yahoo-inc.com>
Committed: Mon Sep 22 23:45:42 2014 +0000

----------------------------------------------------------------------
 .../configuration/records.config.en.rst         | 17 ++++-
 proxy/http/HttpSM.cc                            | 70 ++++++++++++++------
 proxy/http/HttpSM.h                             |  1 +
 proxy/http/HttpTransact.cc                      |  4 +-
 proxy/http/HttpTransact.h                       |  4 +-
 5 files changed, 71 insertions(+), 25 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/trafficserver/blob/15d3887b/doc/reference/configuration/records.config.en.rst
----------------------------------------------------------------------
diff --git a/doc/reference/configuration/records.config.en.rst b/doc/reference/configuration/records.config.en.rst
index cec4de6..defcefe 100644
--- a/doc/reference/configuration/records.config.en.rst
+++ b/doc/reference/configuration/records.config.en.rst
@@ -1086,8 +1086,21 @@ Cache Control
 .. ts:cv:: CONFIG proxy.config.cache.enable_read_while_writer INT 1
    :reloadable:
 
-   Enables (``1``) or disables (``0``) ability to a read cached object while the another connection is completing the write to cache for
-   the same object. Several other configuration values need to be set for this to become active. See :ref:`reducing-origin-server-requests-avoiding-the-thundering-herd`
+   Specifies when to enable the ability to read a cached object while another
+   connection is completing the write to cache for that same object. The goal
+   here is to avoid multiple origin connections for the same cacheable object
+   upon a cache miss. The possible values of this config are:
+
+   -  ``0`` = never allow
+   -  ``1`` = always allowed
+   -  ``2`` = allowed, only if the ``Range`` requested can be satisfied from cache
+
+   The ``2`` option is useful to avoid delaying requests which can not easily
+   be satisfied by the partially written response.
+
+   Several other configuration values need to be set for this to be
+   usable. See :ref:`Reducing Origin Server Requests
+   <http-proxy-caching.en.html#reducing-origin-server-requests-avoiding-the-thundering-herd>`.
 
 .. ts:cv:: CONFIG proxy.config.cache.force_sector_size INT 0
    :reloadable:

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/15d3887b/proxy/http/HttpSM.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpSM.cc b/proxy/http/HttpSM.cc
index 166cb7e..7d44149 100644
--- a/proxy/http/HttpSM.cc
+++ b/proxy/http/HttpSM.cc
@@ -327,7 +327,8 @@ HttpSM::HttpSM()
     pushed_response_hdr_bytes(0), pushed_response_body_bytes(0),
     plugin_tag(0), plugin_id(0),
     hooks_set(false), cur_hook_id(TS_HTTP_LAST_HOOK), cur_hook(NULL),
-    cur_hooks(0), callout_state(HTTP_API_NO_CALLOUT), terminate_sm(false), kill_this_async_done(false)
+    cur_hooks(0), callout_state(HTTP_API_NO_CALLOUT), terminate_sm(false),
+    kill_this_async_done(false), parse_range_done(false)
 {
   static int scatter_init = 0;
 
@@ -4114,6 +4115,12 @@ HttpSM::parse_range_and_compare(MIMEField *field, int64_t content_length)
     return;
   }
 
+  if (parse_range_done) {
+    Debug("http_range", "parse_range already done, t_state.range_setup %d", t_state.range_setup);
+    return;
+  }
+  parse_range_done = true;
+
   n_values = 0;
   value = csv.get_first(field, &value_len);
   while (value) {
@@ -4129,6 +4136,9 @@ HttpSM::parse_range_and_compare(MIMEField *field, int64_t content_length)
   value += 6; // skip leading 'bytes='
   value_len -= 6;
 
+  // assume range_in_cache
+  t_state.range_in_cache = true;
+
   for (; value; value = csv.get_next(&value_len)) {
     if (!(tmp = (const char *) memchr(value, '-', value_len))) {
       t_state.range_setup = HttpTransact::RANGE_NONE;
@@ -4211,6 +4221,17 @@ HttpSM::parse_range_and_compare(MIMEField *field, int64_t content_length)
     ranges[nr]._start = start;
     ranges[nr]._end = end;
     ++nr;
+
+    if (!cache_sm.cache_read_vc->is_pread_capable() && cache_config_read_while_writer==2) {
+      // write in progress, check if request range not in cache yet
+      HTTPInfo::FragOffset* frag_offset_tbl = t_state.cache_info.object_read->get_frag_table();
+      int frag_offset_cnt = t_state.cache_info.object_read->get_frag_offset_count();
+
+      if (!frag_offset_tbl || (frag_offset_tbl[frag_offset_cnt - 1] < end)) {
+        Debug("http_range", "request range in cache, end %" PRId64 ", frg_offset_cnt %d, frag_size %" PRId64, end, frag_offset_cnt, frag_offset_tbl[frag_offset_cnt - 1]);
+        t_state.range_in_cache = false;
+      }
+    }
   }
 
   if (nr > 0) {
@@ -4224,6 +4245,7 @@ HttpSM::parse_range_and_compare(MIMEField *field, int64_t content_length)
     t_state.range_setup = HttpTransact::RANGE_NOT_SATISFIABLE;
 
 Lfaild:
+  t_state.range_in_cache = false;
   t_state.num_range_fields = -1;
   delete []ranges;
   return;
@@ -4295,26 +4317,32 @@ HttpSM::do_range_setup_if_necessary()
   if (t_state.method == HTTP_WKSIDX_GET && t_state.hdr_info.client_request.version_get() == HTTPVersion(1, 1)) {
     do_range_parse(field);
 
-    // if only one range entry and pread is capable, no need transform range
-    if (t_state.range_setup == HttpTransact::RANGE_REQUESTED &&
-        t_state.num_range_fields == 1 &&
-        cache_sm.cache_read_vc->is_pread_capable())
-      t_state.range_setup = HttpTransact::RANGE_NOT_TRANSFORM_REQUESTED;
-
-    if (t_state.range_setup == HttpTransact::RANGE_REQUESTED && 
-        api_hooks.get(TS_HTTP_RESPONSE_TRANSFORM_HOOK) == NULL) {
-      Debug("http_trans", "Unable to accelerate range request, fallback to transform");
-      content_type = t_state.cache_info.object_read->response_get()->value_get(MIME_FIELD_CONTENT_TYPE, MIME_LEN_CONTENT_TYPE, &field_content_type_len);
-      //create a Range: transform processor for requests of type Range: bytes=1-2,4-5,10-100 (eg. multiple ranges)
-      range_trans = transformProcessor.range_transform(mutex,
-          t_state.ranges,
-          t_state.num_range_fields,
-          &t_state.hdr_info.transform_response,
-          content_type,
-          field_content_type_len,
-          t_state.cache_info.object_read->object_size_get()
-          );
-      api_hooks.append(TS_HTTP_RESPONSE_TRANSFORM_HOOK, range_trans);
+    if (t_state.range_setup == HttpTransact::RANGE_REQUESTED) {
+
+      if (!t_state.range_in_cache) {
+        Debug("http_range", "range can't be satisifed from cache, force origin request");
+        t_state.cache_lookup_result = HttpTransact::CACHE_LOOKUP_MISS;
+        return;
+      }
+
+      // if only one range entry and pread is capable, no need transform range
+      if (t_state.num_range_fields == 1 &&
+         (cache_sm.cache_read_vc->is_pread_capable() || t_state.range_in_cache)) {
+        t_state.range_setup = HttpTransact::RANGE_NOT_TRANSFORM_REQUESTED;
+      } else if (api_hooks.get(TS_HTTP_RESPONSE_TRANSFORM_HOOK) == NULL) {
+        Debug("http_trans", "Unable to accelerate range request, fallback to transform");
+        content_type = t_state.cache_info.object_read->response_get()->value_get(MIME_FIELD_CONTENT_TYPE, MIME_LEN_CONTENT_TYPE, &field_content_type_len);
+        //create a Range: transform processor for requests of type Range: bytes=1-2,4-5,10-100 (eg. multiple ranges)
+        range_trans = transformProcessor.range_transform(mutex,
+            t_state.ranges,
+            t_state.num_range_fields,
+            &t_state.hdr_info.transform_response,
+            content_type,
+            field_content_type_len,
+            t_state.cache_info.object_read->object_size_get()
+            );
+        api_hooks.append(TS_HTTP_RESPONSE_TRANSFORM_HOOK, range_trans);
+      }
     }
   }
 }

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/15d3887b/proxy/http/HttpSM.h
----------------------------------------------------------------------
diff --git a/proxy/http/HttpSM.h b/proxy/http/HttpSM.h
index 015a59b..e143ab8 100644
--- a/proxy/http/HttpSM.h
+++ b/proxy/http/HttpSM.h
@@ -520,6 +520,7 @@ protected:
   //   when the flag is set
   bool terminate_sm;
   bool kill_this_async_done;
+  bool parse_range_done;
   virtual int kill_this_async_hook(int event, void *data);
   void kill_this();
   void update_stats();

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/15d3887b/proxy/http/HttpTransact.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpTransact.cc b/proxy/http/HttpTransact.cc
index 568b2d3..293a168 100644
--- a/proxy/http/HttpTransact.cc
+++ b/proxy/http/HttpTransact.cc
@@ -67,6 +67,7 @@ static char range_type[] = "multipart/byteranges; boundary=RANGE_SEPARATOR";
 
 extern HttpBodyFactory *body_factory;
 extern int cache_config_vary_on_user_agent;
+extern int cache_config_read_while_writer;
 
 static const char local_host_ip_str[] = "127.0.0.1";
 
@@ -2863,8 +2864,9 @@ HttpTransact::build_response_from_cache(State* s, HTTPWarningCode warning_code)
           s->cache_info.action = CACHE_DO_NO_ACTION;
           s->next_action = SM_ACTION_INTERNAL_CACHE_NOOP;
           break;
-        } else if (s->range_setup == RANGE_NOT_HANDLED) {
+        } else if ((s->range_setup == RANGE_NOT_HANDLED) || !s->range_in_cache) {
           // we switch to tunneling for Range requests if it is out of order.
+          // or if the range can't be satisfied from the cache
           // In that case we fetch the entire source so it's OK to switch
           // this late.
           DebugTxn("http_seq", "[HttpTransact::HandleCacheOpenReadHit] Out-of-order Range request - tunneling");

http://git-wip-us.apache.org/repos/asf/trafficserver/blob/15d3887b/proxy/http/HttpTransact.h
----------------------------------------------------------------------
diff --git a/proxy/http/HttpTransact.h b/proxy/http/HttpTransact.h
index 59b76ef..f35d0fe 100644
--- a/proxy/http/HttpTransact.h
+++ b/proxy/http/HttpTransact.h
@@ -1017,6 +1017,7 @@ public:
     OverridableHttpConfigParams my_txn_conf; // Storage for plugins, to avoid malloc
 
     bool transparent_passthrough;
+    bool range_in_cache;
     
     // Methods
     void
@@ -1112,7 +1113,8 @@ public:
         range_output_cl(0),
         ranges(NULL),
         txn_conf(NULL),
-        transparent_passthrough(false)
+        transparent_passthrough(false),
+        range_in_cache(false)
     {
       int i;
       char *via_ptr = via_string;