Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 107 broken_alternative_service_list_.erase(map_it->second); | 107 broken_alternative_service_list_.erase(map_it->second); |
| 108 broken_alternative_service_map_.erase(map_it); | 108 broken_alternative_service_map_.erase(map_it); |
| 109 } | 109 } |
| 110 | 110 |
| 111 auto it = recently_broken_alternative_services_.Get(alternative_service); | 111 auto it = recently_broken_alternative_services_.Get(alternative_service); |
| 112 if (it != recently_broken_alternative_services_.end()) { | 112 if (it != recently_broken_alternative_services_.end()) { |
| 113 recently_broken_alternative_services_.Erase(it); | 113 recently_broken_alternative_services_.Erase(it); |
| 114 } | 114 } |
| 115 } | 115 } |
| 116 | 116 |
| 117 const BrokenAlternativeServiceList& | |
| 118 BrokenAlternativeServices::broken_alternative_service_list() const { | |
| 119 return broken_alternative_service_list_; | |
| 120 } | |
| 121 | |
| 122 const RecentlyBrokenAlternativeServices& | |
| 123 BrokenAlternativeServices::recently_broken_alternative_services() const { | |
| 124 return recently_broken_alternative_services_; | |
| 125 } | |
| 126 | |
| 127 void BrokenAlternativeServices::SetBrokenAndRecentlyBrokenAlternativeServices( | |
| 128 std::unique_ptr<BrokenAlternativeServiceList> | |
| 129 broken_alternative_service_list, | |
| 130 std::unique_ptr<RecentlyBrokenAlternativeServices> | |
| 131 recently_broken_alternative_services) { | |
| 132 DCHECK(broken_alternative_service_list); | |
| 133 DCHECK(recently_broken_alternative_services); | |
| 134 | |
| 135 // Make sure all alt svcs in |broken_alternative_service_list| has an entry | |
| 136 // in |recently_broken_alternative_services| | |
| 137 for (const auto& pair : *broken_alternative_service_list) { | |
| 138 DCHECK(recently_broken_alternative_services->Peek(pair.first) != | |
| 139 recently_broken_alternative_services->end()); | |
| 140 } | |
| 141 | |
| 142 base::TimeTicks next_expiration = | |
| 143 broken_alternative_service_list_.empty() | |
| 144 ? base::TimeTicks::Max() | |
| 145 : broken_alternative_service_list_.front().second; | |
| 146 | |
| 147 // Add recently broken alt svcs to |recently_broken_alternative_services_|. | |
| 148 // If an alt-svc already exists, update its broken-count to the one provided | |
| 149 // in |recently_broken_alternative_services|. | |
| 150 | |
| 151 recently_broken_alternative_services_.Swap( | |
| 152 *recently_broken_alternative_services); | |
| 153 // Add back all existing recently broken alt svcs to cache so they're at | |
| 154 // front of recency list (MRUCache::Get() does this automatically). | |
| 155 for (auto it = recently_broken_alternative_services->rbegin(); | |
| 156 it != recently_broken_alternative_services->rend(); ++it) { | |
| 157 if (recently_broken_alternative_services_.Get(it->first) == | |
| 158 recently_broken_alternative_services_.end()) { | |
| 159 recently_broken_alternative_services_.Put(it->first, it->second); | |
| 160 } | |
| 161 } | |
| 162 | |
| 163 // Add broken alt svcs to |broken_alternative_service_map_|. If an entry | |
| 164 // already exists, delete its corresponding entry in | |
| 165 // |broken_alternative_service_list_| and update its map entry to point to | |
| 166 // its position in |broken_alternative_service_list|. | |
|
Zhongyi Shi
2017/06/12 23:20:38
This method has no guarantee on when it will be ca
wangyix1
2017/06/13 01:17:46
If some data exists in both cache and disk, I curr
Zhongyi Shi
2017/06/13 21:45:22
Urm, I don't think we could assume before disk loa
Ryan Hamilton
2017/06/19 17:05:35
I think we should be consistent with the behavior
wangyix1
2017/06/19 19:47:35
The other setters in HttpServerPropertiesImpl() al
| |
| 167 for (auto it = broken_alternative_service_list->begin(); | |
| 168 it != broken_alternative_service_list->end(); ++it) { | |
| 169 const AlternativeService& alternative_service = it->first; | |
| 170 auto map_it = broken_alternative_service_map_.find(alternative_service); | |
| 171 if (map_it != broken_alternative_service_map_.end()) { | |
| 172 broken_alternative_service_list_.erase(map_it->second); | |
| 173 map_it->second = it; | |
| 174 } else { | |
| 175 broken_alternative_service_map_.insert( | |
| 176 std::make_pair(alternative_service, it)); | |
| 177 } | |
| 178 } | |
| 179 | |
| 180 // Merge |broken_alternative_service_list| with | |
| 181 // |broken_alternative_service_list_|. Both should already be sorted by | |
| 182 // expiration time. std::list::merge() will not invalidate any iterators | |
| 183 // of either list, so all iterators in |broken_alternative_service_map_| | |
| 184 // remain valid. | |
| 185 broken_alternative_service_list_.merge( | |
| 186 *broken_alternative_service_list, | |
| 187 [](const std::pair<AlternativeService, base::TimeTicks>& lhs, | |
| 188 const std::pair<AlternativeService, base::TimeTicks>& rhs) -> bool { | |
| 189 return lhs.second < rhs.second; | |
| 190 }); | |
| 191 | |
| 192 base::TimeTicks new_next_expiration = | |
| 193 broken_alternative_service_list_.empty() | |
| 194 ? base::TimeTicks::Max() | |
| 195 : broken_alternative_service_list_.front().second; | |
| 196 | |
| 197 if (new_next_expiration != next_expiration) | |
| 198 ScheduleBrokenAlternateProtocolMappingsExpiration(); | |
| 199 } | |
| 200 | |
| 117 bool BrokenAlternativeServices::AddToBrokenAlternativeServiceListAndMap( | 201 bool BrokenAlternativeServices::AddToBrokenAlternativeServiceListAndMap( |
| 118 const AlternativeService& alternative_service, | 202 const AlternativeService& alternative_service, |
| 119 base::TimeTicks expiration, | 203 base::TimeTicks expiration, |
| 120 BrokenAlternativeServiceList::iterator* it) { | 204 BrokenAlternativeServiceList::iterator* it) { |
| 121 DCHECK(it); | 205 DCHECK(it); |
| 122 | 206 |
| 123 auto map_it = broken_alternative_service_map_.find(alternative_service); | 207 auto map_it = broken_alternative_service_map_.find(alternative_service); |
| 124 if (map_it != broken_alternative_service_map_.end()) | 208 if (map_it != broken_alternative_service_map_.end()) |
| 125 return false; | 209 return false; |
| 126 | 210 |
| 127 // Iterate from end of |broken_alternative_service_list_| to find where to | 211 // Iterate from end of |broken_alternative_service_list_| to find where to |
| 128 // insert it to keep the list sorted by expiration time. | 212 // insert it to keep the list sorted by expiration time. |
| 129 auto list_it = broken_alternative_service_list_.end(); | 213 auto list_it = broken_alternative_service_list_.end(); |
| 130 while (list_it != broken_alternative_service_list_.begin()) { | 214 while (list_it != broken_alternative_service_list_.begin()) { |
| 131 --list_it; | 215 --list_it; |
| 132 if (list_it->expiration <= expiration) { | 216 if (list_it->second <= expiration) { |
| 133 ++list_it; | 217 ++list_it; |
| 134 break; | 218 break; |
| 135 } | 219 } |
| 136 } | 220 } |
| 137 | 221 |
| 138 // Insert |alternative_service| into the list and the map | 222 // Insert |alternative_service| into the list and the map |
| 139 list_it = broken_alternative_service_list_.insert( | 223 list_it = broken_alternative_service_list_.insert( |
| 140 list_it, BrokenAltSvcExpireInfo(alternative_service, expiration)); | 224 list_it, std::make_pair(alternative_service, expiration)); |
| 141 broken_alternative_service_map_.insert( | 225 broken_alternative_service_map_.insert( |
| 142 std::make_pair(alternative_service, list_it)); | 226 std::make_pair(alternative_service, list_it)); |
| 143 | 227 |
| 144 *it = list_it; | 228 *it = list_it; |
| 145 return true; | 229 return true; |
| 146 } | 230 } |
| 147 | 231 |
| 148 void BrokenAlternativeServices::ExpireBrokenAlternateProtocolMappings() { | 232 void BrokenAlternativeServices::ExpireBrokenAlternateProtocolMappings() { |
| 149 base::TimeTicks now = clock_->NowTicks(); | 233 base::TimeTicks now = clock_->NowTicks(); |
| 150 | 234 |
| 151 while (!broken_alternative_service_list_.empty()) { | 235 while (!broken_alternative_service_list_.empty()) { |
| 152 auto it = broken_alternative_service_list_.begin(); | 236 auto it = broken_alternative_service_list_.begin(); |
| 153 if (now < it->expiration) { | 237 if (now < it->second) { |
| 154 break; | 238 break; |
| 155 } | 239 } |
| 156 | 240 |
| 157 delegate_->OnExpireBrokenAlternativeService(it->alternative_service); | 241 delegate_->OnExpireBrokenAlternativeService(it->first); |
| 158 | 242 |
| 159 broken_alternative_service_map_.erase(it->alternative_service); | 243 broken_alternative_service_map_.erase(it->first); |
| 160 broken_alternative_service_list_.erase(it); | 244 broken_alternative_service_list_.erase(it); |
| 161 } | 245 } |
| 162 | 246 |
| 163 if (!broken_alternative_service_list_.empty()) | 247 if (!broken_alternative_service_list_.empty()) |
| 164 ScheduleBrokenAlternateProtocolMappingsExpiration(); | 248 ScheduleBrokenAlternateProtocolMappingsExpiration(); |
| 165 } | 249 } |
| 166 | 250 |
| 167 void BrokenAlternativeServices :: | 251 void BrokenAlternativeServices :: |
| 168 ScheduleBrokenAlternateProtocolMappingsExpiration() { | 252 ScheduleBrokenAlternateProtocolMappingsExpiration() { |
| 169 DCHECK(!broken_alternative_service_list_.empty()); | 253 DCHECK(!broken_alternative_service_list_.empty()); |
| 170 base::TimeTicks now = clock_->NowTicks(); | 254 base::TimeTicks now = clock_->NowTicks(); |
| 171 base::TimeTicks when = broken_alternative_service_list_.front().expiration; | 255 base::TimeTicks when = broken_alternative_service_list_.front().second; |
| 172 base::TimeDelta delay = when > now ? when - now : base::TimeDelta(); | 256 base::TimeDelta delay = when > now ? when - now : base::TimeDelta(); |
| 173 expiration_timer_.Stop(); | 257 expiration_timer_.Stop(); |
| 174 expiration_timer_.Start( | 258 expiration_timer_.Start( |
| 175 FROM_HERE, delay, | 259 FROM_HERE, delay, |
| 176 base::Bind( | 260 base::Bind( |
| 177 &BrokenAlternativeServices ::ExpireBrokenAlternateProtocolMappings, | 261 &BrokenAlternativeServices ::ExpireBrokenAlternateProtocolMappings, |
| 178 weak_ptr_factory_.GetWeakPtr())); | 262 weak_ptr_factory_.GetWeakPtr())); |
| 179 } | 263 } |
| 180 | 264 |
| 181 } // namespace net | 265 } // namespace net |
| OLD | NEW |