| 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 |