Repository: trafficserver Updated Branches: refs/heads/master 596512ecf -> 5f251bdf2
TS-4030: Allow parent selection to ignore query string This closes #369. Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/5f251bdf Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/5f251bdf Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/5f251bdf Branch: refs/heads/master Commit: 5f251bdf293dc6b59e362d5ea81fe2fc7dc4d489 Parents: 596512e Author: Phil Sorber <[email protected]> Authored: Thu Nov 19 10:32:55 2015 -0700 Committer: Phil Sorber <[email protected]> Committed: Mon Dec 14 12:37:05 2015 -0700 ---------------------------------------------------------------------- lib/ts/ConsistentHash.cc | 29 +++++++++++- lib/ts/ConsistentHash.h | 1 + proxy/ParentSelection.cc | 106 +++++++++++++++++++++++++++--------------- proxy/ParentSelection.h | 7 ++- 4 files changed, 104 insertions(+), 39 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5f251bdf/lib/ts/ConsistentHash.cc ---------------------------------------------------------------------- diff --git a/lib/ts/ConsistentHash.cc b/lib/ts/ConsistentHash.cc index 461c39f..9acbab6 100644 --- a/lib/ts/ConsistentHash.cc +++ b/lib/ts/ConsistentHash.cc @@ -106,7 +106,6 @@ ATSConsistentHash::lookup(const char *url, ATSConsistentHashIter *i, bool *w, AT *wptr = true; *iter = NodeMap.begin(); } - } else { (*iter)++; } @@ -179,6 +178,34 @@ ATSConsistentHash::lookup_available(const char *url, ATSConsistentHashIter *i, b return (*iter)->second; } +ATSConsistentHashNode * +ATSConsistentHash::lookup_by_hashval(uint64_t hashval, ATSConsistentHashIter *i, bool *w) +{ + ATSConsistentHashIter NodeMapIterUp, *iter; + bool *wptr, wrapped = false; + + if (w) { + wptr = w; + } else { + wptr = &wrapped; + } + + if (i) { + iter = i; + } else { + iter = &NodeMapIterUp; + } + + *iter = NodeMap.lower_bound(hashval); + + if (*iter == NodeMap.end()) { + *wptr = true; + *iter = NodeMap.begin(); + } + + return (*iter)->second; +} + ATSConsistentHash::~ATSConsistentHash() { if (hash) { http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5f251bdf/lib/ts/ConsistentHash.h ---------------------------------------------------------------------- diff --git a/lib/ts/ConsistentHash.h b/lib/ts/ConsistentHash.h index 1440b23..d1a34ba 100644 --- a/lib/ts/ConsistentHash.h +++ b/lib/ts/ConsistentHash.h @@ -52,6 +52,7 @@ struct ATSConsistentHash { ATSConsistentHashNode *lookup(const char *url = NULL, ATSConsistentHashIter *i = NULL, bool *w = NULL, ATSHash64 *h = NULL); ATSConsistentHashNode *lookup_available(const char *url = NULL, ATSConsistentHashIter *i = NULL, bool *w = NULL, ATSHash64 *h = NULL); + ATSConsistentHashNode *lookup_by_hashval(uint64_t hashval, ATSConsistentHashIter *i = NULL, bool *w = NULL); ~ATSConsistentHash(); private: http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5f251bdf/proxy/ParentSelection.cc ---------------------------------------------------------------------- diff --git a/proxy/ParentSelection.cc b/proxy/ParentSelection.cc index 9000982..69ce74c 100644 --- a/proxy/ParentSelection.cc +++ b/proxy/ParentSelection.cc @@ -472,6 +472,34 @@ ParentConfigParams::nextParent(HttpRequestData *rdata, ParentResult *result) // End API functions // +uint64_t +ParentRecord::getPathHash(HttpRequestData *hrdata, ATSHash64 *h) +{ + const char *tmp = NULL; + int len; + URL *url = hrdata->hdr->url_get(); + + // Always hash on '/' because paths returned by ATS are always stripped of it + h->update("/", 1); + + tmp = url->path_get(&len); + if (tmp) { + h->update(tmp, len); + } + + if (!ignore_query) { + tmp = url->query_get(&len); + if (tmp) { + h->update("?", 1); + h->update(tmp, len); + } + } + + h->final(); + + return h->get(); +} + void ParentRecord::FindParent(bool first_call, ParentResult *result, RequestData *rdata, ParentConfigParams *config) { @@ -480,29 +508,23 @@ ParentRecord::FindParent(bool first_call, ParentResult *result, RequestData *rda bool parentUp = false; bool parentRetry = false; bool bypass_ok = (go_direct == true && config->DNS_ParentOnly == 0); - char *url, *path = NULL; + uint64_t path_hash; + ATSHash64Sip24 hash; pRecord *prtmp = NULL; - HttpRequestData *request_info = (HttpRequestData *)rdata; + HttpRequestData *request_info = static_cast<HttpRequestData *>(rdata); ink_assert(num_parents > 0 || go_direct == true); - if (first_call == true) { + if (first_call) { if (parents == NULL) { // We should only get into this state if - // if we are supposed to go dirrect + // if we are supposed to go direct ink_assert(go_direct == true); goto NO_PARENTS; - } else if (round_robin == true) { - cur_index = ink_atomic_increment((int32_t *)&rr_next, 1); - cur_index = result->start_parent = cur_index % num_parents; } else { switch (round_robin) { - case P_STRICT_ROUND_ROBIN: - cur_index = ink_atomic_increment((int32_t *)&rr_next, 1); - cur_index = cur_index % num_parents; - break; case P_HASH_ROUND_ROBIN: // INKqa12817 - make sure to convert to host byte order // Why was it important to do host order here? And does this have any @@ -516,24 +538,24 @@ ParentRecord::FindParent(bool first_call, ParentResult *result, RequestData *rda } break; case P_CONSISTENT_HASH: - url = rdata->get_string(); - path = strstr(url + 7, "/"); - if (path) { - prtmp = (pRecord *)chash->lookup(path, &(result->chashIter), NULL, (ATSHash64 *)&hash); + path_hash = getPathHash(request_info, (ATSHash64 *)&hash); + if (path_hash) { + prtmp = (pRecord *)chash->lookup_by_hashval(path_hash, &result->chashIter, &result->wrap_around); if (prtmp) { cur_index = prtmp->idx; result->foundParents[cur_index] = true; result->start_parent++; + break; } else { Error("Consistent Hash loopup returned NULL"); - cur_index = ink_atomic_increment((int32_t *)&rr_next, 1); - cur_index = cur_index % num_parents; } } else { - Error("Could not find path in URL: %s", url); - cur_index = ink_atomic_increment((int32_t *)&rr_next, 1); - cur_index = cur_index % num_parents; + Error("Could not find path"); } + // Fall through to round robin + case P_STRICT_ROUND_ROBIN: + cur_index = ink_atomic_increment((int32_t *)&rr_next, 1); + cur_index = cur_index % num_parents; break; case P_NO_ROUND_ROBIN: cur_index = result->start_parent = 0; @@ -544,22 +566,26 @@ ParentRecord::FindParent(bool first_call, ParentResult *result, RequestData *rda } } else { if (round_robin == P_CONSISTENT_HASH) { + Debug("parent_select", "result->start_parent=%d, num_parents=%d", result->start_parent, num_parents); if (result->start_parent == (unsigned int)num_parents) { result->wrap_around = true; result->start_parent = 0; memset(result->foundParents, 0, sizeof(result->foundParents)); - url = rdata->get_string(); - path = strstr(url + 7, "/"); } do { - prtmp = (pRecord *)chash->lookup(path, &(result->chashIter), NULL, (ATSHash64 *)&hash); - path = NULL; - } while (result->foundParents[prtmp->idx]); + prtmp = (pRecord *)chash->lookup(NULL, &result->chashIter, &result->wrap_around, &hash); + } while (prtmp && result->foundParents[prtmp->idx]); - cur_index = prtmp->idx; - result->foundParents[cur_index] = true; - result->start_parent++; + if (prtmp) { + cur_index = prtmp->idx; + result->foundParents[cur_index] = true; + result->start_parent++; + } else { + Error("Consistent Hash loopup returned NULL"); + cur_index = ink_atomic_increment((int32_t *)&rr_next, 1); + cur_index = cur_index % num_parents; + } } else { // Move to next parent due to failure cur_index = (result->last_parent + 1) % num_parents; @@ -598,7 +624,6 @@ ParentRecord::FindParent(bool first_call, ParentResult *result, RequestData *rda parentUp = true; parentRetry = true; Debug("parent_select", "Parent marked for retry %s:%d", parents[cur_index].hostname, parents[cur_index].port); - } else { parentUp = false; } @@ -621,18 +646,17 @@ ParentRecord::FindParent(bool first_call, ParentResult *result, RequestData *rda result->wrap_around = false; result->start_parent = 0; memset(result->foundParents, 0, sizeof(result->foundParents)); - url = rdata->get_string(); - path = strstr(url + 7, "/"); } do { - prtmp = (pRecord *)chash->lookup(path, &(result->chashIter), NULL, (ATSHash64 *)&hash); - path = NULL; - } while (result->foundParents[prtmp->idx]); + prtmp = (pRecord *)chash->lookup(NULL, &(result->chashIter), &result->wrap_around, &hash); + } while (prtmp && result->foundParents[prtmp->idx]); - cur_index = prtmp->idx; - result->foundParents[cur_index] = true; - result->start_parent++; + if (prtmp) { + cur_index = prtmp->idx; + result->foundParents[cur_index] = true; + result->start_parent++; + } } else { cur_index = (cur_index + 1) % num_parents; } @@ -784,6 +808,7 @@ ParentRecord::DefaultInit(char *val) this->go_direct = true; this->round_robin = P_NO_ROUND_ROBIN; + this->ignore_query = false; this->scheme = NULL; errPtr = ProcessParents(val); @@ -877,6 +902,13 @@ ParentRecord::Init(matcher_line *line_info) go_direct = true; } used = true; + } else if (strcasecmp(label, "qstring") == 0) { + // qstring=ignore | consider + if (strcasecmp(val, "ignore") == 0) { + this->ignore_query = true; + } else { + this->ignore_query = false; + } } // Report errors generated by ProcessParents(); if (errPtr != NULL) { http://git-wip-us.apache.org/repos/asf/trafficserver/blob/5f251bdf/proxy/ParentSelection.h ---------------------------------------------------------------------- diff --git a/proxy/ParentSelection.h b/proxy/ParentSelection.h index a74b659..8dc428c 100644 --- a/proxy/ParentSelection.h +++ b/proxy/ParentSelection.h @@ -195,7 +195,10 @@ enum ParentRR_t { class ParentRecord : public ControlBase { public: - ParentRecord() : parents(NULL), num_parents(0), round_robin(P_NO_ROUND_ROBIN), rr_next(0), go_direct(true), chash(NULL) {} + ParentRecord() + : parents(NULL), num_parents(0), round_robin(P_NO_ROUND_ROBIN), ignore_query(false), rr_next(0), go_direct(true), chash(NULL) + { + } ~ParentRecord(); @@ -203,6 +206,7 @@ public: bool DefaultInit(char *val); void UpdateMatch(ParentResult *result, RequestData *rdata); void FindParent(bool firstCall, ParentResult *result, RequestData *rdata, ParentConfigParams *config); + uint64_t getPathHash(HttpRequestData *hrdata, ATSHash64 *h); void Print(); pRecord *parents; int num_parents; @@ -218,6 +222,7 @@ public: const char *ProcessParents(char *val); void buildConsistentHash(void); ParentRR_t round_robin; + bool ignore_query; volatile uint32_t rr_next; bool go_direct; ATSConsistentHash *chash;
