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 2022/02/17 00:16:13 UTC
[trafficserver] 02/03: Ports #7925 #8365 core to parent_select plugin (#8590)
This is an automated email from the ASF dual-hosted git repository.
zwoop pushed a commit to branch 9.2.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit 9d1d80180ed993f4ae117ab3b5011f142bf76b25
Author: Robert O Butts <ro...@users.noreply.github.com>
AuthorDate: Mon Jan 31 08:57:54 2022 -0700
Ports #7925 #8365 core to parent_select plugin (#8590)
Ports #7925 and #8365 from core strategies to parent_select plugin.
PR #7925 adds go_direct support to peering_ring strategies.
PR #8365 refactors strategy consistent hashing to fix a bug.
They both essentially completely rewrite the strategy consistent
hashing, so it was safer and easier to port them both at the same
time.
Add parent_select plugin autests
Tests are mostly copied from the core strategies tests, which makes
sense since the plugin strategies should behave the same as core.
(cherry picked from commit d7b1154767e120ca07767e82c6f52347977e5e3a)
---
.../experimental/parent_select/consistenthash.cc | 362 +++++----
.../experimental/parent_select/consistenthash.h | 4 +
.../experimental/parent_select/parent_select.cc | 15 +-
plugins/experimental/parent_select/strategy.cc | 39 +-
plugins/experimental/parent_select/strategy.h | 26 +-
.../gold_tests/pluginTest/parent_select/body.gold | 1 +
.../pluginTest/parent_select/parent_select.test.py | 147 ++++
.../parent_select/parent_select_peer.test.py | 177 ++++
.../parent_select/parent_select_peer2.test.py | 172 ++++
.../pluginTest/parent_select/peer.body.gold | 1 +
.../pluginTest/parent_select/peer.trace.gold | 898 +++++++++++++++++++++
.../pluginTest/parent_select/peer2.body.gold | 1 +
.../pluginTest/parent_select/peer2.trace.gold | 804 ++++++++++++++++++
.../gold_tests/pluginTest/parent_select/trace.gold | 96 +++
14 files changed, 2544 insertions(+), 199 deletions(-)
diff --git a/plugins/experimental/parent_select/consistenthash.cc b/plugins/experimental/parent_select/consistenthash.cc
index 00f20e0..dfa1728 100644
--- a/plugins/experimental/parent_select/consistenthash.cc
+++ b/plugins/experimental/parent_select/consistenthash.cc
@@ -54,25 +54,16 @@ constexpr std::string_view hash_key_path_query = "path+query";
constexpr std::string_view hash_key_path_fragment = "path+fragment";
constexpr std::string_view hash_key_cache = "cache_key";
-PLHostRecord *
-chash_lookup(const std::shared_ptr<ATSConsistentHash> &ring, uint64_t hash_key, ATSConsistentHashIter *iter, bool *wrapped,
- ATSHash64Sip24 *hash, bool *hash_init, bool *mapWrapped, uint64_t sm_id)
+static bool
+isWrapped(std::vector<bool> &wrap_around, uint32_t groups)
{
- PLHostRecord *host_rec = nullptr;
-
- if (*hash_init == false) {
- host_rec = static_cast<PLHostRecord *>(ring->lookup_by_hashval(hash_key, iter, wrapped));
- *hash_init = true;
- } else {
- host_rec = static_cast<PLHostRecord *>(ring->lookup(nullptr, iter, wrapped, hash));
- }
- bool wrap_around = *wrapped;
- *wrapped = *mapWrapped && *wrapped;
- if (!*mapWrapped && wrap_around) {
- *mapWrapped = true;
+ bool all_wrapped = true;
+ for (uint32_t c = 0; c < groups; c++) {
+ if (wrap_around[c] == false) {
+ all_wrapped = false;
+ }
}
-
- return host_rec;
+ return all_wrapped;
}
void
@@ -84,6 +75,37 @@ chTxnToStatusTxn(PLNextHopConsistentHashTxn *txn, PLStatusTxn *statusTxn)
} // namespace
+std::shared_ptr<PLHostRecord>
+PLNextHopConsistentHash::chashLookup(const std::shared_ptr<ATSConsistentHash> &ring, uint32_t cur_ring,
+ PLNextHopConsistentHashTxn *state, bool *wrapped, uint64_t sm_id, TSMBuffer reqp, TSMLoc url,
+ TSMLoc parent_selection_url)
+{
+ uint64_t hash_key = 0;
+ ATSHash64Sip24 hash;
+ PLHostRecord *host_rec = nullptr;
+ ATSConsistentHashIter *iter = &state->chashIter[cur_ring];
+
+ if (state->chash_init[cur_ring] == false) {
+ hash_key = getHashKey(sm_id, reqp, url, parent_selection_url, &hash);
+ host_rec = static_cast<PLHostRecord *>(ring->lookup_by_hashval(hash_key, iter, wrapped));
+ state->chash_init[cur_ring] = true;
+ } else {
+ host_rec = static_cast<PLHostRecord *>(ring->lookup(nullptr, iter, wrapped, &hash));
+ }
+ bool wrap_around = *wrapped;
+ *wrapped = (state->mapWrapped[cur_ring] && *wrapped) ? true : false;
+ if (!state->mapWrapped[cur_ring] && wrap_around) {
+ state->mapWrapped[cur_ring] = true;
+ }
+
+ if (host_rec == nullptr) {
+ return nullptr;
+ } else {
+ std::shared_ptr<PLHostRecord> h = host_groups[host_rec->group_index][host_rec->host_index];
+ return h;
+ }
+}
+
PLNextHopConsistentHash::PLNextHopConsistentHash(const std::string_view name) : PLNextHopSelectionStrategy(name) {}
PLNextHopConsistentHash::~PLNextHopConsistentHash()
@@ -163,10 +185,21 @@ PLNextHopConsistentHash::Init(const YAML::Node &n)
}
if (ring_mode == PL_NH_PEERING_RING) {
- if (groups != 2) {
- PL_NH_Error("ring mode is '%s', requires two host groups (peering group and an upstream group).", peering_rings.data());
+ if (groups == 1) {
+ if (!go_direct) {
+ PL_NH_Error("when ring mode is '%s', go_direct must be true when there is only one host group.", peering_rings.data());
+ return false;
+ }
+ } else if (groups != 2) {
+ PL_NH_Error("when ring mode is '%s', requires two host groups (peering group and an upstream group),"
+ " or just a single peering group with go_direct.",
+ peering_rings.data());
return false;
}
+ // if (policy_type != PL_NH_CONSISTENT_HASH) {
+ // PL_NH_Error("ring mode '%s', is only implemented for a 'consistent_hash' policy.", peering_rings.data());
+ // return false;
+ // }
}
return true;
@@ -277,16 +310,6 @@ PLNextHopConsistentHash::deleteTxn(void *txn)
delete static_cast<PLNextHopConsistentHashTxn *>(txn);
}
-// next returns the next parent, excluding exclue_hostname:exclude_port as if it were marked down.
-//
-// exclude_hostname and exclude_port are parents to not consider for the next parent.
-// This exists to allow getting the next parent if a failure occurs, before it occurs,
-// without actually marking it down which would cause other concurrent transactions to use the wrong parent.
-// This is necessary, because there's no plugin hook after a response which is a connection failure. Hacky, but it works.
-// If they aren't needed, pass nullptr for exclude_hostname.
-//
-// out_retry is whether the returned parent was marked down, and is now being retried.
-//
void
PLNextHopConsistentHash::next(TSHttpTxn txnp, void *strategyTxn, const char *exclude_hostname, size_t exclude_hostname_len,
in_port_t exclude_port, const char **out_hostname, size_t *out_hostname_len, in_port_t *out_port,
@@ -297,6 +320,8 @@ PLNextHopConsistentHash::next(TSHttpTxn txnp, void *strategyTxn, const char *exc
PL_NH_Debug(PL_NH_DEBUG_TAG, "nextParent NH plugin calling");
+ uint32_t const NO_RING_USE_POST_REMAP = uint32_t(0) - 1;
+
auto state = static_cast<PLNextHopConsistentHashTxn *>(strategyTxn);
int64_t sm_id = TSHttpTxnIdGet(txnp);
@@ -341,34 +366,40 @@ PLNextHopConsistentHash::next(TSHttpTxn txnp, void *strategyTxn, const char *exc
}
time_t _now = now;
- bool firstcall = false;
bool nextHopRetry = false;
bool wrapped = false;
std::vector<bool> wrap_around(groups, false);
- uint32_t cur_ring = 0; // there is a hash ring for each host group
- uint64_t hash_key = 0;
- uint32_t lookups = 0;
- ATSHash64Sip24 hash;
- PLHostRecord *hostRec = nullptr;
+ uint32_t cur_ring = 0; // there is a hash ring for each host group
+ uint32_t lookups = 0;
std::shared_ptr<PLHostRecord> pRec = nullptr;
TSHostStatus host_stat = TSHostStatus::TS_HOST_STATUS_INIT;
+ std::string_view first_call_host;
+ int first_call_port = 0;
- if (state->line_number == -1 && state->result == PL_NH_PARENT_UNDEFINED) {
- firstcall = true;
- }
+ const bool firstcall = state->line_number == -1 && state->result == PL_NH_PARENT_UNDEFINED;
+ // firstcall indicates that this is the first time the state machine has called findNextHop() for this
+ // particular transaction so, a parent will be looked up using a hash from the request to locate a
+ // parent on the consistent hash ring. If not first call, then the transaction was unable to use the parent
+ // returned from the "firstcall" due to some error so, subsequent calls will not search using a hash but,
+ // will instead just increment the hash table iterator to find the next parent on the ring
if (firstcall) {
- PL_NH_Debug(PL_NH_DEBUG_TAG, "nextParent [%" PRIu64 "] firstcall, line_number: %d, result: %s", sm_id, state->line_number,
+ PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] firstcall, line_number: %d, result: %s", sm_id, state->line_number,
PLNHParentResultStr[state->result]);
- state->line_number = PLNextHopConsistentHash::LineNumberPlaceholder;
+ state->line_number = distance;
cur_ring = 0;
for (uint32_t i = 0; i < groups; i++) {
state->chash_init[i] = false;
wrap_around[i] = false;
}
} else {
- PL_NH_Debug(PL_NH_DEBUG_TAG, "getNextHopResult [%" PRIu64 "] not firstcall, line_number: %d, result: %s", sm_id,
- state->line_number, PLNHParentResultStr[state->result]);
+ // not first call, save the previously tried parent.
+ if (state->hostname) {
+ first_call_host = state->hostname;
+ first_call_port = state->port;
+ }
+ PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] not firstcall, line_number: %d, result: %s", sm_id, state->line_number,
+ PLNHParentResultStr[state->result]);
switch (ring_mode) {
case PL_NH_ALTERNATE_RING:
if (groups > 1) {
@@ -378,10 +409,14 @@ PLNextHopConsistentHash::next(TSHttpTxn txnp, void *strategyTxn, const char *exc
}
break;
case PL_NH_PEERING_RING:
- ink_assert(groups == 2);
- // look for the next parent on the
- // upstream ring.
- state->last_group = cur_ring = 1;
+ if (groups == 1) {
+ state->last_group = cur_ring = NO_RING_USE_POST_REMAP;
+ } else {
+ ink_assert(groups == 2);
+ // look for the next parent on the
+ // upstream ring.
+ state->last_group = cur_ring = 1;
+ }
break;
case PL_NH_EXHAUST_RING:
default:
@@ -394,76 +429,91 @@ PLNextHopConsistentHash::next(TSHttpTxn txnp, void *strategyTxn, const char *exc
}
}
- // Do the initial parent look-up.
- hash_key = getHashKey(sm_id, reqp, url, parent_selection_url, &hash);
-
- do { // search until we've selected a different parent if !firstcall
- std::shared_ptr<ATSConsistentHash> r = rings[cur_ring];
- hostRec = chash_lookup(r, hash_key, &state->chashIter[cur_ring], &wrapped, &hash, &state->chash_init[cur_ring],
- &state->mapWrapped[cur_ring], sm_id);
- wrap_around[cur_ring] = wrapped;
- lookups++;
- // the 'available' flag is maintained in 'host_groups' and not the hash ring.
- if (hostRec) {
- pRec = host_groups[hostRec->group_index][hostRec->host_index];
- if (firstcall) {
- TSHostStatus hostStatus;
- const bool hostExists =
- pRec ? (TSHostStatusGet(pRec->hostname.c_str(), pRec->hostname.size(), &hostStatus, nullptr) == TS_SUCCESS) : false;
- state->first_choice_status = hostExists ? hostStatus : TSHostStatus::TS_HOST_STATUS_UP;
- // if peering and the selected host is myself, change rings and search for an upstream
- // parent.
- if (ring_mode == PL_NH_PEERING_RING && TSHostnameIsSelf(pRec->hostname.c_str(), pRec->hostname.size()) == TS_SUCCESS) {
- // switch to the upstream ring.
- cur_ring = 1;
- continue;
- }
+ if (cur_ring != NO_RING_USE_POST_REMAP) {
+ do {
+ // all host groups have been searched and there are no available parents found
+ if (isWrapped(wrap_around, groups)) {
+ PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] No available parents.", sm_id);
+ pRec = nullptr;
break;
}
- } else {
- pRec = nullptr;
- }
- } while (pRec && state->hostname && strncmp(pRec->hostname.c_str(), state->hostname, pRec->hostname.size()) == 0);
- PL_NH_Debug(PL_NH_DEBUG_TAG, "getNextHopResult [%" PRIu64 "] Initial parent lookups: %d", sm_id, lookups);
+ // search for available parent
+ std::shared_ptr<ATSConsistentHash> r = rings[cur_ring];
+ pRec = chashLookup(r, cur_ring, state, &wrapped, sm_id, reqp, url, parent_selection_url);
+ wrap_around[cur_ring] = wrapped;
+ lookups++;
- // ----------------------------------------------------------------------------------------------------
- // Validate initial parent look-up and perform additional look-ups if required.
- // ----------------------------------------------------------------------------------------------------
+ TSHostStatus hostStatus;
+ unsigned int hostStatusReasons;
+ const bool hostExists =
+ pRec ? (TSHostStatusGet(pRec->hostname.c_str(), pRec->hostname.size(), &hostStatus, &hostStatusReasons) == TS_SUCCESS) :
+ false;
- TSHostStatus hostStatus;
- unsigned int hostReasons;
- const bool hostExists =
- pRec ? (TSHostStatusGet(pRec->hostname.c_str(), pRec->hostname.size(), &hostStatus, &hostReasons) == TS_SUCCESS) : false;
- host_stat = hostExists ? hostStatus : TSHostStatus::TS_HOST_STATUS_UP;
- // if the config ignore_self_detect is set to true and the host is down due to SELF_DETECT reason
- // ignore the down status and mark it as available
- if ((pRec && ignore_self_detect) && (hostExists && hostStatus == TS_HOST_STATUS_DOWN)) {
- if (hostReasons & TS_HOST_STATUS_SELF_DETECT) {
- host_stat = TS_HOST_STATUS_UP;
- }
- }
- bool pRecExclude = exclude_hostname != nullptr && pRec &&
- strncmp(pRec->hostname.c_str(), exclude_hostname, pRec->hostname.size()) == 0 &&
- pRec->getPort(scheme) == exclude_port;
- if (!pRec || (pRec && (!pRec->available || pRecExclude)) || host_stat == TS_HOST_STATUS_DOWN) {
- do {
- // check if an unavailable server is now retryable, use it if it is.
- if (pRec && !pRec->available && host_stat == TS_HOST_STATUS_UP && !pRecExclude) {
- _now == 0 ? _now = time(nullptr) : _now = now;
- // check if the host is retryable. It's retryable if the retry window has elapsed
- if ((pRec->failedAt + retry_time) < static_cast<unsigned>(_now)) {
- nextHopRetry = true;
- state->last_parent = pRec->host_index;
- state->last_lookup = pRec->group_index;
- state->retry = nextHopRetry;
- state->result = PL_NH_PARENT_SPECIFIED;
-
- PL_NH_Debug(PL_NH_DEBUG_TAG, "getNextHopResult [%" PRIu64 "] next hop %.*s is now retryable, marked it available.", sm_id,
- int(pRec->hostname.size()), pRec->hostname.c_str());
+ // found a parent
+ if (pRec) {
+ bool is_self = TSHostnameIsSelf(pRec->hostname.c_str(), pRec->hostname.size()) == TS_SUCCESS;
+ host_stat = hostExists ? hostStatus : TSHostStatus::TS_HOST_STATUS_UP;
+
+ // if the config ignore_self_detect is set to true and the host is down due to SELF_DETECT reason
+ // ignore the down status and mark it as available
+ if ((host_stat == TS_HOST_STATUS_DOWN && is_self && ignore_self_detect)) {
+ if (hostStatusReasons == TS_HOST_STATUS_SELF_DETECT) {
+ host_stat = TS_HOST_STATUS_UP;
+ }
+ }
+
+ if (firstcall) {
+ state->first_choice_status = hostExists ? hostStatus : TSHostStatus::TS_HOST_STATUS_UP;
+ // if peering and the selected host is myself, change rings and search for an upstream parent.
+ if (ring_mode == PL_NH_PEERING_RING && (pRec->self || is_self)) {
+ PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] peering ring got self %s - searching for upstream parent", sm_id,
+ pRec->hostname.c_str());
+ if (groups == 1) {
+ PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] peering ring got self %s - 1 group, using host from post-remap URL",
+ sm_id, pRec->hostname.c_str());
+ // use host from post-remap URL
+ cur_ring = NO_RING_USE_POST_REMAP;
+ pRec = nullptr;
+ break;
+ } else {
+ PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] peering ring got self %s - !1 group, searching upstream ring", sm_id,
+ pRec->hostname.c_str());
+ // switch to and search the upstream ring.
+ cur_ring = 1;
+ pRec = nullptr;
+ continue;
+ }
+ }
+ } else {
+ // not first call, make sure we're not re-using the same parent, search again if we are.
+ if (first_call_host.size() > 0 && first_call_host == pRec->hostname && first_call_port == pRec->getPort(scheme)) {
+ pRec = nullptr;
+ continue;
+ }
+ }
+ // if the parent is not available check to see if the retry window has expired making it available
+ // for retry.
+ if (!pRec->available.load() && host_stat == TS_HOST_STATUS_UP) {
+ _now == 0 ? _now = time(nullptr) : _now = now;
+ if ((pRec->failedAt.load() + retry_time) < static_cast<unsigned>(_now)) {
+ nextHopRetry = true;
+ state->last_parent = pRec->host_index;
+ state->last_lookup = pRec->group_index;
+ state->retry = nextHopRetry;
+ state->result = PL_NH_PARENT_SPECIFIED;
+ state->no_cache = false;
+ PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] next hop %s is now retryable", sm_id, pRec->hostname.c_str());
+ break;
+ }
+ }
+
+ // use the available selected parent
+ if (pRec->available.load() && host_stat == TS_HOST_STATUS_UP) {
break;
}
}
+ // try other rings per per the ring mode
switch (ring_mode) {
case PL_NH_ALTERNATE_RING:
if (groups > 0) {
@@ -477,70 +527,29 @@ PLNextHopConsistentHash::next(TSHttpTxn txnp, void *strategyTxn, const char *exc
}
break;
}
- std::shared_ptr<ATSConsistentHash> r = rings[cur_ring];
- hostRec = chash_lookup(r, hash_key, &state->chashIter[cur_ring], &wrapped, &hash, &state->chash_init[cur_ring],
- &state->mapWrapped[cur_ring], sm_id);
- wrap_around[cur_ring] = wrapped;
- lookups++;
- if (hostRec) {
- pRec = host_groups[hostRec->group_index][hostRec->host_index];
- pRecExclude = exclude_hostname != nullptr && pRec &&
- strncmp(pRec->hostname.c_str(), exclude_hostname, pRec->hostname.size()) == 0 &&
- pRec->getPort(scheme) == exclude_port;
-
- TSHostStatus hostStatus;
- unsigned int hostReasons;
- const bool hostExists =
- pRec ? (TSHostStatusGet(pRec->hostname.c_str(), pRec->hostname.size(), &hostStatus, &hostReasons) == TS_SUCCESS) : false;
- host_stat = hostExists ? hostStatus : TSHostStatus::TS_HOST_STATUS_UP;
- // if the config ignore_self_detect is set to true and the host is down due to SELF_DETECT reason
- // ignore the down status and mark it as available
- if ((pRec && ignore_self_detect) && (hostExists && hostStatus == TS_HOST_STATUS_DOWN)) {
- if (hostReasons & TS_HOST_STATUS_SELF_DETECT) {
- host_stat = TS_HOST_STATUS_UP;
- }
- }
- if (pRec) {
- PL_NH_Debug(PL_NH_DEBUG_TAG,
- "nextParent [%" PRIu64 "] Selected a new parent: %.*s, available: %s, wrapped: %s, lookups: %d, exclude: %s.",
- sm_id, int(pRec->hostname.size()), pRec->hostname.c_str(), (pRec->available) ? "true" : "false",
- (wrapped) ? "true" : "false", lookups, pRecExclude ? "true" : "false");
- } else {
- PL_NH_Debug(PL_NH_DEBUG_TAG, "nextParent [%" PRIu64 "] Selected a new parent: null", sm_id);
- }
- // use available host.
- if (pRec && pRec->available && !pRecExclude && host_stat == TS_HOST_STATUS_UP) {
- break;
- }
- } else {
- pRec = nullptr;
- }
- bool all_wrapped = true;
- for (uint32_t c = 0; c < groups; c++) {
- if (wrap_around[c] == false) {
- all_wrapped = false;
- }
- }
- if (all_wrapped) {
- PL_NH_Debug(PL_NH_DEBUG_TAG, "nextParent [%" PRIu64 "] No available parents.", sm_id);
- if (pRec) {
+ if (pRec) {
+ // if the selected host is down, search again.
+ if (!pRec->available || host_stat == TS_HOST_STATUS_DOWN) {
+ PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] hostname: %s, available: %s, host_stat: %d", sm_id, pRec->hostname.c_str(),
+ pRec->available ? "true" : "false", host_stat);
pRec = nullptr;
+ continue;
}
- break;
}
- } while (!pRec || (pRec && (!pRec->available || pRecExclude)) || host_stat == TS_HOST_STATUS_DOWN);
+ } while (!pRec);
+
+ PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] Initial parent lookups: %d", sm_id, lookups);
}
// ----------------------------------------------------------------------------------------------------
// Validate and return the final result.
// ----------------------------------------------------------------------------------------------------
- if (pRec && host_stat == TS_HOST_STATUS_UP && (pRec->available || state->retry) && !pRecExclude) {
- state->result = PL_NH_PARENT_SPECIFIED;
- state->hostname = pRec->hostname.c_str();
- state->hostname_len = pRec->hostname.size();
- state->last_parent = pRec->host_index;
+ if (pRec && host_stat == TS_HOST_STATUS_UP && (pRec->available.load() || state->retry)) {
+ state->result = PL_NH_PARENT_SPECIFIED;
+ state->hostname = pRec->hostname.c_str();
+ state->last_parent = pRec->host_index;
state->last_lookup = state->last_group = cur_ring;
switch (scheme) {
case PL_NH_SCHEME_NONE:
@@ -552,30 +561,23 @@ PLNextHopConsistentHash::next(TSHttpTxn txnp, void *strategyTxn, const char *exc
break;
}
state->retry = nextHopRetry;
-
// if using a peering ring mode and the parent selected came from the 'peering' group,
// cur_ring == 0, then if the config allows it, set the flag to not cache the result.
state->no_cache = ring_mode == PL_NH_PEERING_RING && !cache_peer_result && cur_ring == 0;
PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] setting do not cache response from a peer per config: %s", sm_id,
- state->no_cache ? "true" : "false");
-
+ (state->no_cache) ? "true" : "false");
ink_assert(state->hostname != nullptr);
ink_assert(state->port != 0);
- PL_NH_Debug(PL_NH_DEBUG_TAG, "nextParent [%" PRIu64 "] state->result: %s Chosen parent: %.*s:%d", sm_id,
- PLNHParentResultStr[state->result], int(state->hostname_len), state->hostname, state->port);
+ PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] state->result: %s Chosen parent: %s.%d", sm_id, PLNHParentResultStr[state->result],
+ state->hostname, state->port);
} else {
- if (go_direct == true) {
- state->result = PL_NH_PARENT_DIRECT;
- } else {
- state->result = PL_NH_PARENT_FAIL;
- }
- state->hostname = nullptr;
- state->hostname_len = 0;
- state->port = 0;
- state->retry = false;
- state->no_cache = false;
- PL_NH_Debug(PL_NH_DEBUG_TAG, "nextParent [%" PRIu64 "] state->result: %s set hostname null port 0 retry false", sm_id,
- PLNHParentResultStr[state->result]);
+ state->result = go_direct ? PL_NH_PARENT_DIRECT : PL_NH_PARENT_FAIL;
+ state->retry = false;
+ state->hostname = nullptr;
+ state->port = 0;
+ state->no_cache = false;
+ PL_NH_Debug(PL_NH_DEBUG_TAG, "[%" PRIu64 "] state->result: %s set hostname null port 0 retry %d", sm_id,
+ PLNHParentResultStr[state->result], state->retry);
}
*out_hostname = state->hostname;
@@ -583,6 +585,8 @@ PLNextHopConsistentHash::next(TSHttpTxn txnp, void *strategyTxn, const char *exc
*out_port = state->port;
*out_retry = state->retry;
*out_no_cache = state->no_cache;
+
+ return;
}
void
diff --git a/plugins/experimental/parent_select/consistenthash.h b/plugins/experimental/parent_select/consistenthash.h
index a8c46af..6232f07 100644
--- a/plugins/experimental/parent_select/consistenthash.h
+++ b/plugins/experimental/parent_select/consistenthash.h
@@ -63,6 +63,10 @@ class PLNextHopConsistentHash : public PLNextHopSelectionStrategy
std::vector<std::shared_ptr<ATSConsistentHash>> rings;
uint64_t getHashKey(uint64_t sm_id, TSMBuffer reqp, TSMLoc url, TSMLoc parent_selection_url, ATSHash64 *h);
+ std::shared_ptr<PLHostRecord> chashLookup(const std::shared_ptr<ATSConsistentHash> &ring, uint32_t cur_ring,
+ PLNextHopConsistentHashTxn *state, bool *wrapped, uint64_t sm_id, TSMBuffer reqp,
+ TSMLoc url, TSMLoc parent_selection_url);
+
public:
const uint32_t LineNumberPlaceholder = 99999;
diff --git a/plugins/experimental/parent_select/parent_select.cc b/plugins/experimental/parent_select/parent_select.cc
index 17ad8f1..ef9820c 100644
--- a/plugins/experimental/parent_select/parent_select.cc
+++ b/plugins/experimental/parent_select/parent_select.cc
@@ -438,7 +438,14 @@ TSRemapDoRemap(void *ih, TSHttpTxn txnp, TSRemapRequestInfo *rri)
strategy->next(txnp, strategyTxn->txn, exclude_host, exclude_host_len, exclude_port, &ra.hostname, &ra.hostname_len, &ra.port,
&ra.is_retry, &ra.no_cache);
- if (ra.hostname == nullptr) {
+ ra.nextHopExists = ra.hostname != nullptr;
+ ra.fail = !ra.nextHopExists;
+ // The action here is used for the very first connection, not any retry. So of course we should try it.
+ ra.responseIsRetryable = true;
+ ra.goDirect = strategy->goDirect();
+ ra.parentIsProxy = strategy->parentIsProxy();
+
+ if (ra.fail && !ra.goDirect) {
// TODO make configurable
TSDebug(PLUGIN_NAME, "TSRemapDoRemap strategy '%s' next returned nil, returning 502!", strategy->name());
TSHttpTxnStatusSet(txnp, TS_HTTP_STATUS_BAD_GATEWAY);
@@ -446,12 +453,6 @@ TSRemapDoRemap(void *ih, TSHttpTxn txnp, TSRemapRequestInfo *rri)
return TSREMAP_DID_REMAP;
}
- ra.fail = false;
- ra.nextHopExists = true;
- ra.responseIsRetryable =
- true; // The action here is used for the very first connection, not any retry. So of course we should try it.
- ra.goDirect = strategy->goDirect();
- ra.parentIsProxy = strategy->parentIsProxy();
TSDebug(PLUGIN_NAME, "TSRemapDoRemap setting response_action hostname '%.*s' port %d direct %d proxy %d", int(ra.hostname_len),
ra.hostname, ra.port, ra.goDirect, ra.parentIsProxy);
TSHttpTxnResponseActionSet(txnp, &ra);
diff --git a/plugins/experimental/parent_select/strategy.cc b/plugins/experimental/parent_select/strategy.cc
index 8a822d4..726680a 100644
--- a/plugins/experimental/parent_select/strategy.cc
+++ b/plugins/experimental/parent_select/strategy.cc
@@ -67,6 +67,8 @@ bool
PLNextHopSelectionStrategy::Init(const YAML::Node &n)
{
PL_NH_Debug(PL_NH_DEBUG_TAG, "calling Init()");
+ std::string self_host;
+ bool self_host_used = false;
try {
if (n["scheme"]) {
@@ -112,7 +114,12 @@ PLNextHopSelectionStrategy::Init(const YAML::Node &n)
} else if (ring_mode_val == exhaust_rings) {
ring_mode = PL_NH_EXHAUST_RING;
} else if (ring_mode_val == peering_rings) {
- ring_mode = PL_NH_PEERING_RING;
+ ring_mode = PL_NH_PEERING_RING;
+ YAML::Node self_node = failover_node["self"];
+ if (self_node) {
+ self_host = self_node.Scalar();
+ PL_NH_Debug(PL_NH_DEBUG_TAG, "%s is self", self_host.c_str());
+ }
} else {
ring_mode = PL_NH_ALTERNATE_RING;
PL_NH_Note("Invalid 'ring_mode' value, '%s', for the strategy named '%s', using default '%s'.", ring_mode_val.c_str(),
@@ -197,9 +204,16 @@ PLNextHopSelectionStrategy::Init(const YAML::Node &n)
std::shared_ptr<PLHostRecord> host_rec = std::make_shared<PLHostRecord>(hosts_list[hst].as<PLHostRecord>());
host_rec->group_index = grp;
host_rec->host_index = hst;
- if (TSHostnameIsSelf(host_rec->hostname.c_str(), host_rec->hostname.size()) == TS_SUCCESS) {
+ if (self_host == host_rec->hostname ||
+ TSHostnameIsSelf(host_rec->hostname.c_str(), host_rec->hostname.size()) == TS_SUCCESS) {
+ if (ring_mode == PL_NH_PEERING_RING && grp != 0) {
+ throw std::invalid_argument("self host (" + self_host +
+ ") can only appear in first host group for peering ring mode");
+ }
TSHostStatusSet(host_rec->hostname.c_str(), host_rec->hostname.size(), TSHostStatus::TS_HOST_STATUS_DOWN, 0,
static_cast<unsigned int>(TS_HOST_STATUS_SELF_DETECT));
+ host_rec->self = true;
+ self_host_used = true;
}
hosts_inner.push_back(std::move(host_rec));
num_parents++;
@@ -210,12 +224,33 @@ PLNextHopSelectionStrategy::Init(const YAML::Node &n)
}
}
}
+ if (!self_host.empty() && !self_host_used) {
+ throw std::invalid_argument("self host (" + self_host + ") does not appear in the first (peer) group");
+ }
} catch (std::exception &ex) {
PL_NH_Note("Error parsing the strategy named '%s' due to '%s', this strategy will be ignored.", strategy_name.c_str(),
ex.what());
return false;
}
+ if (ring_mode == PL_NH_PEERING_RING) {
+ if (groups == 1) {
+ if (!go_direct) {
+ PL_NH_Error("when ring mode is '%s', go_direct must be true when there is only one host group.", peering_rings.data());
+ return false;
+ }
+ } else if (groups != 2) {
+ PL_NH_Error("when ring mode is '%s', requires two host groups (peering group and an upstream group),"
+ " or just a single peering group with go_direct.",
+ peering_rings.data());
+ return false;
+ }
+ // if (policy_type != PL_NH_CONSISTENT_HASH) {
+ // PL_NH_Error("ring mode '%s', is only implemented for a 'consistent_hash' policy.", peering_rings.data());
+ // return false;
+ // }
+ }
+
return true;
}
diff --git a/plugins/experimental/parent_select/strategy.h b/plugins/experimental/parent_select/strategy.h
index deff4d1..6048e70 100644
--- a/plugins/experimental/parent_select/strategy.h
+++ b/plugins/experimental/parent_select/strategy.h
@@ -105,13 +105,14 @@ struct PLNHProtocol {
struct PLHostRecord : ATSConsistentHashNode {
std::mutex _mutex;
std::string hostname;
- time_t failedAt;
- uint32_t failCount;
- time_t upAt;
+ std::atomic<time_t> failedAt;
+ std::atomic<uint32_t> failCount;
+ std::atomic<time_t> upAt;
float weight;
std::string hash_string;
int host_index;
int group_index;
+ bool self = false;
std::vector<std::shared_ptr<PLNHProtocol>> protocols;
// construct without locking the _mutex.
@@ -132,15 +133,16 @@ struct PLHostRecord : ATSConsistentHashNode {
PLHostRecord(const PLHostRecord &o)
{
hostname = o.hostname;
- failedAt = o.failedAt;
- failCount = o.failCount;
- upAt = o.upAt;
+ failedAt = o.failedAt.load();
+ failCount = o.failCount.load();
+ upAt = o.upAt.load();
weight = o.weight;
hash_string = o.hash_string;
- host_index = -1;
- group_index = -1;
- available = true;
+ host_index = o.host_index;
+ group_index = o.group_index;
+ available = o.available.load();
protocols = o.protocols;
+ self = o.self;
}
// assign without copying the _mutex.
@@ -148,14 +150,16 @@ struct PLHostRecord : ATSConsistentHashNode {
operator=(const PLHostRecord &o)
{
hostname = o.hostname;
- failedAt = o.failedAt;
- upAt = o.upAt;
+ failedAt = o.failedAt.load();
+ failCount = o.failCount.load();
+ upAt = o.upAt.load();
weight = o.weight;
hash_string = o.hash_string;
host_index = o.host_index;
group_index = o.group_index;
available = o.available.load();
protocols = o.protocols;
+ self = o.self;
return *this;
}
diff --git a/tests/gold_tests/pluginTest/parent_select/body.gold b/tests/gold_tests/pluginTest/parent_select/body.gold
new file mode 100755
index 0000000..b220ced
--- /dev/null
+++ b/tests/gold_tests/pluginTest/parent_select/body.gold
@@ -0,0 +1 @@
+This is the body.
diff --git a/tests/gold_tests/pluginTest/parent_select/parent_select.test.py b/tests/gold_tests/pluginTest/parent_select/parent_select.test.py
new file mode 100755
index 0000000..d93c886
--- /dev/null
+++ b/tests/gold_tests/pluginTest/parent_select/parent_select.test.py
@@ -0,0 +1,147 @@
+'''
+'''
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+Test.Summary = '''
+Basic parent_select plugin test
+'''
+
+Test.SkipUnless(
+ Condition.PluginExists('parent_select.so'),
+)
+Test.ContinueOnFail = False
+
+# Define and populate MicroServer.
+#
+server = Test.MakeOriginServer("server")
+response_header = {
+ "headers":
+ "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Cache-control: max-age=85000\r\n"
+ "\r\n",
+ "timestamp": "1469733493.993",
+ "body": "This is the body.\n"
+}
+num_objects = 32
+for i in range(num_objects):
+ request_header = {
+ "headers":
+ f"GET /obj{i} HTTP/1.1\r\n"
+ "Host: does.not.matter\r\n" # But cannot be omitted.
+ "\r\n",
+ "timestamp": "1469733493.993",
+ "body": ""
+ }
+ server.addResponse("sessionlog.json", request_header, response_header)
+
+dns = Test.MakeDNServer("dns")
+
+# Define next hop trafficserver instances.
+#
+num_nh = 8
+ts_nh = []
+for i in range(num_nh):
+ ts = Test.MakeATSProcess(f"ts_nh{i}", command=f"traffic_server 2>nh_trace{i}.log")
+ ts.Disk.records_config.update({
+ 'proxy.config.diags.debug.enabled': 1,
+ 'proxy.config.diags.debug.tags': 'http|dns',
+ 'proxy.config.dns.nameservers': f"127.0.0.1:{dns.Variables.Port}",
+ 'proxy.config.dns.resolv_conf': "NULL",
+ })
+ ts.Disk.remap_config.AddLine(
+ f"map / http://127.0.0.1:{server.Variables.Port}"
+ )
+ ts_nh.append(ts)
+
+ts = Test.MakeATSProcess("ts")
+
+ts.Disk.records_config.update({
+ 'proxy.config.diags.debug.enabled': 1,
+ 'proxy.config.diags.debug.tags': 'http|dns|parent|next_hop|host_statuses|hostdb',
+ 'proxy.config.dns.nameservers': f"127.0.0.1:{dns.Variables.Port}", # Only nameservers if resolv_conf NULL.
+ 'proxy.config.dns.resolv_conf': "NULL", # This defaults to /etc/resvolv.conf (OS namesevers) if not NULL.
+ 'proxy.config.http.cache.http': 0,
+ 'proxy.config.http.uncacheable_requests_bypass_parent': 0,
+ 'proxy.config.http.no_dns_just_forward_to_parent': 1,
+ 'proxy.config.http.parent_proxy.mark_down_hostdb': 0,
+ 'proxy.config.http.parent_proxy.self_detect': 0,
+})
+
+ts.Disk.File(ts.Variables.CONFIGDIR + "/strategies.yaml", id="strategies", typename="ats:config")
+s = ts.Disk.strategies
+s.AddLine("groups:")
+s.AddLine(" - &g1")
+for i in range(num_nh):
+ dns.addRecords(records={f"next_hop{i}": ["127.0.0.1"]})
+ s.AddLine(f" - host: next_hop{i}")
+ s.AddLine(f" protocol:")
+ s.AddLine(f" - scheme: http")
+ s.AddLine(f" port: {ts_nh[i].Variables.port}")
+ # The health check URL does not seem to be used currently.
+ # s.AddLine(f" health_check_url: http://next_hop{i}:{ts_nh[i].Variables.port}")
+ s.AddLine(f" weight: 1.0")
+s.AddLines([
+ "strategies:",
+ " - strategy: the-strategy",
+ " policy: consistent_hash",
+ " hash_key: path",
+ " go_direct: false",
+ " parent_is_proxy: true",
+ " ignore_self_detect: true",
+ " groups:",
+ " - *g1",
+ " scheme: http"])
+
+# Fallover not currently tested.
+#
+# s.AddLines([
+# " fallover:",
+# " max_simple_retries: 2",
+# " ring_mode: exhaust_ring",
+# " response_codes:",
+# " - 404",
+# " health_check:",
+# " - passive"])
+
+ts.Disk.remap_config.AddLine(
+ "map http://dummy.com http://not_used @plugin=parent_select.so @pparam=" +
+ ts.Variables.CONFIGDIR +
+ "/strategies.yaml @pparam=the-strategy")
+
+tr = Test.AddTestRun()
+tr.Processes.Default.StartBefore(server)
+tr.Processes.Default.StartBefore(dns)
+for i in range(num_nh):
+ tr.Processes.Default.StartBefore(ts_nh[i])
+tr.Processes.Default.StartBefore(Test.Processes.ts)
+tr.Processes.Default.Command = 'echo start TS, HTTP server, DNS server and next hop TSes'
+tr.Processes.Default.ReturnCode = 0
+
+for i in range(num_objects):
+ tr = Test.AddTestRun()
+ tr.Processes.Default.Command = (
+ f'curl --verbose --proxy 127.0.0.1:{ts.Variables.port} http://dummy.com/obj{i}'
+ )
+ tr.Processes.Default.Streams.stdout = "body.gold"
+ tr.Processes.Default.ReturnCode = 0
+
+tr = Test.AddTestRun()
+# For some reason, the * won't be expanded when the command is executed, if stdout is not piped through "cat".
+tr.Processes.Default.Command = "grep -F '200 OK' nh_trace*.log | cat"
+tr.Processes.Default.Streams.stdout = "trace.gold"
+tr.Processes.Default.ReturnCode = 0
diff --git a/tests/gold_tests/pluginTest/parent_select/parent_select_peer.test.py b/tests/gold_tests/pluginTest/parent_select/parent_select_peer.test.py
new file mode 100644
index 0000000..f28b9c8
--- /dev/null
+++ b/tests/gold_tests/pluginTest/parent_select/parent_select_peer.test.py
@@ -0,0 +1,177 @@
+'''
+'''
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+Test.Summary = '''
+Test next hop selection using strategies.yaml with consistent hashing, with peering.
+'''
+
+# The tls_conn_timeout test will fail if it runs before this test in CI. Therefore, this test has a zzz
+# prefix so it will run last in CI.
+
+# Define and populate MicroServer.
+#
+server = Test.MakeOriginServer("server")
+response_header = {
+ "headers":
+ "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Cache-control: max-age=85000\r\n"
+ "\r\n",
+ "timestamp": "1469733493.993",
+ "body": "This is the body.\n"
+}
+num_object = 16
+for i in range(num_object):
+ request_header = {
+ "headers":
+ f"GET /obj{i} HTTP/1.1\r\n"
+ "Host: does.not.matter\r\n" # But cannot be omitted.
+ "\r\n",
+ "timestamp": "1469733493.993",
+ "body": ""
+ }
+ server.addResponse("sessionlog.json", request_header, response_header)
+
+dns = Test.MakeDNServer("dns")
+
+# Define upstream trafficserver instances.
+#
+num_upstream = 6
+ts_upstream = []
+for i in range(num_upstream):
+ ts = Test.MakeATSProcess(f"ts_upstream{i}")
+ dns.addRecords(records={f"ts_upstream{i}": ["127.0.0.1"]})
+ ts.Disk.records_config.update({
+ 'proxy.config.diags.debug.enabled': 1,
+ 'proxy.config.diags.debug.tags': 'http|dns',
+ 'proxy.config.dns.nameservers': f"127.0.0.1:{dns.Variables.Port}",
+ 'proxy.config.dns.resolv_conf': "NULL",
+ })
+ ts.Disk.remap_config.AddLine(
+ f"map / http://127.0.0.1:{server.Variables.Port}"
+ )
+ ts_upstream.append(ts)
+
+# Define peer trafficserver instances.
+#
+num_peer = 8
+ts_peer = []
+for i in range(num_peer):
+ ts = Test.MakeATSProcess(f"ts_peer{i}", command=f"traffic_server 2> trace_peer{i}.log")
+ ts_peer.append(ts)
+for i in range(num_peer):
+ ts = ts_peer[i]
+ dns.addRecords(records={f"ts_peer{i}": ["127.0.0.1"]})
+
+ ts.Disk.records_config.update({
+ 'proxy.config.diags.debug.enabled': 1,
+ 'proxy.config.diags.debug.tags': 'http|dns|parent|next_hop|host_statuses|hostdb|cachekey|plugin_nexthop',
+ 'proxy.config.dns.nameservers': f"127.0.0.1:{dns.Variables.Port}", # Only nameservers if resolv_conf NULL.
+ 'proxy.config.dns.resolv_conf': "NULL", # This defaults to /etc/resvolv.conf (OS namesevers) if not NULL.
+ 'proxy.config.http.cache.http': 1,
+ 'proxy.config.http.cache.required_headers': 0,
+ 'proxy.config.http.uncacheable_requests_bypass_parent': 0,
+ 'proxy.config.http.no_dns_just_forward_to_parent': 1,
+ 'proxy.config.http.parent_proxy.mark_down_hostdb': 0,
+ 'proxy.config.http.parent_proxy.self_detect': 1,
+ })
+
+ ts.Disk.File(ts.Variables.CONFIGDIR + "/strategies.yaml", id="strategies", typename="ats:config")
+ s = ts.Disk.strategies
+ s.AddLine("groups:")
+ s.AddLine(" - &peer_group")
+ for j in range(num_peer):
+ s.AddLine(f" - host: ts_peer{j}")
+ s.AddLine(f" protocol:")
+ s.AddLine(f" - scheme: http")
+ s.AddLine(f" port: {ts_peer[j].Variables.port}")
+ # The health check URL does not seem to be used currently.
+ # s.AddLine(f" health_check_url: http://ts_peer{j}:{ts_peer[j].Variables.port}")
+ s.AddLine(f" weight: 1.0")
+ s.AddLine(" - &peer_upstream")
+ for j in range(num_upstream):
+ s.AddLine(f" - host: ts_upstream{j}")
+ s.AddLine(f" protocol:")
+ s.AddLine(f" - scheme: http")
+ s.AddLine(f" port: {ts_upstream[j].Variables.port}")
+ # The health check URL does not seem to be used currently.
+ # s.AddLine(f" health_check_url: http://ts_upstream{j}:{ts_upstream[j].Variables.port}")
+ s.AddLine(f" weight: 1.0")
+ s.AddLines([
+ "strategies:",
+ " - strategy: the-strategy",
+ " policy: consistent_hash",
+ " hash_key: cache_key",
+ " go_direct: false",
+ " parent_is_proxy: true",
+ " cache_peer_result: false",
+ " ignore_self_detect: false",
+ " groups:",
+ " - *peer_group",
+ " - *peer_upstream",
+ " scheme: http",
+ " failover:",
+ " ring_mode: peering_ring",
+ f" self: ts_peer{i}",
+ #" max_simple_retries: 2",
+ #" response_codes:",
+ #" - 404",
+ #" health_check:",
+ #" - passive",
+ ])
+
+ suffix = f" @plugin=parent_select.so @pparam={ts.Variables.CONFIGDIR}/strategies.yaml @pparam=the-strategy @plugin=cachekey.so @pparam=--uri-type=remap @pparam=--capture-prefix=/(.*):(.*)/$1/"
+ ts.Disk.remap_config.AddLines([
+ "map http://dummy.com http://not_used" + suffix,
+ "map http://not_used http://also_not_used" + suffix,
+ ])
+
+tr = Test.AddTestRun()
+tr.Processes.Default.StartBefore(server)
+tr.Processes.Default.StartBefore(dns)
+for i in range(num_peer):
+ tr.Processes.Default.StartBefore(ts_peer[i])
+for i in range(num_upstream):
+ tr.Processes.Default.StartBefore(ts_upstream[i])
+tr.Processes.Default.Command = 'echo start peer and upstream TSes, HTTP server and DNS server'
+tr.Processes.Default.ReturnCode = 0
+
+for i in range(num_object):
+ tr = Test.AddTestRun()
+ tr.Processes.Default.Command = (
+ f'curl --verbose --proxy 127.0.0.1:{ts_peer[i % num_peer].Variables.port} http://dummy.com/obj{i}'
+ )
+ tr.Processes.Default.Streams.stdout = "peer.body.gold"
+ tr.Processes.Default.ReturnCode = 0
+
+for i in range(num_object):
+ tr = Test.AddTestRun()
+ # num_peer must not be a multiple of 3
+ tr.Processes.Default.Command = (
+ f'curl --verbose --proxy 127.0.0.1:{ts_peer[(i * 3) % num_peer].Variables.port} http://dummy.com/obj{i}'
+ )
+ tr.Processes.Default.Streams.stdout = "peer.body.gold"
+ tr.Processes.Default.ReturnCode = 0
+
+tr = Test.AddTestRun()
+tr.Processes.Default.Command = (
+ "grep -e '^+++' -e '^[A-Z].*TTP/' -e '^.alts. --' -e 'PARENT_SPECIFIED' trace_peer*.log"
+ " | sed 's/^.*(plugin_nexthop) [^ ]* //' | sed 's/[.][0-9]*$$//'"
+)
+tr.Processes.Default.Streams.stdout = "peer.trace.gold"
+tr.Processes.Default.ReturnCode = 0
diff --git a/tests/gold_tests/pluginTest/parent_select/parent_select_peer2.test.py b/tests/gold_tests/pluginTest/parent_select/parent_select_peer2.test.py
new file mode 100644
index 0000000..e611c94
--- /dev/null
+++ b/tests/gold_tests/pluginTest/parent_select/parent_select_peer2.test.py
@@ -0,0 +1,172 @@
+'''
+'''
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+Test.Summary = '''
+Test next hop using strategies.yaml with consistent hashing, with peering, and no upstream group"
+'''
+
+# The tls_conn_timeout test will fail if it runs before this test in CI. Therefore, this test has a zzz
+# prefix so it will run last in CI.
+
+# Define and populate MicroServer.
+#
+server = Test.MakeOriginServer("server")
+response_header = {
+ "headers":
+ "HTTP/1.1 200 OK\r\n"
+ "Connection: close\r\n"
+ "Cache-control: max-age=85000\r\n"
+ "\r\n",
+ "timestamp": "1469733493.993",
+ "body": "This is the body.\n"
+}
+num_object = 16
+for i in range(num_object):
+ request_header = {
+ "headers":
+ f"GET /obj{i} HTTP/1.1\r\n"
+ "Host: does.not.matter\r\n" # But cannot be omitted.
+ "\r\n",
+ "timestamp": "1469733493.993",
+ "body": ""
+ }
+ server.addResponse("sessionlog.json", request_header, response_header)
+
+dns = Test.MakeDNServer("dns")
+
+# Define upstream trafficserver instances.
+#
+num_upstream = 6
+ts_upstream = []
+for i in range(num_upstream):
+ ts = Test.MakeATSProcess(f"ts_upstream{i}")
+ dns.addRecords(records={f"ts_upstream{i}": ["127.0.0.1"]})
+ ts.Disk.records_config.update({
+ 'proxy.config.diags.debug.enabled': 1,
+ 'proxy.config.diags.debug.tags': 'http|dns',
+ 'proxy.config.dns.nameservers': f"127.0.0.1:{dns.Variables.Port}",
+ 'proxy.config.dns.resolv_conf': "NULL",
+ })
+ ts.Disk.remap_config.AddLine(
+ f"map / http://127.0.0.1:{server.Variables.Port}"
+ )
+ ts_upstream.append(ts)
+
+# Define peer trafficserver instances.
+#
+num_peer = 8
+ts_peer = []
+for i in range(num_peer):
+ ts = Test.MakeATSProcess(f"ts_peer{i}", command=f"traffic_server 2> trace_peer{i}.log")
+ ts_peer.append(ts)
+for i in range(num_peer):
+ ts = ts_peer[i]
+ dns.addRecords(records={f"ts_peer{i}": ["127.0.0.1"]})
+
+ ts.Disk.records_config.update({
+ 'proxy.config.diags.debug.enabled': 1,
+ 'proxy.config.diags.debug.tags': 'http|dns|parent|next_hop|host_statuses|hostdb|plugin_nexthop',
+ 'proxy.config.dns.nameservers': f"127.0.0.1:{dns.Variables.Port}", # Only nameservers if resolv_conf NULL.
+ 'proxy.config.dns.resolv_conf': "NULL", # This defaults to /etc/resvolv.conf (OS namesevers) if not NULL.
+ 'proxy.config.http.cache.http': 1,
+ 'proxy.config.http.cache.required_headers': 0,
+ 'proxy.config.http.uncacheable_requests_bypass_parent': 0,
+ 'proxy.config.http.no_dns_just_forward_to_parent': 0,
+ 'proxy.config.http.parent_proxy.mark_down_hostdb': 0,
+ 'proxy.config.http.parent_proxy.self_detect': 1,
+ })
+
+ ts.Disk.File(ts.Variables.CONFIGDIR + "/strategies.yaml", id="strategies", typename="ats:config")
+ s = ts.Disk.strategies
+ s.AddLine("groups:")
+ s.AddLine(" - &peer_group")
+ for j in range(num_peer):
+ s.AddLine(f" - host: ts_peer{j}")
+ s.AddLine(f" protocol:")
+ s.AddLine(f" - scheme: http")
+ s.AddLine(f" port: {ts_peer[j].Variables.port}")
+ # The health check URL does not seem to be used currently.
+ # s.AddLine(f" health_check_url: http://ts_peer{j}:{ts_peer[j].Variables.port}")
+ s.AddLine(f" weight: 1.0")
+ s.AddLines([
+ "strategies:",
+ " - strategy: the-strategy",
+ " policy: consistent_hash",
+ " hash_key: path",
+ " go_direct: true",
+ " parent_is_proxy: true",
+ " cache_peer_result: false",
+ " ignore_self_detect: false",
+ " groups:",
+ " - *peer_group",
+ " scheme: http",
+ " failover:",
+ " ring_mode: peering_ring",
+ f" self: ts_peer{i}",
+ #" max_simple_retries: 2",
+ #" response_codes:",
+ #" - 404",
+ #" health_check:",
+ #" - passive",
+ ])
+
+ for i in range(num_upstream):
+ prefix = f"http://ts_upstream{i}:{ts_upstream[i].Variables.port}/"
+ ts.Disk.remap_config.AddLine(
+ f"map {prefix} {prefix} @plugin=parent_select.so @pparam=" +
+ ts.Variables.CONFIGDIR +
+ "/strategies.yaml @pparam=the-strategy")
+
+tr = Test.AddTestRun()
+tr.Processes.Default.StartBefore(server)
+tr.Processes.Default.StartBefore(dns)
+for i in range(num_peer):
+ tr.Processes.Default.StartBefore(ts_peer[i])
+for i in range(num_upstream):
+ tr.Processes.Default.StartBefore(ts_upstream[i])
+tr.Processes.Default.Command = 'echo start peer and upstream TSes, HTTP server and DNS server'
+tr.Processes.Default.ReturnCode = 0
+
+for i in range(num_object):
+ tr = Test.AddTestRun()
+ tr.Processes.Default.Command = (
+ f'curl --verbose --proxy 127.0.0.1:{ts_peer[i % num_peer].Variables.port} http://ts_upstream0:{ts_upstream[0].Variables.port}/obj{i}'
+ )
+ tr.Processes.Default.Streams.stdout = "peer2.body.gold"
+ tr.Processes.Default.ReturnCode = 0
+
+for i in range(num_object):
+ tr = Test.AddTestRun()
+ # num_peer must not be a multiple of 3
+ tr.Processes.Default.Command = (
+ f'curl --verbose --proxy 127.0.0.1:{ts_peer[(i * 3) % num_peer].Variables.port} http://ts_upstream0:{ts_upstream[0].Variables.port}/obj{i}'
+ )
+ tr.Processes.Default.Streams.stdout = "peer2.body.gold"
+ tr.Processes.Default.ReturnCode = 0
+
+normalize_ports = ""
+for i in range(num_upstream):
+ normalize_ports += f" | sed 's/:{ts_upstream[i].Variables.port}/:UP_PORT{i}/'"
+
+tr = Test.AddTestRun()
+tr.Processes.Default.Command = (
+ "grep -e '^+++' -e '^[A-Z].*TTP/' -e '^.alts. --' -e 'PARENT_SPECIFIED' trace_peer*.log"
+ " | sed 's/^.*(plugin_nexthop) [^ ]* //' | sed 's/[.][0-9]*$$//' " + normalize_ports
+)
+tr.Processes.Default.Streams.stdout = "peer2.trace.gold"
+tr.Processes.Default.ReturnCode = 0
diff --git a/tests/gold_tests/pluginTest/parent_select/peer.body.gold b/tests/gold_tests/pluginTest/parent_select/peer.body.gold
new file mode 100755
index 0000000..b220ced
--- /dev/null
+++ b/tests/gold_tests/pluginTest/parent_select/peer.body.gold
@@ -0,0 +1 @@
+This is the body.
diff --git a/tests/gold_tests/pluginTest/parent_select/peer.trace.gold b/tests/gold_tests/pluginTest/parent_select/peer.trace.gold
new file mode 100644
index 0000000..4c1810e
--- /dev/null
+++ b/tests/gold_tests/pluginTest/parent_select/peer.trace.gold
@@ -0,0 +1,898 @@
+trace_peer0.log:+++++++++ Incoming Request +++++++++
+trace_peer0.log:GET http://dummy.com/obj0 HTTP/1.1
+[0] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3
+trace_peer0.log:+++++++++ Proxy's Request +++++++++
+trace_peer0.log:GET http://not_used/obj0 HTTP/1.1
+[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[0] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2
+trace_peer0.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer0.log:GET http://not_used/obj0 HTTP/1.1
+trace_peer0.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer0.log:GET http://not_used/obj0 HTTP/1.1
+trace_peer0.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Incoming Request +++++++++
+trace_peer0.log:GET http://not_used/obj7 HTTP/1.1
+[1] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5
+trace_peer0.log:+++++++++ Proxy's Request +++++++++
+trace_peer0.log:GET http://also_not_used/obj7 HTTP/1.1
+[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[1] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0
+trace_peer0.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer0.log:GET http://also_not_used/obj7 HTTP/1.1
+trace_peer0.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer0.log:GET http://also_not_used/obj7 HTTP/1.1
+trace_peer0.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Incoming Request +++++++++
+trace_peer0.log:GET http://dummy.com/obj8 HTTP/1.1
+[2] state->result: PARENT_SPECIFIED Chosen parent: ts_peer6
+trace_peer0.log:+++++++++ Proxy's Request +++++++++
+trace_peer0.log:GET http://not_used/obj8 HTTP/1.1
+[2] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[2] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0
+trace_peer0.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer0.log:GET http://not_used/obj8 HTTP/1.1
+trace_peer0.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer0.log:GET http://not_used/obj8 HTTP/1.1
+trace_peer0.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Incoming Request +++++++++
+trace_peer0.log:GET http://dummy.com/obj0 HTTP/1.1
+[3] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3
+trace_peer0.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer0.log:GET http://not_used/obj0 HTTP/1.1
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Incoming Request +++++++++
+trace_peer0.log:GET http://not_used/obj7 HTTP/1.1
+[4] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5
+trace_peer0.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer0.log:GET http://also_not_used/obj7 HTTP/1.1
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Incoming Request +++++++++
+trace_peer0.log:GET http://dummy.com/obj8 HTTP/1.1
+[5] state->result: PARENT_SPECIFIED Chosen parent: ts_peer6
+trace_peer0.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer0.log:GET http://not_used/obj8 HTTP/1.1
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Incoming Request +++++++++
+trace_peer1.log:GET http://dummy.com/obj1 HTTP/1.1
+[0] state->result: PARENT_SPECIFIED Chosen parent: ts_peer5
+trace_peer1.log:+++++++++ Proxy's Request +++++++++
+trace_peer1.log:GET http://not_used/obj1 HTTP/1.1
+[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[0] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5
+trace_peer1.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer1.log:GET http://not_used/obj1 HTTP/1.1
+trace_peer1.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer1.log:GET http://not_used/obj1 HTTP/1.1
+trace_peer1.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Incoming Request +++++++++
+trace_peer1.log:GET http://dummy.com/obj9 HTTP/1.1
+[1] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7
+trace_peer1.log:+++++++++ Proxy's Request +++++++++
+trace_peer1.log:GET http://not_used/obj9 HTTP/1.1
+[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[1] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0
+trace_peer1.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer1.log:GET http://not_used/obj9 HTTP/1.1
+trace_peer1.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer1.log:GET http://not_used/obj9 HTTP/1.1
+trace_peer1.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Incoming Request +++++++++
+trace_peer1.log:GET http://not_used/obj10 HTTP/1.1
+[2] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4
+trace_peer1.log:+++++++++ Proxy's Request +++++++++
+trace_peer1.log:GET http://also_not_used/obj10 HTTP/1.1
+[2] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[2] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2
+trace_peer1.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer1.log:GET http://also_not_used/obj10 HTTP/1.1
+trace_peer1.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer1.log:GET http://also_not_used/obj10 HTTP/1.1
+trace_peer1.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Incoming Request +++++++++
+trace_peer1.log:GET http://dummy.com/obj3 HTTP/1.1
+[3] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2
+trace_peer1.log:+++++++++ Proxy's Request +++++++++
+trace_peer1.log:GET http://not_used/obj3 HTTP/1.1
+[3] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[3] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0
+trace_peer1.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer1.log:GET http://not_used/obj3 HTTP/1.1
+trace_peer1.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer1.log:GET http://not_used/obj3 HTTP/1.1
+trace_peer1.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Incoming Request +++++++++
+trace_peer1.log:GET http://not_used/obj10 HTTP/1.1
+[4] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4
+trace_peer1.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer1.log:GET http://also_not_used/obj10 HTTP/1.1
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Incoming Request +++++++++
+trace_peer1.log:GET http://dummy.com/obj11 HTTP/1.1
+[5] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7
+trace_peer1.log:+++++++++ Proxy's Request +++++++++
+trace_peer1.log:GET http://not_used/obj11 HTTP/1.1
+[5] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[5] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2
+trace_peer1.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer1.log:GET http://not_used/obj11 HTTP/1.1
+trace_peer1.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer1.log:GET http://not_used/obj11 HTTP/1.1
+trace_peer1.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Incoming Request +++++++++
+trace_peer2.log:GET http://dummy.com/obj2 HTTP/1.1
+[0] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7
+trace_peer2.log:+++++++++ Proxy's Request +++++++++
+trace_peer2.log:GET http://not_used/obj2 HTTP/1.1
+[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[0] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5
+trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer2.log:GET http://not_used/obj2 HTTP/1.1
+trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer2.log:GET http://not_used/obj2 HTTP/1.1
+trace_peer2.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Incoming Request +++++++++
+trace_peer2.log:GET http://not_used/obj3 HTTP/1.1
+[1] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0
+trace_peer2.log:+++++++++ Proxy's Request +++++++++
+trace_peer2.log:GET http://also_not_used/obj3 HTTP/1.1
+[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[1] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5
+trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer2.log:GET http://also_not_used/obj3 HTTP/1.1
+trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer2.log:GET http://also_not_used/obj3 HTTP/1.1
+trace_peer2.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Incoming Request +++++++++
+trace_peer2.log:GET http://not_used/obj4 HTTP/1.1
+[2] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0
+trace_peer2.log:+++++++++ Proxy's Request +++++++++
+trace_peer2.log:GET http://also_not_used/obj4 HTTP/1.1
+[2] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[2] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2
+trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer2.log:GET http://also_not_used/obj4 HTTP/1.1
+trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer2.log:GET http://also_not_used/obj4 HTTP/1.1
+trace_peer2.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Incoming Request +++++++++
+trace_peer2.log:GET http://not_used/obj5 HTTP/1.1
+[3] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5
+trace_peer2.log:+++++++++ Proxy's Request +++++++++
+trace_peer2.log:GET http://also_not_used/obj5 HTTP/1.1
+[3] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[3] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0
+trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer2.log:GET http://also_not_used/obj5 HTTP/1.1
+trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer2.log:GET http://also_not_used/obj5 HTTP/1.1
+trace_peer2.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Incoming Request +++++++++
+trace_peer2.log:GET http://not_used/obj6 HTTP/1.1
+[4] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5
+trace_peer2.log:+++++++++ Proxy's Request +++++++++
+trace_peer2.log:GET http://also_not_used/obj6 HTTP/1.1
+[4] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[4] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0
+trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer2.log:GET http://also_not_used/obj6 HTTP/1.1
+trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer2.log:GET http://also_not_used/obj6 HTTP/1.1
+trace_peer2.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Incoming Request +++++++++
+trace_peer2.log:GET http://dummy.com/obj10 HTTP/1.1
+[5] state->result: PARENT_SPECIFIED Chosen parent: ts_peer1
+trace_peer2.log:+++++++++ Proxy's Request +++++++++
+trace_peer2.log:GET http://not_used/obj10 HTTP/1.1
+[5] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[5] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4
+trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer2.log:GET http://not_used/obj10 HTTP/1.1
+trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer2.log:GET http://not_used/obj10 HTTP/1.1
+trace_peer2.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Incoming Request +++++++++
+trace_peer2.log:GET http://not_used/obj12 HTTP/1.1
+[6] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0
+trace_peer2.log:+++++++++ Proxy's Request +++++++++
+trace_peer2.log:GET http://also_not_used/obj12 HTTP/1.1
+[6] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[6] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4
+trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer2.log:GET http://also_not_used/obj12 HTTP/1.1
+trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer2.log:GET http://also_not_used/obj12 HTTP/1.1
+trace_peer2.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Incoming Request +++++++++
+trace_peer2.log:GET http://not_used/obj3 HTTP/1.1
+[7] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0
+trace_peer2.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer2.log:GET http://also_not_used/obj3 HTTP/1.1
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Incoming Request +++++++++
+trace_peer2.log:GET http://not_used/obj5 HTTP/1.1
+[8] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5
+trace_peer2.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer2.log:GET http://also_not_used/obj5 HTTP/1.1
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Incoming Request +++++++++
+trace_peer2.log:GET http://dummy.com/obj6 HTTP/1.1
+[9] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5
+trace_peer2.log:+++++++++ Proxy's Request +++++++++
+trace_peer2.log:GET http://not_used/obj6 HTTP/1.1
+[9] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[9] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0
+trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer2.log:GET http://not_used/obj6 HTTP/1.1
+trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer2.log:GET http://not_used/obj6 HTTP/1.1
+trace_peer2.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Incoming Request +++++++++
+trace_peer2.log:GET http://dummy.com/obj14 HTTP/1.1
+[10] state->result: PARENT_SPECIFIED Chosen parent: ts_peer5
+trace_peer2.log:+++++++++ Proxy's Request +++++++++
+trace_peer2.log:GET http://not_used/obj14 HTTP/1.1
+[10] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[10] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0
+trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer2.log:GET http://not_used/obj14 HTTP/1.1
+trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer2.log:GET http://not_used/obj14 HTTP/1.1
+trace_peer2.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Incoming Request +++++++++
+trace_peer3.log:GET http://not_used/obj0 HTTP/1.1
+[0] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2
+trace_peer3.log:+++++++++ Proxy's Request +++++++++
+trace_peer3.log:GET http://also_not_used/obj0 HTTP/1.1
+[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[0] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4
+trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer3.log:GET http://also_not_used/obj0 HTTP/1.1
+trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer3.log:GET http://also_not_used/obj0 HTTP/1.1
+trace_peer3.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Incoming Request +++++++++
+trace_peer3.log:GET http://dummy.com/obj3 HTTP/1.1
+[1] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2
+trace_peer3.log:+++++++++ Proxy's Request +++++++++
+trace_peer3.log:GET http://not_used/obj3 HTTP/1.1
+[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[1] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0
+trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer3.log:GET http://not_used/obj3 HTTP/1.1
+trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer3.log:GET http://not_used/obj3 HTTP/1.1
+trace_peer3.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Incoming Request +++++++++
+trace_peer3.log:GET http://dummy.com/obj11 HTTP/1.1
+[2] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7
+trace_peer3.log:+++++++++ Proxy's Request +++++++++
+trace_peer3.log:GET http://not_used/obj11 HTTP/1.1
+[2] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[2] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2
+trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer3.log:GET http://not_used/obj11 HTTP/1.1
+trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer3.log:GET http://not_used/obj11 HTTP/1.1
+trace_peer3.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Incoming Request +++++++++
+trace_peer3.log:GET http://not_used/obj13 HTTP/1.1
+[3] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2
+trace_peer3.log:+++++++++ Proxy's Request +++++++++
+trace_peer3.log:GET http://also_not_used/obj13 HTTP/1.1
+[3] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[3] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4
+trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer3.log:GET http://also_not_used/obj13 HTTP/1.1
+trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer3.log:GET http://also_not_used/obj13 HTTP/1.1
+trace_peer3.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Incoming Request +++++++++
+trace_peer3.log:GET http://not_used/obj15 HTTP/1.1
+[4] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4
+trace_peer3.log:+++++++++ Proxy's Request +++++++++
+trace_peer3.log:GET http://also_not_used/obj15 HTTP/1.1
+[4] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[4] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream1
+trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer3.log:GET http://also_not_used/obj15 HTTP/1.1
+trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer3.log:GET http://also_not_used/obj15 HTTP/1.1
+trace_peer3.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Incoming Request +++++++++
+trace_peer3.log:GET http://dummy.com/obj1 HTTP/1.1
+[5] state->result: PARENT_SPECIFIED Chosen parent: ts_peer5
+trace_peer3.log:+++++++++ Proxy's Request +++++++++
+trace_peer3.log:GET http://not_used/obj1 HTTP/1.1
+[5] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[5] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5
+trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer3.log:GET http://not_used/obj1 HTTP/1.1
+trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer3.log:GET http://not_used/obj1 HTTP/1.1
+trace_peer3.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Incoming Request +++++++++
+trace_peer3.log:GET http://dummy.com/obj9 HTTP/1.1
+[6] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7
+trace_peer3.log:+++++++++ Proxy's Request +++++++++
+trace_peer3.log:GET http://not_used/obj9 HTTP/1.1
+[6] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[6] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0
+trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer3.log:GET http://not_used/obj9 HTTP/1.1
+trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer3.log:GET http://not_used/obj9 HTTP/1.1
+trace_peer3.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Incoming Request +++++++++
+trace_peer3.log:GET http://not_used/obj13 HTTP/1.1
+[7] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2
+trace_peer3.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer3.log:GET http://also_not_used/obj13 HTTP/1.1
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Incoming Request +++++++++
+trace_peer3.log:GET http://not_used/obj15 HTTP/1.1
+[8] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4
+trace_peer3.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer3.log:GET http://also_not_used/obj15 HTTP/1.1
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Incoming Request +++++++++
+trace_peer4.log:GET http://dummy.com/obj4 HTTP/1.1
+[0] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2
+trace_peer4.log:+++++++++ Proxy's Request +++++++++
+trace_peer4.log:GET http://not_used/obj4 HTTP/1.1
+[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[0] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0
+trace_peer4.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer4.log:GET http://not_used/obj4 HTTP/1.1
+trace_peer4.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer4.log:GET http://not_used/obj4 HTTP/1.1
+trace_peer4.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Incoming Request +++++++++
+trace_peer4.log:GET http://dummy.com/obj12 HTTP/1.1
+[1] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2
+trace_peer4.log:+++++++++ Proxy's Request +++++++++
+trace_peer4.log:GET http://not_used/obj12 HTTP/1.1
+[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[1] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0
+trace_peer4.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer4.log:GET http://not_used/obj12 HTTP/1.1
+trace_peer4.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer4.log:GET http://not_used/obj12 HTTP/1.1
+trace_peer4.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Incoming Request +++++++++
+trace_peer4.log:GET http://dummy.com/obj4 HTTP/1.1
+[2] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2
+trace_peer4.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer4.log:GET http://not_used/obj4 HTTP/1.1
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Incoming Request +++++++++
+trace_peer4.log:GET http://dummy.com/obj12 HTTP/1.1
+[3] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2
+trace_peer4.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer4.log:GET http://not_used/obj12 HTTP/1.1
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Incoming Request +++++++++
+trace_peer5.log:GET http://not_used/obj1 HTTP/1.1
+[0] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5
+trace_peer5.log:+++++++++ Proxy's Request +++++++++
+trace_peer5.log:GET http://also_not_used/obj1 HTTP/1.1
+[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[0] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4
+trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer5.log:GET http://also_not_used/obj1 HTTP/1.1
+trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer5.log:GET http://also_not_used/obj1 HTTP/1.1
+trace_peer5.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Incoming Request +++++++++
+trace_peer5.log:GET http://dummy.com/obj5 HTTP/1.1
+[1] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2
+trace_peer5.log:+++++++++ Proxy's Request +++++++++
+trace_peer5.log:GET http://not_used/obj5 HTTP/1.1
+[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[1] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5
+trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer5.log:GET http://not_used/obj5 HTTP/1.1
+trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer5.log:GET http://not_used/obj5 HTTP/1.1
+trace_peer5.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Incoming Request +++++++++
+trace_peer5.log:GET http://dummy.com/obj13 HTTP/1.1
+[2] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3
+trace_peer5.log:+++++++++ Proxy's Request +++++++++
+trace_peer5.log:GET http://not_used/obj13 HTTP/1.1
+[2] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[2] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2
+trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer5.log:GET http://not_used/obj13 HTTP/1.1
+trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer5.log:GET http://not_used/obj13 HTTP/1.1
+trace_peer5.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Incoming Request +++++++++
+trace_peer5.log:GET http://not_used/obj14 HTTP/1.1
+[3] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0
+trace_peer5.log:+++++++++ Proxy's Request +++++++++
+trace_peer5.log:GET http://also_not_used/obj14 HTTP/1.1
+[3] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[3] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream1
+trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer5.log:GET http://also_not_used/obj14 HTTP/1.1
+trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer5.log:GET http://also_not_used/obj14 HTTP/1.1
+trace_peer5.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Incoming Request +++++++++
+trace_peer5.log:GET http://not_used/obj1 HTTP/1.1
+[4] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5
+trace_peer5.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer5.log:GET http://also_not_used/obj1 HTTP/1.1
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Incoming Request +++++++++
+trace_peer5.log:GET http://dummy.com/obj7 HTTP/1.1
+[5] state->result: PARENT_SPECIFIED Chosen parent: ts_peer0
+trace_peer5.log:+++++++++ Proxy's Request +++++++++
+trace_peer5.log:GET http://not_used/obj7 HTTP/1.1
+[5] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[5] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5
+trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer5.log:GET http://not_used/obj7 HTTP/1.1
+trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer5.log:GET http://not_used/obj7 HTTP/1.1
+trace_peer5.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Incoming Request +++++++++
+trace_peer5.log:GET http://not_used/obj14 HTTP/1.1
+[6] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0
+trace_peer5.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer5.log:GET http://also_not_used/obj14 HTTP/1.1
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Incoming Request +++++++++
+trace_peer5.log:GET http://dummy.com/obj15 HTTP/1.1
+[7] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3
+trace_peer5.log:+++++++++ Proxy's Request +++++++++
+trace_peer5.log:GET http://not_used/obj15 HTTP/1.1
+[7] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[7] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4
+trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer5.log:GET http://not_used/obj15 HTTP/1.1
+trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer5.log:GET http://not_used/obj15 HTTP/1.1
+trace_peer5.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Incoming Request +++++++++
+trace_peer6.log:GET http://dummy.com/obj6 HTTP/1.1
+[0] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2
+trace_peer6.log:+++++++++ Proxy's Request +++++++++
+trace_peer6.log:GET http://not_used/obj6 HTTP/1.1
+[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[0] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5
+trace_peer6.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer6.log:GET http://not_used/obj6 HTTP/1.1
+trace_peer6.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer6.log:GET http://not_used/obj6 HTTP/1.1
+trace_peer6.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Incoming Request +++++++++
+trace_peer6.log:GET http://not_used/obj8 HTTP/1.1
+[1] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0
+trace_peer6.log:+++++++++ Proxy's Request +++++++++
+trace_peer6.log:GET http://also_not_used/obj8 HTTP/1.1
+[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[1] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream3
+trace_peer6.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer6.log:GET http://also_not_used/obj8 HTTP/1.1
+trace_peer6.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer6.log:GET http://also_not_used/obj8 HTTP/1.1
+trace_peer6.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Incoming Request +++++++++
+trace_peer6.log:GET http://dummy.com/obj14 HTTP/1.1
+[2] state->result: PARENT_SPECIFIED Chosen parent: ts_peer5
+trace_peer6.log:+++++++++ Proxy's Request +++++++++
+trace_peer6.log:GET http://not_used/obj14 HTTP/1.1
+[2] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[2] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0
+trace_peer6.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer6.log:GET http://not_used/obj14 HTTP/1.1
+trace_peer6.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer6.log:GET http://not_used/obj14 HTTP/1.1
+trace_peer6.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Incoming Request +++++++++
+trace_peer6.log:GET http://dummy.com/obj2 HTTP/1.1
+[3] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7
+trace_peer6.log:+++++++++ Proxy's Request +++++++++
+trace_peer6.log:GET http://not_used/obj2 HTTP/1.1
+[3] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[3] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5
+trace_peer6.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer6.log:GET http://not_used/obj2 HTTP/1.1
+trace_peer6.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer6.log:GET http://not_used/obj2 HTTP/1.1
+trace_peer6.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Incoming Request +++++++++
+trace_peer6.log:GET http://dummy.com/obj10 HTTP/1.1
+[4] state->result: PARENT_SPECIFIED Chosen parent: ts_peer1
+trace_peer6.log:+++++++++ Proxy's Request +++++++++
+trace_peer6.log:GET http://not_used/obj10 HTTP/1.1
+[4] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[4] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4
+trace_peer6.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer6.log:GET http://not_used/obj10 HTTP/1.1
+trace_peer6.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer6.log:GET http://not_used/obj10 HTTP/1.1
+trace_peer6.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Incoming Request +++++++++
+trace_peer7.log:GET http://not_used/obj2 HTTP/1.1
+[0] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5
+trace_peer7.log:+++++++++ Proxy's Request +++++++++
+trace_peer7.log:GET http://also_not_used/obj2 HTTP/1.1
+[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[0] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2
+trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer7.log:GET http://also_not_used/obj2 HTTP/1.1
+trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer7.log:GET http://also_not_used/obj2 HTTP/1.1
+trace_peer7.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Incoming Request +++++++++
+trace_peer7.log:GET http://dummy.com/obj7 HTTP/1.1
+[1] state->result: PARENT_SPECIFIED Chosen parent: ts_peer0
+trace_peer7.log:+++++++++ Proxy's Request +++++++++
+trace_peer7.log:GET http://not_used/obj7 HTTP/1.1
+[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[1] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5
+trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer7.log:GET http://not_used/obj7 HTTP/1.1
+trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer7.log:GET http://not_used/obj7 HTTP/1.1
+trace_peer7.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Incoming Request +++++++++
+trace_peer7.log:GET http://not_used/obj9 HTTP/1.1
+[2] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0
+trace_peer7.log:+++++++++ Proxy's Request +++++++++
+trace_peer7.log:GET http://also_not_used/obj9 HTTP/1.1
+[2] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[2] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2
+trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer7.log:GET http://also_not_used/obj9 HTTP/1.1
+trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer7.log:GET http://also_not_used/obj9 HTTP/1.1
+trace_peer7.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Incoming Request +++++++++
+trace_peer7.log:GET http://not_used/obj11 HTTP/1.1
+[3] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2
+trace_peer7.log:+++++++++ Proxy's Request +++++++++
+trace_peer7.log:GET http://also_not_used/obj11 HTTP/1.1
+[3] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[3] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5
+trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer7.log:GET http://also_not_used/obj11 HTTP/1.1
+trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer7.log:GET http://also_not_used/obj11 HTTP/1.1
+trace_peer7.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Incoming Request +++++++++
+trace_peer7.log:GET http://dummy.com/obj15 HTTP/1.1
+[4] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3
+trace_peer7.log:+++++++++ Proxy's Request +++++++++
+trace_peer7.log:GET http://not_used/obj15 HTTP/1.1
+[4] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[4] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream4
+trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer7.log:GET http://not_used/obj15 HTTP/1.1
+trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer7.log:GET http://not_used/obj15 HTTP/1.1
+trace_peer7.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Incoming Request +++++++++
+trace_peer7.log:GET http://not_used/obj2 HTTP/1.1
+[5] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5
+trace_peer7.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer7.log:GET http://also_not_used/obj2 HTTP/1.1
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Incoming Request +++++++++
+trace_peer7.log:GET http://dummy.com/obj5 HTTP/1.1
+[6] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2
+trace_peer7.log:+++++++++ Proxy's Request +++++++++
+trace_peer7.log:GET http://not_used/obj5 HTTP/1.1
+[6] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[6] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream5
+trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer7.log:GET http://not_used/obj5 HTTP/1.1
+trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer7.log:GET http://not_used/obj5 HTTP/1.1
+trace_peer7.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Incoming Request +++++++++
+trace_peer7.log:GET http://not_used/obj9 HTTP/1.1
+[7] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream0
+trace_peer7.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer7.log:GET http://also_not_used/obj9 HTTP/1.1
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Incoming Request +++++++++
+trace_peer7.log:GET http://not_used/obj11 HTTP/1.1
+[8] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2
+trace_peer7.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer7.log:GET http://also_not_used/obj11 HTTP/1.1
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Incoming Request +++++++++
+trace_peer7.log:GET http://dummy.com/obj13 HTTP/1.1
+[9] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3
+trace_peer7.log:+++++++++ Proxy's Request +++++++++
+trace_peer7.log:GET http://not_used/obj13 HTTP/1.1
+[9] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+[9] state->result: PARENT_SPECIFIED Chosen parent: ts_upstream2
+trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer7.log:GET http://not_used/obj13 HTTP/1.1
+trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer7.log:GET http://not_used/obj13 HTTP/1.1
+trace_peer7.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
diff --git a/tests/gold_tests/pluginTest/parent_select/peer2.body.gold b/tests/gold_tests/pluginTest/parent_select/peer2.body.gold
new file mode 100644
index 0000000..b220ced
--- /dev/null
+++ b/tests/gold_tests/pluginTest/parent_select/peer2.body.gold
@@ -0,0 +1 @@
+This is the body.
diff --git a/tests/gold_tests/pluginTest/parent_select/peer2.trace.gold b/tests/gold_tests/pluginTest/parent_select/peer2.trace.gold
new file mode 100644
index 0000000..47eee1d
--- /dev/null
+++ b/tests/gold_tests/pluginTest/parent_select/peer2.trace.gold
@@ -0,0 +1,804 @@
+trace_peer0.log:+++++++++ Incoming Request +++++++++
+trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj0 HTTP/1.1
+[0] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3
+trace_peer0.log:+++++++++ Proxy's Request +++++++++
+trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj0 HTTP/1.1
+[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer0.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj0 HTTP/1.1
+trace_peer0.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj0 HTTP/1.1
+trace_peer0.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Incoming Request +++++++++
+trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1
+trace_peer0.log:+++++++++ Proxy's Request +++++++++
+trace_peer0.log:GET /obj7 HTTP/1.1
+trace_peer0.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer0.log:GET /obj7 HTTP/1.1
+trace_peer0.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1
+trace_peer0.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Incoming Request +++++++++
+trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj8 HTTP/1.1
+[2] state->result: PARENT_SPECIFIED Chosen parent: ts_peer6
+trace_peer0.log:+++++++++ Proxy's Request +++++++++
+trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj8 HTTP/1.1
+[2] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer0.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj8 HTTP/1.1
+trace_peer0.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj8 HTTP/1.1
+trace_peer0.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Incoming Request +++++++++
+trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj0 HTTP/1.1
+[3] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3
+trace_peer0.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj0 HTTP/1.1
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Incoming Request +++++++++
+trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1
+trace_peer0.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Incoming Request +++++++++
+trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj8 HTTP/1.1
+[5] state->result: PARENT_SPECIFIED Chosen parent: ts_peer6
+trace_peer0.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer0.log:GET http://ts_upstream0:UP_PORT0/obj8 HTTP/1.1
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer0.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer0.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Incoming Request +++++++++
+trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1
+[0] state->result: PARENT_SPECIFIED Chosen parent: ts_peer5
+trace_peer1.log:+++++++++ Proxy's Request +++++++++
+trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1
+[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer1.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1
+trace_peer1.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1
+trace_peer1.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Incoming Request +++++++++
+trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1
+[1] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7
+trace_peer1.log:+++++++++ Proxy's Request +++++++++
+trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1
+[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer1.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1
+trace_peer1.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1
+trace_peer1.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Incoming Request +++++++++
+trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1
+trace_peer1.log:+++++++++ Proxy's Request +++++++++
+trace_peer1.log:GET /obj10 HTTP/1.1
+trace_peer1.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer1.log:GET /obj10 HTTP/1.1
+trace_peer1.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1
+trace_peer1.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Incoming Request +++++++++
+trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1
+[3] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2
+trace_peer1.log:+++++++++ Proxy's Request +++++++++
+trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1
+[3] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer1.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1
+trace_peer1.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1
+trace_peer1.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Incoming Request +++++++++
+trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1
+trace_peer1.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Incoming Request +++++++++
+trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1
+[5] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7
+trace_peer1.log:+++++++++ Proxy's Request +++++++++
+trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1
+[5] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer1.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1
+trace_peer1.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer1.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1
+trace_peer1.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer1.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer1.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Incoming Request +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1
+[0] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7
+trace_peer2.log:+++++++++ Proxy's Request +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1
+[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1
+trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1
+trace_peer2.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Incoming Request +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1
+trace_peer2.log:+++++++++ Proxy's Request +++++++++
+trace_peer2.log:GET /obj3 HTTP/1.1
+trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer2.log:GET /obj3 HTTP/1.1
+trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1
+trace_peer2.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Incoming Request +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj4 HTTP/1.1
+trace_peer2.log:+++++++++ Proxy's Request +++++++++
+trace_peer2.log:GET /obj4 HTTP/1.1
+trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer2.log:GET /obj4 HTTP/1.1
+trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj4 HTTP/1.1
+trace_peer2.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Incoming Request +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1
+trace_peer2.log:+++++++++ Proxy's Request +++++++++
+trace_peer2.log:GET /obj5 HTTP/1.1
+trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer2.log:GET /obj5 HTTP/1.1
+trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1
+trace_peer2.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Incoming Request +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj6 HTTP/1.1
+trace_peer2.log:+++++++++ Proxy's Request +++++++++
+trace_peer2.log:GET /obj6 HTTP/1.1
+trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer2.log:GET /obj6 HTTP/1.1
+trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj6 HTTP/1.1
+trace_peer2.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Incoming Request +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1
+[5] state->result: PARENT_SPECIFIED Chosen parent: ts_peer1
+trace_peer2.log:+++++++++ Proxy's Request +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1
+[5] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1
+trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1
+trace_peer2.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Incoming Request +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj12 HTTP/1.1
+trace_peer2.log:+++++++++ Proxy's Request +++++++++
+trace_peer2.log:GET /obj12 HTTP/1.1
+trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer2.log:GET /obj12 HTTP/1.1
+trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj12 HTTP/1.1
+trace_peer2.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Incoming Request +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1
+trace_peer2.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Incoming Request +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1
+trace_peer2.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Incoming Request +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj6 HTTP/1.1
+trace_peer2.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj6 HTTP/1.1
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Incoming Request +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1
+[10] state->result: PARENT_SPECIFIED Chosen parent: ts_peer5
+trace_peer2.log:+++++++++ Proxy's Request +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1
+[10] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer2.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1
+trace_peer2.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer2.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1
+trace_peer2.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer2.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer2.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Incoming Request +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj0 HTTP/1.1
+trace_peer3.log:+++++++++ Proxy's Request +++++++++
+trace_peer3.log:GET /obj0 HTTP/1.1
+trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer3.log:GET /obj0 HTTP/1.1
+trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj0 HTTP/1.1
+trace_peer3.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Incoming Request +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1
+[1] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2
+trace_peer3.log:+++++++++ Proxy's Request +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1
+[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1
+trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj3 HTTP/1.1
+trace_peer3.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Incoming Request +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1
+[2] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7
+trace_peer3.log:+++++++++ Proxy's Request +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1
+[2] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1
+trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1
+trace_peer3.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Incoming Request +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1
+trace_peer3.log:+++++++++ Proxy's Request +++++++++
+trace_peer3.log:GET /obj13 HTTP/1.1
+trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer3.log:GET /obj13 HTTP/1.1
+trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1
+trace_peer3.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Incoming Request +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1
+trace_peer3.log:+++++++++ Proxy's Request +++++++++
+trace_peer3.log:GET /obj15 HTTP/1.1
+trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer3.log:GET /obj15 HTTP/1.1
+trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1
+trace_peer3.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Incoming Request +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1
+[5] state->result: PARENT_SPECIFIED Chosen parent: ts_peer5
+trace_peer3.log:+++++++++ Proxy's Request +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1
+[5] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1
+trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1
+trace_peer3.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Incoming Request +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1
+[6] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7
+trace_peer3.log:+++++++++ Proxy's Request +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1
+[6] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer3.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1
+trace_peer3.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1
+trace_peer3.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Incoming Request +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1
+trace_peer3.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Incoming Request +++++++++
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1
+trace_peer3.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer3.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer3.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer3.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Incoming Request +++++++++
+trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj4 HTTP/1.1
+[0] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2
+trace_peer4.log:+++++++++ Proxy's Request +++++++++
+trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj4 HTTP/1.1
+[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer4.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj4 HTTP/1.1
+trace_peer4.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj4 HTTP/1.1
+trace_peer4.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Incoming Request +++++++++
+trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj12 HTTP/1.1
+[1] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2
+trace_peer4.log:+++++++++ Proxy's Request +++++++++
+trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj12 HTTP/1.1
+[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer4.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj12 HTTP/1.1
+trace_peer4.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj12 HTTP/1.1
+trace_peer4.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Incoming Request +++++++++
+trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj4 HTTP/1.1
+[2] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2
+trace_peer4.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj4 HTTP/1.1
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Incoming Request +++++++++
+trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj12 HTTP/1.1
+[3] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2
+trace_peer4.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer4.log:GET http://ts_upstream0:UP_PORT0/obj12 HTTP/1.1
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer4.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer4.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Incoming Request +++++++++
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1
+trace_peer5.log:+++++++++ Proxy's Request +++++++++
+trace_peer5.log:GET /obj1 HTTP/1.1
+trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer5.log:GET /obj1 HTTP/1.1
+trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1
+trace_peer5.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Incoming Request +++++++++
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1
+[1] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2
+trace_peer5.log:+++++++++ Proxy's Request +++++++++
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1
+[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1
+trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1
+trace_peer5.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Incoming Request +++++++++
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1
+[2] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3
+trace_peer5.log:+++++++++ Proxy's Request +++++++++
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1
+[2] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1
+trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1
+trace_peer5.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Incoming Request +++++++++
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1
+trace_peer5.log:+++++++++ Proxy's Request +++++++++
+trace_peer5.log:GET /obj14 HTTP/1.1
+trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer5.log:GET /obj14 HTTP/1.1
+trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1
+trace_peer5.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Incoming Request +++++++++
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1
+trace_peer5.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj1 HTTP/1.1
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Incoming Request +++++++++
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1
+[5] state->result: PARENT_SPECIFIED Chosen parent: ts_peer0
+trace_peer5.log:+++++++++ Proxy's Request +++++++++
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1
+[5] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1
+trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1
+trace_peer5.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Incoming Request +++++++++
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1
+trace_peer5.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Incoming Request +++++++++
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1
+[7] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3
+trace_peer5.log:+++++++++ Proxy's Request +++++++++
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1
+[7] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer5.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1
+trace_peer5.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer5.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1
+trace_peer5.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer5.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer5.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Incoming Request +++++++++
+trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj6 HTTP/1.1
+[0] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2
+trace_peer6.log:+++++++++ Proxy's Request +++++++++
+trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj6 HTTP/1.1
+[0] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer6.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj6 HTTP/1.1
+trace_peer6.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj6 HTTP/1.1
+trace_peer6.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Incoming Request +++++++++
+trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj8 HTTP/1.1
+trace_peer6.log:+++++++++ Proxy's Request +++++++++
+trace_peer6.log:GET /obj8 HTTP/1.1
+trace_peer6.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer6.log:GET /obj8 HTTP/1.1
+trace_peer6.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj8 HTTP/1.1
+trace_peer6.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Incoming Request +++++++++
+trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1
+[2] state->result: PARENT_SPECIFIED Chosen parent: ts_peer5
+trace_peer6.log:+++++++++ Proxy's Request +++++++++
+trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1
+[2] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer6.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1
+trace_peer6.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj14 HTTP/1.1
+trace_peer6.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Incoming Request +++++++++
+trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1
+[3] state->result: PARENT_SPECIFIED Chosen parent: ts_peer7
+trace_peer6.log:+++++++++ Proxy's Request +++++++++
+trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1
+[3] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer6.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1
+trace_peer6.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1
+trace_peer6.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Incoming Request +++++++++
+trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1
+[4] state->result: PARENT_SPECIFIED Chosen parent: ts_peer1
+trace_peer6.log:+++++++++ Proxy's Request +++++++++
+trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1
+[4] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer6.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1
+trace_peer6.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer6.log:GET http://ts_upstream0:UP_PORT0/obj10 HTTP/1.1
+trace_peer6.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer6.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer6.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Incoming Request +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1
+trace_peer7.log:+++++++++ Proxy's Request +++++++++
+trace_peer7.log:GET /obj2 HTTP/1.1
+trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer7.log:GET /obj2 HTTP/1.1
+trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1
+trace_peer7.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Incoming Request +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1
+[1] state->result: PARENT_SPECIFIED Chosen parent: ts_peer0
+trace_peer7.log:+++++++++ Proxy's Request +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1
+[1] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1
+trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj7 HTTP/1.1
+trace_peer7.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Incoming Request +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1
+trace_peer7.log:+++++++++ Proxy's Request +++++++++
+trace_peer7.log:GET /obj9 HTTP/1.1
+trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer7.log:GET /obj9 HTTP/1.1
+trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1
+trace_peer7.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Incoming Request +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1
+trace_peer7.log:+++++++++ Proxy's Request +++++++++
+trace_peer7.log:GET /obj11 HTTP/1.1
+trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer7.log:GET /obj11 HTTP/1.1
+trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1
+trace_peer7.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Incoming Request +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1
+[4] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3
+trace_peer7.log:+++++++++ Proxy's Request +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1
+[4] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1
+trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj15 HTTP/1.1
+trace_peer7.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Incoming Request +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1
+trace_peer7.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj2 HTTP/1.1
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Incoming Request +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1
+[6] state->result: PARENT_SPECIFIED Chosen parent: ts_peer2
+trace_peer7.log:+++++++++ Proxy's Request +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1
+[6] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1
+trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj5 HTTP/1.1
+trace_peer7.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Incoming Request +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1
+trace_peer7.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj9 HTTP/1.1
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Incoming Request +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1
+trace_peer7.log:[alts] ---- alternate #1 (Q = 1) has these request/response hdrs:
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj11 HTTP/1.1
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Incoming Request +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1
+[9] state->result: PARENT_SPECIFIED Chosen parent: ts_peer3
+trace_peer7.log:+++++++++ Proxy's Request +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1
+[9] not firstcall, line_number: 0, result: PARENT_SPECIFIED
+trace_peer7.log:+++++++++ Proxy's Request after hooks +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1
+trace_peer7.log:+++++++++ Incoming O.S. Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Cached Request Hdr +++++++++
+trace_peer7.log:GET http://ts_upstream0:UP_PORT0/obj13 HTTP/1.1
+trace_peer7.log:+++++++++ Base Header for Building Response +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
+trace_peer7.log:+++++++++ Proxy's Response 2 +++++++++
+trace_peer7.log:HTTP/1.1 200 OK
diff --git a/tests/gold_tests/pluginTest/parent_select/trace.gold b/tests/gold_tests/pluginTest/parent_select/trace.gold
new file mode 100755
index 0000000..05120d3
--- /dev/null
+++ b/tests/gold_tests/pluginTest/parent_select/trace.gold
@@ -0,0 +1,96 @@
+nh_trace0.log:HTTP/1.1 200 OK
+nh_trace0.log:HTTP/1.1 200 OK
+nh_trace0.log:HTTP/1.1 200 OK
+nh_trace0.log:HTTP/1.1 200 OK
+nh_trace0.log:HTTP/1.1 200 OK
+nh_trace0.log:HTTP/1.1 200 OK
+nh_trace0.log:HTTP/1.1 200 OK
+nh_trace0.log:HTTP/1.1 200 OK
+nh_trace0.log:HTTP/1.1 200 OK
+nh_trace1.log:HTTP/1.1 200 OK
+nh_trace1.log:HTTP/1.1 200 OK
+nh_trace1.log:HTTP/1.1 200 OK
+nh_trace1.log:HTTP/1.1 200 OK
+nh_trace1.log:HTTP/1.1 200 OK
+nh_trace1.log:HTTP/1.1 200 OK
+nh_trace1.log:HTTP/1.1 200 OK
+nh_trace1.log:HTTP/1.1 200 OK
+nh_trace1.log:HTTP/1.1 200 OK
+nh_trace1.log:HTTP/1.1 200 OK
+nh_trace1.log:HTTP/1.1 200 OK
+nh_trace1.log:HTTP/1.1 200 OK
+nh_trace2.log:HTTP/1.1 200 OK
+nh_trace2.log:HTTP/1.1 200 OK
+nh_trace2.log:HTTP/1.1 200 OK
+nh_trace2.log:HTTP/1.1 200 OK
+nh_trace2.log:HTTP/1.1 200 OK
+nh_trace2.log:HTTP/1.1 200 OK
+nh_trace2.log:HTTP/1.1 200 OK
+nh_trace2.log:HTTP/1.1 200 OK
+nh_trace2.log:HTTP/1.1 200 OK
+nh_trace2.log:HTTP/1.1 200 OK
+nh_trace2.log:HTTP/1.1 200 OK
+nh_trace2.log:HTTP/1.1 200 OK
+nh_trace3.log:HTTP/1.1 200 OK
+nh_trace3.log:HTTP/1.1 200 OK
+nh_trace3.log:HTTP/1.1 200 OK
+nh_trace3.log:HTTP/1.1 200 OK
+nh_trace3.log:HTTP/1.1 200 OK
+nh_trace3.log:HTTP/1.1 200 OK
+nh_trace3.log:HTTP/1.1 200 OK
+nh_trace3.log:HTTP/1.1 200 OK
+nh_trace3.log:HTTP/1.1 200 OK
+nh_trace3.log:HTTP/1.1 200 OK
+nh_trace3.log:HTTP/1.1 200 OK
+nh_trace3.log:HTTP/1.1 200 OK
+nh_trace3.log:HTTP/1.1 200 OK
+nh_trace3.log:HTTP/1.1 200 OK
+nh_trace3.log:HTTP/1.1 200 OK
+nh_trace4.log:HTTP/1.1 200 OK
+nh_trace4.log:HTTP/1.1 200 OK
+nh_trace4.log:HTTP/1.1 200 OK
+nh_trace4.log:HTTP/1.1 200 OK
+nh_trace4.log:HTTP/1.1 200 OK
+nh_trace4.log:HTTP/1.1 200 OK
+nh_trace4.log:HTTP/1.1 200 OK
+nh_trace4.log:HTTP/1.1 200 OK
+nh_trace4.log:HTTP/1.1 200 OK
+nh_trace4.log:HTTP/1.1 200 OK
+nh_trace4.log:HTTP/1.1 200 OK
+nh_trace4.log:HTTP/1.1 200 OK
+nh_trace4.log:HTTP/1.1 200 OK
+nh_trace4.log:HTTP/1.1 200 OK
+nh_trace4.log:HTTP/1.1 200 OK
+nh_trace5.log:HTTP/1.1 200 OK
+nh_trace5.log:HTTP/1.1 200 OK
+nh_trace5.log:HTTP/1.1 200 OK
+nh_trace5.log:HTTP/1.1 200 OK
+nh_trace5.log:HTTP/1.1 200 OK
+nh_trace5.log:HTTP/1.1 200 OK
+nh_trace5.log:HTTP/1.1 200 OK
+nh_trace5.log:HTTP/1.1 200 OK
+nh_trace5.log:HTTP/1.1 200 OK
+nh_trace6.log:HTTP/1.1 200 OK
+nh_trace6.log:HTTP/1.1 200 OK
+nh_trace6.log:HTTP/1.1 200 OK
+nh_trace6.log:HTTP/1.1 200 OK
+nh_trace6.log:HTTP/1.1 200 OK
+nh_trace6.log:HTTP/1.1 200 OK
+nh_trace6.log:HTTP/1.1 200 OK
+nh_trace6.log:HTTP/1.1 200 OK
+nh_trace6.log:HTTP/1.1 200 OK
+nh_trace6.log:HTTP/1.1 200 OK
+nh_trace6.log:HTTP/1.1 200 OK
+nh_trace6.log:HTTP/1.1 200 OK
+nh_trace6.log:HTTP/1.1 200 OK
+nh_trace6.log:HTTP/1.1 200 OK
+nh_trace6.log:HTTP/1.1 200 OK
+nh_trace6.log:HTTP/1.1 200 OK
+nh_trace6.log:HTTP/1.1 200 OK
+nh_trace6.log:HTTP/1.1 200 OK
+nh_trace7.log:HTTP/1.1 200 OK
+nh_trace7.log:HTTP/1.1 200 OK
+nh_trace7.log:HTTP/1.1 200 OK
+nh_trace7.log:HTTP/1.1 200 OK
+nh_trace7.log:HTTP/1.1 200 OK
+nh_trace7.log:HTTP/1.1 200 OK