OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/disk_cache_based_quic_server_info.h" | 5 #include "net/http/disk_cache_based_quic_server_info.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback.h" | 8 #include "base/callback.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
11 #include "net/base/completion_callback.h" | 11 #include "net/base/completion_callback.h" |
12 #include "net/base/io_buffer.h" | 12 #include "net/base/io_buffer.h" |
13 #include "net/base/net_errors.h" | 13 #include "net/base/net_errors.h" |
14 #include "net/http/http_cache.h" | 14 #include "net/http/http_cache.h" |
15 #include "net/http/http_network_session.h" | 15 #include "net/http/http_network_session.h" |
16 #include "net/quic/quic_server_id.h" | 16 #include "net/quic/quic_server_id.h" |
17 | 17 |
18 namespace net { | 18 namespace net { |
19 | 19 |
20 // Histogram for tracking down the state of disk_cache::Entry. | 20 // Histogram that tracks number of times data read/parse/write API calls of |
21 enum DiskCacheEntryState { | 21 // QuicServerInfo to and from disk cache is called. |
22 DISK_CACHE_ENTRY_OPENED = 0, | 22 enum QuicServerInfoAPICall { |
23 DISK_CACHE_ENTRY_CLOSED = 1, | 23 QUIC_SERVER_INFO_START = 0, |
24 DISK_CACHE_ENTRY_NUM_STATES = 2, | 24 QUIC_SERVER_INFO_WAIT_FOR_DATA_READY = 1, |
| 25 QUIC_SERVER_INFO_PARSE = 2, |
| 26 QUIC_SERVER_INFO_WAIT_FOR_DATA_READY_CANCEL = 3, |
| 27 QUIC_SERVER_INFO_READY_TO_PERSIST = 4, |
| 28 QUIC_SERVER_INFO_PERSIST = 5, |
| 29 QUIC_SERVER_INFO_NUM_OF_API_CALLS = 6, |
25 }; | 30 }; |
26 | 31 |
27 void RecordDiskCacheEntryState(DiskCacheEntryState entry_state) { | 32 // Histogram that tracks failure reasons to read/load/write of QuicServerInfo to |
28 UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.EntryState", entry_state, | 33 // and from disk cache. |
29 DISK_CACHE_ENTRY_NUM_STATES); | 34 enum FailureReason { |
| 35 WAIT_FOR_DATA_READY_INVALID_ARGUMENT_FAILURE = 0, |
| 36 GET_BACKEND_FAILURE = 1, |
| 37 OPEN_FAILURE = 2, |
| 38 CREATE_OR_OPEN_FAILURE = 3, |
| 39 PARSE_NO_DATA_FAILURE = 4, |
| 40 PARSE_FAILURE = 5, |
| 41 READ_FAILURE = 6, |
| 42 READY_TO_PERSIST_FAILURE = 7, |
| 43 PERSIST_NO_BACKEND_FAILURE = 8, |
| 44 WRITE_FAILURE = 9, |
| 45 NUM_OF_FAILURES = 10, |
| 46 }; |
| 47 |
| 48 void RecordQuicServerInfoStatus(QuicServerInfoAPICall call) { |
| 49 UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.APICall", call, |
| 50 QUIC_SERVER_INFO_NUM_OF_API_CALLS); |
| 51 } |
| 52 |
| 53 void RecordQuicServerInfoFailure(FailureReason failure) { |
| 54 UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.FailureReason", failure, |
| 55 NUM_OF_FAILURES); |
30 } | 56 } |
31 | 57 |
32 // Some APIs inside disk_cache take a handle that the caller must keep alive | 58 // Some APIs inside disk_cache take a handle that the caller must keep alive |
33 // until the API has finished its asynchronous execution. | 59 // until the API has finished its asynchronous execution. |
34 // | 60 // |
35 // Unfortunately, DiskCacheBasedQuicServerInfo may be deleted before the | 61 // Unfortunately, DiskCacheBasedQuicServerInfo may be deleted before the |
36 // operation completes causing a use-after-free. | 62 // operation completes causing a use-after-free. |
37 // | 63 // |
38 // This data shim struct is meant to provide a location for the disk_cache | 64 // This data shim struct is meant to provide a location for the disk_cache |
39 // APIs to write into even if the originating DiskCacheBasedQuicServerInfo | 65 // APIs to write into even if the originating DiskCacheBasedQuicServerInfo |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
71 weak_factory_(this) { | 97 weak_factory_(this) { |
72 io_callback_ = | 98 io_callback_ = |
73 base::Bind(&DiskCacheBasedQuicServerInfo::OnIOComplete, | 99 base::Bind(&DiskCacheBasedQuicServerInfo::OnIOComplete, |
74 weak_factory_.GetWeakPtr(), | 100 weak_factory_.GetWeakPtr(), |
75 base::Owned(data_shim_)); // Ownership assigned. | 101 base::Owned(data_shim_)); // Ownership assigned. |
76 } | 102 } |
77 | 103 |
78 void DiskCacheBasedQuicServerInfo::Start() { | 104 void DiskCacheBasedQuicServerInfo::Start() { |
79 DCHECK(CalledOnValidThread()); | 105 DCHECK(CalledOnValidThread()); |
80 DCHECK_EQ(GET_BACKEND, state_); | 106 DCHECK_EQ(GET_BACKEND, state_); |
| 107 RecordQuicServerInfoStatus(QUIC_SERVER_INFO_START); |
81 load_start_time_ = base::TimeTicks::Now(); | 108 load_start_time_ = base::TimeTicks::Now(); |
82 DoLoop(OK); | 109 DoLoop(OK); |
83 } | 110 } |
84 | 111 |
85 int DiskCacheBasedQuicServerInfo::WaitForDataReady( | 112 int DiskCacheBasedQuicServerInfo::WaitForDataReady( |
86 const CompletionCallback& callback) { | 113 const CompletionCallback& callback) { |
87 DCHECK(CalledOnValidThread()); | 114 DCHECK(CalledOnValidThread()); |
88 DCHECK_NE(GET_BACKEND, state_); | 115 DCHECK_NE(GET_BACKEND, state_); |
89 | 116 |
| 117 RecordQuicServerInfoStatus(QUIC_SERVER_INFO_WAIT_FOR_DATA_READY); |
90 if (ready_) | 118 if (ready_) |
91 return OK; | 119 return OK; |
92 | 120 |
93 if (!callback.is_null()) { | 121 if (!callback.is_null()) { |
94 // Prevent a new callback for WaitForDataReady overwriting an existing | 122 // Prevent a new callback for WaitForDataReady overwriting an existing |
95 // pending callback (|user_callback_|). | 123 // pending callback (|user_callback_|). |
96 if (!user_callback_.is_null()) | 124 if (!user_callback_.is_null()) { |
| 125 RecordQuicServerInfoFailure(WAIT_FOR_DATA_READY_INVALID_ARGUMENT_FAILURE); |
97 return ERR_INVALID_ARGUMENT; | 126 return ERR_INVALID_ARGUMENT; |
| 127 } |
98 user_callback_ = callback; | 128 user_callback_ = callback; |
99 } | 129 } |
100 | 130 |
101 return ERR_IO_PENDING; | 131 return ERR_IO_PENDING; |
102 } | 132 } |
103 | 133 |
104 void DiskCacheBasedQuicServerInfo::CancelWaitForDataReadyCallback() { | 134 void DiskCacheBasedQuicServerInfo::CancelWaitForDataReadyCallback() { |
105 DCHECK(CalledOnValidThread()); | 135 DCHECK(CalledOnValidThread()); |
106 | 136 |
| 137 RecordQuicServerInfoStatus(QUIC_SERVER_INFO_WAIT_FOR_DATA_READY_CANCEL); |
107 if (!user_callback_.is_null()) | 138 if (!user_callback_.is_null()) |
108 user_callback_.Reset(); | 139 user_callback_.Reset(); |
109 } | 140 } |
110 | 141 |
111 bool DiskCacheBasedQuicServerInfo::IsDataReady() { | 142 bool DiskCacheBasedQuicServerInfo::IsDataReady() { |
112 return ready_; | 143 return ready_; |
113 } | 144 } |
114 | 145 |
115 bool DiskCacheBasedQuicServerInfo::IsReadyToPersist() { | 146 bool DiskCacheBasedQuicServerInfo::IsReadyToPersist() { |
116 // TODO(rtenneti): Handle updates while a write is pending. Change | 147 // TODO(rtenneti): Handle updates while a write is pending. Change |
117 // Persist() to save the data to be written into a temporary buffer | 148 // Persist() to save the data to be written into a temporary buffer |
118 // and then persist that data when we are ready to persist. | 149 // and then persist that data when we are ready to persist. |
119 // | 150 // |
120 // The data can be persisted if it has been loaded from the disk cache | 151 // The data can be persisted if it has been loaded from the disk cache |
121 // and there are no pending writes. | 152 // and there are no pending writes. |
122 return ready_ && new_data_.empty(); | 153 RecordQuicServerInfoStatus(QUIC_SERVER_INFO_READY_TO_PERSIST); |
| 154 if (ready_ && new_data_.empty()) |
| 155 return true; |
| 156 RecordQuicServerInfoFailure(READY_TO_PERSIST_FAILURE); |
| 157 return false; |
123 } | 158 } |
124 | 159 |
125 void DiskCacheBasedQuicServerInfo::Persist() { | 160 void DiskCacheBasedQuicServerInfo::Persist() { |
126 DCHECK(CalledOnValidThread()); | 161 DCHECK(CalledOnValidThread()); |
127 DCHECK_NE(GET_BACKEND, state_); | 162 DCHECK_NE(GET_BACKEND, state_); |
128 | 163 |
129 DCHECK(new_data_.empty()); | 164 DCHECK(new_data_.empty()); |
130 CHECK(ready_); | 165 CHECK(ready_); |
131 DCHECK(user_callback_.is_null()); | 166 DCHECK(user_callback_.is_null()); |
132 new_data_ = Serialize(); | 167 new_data_ = Serialize(); |
133 | 168 |
134 if (!backend_) | 169 RecordQuicServerInfoStatus(QUIC_SERVER_INFO_PERSIST); |
| 170 if (!backend_) { |
| 171 RecordQuicServerInfoFailure(PERSIST_NO_BACKEND_FAILURE); |
135 return; | 172 return; |
| 173 } |
136 | 174 |
137 state_ = CREATE_OR_OPEN; | 175 state_ = CREATE_OR_OPEN; |
138 DoLoop(OK); | 176 DoLoop(OK); |
139 } | 177 } |
140 | 178 |
141 DiskCacheBasedQuicServerInfo::~DiskCacheBasedQuicServerInfo() { | 179 DiskCacheBasedQuicServerInfo::~DiskCacheBasedQuicServerInfo() { |
142 DCHECK(user_callback_.is_null()); | 180 DCHECK(user_callback_.is_null()); |
143 if (entry_) { | 181 if (entry_) |
144 entry_->Close(); | 182 entry_->Close(); |
145 RecordDiskCacheEntryState(DISK_CACHE_ENTRY_CLOSED); | |
146 } | |
147 } | 183 } |
148 | 184 |
149 std::string DiskCacheBasedQuicServerInfo::key() const { | 185 std::string DiskCacheBasedQuicServerInfo::key() const { |
150 return "quicserverinfo:" + server_id_.ToString(); | 186 return "quicserverinfo:" + server_id_.ToString(); |
151 } | 187 } |
152 | 188 |
153 void DiskCacheBasedQuicServerInfo::OnIOComplete(CacheOperationDataShim* unused, | 189 void DiskCacheBasedQuicServerInfo::OnIOComplete(CacheOperationDataShim* unused, |
154 int rv) { | 190 int rv) { |
155 DCHECK_NE(NONE, state_); | 191 DCHECK_NE(NONE, state_); |
156 rv = DoLoop(rv); | 192 rv = DoLoop(rv); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
207 } while (rv != ERR_IO_PENDING && state_ != NONE); | 243 } while (rv != ERR_IO_PENDING && state_ != NONE); |
208 | 244 |
209 return rv; | 245 return rv; |
210 } | 246 } |
211 | 247 |
212 int DiskCacheBasedQuicServerInfo::DoGetBackendComplete(int rv) { | 248 int DiskCacheBasedQuicServerInfo::DoGetBackendComplete(int rv) { |
213 if (rv == OK) { | 249 if (rv == OK) { |
214 backend_ = data_shim_->backend; | 250 backend_ = data_shim_->backend; |
215 state_ = OPEN; | 251 state_ = OPEN; |
216 } else { | 252 } else { |
| 253 RecordQuicServerInfoFailure(GET_BACKEND_FAILURE); |
217 state_ = WAIT_FOR_DATA_READY_DONE; | 254 state_ = WAIT_FOR_DATA_READY_DONE; |
218 } | 255 } |
219 return OK; | 256 return OK; |
220 } | 257 } |
221 | 258 |
222 int DiskCacheBasedQuicServerInfo::DoOpenComplete(int rv) { | 259 int DiskCacheBasedQuicServerInfo::DoOpenComplete(int rv) { |
223 if (rv == OK) { | 260 if (rv == OK) { |
224 entry_ = data_shim_->entry; | 261 entry_ = data_shim_->entry; |
225 state_ = READ; | 262 state_ = READ; |
226 found_entry_ = true; | 263 found_entry_ = true; |
227 RecordDiskCacheEntryState(DISK_CACHE_ENTRY_OPENED); | |
228 } else { | 264 } else { |
| 265 RecordQuicServerInfoFailure(OPEN_FAILURE); |
229 state_ = WAIT_FOR_DATA_READY_DONE; | 266 state_ = WAIT_FOR_DATA_READY_DONE; |
230 } | 267 } |
231 | 268 |
232 return OK; | 269 return OK; |
233 } | 270 } |
234 | 271 |
235 int DiskCacheBasedQuicServerInfo::DoReadComplete(int rv) { | 272 int DiskCacheBasedQuicServerInfo::DoReadComplete(int rv) { |
236 if (rv > 0) | 273 if (rv > 0) |
237 data_.assign(read_buffer_->data(), rv); | 274 data_.assign(read_buffer_->data(), rv); |
| 275 else if (rv < 0) |
| 276 RecordQuicServerInfoFailure(READ_FAILURE); |
238 | 277 |
239 state_ = WAIT_FOR_DATA_READY_DONE; | 278 state_ = WAIT_FOR_DATA_READY_DONE; |
240 return OK; | 279 return OK; |
241 } | 280 } |
242 | 281 |
243 int DiskCacheBasedQuicServerInfo::DoWriteComplete(int rv) { | 282 int DiskCacheBasedQuicServerInfo::DoWriteComplete(int rv) { |
| 283 if (rv < 0) |
| 284 RecordQuicServerInfoFailure(WRITE_FAILURE); |
244 state_ = SET_DONE; | 285 state_ = SET_DONE; |
245 return OK; | 286 return OK; |
246 } | 287 } |
247 | 288 |
248 int DiskCacheBasedQuicServerInfo::DoCreateOrOpenComplete(int rv) { | 289 int DiskCacheBasedQuicServerInfo::DoCreateOrOpenComplete(int rv) { |
249 if (rv != OK) { | 290 if (rv != OK) { |
| 291 RecordQuicServerInfoFailure(CREATE_OR_OPEN_FAILURE); |
250 state_ = SET_DONE; | 292 state_ = SET_DONE; |
251 } else { | 293 } else { |
252 if (!entry_) { | 294 if (!entry_) { |
253 entry_ = data_shim_->entry; | 295 entry_ = data_shim_->entry; |
254 found_entry_ = true; | 296 found_entry_ = true; |
255 RecordDiskCacheEntryState(DISK_CACHE_ENTRY_OPENED); | |
256 } | 297 } |
257 DCHECK(entry_); | 298 DCHECK(entry_); |
258 state_ = WRITE; | 299 state_ = WRITE; |
259 } | 300 } |
260 return OK; | 301 return OK; |
261 } | 302 } |
262 | 303 |
263 int DiskCacheBasedQuicServerInfo::DoGetBackend() { | 304 int DiskCacheBasedQuicServerInfo::DoGetBackend() { |
264 state_ = GET_BACKEND_COMPLETE; | 305 state_ = GET_BACKEND_COMPLETE; |
265 return http_cache_->GetBackend(&data_shim_->backend, io_callback_); | 306 return http_cache_->GetBackend(&data_shim_->backend, io_callback_); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
307 | 348 |
308 return backend_->CreateEntry(key(), &data_shim_->entry, io_callback_); | 349 return backend_->CreateEntry(key(), &data_shim_->entry, io_callback_); |
309 } | 350 } |
310 | 351 |
311 int DiskCacheBasedQuicServerInfo::DoWaitForDataReadyDone() { | 352 int DiskCacheBasedQuicServerInfo::DoWaitForDataReadyDone() { |
312 DCHECK(!ready_); | 353 DCHECK(!ready_); |
313 state_ = NONE; | 354 state_ = NONE; |
314 ready_ = true; | 355 ready_ = true; |
315 // We close the entry because, if we shutdown before ::Persist is called, | 356 // We close the entry because, if we shutdown before ::Persist is called, |
316 // then we might leak a cache reference, which causes a DCHECK on shutdown. | 357 // then we might leak a cache reference, which causes a DCHECK on shutdown. |
317 if (entry_) { | 358 if (entry_) |
318 entry_->Close(); | 359 entry_->Close(); |
319 RecordDiskCacheEntryState(DISK_CACHE_ENTRY_CLOSED); | 360 entry_ = NULL; |
| 361 |
| 362 RecordQuicServerInfoStatus(QUIC_SERVER_INFO_PARSE); |
| 363 if (!Parse(data_)) { |
| 364 if (data_.empty()) |
| 365 RecordQuicServerInfoFailure(PARSE_NO_DATA_FAILURE); |
| 366 else |
| 367 RecordQuicServerInfoFailure(PARSE_FAILURE); |
320 } | 368 } |
321 entry_ = NULL; | 369 |
322 Parse(data_); | |
323 UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheLoadTime", | 370 UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheLoadTime", |
324 base::TimeTicks::Now() - load_start_time_); | 371 base::TimeTicks::Now() - load_start_time_); |
325 return OK; | 372 return OK; |
326 } | 373 } |
327 | 374 |
328 int DiskCacheBasedQuicServerInfo::DoSetDone() { | 375 int DiskCacheBasedQuicServerInfo::DoSetDone() { |
329 if (entry_) { | 376 if (entry_) |
330 entry_->Close(); | 377 entry_->Close(); |
331 RecordDiskCacheEntryState(DISK_CACHE_ENTRY_CLOSED); | |
332 } | |
333 entry_ = NULL; | 378 entry_ = NULL; |
334 new_data_.clear(); | 379 new_data_.clear(); |
335 state_ = NONE; | 380 state_ = NONE; |
336 return OK; | 381 return OK; |
337 } | 382 } |
338 | 383 |
339 } // namespace net | 384 } // namespace net |
OLD | NEW |