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 {