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 2018/08/13 18:18:09 UTC

[trafficserver] 01/02: Add feature to use modified cache-key-url for parent selection.

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

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

commit 325b99237efddb04113f5e385d4d76440a2ae4b6
Author: Jeffrey Bevill <Je...@comcast.com>
AuthorDate: Tue Jul 3 20:32:46 2018 +0000

    Add feature to use modified cache-key-url for parent selection.
    
    (cherry picked from commit 148d9897cbbc5d2d95b18d624ed29a6cb5e3ab8d)
---
 plugins/experimental/cache_range_requests/README   |  20 ++++
 .../cache_range_requests/cache_range_requests.cc   | 133 +++++++++++++++++++--
 2 files changed, 140 insertions(+), 13 deletions(-)

diff --git a/plugins/experimental/cache_range_requests/README b/plugins/experimental/cache_range_requests/README
index 18a88c6..4844156 100644
--- a/plugins/experimental/cache_range_requests/README
+++ b/plugins/experimental/cache_range_requests/README
@@ -34,3 +34,23 @@ Configuration:
     Or for a global plugin where all range requests are processed,
     Add cache_range_requests.so to the plugin.config
 
+Parent Selection Mode (consisent-hash only):
+  
+    default: Parent selection is based solely on the hash of a URL Path
+             In this mode, all partial content of a URL is requested from the same 
+             upstream parent cache listed in parent.config
+             
+    cache_key_url: Parent selection is based on the full cache_key_url which 
+                   includes information about the partial content range.
+                   In this mode, all requests (include partial content) will use
+                   consistent hashing method for parent selection. 
+
+    To enable cache_key_url parent select mode, the following param must be set:
+
+    Global Plugin (plugin.config):
+  
+      cache_range_requests.so ps_mode:cache_key_url
+
+    Remap Plugin (remap.config):
+      
+      <from-url> <to-url> @plugin=cache_range_requests.so @pparam=ps_mode:cache_key_url
diff --git a/plugins/experimental/cache_range_requests/cache_range_requests.cc b/plugins/experimental/cache_range_requests/cache_range_requests.cc
index 14bbe57..b0b61ec 100644
--- a/plugins/experimental/cache_range_requests/cache_range_requests.cc
+++ b/plugins/experimental/cache_range_requests/cache_range_requests.cc
@@ -35,18 +35,76 @@
 #define DEBUG_LOG(fmt, ...) TSDebug(PLUGIN_NAME, "[%s:%d] %s(): " fmt, __FILE__, __LINE__, __func__, ##__VA_ARGS__)
 #define ERROR_LOG(fmt, ...) TSError("[%s:%d] %s(): " fmt, __FILE__, __LINE__, __func__, ##__VA_ARGS__)
 
+typedef enum parent_select_mode {
+  PS_DEFAULT,      // Default ATS parent selection mode
+  PS_CACHEKEY_URL, // Set parent selection url to cache_key url
+} parent_select_mode_t;
+
+struct pluginconfig {
+  parent_select_mode_t ps_mode;
+};
+
 struct txndata {
   char *range_value;
 };
 
 static int handle_read_request_header(TSCont, TSEvent, void *);
-static void range_header_check(TSHttpTxn txnp);
+static void range_header_check(TSHttpTxn txnp, struct pluginconfig *pc);
 static void handle_send_origin_request(TSCont, TSHttpTxn, struct txndata *);
 static void handle_client_send_response(TSHttpTxn, struct txndata *);
 static void handle_server_read_response(TSHttpTxn, struct txndata *);
 static int remove_header(TSMBuffer, TSMLoc, const char *, int);
 static bool set_header(TSMBuffer, TSMLoc, const char *, int, const char *, int);
 static int transaction_handler(TSCont, TSEvent, void *);
+static struct pluginconfig *create_pluginconfig(int argc, const char *argv[]);
+static void delete_pluginconfig(struct pluginconfig *);
+
+// pluginconfig struct (global plugin only)
+static struct pluginconfig *gPluginConfig = nullptr;
+
+/**
+ * Creates pluginconfig data structure
+ * Sets default parent url selection mode
+ * Walk plugin argument list and updates config
+ */
+static struct pluginconfig *
+create_pluginconfig(int argc, const char *argv[])
+{
+  struct pluginconfig *pc = nullptr;
+
+  pc = (struct pluginconfig *)TSmalloc(sizeof(struct pluginconfig));
+
+  if (nullptr == pc) {
+    ERROR_LOG("Can't allocate pluginconfig");
+    return nullptr;
+  }
+
+  // Plugin uses default ATS selection (hash of URL path)
+  pc->ps_mode = PS_DEFAULT;
+
+  // Walk through param list.
+  for (int c = 0; c < argc; c++) {
+    if (strcmp("ps_mode:cache_key_url", argv[c]) == 0) {
+      pc->ps_mode = PS_CACHEKEY_URL;
+      break;
+    }
+  }
+
+  return pc;
+}
+
+/**
+ * Destroy pluginconfig data stucture.
+ */
+static void
+delete_pluginconfig(struct pluginconfig *pc)
+{
+  if (nullptr != pc) {
+    DEBUG_LOG("Delete struct pluginconfig");
+    TSfree(pc);
+    pc = nullptr;
+  }
+}
 
 /**
  * Entry point when used as a global plugin.
@@ -57,7 +115,7 @@ handle_read_request_header(TSCont txn_contp, TSEvent event, void *edata)
 {
   TSHttpTxn txnp = static_cast<TSHttpTxn>(edata);
 
-  range_header_check(txnp);
+  range_header_check(txnp, gPluginConfig);
 
   TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
   return 0;
@@ -74,11 +132,11 @@ handle_read_request_header(TSCont txn_contp, TSEvent event, void *edata)
  *    and TS_HTTP_TXN_CLOSE_HOOK for further processing.
  */
 static void
-range_header_check(TSHttpTxn txnp)
+range_header_check(TSHttpTxn txnp, struct pluginconfig *pc)
 {
   char cache_key_url[8192] = {0};
   char *req_url;
-  int length, url_length;
+  int length, url_length, cache_key_url_length;
   struct txndata *txn_state;
   TSMBuffer hdr_bufp;
   TSMLoc req_hdrs = nullptr;
@@ -92,7 +150,7 @@ range_header_check(TSHttpTxn txnp)
       if (!hdr_value || length <= 0) {
         DEBUG_LOG("Not a range request.");
       } else {
-        if (nullptr == (txn_contp = TSContCreate(transaction_handler, nullptr))) {
+        if (nullptr == (txn_contp = TSContCreate((TSEventFunc)transaction_handler, nullptr))) {
           ERROR_LOG("failed to create the transaction handler continuation.");
         } else {
           txn_state              = (struct txndata *)TSmalloc(sizeof(struct txndata));
@@ -100,17 +158,34 @@ range_header_check(TSHttpTxn txnp)
           DEBUG_LOG("length: %d, txn_state->range_value: %s", length, txn_state->range_value);
           txn_state->range_value[length] = '\0'; // workaround for bug in core
 
-          req_url = TSHttpTxnEffectiveUrlStringGet(txnp, &url_length);
-          snprintf(cache_key_url, 8192, "%s-%s", req_url, txn_state->range_value);
+          req_url              = TSHttpTxnEffectiveUrlStringGet(txnp, &url_length);
+          cache_key_url_length = snprintf(cache_key_url, 8192, "%s-%s", req_url, txn_state->range_value);
           DEBUG_LOG("Rewriting cache URL for %s to %s", req_url, cache_key_url);
           if (req_url != nullptr) {
             TSfree(req_url);
           }
 
           // set the cache key.
-          if (TS_SUCCESS != TSCacheUrlSet(txnp, cache_key_url, strlen(cache_key_url))) {
+          if (TS_SUCCESS != TSCacheUrlSet(txnp, cache_key_url, cache_key_url_length)) {
             DEBUG_LOG("failed to change the cache url to %s.", cache_key_url);
           }
+
+          // Optionally set the parent_selection_url to the cache_key url or path
+          if (nullptr != pc && PS_DEFAULT != pc->ps_mode) {
+            TSMLoc ps_loc = nullptr;
+
+            if (PS_CACHEKEY_URL == pc->ps_mode) {
+              const char *start = cache_key_url;
+              const char *end   = cache_key_url + cache_key_url_length;
+              if (TS_SUCCESS == TSUrlCreate(hdr_bufp, &ps_loc) &&
+                  TS_PARSE_DONE == TSUrlParse(hdr_bufp, ps_loc, &start, end) && // This should always succeed.
+                  TS_SUCCESS == TSHttpTxnParentSelectionUrlSet(txnp, hdr_bufp, ps_loc)) {
+                DEBUG_LOG("Set Parent Selection URL to cache_key_url: %s", cache_key_url);
+                TSHandleMLocRelease(hdr_bufp, TS_NULL_MLOC, ps_loc);
+              }
+            }
+          }
+
           // remove the range request header.
           if (remove_header(hdr_bufp, req_hdrs, TS_MIME_FIELD_RANGE, TS_MIME_LEN_RANGE) > 0) {
             DEBUG_LOG("Removed the Range: header from the request.");
@@ -325,21 +400,41 @@ TSRemapInit(TSRemapInterface *api_info, char *errbuf, int errbuf_size)
 }
 
 /**
- * not used.
+ * New Remap instance
  */
 TSReturnCode
 TSRemapNewInstance(int argc, char *argv[], void **ih, char * /*errbuf */, int /* errbuf_size */)
 {
+  if (argc < 2) {
+    ERROR_LOG("Remap argument list should contain at least 2 params"); // Should never happen..
+    return TS_ERROR;
+  }
+
+  // Skip over the Remap params
+  const char **plugin_argv = const_cast<const char **>(argv + 2);
+  argc -= 2;
+
+  // Parse the argument list.
+  *ih = (struct pluginconfig *)create_pluginconfig(argc, plugin_argv);
+
+  if (*ih == nullptr) {
+    ERROR_LOG("Can't create pluginconfig");
+  }
+
   return TS_SUCCESS;
 }
 
 /**
- * not used.
+ * Delete Remap instance
  */
 void
 TSRemapDeleteInstance(void *ih)
 {
-  DEBUG_LOG("no op");
+  struct pluginconfig *pc = (struct pluginconfig *)ih;
+
+  if (nullptr != pc) {
+    delete_pluginconfig(pc);
+  }
 }
 
 /**
@@ -348,7 +443,10 @@ TSRemapDeleteInstance(void *ih)
 TSRemapStatus
 TSRemapDoRemap(void *ih, TSHttpTxn txnp, TSRemapRequestInfo * /* rri */)
 {
-  range_header_check(txnp);
+  struct pluginconfig *pc = (struct pluginconfig *)ih;
+
+  range_header_check(txnp, pc);
+
   return TSREMAP_NO_REMAP;
 }
 
@@ -371,7 +469,16 @@ TSPluginInit(int argc, const char *argv[])
     return;
   }
 
-  if (nullptr == (txnp_cont = TSContCreate(handle_read_request_header, nullptr))) {
+  if (nullptr == gPluginConfig) {
+    if (argc > 1) {
+      // Skip ahead of first param (name of traffic server plugin shared object)
+      const char **plugin_argv = const_cast<const char **>(argv + 1);
+      argc -= 1;
+      gPluginConfig = create_pluginconfig(argc, plugin_argv);
+    }
+  }
+
+  if (nullptr == (txnp_cont = TSContCreate((TSEventFunc)handle_read_request_header, nullptr))) {
     ERROR_LOG("failed to create the transaction continuation handler.");
     return;
   } else {