nghttpx: Use BlockAllocator per DownstreamConfig

This commit is contained in:
Tatsuhiro Tsujikawa 2016-10-02 17:44:45 +09:00
parent f5285d1f5a
commit 272cfa320e
5 changed files with 129 additions and 42 deletions

View File

@ -804,7 +804,7 @@ namespace {
// as catch-all. We also parse protocol specified in |src_proto|.
//
// This function returns 0 if it succeeds, or -1.
int parse_mapping(Config *config, DownstreamAddrConfig addr,
int parse_mapping(Config *config, DownstreamAddrConfig &addr,
const StringRef &src_pattern, const StringRef &src_params) {
// This returns at least 1 element (it could be empty string). We
// will append '/' to all patterns, so it becomes catch-all pattern.
@ -824,7 +824,7 @@ int parse_mapping(Config *config, DownstreamAddrConfig addr,
addr.rise = params.rise;
addr.proto = params.proto;
addr.tls = params.tls;
addr.sni = ImmutableString{std::begin(params.sni), std::end(params.sni)};
addr.sni = make_string_ref(downstreamconf.balloc, params.sni);
auto &routerconf = downstreamconf.router;
auto &router = routerconf.router;
@ -833,18 +833,31 @@ int parse_mapping(Config *config, DownstreamAddrConfig addr,
for (const auto &raw_pattern : mapping) {
auto done = false;
std::string pattern;
StringRef pattern;
auto slash = std::find(std::begin(raw_pattern), std::end(raw_pattern), '/');
if (slash == std::end(raw_pattern)) {
// This effectively makes empty pattern to "/".
pattern.assign(std::begin(raw_pattern), std::end(raw_pattern));
util::inp_strlower(pattern);
pattern += '/';
// This effectively makes empty pattern to "/". 2 for '/' and
// terminal NULL character.
auto iov = make_byte_ref(downstreamconf.balloc, raw_pattern.size() + 2);
auto p = iov.base;
p = std::copy(std::begin(raw_pattern), std::end(raw_pattern), p);
util::inp_strlower(iov.base, p);
*p++ = '/';
*p = '\0';
pattern = StringRef{iov.base, p};
} else {
pattern.assign(std::begin(raw_pattern), slash);
util::inp_strlower(pattern);
pattern += http2::normalize_path(StringRef{slash, std::end(raw_pattern)},
StringRef{});
auto path = http2::normalize_path(downstreamconf.balloc,
StringRef{slash, std::end(raw_pattern)},
StringRef{});
auto iov = make_byte_ref(downstreamconf.balloc,
std::distance(std::begin(raw_pattern), slash) +
path.size() + 1);
auto p = iov.base;
p = std::copy(std::begin(raw_pattern), slash, p);
util::inp_strlower(iov.base, p);
p = std::copy(std::begin(path), std::end(path), p);
*p = '\0';
pattern = StringRef{iov.base, p};
}
for (auto &g : addr_groups) {
if (g.pattern == pattern) {
@ -863,7 +876,7 @@ int parse_mapping(Config *config, DownstreamAddrConfig addr,
}
auto idx = addr_groups.size();
addr_groups.emplace_back(StringRef{pattern});
addr_groups.emplace_back(pattern);
auto &g = addr_groups.back();
g.addrs.push_back(addr);
g.affinity = params.affinity;
@ -886,10 +899,13 @@ int parse_mapping(Config *config, DownstreamAddrConfig addr,
auto &router = wildcard_patterns.back().router;
router.add_route(path, idx);
auto rev_host = host.str();
std::reverse(std::begin(rev_host), std::end(rev_host));
auto iov = make_byte_ref(downstreamconf.balloc, host.size() + 1);
auto p = iov.base;
p = std::reverse_copy(std::begin(host), std::end(host), p);
*p = '\0';
auto rev_host = StringRef{iov.base, p};
rw_router.add_route(StringRef{rev_host}, wildcard_patterns.size() - 1);
rw_router.add_route(rev_host, wildcard_patterns.size() - 1);
} else {
(*it).router.add_route(path, idx);
}
@ -897,7 +913,7 @@ int parse_mapping(Config *config, DownstreamAddrConfig addr,
continue;
}
router.add_route(StringRef{g.pattern}, idx);
router.add_route(g.pattern, idx);
}
return 0;
}
@ -1804,12 +1820,14 @@ int parse_config(Config *config, int optid, const StringRef &opt,
switch (optid) {
case SHRPX_OPTID_BACKEND: {
auto &downstreamconf = *config->conn.downstream;
auto addr_end = std::find(std::begin(optarg), std::end(optarg), ';');
DownstreamAddrConfig addr{};
if (util::istarts_with(optarg, SHRPX_UNIX_PATH_PREFIX)) {
auto path = std::begin(optarg) + SHRPX_UNIX_PATH_PREFIX.size();
addr.host = ImmutableString(path, addr_end);
addr.host =
make_string_ref(downstreamconf.balloc, StringRef{path, addr_end});
addr.host_unix = true;
} else {
if (split_host_port(host, sizeof(host), &port,
@ -1817,7 +1835,7 @@ int parse_config(Config *config, int optid, const StringRef &opt,
return -1;
}
addr.host = ImmutableString(host);
addr.host = make_string_ref(downstreamconf.balloc, StringRef{host});
addr.port = port;
}
@ -3071,13 +3089,13 @@ int configure_downstream_group(Config *config, bool http2_proxy,
if (addr_groups.empty()) {
DownstreamAddrConfig addr{};
addr.host = ImmutableString::from_lit(DEFAULT_DOWNSTREAM_HOST);
addr.host = StringRef::from_lit(DEFAULT_DOWNSTREAM_HOST);
addr.port = DEFAULT_DOWNSTREAM_PORT;
addr.proto = PROTO_HTTP1;
DownstreamAddrGroupConfig g(StringRef::from_lit("/"));
g.addrs.push_back(std::move(addr));
router.add_route(StringRef{g.pattern}, addr_groups.size());
router.add_route(g.pattern, addr_groups.size());
addr_groups.push_back(std::move(g));
} else if (http2_proxy) {
// We don't support host mapping in these cases. Move all
@ -3090,7 +3108,7 @@ int configure_downstream_group(Config *config, bool http2_proxy,
std::vector<DownstreamAddrGroupConfig>().swap(addr_groups);
// maybe not necessary?
routerconf = RouterConfig{};
router.add_route(StringRef{catch_all.pattern}, addr_groups.size());
router.add_route(catch_all.pattern, addr_groups.size());
addr_groups.push_back(std::move(catch_all));
}
@ -3100,7 +3118,7 @@ int configure_downstream_group(Config *config, bool http2_proxy,
auto &sni = tlsconf.backend_sni_name;
for (auto &addr_group : addr_groups) {
for (auto &addr : addr_group.addrs) {
addr.sni = ImmutableString{sni};
addr.sni = StringRef{sni};
}
}
}
@ -3147,7 +3165,7 @@ int configure_downstream_group(Config *config, bool http2_proxy,
// for AF_UNIX socket, we use "localhost" as host for backend
// hostport. This is used as Host header field to backend and
// not going to be passed to any syscalls.
addr.hostport = ImmutableString::from_lit("localhost");
addr.hostport = StringRef::from_lit("localhost");
auto path = addr.host.c_str();
auto pathlen = addr.host.size();
@ -3171,10 +3189,11 @@ int configure_downstream_group(Config *config, bool http2_proxy,
continue;
}
addr.hostport = ImmutableString(
util::make_http_hostport(StringRef(addr.host), addr.port));
addr.hostport =
util::make_http_hostport(downstreamconf.balloc, addr.host, addr.port);
auto hostport = util::make_hostport(StringRef{addr.host}, addr.port);
auto hostport =
util::make_hostport(downstreamconf.balloc, addr.host, addr.port);
if (resolve_hostname(&addr.addr, addr.host.c_str(), addr.port,
downstreamconf.family, resolve_flags) == -1) {

View File

@ -54,6 +54,7 @@
#include "template.h"
#include "http2.h"
#include "network.h"
#include "allocator.h"
using namespace nghttp2;
@ -375,13 +376,13 @@ struct UpstreamAddr {
struct DownstreamAddrConfig {
Address addr;
// backend address. If |host_unix| is true, this is UNIX domain
// socket path.
ImmutableString host;
// socket path. This must be NULL terminated string.
StringRef host;
// <HOST>:<PORT>. This does not treat 80 and 443 specially. If
// |host_unix| is true, this is "localhost".
ImmutableString hostport;
StringRef hostport;
// hostname sent as SNI field
ImmutableString sni;
StringRef sni;
size_t fall;
size_t rise;
// Application protocol used in this group
@ -404,9 +405,9 @@ struct AffinityHash {
struct DownstreamAddrGroupConfig {
DownstreamAddrGroupConfig(const StringRef &pattern)
: pattern(pattern.c_str(), pattern.size()), affinity(AFFINITY_NONE) {}
: pattern(pattern), affinity(AFFINITY_NONE) {}
ImmutableString pattern;
StringRef pattern;
std::vector<DownstreamAddrConfig> addrs;
// Bunch of session affinity hash. Only used if affinity ==
// AFFINITY_IP.
@ -655,10 +656,11 @@ struct RateLimitConfig {
// field. router includes all path patterns sharing the same wildcard
// host.
struct WildcardPattern {
WildcardPattern(const StringRef &host)
: host(std::begin(host), std::end(host)) {}
WildcardPattern(const StringRef &host) : host(host) {}
ImmutableString host;
// This may not be NULL terminated. Currently it is only used for
// comparison.
StringRef host;
Router router;
};
@ -676,7 +678,8 @@ struct RouterConfig {
struct DownstreamConfig {
DownstreamConfig()
: timeout{},
: balloc(1024, 1024),
timeout{},
addr_group_catch_all{0},
connections_per_host{0},
connections_per_frontend{0},
@ -684,6 +687,12 @@ struct DownstreamConfig {
response_buffer_size{0},
family{0} {}
DownstreamConfig(const DownstreamConfig &) = delete;
DownstreamConfig(DownstreamConfig &&) = delete;
DownstreamConfig &operator=(const DownstreamConfig &) = delete;
DownstreamConfig &operator=(DownstreamConfig &&) = delete;
BlockAllocator balloc;
struct {
ev_tstamp read;
ev_tstamp write;

View File

@ -182,7 +182,8 @@ void Worker::replace_downstream_config(
auto &dst = downstream_addr_groups_[i];
dst = std::make_shared<DownstreamAddrGroup>();
dst->pattern = src.pattern;
dst->pattern =
ImmutableString{std::begin(src.pattern), std::end(src.pattern)};
auto shared_addr = std::make_shared<SharedDownstreamAddr>();
@ -198,16 +199,14 @@ void Worker::replace_downstream_config(
auto &dst_addr = shared_addr->addrs[j];
dst_addr.addr = src_addr.addr;
dst_addr.host =
make_string_ref(shared_addr->balloc, StringRef{src_addr.host});
dst_addr.host = make_string_ref(shared_addr->balloc, src_addr.host);
dst_addr.hostport =
make_string_ref(shared_addr->balloc, StringRef{src_addr.hostport});
make_string_ref(shared_addr->balloc, src_addr.hostport);
dst_addr.port = src_addr.port;
dst_addr.host_unix = src_addr.host_unix;
dst_addr.proto = src_addr.proto;
dst_addr.tls = src_addr.tls;
dst_addr.sni =
make_string_ref(shared_addr->balloc, StringRef{src_addr.sni});
dst_addr.sni = make_string_ref(shared_addr->balloc, src_addr.sni);
dst_addr.fall = src_addr.fall;
dst_addr.rise = src_addr.rise;

View File

@ -1172,6 +1172,32 @@ std::string make_http_hostport(const StringRef &host, uint16_t port) {
return hostport;
}
StringRef make_http_hostport(BlockAllocator &balloc, const StringRef &host,
uint16_t port) {
if (port != 80 && port != 443) {
return make_hostport(balloc, host, port);
}
auto ipv6 = ipv6_numeric_addr(host.c_str());
auto iov = make_byte_ref(balloc, host.size() + (ipv6 ? 2 : 0) + 1);
auto p = iov.base;
if (ipv6) {
*p++ = '[';
}
p = std::copy(std::begin(host), std::end(host), p);
if (ipv6) {
*p++ = ']';
}
*p = '\0';
return StringRef{iov.base, p};
}
std::string make_hostport(const StringRef &host, uint16_t port) {
auto ipv6 = ipv6_numeric_addr(host.c_str());
auto serv = utos(port);
@ -1197,6 +1223,34 @@ std::string make_hostport(const StringRef &host, uint16_t port) {
return hostport;
}
StringRef make_hostport(BlockAllocator &balloc, const StringRef &host,
uint16_t port) {
auto ipv6 = ipv6_numeric_addr(host.c_str());
auto serv = utos(port);
auto iov =
make_byte_ref(balloc, host.size() + (ipv6 ? 2 : 0) + 1 + serv.size());
auto p = iov.base;
if (ipv6) {
*p++ = '[';
}
p = std::copy(std::begin(host), std::end(host), p);
if (ipv6) {
*p++ = ']';
}
*p++ = ':';
std::copy(std::begin(serv), std::end(serv), p);
*p = '\0';
return StringRef{iov.base, p};
}
namespace {
void hexdump8(FILE *out, const uint8_t *first, const uint8_t *last) {
auto stop = std::min(first + 8, last);

View File

@ -635,10 +635,16 @@ std::string format_duration(double t);
// and "]". If |port| is 80 or 443, port part is omitted.
std::string make_http_hostport(const StringRef &host, uint16_t port);
StringRef make_http_hostport(BlockAllocator &balloc, const StringRef &host,
uint16_t port);
// Just like make_http_hostport(), but doesn't treat 80 and 443
// specially.
std::string make_hostport(const StringRef &host, uint16_t port);
StringRef make_hostport(BlockAllocator &balloc, const StringRef &host,
uint16_t port);
// Dumps |src| of length |len| in the format similar to `hexdump -C`.
void hexdump(FILE *out, const uint8_t *src, size_t len);