Commit 127681fc authored by bnc's avatar bnc Committed by Commit bot

Use linked hash map for broken alternative service queue.

Use linked hash map for broken alternative service queue in
HttpServerPropertiesImpl.  This container has efficient lookup by key, allowing
us to use it as the definitive set of broken alternative services in an upcoming
CL.

Also rename broken_alternate_protocol_map_ to
recently_broken_alternative_services_ for consistency and because it makes more
sense.

BUG=392576

Review URL: https://codereview.chromium.org/989253005

Cr-Commit-Position: refs/heads/master@{#319764}
parent 9d2bd87c
......@@ -99,6 +99,11 @@ struct NET_EXPORT AlternativeService {
AlternativeService& operator=(const AlternativeService& alternative_service) =
default;
bool operator==(const AlternativeService& other) const {
return protocol == other.protocol && host == other.host &&
port == other.port;
}
bool operator<(const AlternativeService& other) const {
if (protocol != other.protocol)
return protocol < other.protocol;
......
......@@ -320,12 +320,16 @@ void HttpServerPropertiesImpl::SetBrokenAlternateProtocol(
it->second.is_broken = true;
const AlternativeService alternative_service(alternate.protocol,
server.host(), alternate.port);
int count = ++broken_alternate_protocol_map_[alternative_service];
int count = ++recently_broken_alternative_services_[alternative_service];
base::TimeDelta delay =
base::TimeDelta::FromSeconds(kBrokenAlternateProtocolDelaySecs);
base::TimeTicks when = base::TimeTicks::Now() + delay * (1 << (count - 1));
broken_alternate_protocol_list_.push_back(
BrokenAlternateProtocolEntryWithTime(alternative_service, when));
auto result = broken_alternative_services_.insert(
std::make_pair(alternative_service, when));
// Return if alternative service is already in expiration queue.
if (!result.second) {
return;
}
// Do not leave this host as canonical so that we don't infer the other
// hosts are also broken without testing them first.
......@@ -333,7 +337,7 @@ void HttpServerPropertiesImpl::SetBrokenAlternateProtocol(
// If this is the only entry in the list, schedule an expiration task.
// Otherwise it will be rescheduled automatically when the pending task runs.
if (broken_alternate_protocol_list_.size() == 1) {
if (broken_alternative_services_.size() == 1) {
ScheduleBrokenAlternateProtocolMappingsExpiration();
}
}
......@@ -345,7 +349,8 @@ bool HttpServerPropertiesImpl::WasAlternateProtocolRecentlyBroken(
return false;
const AlternativeService alternative_service(
alternate_protocol.protocol, server.host(), alternate_protocol.port);
return ContainsKey(broken_alternate_protocol_map_, alternative_service);
return ContainsKey(recently_broken_alternative_services_,
alternative_service);
}
void HttpServerPropertiesImpl::ConfirmAlternateProtocol(
......@@ -355,7 +360,7 @@ void HttpServerPropertiesImpl::ConfirmAlternateProtocol(
return;
const AlternativeService alternative_service(
alternate_protocol.protocol, server.host(), alternate_protocol.port);
broken_alternate_protocol_map_.erase(alternative_service);
recently_broken_alternative_services_.erase(alternative_service);
}
void HttpServerPropertiesImpl::ClearAlternateProtocol(
......@@ -504,29 +509,28 @@ void HttpServerPropertiesImpl::RemoveCanonicalHost(
void HttpServerPropertiesImpl::ExpireBrokenAlternateProtocolMappings() {
base::TimeTicks now = base::TimeTicks::Now();
while (!broken_alternate_protocol_list_.empty()) {
BrokenAlternateProtocolEntryWithTime entry_with_time =
broken_alternate_protocol_list_.front();
if (now < entry_with_time.when) {
while (!broken_alternative_services_.empty()) {
BrokenAlternativeServices::iterator it =
broken_alternative_services_.begin();
if (now < it->second) {
break;
}
const AlternativeService& alternative_service =
entry_with_time.alternative_service;
const AlternativeService& alternative_service = it->first;
ClearAlternateProtocol(
HostPortPair(alternative_service.host, alternative_service.port));
broken_alternate_protocol_list_.pop_front();
broken_alternative_services_.erase(it);
}
ScheduleBrokenAlternateProtocolMappingsExpiration();
}
void
HttpServerPropertiesImpl::ScheduleBrokenAlternateProtocolMappingsExpiration() {
if (broken_alternate_protocol_list_.empty()) {
if (broken_alternative_services_.empty()) {
return;
}
base::TimeTicks now = base::TimeTicks::Now();
base::TimeTicks when = broken_alternate_protocol_list_.front().when;
base::TimeTicks when = broken_alternative_services_.front().second;
base::TimeDelta delay = when > now ? when - now : base::TimeDelta();
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
......
......@@ -17,6 +17,7 @@
#include "base/threading/non_thread_safe.h"
#include "base/values.h"
#include "net/base/host_port_pair.h"
#include "net/base/linked_hash_map.h"
#include "net/base/net_export.h"
#include "net/http/http_server_properties.h"
......@@ -24,6 +25,17 @@ namespace base {
class ListValue;
}
namespace BASE_HASH_NAMESPACE {
template <>
struct hash<net::AlternativeService> {
size_t operator()(const net::AlternativeService& entry) const {
return entry.protocol ^ hash<std::string>()(entry.host) ^ entry.port;
}
};
} // namespace BASE_HASH_NAMESPACE
namespace net {
// The implementation for setting/retrieving the HTTP server properties.
......@@ -117,23 +129,13 @@ class NET_EXPORT HttpServerPropertiesImpl
typedef std::vector<std::string> CanonicalSufficList;
typedef std::set<HostPortPair> Http11ServerHostPortSet;
// Broken alternative service with expiration time.
struct BrokenAlternateProtocolEntryWithTime {
BrokenAlternateProtocolEntryWithTime(
const AlternativeService& alternative_service,
base::TimeTicks when)
: alternative_service(alternative_service), when(when) {}
AlternativeService alternative_service;
base::TimeTicks when;
};
// Deque of BrokenAlternateProtocolEntryWithTime items, ordered by expiration
// time.
typedef std::deque<BrokenAlternateProtocolEntryWithTime>
BrokenAlternateProtocolList;
// Map from (server, alternate protocol and port) to the number of
// times that alternate protocol has been marked broken for that server.
typedef std::map<AlternativeService, int> BrokenAlternateProtocolMap;
// Linked hash map from AlternativeService to expiration time. This container
// is a queue with O(1) enqueue and dequeue, and a hash_map with O(1) lookup
// at the same time.
typedef linked_hash_map<AlternativeService, base::TimeTicks>
BrokenAlternativeServices;
// Map to the number of times each alternative service has been marked broken.
typedef std::map<AlternativeService, int> RecentlyBrokenAlternativeServices;
// Return the iterator for |server|, or for its canonical host, or end.
AlternateProtocolMap::const_iterator GetAlternateProtocolIterator(
......@@ -150,8 +152,10 @@ class NET_EXPORT HttpServerPropertiesImpl
Http11ServerHostPortSet http11_servers_;
AlternateProtocolMap alternate_protocol_map_;
BrokenAlternateProtocolList broken_alternate_protocol_list_;
BrokenAlternateProtocolMap broken_alternate_protocol_map_;
BrokenAlternativeServices broken_alternative_services_;
// Class invariant: Every alternative service in broken_alternative_services_
// must also be in recently_broken_alternative_services_.
RecentlyBrokenAlternativeServices recently_broken_alternative_services_;
IPAddressNumber last_quic_address_;
SpdySettingsMap spdy_settings_map_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment