Skip to content

Commit

Permalink
Merge pull request apache#476 from solidwallofcode/edge-hostdb-restru…
Browse files Browse the repository at this point in the history
…cture

HostDB restructure
  • Loading branch information
shinrich authored and GitHub Enterprise committed Jun 16, 2021
2 parents 8d40c20 + 4a5ec19 commit 6f63e83
Show file tree
Hide file tree
Showing 38 changed files with 2,260 additions and 1,929 deletions.
1 change: 1 addition & 0 deletions configs/body_factory/default/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ dist_bodyfactory_DATA = \
connect\#dns_failed \
connect\#failed_connect \
connect\#hangup \
connect\#all_dead \
default \
interception\#no_host \
README \
Expand Down
17 changes: 17 additions & 0 deletions configs/body_factory/default/connect#all_dead
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<HTML>
<HEAD>
<TITLE>No Valid Host</TITLE>
</HEAD>

<BODY BGCOLOR="white" FGCOLOR="black">
<H1>No Valid Host</H1>
<HR>

<FONT FACE="Helvetica,Arial"><B>
Description: Unable to find a valid target host.

The server was found but all of the addresses are marked dead and so there is
no valid target address to which to connect. Please try again after a few minutes.
</B></FONT>
<HR>
</BODY>
40 changes: 40 additions & 0 deletions doc/developer-guide/core-architecture/hostdb.en.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
.. 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.
.. include:: ../../common.defs

.. highlight:: cpp
.. default-domain:: cpp

.. _developer-doc-hostdb:

HostDB
******

HostDB is a cache of DNS results. It is used to increase performance by aggregating address
resolution across transactions.

Runtime Structure
=================

DNS results are stored in a global hash table as instances of ``HostDBRecord``. Each instance
stores the results of a single query. These records are not updated with new DNS results. Instead
a new record instance is created and replaces the previous instance in the table. Some specific
dynamic data is migrated from the old record to the new one, such as the failure status of the
upstreams in the record.


24 changes: 24 additions & 0 deletions doc/uml/host-resolve.plantuml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
' SPDX-License-Identifier: Apache-2.0
' Licensed 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.

@startuml

hide empty description

state HttpSM {
state do_http_server_open {
}
}

state HandleRequest #cyan
state CallOSDNSLookup #cyan

CallOSDNSLookup -> OSDNSLookup

@enduml

14 changes: 7 additions & 7 deletions example/plugins/c-api/protocol/TxnSM.c
Original file line number Diff line number Diff line change
Expand Up @@ -477,8 +477,8 @@ int
state_dns_lookup(TSCont contp, TSEvent event, TSHostLookupResult host_info)
{
TxnSM *txn_sm = (TxnSM *)TSContDataGet(contp);
struct sockaddr const *q_server_addr;
struct sockaddr_in ip_addr;
struct sockaddr_storage q_server_addr;
struct sockaddr_in *addr;

TSDebug(PLUGIN_NAME, "enter state_dns_lookup");

Expand All @@ -489,16 +489,16 @@ state_dns_lookup(TSCont contp, TSEvent event, TSHostLookupResult host_info)
txn_sm->q_pending_action = NULL;

/* Get the server IP from data structure TSHostLookupResult. */
q_server_addr = TSHostLookupResultAddrGet(host_info);
TSHostLookupResultAddrGet(host_info, (struct sockaddr *)&q_server_addr);

/* Connect to the server using its IP. */
set_handler(txn_sm->q_current_handler, (TxnSMHandler)&state_connect_to_server);
TSAssert(txn_sm->q_pending_action == NULL);
TSAssert(q_server_addr->sa_family == AF_INET); /* NO IPv6 in this plugin */
TSAssert(q_server_addr.ss_family == AF_INET); /* NO IPv6 in this plugin */
addr = (struct sockaddr_in *)(&q_server_addr);

memcpy(&ip_addr, q_server_addr, sizeof(ip_addr));
ip_addr.sin_port = txn_sm->q_server_port;
txn_sm->q_pending_action = TSNetConnect(contp, (struct sockaddr const *)&ip_addr);
addr->sin_port = txn_sm->q_server_port;
txn_sm->q_pending_action = TSNetConnect(contp, (struct sockaddr const *)addr);

return TS_SUCCESS;
}
Expand Down
9 changes: 8 additions & 1 deletion include/ts/ts.h
Original file line number Diff line number Diff line change
Expand Up @@ -1926,7 +1926,14 @@ tsapi TSReturnCode TSPortDescriptorAccept(TSPortDescriptor, TSCont);
/* --------------------------------------------------------------------------
DNS Lookups */
tsapi TSAction TSHostLookup(TSCont contp, const char *hostname, size_t namelen);
tsapi struct sockaddr const *TSHostLookupResultAddrGet(TSHostLookupResult lookup_result);
/** Retrieve an address from the host lookup.
*
* @param lookup_result Result handle passed to event callback.
* @param dst Destination for copying the address.
* @return @c TS_SUCCESS if the address was available and copied, @c TS_ERROR otherwise.
*/
tsapi TSReturnCode TSHostLookupResultAddrGet(TSHostLookupResult lookup_result, struct sockaddr *dst);

/* TODO: Eventually, we might want something like this as well, but it requires
support for building the HostDBInfo struct:
tsapi void TSHostLookupResultSet(TSHttpTxn txnp, TSHostLookupResult result);
Expand Down
7 changes: 7 additions & 0 deletions include/tscore/BufferWriterForward.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,11 @@ class BWFormat;

class BufferWriter;

/// Storage for debug messages.
/// If @c bwprint is used with this, the storage is reused which minimizes allocations.
/// E.g.
/// @code

inline thread_local std::string bw_dbg;

} // namespace ts
9 changes: 9 additions & 0 deletions include/tscore/Diags.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,15 @@ extern inkcoreapi Diags *diags;
} \
} while (0)

#define Debug_bw(tag, fmt, ...) \
do { \
if (unlikely(diags->on())) { \
static const SourceLocation loc = MakeSourceLocation(); \
static LogMessage log_message; \
log_message.debug(tag, loc, "%s", ts::bwprint(ts::bw_dbg, fmt, __VA_ARGS__).c_str()); \
} \
} while (0)

/** Same as Debug above, but this allows a positive override of the tag
* mechanism by a flag boolean.
*
Expand Down
16 changes: 16 additions & 0 deletions include/tscore/bwf_std_format.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <atomic>
#include <array>
#include <string_view>
#include <chrono>
#include "tscpp/util/TextView.h"
#include "tscore/BufferWriterForward.h"

Expand All @@ -37,6 +38,21 @@ bwformat(ts::BufferWriter &w, ts::BWFSpec const &spec, atomic<T> const &v)
{
return ts::bwformat(w, spec, v.load());
}

template <typename Rep, typename Period>
ts::BufferWriter &
bwformat(ts::BufferWriter &w, ts::BWFSpec const &spec, chrono::duration<Rep, Period> const &d)
{
return bwformat(w, spec, d.count());
}

template <typename Clock, typename Duration>
ts::BufferWriter &
bwformat(ts::BufferWriter &w, ts::BWFSpec const &spec, chrono::time_point<Clock, Duration> const &t)
{
return bwformat(w, spec, t.time_since_epoch());
}

} // end namespace std

namespace ts
Expand Down
10 changes: 10 additions & 0 deletions include/tscore/ink_inet.h
Original file line number Diff line number Diff line change
Expand Up @@ -1231,6 +1231,16 @@ struct IpAddr {
size_t len ///< [in] Size of buffer.
) const;

/** Write the address to a socket address.
*
* @param dest Socket address to update.
* @return @a dest
*
* The address and family are updated. The port is unchanged. @a dest is assumed to be the
* appropriate underlying type for the family of @a this.
*/
sockaddr *toSockAddr(sockaddr *dest) const;

/// Equality.
bool
operator==(self const &that) const
Expand Down
14 changes: 13 additions & 1 deletion include/tscore/ink_time.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@

#pragma once

#include <chrono>

#include "tscore/ink_platform.h"
#include "tscore/ink_defs.h"
#include "tscore/ink_hrtime.h"
Expand All @@ -43,7 +45,17 @@
*===========================================================================*/

typedef time_t ink_time_t;
using ink_time_t = time_t;
using ts_clock = std::chrono::system_clock;
using ts_time = ts_clock::time_point;
using ts_hr_clock = std::chrono::high_resolution_clock;
using ts_hr_time = ts_hr_clock::time_point;

using ts_seconds = std::chrono::seconds;
using ts_milliseconds = std::chrono::milliseconds;

/// Equivalent of 0 for @c ts_time. This should be used as the default initializer.
static constexpr ts_time TS_TIME_ZERO;

/*===========================================================================*
Expand Down
7 changes: 7 additions & 0 deletions include/tscore/ts_file.h
Original file line number Diff line number Diff line change
Expand Up @@ -329,5 +329,12 @@ namespace file

/* ------------------------------------------------------------------- */
} // namespace file

inline BufferWriter &
bwformat(BufferWriter &w, BWFSpec const &spec, file::path const &path)
{
return bwformat(w, spec, path.string());
}

} // namespace ts
/* ------------------------------------------------------------------- */
23 changes: 23 additions & 0 deletions include/tscpp/util/TextView.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,29 @@ int strcasecmp(const std::string_view &lhs, const std::string_view &rhs);
*/
int memcmp(const std::string_view &lhs, const std::string_view &rhs);

/** Copy bytes.
*
* @param dst Destination buffer.
* @param src Original string.
* @return @a dest
*
* This is a convenience for
* @code
* memcpy(dst, src.data(), size.size());
* @endcode
* Therefore @a dst must point at a buffer large enought to hold @a src. If this is not already
* determined, then presuming @c DST_SIZE is the size of the buffer at @a dst
* @code
* memcpy(dst, src.prefix(DST_SIZE));
* @endcode
*
*/
inline void *
memcpy(void *dst, const std::string_view &src)
{
return memcpy(dst, src.data(), src.size());
}

/** Compare views with ordering.
*
* @param lhs input view
Expand Down
40 changes: 20 additions & 20 deletions iocore/dns/DNS.cc
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ DNSProcessor::DNSProcessor()
}

void
DNSEntry::init(const char *x, int len, int qtype_arg, Continuation *acont, DNSProcessor::Options const &opt)
DNSEntry::init(DNSQueryData target, int qtype_arg, Continuation *acont, DNSProcessor::Options const &opt)
{
qtype = qtype_arg;
host_res_style = opt.host_res_style;
Expand All @@ -427,21 +427,16 @@ DNSEntry::init(const char *x, int len, int qtype_arg, Continuation *acont, DNSPr
mutex = dnsH->mutex;

if (is_addr_query(qtype) || qtype == T_SRV) {
if (len) {
len = len > (MAXDNAME - 1) ? (MAXDNAME - 1) : len;
memcpy(qname, x, len);
qname[len] = 0;
orig_qname_len = qname_len = len;
} else {
qname_len = ink_strlcpy(qname, x, MAXDNAME);
orig_qname_len = qname_len;
}
auto name = target.name.substr(0, MAXDNAME); // be sure of safe copy into @a qname
memcpy(qname, name);
qname[name.size()] = '\0';
orig_qname_len = qname_len = name.size();
} else { // T_PTR
IpAddr const *ip = reinterpret_cast<IpAddr const *>(x);
if (ip->isIp6()) {
orig_qname_len = qname_len = make_ipv6_ptr(&ip->_addr._ip6, qname);
} else if (ip->isIp4()) {
orig_qname_len = qname_len = make_ipv4_ptr(ip->_addr._ip4, qname);
auto addr = target.addr;
if (addr->isIp6()) {
orig_qname_len = qname_len = make_ipv6_ptr(&addr->_addr._ip6, qname);
} else if (addr->isIp4()) {
orig_qname_len = qname_len = make_ipv4_ptr(addr->_addr._ip4, qname);
} else {
ink_assert(!"T_PTR query to DNS must be IP address.");
}
Expand Down Expand Up @@ -1305,15 +1300,20 @@ DNSEntry::mainEvent(int event, Event *e)
}

Action *
DNSProcessor::getby(const char *x, int len, int type, Continuation *cont, Options const &opt)
DNSProcessor::getby(DNSQueryData x, 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, opt.timeout);
if (type == T_PTR) {
Debug("dns", "received reverse query type = %d, timeout = %d", type, opt.timeout);
} else {
Debug("dns", "received query %.*s type = %d, timeout = %d", int(x.name.size()), x.name.data(), type, opt.timeout);
if (type == T_SRV) {
Debug("dns_srv", "DNSProcessor::getby attempting an SRV lookup for %.*s, timeout = %d", int(x.name.size()), x.name.data(),
opt.timeout);
}
}
DNSEntry *e = dnsEntryAllocator.alloc();
e->retries = dns_retries;
e->init(x, len, type, cont, opt);
e->init(x, type, cont, opt);
MUTEX_TRY_LOCK(lock, e->mutex, this_ethread());
if (!lock.is_locked()) {
thread->schedule_imm(e);
Expand Down
Loading

0 comments on commit 6f63e83

Please sign in to comment.