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

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

Issue 723343002: Update from https://crrev.com/304121 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 6 years, 1 month 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 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/callback_helpers.h"
9 #include "base/logging.h" 10 #include "base/logging.h"
10 #include "base/metrics/histogram.h" 11 #include "base/metrics/histogram.h"
11 #include "net/base/completion_callback.h" 12 #include "net/base/completion_callback.h"
12 #include "net/base/io_buffer.h" 13 #include "net/base/io_buffer.h"
13 #include "net/base/net_errors.h" 14 #include "net/base/net_errors.h"
14 #include "net/http/http_cache.h" 15 #include "net/http/http_cache.h"
15 #include "net/http/http_network_session.h" 16 #include "net/http/http_network_session.h"
16 #include "net/quic/quic_server_id.h" 17 #include "net/quic/quic_server_id.h"
17 18
18 namespace net { 19 namespace net {
19 20
20 // Histogram that tracks number of times data read/parse/write API calls of
21 // QuicServerInfo to and from disk cache is called.
22 enum QuicServerInfoAPICall {
23 QUIC_SERVER_INFO_START = 0,
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,
30 };
31
32 // Histogram that tracks failure reasons to read/load/write of QuicServerInfo to
33 // and from disk cache.
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);
56 }
57
58 // Some APIs inside disk_cache take a handle that the caller must keep alive 21 // Some APIs inside disk_cache take a handle that the caller must keep alive
59 // until the API has finished its asynchronous execution. 22 // until the API has finished its asynchronous execution.
60 // 23 //
61 // Unfortunately, DiskCacheBasedQuicServerInfo may be deleted before the 24 // Unfortunately, DiskCacheBasedQuicServerInfo may be deleted before the
62 // operation completes causing a use-after-free. 25 // operation completes causing a use-after-free.
63 // 26 //
64 // This data shim struct is meant to provide a location for the disk_cache 27 // This data shim struct is meant to provide a location for the disk_cache
65 // APIs to write into even if the originating DiskCacheBasedQuicServerInfo 28 // APIs to write into even if the originating DiskCacheBasedQuicServerInfo
66 // object has been deleted. The lifetime for instances of this struct 29 // object has been deleted. The lifetime for instances of this struct
67 // should be bound to the CompletionCallback that is passed to the disk_cache 30 // should be bound to the CompletionCallback that is passed to the disk_cache
(...skipping 19 matching lines...) Expand all
87 HttpCache* http_cache) 50 HttpCache* http_cache)
88 : QuicServerInfo(server_id), 51 : QuicServerInfo(server_id),
89 data_shim_(new CacheOperationDataShim()), 52 data_shim_(new CacheOperationDataShim()),
90 state_(GET_BACKEND), 53 state_(GET_BACKEND),
91 ready_(false), 54 ready_(false),
92 found_entry_(false), 55 found_entry_(false),
93 server_id_(server_id), 56 server_id_(server_id),
94 http_cache_(http_cache), 57 http_cache_(http_cache),
95 backend_(NULL), 58 backend_(NULL),
96 entry_(NULL), 59 entry_(NULL),
60 last_failure_(NO_FAILURE),
97 weak_factory_(this) { 61 weak_factory_(this) {
98 io_callback_ = 62 io_callback_ =
99 base::Bind(&DiskCacheBasedQuicServerInfo::OnIOComplete, 63 base::Bind(&DiskCacheBasedQuicServerInfo::OnIOComplete,
100 weak_factory_.GetWeakPtr(), 64 weak_factory_.GetWeakPtr(),
101 base::Owned(data_shim_)); // Ownership assigned. 65 base::Owned(data_shim_)); // Ownership assigned.
102 } 66 }
103 67
104 void DiskCacheBasedQuicServerInfo::Start() { 68 void DiskCacheBasedQuicServerInfo::Start() {
105 DCHECK(CalledOnValidThread()); 69 DCHECK(CalledOnValidThread());
106 DCHECK_EQ(GET_BACKEND, state_); 70 DCHECK_EQ(GET_BACKEND, state_);
71 DCHECK_EQ(last_failure_, NO_FAILURE);
107 RecordQuicServerInfoStatus(QUIC_SERVER_INFO_START); 72 RecordQuicServerInfoStatus(QUIC_SERVER_INFO_START);
108 load_start_time_ = base::TimeTicks::Now(); 73 load_start_time_ = base::TimeTicks::Now();
109 DoLoop(OK); 74 DoLoop(OK);
110 } 75 }
111 76
112 int DiskCacheBasedQuicServerInfo::WaitForDataReady( 77 int DiskCacheBasedQuicServerInfo::WaitForDataReady(
113 const CompletionCallback& callback) { 78 const CompletionCallback& callback) {
114 DCHECK(CalledOnValidThread()); 79 DCHECK(CalledOnValidThread());
115 DCHECK_NE(GET_BACKEND, state_); 80 DCHECK_NE(GET_BACKEND, state_);
116 81
117 RecordQuicServerInfoStatus(QUIC_SERVER_INFO_WAIT_FOR_DATA_READY); 82 RecordQuicServerInfoStatus(QUIC_SERVER_INFO_WAIT_FOR_DATA_READY);
118 if (ready_) 83 if (ready_) {
84 RecordLastFailure();
119 return OK; 85 return OK;
86 }
120 87
121 if (!callback.is_null()) { 88 if (!callback.is_null()) {
122 // Prevent a new callback for WaitForDataReady overwriting an existing 89 // Prevent a new callback for WaitForDataReady overwriting an existing
123 // pending callback (|user_callback_|). 90 // pending callback (|wait_for_ready_callback_|).
124 if (!user_callback_.is_null()) { 91 if (!wait_for_ready_callback_.is_null()) {
125 RecordQuicServerInfoFailure(WAIT_FOR_DATA_READY_INVALID_ARGUMENT_FAILURE); 92 RecordQuicServerInfoFailure(WAIT_FOR_DATA_READY_INVALID_ARGUMENT_FAILURE);
126 return ERR_INVALID_ARGUMENT; 93 return ERR_INVALID_ARGUMENT;
127 } 94 }
128 user_callback_ = callback; 95 wait_for_ready_callback_ = callback;
129 } 96 }
130 97
131 return ERR_IO_PENDING; 98 return ERR_IO_PENDING;
132 } 99 }
133 100
134 void DiskCacheBasedQuicServerInfo::CancelWaitForDataReadyCallback() { 101 void DiskCacheBasedQuicServerInfo::CancelWaitForDataReadyCallback() {
135 DCHECK(CalledOnValidThread()); 102 DCHECK(CalledOnValidThread());
136 103
137 RecordQuicServerInfoStatus(QUIC_SERVER_INFO_WAIT_FOR_DATA_READY_CANCEL); 104 RecordQuicServerInfoStatus(QUIC_SERVER_INFO_WAIT_FOR_DATA_READY_CANCEL);
138 if (!user_callback_.is_null()) 105 if (!wait_for_ready_callback_.is_null()) {
139 user_callback_.Reset(); 106 RecordLastFailure();
107 wait_for_ready_callback_.Reset();
108 }
140 } 109 }
141 110
142 bool DiskCacheBasedQuicServerInfo::IsDataReady() { 111 bool DiskCacheBasedQuicServerInfo::IsDataReady() {
143 return ready_; 112 return ready_;
144 } 113 }
145 114
146 bool DiskCacheBasedQuicServerInfo::IsReadyToPersist() { 115 bool DiskCacheBasedQuicServerInfo::IsReadyToPersist() {
147 // TODO(rtenneti): Handle updates while a write is pending. Change
148 // Persist() to save the data to be written into a temporary buffer
149 // and then persist that data when we are ready to persist.
150 //
151 // The data can be persisted if it has been loaded from the disk cache 116 // The data can be persisted if it has been loaded from the disk cache
152 // and there are no pending writes. 117 // and there are no pending writes.
153 RecordQuicServerInfoStatus(QUIC_SERVER_INFO_READY_TO_PERSIST); 118 RecordQuicServerInfoStatus(QUIC_SERVER_INFO_READY_TO_PERSIST);
154 if (ready_ && new_data_.empty()) 119 if (ready_ && new_data_.empty())
155 return true; 120 return true;
156 RecordQuicServerInfoFailure(READY_TO_PERSIST_FAILURE); 121 RecordQuicServerInfoFailure(READY_TO_PERSIST_FAILURE);
157 return false; 122 return false;
158 } 123 }
159 124
160 void DiskCacheBasedQuicServerInfo::Persist() { 125 void DiskCacheBasedQuicServerInfo::Persist() {
161 DCHECK(CalledOnValidThread()); 126 DCHECK(CalledOnValidThread());
127 if (!IsReadyToPersist()) {
128 // Handle updates while a write is pending or if we haven't loaded from disk
129 // cache. Save the data to be written into a temporary buffer and then
130 // persist that data when we are ready to persist.
131 pending_write_data_ = Serialize();
132 return;
133 }
134 PersistInternal();
135 }
136
137 void DiskCacheBasedQuicServerInfo::PersistInternal() {
138 DCHECK(CalledOnValidThread());
162 DCHECK_NE(GET_BACKEND, state_); 139 DCHECK_NE(GET_BACKEND, state_);
163
164 DCHECK(new_data_.empty()); 140 DCHECK(new_data_.empty());
165 CHECK(ready_); 141 CHECK(ready_);
166 DCHECK(user_callback_.is_null()); 142 DCHECK(wait_for_ready_callback_.is_null());
167 new_data_ = Serialize(); 143
144 if (pending_write_data_.empty()) {
145 new_data_ = Serialize();
146 } else {
147 new_data_ = pending_write_data_;
148 pending_write_data_.clear();
149 }
168 150
169 RecordQuicServerInfoStatus(QUIC_SERVER_INFO_PERSIST); 151 RecordQuicServerInfoStatus(QUIC_SERVER_INFO_PERSIST);
170 if (!backend_) { 152 if (!backend_) {
171 RecordQuicServerInfoFailure(PERSIST_NO_BACKEND_FAILURE); 153 RecordQuicServerInfoFailure(PERSIST_NO_BACKEND_FAILURE);
172 return; 154 return;
173 } 155 }
174 156
175 state_ = CREATE_OR_OPEN; 157 state_ = CREATE_OR_OPEN;
176 DoLoop(OK); 158 DoLoop(OK);
177 } 159 }
178 160
161 void DiskCacheBasedQuicServerInfo::OnExternalCacheHit() {
162 DCHECK(CalledOnValidThread());
163 DCHECK_NE(GET_BACKEND, state_);
164
165 RecordQuicServerInfoStatus(QUIC_SERVER_INFO_EXTERNAL_CACHE_HIT);
166 if (!backend_) {
167 RecordQuicServerInfoFailure(PERSIST_NO_BACKEND_FAILURE);
168 return;
169 }
170
171 backend_->OnExternalCacheHit(key());
172 }
173
179 DiskCacheBasedQuicServerInfo::~DiskCacheBasedQuicServerInfo() { 174 DiskCacheBasedQuicServerInfo::~DiskCacheBasedQuicServerInfo() {
180 DCHECK(user_callback_.is_null()); 175 DCHECK(wait_for_ready_callback_.is_null());
181 if (entry_) 176 if (entry_)
182 entry_->Close(); 177 entry_->Close();
183 } 178 }
184 179
185 std::string DiskCacheBasedQuicServerInfo::key() const { 180 std::string DiskCacheBasedQuicServerInfo::key() const {
186 return "quicserverinfo:" + server_id_.ToString(); 181 return "quicserverinfo:" + server_id_.ToString();
187 } 182 }
188 183
189 void DiskCacheBasedQuicServerInfo::OnIOComplete(CacheOperationDataShim* unused, 184 void DiskCacheBasedQuicServerInfo::OnIOComplete(CacheOperationDataShim* unused,
190 int rv) { 185 int rv) {
191 DCHECK_NE(NONE, state_); 186 DCHECK_NE(NONE, state_);
192 rv = DoLoop(rv); 187 rv = DoLoop(rv);
193 if (rv != ERR_IO_PENDING && !user_callback_.is_null()) { 188 if (rv == ERR_IO_PENDING)
194 CompletionCallback callback = user_callback_; 189 return;
195 user_callback_.Reset(); 190 if (!wait_for_ready_callback_.is_null()) {
196 callback.Run(rv); 191 RecordLastFailure();
192 base::ResetAndReturn(&wait_for_ready_callback_).Run(rv);
193 }
194 if (ready_ && !pending_write_data_.empty()) {
195 DCHECK_EQ(NONE, state_);
196 PersistInternal();
197 } 197 }
198 } 198 }
199 199
200 int DiskCacheBasedQuicServerInfo::DoLoop(int rv) { 200 int DiskCacheBasedQuicServerInfo::DoLoop(int rv) {
201 do { 201 do {
202 switch (state_) { 202 switch (state_) {
203 case GET_BACKEND: 203 case GET_BACKEND:
204 rv = DoGetBackend(); 204 rv = DoGetBackend();
205 break; 205 break;
206 case GET_BACKEND_COMPLETE: 206 case GET_BACKEND_COMPLETE:
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
374 374
375 int DiskCacheBasedQuicServerInfo::DoSetDone() { 375 int DiskCacheBasedQuicServerInfo::DoSetDone() {
376 if (entry_) 376 if (entry_)
377 entry_->Close(); 377 entry_->Close();
378 entry_ = NULL; 378 entry_ = NULL;
379 new_data_.clear(); 379 new_data_.clear();
380 state_ = NONE; 380 state_ = NONE;
381 return OK; 381 return OK;
382 } 382 }
383 383
384 void DiskCacheBasedQuicServerInfo::RecordQuicServerInfoStatus(
385 QuicServerInfoAPICall call) {
386 if (!backend_) {
387 UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.APICall.NoBackend", call,
388 QUIC_SERVER_INFO_NUM_OF_API_CALLS);
389 } else if (backend_->GetCacheType() == net::MEMORY_CACHE) {
390 UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.APICall.MemoryCache", call,
391 QUIC_SERVER_INFO_NUM_OF_API_CALLS);
392 } else {
393 UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.APICall.DiskCache", call,
394 QUIC_SERVER_INFO_NUM_OF_API_CALLS);
395 }
396 }
397
398 void DiskCacheBasedQuicServerInfo::RecordLastFailure() {
399 if (last_failure_ != NO_FAILURE) {
400 UMA_HISTOGRAM_ENUMERATION(
401 "Net.QuicDiskCache.FailureReason.WaitForDataReady",
402 last_failure_, NUM_OF_FAILURES);
403 }
404 last_failure_ = NO_FAILURE;
405 }
406
407 void DiskCacheBasedQuicServerInfo::RecordQuicServerInfoFailure(
408 FailureReason failure) {
409 last_failure_ = failure;
410
411 if (!backend_) {
412 UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.FailureReason.NoBackend",
413 failure, NUM_OF_FAILURES);
414 } else if (backend_->GetCacheType() == net::MEMORY_CACHE) {
415 UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.FailureReason.MemoryCache",
416 failure, NUM_OF_FAILURES);
417 } else {
418 UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.FailureReason.DiskCache",
419 failure, NUM_OF_FAILURES);
420 }
421 }
422
384 } // namespace net 423 } // namespace net
OLDNEW
« no previous file with comments | « net/http/disk_cache_based_quic_server_info.h ('k') | net/http/disk_cache_based_quic_server_info_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698