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