You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by am...@apache.org on 2012/12/10 18:03:21 UTC
[1/2] git commit: TS-1422 TS-1307 : Update HostDB for better IPv6
handling.
Updated Branches:
refs/heads/master 998810c16 -> 043815e7a
TS-1422 TS-1307 : Update HostDB for better IPv6 handling.
Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/043815e7
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/043815e7
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/043815e7
Branch: refs/heads/master
Commit: 043815e7a7a67b79a2ca6fdc3f6d6751e5150411
Parents: 998810c
Author: Alan M. Carroll <am...@network-geographics.com>
Authored: Mon Dec 10 11:02:42 2012 -0600
Committer: Alan M. Carroll <am...@network-geographics.com>
Committed: Mon Dec 10 11:02:42 2012 -0600
----------------------------------------------------------------------
CHANGES | 5 +
iocore/dns/DNS.cc | 122 +++---
iocore/dns/I_DNSProcessor.h | 107 ++++-
iocore/dns/P_DNSProcessor.h | 6 +-
iocore/hostdb/HostDB.cc | 713 ++++++++++++++++------------
iocore/hostdb/I_HostDBProcessor.h | 62 ++-
iocore/hostdb/P_HostDB.h | 6 +-
iocore/hostdb/P_HostDBProcessor.h | 154 ++++--
iocore/hostdb/P_MultiCache.h | 4 +-
lib/records/I_RecHttp.h | 13 +
lib/records/RecHttp.cc | 64 +++-
lib/ts/INK_MD5.h | 6 +-
lib/ts/ink_inet.h | 43 ++-
lib/ts/ink_res_init.cc | 84 ++++
lib/ts/ink_res_mkquery.cc | 35 ++
lib/ts/ink_resolver.h | 67 +++
mgmt/Main.cc | 1 +
mgmt/RecordsConfig.cc | 2 +
proxy/http/HttpAccept.cc | 1 +
proxy/http/HttpAccept.h | 14 +-
proxy/http/HttpClientSession.cc | 5 +-
proxy/http/HttpClientSession.h | 2 +
proxy/http/HttpProxyServerMain.cc | 1 +
proxy/http/HttpSM.cc | 71 ++--
proxy/http/HttpTransact.cc | 151 ++++---
proxy/http/HttpTransact.h | 21 +-
proxy/logging/LogCollationClientSM.cc | 2 +-
27 files changed, 1181 insertions(+), 581 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/043815e7/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index d37ae5a..39d0ffb 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,11 @@
-*- coding: utf-8 -*-
Changes with Apache Traffic Server 3.3.1
+ *) [TS-1307] [TS-1422] Changed HostDB handling of IPv4 and
+ IPv6. Address resolution preferences can be configured globally and
+ per HTTP proxy port. Transparent connections can now fail over even
+ if use_client_target_addr is set.
+
*) [TS-1616] authorization proxy plugin
*) [TS-1615] Some spelling errors in source code
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/043815e7/iocore/dns/DNS.cc
----------------------------------------------------------------------
diff --git a/iocore/dns/DNS.cc b/iocore/dns/DNS.cc
index 63f638f..31dda7a 100644
--- a/iocore/dns/DNS.cc
+++ b/iocore/dns/DNS.cc
@@ -57,20 +57,12 @@ char *dns_local_ipv4 = NULL;
int dns_thread = 0;
int dns_prefer_ipv6 = 0;
namespace {
- inline bool prefer_ipv6_p() { return 0 != dns_prefer_ipv6; }
- inline int preferred_query_type() { return prefer_ipv6_p() ? T_AAAA : T_A; }
// Currently only used for A and AAAA.
inline char const* QtypeName(int qtype) {
return T_AAAA == qtype ? "AAAA" : T_A == qtype ? "A" : "*";
}
- inline void set_loopback(sockaddr* addr) {
- if (prefer_ipv6_p())
- ats_ip6_set(addr, in6addr_loopback, htons(DOMAIN_SERVICE_PORT));
- else
- ats_ip4_set(addr, htonl(INADDR_LOOPBACK), htons(DOMAIN_SERVICE_PORT));
- }
- inline void set_loopback(IpEndpoint* ip) {
- set_loopback(&ip->sa);
+ inline bool is_addr_query(int qtype) {
+ return qtype == T_A || qtype == T_AAAA;
}
}
@@ -116,10 +108,6 @@ void HostEnt::free() {
dnsBufAllocator.free(this);
}
-inline bool is_addr_type_reply(int qtype) {
- return qtype == T_A || qtype == T_AAAA;
-}
-
void
make_ipv4_ptr(in_addr_t addr, char *buffer)
{
@@ -193,7 +181,6 @@ DNSProcessor::start(int) {
IOCORE_ReadConfigStringAlloc(dns_local_ipv6, "proxy.config.dns.local_ipv6");
IOCORE_ReadConfigStringAlloc(dns_resolv_conf, "proxy.config.dns.resolv_conf");
IOCORE_EstablishStaticConfigInt32(dns_thread, "proxy.config.dns.dedicated_thread");
- IOCORE_EstablishStaticConfigInt32(dns_prefer_ipv6, "proxy.config.dns.prefer_ipv6");
if (dns_thread > 0) {
ET_DNS = eventProcessor.spawn_event_threads(1, "ET_DNS"); // TODO: Hmmm, should we just get a single thread some other way?
@@ -353,23 +340,34 @@ ink_dn_expand(const u_char *msg, const u_char *eom, const u_char *comp_dn, u_cha
DNSProcessor::DNSProcessor()
: thread(NULL), handler(NULL)
{
- memset(&l_res, 0, sizeof(l_res));
- memset(&local_ipv6, 0, sizeof local_ipv6);
- memset(&local_ipv4, 0, sizeof local_ipv4);
+ ink_zero(l_res);
+ ink_zero(local_ipv6);
+ ink_zero(local_ipv4);
}
void
-DNSEntry::init(const char *x, int len, int qtype_arg,
- Continuation *acont, DNSHandler *adnsH, int dns_lookup_timeout)
+DNSEntry::init(const char *x, int len, int qtype_arg, Continuation* acont,
+ DNSProcessor::Options const& opt)
{
qtype = qtype_arg;
+ host_res_style = opt.host_res_style;
+ if (is_addr_query(qtype)) {
+ // adjust things based on family preference.
+ if (HOST_RES_IPV4 == host_res_style ||
+ HOST_RES_IPV4_ONLY == host_res_style) {
+ qtype = T_A;
+ } else if (HOST_RES_IPV6 == host_res_style ||
+ HOST_RES_IPV6_ONLY == host_res_style) {
+ qtype = T_AAAA;
+ }
+ }
submit_time = ink_get_hrtime();
action = acont;
submit_thread = acont->mutex->thread_holding;
#ifdef SPLIT_DNS
if (SplitDNSConfig::gsplit_dns_enabled) {
- dnsH = adnsH ? adnsH : dnsProcessor.handler;
+ dnsH = opt.handler ? opt.handler : dnsProcessor.handler;
} else {
dnsH = dnsProcessor.handler;
}
@@ -378,11 +376,11 @@ DNSEntry::init(const char *x, int len, int qtype_arg,
dnsH = dnsProcessor.handler;
#endif // SPLIT_DNS
- dnsH->txn_lookup_timeout = dns_lookup_timeout;
+ dnsH->txn_lookup_timeout = opt.timeout;
mutex = dnsH->mutex;
- if (is_addr_type_reply(qtype) || qtype == T_SRV) {
+ if (is_addr_query(qtype) || qtype == T_SRV) {
if (len) {
len = len > (MAXDNAME - 1) ? (MAXDNAME - 1) : len;
memcpy(qname, x, len);
@@ -393,11 +391,11 @@ DNSEntry::init(const char *x, int len, int qtype_arg,
qname_len = strlen(qname);
}
} else { //T_PTR
- sockaddr const* ip = reinterpret_cast<sockaddr const*>(x);
- if (ats_is_ip6(ip))
- make_ipv6_ptr(&ats_ip6_addr_cast(ip), qname);
- else if (ats_is_ip4(ip))
- make_ipv4_ptr(ats_ip4_addr_cast(ip), qname);
+ IpAddr const* ip = reinterpret_cast<IpAddr const*>(x);
+ if (ip->isIp6())
+ make_ipv6_ptr(&ip->_addr._ip6, qname);
+ else if (ip->isIp4())
+ make_ipv4_ptr(ip->_addr._ip4, qname);
else
ink_assert(!"T_PTR query to DNS must be IP address.");
}
@@ -459,14 +457,12 @@ DNSHandler::open_con(sockaddr const* target, bool failed, int icon)
void
DNSHandler::validate_ip() {
- if (!ats_is_ip(&ip.sa)) {
+ if (!ip.isValid()) {
// Invalid, switch to default.
// seems that res_init always sets m_res.nscount to at least 1!
if (!m_res->nscount || !ats_ip_copy(&ip.sa, &m_res->nsaddr_list[0].sa)) {
- Warning("bad nameserver config, fallback to %s loopback",
- prefer_ipv6_p() ? "IPv6" : "IPv4"
- );
- set_loopback(&ip);
+ Warning("bad nameserver config, fallback to loopback");
+ ip.setToLoopback(AF_INET);
}
}
}
@@ -572,7 +568,7 @@ DNSHandler::retry_named(int ndx, ink_hrtime t, bool reopen)
char buffer[MAX_DNS_PACKET_LEN];
Debug("dns", "trying to resolve '%s' from DNS connection, ndx %d", try_server_names[try_servers], ndx);
- int r = _ink_res_mkquery(m_res, try_server_names[try_servers], preferred_query_type(), buffer);
+ int r = _ink_res_mkquery(m_res, try_server_names[try_servers], T_A, buffer);
try_servers = (try_servers + 1) % SIZE(try_server_names);
ink_assert(r >= 0);
if (r >= 0) { // looking for a bounce
@@ -595,7 +591,7 @@ DNSHandler::try_primary_named(bool reopen)
last_primary_retry = t;
Debug("dns", "trying to resolve '%s' from primary DNS connection", try_server_names[try_servers]);
- int r = _ink_res_mkquery(m_res, try_server_names[try_servers], preferred_query_type(), buffer);
+ int r = _ink_res_mkquery(m_res, try_server_names[try_servers], T_A, buffer);
// if try_server_names[] is not full, round-robin within the
// filled entries.
if (local_num_entries < DEFAULT_NUM_TRY_SERVER)
@@ -647,7 +643,7 @@ DNSHandler::failover()
ats_ip_ntop(&target.sa, buff2, sizeof(buff2))
);
- if (!ats_is_ip(&target.sa)) set_loopback(&target.sa);
+ if (!target.isValid()) target.setToLoopback(AF_INET);
open_con(&target.sa, true, name_server);
if (n_con <= name_server)
@@ -876,7 +872,7 @@ get_entry(DNSHandler *h, char *qname, int qtype)
{
for (DNSEntry *e = h->entries.head; e; e = (DNSEntry *) e->link.next) {
if (e->qtype == qtype) {
- if (is_addr_type_reply(qtype)) {
+ if (is_addr_query(qtype)) {
if (!strcmp(qname, e->qname))
return e;
} else if (0 == memcmp(qname, e->qname, e->qname_len))
@@ -1091,14 +1087,15 @@ DNSEntry::mainEvent(int event, Event *e)
}
Action *
-DNSProcessor::getby(const char *x, int len, int type, Continuation *cont, DNSHandler *adnsH, int timeout) {
- Debug("dns", "received query %s type = %d, timeout = %d", x, type, timeout);
+DNSProcessor::getby(const char *x, int len, int type, Continuation *cont, Options const& opt)
+{
+ Debug("dns", "received query %s type = %d, timeout = %d", x, type, opt.timeout);
if (type == T_SRV) {
- Debug("dns_srv", "DNSProcessor::getby attempting an SRV lookup for %s, timeout = %d", x, timeout);
+ Debug("dns_srv", "DNSProcessor::getby attempting an SRV lookup for %s, timeout = %d", x, opt.timeout);
}
DNSEntry *e = dnsEntryAllocator.alloc();
e->retries = dns_retries;
- e->init(x, len, type, cont, adnsH, timeout);
+ e->init(x, len, type, cont, opt);
MUTEX_TRY_LOCK(lock, e->mutex, this_ethread());
if (!lock)
thread->schedule_imm(e);
@@ -1126,18 +1123,6 @@ dns_result(DNSHandler *h, DNSEntry *e, HostEnt *ent, bool retry) {
--(e->retries);
write_dns(h);
return;
- } else if (prefer_ipv6_p() && e->qtype == T_AAAA) {
- Debug("dns", "Trying A after AAAA failure for %s", e->qname);
- e->retries = dns_retries;
- e->qtype = T_A;
- write_dns(h);
- return;
- } else if (!prefer_ipv6_p() && e->qtype == T_A) {
- Debug("dns", "Trying AAAA after A failure for %s", e->qname);
- e->retries = dns_retries;
- e->qtype = T_AAAA;
- write_dns(h);
- return;
} else if (e->domains && *e->domains) {
do {
Debug("dns", "domain extending %s", e->qname);
@@ -1196,15 +1181,20 @@ dns_result(DNSHandler *h, DNSEntry *e, HostEnt *ent, bool retry) {
}
h->entries.remove(e);
- if (is_addr_type_reply(e->qtype)) {
- ip_text_buffer buff;
- char const* ptr = "<none>";
- if (ent) ptr = inet_ntop(e->qtype == T_AAAA ? AF_INET6 : AF_INET, ent->ent.h_addr_list[0], buff, sizeof(buff));
- Debug("dns", "%s result for %s = %s retry %d",
- ent ? "SUCCESS" : "FAIL", e->qname, ptr, retry);
- } else {
- Debug("dns", "%s result for %s = %s retry %d",
- ent ? "SUCCESS" : "FAIL", e->qname, (ent != NULL ? ent->ent.h_name : "<not found>"), retry);
+ if (is_debug_tag_set("dns")) {
+ if (is_addr_query(e->qtype)) {
+ ip_text_buffer buff;
+ char const* ptr = "<none>";
+ char const* result = "FAIL";
+ if (ent) {
+ result = "SUCCESS";
+ ptr = inet_ntop(e->qtype == T_AAAA ? AF_INET6 : AF_INET, ent->ent.h_addr_list[0], buff, sizeof(buff));
+ }
+ Debug("dns", "%s result for %s = %s retry %d", result, e->qname, ptr, retry);
+ } else {
+ Debug("dns", "%s result for %s = %s af=%d retry %d",
+ ent ? "SUCCESS" : "FAIL", e->qname, (ent != NULL ? ent->ent.h_name : "<not found>"), ent->ent.h_addrtype, retry);
+ }
}
if (ent) {
@@ -1398,7 +1388,7 @@ dns_process(DNSHandler *handler, HostEnt *buf, int len)
}
cp += n + QFIXEDSZ;
- if (is_addr_type_reply(e->qtype)) {
+ if (is_addr_query(e->qtype)) {
if (-1 == rname_len)
n = strlen((char *)bp) + 1;
else
@@ -1473,7 +1463,7 @@ dns_process(DNSHandler *handler, HostEnt *buf, int len)
//
// Decode cname
//
- if (is_addr_type_reply(e->qtype) && type == T_CNAME) {
+ if (is_addr_query(e->qtype) && type == T_CNAME) {
if (ap >= &buf->host_aliases[DNS_MAX_ALIASES - 1])
continue;
n = ink_dn_expand((u_char *) h, eom, cp, tbuf, sizeof(tbuf));
@@ -1551,7 +1541,7 @@ dns_process(DNSHandler *handler, HostEnt *buf, int len)
buf->srv_hosts.insert(s);
++num_srv;
- } else if (is_addr_type_reply(type)) {
+ } else if (is_addr_query(type)) {
if (answer) {
if (n != buf->ent.h_length) {
cp += n;
@@ -1700,7 +1690,7 @@ struct DNSRegressionContinuation: public Continuation
}
}
if (i < hosts) {
- dnsProcessor.gethostbyname(this, hostnames[i]);
+ dnsProcessor.gethostbyname(this, hostnames[i], DNSProcessor::Options().setHostResStyle(HOST_RES_IPV4_ONLY));
++i;
return EVENT_CONT;
} else {
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/043815e7/iocore/dns/I_DNSProcessor.h
----------------------------------------------------------------------
diff --git a/iocore/dns/I_DNSProcessor.h b/iocore/dns/I_DNSProcessor.h
index 2375178..28c13a5 100644
--- a/iocore/dns/I_DNSProcessor.h
+++ b/iocore/dns/I_DNSProcessor.h
@@ -68,17 +68,50 @@ struct DNSProcessor: public Processor
// Public Interface
//
+ /// Options for host name resolution.
+ struct Options {
+ typedef Options self; ///< Self reference type.
+
+ /// Query handler to use.
+ /// Default: single threaded handler.
+ DNSHandler* handler;
+ /// Query timeout value.
+ /// Default: @c DEFAULT_DNS_TIMEOUT (or as set in records.config)
+ int timeout; ///< Timeout value for request.
+ /// Host resolution style.
+ /// Default: IPv4, IPv6 ( @c HOST_RES_IPV4 )
+ HostResStyle host_res_style;
+
+ /// Default constructor.
+ Options();
+
+ /// Set @a handler option.
+ /// @return This object.
+ self& setHandler(DNSHandler* handler);
+
+ /// Set @a timeout option.
+ /// @return This object.
+ self& setTimeout(int timeout);
+
+ /// Set host query @a style option.
+ /// @return This object.
+ self& setHostResStyle(HostResStyle style);
+
+ /// Reset to default constructed values.
+ /// @return This object.
+ self& reset();
+ };
+
// DNS lookup
// calls: cont->handleEvent( DNS_EVENT_LOOKUP, HostEnt *ent) on success
// cont->handleEvent( DNS_EVENT_LOOKUP, NULL) on failure
// NOTE: the HostEnt *block is freed when the function returns
//
- Action *gethostbyname(Continuation *cont, const char *name, DNSHandler *adnsH = 0, int timeout = 0);
- Action *getSRVbyname(Continuation *cont, const char *name, DNSHandler *adnsH = 0, int timeout = 0);
- Action *gethostbyname(Continuation *cont, const char *name, int len, int timeout = 0);
- Action *gethostbyaddr(Continuation *cont, in_addr_t ip, int timeout = 0);
- Action *gethostbyaddr(Continuation *cont, sockaddr const* ip, int timeout = 0);
+ Action *gethostbyname(Continuation *cont, const char *name, Options const& opt);
+ Action *getSRVbyname(Continuation *cont, const char *name, Options const& opt);
+ Action *gethostbyname(Continuation *cont, const char *name, int len, Options const& opt);
+ Action *gethostbyaddr(Continuation *cont, IpAddr const* ip, Options const& opt);
// Processor API
@@ -100,7 +133,16 @@ struct DNSProcessor: public Processor
ts_imp_res_state l_res;
IpEndpoint local_ipv6;
IpEndpoint local_ipv4;
- Action *getby(const char *x, int len, int type, Continuation *cont, DNSHandler *adnsH = NULL, int timeout = 0);
+
+ /** Internal implementation for all getXbyY methods.
+ For host resolution queries pass @c T_A for @a type. It will be adjusted
+ as needed based on @a opt.host_res_style.
+
+ For address resolution ( @a type is @c T_PTR ), @a x should be a
+ @c sockaddr cast to @c char @c const* .
+ */
+ Action *getby(const char *x, int len, int type, Continuation *cont, Options const& opt);
+
void dns_init();
};
@@ -115,35 +157,62 @@ extern DNSProcessor dnsProcessor;
//
inline Action *
-DNSProcessor::getSRVbyname(Continuation *cont, const char *name, DNSHandler *adnsH, int timeout)
+DNSProcessor::getSRVbyname(Continuation *cont, const char *name, Options const& opt)
{
- return getby(name, 0, T_SRV, cont, adnsH, timeout);
+ return getby(name, 0, T_SRV, cont, opt);
}
inline Action *
-DNSProcessor::gethostbyname(Continuation *cont, const char *name, DNSHandler *adnsH, int timeout)
+DNSProcessor::gethostbyname(Continuation *cont, const char *name, Options const& opt)
{
- return getby(name, 0, T_A, cont, adnsH, timeout);
+ return getby(name, 0, T_A, cont, opt);
}
inline Action *
-DNSProcessor::gethostbyname(Continuation *cont, const char *name, int len, int timeout)
+DNSProcessor::gethostbyname(Continuation *cont, const char *name, int len, Options const& opt)
{
- return getby(name, len, T_A, cont, NULL, timeout);
+ return getby(name, len, T_A, cont, opt);
}
inline Action *
-DNSProcessor::gethostbyaddr(Continuation *cont, in_addr_t addr, int timeout)
+DNSProcessor::gethostbyaddr(Continuation *cont, IpAddr const* addr, Options const& opt)
{
- sockaddr_in ip;
- ats_ip4_set(&ip, addr);
- return getby(reinterpret_cast<char const*>(&ip), 0, T_PTR, cont, NULL, timeout);
+ return getby(reinterpret_cast<char const*>(addr), 0, T_PTR, cont, opt);
}
-inline Action *
-DNSProcessor::gethostbyaddr(Continuation *cont, sockaddr const* addr, int timeout)
+inline DNSProcessor::Options::Options()
+ : handler(0)
+ , timeout(0)
+ , host_res_style(HOST_RES_IPV4)
+{
+}
+
+inline DNSProcessor::Options&
+DNSProcessor::Options::setHandler(DNSHandler* h)
+{
+ handler = h;
+ return *this;
+}
+
+inline DNSProcessor::Options&
+DNSProcessor::Options::setTimeout(int t)
+{
+ timeout = t;
+ return *this;
+}
+
+inline DNSProcessor::Options&
+DNSProcessor::Options::setHostResStyle(HostResStyle style)
+{
+ host_res_style = style;
+ return *this;
+}
+
+inline DNSProcessor::Options&
+DNSProcessor::Options::reset()
{
- return getby(reinterpret_cast<char const*>(addr), 0, T_PTR, cont, NULL, timeout);
+ *this = Options();
+ return *this;
}
void ink_dns_init(ModuleVersion version);
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/043815e7/iocore/dns/P_DNSProcessor.h
----------------------------------------------------------------------
diff --git a/iocore/dns/P_DNSProcessor.h b/iocore/dns/P_DNSProcessor.h
index 3f74082..e5b79f8 100644
--- a/iocore/dns/P_DNSProcessor.h
+++ b/iocore/dns/P_DNSProcessor.h
@@ -148,7 +148,8 @@ extern RecRawStatBlock *dns_rsb;
struct DNSEntry: public Continuation
{
int id[MAX_DNS_RETRIES];
- int qtype;
+ int qtype; ///< Type of query to send.
+ HostResStyle host_res_style; ///< Preferred IP address family.
int retries;
int which_ns;
ink_hrtime submit_time;
@@ -171,11 +172,12 @@ struct DNSEntry: public Continuation
int delayEvent(int event, Event *e);
int post(DNSHandler *h, HostEnt *ent);
int postEvent(int event, Event *e);
- void init(const char *x, int len, int qtype_arg, Continuation *acont, DNSHandler *adnsH, int timeout);
+ void init(const char *x, int len, int qtype_arg, Continuation *acont, DNSProcessor::Options const& opt);
DNSEntry()
: Continuation(NULL),
qtype(0),
+ host_res_style(HOST_RES_NONE),
retries(DEFAULT_DNS_RETRIES),
which_ns(NO_NAMESERVER_SELECTED), submit_time(0), send_time(0), qname_len(0), domains(0),
timeout(0), result_ent(0), dnsH(0), written_flag(false), once_written_flag(false), last(false)
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/043815e7/iocore/hostdb/HostDB.cc
----------------------------------------------------------------------
diff --git a/iocore/hostdb/HostDB.cc b/iocore/hostdb/HostDB.cc
index b05b4f7..418a2ff 100644
--- a/iocore/hostdb/HostDB.cc
+++ b/iocore/hostdb/HostDB.cc
@@ -47,6 +47,8 @@
HostDBProcessor hostDBProcessor;
int HostDBProcessor::hostdb_strict_round_robin = 0;
int HostDBProcessor::hostdb_timed_round_robin = 0;
+HostDBProcessor::Options const HostDBProcessor::DEFAULT_OPTIONS;
+HostDBContinuation::Options const HostDBContinuation::DEFAULT_OPTIONS;
int hostdb_enable = true;
int hostdb_migrate_on_demand = true;
int hostdb_cluster = false;
@@ -70,8 +72,7 @@ ClassAllocator<HostDBContinuation> hostDBContAllocator("hostDBContAllocator");
// Static configuration information
-HostDBCache
- hostDB;
+HostDBCache hostDB;
#ifdef NON_MODULAR
static Queue <HostDBContinuation > remoteHostDBQueue[MULTI_CACHE_PARTITIONS];
@@ -109,6 +110,20 @@ ip_addr_set(
else ats_ip_invalidate(ip);
}
+static inline void
+ip_addr_set(
+ IpAddr& ip, ///< Target storage.
+ uint8_t af, ///< Address format.
+ void* ptr ///< Raw address data
+) {
+ if (AF_INET6 == af)
+ ip = *static_cast<in6_addr*>(ptr);
+ else if (AF_INET == af)
+ ip = *static_cast<in_addr_t*>(ptr);
+ else
+ ip.invalidate();
+}
+
inline void
hostdb_cont_free(HostDBContinuation * cont)
{
@@ -119,6 +134,29 @@ hostdb_cont_free(HostDBContinuation * cont)
hostDBContAllocator.free(cont);
}
+/* Check whether a resolution fail should lead to a retry.
+ The @a mark argument is updated if appropriate.
+ @return @c true if @a mark was updated, @c false if no retry should be done.
+*/
+static inline bool
+check_for_retry(HostDBMark& mark, HostResStyle style) {
+ bool zret = true;
+ if (HOSTDB_MARK_IPV4 == mark && HOST_RES_IPV4 == style)
+ mark = HOSTDB_MARK_IPV6;
+ else if (HOSTDB_MARK_IPV6 == mark && HOST_RES_IPV6 == style)
+ mark = HOSTDB_MARK_IPV4;
+ else
+ zret = false;
+ return zret;
+}
+
+char const*
+string_for(HostDBMark mark) {
+ static char const* STRING[] = {
+ "Generic", "IPv4", "IPv6", "SRV"
+ };
+ return STRING[mark];
+}
//
// Function Prototypes
@@ -128,6 +166,29 @@ static Action *
register_ShowHostDB(Continuation * c, HTTPHdr * h);
#endif
+void
+HostDBMD5::refresh() {
+ if (host_name) {
+ char const* server_line = dns_server ? dns_server->x_dns_ip_line : 0;
+ make_md5(hash, host_name, host_len, port, server_line, db_mark);
+ } else {
+ // INK_MD5 the ip, pad on both sizes with 0's
+ // so that it does not intersect the string space
+ //
+ uint8_t buff[TS_IP6_SIZE+4];
+ int n = ip.isIp6() ? sizeof(in6_addr) : sizeof(in_addr_t);
+ memset(buff, 0, 2);
+ memcpy(buff+2, ip._addr._byte, n);
+ memset(buff + 2 + n , 0, 2);
+ hash.encodeBuffer(buff, n+4);
+ }
+}
+
+HostDBMD5::HostDBMD5()
+ : host_name(0), host_len(0), port(0),
+ dns_server(0), db_mark(HOSTDB_MARK_GENERIC)
+{
+}
HostDBCache::HostDBCache()
{
@@ -231,7 +292,7 @@ struct HostDBTestRR: public Continuation
else {
*end = 0;
outstanding++;
- hostDBProcessor.getbyname_re(this, b);
+ hostDBProcessor.getbyname_re(this, b, 0);
nb -= ((end + 1) - b);
memcpy(b, end + 1, nb);
if (!nb)
@@ -432,34 +493,45 @@ HostDBProcessor::start(int)
void
-HostDBContinuation::init(
- const char *hostname, int len,
- sockaddr const* aip,
- INK_MD5 & amd5, Continuation * cont, void *pDS, bool is_srv, int timeout
-) {
- if (hostname) {
- memcpy(name, hostname, len);
- name[len] = 0;
- } else
- name[0] = 0;
- dns_lookup_timeout = timeout;
- namelen = len;
- is_srv_lookup = is_srv;
- ats_ip_copy(&ip.sa, aip);
- md5 = amd5;
- mutex = hostDB.lock_for_bucket((int) (fold_md5(md5) % hostDB.buckets));
- m_pDS = pDS;
- if (cont) {
- action = cont;
+HostDBContinuation::init(HostDBMD5 const& the_md5, Options const& opt)
+{
+ md5 = the_md5;
+ if (md5.host_name) {
+ // copy to backing store.
+ if (md5.host_len > static_cast<int>(sizeof(md5_host_name_store)-1))
+ md5.host_len = sizeof(md5_host_name_store)-1;
+ memcpy(md5_host_name_store, md5.host_name, md5.host_len);
+ } else {
+ md5.host_len = 0;
+ }
+ md5_host_name_store[md5.host_len] = 0;
+ md5.host_name = md5_host_name_store;
+
+ host_res_style = opt.host_res_style;
+ dns_lookup_timeout = opt.timeout;
+ mutex = hostDB.lock_for_bucket((int) (fold_md5(md5.hash) % hostDB.buckets));
+ if (opt.cont) {
+ action = opt.cont;
} else {
//ink_assert(!"this sucks");
action.mutex = mutex;
}
}
+void
+HostDBContinuation::refresh_MD5() {
+ ProxyMutex* old_bucket_mutex = hostDB.lock_for_bucket((int) (fold_md5(md5.hash) % hostDB.buckets));
+ // We're not pending DNS anymore.
+ remove_trigger_pending_dns();
+ md5.refresh();
+ // Update the mutex if it's from the bucket.
+ // Some call sites modify this after calling @c init so need to check.
+ if (old_bucket_mutex == mutex)
+ mutex = hostDB.lock_for_bucket((int) (fold_md5(md5.hash) % hostDB.buckets));
+}
void
-make_md5(INK_MD5 & md5, const char *hostname, int len, int port, char *pDNSServers, int srv)
+make_md5(INK_MD5 & md5, const char *hostname, int len, int port, char const* pDNSServers, HostDBMark mark)
{
#ifdef USE_MMH
MMH_CTX ctx;
@@ -468,7 +540,8 @@ make_md5(INK_MD5 & md5, const char *hostname, int len, int port, char *pDNSServe
unsigned short p = port;
p = htons(p);
ink_code_incr_MMH_update(&ctx, (char *) &p, 2);
- ink_code_incr_MMH_update(&ctx, (char *) &srv, 4); /* FIXME: check this */
+ uint8_t m = static_cast<uint8_t>(mark);
+ ink_code_incr_MMH_update(&ctx, (char *) &m, sizeof(m)); /* FIXME: check this */
if (pDNSServers)
ink_code_incr_MMH_update(&ctx, pDNSServers, strlen(pDNSServers));
ink_code_incr_MMH_final((char *) &md5, &ctx);
@@ -479,7 +552,8 @@ make_md5(INK_MD5 & md5, const char *hostname, int len, int port, char *pDNSServe
unsigned short p = port;
p = htons(p);
ink_code_incr_md5_update(&ctx, (char *) &p, 2);
- ink_code_incr_MMH_update(&ctx, (char *) &srv, 4); /* FIXME: check this */
+ uint8_t m = static_cast<uint8_t>(mark);
+ ink_code_incr_md5_update(&ctx, (char *) &m, sizeof(m)); /* FIXME: check this */
if (pDNSServers)
ink_code_incr_md5_update(&ctx, pDNSServers, strlen(pDNSServers));
ink_code_incr_md5_final((char *) &md5, &ctx);
@@ -549,17 +623,44 @@ Ldelete:
return false;
}
+inline HostResStyle
+host_res_style_for(sockaddr const* ip) {
+ return ats_is_ip6(ip) ? HOST_RES_IPV6_ONLY : HOST_RES_IPV4_ONLY;
+}
+
+inline HostResStyle
+host_res_style_for(HostDBMark mark) {
+ return HOSTDB_MARK_IPV4 == mark ? HOST_RES_IPV4_ONLY
+ : HOSTDB_MARK_IPV6 == mark ? HOST_RES_IPV6_ONLY
+ : HOST_RES_NONE
+ ;
+}
+
+inline HostDBMark
+db_mark_for(HostResStyle style) {
+ HostDBMark zret = HOSTDB_MARK_GENERIC;
+ if (HOST_RES_IPV4 == style || HOST_RES_IPV4_ONLY == style)
+ zret = HOSTDB_MARK_IPV4;
+ else if (HOST_RES_IPV6 == style || HOST_RES_IPV6_ONLY == style)
+ zret = HOSTDB_MARK_IPV6;
+ return zret;
+}
+
+inline HostDBMark
+db_mark_for(sockaddr const* ip) {
+ return ats_is_ip6(ip) ? HOSTDB_MARK_IPV6 : HOSTDB_MARK_IPV4;
+}
HostDBInfo *
-probe(ProxyMutex *mutex, INK_MD5 & md5, const char *hostname, int len, sockaddr const* ip, void *pDS, bool ignore_timeout,
- bool is_srv_lookup)
+probe(ProxyMutex *mutex, HostDBMD5 const& md5, bool ignore_timeout)
{
- ink_debug_assert(this_ethread() == hostDB.lock_for_bucket((int) (fold_md5(md5) % hostDB.buckets))->thread_holding);
+ ink_debug_assert(this_ethread() == hostDB.lock_for_bucket((int) (fold_md5(md5.hash) % hostDB.buckets))->thread_holding);
if (hostdb_enable) {
- uint64_t folded_md5 = fold_md5(md5);
+ uint64_t folded_md5 = fold_md5(md5.hash);
HostDBInfo *r = hostDB.lookup_block(folded_md5, hostDB.levels);
- Debug("hostdb", "probe %s %" PRIx64" %d [ignore_timeout = %d]", hostname, folded_md5, !!r, ignore_timeout);
- if (r && md5[1] == r->md5_high) {
+ Debug("hostdb", "probe %.*s %" PRIx64 " %d [ignore_timeout = %d]",
+ md5.host_len, md5.host_name, folded_md5, !!r, ignore_timeout);
+ if (r && md5.hash[1] == r->md5_high) {
// Check for timeout (fail probe)
//
@@ -567,7 +668,7 @@ probe(ProxyMutex *mutex, INK_MD5 & md5, const char *hostname, int len, sockaddr
Debug("hostdb", "HostDB entry was set as deleted");
return NULL;
} else if (r->failed()) {
- Debug("hostdb", "%s failed", hostname);
+ Debug("hostdb", "'%.*s' failed", md5.host_len, md5.host_name);
if (r->is_ip_fail_timeout()) {
Debug("hostdb", "fail timeout %u", r->ip_interval());
return NULL;
@@ -593,15 +694,17 @@ probe(ProxyMutex *mutex, INK_MD5 & md5, const char *hostname, int len, sockaddr
// we are beyond our TTL but we choose to serve for another N seconds [hostdb_serve_stale_but_revalidate seconds]
if ((!ignore_timeout && r->is_ip_stale()
#ifdef NON_MODULAR
- && !cluster_machine_at_depth(master_hash(md5))
+ && !cluster_machine_at_depth(master_hash(md5.hash))
#endif
&& !r->reverse_dns) || (r->is_ip_timeout() && r->serve_stale_but_revalidate())) {
Debug("hostdb", "stale %u %u %u, using it and refreshing it", r->ip_interval(),
r->ip_timestamp, r->ip_timeout_interval);
r->refresh_ip();
- if (!is_dotted_form_hostname(hostname)) {
+ if (!is_dotted_form_hostname(md5.host_name)) {
HostDBContinuation *c = hostDBContAllocator.alloc();
- c->init(hostname, len, ip, md5, NULL, pDS, is_srv_lookup, 0);
+ HostDBContinuation::Options copt;
+ copt.host_res_style = host_res_style_for(r->ip());
+ c->init(md5, copt);
c->do_dns();
}
}
@@ -623,20 +726,21 @@ probe(ProxyMutex *mutex, INK_MD5 & md5, const char *hostname, int len, sockaddr
HostDBInfo *
HostDBContinuation::insert(unsigned int attl)
{
- ink_debug_assert(this_ethread() == hostDB.lock_for_bucket((int) (fold_md5(md5) % hostDB.buckets))->thread_holding);
- uint64_t folded_md5 = fold_md5(md5);
+ uint64_t folded_md5 = fold_md5(md5.hash);
+ int bucket = folded_md5 % hostDB.buckets;
+
+ ink_debug_assert(this_ethread() == hostDB.lock_for_bucket(bucket)->thread_holding);
// remove the old one to prevent buildup
HostDBInfo *old_r = hostDB.lookup_block(folded_md5, 3);
if (old_r)
hostDB.delete_block(old_r);
HostDBInfo *r = hostDB.insert_block(folded_md5, NULL, 0);
- Debug("hostdb_insert", "inserting in bucket %d", (int) (folded_md5 % hostDB.buckets));
- r->md5_high = md5[1];
+ r->md5_high = md5.hash[1];
if (attl > HOST_DB_MAX_TTL)
attl = HOST_DB_MAX_TTL;
r->ip_timeout_interval = attl;
r->ip_timestamp = hostdb_current_interval;
- Debug("hostdb", "inserting for: %s: (md5: %" PRIx64") now: %u timeout: %u ttl: %u", name, folded_md5, r->ip_timestamp,
+ Debug("hostdb", "inserting for: %.*s: (md5: %" PRIx64 ") bucket: %d now: %u timeout: %u ttl: %u", md5.host_len, md5.host_name, folded_md5, bucket, r->ip_timestamp,
r->ip_timeout_interval, attl);
return r;
}
@@ -647,14 +751,11 @@ HostDBContinuation::insert(unsigned int attl)
//
Action *
HostDBProcessor::getby(Continuation * cont,
- const char *hostname, int len, sockaddr const* ip, bool aforce_dns, int dns_lookup_timeout)
+ const char *hostname, int len, sockaddr const* ip, bool aforce_dns, HostResStyle host_res_style, int dns_lookup_timeout)
{
- INK_MD5 md5;
- char *pServerLine = 0;
- void *pDS = 0;
+ HostDBMD5 md5;
EThread *thread = this_ethread();
ProxyMutex *mutex = thread->mutex;
- unsigned short port = ats_ip_port_host_order(ip);
ip_text_buffer ipb;
HOSTDB_INCREMENT_DYN_STAT(hostdb_total_lookups_stat);
@@ -666,68 +767,62 @@ HostDBProcessor::getby(Continuation * cont,
cont->handleEvent(EVENT_HOST_DB_LOOKUP, NULL);
return ACTION_RESULT_DONE;
}
+
+ // Load the MD5 data.
+ md5.host_name = hostname;
+ md5.host_len = hostname ? (len ? len : strlen(hostname)) : 0;
+ md5.ip.assign(ip);
+ md5.port = ip ? ats_ip_port_host_order(ip) : 0;
+ md5.db_mark = db_mark_for(host_res_style);
#ifdef SPLIT_DNS
if (hostname && SplitDNSConfig::isSplitDNSEnabled()) {
const char *scan = hostname;
+ // Is this a check for IPv4 address? Add check for IPv6?
for (; *scan != '\0' && (ParseRules::is_digit(*scan) || '.' == *scan); scan++);
if ('\0' != *scan) {
- void *pSD = (void *) SplitDNSConfig::acquire();
- if (0 != pSD) {
- pDS = ((SplitDNS *) pSD)->getDNSRecord(hostname);
-
- if (0 != pDS) {
- pServerLine = ((DNSServer *) pDS)->x_dns_ip_line;
- }
- }
- SplitDNSConfig::release((SplitDNS *) pSD);
+ SplitDNS* pSD = SplitDNSConfig::acquire();
+ if (0 != pSD)
+ md5.dns_server = static_cast<DNSServer*>(pSD->getDNSRecord(hostname));
+ SplitDNSConfig::release(pSD);
}
}
#endif // SPLIT_DNS
-
- // if it is by name, INK_MD5 the name
- //
- if (hostname) {
- if (!len)
- len = strlen(hostname);
- make_md5(md5, hostname, len, port, pServerLine);
- } else {
- // INK_MD5 the ip, pad on both sizes with 0's
- // so that it does not intersect the string space
- //
- uint8_t buff[TS_IP6_SIZE+4];
- memset(buff, 0, sizeof(buff));
- if (ats_is_ip4(ip))
- memcpy(buff+2, &ats_ip4_addr_cast(ip), sizeof(in_addr_t));
- else if (ats_is_ip6(ip))
- memcpy(buff+2, &ats_ip6_addr_cast(ip), sizeof(in6_addr));
- md5.encodeBuffer(buff, sizeof buff);
- }
+ md5.refresh();
// Attempt to find the result in-line, for level 1 hits
//
if (!aforce_dns) {
- // find the partition lock
- //
- // TODO: Could we reuse the "mutex" above safely? I think so, but not sure.
- ProxyMutex *bmutex = hostDB.lock_for_bucket((int) (fold_md5(md5) % hostDB.buckets));
- MUTEX_TRY_LOCK(lock, bmutex, thread);
- MUTEX_TRY_LOCK(lock2, cont->mutex, thread);
-
- // If we can get the lock and a level 1 probe succeeds, return
- //
- if (lock && lock2) {
- HostDBInfo *r = probe(bmutex, md5, hostname, len, ip, pDS);
- if (r) {
- Debug("hostdb", "immediate answer for %s",
- hostname ? hostname
- : ats_is_ip(ip) ? ats_ip_ntop(ip, ipb, sizeof ipb)
- : "<null>"
- );
- HOSTDB_INCREMENT_DYN_STAT(hostdb_total_hits_stat);
- reply_to_cont(cont, r);
- return ACTION_RESULT_DONE;
+ bool loop;
+ do {
+ loop = false; // Only loop on explicit set for retry.
+ // find the partition lock
+ //
+ // TODO: Could we reuse the "mutex" above safely? I think so but not sure.
+ ProxyMutex *bmutex = hostDB.lock_for_bucket((int) (fold_md5(md5.hash) % hostDB.buckets));
+ MUTEX_TRY_LOCK(lock, bmutex, thread);
+ MUTEX_TRY_LOCK(lock2, cont->mutex, thread);
+
+ if (lock && lock2) {
+ // If we can get the lock and a level 1 probe succeeds, return
+ HostDBInfo *r = probe(bmutex, md5, aforce_dns);
+ if (r) {
+ if (r->failed() && hostname)
+ loop = check_for_retry(md5.db_mark, host_res_style);
+ if (!loop) {
+ // No retry -> final result. Return it.
+ Debug("hostdb", "immediate answer for %s",
+ hostname ? hostname
+ : ats_is_ip(ip) ? ats_ip_ntop(ip, ipb, sizeof ipb)
+ : "<null>"
+ );
+ HOSTDB_INCREMENT_DYN_STAT(hostdb_total_hits_stat);
+ reply_to_cont(cont, r);
+ return ACTION_RESULT_DONE;
+ }
+ md5.refresh();
+ }
}
- }
+ } while (loop);
}
Debug("hostdb", "delaying force %d answer for %s", aforce_dns,
hostname ? hostname
@@ -739,9 +834,12 @@ Lretry:
// Otherwise, create a continuation to do a deeper probe in the background
//
HostDBContinuation *c = hostDBContAllocator.alloc();
- c->init(hostname, len, ip, md5, cont, pDS, false, dns_lookup_timeout);
- c->action = cont;
- c->force_dns = aforce_dns;
+ HostDBContinuation::Options opt;
+ opt.timeout = dns_lookup_timeout;
+ opt.force_dns = aforce_dns;
+ opt.cont = cont;
+ opt.host_res_style = host_res_style;
+ c->init(md5, opt);
SET_CONTINUATION_HANDLER(c, (HostDBContHandler) & HostDBContinuation::probeEvent);
// Since ProxyMutexPtr has a cast operator, gcc-3.x get upset
@@ -760,46 +858,42 @@ Lretry:
// Wrapper from getbyname to getby
//
Action *
-HostDBProcessor::getbyname_re(Continuation * cont, const char *ahostname, int len, int port, int flags)
+HostDBProcessor::getbyname_re(Continuation * cont, const char *ahostname, int len, Options const& opt)
{
bool force_dns = false;
EThread *thread = this_ethread();
ProxyMutex *mutex = thread->mutex;
- sockaddr_in ip;
-
- ats_ip4_set(&ip, INADDR_ANY, htons(port));
- if (flags & HOSTDB_FORCE_DNS_ALWAYS)
+ if (opt.flags & HOSTDB_FORCE_DNS_ALWAYS)
force_dns = true;
- else if (flags & HOSTDB_FORCE_DNS_RELOAD) {
+ else if (opt.flags & HOSTDB_FORCE_DNS_RELOAD) {
force_dns = (hostdb_re_dns_on_reload ? true : false);
if (force_dns)
HOSTDB_INCREMENT_DYN_STAT(hostdb_re_dns_on_reload_stat);
}
- return getby(cont, ahostname, len, ats_ip_sa_cast(&ip), force_dns);
+ return getby(cont, ahostname, len, 0, force_dns, opt.host_res_style, opt.timeout);
}
/* Support SRV records */
Action *
HostDBProcessor::getSRVbyname_imm(Continuation * cont, process_srv_info_pfn process_srv_info,
- const char *hostname, int len, int port, int flags, int dns_lookup_timeout)
+ const char *hostname, int len, Options const& opt)
{
ink_debug_assert(cont->mutex->thread_holding == this_ethread());
bool force_dns = false;
EThread *thread = cont->mutex->thread_holding;
ProxyMutex *mutex = thread->mutex;
- if (flags & HOSTDB_FORCE_DNS_ALWAYS)
+ if (opt.flags & HOSTDB_FORCE_DNS_ALWAYS)
force_dns = true;
- else if (flags & HOSTDB_FORCE_DNS_RELOAD) {
+ else if (opt.flags & HOSTDB_FORCE_DNS_RELOAD) {
force_dns = (hostdb_re_dns_on_reload ? true : false);
if (force_dns)
HOSTDB_INCREMENT_DYN_STAT(hostdb_re_dns_on_reload_stat);
}
- INK_MD5 md5;
- void *pDS = 0;
+ HostDBMD5 md5;
HOSTDB_INCREMENT_DYN_STAT(hostdb_total_lookups_stat);
@@ -808,23 +902,21 @@ HostDBProcessor::getSRVbyname_imm(Continuation * cont, process_srv_info_pfn proc
return ACTION_RESULT_DONE;
}
- sockaddr_in ip;
- ats_ip4_set(&ip, INADDR_ANY, htons(port));
-
- if (!len)
- len = strlen(hostname);
-
- make_md5(md5, hostname, len, port, 0, 1);
+ md5.host_name = hostname;
+ md5.host_len = hostname ? (len ? len : strlen(hostname)) : 0;
+ md5.port = opt.port;
+ md5.db_mark = HOSTDB_MARK_SRV;
+ md5.refresh();
// Attempt to find the result in-line, for level 1 hits
if (!force_dns) {
// find the partition lock
- ProxyMutex *bucket_mutex = hostDB.lock_for_bucket((int) (fold_md5(md5) % hostDB.buckets));
+ ProxyMutex *bucket_mutex = hostDB.lock_for_bucket((int) (fold_md5(md5.hash) % hostDB.buckets));
MUTEX_TRY_LOCK(lock, bucket_mutex, thread);
// If we can get the lock and a level 1 probe succeeds, return
if (lock) {
- HostDBInfo *r = probe(bucket_mutex, md5, hostname, len, ats_ip_sa_cast(&ip), pDS, false, true);
+ HostDBInfo *r = probe(bucket_mutex, md5, false);
if (r) {
Debug("hostdb", "immediate SRV answer for %s from hostdb", hostname);
Debug("dns_srv", "immediate SRV answer for %s from hostdb", hostname);
@@ -835,12 +927,15 @@ HostDBProcessor::getSRVbyname_imm(Continuation * cont, process_srv_info_pfn proc
}
}
- Debug("dns_srv", "delaying (force=%d) SRV answer for %s [timeout = %d]", force_dns, hostname, dns_lookup_timeout);
+ Debug("dns_srv", "delaying (force=%d) SRV answer for %.*s [timeout = %d]", force_dns, md5.host_len, md5.host_name, opt.timeout);
// Otherwise, create a continuation to do a deeper probe in the background
HostDBContinuation *c = hostDBContAllocator.alloc();
- c->init(hostname, len, ats_ip_sa_cast(&ip), md5, cont, pDS, true, dns_lookup_timeout);
- c->force_dns = force_dns;
+ HostDBContinuation::Options copt;
+ copt.timeout = opt.timeout;
+ copt.cont = cont;
+ copt.force_dns = force_dns;
+ c->init(md5, copt);
SET_CONTINUATION_HANDLER(c, (HostDBContHandler) & HostDBContinuation::probeEvent);
if (thread->mutex == cont->mutex) {
@@ -857,26 +952,22 @@ HostDBProcessor::getSRVbyname_imm(Continuation * cont, process_srv_info_pfn proc
//
Action *
HostDBProcessor::getbyname_imm(Continuation * cont, process_hostdb_info_pfn process_hostdb_info,
- const char *hostname, int len, int port, int flags, int dns_lookup_timeout)
+ const char *hostname, int len, Options const& opt)
{
ink_debug_assert(cont->mutex->thread_holding == this_ethread());
bool force_dns = false;
EThread *thread = cont->mutex->thread_holding;
ProxyMutex *mutex = thread->mutex;
- sockaddr_in ip_store;
- sockaddr* ip = ats_ip_sa_cast(&ip_store);
- ats_ip4_set(ip, INADDR_ANY, htons(port));
+ HostDBMD5 md5;
- if (flags & HOSTDB_FORCE_DNS_ALWAYS)
+ if (opt.flags & HOSTDB_FORCE_DNS_ALWAYS)
force_dns = true;
- else if (flags & HOSTDB_FORCE_DNS_RELOAD) {
+ else if (opt.flags & HOSTDB_FORCE_DNS_RELOAD) {
force_dns = (hostdb_re_dns_on_reload ? true : false);
if (force_dns)
HOSTDB_INCREMENT_DYN_STAT(hostdb_re_dns_on_reload_stat);
}
- INK_MD5 md5;
- void *pDS = 0;
HOSTDB_INCREMENT_DYN_STAT(hostdb_total_lookups_stat);
if (!hostdb_enable || !*hostname) {
@@ -884,54 +975,62 @@ HostDBProcessor::getbyname_imm(Continuation * cont, process_hostdb_info_pfn proc
return ACTION_RESULT_DONE;
}
- if (!len)
- len = strlen(hostname);
-
+ md5.host_name = hostname;
+ md5.host_len = hostname ? (len ? len : strlen(hostname)) : 0;
+ md5.port = opt.port;
+ md5.db_mark = db_mark_for(opt.host_res_style);
#ifdef SPLIT_DNS
if (SplitDNSConfig::isSplitDNSEnabled()) {
const char *scan = hostname;
- char *pServerLine = 0;
for (; *scan != '\0' && (ParseRules::is_digit(*scan) || '.' == *scan); scan++);
if ('\0' != *scan) {
- void *pSD = (void *) SplitDNSConfig::acquire();
- if (0 != pSD) {
- pDS = ((SplitDNS *) pSD)->getDNSRecord(hostname);
-
- if (0 != pDS) {
- pServerLine = ((DNSServer *) pDS)->x_dns_ip_line;
- }
- }
- SplitDNSConfig::release((SplitDNS *) pSD);
+ SplitDNS* pSD = SplitDNSConfig::acquire();
+ if (0 != pSD)
+ md5.dns_server = static_cast<DNSServer*>(pSD->getDNSRecord(md5.host_name));
+ SplitDNSConfig::release(pSD);
}
- make_md5(md5, hostname, len, port, pServerLine);
- } else
+ }
#endif // SPLIT_DNS
- make_md5(md5, hostname, len, port, 0);
+ md5.refresh();
// Attempt to find the result in-line, for level 1 hits
if (!force_dns) {
- // find the partition lock
- ProxyMutex *bucket_mutex = hostDB.lock_for_bucket((int) (fold_md5(md5) % hostDB.buckets));
- MUTEX_TRY_LOCK(lock, bucket_mutex, thread);
-
- // If we can get the lock and a level 1 probe succeeds, return
- if (lock) {
- HostDBInfo *r = probe(bucket_mutex, md5, hostname, len, ip, pDS);
- if (r) {
- Debug("hostdb", "immediate answer for %s", hostname ? hostname : "<addr>");
- HOSTDB_INCREMENT_DYN_STAT(hostdb_total_hits_stat);
- (cont->*process_hostdb_info) (r);
- return ACTION_RESULT_DONE;
+ bool loop;
+ do {
+ loop = false; // loop only on explicit set for retry
+ // find the partition lock
+ ProxyMutex *bucket_mutex = hostDB.lock_for_bucket((int) (fold_md5(md5.hash) % hostDB.buckets));
+ MUTEX_TRY_LOCK(lock, bucket_mutex, thread);
+
+ if (lock) {
+ // If we can get the lock do a level 1 probe for immediate result.
+ HostDBInfo *r = probe(bucket_mutex, md5, false);
+ if (r) {
+ if (r->failed()) // fail, see if we should retry with alternate
+ loop = check_for_retry(md5.db_mark, opt.host_res_style);
+ if (!loop) {
+ // No retry -> final result. Return it.
+ Debug("hostdb", "immediate answer for %.*s", md5.host_len, md5.host_name);
+ HOSTDB_INCREMENT_DYN_STAT(hostdb_total_hits_stat);
+ (cont->*process_hostdb_info) (r);
+ return ACTION_RESULT_DONE;
+ }
+ md5.refresh(); // Update for retry.
+ }
}
- }
+ } while (loop);
}
- Debug("hostdb", "delaying force %d answer for %s [timeout %d]", force_dns, hostname, dns_lookup_timeout);
+ Debug("hostdb", "delaying force %d answer for %.*s [timeout %d]", force_dns, md5.host_len, md5.host_name, opt.timeout);
// Otherwise, create a continuation to do a deeper probe in the background
HostDBContinuation *c = hostDBContAllocator.alloc();
- c->init(hostname, len, ip, md5, cont, pDS, false, dns_lookup_timeout);
- c->force_dns = force_dns;
+ HostDBContinuation::Options copt;
+ copt.cont = cont;
+ copt.force_dns = force_dns;
+ copt.timeout = opt.timeout;
+ copt.host_res_style = opt.host_res_style;
+ c->init(md5, copt);
SET_CONTINUATION_HANDLER(c, (HostDBContHandler) & HostDBContinuation::probeEvent);
thread->schedule_in(c, MUTEX_RETRY_DELAY);
@@ -941,14 +1040,14 @@ HostDBProcessor::getbyname_imm(Continuation * cont, process_hostdb_info_pfn proc
static void
-do_setby(HostDBInfo * r, HostDBApplicationInfo * app, const char *hostname, sockaddr const* ip)
+do_setby(HostDBInfo * r, HostDBApplicationInfo * app, const char *hostname, IpAddr const& ip)
{
HostDBRoundRobin *rr = r->rr();
if (rr) {
ink_assert(hostname);
for (int i = 0; i < rr->n; i++) {
- if (0 == ats_ip_addr_cmp(rr->info[i].ip(), ip)) {
+ if (rr->info[i].ip() == ip) {
Debug("hostdb", "immediate setby for %s", hostname ? hostname : "<addr>");
rr->info[i].app.allotment.application1 = app->allotment.application1;
rr->info[i].app.allotment.application2 = app->allotment.application2;
@@ -956,7 +1055,7 @@ do_setby(HostDBInfo * r, HostDBApplicationInfo * app, const char *hostname, sock
}
}
} else {
- if (r->reverse_dns || (!r->round_robin && ats_ip_addr_eq(r->ip(), ip))) {
+ if (r->reverse_dns || (!r->round_robin && ip == r->ip())) {
Debug("hostdb", "immediate setby for %s", hostname ? hostname : "<addr>");
r->app.allotment.application1 = app->allotment.application1;
r->app.allotment.application2 = app->allotment.application2;
@@ -971,44 +1070,30 @@ HostDBProcessor::setby(const char *hostname, int len, sockaddr const* ip, HostDB
if (!hostdb_enable)
return;
- INK_MD5 md5;
- unsigned short port = ats_ip_port_host_order(ip);
-
- // if it is by name, INK_MD5 the name
- //
- if (hostname) {
- if (!len)
- len = strlen(hostname);
- make_md5(md5, hostname, len, port);
- } else {
- // INK_MD5 the ip, pad on both sizes with 0's
- // so that it does not intersect the string space
- //
- uint8_t buff[TS_IP6_SIZE+4];
- memset(buff, 0, sizeof(buff));
- if (ats_is_ip4(ip))
- memcpy(buff+2, &ats_ip4_addr_cast(ip), sizeof(in_addr_t));
- else if (ats_is_ip6(ip))
- memcpy(buff+2, &ats_ip6_addr_cast(ip), sizeof(in6_addr));
- md5.encodeBuffer(buff, sizeof buff);
- }
+ HostDBMD5 md5;
+ md5.host_name = hostname;
+ md5.host_len = hostname ? (len ? len : strlen(hostname)) : 0;
+ md5.ip.assign(ip);
+ md5.port = ip ? ats_ip_port_host_order(ip) : 0;
+ md5.db_mark = db_mark_for(ip);
+ md5.refresh();
// Attempt to find the result in-line, for level 1 hits
- ProxyMutex *mutex = hostDB.lock_for_bucket((int) (fold_md5(md5) % hostDB.buckets));
+ ProxyMutex *mutex = hostDB.lock_for_bucket((int) (fold_md5(md5.hash) % hostDB.buckets));
EThread *thread = this_ethread();
MUTEX_TRY_LOCK(lock, mutex, thread);
if (lock) {
- HostDBInfo *r = probe(mutex, md5, hostname, len, ip, 0);
+ HostDBInfo *r = probe(mutex, md5, false);
if (r)
- do_setby(r, app, hostname, ip);
+ do_setby(r, app, hostname, md5.ip);
return;
}
// Create a continuation to do a deaper probe in the background
HostDBContinuation *c = hostDBContAllocator.alloc();
- c->init(hostname, len, ip, md5, NULL);
+ c->init(md5);
c->app.allotment.application1 = app->allotment.application1;
c->app.allotment.application2 = app->allotment.application2;
SET_CONTINUATION_HANDLER(c, (HostDBContHandler) & HostDBContinuation::setbyEvent);
@@ -1021,17 +1106,18 @@ HostDBContinuation::setbyEvent(int event, Event * e)
{
NOWARN_UNUSED(event);
NOWARN_UNUSED(e);
- HostDBInfo *r = probe(mutex, md5, name, namelen, &ip.sa, 0);
+ HostDBInfo *r = probe(mutex, md5, false);
if (r)
- do_setby(r, &app, name, &ip.sa);
+ do_setby(r, &app, md5.host_name, md5.ip);
+
hostdb_cont_free(this);
return EVENT_DONE;
}
static int
-remove_round_robin(HostDBInfo * r, const char *hostname, sockaddr const* ip)
+remove_round_robin(HostDBInfo * r, const char *hostname, IpAddr const& ip)
{
if (r) {
if (!r->round_robin)
@@ -1040,12 +1126,9 @@ remove_round_robin(HostDBInfo * r, const char *hostname, sockaddr const* ip)
if (!rr)
return false;
for (int i = 0; i < rr->good; i++) {
- if (0 == ats_ip_addr_cmp(rr->info[i].ip(), ip)) {
+ if (ip == rr->info[i].ip()) {
ip_text_buffer b;
- Debug("hostdb", "Deleting %s from '%s' round robin DNS entry",
- ats_ip_ntop(ip, b, sizeof b),
- hostname
- );
+ Debug("hostdb", "Deleting %s from '%s' round robin DNS entry", ip.toString(b, sizeof b), hostname);
HostDBInfo tmp = rr->info[i];
rr->info[i] = rr->info[rr->good - 1];
rr->info[rr->good - 1] = tmp;
@@ -1074,55 +1157,52 @@ remove_round_robin(HostDBInfo * r, const char *hostname, sockaddr const* ip)
return false;
}
-
+# if 0
Action *
HostDBProcessor::failed_connect_on_ip_for_name(Continuation * cont, sockaddr const* ip, const char *hostname, int len)
{
- INK_MD5 md5;
- char *pServerLine = 0;
- void *pDS = 0;
- unsigned short port = ats_ip_port_host_order(ip);
-
+ HostDBMD5 md5;
+ md5.host_name = hostname;
+ md5.host_len = hostname ? (len ? len : strlen(hostname)) : 0;
+ md5.ip.assign(ip);
+ md5.port = ip ? ats_ip_port_host_order(ip) : 0;
+ md5.db_mark = db_mark_for(ip);
#ifdef SPLIT_DNS
SplitDNS *pSD = 0;
if (hostname && SplitDNSConfig::isSplitDNSEnabled()) {
pSD = SplitDNSConfig::acquire();
- if (0 != pSD) {
- pDS = pSD->getDNSRecord(hostname);
- pServerLine = ((DNSServer *) pDS)->x_dns_ip_line;
- }
+ if (0 != pSD)
+ md5.dns_server = static_cast<DNSServer*>(pSD->getDNSRecord(hostname));
SplitDNSConfig::release(pSD);
}
#endif // SPLIT_DNS
+ md5.refresh();
- make_md5(md5, hostname, len, port, pServerLine);
- ProxyMutex *mutex = hostDB.lock_for_bucket((int) (fold_md5(md5) % hostDB.buckets));
+ ProxyMutex *mutex = hostDB.lock_for_bucket((int) (fold_md5(md5.hash) % hostDB.buckets));
EThread *thread = this_ethread();
MUTEX_TRY_LOCK(lock, mutex, thread);
if (lock) {
- if (!hostdb_enable || NULL == pDS) {
+ if (!hostdb_enable || NULL == md5.dns_server) {
if (cont)
cont->handleEvent(EVENT_HOST_DB_IP_REMOVED, (void *) NULL);
return ACTION_RESULT_DONE;
}
-#ifdef SPLIT_DNS
- HostDBInfo *r = probe(mutex, md5, hostname, len, ip, pDS);
-#else
- HostDBInfo *r = probe(mutex, md5, hostname, len, ip, 0);
-#endif
+ HostDBInfo *r = probe(mutex, md5, false);
bool res = (remove_round_robin(r, hostname, ip) ? true : false);
if (cont)
cont->handleEvent(EVENT_HOST_DB_IP_REMOVED, res ? (void *) ip : (void *) NULL);
return ACTION_RESULT_DONE;
}
HostDBContinuation *c = hostDBContAllocator.alloc();
- c->init(hostname, len, ip, md5, cont, pDS);
+ HostDBContinuation::Options copt;
+ copt.cont = cont;
+ c->init(md5, copt);
SET_CONTINUATION_HANDLER(c, (HostDBContHandler) & HostDBContinuation::removeEvent);
thread->schedule_in(c, MUTEX_RETRY_DELAY);
return &c->action;
}
-
+#endif
int
HostDBContinuation::removeEvent(int event, Event * e)
@@ -1140,12 +1220,12 @@ HostDBContinuation::removeEvent(int event, Event * e)
if (cont)
cont->handleEvent(EVENT_HOST_DB_IP_REMOVED, (void *) NULL);
} else {
- HostDBInfo *r = probe(mutex, md5, name, namelen, &ip.sa, m_pDS);
- bool res = (remove_round_robin(r, name, &ip.sa) ? true : false);
+ HostDBInfo *r = probe(mutex, md5, false);
+ bool res = (remove_round_robin(r, md5.host_name, md5.ip) ? true : false);
if (cont)
cont->handleEvent(
EVENT_HOST_DB_IP_REMOVED,
- res ? static_cast<void *>(&ip) : static_cast<void *>(NULL)
+ res ? static_cast<void *>(&md5.ip) : static_cast<void *>(NULL)
);
}
}
@@ -1158,23 +1238,24 @@ HostDBContinuation::removeEvent(int event, Event * e)
// calling continuation or to the calling cluster node.
//
HostDBInfo *
-HostDBContinuation::lookup_done(sockaddr const* aip, char *aname, bool around_robin, unsigned int ttl_seconds, SRVHosts * srv)
+HostDBContinuation::lookup_done(IpAddr const& ip, char const* aname, bool around_robin, unsigned int ttl_seconds, SRVHosts * srv)
{
HostDBInfo *i = NULL;
- ink_debug_assert(this_ethread() == hostDB.lock_for_bucket((int) (fold_md5(md5) % hostDB.buckets))->thread_holding);
- if (!aip || !ats_is_ip(aip) || !aname || !aname[0]) {
+ ink_debug_assert(this_ethread() == hostDB.lock_for_bucket((int) (fold_md5(md5.hash) % hostDB.buckets))->thread_holding);
+ if (!ip.isValid() || !aname || !aname[0]) {
if (is_byname()) {
- Debug("hostdb", "lookup_done() failed for '%s'", name);
+ Debug("hostdb", "lookup_done() failed for '%.*s'", md5.host_len, md5.host_name);
} else if (is_srv()) {
- Debug("dns_srv", "SRV failed for '%s'", name);
+ Debug("dns_srv", "SRV failed for '%.*s'", md5.host_len, md5.host_name);
} else {
ip_text_buffer b;
- Debug("hostdb", "failed for %s", ats_ip_ntop(&ip.sa, b, sizeof b));
+ Debug("hostdb", "failed for %s", md5.ip.toString(b, sizeof b));
}
i = insert(hostdb_ip_fail_timeout_interval); // currently ... 0
i->round_robin = false;
i->reverse_dns = !is_byname() && !is_srv();
+ i->set_failed();
} else {
switch (hostdb_ttl_mode) {
default:
@@ -1199,18 +1280,16 @@ HostDBContinuation::lookup_done(sockaddr const* aip, char *aname, bool around_ro
i = insert(ttl_seconds);
if (is_byname()) {
ip_text_buffer b;
- Debug("hostdb", "done %s TTL %d", ats_ip_ntop(aip, b, sizeof b), ttl_seconds);
- ats_ip_copy(i->ip(), aip);
+ Debug("hostdb", "done %s TTL %d", ip.toString(b, sizeof b), ttl_seconds);
+ ats_ip_set(i->ip(), ip);
i->round_robin = around_robin;
i->reverse_dns = false;
- if (name != aname) {
- ink_strlcpy(name, aname, sizeof(name));
+ if (md5.host_name != aname) {
+ ink_strlcpy(md5_host_name_store, aname, sizeof(md5_host_name_store));
}
i->is_srv = false;
} else if (is_srv()) {
-
- ats_ip_copy(i->ip(), aip); /* this doesnt matter w. srv records -- setting to 1 so Md5 works */
-
+ ats_ip_set(i->ip(), ip);
i->reverse_dns = false;
if (srv) { //failed case: srv == NULL
@@ -1227,8 +1306,8 @@ HostDBContinuation::lookup_done(sockaddr const* aip, char *aname, bool around_ro
i->is_srv = true;
- if (name != aname) {
- ink_strlcpy(name, aname, sizeof(name));
+ if (md5.host_name != aname) {
+ ink_strlcpy(md5_host_name_store, aname, sizeof(md5_host_name_store));
}
} else {
@@ -1260,7 +1339,7 @@ HostDBContinuation::lookup_done(sockaddr const* aip, char *aname, bool around_ro
int
HostDBContinuation::dnsPendingEvent(int event, Event * e)
{
- ink_debug_assert(this_ethread() == hostDB.lock_for_bucket(fold_md5(md5) % hostDB.buckets)->thread_holding);
+ ink_debug_assert(this_ethread() == hostDB.lock_for_bucket(fold_md5(md5.hash) % hostDB.buckets)->thread_holding);
if (timeout) {
timeout->cancel(this);
timeout = NULL;
@@ -1274,7 +1353,7 @@ HostDBContinuation::dnsPendingEvent(int event, Event * e)
}
if (!action.cancelled && action.continuation)
action.continuation->handleEvent(EVENT_HOST_DB_LOOKUP, NULL);
- hostDB.pending_dns_for_hash(md5).remove(this);
+ hostDB.pending_dns_for_hash(md5.hash).remove(this);
hostdb_cont_free(this);
return EVENT_DONE;
} else {
@@ -1306,7 +1385,7 @@ restore_info(HostDBInfo * r, HostDBInfo * old_r, HostDBInfo & old_info, HostDBRo
int
HostDBContinuation::dnsEvent(int event, HostEnt * e)
{
- ink_debug_assert(this_ethread() == hostDB.lock_for_bucket(fold_md5(md5) % hostDB.buckets)->thread_holding);
+ ink_debug_assert(this_ethread() == hostDB.lock_for_bucket(fold_md5(md5.hash) % hostDB.buckets)->thread_holding);
if (timeout) {
timeout->cancel(this);
timeout = NULL;
@@ -1324,6 +1403,10 @@ HostDBContinuation::dnsEvent(int event, HostEnt * e)
timeout = thread->schedule_in(this, HOST_DB_RETRY_PERIOD);
return EVENT_CONT;
}
+ // [amc] Callback to client to indicate a failure due to timeout.
+ // We don't try a different family here because a timeout indicates
+ // a server issue that won't be fixed by asking for a different
+ // address family.
if (!action.cancelled && action.continuation)
action.continuation->handleEvent(EVENT_HOST_DB_LOOKUP, NULL);
action = NULL;
@@ -1333,18 +1416,20 @@ HostDBContinuation::dnsEvent(int event, HostEnt * e)
} else {
bool failed = !e;
- bool rr;
+ bool rr = false;
+ pending_action = NULL;
+
if (is_srv()) {
rr = !failed && (e->srv_hosts.getCount() > 0);
- } else
- rr = !failed && e->ent.h_addr_list[1];
-
- pending_action = NULL;
+ } else if (!failed) {
+ rr = 0 != e->ent.h_addr_list[1];
+ } else {
+ }
ttl = failed ? 0 : e->ttl / 60;
- int ttl_seconds = failed ? 0 : e->ttl; //ebalsa: moving to second accuracy
+ int ttl_seconds = failed ? 0 : e->ttl; //ebalsa: moving to second accuracy
- HostDBInfo *old_r = probe(mutex, md5, name, namelen, &ip.sa, m_pDS, true);
+ HostDBInfo *old_r = probe(mutex, md5, true);
HostDBInfo old_info;
if (old_r)
old_info = *old_r;
@@ -1352,9 +1437,8 @@ HostDBContinuation::dnsEvent(int event, HostEnt * e)
int n = 0, nn = 0;
void* first = 0;
- uint8_t af = e ? e->ent.h_addrtype : AF_UNSPEC;
+ uint8_t af = e ? e->ent.h_addrtype : AF_UNSPEC; // address family
if (rr) {
- af = e->ent.h_addrtype;
if (is_srv() && !failed) {
n = e->srv_hosts.getCount();
} else {
@@ -1368,7 +1452,7 @@ HostDBContinuation::dnsEvent(int event, HostEnt * e)
if (! first) first = ptr;
++n;
} else {
- Warning("Zero address removed from round-robin list for '%s'", name);
+ Warning("Zero address removed from round-robin list for '%s'", md5.host_name);
}
// what's the point of @a n? Should there be something like
// if (n != nn) e->ent.h_addr_list[n] = e->ent->h_addr_list[nn];
@@ -1384,21 +1468,23 @@ HostDBContinuation::dnsEvent(int event, HostEnt * e)
} // else first is 0.
HostDBInfo *r = NULL;
- sockaddr_storage tip; // temporary IP data.
- sockaddr* tip_ptr = ats_ip_sa_cast(&tip);
- ats_ip_invalidate(tip_ptr);
- if (first) ip_addr_set(tip_ptr, af, first);
-
- if (is_byname())
- r = lookup_done(tip_ptr, name, rr, ttl_seconds, failed ? 0 : &e->srv_hosts);
- else if (is_srv())
- r = lookup_done(tip_ptr, /* junk: FIXME: is the code in lookup_done() wrong to NEED this? */
- name, /* hostname */
+ IpAddr tip; // temp storage if needed.
+
+ if (is_byname()) {
+ if (first) ip_addr_set(tip, af, first);
+ r = lookup_done(tip, md5.host_name, rr, ttl_seconds, failed ? 0 : &e->srv_hosts);
+ } else if (is_srv()) {
+ if (first) ip_addr_set(tip, af, first);
+ r = lookup_done(tip, /* junk: FIXME: is the code in lookup_done() wrong to NEED this? */
+ md5.host_name, /* hostname */
rr, /* is round robin, doesnt matter for SRV since we recheck getCount() inside lookup_done() */
ttl_seconds, /* ttl in seconds */
failed ? 0 : &e->srv_hosts);
- else
- r = lookup_done(tip_ptr, failed ? name : e->ent.h_name, false, ttl_seconds, failed ? 0 : &e->srv_hosts);
+ } else if (failed) {
+ r = lookup_done(tip, md5.host_name, false, ttl_seconds, 0);
+ } else {
+ r = lookup_done(md5.ip, e->ent.h_name, false, ttl_seconds, &e->srv_hosts);
+ }
if (rr) {
int s = HostDBRoundRobin::size(n, is_srv());
@@ -1469,11 +1555,18 @@ HostDBContinuation::dnsEvent(int event, HostEnt * e)
#ifdef NON_MODULAR
// if we are not the owner, put on the owner
//
- ClusterMachine *m = cluster_machine_at_depth(master_hash(md5));
+ ClusterMachine *m = cluster_machine_at_depth(master_hash(md5.hash));
if (m)
do_put_response(m, r, NULL);
#endif
+ // Check for IP family failover
+ if (failed && check_for_retry(md5.db_mark, host_res_style)) {
+ this->refresh_MD5();
+ SET_CONTINUATION_HANDLER(this, (HostDBContHandler) & HostDBContinuation::probeEvent);
+ thread->schedule_in(this, MUTEX_RETRY_DELAY);
+ return EVENT_CONT;
+ }
// try to callback the user
//
if (action.continuation) {
@@ -1521,15 +1614,15 @@ HostDBContinuation::make_get_message(char *buf, int size)
ink_assert(size >= (int) sizeof(HostDB_get_message));
HostDB_get_message *msg = reinterpret_cast<HostDB_get_message *>(buf);
- msg->md5 = md5;
- ats_ip_copy(&msg->ip.sa, &ip.sa);
+ msg->md5 = md5.hash;
+ ats_ip_set(&msg->ip.sa, md5.ip, htons(md5.port));
msg->cont = this;
// name
- ink_strlcpy(msg->name, name, sizeof(msg->name));
+ ink_strlcpy(msg->name, md5.host_name, sizeof(msg->name));
// length
- int len = sizeof(HostDB_get_message) - MAXDNAME + strlen(name) + 1;
+ int len = sizeof(HostDB_get_message) - MAXDNAME + md5.host_len + 1;
return len;
}
@@ -1550,11 +1643,11 @@ bool HostDBContinuation::do_get_response(Event * e)
m = NULL;
if (hostdb_migrate_on_demand)
- m = cluster_machine_at_depth(master_hash(md5), &probe_depth, past_probes);
+ m = cluster_machine_at_depth(master_hash(md5.hash), &probe_depth, past_probes);
else {
if (probe_depth)
return false;
- m = cluster_machine_at_depth(master_hash(md5));
+ m = cluster_machine_at_depth(master_hash(md5.hash));
probe_depth = 1;
}
@@ -1613,7 +1706,7 @@ HostDBContinuation::make_put_message(HostDBInfo * r, Continuation * c, char *buf
HostDB_put_message *msg = reinterpret_cast<HostDB_put_message *>(buf);
memset(msg, 0, sizeof(HostDB_put_message));
- msg->md5 = md5;
+ msg->md5 = md5.hash;
msg->cont = c;
if (r) {
ats_ip_copy(&msg->ip.sa, r->ip());
@@ -1627,10 +1720,10 @@ HostDBContinuation::make_put_message(HostDBInfo * r, Continuation * c, char *buf
}
// name
- ink_strlcpy(msg->name, name, sizeof(msg->name));
+ ink_strlcpy(msg->name, md5.host_name, sizeof(msg->name));
// length
- int len = sizeof(HostDB_put_message) - MAXDNAME + strlen(name) + 1;
+ int len = sizeof(HostDB_put_message) - MAXDNAME + md5.host_len + 1;
return len;
}
@@ -1677,7 +1770,7 @@ HostDBContinuation::probeEvent(int event, Event * e)
return EVENT_DONE;
}
- if (!hostdb_enable || (!*name && !ats_is_ip(&ip.sa))) {
+ if (!hostdb_enable || (!*md5.host_name && !md5.ip.isValid())) {
if (action.continuation)
action.continuation->handleEvent(EVENT_HOST_DB_LOOKUP, NULL);
#ifdef NON_MODULAR
@@ -1692,7 +1785,7 @@ HostDBContinuation::probeEvent(int event, Event * e)
// Do the probe
//
- HostDBInfo *r = probe(mutex, md5, name, namelen, &ip.sa, m_pDS);
+ HostDBInfo *r = probe(mutex, md5, false);
if (r)
HOSTDB_INCREMENT_DYN_STAT(hostdb_total_hits_stat);
@@ -1730,10 +1823,10 @@ HostDBContinuation::probeEvent(int event, Event * e)
int
HostDBContinuation::set_check_pending_dns()
{
- Queue<HostDBContinuation> &q = hostDB.pending_dns_for_hash(md5);
+ Queue<HostDBContinuation> &q = hostDB.pending_dns_for_hash(md5.hash);
HostDBContinuation *c = q.head;
for (; c; c = (HostDBContinuation *) c->link.next) {
- if (md5 == c->md5) {
+ if (md5.hash == c->md5.hash) {
Debug("hostdb", "enqueuing additional request");
q.enqueue(this);
return false;
@@ -1747,13 +1840,13 @@ HostDBContinuation::set_check_pending_dns()
void
HostDBContinuation::remove_trigger_pending_dns()
{
- Queue<HostDBContinuation> &q = hostDB.pending_dns_for_hash(md5);
+ Queue<HostDBContinuation> &q = hostDB.pending_dns_for_hash(md5.hash);
q.remove(this);
HostDBContinuation *c = q.head;
Queue<HostDBContinuation> qq;
while (c) {
HostDBContinuation *n = (HostDBContinuation *) c->link.next;
- if (md5 == c->md5) {
+ if (md5.hash == c->md5.hash) {
Debug("hostdb", "dequeuing additional request");
q.remove(c);
qq.enqueue(c);
@@ -1773,12 +1866,12 @@ HostDBContinuation::do_dns()
{
ink_assert(!action.cancelled);
if (is_byname()) {
- Debug("hostdb", "DNS %s", name);
- IpEndpoint tip;
- if (0 == ats_ip_pton(name, &tip.sa)) {
+ Debug("hostdb", "DNS %s", md5.host_name);
+ IpAddr tip;
+ if (0 == tip.load(md5.host_name)) {
// check 127.0.0.1 format // What the heck does that mean? - AMC
if (action.continuation) {
- HostDBInfo *r = lookup_done(&tip.sa, name, false, HOST_DB_MAX_TTL, NULL);
+ HostDBInfo *r = lookup_done(tip, md5.host_name, false, HOST_DB_MAX_TTL, NULL);
reply_to_cont(action.continuation, r);
}
hostdb_cont_free(this);
@@ -1790,22 +1883,21 @@ HostDBContinuation::do_dns()
else
timeout = NULL;
if (set_check_pending_dns()) {
+ DNSProcessor::Options opt;
+ opt.timeout = dns_lookup_timeout;
+ opt.host_res_style = host_res_style_for(md5.db_mark);
SET_HANDLER((HostDBContHandler) & HostDBContinuation::dnsEvent);
if (is_byname()) {
- DNSHandler *dnsH = 0;
-#ifdef SPLIT_DNS
- if (m_pDS)
- dnsH = static_cast<DNSServer *>(m_pDS)->x_dnsH;
-#endif
- pending_action = dnsProcessor.gethostbyname(this, name, dnsH, dns_lookup_timeout);
+ if (md5.dns_server)
+ opt.handler = md5.dns_server->x_dnsH;
+ pending_action = dnsProcessor.gethostbyname(this, md5.host_name, opt);
} else if (is_srv()) {
- DNSHandler *dnsH = 0;
- Debug("dns_srv", "SRV lookup of %s", name);
- pending_action = dnsProcessor.getSRVbyname(this, name, dnsH, dns_lookup_timeout);
+ Debug("dns_srv", "SRV lookup of %s", md5.host_name);
+ pending_action = dnsProcessor.getSRVbyname(this, md5.host_name, opt);
} else {
ip_text_buffer ipb;
- Debug("hostdb", "DNS IP %s", ats_ip_ntop(&ip.sa, ipb, sizeof ipb));
- pending_action = dnsProcessor.gethostbyaddr(this, &ip.sa, dns_lookup_timeout);
+ Debug("hostdb", "DNS IP %s", md5.ip.toString(ipb, sizeof ipb));
+ pending_action = dnsProcessor.gethostbyaddr(this, &md5.ip, opt);
}
} else {
SET_HANDLER((HostDBContHandler) & HostDBContinuation::dnsPendingEvent);
@@ -1846,7 +1938,7 @@ HostDBContinuation::clusterResponseEvent(int event, Event * e)
action = 0;
// just a remote fill
ink_assert(!missing);
- lookup_done(&ip.sa, name, false, ttl, NULL);
+ lookup_done(md5.ip, md5.host_name, false, ttl, NULL);
}
hostdb_cont_free(this);
return EVENT_DONE;
@@ -1878,7 +1970,7 @@ HostDBContinuation::clusterEvent(int event, Event * e)
}
if (e) {
HostDBContinuation *c = (HostDBContinuation *) e;
- HostDBInfo *r = lookup_done(&c->ip.sa, c->name, false, c->ttl, NULL);
+ HostDBInfo *r = lookup_done(md5.ip, c->md5.host_name, false, c->ttl, NULL);
r->app.allotment.application1 = c->app.allotment.application1;
r->app.allotment.application2 = c->app.allotment.application2;
@@ -1890,7 +1982,7 @@ HostDBContinuation::clusterEvent(int event, Event * e)
// fill the owner
//
if (hostdb_migrate_on_demand) {
- ClusterMachine *m = cluster_machine_at_depth(master_hash(md5));
+ ClusterMachine *m = cluster_machine_at_depth(master_hash(md5.hash));
if (m && m != c->from)
do_put_response(m, r, NULL);
}
@@ -1938,9 +2030,15 @@ void
get_hostinfo_ClusterFunction(ClusterHandler *ch, void *data, int len)
{
NOWARN_UNUSED(len);
- void *pDS = 0;
+ HostDBMD5 md5;
HostDB_get_message *msg = (HostDB_get_message *) data;
+ md5.host_name = msg->name;
+ md5.host_len = msg->namelen;
+ md5.ip.assign(&msg->ip.sa);
+ md5.port = ats_ip_port_host_order(&msg->ip.sa);
+ md5.hash = msg->md5;
+ md5.db_mark = db_mark_for(&msg->ip.sa);
#ifdef SPLIT_DNS
SplitDNS *pSD = 0;
char *hostname = msg->name;
@@ -1948,13 +2046,14 @@ get_hostinfo_ClusterFunction(ClusterHandler *ch, void *data, int len)
pSD = SplitDNSConfig::acquire();
if (0 != pSD) {
- pDS = pSD->getDNSRecord(hostname);
+ md5.dns_server = static_cast<DNSServer*>(pSD->getDNSRecord(hostname));
}
SplitDNSConfig::release(pSD);
}
#endif // SPLIT_DNS
HostDBContinuation *c = hostDBContAllocator.alloc();
+ HostDBContinuation::Options copt;
SET_CONTINUATION_HANDLER(c, (HostDBContHandler) & HostDBContinuation::probeEvent);
c->from = ch->machine;
c->from_cont = msg->cont;
@@ -1966,8 +2065,8 @@ get_hostinfo_ClusterFunction(ClusterHandler *ch, void *data, int len)
DNS servers
----------------------------------------- */
-
- c->init(msg->name, msg->namelen, &msg->ip.sa, msg->md5, NULL, pDS);
+ copt.host_res_style = host_res_style_for(&msg->ip.sa);
+ c->init(md5, copt);
c->mutex = hostDB.lock_for_bucket(fold_md5(msg->md5) % hostDB.buckets);
c->action.mutex = c->mutex;
dnsProcessor.thread->schedule_imm(c);
@@ -1980,9 +2079,18 @@ put_hostinfo_ClusterFunction(ClusterHandler *ch, void *data, int len)
NOWARN_UNUSED(len);
HostDB_put_message *msg = (HostDB_put_message *) data;
HostDBContinuation *c = hostDBContAllocator.alloc();
+ HostDBContinuation::Options copt;
+ HostDBMD5 md5;
SET_CONTINUATION_HANDLER(c, (HostDBContHandler) & HostDBContinuation::clusterResponseEvent);
- c->init(msg->name, msg->namelen, &msg->ip.sa, msg->md5, NULL);
+ md5.host_name = msg->name;
+ md5.host_len = msg->namelen;
+ md5.ip.assign(&msg->ip.sa);
+ md5.port = ats_ip_port_host_order(&msg->ip.sa);
+ md5.hash = msg->md5;
+ md5.db_mark = db_mark_for(&msg->ip.sa);
+ copt.host_res_style = host_res_style_for(&msg->ip.sa);
+ c->init(md5, copt);
c->mutex = hostDB.lock_for_bucket(fold_md5(msg->md5) % hostDB.buckets);
c->from_cont = msg->cont; // cannot use action if cont freed due to timeout
c->missing = msg->missing;
@@ -2096,11 +2204,10 @@ HostDBInfo::heap_offset_ptr()
ClusterMachine *
HostDBContinuation::master_machine(ClusterConfiguration * cc)
{
- return cc->machine_hash((int) (md5[1] >> 32));
+ return cc->machine_hash((int) (md5.hash[1] >> 32));
}
#endif // NON_MODULAR
-
#ifdef NON_MODULAR
struct ShowHostDB;
typedef int (ShowHostDB::*ShowHostDBEventHandler) (int event, Event * data);
@@ -2134,7 +2241,7 @@ struct ShowHostDB: public ShowCont
NOWARN_UNUSED(e);
SET_HANDLER(&ShowHostDB::showLookupDone);
if (name)
- hostDBProcessor.getbyname_re(this, name, 0, force ? HostDBProcessor::HOSTDB_FORCE_DNS_ALWAYS : 0);
+ hostDBProcessor.getbyname_re(this, name, 0, HostDBProcessor::Options().setFlags(force ? HostDBProcessor::HOSTDB_FORCE_DNS_ALWAYS : 0));
else
hostDBProcessor.getbyaddr_re(this, &ip.sa);
return EVENT_CONT;
@@ -2363,4 +2470,6 @@ ink_hostdb_init(ModuleVersion v)
RecRegisterRawStat(hostdb_rsb, RECT_PROCESS,
"proxy.process.hostdb.bytes", RECD_INT, RECP_NULL, (int) hostdb_bytes_stat, RecRawStatSyncCount);
+
+ ts_host_res_global_init();
}
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/043815e7/iocore/hostdb/I_HostDBProcessor.h
----------------------------------------------------------------------
diff --git a/iocore/hostdb/I_HostDBProcessor.h b/iocore/hostdb/I_HostDBProcessor.h
index 5f65a55..cf8aa19 100644
--- a/iocore/hostdb/I_HostDBProcessor.h
+++ b/iocore/hostdb/I_HostDBProcessor.h
@@ -371,22 +371,18 @@ struct HostDBRoundRobin
}
}
+ /** Find the index of @a addr in member @a info.
+ @return The index if found, -1 if not found.
+ */
+ int index_of(sockaddr const* addr);
HostDBInfo *find_ip(sockaddr const* addr);
- HostDBInfo *select_best(sockaddr const* client_ip, HostDBInfo * r = NULL);
+ /** Select the next entry after @a addr.
+ @note If @a addr isn't an address in the round robin nothing is updated.
+ @return The selected entry or @c NULL if @a addr wasn't present.
+ */
+ HostDBInfo* select_next(sockaddr const* addr);
HostDBInfo *select_best_http(sockaddr const* client_ip, ink_time_t now, int32_t fail_window);
- HostDBInfo *increment_round_robin()
- {
- bool bad = (n <= 0 || n > HOST_DB_MAX_ROUND_ROBIN_INFO || good <= 0 || good > HOST_DB_MAX_ROUND_ROBIN_INFO);
-
- if (bad) {
- ink_assert(!"bad round robin size");
- return NULL;
- }
- current++;
- return NULL;
- }
-
HostDBRoundRobin()
: n(0), good(0), current(0), timed_rr_ctime(0)
{ }
@@ -404,6 +400,7 @@ typedef void (Continuation::*process_srv_info_pfn) (HostDBInfo * r);
/** The Host Databse access interface. */
struct HostDBProcessor: public Processor
{
+ friend struct HostDBSyncer;
// Public Interface
// Lookup Hostinfo by name
@@ -422,33 +419,47 @@ struct HostDBProcessor: public Processor
HOSTDB_DO_NOT_ROUND_ROBIN = 4
};
+ /// Optional parameters for getby...
+ struct Options {
+ typedef Options self; ///< Self reference type.
+ int port; ///< Target service port (default 0 -> don't care)
+ int flags; ///< Processing flags (default HOSTDB_DO_NOT_FORCE_DNS)
+ int timeout; ///< Timeout value (default 0 -> default timeout)
+ HostResStyle host_res_style; ///< How to query host (default HOST_RES_IPV4)
+
+ Options() : port(0), flags(HOSTDB_DO_NOT_FORCE_DNS), timeout(0), host_res_style(HOST_RES_IPV4)
+ { }
+
+ /// Set the flags.
+ self& setFlags(int f) { flags = f; return *this; }
+ };
+
+ /// Default options.
+ static Options const DEFAULT_OPTIONS;
+
HostDBProcessor()
{ }
- inkcoreapi Action *getbyname_re(Continuation * cont, const char *hostname, int len = 0, int port = 0,
- int flags = HOSTDB_DO_NOT_FORCE_DNS);
+ inkcoreapi Action *getbyname_re(Continuation * cont, const char *hostname, int len, Options const& opt = DEFAULT_OPTIONS);
- Action *getSRVbyname_imm(Continuation * cont, process_srv_info_pfn process_srv_info, const char *hostname, int len = 0,
- int port = 0, int flags = HOSTDB_DO_NOT_FORCE_DNS, int timeout = 0);
+ Action *getSRVbyname_imm(Continuation * cont, process_srv_info_pfn process_srv_info, const char *hostname, int len, Options const& opt = DEFAULT_OPTIONS);
Action *getbyname_imm(
Continuation * cont,
process_hostdb_info_pfn process_hostdb_info,
const char *hostname,
- int len = 0,
- int port = 0,
- int flags = HOSTDB_DO_NOT_FORCE_DNS,
- int timeout = 0
+ int len,
+ Options const& opt = DEFAULT_OPTIONS
);
/** Lookup Hostinfo by addr */
Action *getbyaddr_re(Continuation * cont, sockaddr const* aip)
{
- return getby(cont, NULL, 0, aip, false);
+ return getby(cont, NULL, 0, aip, false, HOST_RES_NONE, 0);
}
-
+#if 0
/**
If you were unable to connect to an IP address associated with a
particular hostname, call this function and that IP address will
@@ -461,6 +472,7 @@ struct HostDBProcessor: public Processor
sockaddr const* aip,
const char *hostname, int len = 0
);
+#endif
/** Set the application information (fire-and-forget). */
void setbyname_appinfo(char *hostname, int len, int port, HostDBApplicationInfo * app)
@@ -493,12 +505,14 @@ struct HostDBProcessor: public Processor
// Private
HostDBCache *cache();
+private:
Action *getby(
Continuation * cont,
const char *hostname, int len,
sockaddr const* ip,
- bool aforce_dns, int timeout = 0
+ bool aforce_dns, HostResStyle host_res_style, int timeout
);
+public:
/** Set something.
@a aip can carry address and / or port information. If setting just
by a port value, the address should be set to INADDR_ANY which is of
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/043815e7/iocore/hostdb/P_HostDB.h
----------------------------------------------------------------------
diff --git a/iocore/hostdb/P_HostDB.h b/iocore/hostdb/P_HostDB.h
index d543495..548226b 100644
--- a/iocore/hostdb/P_HostDB.h
+++ b/iocore/hostdb/P_HostDB.h
@@ -58,9 +58,7 @@
HOSTDB_MODULE_MAJOR_VERSION, \
HOSTDB_MODULE_MINOR_VERSION, \
PRIVATE_MODULE_HEADER)
-HostDBInfo *probe(ProxyMutex * mutex,
- INK_MD5 & md5, const char *hostname, int len,
- sockaddr const* addr, void *pDS, bool ignore_timeout = false, bool is_srv_lookup = false);
+HostDBInfo *probe(ProxyMutex * mutex, HostDBMD5 const& md5, bool ignore_timeout);
-void make_md5(INK_MD5 & md5, const char *hostname, int len, int port, char *pDNSServers = 0, int srv = 0);
+void make_md5(INK_MD5 & md5, const char *hostname, int len, int port, char const*pDNSServers, HostDBMark mark);
#endif
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/043815e7/iocore/hostdb/P_HostDBProcessor.h
----------------------------------------------------------------------
diff --git a/iocore/hostdb/P_HostDBProcessor.h b/iocore/hostdb/P_HostDBProcessor.h
index b7961ea..06a3d44 100644
--- a/iocore/hostdb/P_HostDBProcessor.h
+++ b/iocore/hostdb/P_HostDBProcessor.h
@@ -30,6 +30,23 @@
#include "I_HostDBProcessor.h"
+/** Host DB record mark.
+
+ The records in the host DB are de facto segregated by roughly the
+ DNS query type. We use an intermediate type to provide a little flexibility
+ although the type is presumed to be a single byte.
+ */
+enum HostDBMark {
+ HOSTDB_MARK_GENERIC, ///< Anything that's not one of the other types.
+ HOSTDB_MARK_IPV4, ///< IPv4 / T_A
+ HOSTDB_MARK_IPV6, ///< IPv6 / T_AAAA
+ HOSTDB_MARK_SRV, ///< Service / T_SRV
+};
+/** Convert a HostDB @a mark to a string.
+ @return A static string.
+ */
+extern char const* string_for(HostDBMark mark);
+
inline unsigned int HOSTDB_CLIENT_IP_HASH(
sockaddr const* lhs,
sockaddr const* rhs
@@ -62,8 +79,8 @@ inline unsigned int HOSTDB_CLIENT_IP_HASH(
// Bump this any time hostdb format is changed
#define HOST_DB_CACHE_MAJOR_VERSION 2
-#define HOST_DB_CACHE_MINOR_VERSION 1
-// 2.1 : IPv6
+#define HOST_DB_CACHE_MINOR_VERSION 2
+// 2.2: IP family split 2.1 : IPv6
#define DEFAULT_HOST_DB_FILENAME "host.db"
#define DEFAULT_HOST_DB_SIZE (1<<14)
@@ -165,48 +182,40 @@ struct HostDBCache: public MultiCache<HostDBInfo>
HostDBCache();
};
-inline HostDBInfo*
-HostDBRoundRobin::find_ip(sockaddr const* ip) {
+inline int
+HostDBRoundRobin::index_of(sockaddr const* ip) {
bool bad = (n <= 0 || n > HOST_DB_MAX_ROUND_ROBIN_INFO || good <= 0 || good > HOST_DB_MAX_ROUND_ROBIN_INFO);
if (bad) {
ink_assert(!"bad round robin size");
- return NULL;
+ return -1;
}
for (int i = 0; i < good; i++) {
if (ats_ip_addr_eq(ip, info[i].ip())) {
- return &info[i];
+ return i;
}
}
- return NULL;
+ return -1;
}
-inline HostDBInfo *
-HostDBRoundRobin::select_best(sockaddr const* client_ip, HostDBInfo * r)
-{
- (void) r;
- bool bad = (n <= 0 || n > HOST_DB_MAX_ROUND_ROBIN_INFO || good <= 0 || good > HOST_DB_MAX_ROUND_ROBIN_INFO);
- if (bad) {
- ink_assert(!"bad round robin size");
- return NULL;
- }
- int best = 0;
- if (HostDBProcessor::hostdb_strict_round_robin) {
- best = current++ % good;
- } else {
- sockaddr const* ip = info[0].ip();
- unsigned int best_hash = HOSTDB_CLIENT_IP_HASH(client_ip, ip);
- for (int i = 1; i < good; i++) {
- ip = info[i].ip();
- unsigned int h = HOSTDB_CLIENT_IP_HASH(client_ip, ip);
- if (best_hash < h) {
- best = i;
- best_hash = h;
- }
+inline HostDBInfo*
+HostDBRoundRobin::find_ip(sockaddr const* ip) {
+ int idx = this->index_of(ip);
+ return idx < 0 ? NULL : &info[idx];
+}
+
+inline HostDBInfo*
+HostDBRoundRobin::select_next(sockaddr const* ip) {
+ HostDBInfo* zret = 0;
+ if (good > 1) {
+ int idx = this->index_of(ip);
+ if (idx >= 0) {
+ idx = (idx+1)%good;
+ zret = &info[idx];
}
}
- return &info[best];
+ return zret;
}
inline HostDBInfo *
@@ -290,6 +299,30 @@ HostDBRoundRobin::select_best_http(sockaddr const* client_ip, ink_time_t now, in
// Types
//
+/** Container for an MD5 hash and its dependent data.
+ This handles both the host name and raw address cases.
+*/
+struct HostDBMD5 {
+ typedef HostDBMD5 self; ///< Self reference type.
+
+ INK_MD5 hash; ///< The hash value.
+
+ char const* host_name; ///< Host name.
+ int host_len; ///< Length of @a _host_name
+ IpAddr ip; ///< IP address.
+ int port; ///< IP port (host order).
+ /// DNS server. Not strictly part of the MD5 data but
+ /// it's both used by @c HostDBContinuation and provides access to
+ /// MD5 data. It's just handier to store it here for both uses.
+ DNSServer* dns_server;
+ HostDBMark db_mark; ///< Mark / type of record.
+
+ /// Default constructor.
+ HostDBMD5();
+ /// Recompute and update the MD5 hash.
+ void refresh();
+};
+
//
// Handles a HostDB lookup request
//
@@ -299,19 +332,25 @@ typedef int (HostDBContinuation::*HostDBContHandler) (int, void *);
struct HostDBContinuation: public Continuation
{
Action action;
- IpEndpoint ip;
+ HostDBMD5 md5;
+ // IpEndpoint ip;
unsigned int ttl;
- bool is_srv_lookup;
+ // HostDBMark db_mark; ///< Target type.
+ /// Original IP address family style. Note this will disagree with
+ /// @a md5.db_mark when doing a retry on an alternate family. The retry
+ /// logic depends on it to avoid looping.
+ HostResStyle host_res_style; ///< Address family priority.
int dns_lookup_timeout;
- INK_MD5 md5;
+ // INK_MD5 md5;
Event *timeout;
ClusterMachine *from;
Continuation *from_cont;
HostDBApplicationInfo app;
int probe_depth;
ClusterMachine *past_probes[CONFIGURATION_HISTORY_PROBE_DEPTH];
- int namelen;
- char name[MAXDNAME];
+ // char name[MAXDNAME];
+ // int namelen;
+ char md5_host_name_store[MAXDNAME+1]; // used as backing store for @a md5
void *m_pDS;
Action *pending_action;
@@ -329,16 +368,18 @@ struct HostDBContinuation: public Continuation
int removeEvent(int event, Event * e);
int setbyEvent(int event, Event * e);
+ /// Recompute the MD5 and update ancillary values.
+ void refresh_MD5();
void do_dns();
bool is_byname()
{
- return ((*name && !is_srv_lookup) ? true : false);
+ return *md5.host_name && md5.db_mark != HOSTDB_MARK_SRV;
}
bool is_srv()
{
- return ((*name && is_srv_lookup) ? true : false);
+ return *md5.host_name && md5.db_mark == HOSTDB_MARK_SRV;
}
- HostDBInfo *lookup_done(sockaddr const* aip, char *aname, bool round_robin, unsigned int attl, SRVHosts * s = NULL);
+ HostDBInfo *lookup_done(IpAddr const& ip, char const* aname, bool round_robin, unsigned int attl, SRVHosts * s = NULL);
bool do_get_response(Event * e);
void do_put_response(ClusterMachine * m, HostDBInfo * r, Continuation * cont);
int failed_cluster_request(Event * e);
@@ -350,20 +391,35 @@ struct HostDBContinuation: public Continuation
HostDBInfo *insert(unsigned int attl);
- void init(const char *hostname, int len, sockaddr const* ip, INK_MD5 & amd5,
- Continuation * cont, void *pDS = 0, bool is_srv = false, int timeout = 0);
+ /** Optional values for @c init.
+ */
+ struct Options {
+ typedef Options self; ///< Self reference type.
+
+ int timeout; ///< Timeout value. Default 0
+ HostResStyle host_res_style; ///< IP address family fallback. Default @c HOST_RES_NONE
+ bool force_dns; ///< Force DNS lookup. Default @c false
+ Continuation* cont; ///< Continuation / action. Default @c NULL (none)
+
+ Options()
+ : timeout(0), host_res_style(HOST_RES_NONE), force_dns(false), cont(0)
+ { }
+ };
+ static const Options DEFAULT_OPTIONS; ///< Default defaults.
+ void init(HostDBMD5 const& md5,
+ Options const& opt = DEFAULT_OPTIONS);
int make_get_message(char *buf, int len);
int make_put_message(HostDBInfo * r, Continuation * c, char *buf, int len);
HostDBContinuation():
Continuation(NULL), ttl(0),
- is_srv_lookup(false), dns_lookup_timeout(0),
+ host_res_style(DEFAULT_OPTIONS.host_res_style),
+ dns_lookup_timeout(DEFAULT_OPTIONS.timeout),
timeout(0), from(0),
- from_cont(0), probe_depth(0), namelen(0), missing(false), force_dns(false), round_robin(false) {
- memset(&ip, 0, sizeof ip);
- memset(name, 0, MAXDNAME);
- md5.b[0] = 0;
- md5.b[1] = 0;
+ from_cont(0), probe_depth(0), missing(false),
+ force_dns(DEFAULT_OPTIONS.force_dns), round_robin(false) {
+ ink_zero(md5_host_name_store);
+ ink_zero(md5.hash);
SET_HANDLER((HostDBContHandler) & HostDBContinuation::probeEvent);
}
};
@@ -402,9 +458,9 @@ extern HostDBCache hostDB;
//extern Queue<HostDBContinuation> remoteHostDBQueue[MULTI_CACHE_PARTITIONS];
inline unsigned int
-master_hash(INK_MD5 & md5)
+master_hash(INK_MD5 const& md5)
{
- return (int) (md5[1] >> 32);
+ return static_cast<int>(md5[1] >> 32);
}
inline bool
@@ -422,7 +478,7 @@ HostDBCache::pending_dns_for_hash(INK_MD5 & md5)
inline int
HostDBContinuation::key_partition()
{
- return hostDB.partition_of_bucket(fold_md5(md5) % hostDB.buckets);
+ return hostDB.partition_of_bucket(fold_md5(md5.hash) % hostDB.buckets);
}
#endif /* _P_HostDBProcessor_h_ */
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/043815e7/iocore/hostdb/P_MultiCache.h
----------------------------------------------------------------------
diff --git a/iocore/hostdb/P_MultiCache.h b/iocore/hostdb/P_MultiCache.h
index b37ac83..f2ab823 100644
--- a/iocore/hostdb/P_MultiCache.h
+++ b/iocore/hostdb/P_MultiCache.h
@@ -447,9 +447,9 @@ template<class C> struct MultiCache: public MultiCacheBase
};
inline uint64_t
-fold_md5(INK_MD5 & md5)
+fold_md5(INK_MD5 const& md5)
{
- return (md5.fold());
+ return md5.fold();
}
template<class C> inline int MultiCache<C>::level_of_block(C * b)
Re: [1/2] git commit: TS-1422 TS-1307 : Update HostDB for better IPv6 handling.
Posted by Igor Galić <i....@brainsware.org>.
Failing Regressions arfter this update.
FATAL: /home/igalic/src/asf/trafficserver/iocore/dns/DNS.cc:400: failed assert `!"T_PTR query to DNS must be IP address."`
/tmp/org.apache.trafficserver.14892/dst/bin/traffic_server - STACK TRACE:
/tmp/org.apache.trafficserver.14892/dst/lib/libtsutil.so.3(ink_fatal+0xa3)[0x7f81f0c08f48]
/tmp/org.apache.trafficserver.14892/dst/lib/libtsutil.so.3(ink_get_rand()+0x0)[0x7f81f0c07c4c]
/tmp/org.apache.trafficserver.14892/dst/bin/traffic_server(DNSEntry::init(char const*, int, int, Continuation*, DNSProcessor::Options const&)+0x2a1)[0x7f81f12d5f7d]
/tmp/org.apache.trafficserver.14892/dst/bin/traffic_server(DNSProcessor::getby(char const*, int, int, Continuation*, DNSProcessor::Options const&)+0x161)[0x7f81f12d97c7]
/tmp/org.apache.trafficserver.14892/dst/bin/traffic_server(DNSProcessor::gethostbyaddr(Continuation*, IpAddr const*, DNSProcessor::Options const&)+0x40)[0x7f81f12cb78c]
/tmp/org.apache.trafficserver.14892/dst/bin/traffic_server(HostDBContinuation::do_dns()+0x483)[0x7f81f12c9bb9]
/tmp/org.apache.trafficserver.14892/dst/bin/traffic_server(HostDBContinuation::probeEvent(int, Event*)+0x308)[0x7f81f12c9484]
/tmp/org.apache.trafficserver.14892/dst/bin/traffic_server(Continuation::handleEvent(int, void*)+0x72)[0x7f81f116a0c8]
/tmp/org.apache.trafficserver.14892/dst/bin/traffic_server(EThread::process_event(Event*, int)+0x12c)[0x7f81f138c9a4]
/tmp/org.apache.trafficserver.14892/dst/bin/traffic_server(EThread::execute()+0x27c)[0x7f81f138cdc0]
/tmp/org.apache.trafficserver.14892/dst/bin/traffic_server(+0x32fb69)[0x7f81f138bb69]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x7e9a)[0x7f81f09d6e9a]
/lib/x86_64-linux-gnu/libc.so.6(clone+0x6d)[0x7f81ee8e1cbd]
[1] 18400 abort (core dumped) /tmp/org.apache.trafficserver.14892/dst/bin/traffic_server -R 1
-- i