Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(123)

Side by Side Diff: net/http/broken_alternative_services.cc

Issue 2932953002: Persist broken and recently-broken alt-svcs to prefs in HttpServerPropertiesManager (Closed)
Patch Set: Added a DCHECK Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2017 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/http/broken_alternative_services.h" 5 #include "net/http/broken_alternative_services.h"
6 6
7 #include "base/memory/singleton.h" 7 #include "base/memory/singleton.h"
8 #include "base/time/tick_clock.h" 8 #include "base/time/tick_clock.h"
9 #include "base/time/time.h" 9 #include "base/time/time.h"
10 #include "net/http/http_server_properties_impl.h" 10 #include "net/http/http_server_properties_impl.h"
(...skipping 12 matching lines...) Expand all
23 int broken_count) { 23 int broken_count) {
24 DCHECK_GE(broken_count, 0); 24 DCHECK_GE(broken_count, 0);
25 if (broken_count > kBrokenDelayMaxShift) 25 if (broken_count > kBrokenDelayMaxShift)
26 broken_count = kBrokenDelayMaxShift; 26 broken_count = kBrokenDelayMaxShift;
27 return base::TimeDelta::FromSeconds(kBrokenAlternativeProtocolDelaySecs) * 27 return base::TimeDelta::FromSeconds(kBrokenAlternativeProtocolDelaySecs) *
28 (1 << broken_count); 28 (1 << broken_count);
29 } 29 }
30 30
31 } // namespace 31 } // namespace
32 32
33 BrokenAlternativeServices::BrokenAlternativeServices(Delegate* delegate, 33 BrokenAlternativeServices::BrokenAlternativeServices(Delegate* delegate)
34 base::TickClock* clock)
35 : delegate_(delegate), 34 : delegate_(delegate),
36 clock_(clock), 35 clock_(&default_clock_),
37 recently_broken_alternative_services_( 36 recently_broken_alternative_services_(
38 RecentlyBrokenAlternativeServices::NO_AUTO_EVICT), 37 RecentlyBrokenAlternativeServices::NO_AUTO_EVICT),
39 weak_ptr_factory_(this) { 38 weak_ptr_factory_(this) {
40 DCHECK(delegate_); 39 DCHECK(delegate_);
41 DCHECK(clock_);
42 } 40 }
43 41
44 BrokenAlternativeServices::~BrokenAlternativeServices() {} 42 BrokenAlternativeServices::~BrokenAlternativeServices() {}
45 43
44 void BrokenAlternativeServices::Clear() {
45 expiration_timer_.Stop();
46 broken_alternative_service_list_.clear();
47 broken_alternative_service_map_.clear();
48 recently_broken_alternative_services_.Clear();
49 }
50
46 void BrokenAlternativeServices::MarkAlternativeServiceBroken( 51 void BrokenAlternativeServices::MarkAlternativeServiceBroken(
47 const AlternativeService& alternative_service) { 52 const AlternativeService& alternative_service) {
48 // Empty host means use host of origin, callers are supposed to substitute. 53 // Empty host means use host of origin, callers are supposed to substitute.
49 DCHECK(!alternative_service.host.empty()); 54 DCHECK(!alternative_service.host.empty());
50 DCHECK_NE(kProtoUnknown, alternative_service.protocol); 55 DCHECK_NE(kProtoUnknown, alternative_service.protocol);
51 56
52 auto it = recently_broken_alternative_services_.Get(alternative_service); 57 auto it = recently_broken_alternative_services_.Get(alternative_service);
53 int broken_count = 0; 58 int broken_count = 0;
54 if (it == recently_broken_alternative_services_.end()) { 59 if (it == recently_broken_alternative_services_.end()) {
55 recently_broken_alternative_services_.Put(alternative_service, 1); 60 recently_broken_alternative_services_.Put(alternative_service, 1);
56 } else { 61 } else {
57 broken_count = it->second++; 62 broken_count = it->second++;
58 } 63 }
59 base::TimeTicks expiration = 64 base::TimeTicks expiration =
60 clock_->NowTicks() + 65 clock_->NowTicks() +
61 ComputeBrokenAlternativeServiceExpirationDelay(broken_count); 66 ComputeBrokenAlternativeServiceExpirationDelay(broken_count);
62 // Return if alternative service is already in expiration queue. 67 // Return if alternative service is already in expiration queue.
63 BrokenAlternativeServiceList::iterator list_it; 68 BrokenAlternativeServiceList::iterator list_it;
64 if (!AddToBrokenAlternativeServiceListAndMap(alternative_service, expiration, 69 if (!AddToBrokenAlternativeServiceListAndMap(alternative_service, expiration,
65 &list_it)) { 70 &list_it)) {
66 return; 71 return;
67 } 72 }
68 73
69 // If this is now the first entry in the list (i.e. |alternative_service| is 74 // If this is now the first entry in the list (i.e. |alternative_service| is
70 // the next alt svc to expire), schedule an expiration task for it. 75 // the next alt svc to expire), schedule an expiration task for it.
71 if (list_it == broken_alternative_service_list_.begin()) { 76 if (list_it == broken_alternative_service_list_.begin()) {
72 ScheduleBrokenAlternateProtocolMappingsExpiration(); 77 ScheduleBrokenAlternateProtocolMappingsExpiration(
78 broken_alternative_service_list_.front().second);
73 } 79 }
74 } 80 }
75 81
76 void BrokenAlternativeServices::MarkAlternativeServiceRecentlyBroken( 82 void BrokenAlternativeServices::MarkAlternativeServiceRecentlyBroken(
77 const AlternativeService& alternative_service) { 83 const AlternativeService& alternative_service) {
78 DCHECK_NE(kProtoUnknown, alternative_service.protocol); 84 DCHECK_NE(kProtoUnknown, alternative_service.protocol);
79 if (recently_broken_alternative_services_.Get(alternative_service) == 85 if (recently_broken_alternative_services_.Get(alternative_service) ==
80 recently_broken_alternative_services_.end()) { 86 recently_broken_alternative_services_.end()) {
81 recently_broken_alternative_services_.Put(alternative_service, 1); 87 recently_broken_alternative_services_.Put(alternative_service, 1);
82 } 88 }
(...skipping 24 matching lines...) Expand all
107 broken_alternative_service_list_.erase(map_it->second); 113 broken_alternative_service_list_.erase(map_it->second);
108 broken_alternative_service_map_.erase(map_it); 114 broken_alternative_service_map_.erase(map_it);
109 } 115 }
110 116
111 auto it = recently_broken_alternative_services_.Get(alternative_service); 117 auto it = recently_broken_alternative_services_.Get(alternative_service);
112 if (it != recently_broken_alternative_services_.end()) { 118 if (it != recently_broken_alternative_services_.end()) {
113 recently_broken_alternative_services_.Erase(it); 119 recently_broken_alternative_services_.Erase(it);
114 } 120 }
115 } 121 }
116 122
117 const BrokenAlternativeServiceList& 123 void BrokenAlternativeServices::SetTickClockForTesting(base::TickClock* clock) {
118 BrokenAlternativeServices::broken_alternative_service_list() const { 124 DCHECK(clock);
119 return broken_alternative_service_list_; 125 clock_ = clock;
Ryan Hamilton 2017/06/12 18:57:32 I don't think I understand the clock-related chang
wangyix1 2017/06/14 00:01:25 Acknowledged. Will go back to clock being set usin
120 } 126 }
121 127
122 const RecentlyBrokenAlternativeServices& 128 void BrokenAlternativeServices::AddBrokenAndRecentlyBrokenAlternativeServices(
123 BrokenAlternativeServices::recently_broken_alternative_services() const {
124 return recently_broken_alternative_services_;
125 }
126
127 bool BrokenAlternativeServices::AddBrokenAndRecentlyBrokenAlternativeServices(
128 std::unique_ptr<BrokenAlternativeServiceList> 129 std::unique_ptr<BrokenAlternativeServiceList>
129 broken_alternative_service_list, 130 broken_alternative_service_list,
130 std::unique_ptr<RecentlyBrokenAlternativeServices> 131 std::unique_ptr<RecentlyBrokenAlternativeServices>
131 recently_broken_alternative_services) { 132 recently_broken_alternative_services) {
132 DCHECK(broken_alternative_service_list); 133 DCHECK(broken_alternative_service_list);
133 DCHECK(recently_broken_alternative_services); 134 DCHECK(recently_broken_alternative_services);
134 135
135 // Make sure all alt svcs in |broken_alternative_service_list| has an entry 136 // Make sure all alt svcs in |broken_alternative_service_list| has an entry
136 // in |recently_broken_alternative_services| 137 // in |recently_broken_alternative_services|
137 for (const auto& pair : *broken_alternative_service_list) { 138 for (const auto& pair : *broken_alternative_service_list) {
138 DCHECK(recently_broken_alternative_services->Peek(pair.first) != 139 DCHECK(recently_broken_alternative_services->Peek(pair.first) !=
139 recently_broken_alternative_services->end()); 140 recently_broken_alternative_services->end());
140 } 141 }
141 142
142 bool added = false; 143 base::TimeTicks next_expiration =
144 broken_alternative_service_list_.empty()
145 ? base::TimeTicks::Max()
146 : broken_alternative_service_list_.front().second;
147
148 // Add recently broken alt svcs to |recently_broken_alternative_services_|.
149 // If an alt-svc already exists, update its broken-count to the one provided
150 // in |recently_broken_alternative_services|.
143 151
144 recently_broken_alternative_services_.Swap( 152 recently_broken_alternative_services_.Swap(
145 *recently_broken_alternative_services); 153 *recently_broken_alternative_services);
146 // Add back all existing recently broken alt svcs to cache so they're at 154 // Add back all existing recently broken alt svcs to cache so they're at
147 // front of recency list. 155 // front of recency list (MRUCache::Get() does this automatically).
148 for (auto it = recently_broken_alternative_services->rbegin(); 156 for (auto it = recently_broken_alternative_services->rbegin();
149 it != recently_broken_alternative_services->rend(); ++it) { 157 it != recently_broken_alternative_services->rend(); ++it) {
150 if (recently_broken_alternative_services_.Get(it->first) == 158 if (recently_broken_alternative_services_.Get(it->first) ==
151 recently_broken_alternative_services_.end()) { 159 recently_broken_alternative_services_.end()) {
152 recently_broken_alternative_services_.Put(it->first, it->second); 160 recently_broken_alternative_services_.Put(it->first, it->second);
153 added = true;
154 } 161 }
155 } 162 }
156 163
157 // Add broken alt svcs to |broken_alternative_service_map_|. Remove all 164 // Add broken alt svcs to |broken_alternative_service_map_|. If an entry
158 // that already exist in the map. 165 // already exists, delete its corresponding entry in
159 auto it = broken_alternative_service_list->begin(); 166 // |broken_alternative_service_list_| and update its map entry to point to
160 while (it != broken_alternative_service_list->end()) { 167 // its position in |broken_alternative_service_list|.
168 for (auto it = broken_alternative_service_list->begin();
169 it != broken_alternative_service_list->end(); ++it) {
161 const AlternativeService& alternative_service = it->first; 170 const AlternativeService& alternative_service = it->first;
162 if (broken_alternative_service_map_.find(alternative_service) == 171 auto map_it = broken_alternative_service_map_.find(alternative_service);
163 broken_alternative_service_map_.end()) { 172 if (map_it != broken_alternative_service_map_.end()) {
173 broken_alternative_service_list_.erase(map_it->second);
174 map_it->second = it;
175 } else {
164 broken_alternative_service_map_.insert( 176 broken_alternative_service_map_.insert(
165 std::make_pair(alternative_service, it)); 177 std::make_pair(alternative_service, it));
166 ++it;
167 } else {
168 broken_alternative_service_list->erase(it++);
169 } 178 }
170 } 179 }
171 180
172 if (!broken_alternative_service_list->empty())
173 added = true;
174
175 // Merge |broken_alternative_service_list| with 181 // Merge |broken_alternative_service_list| with
176 // |broken_alternative_service_list_|. Both should already be sorted by 182 // |broken_alternative_service_list_|. Both should already be sorted by
177 // expiration time. 183 // expiration time. std::list::merge() will not invalidate any iterators
178 bool schedule_expiration = 184 // of either list, so all iterators in |broken_alternative_service_map_|
179 (!broken_alternative_service_list->empty() && 185 // remain valid.
180 (broken_alternative_service_list_.empty() ||
181 broken_alternative_service_list->front().second <
182 broken_alternative_service_list_.front().second));
183
184 broken_alternative_service_list_.merge( 186 broken_alternative_service_list_.merge(
185 *broken_alternative_service_list, 187 *broken_alternative_service_list,
186 [](const std::pair<AlternativeService, base::TimeTicks>& lhs, 188 [](const std::pair<AlternativeService, base::TimeTicks>& lhs,
187 const std::pair<AlternativeService, base::TimeTicks>& rhs) -> bool { 189 const std::pair<AlternativeService, base::TimeTicks>& rhs) -> bool {
188 return lhs.second < rhs.second; 190 return lhs.second < rhs.second;
189 }); 191 });
190 192
191 if (schedule_expiration) 193 base::TimeTicks new_next_expiration =
192 ScheduleBrokenAlternateProtocolMappingsExpiration(); 194 broken_alternative_service_list_.empty()
195 ? base::TimeTicks::Max()
196 : broken_alternative_service_list_.front().second;
193 197
194 return added; 198 if (new_next_expiration != next_expiration)
199 ScheduleBrokenAlternateProtocolMappingsExpiration(new_next_expiration);
200 }
201
202 const BrokenAlternativeServiceList&
203 BrokenAlternativeServices::broken_alternative_service_list() const {
204 return broken_alternative_service_list_;
205 }
206
207 const RecentlyBrokenAlternativeServices&
208 BrokenAlternativeServices::recently_broken_alternative_services() const {
209 return recently_broken_alternative_services_;
195 } 210 }
196 211
197 bool BrokenAlternativeServices::AddToBrokenAlternativeServiceListAndMap( 212 bool BrokenAlternativeServices::AddToBrokenAlternativeServiceListAndMap(
198 const AlternativeService& alternative_service, 213 const AlternativeService& alternative_service,
199 base::TimeTicks expiration, 214 base::TimeTicks expiration,
200 BrokenAlternativeServiceList::iterator* it) { 215 BrokenAlternativeServiceList::iterator* it) {
201 DCHECK(it); 216 DCHECK(it);
202 217
203 auto map_it = broken_alternative_service_map_.find(alternative_service); 218 auto map_it = broken_alternative_service_map_.find(alternative_service);
204 if (map_it != broken_alternative_service_map_.end()) 219 if (map_it != broken_alternative_service_map_.end())
(...skipping 29 matching lines...) Expand all
234 break; 249 break;
235 } 250 }
236 251
237 delegate_->OnExpireBrokenAlternativeService(it->first); 252 delegate_->OnExpireBrokenAlternativeService(it->first);
238 253
239 broken_alternative_service_map_.erase(it->first); 254 broken_alternative_service_map_.erase(it->first);
240 broken_alternative_service_list_.erase(it); 255 broken_alternative_service_list_.erase(it);
241 } 256 }
242 257
243 if (!broken_alternative_service_list_.empty()) 258 if (!broken_alternative_service_list_.empty())
244 ScheduleBrokenAlternateProtocolMappingsExpiration(); 259 ScheduleBrokenAlternateProtocolMappingsExpiration(
260 broken_alternative_service_list_.front().second);
245 } 261 }
246 262
247 void BrokenAlternativeServices :: 263 void BrokenAlternativeServices ::
248 ScheduleBrokenAlternateProtocolMappingsExpiration() { 264 ScheduleBrokenAlternateProtocolMappingsExpiration(base::TimeTicks when) {
249 DCHECK(!broken_alternative_service_list_.empty()); 265 DCHECK(!broken_alternative_service_list_.empty());
250 base::TimeTicks now = clock_->NowTicks(); 266 base::TimeTicks now = clock_->NowTicks();
251 base::TimeTicks when = broken_alternative_service_list_.front().second;
252 base::TimeDelta delay = when > now ? when - now : base::TimeDelta(); 267 base::TimeDelta delay = when > now ? when - now : base::TimeDelta();
253 expiration_timer_.Stop(); 268 expiration_timer_.Stop();
254 expiration_timer_.Start( 269 expiration_timer_.Start(
255 FROM_HERE, delay, 270 FROM_HERE, delay,
256 base::Bind( 271 base::Bind(
257 &BrokenAlternativeServices ::ExpireBrokenAlternateProtocolMappings, 272 &BrokenAlternativeServices ::ExpireBrokenAlternateProtocolMappings,
258 weak_ptr_factory_.GetWeakPtr())); 273 weak_ptr_factory_.GetWeakPtr()));
259 } 274 }
260 275
261 } // namespace net 276 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698