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

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

Issue 2519473002: Fixes the cache lock issue. (Closed)
Patch Set: Feedback addressed Created 3 years, 10 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
« no previous file with comments | « net/http/http_cache_transaction.h ('k') | net/http/http_cache_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/http_cache_transaction.h" 5 #include "net/http/http_cache_transaction.h"
6 6
7 #include "build/build_config.h" // For OS_POSIX 7 #include "build/build_config.h" // For OS_POSIX
8 8
9 #if defined(OS_POSIX) 9 #if defined(OS_POSIX)
10 #include <unistd.h> 10 #include <unistd.h>
11 #endif 11 #endif
12 12
13 #include <algorithm> 13 #include <algorithm>
14 #include <limits>
14 #include <string> 15 #include <string>
16 #include <utility>
15 17
16 #include "base/bind.h" 18 #include "base/bind.h"
17 #include "base/callback_helpers.h" 19 #include "base/callback_helpers.h"
18 #include "base/compiler_specific.h" 20 #include "base/compiler_specific.h"
19 #include "base/format_macros.h" 21 #include "base/format_macros.h"
20 #include "base/location.h" 22 #include "base/location.h"
21 #include "base/macros.h" 23 #include "base/macros.h"
22 #include "base/metrics/histogram_macros.h" 24 #include "base/metrics/histogram_macros.h"
23 #include "base/metrics/sparse_histogram.h" 25 #include "base/metrics/sparse_histogram.h"
24 #include "base/single_thread_task_runner.h" 26 #include "base/single_thread_task_runner.h"
25 #include "base/strings/string_number_conversions.h" // For HexEncode. 27 #include "base/strings/string_number_conversions.h" // For HexEncode.
26 #include "base/strings/string_piece.h" 28 #include "base/strings/string_piece.h"
27 #include "base/strings/string_util.h" // For LowerCaseEqualsASCII. 29 #include "base/strings/string_util.h" // For LowerCaseEqualsASCII.
28 #include "base/strings/stringprintf.h" 30 #include "base/strings/stringprintf.h"
29 #include "base/threading/thread_task_runner_handle.h" 31 #include "base/threading/thread_task_runner_handle.h"
30 #include "base/time/clock.h" 32 #include "base/time/clock.h"
31 #include "base/trace_event/trace_event.h" 33 #include "base/trace_event/trace_event.h"
32 #include "base/values.h" 34 #include "base/values.h"
33 #include "net/base/auth.h" 35 #include "net/base/auth.h"
34 #include "net/base/load_flags.h" 36 #include "net/base/load_flags.h"
35 #include "net/base/load_timing_info.h" 37 #include "net/base/load_timing_info.h"
36 #include "net/base/trace_constants.h" 38 #include "net/base/trace_constants.h"
37 #include "net/base/upload_data_stream.h" 39 #include "net/base/upload_data_stream.h"
38 #include "net/cert/cert_status_flags.h" 40 #include "net/cert/cert_status_flags.h"
39 #include "net/cert/x509_certificate.h" 41 #include "net/cert/x509_certificate.h"
40 #include "net/disk_cache/disk_cache.h" 42 #include "net/disk_cache/disk_cache.h"
43 #include "net/http/http_cache_shared_writers.h"
41 #include "net/http/http_network_session.h" 44 #include "net/http/http_network_session.h"
42 #include "net/http/http_request_info.h" 45 #include "net/http/http_request_info.h"
43 #include "net/http/http_util.h" 46 #include "net/http/http_util.h"
44 #include "net/log/net_log_event_type.h" 47 #include "net/log/net_log_event_type.h"
45 #include "net/ssl/ssl_cert_request_info.h" 48 #include "net/ssl/ssl_cert_request_info.h"
46 #include "net/ssl/ssl_config_service.h" 49 #include "net/ssl/ssl_config_service.h"
47 50
48 using base::Time; 51 using base::Time;
49 using base::TimeDelta; 52 using base::TimeDelta;
50 using base::TimeTicks; 53 using base::TimeTicks;
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 truncated_(false), 177 truncated_(false),
175 is_sparse_(false), 178 is_sparse_(false),
176 range_requested_(false), 179 range_requested_(false),
177 handling_206_(false), 180 handling_206_(false),
178 cache_pending_(false), 181 cache_pending_(false),
179 done_reading_(false), 182 done_reading_(false),
180 vary_mismatch_(false), 183 vary_mismatch_(false),
181 couldnt_conditionalize_request_(false), 184 couldnt_conditionalize_request_(false),
182 bypass_lock_for_test_(false), 185 bypass_lock_for_test_(false),
183 fail_conditionalization_for_test_(false), 186 fail_conditionalization_for_test_(false),
187 shared_(false),
188 initiate_shared_writing_(false),
189 shared_read_write_failure_result_(0),
184 io_buf_len_(0), 190 io_buf_len_(0),
185 read_offset_(0), 191 read_offset_(0),
186 effective_load_flags_(0), 192 effective_load_flags_(0),
187 write_len_(0), 193 write_len_(0),
188 cache_entry_status_(CacheEntryStatus::ENTRY_UNDEFINED), 194 cache_entry_status_(CacheEntryStatus::ENTRY_UNDEFINED),
189 validation_cause_(VALIDATION_CAUSE_UNDEFINED), 195 validation_cause_(VALIDATION_CAUSE_UNDEFINED),
190 total_received_bytes_(0), 196 total_received_bytes_(0),
191 total_sent_bytes_(0), 197 total_sent_bytes_(0),
192 websocket_handshake_stream_base_create_helper_(NULL), 198 websocket_handshake_stream_base_create_helper_(NULL),
199 have_full_request_headers_(false),
193 weak_factory_(this) { 200 weak_factory_(this) {
194 TRACE_EVENT0("io", "HttpCacheTransaction::Transaction"); 201 TRACE_EVENT0("io", "HttpCacheTransaction::Transaction");
195 static_assert(HttpCache::Transaction::kNumValidationHeaders == 202 static_assert(HttpCache::Transaction::kNumValidationHeaders ==
196 arraysize(kValidationHeaders), 203 arraysize(kValidationHeaders),
197 "invalid number of validation headers"); 204 "invalid number of validation headers");
198 205
199 io_callback_ = base::Bind(&Transaction::OnIOComplete, 206 io_callback_ = base::Bind(&Transaction::OnIOComplete,
200 weak_factory_.GetWeakPtr()); 207 weak_factory_.GetWeakPtr());
201 } 208 }
202 209
203 HttpCache::Transaction::~Transaction() { 210 HttpCache::Transaction::~Transaction() {
204 TRACE_EVENT0("io", "HttpCacheTransaction::~Transaction"); 211 TRACE_EVENT0("io", "HttpCacheTransaction::~Transaction");
212
205 // We may have to issue another IO, but we should never invoke the callback_ 213 // We may have to issue another IO, but we should never invoke the callback_
206 // after this point. 214 // after this point.
207 callback_.Reset(); 215 callback_.Reset();
208 216
217 if (shared_) {
218 // Remove transaction from shared writers and do any cleanup, if needed, for
219 // entry_->shared_writers and entry_.
220 RemoveTransactionFromSharedWriters();
221 }
222
209 if (cache_) { 223 if (cache_) {
210 if (entry_) { 224 if (entry_) {
211 bool cancel_request = reading_ && response_.headers.get(); 225 bool cancel_request = reading_ && response_.headers.get();
212 if (cancel_request) { 226 if (cancel_request) {
213 if (partial_) { 227 if (partial_) {
214 entry_->disk_entry->CancelSparseIO(); 228 entry_->disk_entry->CancelSparseIO();
215 } else { 229 } else {
216 cancel_request &= (response_.headers->response_code() == 200); 230 cancel_request &= (response_.headers->response_code() == 200);
217 } 231 }
218 } 232 }
219
220 cache_->DoneWithEntry(entry_, this, cancel_request); 233 cache_->DoneWithEntry(entry_, this, cancel_request);
221 } else if (cache_pending_) { 234 } else if (cache_pending_) {
222 cache_->RemovePendingTransaction(this); 235 cache_->RemovePendingTransaction(this);
223 } 236 }
224 } 237 }
225 } 238 }
226 239
240 void HttpCache::Transaction::RemoveTransactionFromSharedWriters() {
241 switch (next_state_) {
242 case STATE_GET_BACKEND_COMPLETE:
243 case STATE_OPEN_ENTRY_COMPLETE:
244 case STATE_DOOM_ENTRY_COMPLETE:
245 case STATE_CREATE_ENTRY_COMPLETE:
246 case STATE_ADD_TO_ENTRY_COMPLETE:
247 // Pending transaction not yet added to an entry, so entry_ is null, let
248 // cache_ handle the deletion.
249 cache_->RemovePendingTransaction(this);
250 // Set cache_pending_ to false so that more cleanup is not attempted in
251 // the destructor.
252 cache_pending_ = false;
253 break;
254 case STATE_CACHE_READ_RESPONSE_COMPLETE:
255 case STATE_TOGGLE_UNUSED_SINCE_PREFETCH_COMPLETE:
256 case STATE_CACHE_QUERY_DATA_COMPLETE:
257 case STATE_COMPLETE_PARTIAL_CACHE_VALIDATION:
258 case STATE_SEND_REQUEST_COMPLETE:
259 case STATE_CACHE_WRITE_UPDATED_RESPONSE_COMPLETE:
260 case STATE_UPDATE_CACHED_RESPONSE_COMPLETE:
261 case STATE_CACHE_WRITE_RESPONSE_COMPLETE:
262 case STATE_TRUNCATE_CACHED_DATA_COMPLETE:
263 case STATE_TRUNCATE_CACHED_METADATA_COMPLETE:
264 case STATE_CACHE_READ_METADATA_COMPLETE:
265 entry_->shared_writers->RemoveValidatingTransaction(this);
266 break;
267 case STATE_SHARED_NETWORK_READ_COMPLETE:
268 case STATE_SHARED_CACHE_WRITE_DATA_COMPLETE:
269 // Current shared network transaction's consumer.
270 entry_->shared_writers->RemoveActiveTransaction(this);
271 break;
272 case STATE_SHARED_NETWORK_READ_WAIT_COMPLETE:
273 // Waiting on Read() operation to be completed by another
274 // transaction.
275 entry_->shared_writers->RemoveWaitingForReadTransaction(this);
276 break;
277 case STATE_CACHE_READ_DATA_COMPLETE:
278 case STATE_NONE:
279 entry_->shared_writers->RemoveIdleTransaction(this);
280 break;
281 default:
282 NOTREACHED() << "bad state";
283 break;
284 }
285
286 DCHECK(!shared_);
287
288 // Since any cleanup needed in entry_ and shared_writers is already done,
289 // set entry_ to null.
290 entry_ = nullptr;
291 }
292
227 int HttpCache::Transaction::WriteMetadata(IOBuffer* buf, int buf_len, 293 int HttpCache::Transaction::WriteMetadata(IOBuffer* buf, int buf_len,
228 const CompletionCallback& callback) { 294 const CompletionCallback& callback) {
229 DCHECK(buf); 295 DCHECK(buf);
230 DCHECK_GT(buf_len, 0); 296 DCHECK_GT(buf_len, 0);
231 DCHECK(!callback.is_null()); 297 DCHECK(!callback.is_null());
232 if (!cache_.get() || !entry_) 298 if (!cache_.get() || !entry_)
233 return ERR_UNEXPECTED; 299 return ERR_UNEXPECTED;
234 300
235 // We don't need to track this operation for anything. 301 // We don't need to track this operation for anything.
236 // It could be possible to check if there is something already written and 302 // It could be possible to check if there is something already written and
237 // avoid writing again (it should be the same, right?), but let's allow the 303 // avoid writing again (it should be the same, right?), but let's allow the
238 // caller to "update" the contents with something new. 304 // caller to "update" the contents with something new.
239 return entry_->disk_entry->WriteData(kMetadataIndex, 0, buf, buf_len, 305 return entry_->disk_entry->WriteData(kMetadataIndex, 0, buf, buf_len,
240 callback, true); 306 callback, true);
241 } 307 }
242 308
243 bool HttpCache::Transaction::AddTruncatedFlag() { 309 bool HttpCache::Transaction::AddTruncatedFlag() {
244 DCHECK(mode_ & WRITE || mode_ == NONE); 310 DCHECK(mode_ & WRITE || mode_ == NONE);
245 311
246 // Don't set the flag for sparse entries. 312 // Don't set the flag for sparse entries.
247 if (partial_ && !truncated_) 313 if (partial_ && !truncated_)
248 return true; 314 return true;
249 315
250 if (!CanResume(true)) 316 if (!cache_->CanResumeEntry(true, request_->method, &response_, entry_))
251 return false; 317 return false;
252 318
253 // We may have received the whole resource already. 319 // We may have received the whole resource already.
254 if (done_reading_) 320 if (done_reading_)
255 return true; 321 return true;
256 322
257 truncated_ = true; 323 truncated_ = true;
258 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE; 324 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE;
259 DoLoop(OK); 325 DoLoop(OK);
260 return true; 326 return true;
261 } 327 }
262 328
263 LoadState HttpCache::Transaction::GetWriterLoadState() const { 329 LoadState HttpCache::Transaction::GetWriterLoadState() const {
264 if (network_trans_.get()) 330 HttpTransaction* network_transaction = GetCurrentNetworkTransaction();
265 return network_trans_->GetLoadState(); 331 if (network_transaction)
332 return network_transaction->GetLoadState();
266 if (entry_ || !request_) 333 if (entry_ || !request_)
267 return LOAD_STATE_IDLE; 334 return LOAD_STATE_IDLE;
268 return LOAD_STATE_WAITING_FOR_CACHE; 335 return LOAD_STATE_WAITING_FOR_CACHE;
269 } 336 }
270 337
271 const NetLogWithSource& HttpCache::Transaction::net_log() const { 338 const NetLogWithSource& HttpCache::Transaction::net_log() const {
272 return net_log_; 339 return net_log_;
273 } 340 }
274 341
275 int HttpCache::Transaction::Start(const HttpRequestInfo* request, 342 int HttpCache::Transaction::Start(const HttpRequestInfo* request,
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 } 432 }
366 433
367 bool HttpCache::Transaction::IsReadyToRestartForAuth() { 434 bool HttpCache::Transaction::IsReadyToRestartForAuth() {
368 if (!network_trans_.get()) 435 if (!network_trans_.get())
369 return false; 436 return false;
370 return network_trans_->IsReadyToRestartForAuth(); 437 return network_trans_->IsReadyToRestartForAuth();
371 } 438 }
372 439
373 int HttpCache::Transaction::Read(IOBuffer* buf, int buf_len, 440 int HttpCache::Transaction::Read(IOBuffer* buf, int buf_len,
374 const CompletionCallback& callback) { 441 const CompletionCallback& callback) {
442 if (next_state_ == STATE_SHARED_READ_WRITE_FAILED) {
443 if (net_log_.IsCapturing())
444 net_log_.EndEventWithNetErrorCode(
445 NetLogEventType::HTTP_CACHE_SHARED_READ_WRITE_FAILED,
446 shared_read_write_failure_result_);
447
448 return shared_read_write_failure_result_;
449 }
450
375 DCHECK_EQ(next_state_, STATE_NONE); 451 DCHECK_EQ(next_state_, STATE_NONE);
376 DCHECK(buf); 452 DCHECK(buf);
377 DCHECK_GT(buf_len, 0); 453 DCHECK_GT(buf_len, 0);
378 DCHECK(!callback.is_null()); 454 DCHECK(!callback.is_null());
379 455
380 DCHECK(callback_.is_null()); 456 DCHECK(callback_.is_null());
381 457
382 if (!cache_.get()) 458 if (!cache_.get())
383 return ERR_UNEXPECTED; 459 return ERR_UNEXPECTED;
384 460
385 // If we have an intermediate auth response at this point, then it means the 461 // If we have an intermediate auth response at this point, then it means the
386 // user wishes to read the network response (the error page). If there is a 462 // user wishes to read the network response (the error page). If there is a
387 // previous response in the cache then we should leave it intact. 463 // previous response in the cache then we should leave it intact.
388 if (auth_response_.headers.get() && mode_ != NONE) { 464 if (auth_response_.headers.get() && mode_ != NONE) {
389 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER); 465 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
390 DCHECK(mode_ & WRITE); 466 DCHECK(mode_ & WRITE);
391 DoneWritingToEntry(mode_ == READ_WRITE); 467 DoneWritingToEntry(mode_ == READ_WRITE);
392 mode_ = NONE; 468 mode_ = NONE;
393 } 469 }
394 470
395 reading_ = true; 471 reading_ = true;
396 read_buf_ = buf; 472 read_buf_ = buf;
397 io_buf_len_ = buf_len; 473 io_buf_len_ = buf_len;
398 if (network_trans_) { 474
399 DCHECK(mode_ == WRITE || mode_ == NONE || 475 if (shared_) {
400 (mode_ == READ_WRITE && partial_)); 476 int disk_entry_size =
401 next_state_ = STATE_NETWORK_READ; 477 entry_->disk_entry->GetDataSize(kResponseContentIndex);
402 } else { 478 if (read_offset_ == disk_entry_size) {
403 DCHECK(mode_ == READ || (mode_ == READ_WRITE && partial_)); 479 next_state_ = STATE_SHARED_NETWORK_READ;
404 next_state_ = STATE_CACHE_READ_DATA; 480 } else {
481 DCHECK_LT(read_offset_, disk_entry_size);
482 next_state_ = STATE_CACHE_READ_DATA;
483 }
484 } else { // not shared.
485 if (network_trans_) {
486 DCHECK(mode_ == WRITE || mode_ == NONE ||
487 (mode_ == READ_WRITE && partial_));
488 next_state_ = STATE_NETWORK_READ;
489 } else { // read-only
490 DCHECK(mode_ == READ || (mode_ == READ_WRITE && partial_));
491 next_state_ = STATE_CACHE_READ_DATA;
492 }
405 } 493 }
406 494
407 int rv = DoLoop(OK); 495 int rv = DoLoop(OK);
408 496
409 if (rv == ERR_IO_PENDING) { 497 if (rv == ERR_IO_PENDING) {
410 DCHECK(callback_.is_null()); 498 DCHECK(callback_.is_null());
411 callback_ = callback; 499 callback_ = callback;
412 } 500 }
413 return rv; 501 return rv;
414 } 502 }
415 503
416 void HttpCache::Transaction::StopCaching() { 504 void HttpCache::Transaction::StopCaching() {
417 // We really don't know where we are now. Hopefully there is no operation in 505 // We really don't know where we are now. Hopefully there is no operation in
418 // progress, but nothing really prevents this method to be called after we 506 // progress, but nothing really prevents this method to be called after we
419 // returned ERR_IO_PENDING. We cannot attempt to truncate the entry at this 507 // returned ERR_IO_PENDING. We cannot attempt to truncate the entry at this
420 // point because we need the state machine for that (and even if we are really 508 // point because we need the state machine for that (and even if we are really
421 // free, that would be an asynchronous operation). In other words, keep the 509 // free, that would be an asynchronous operation). In other words, keep the
422 // entry how it is (it will be marked as truncated at destruction), and let 510 // entry how it is (it will be marked as truncated at destruction), and let
423 // the next piece of code that executes know that we are now reading directly 511 // the next piece of code that executes know that we are now reading directly
424 // from the net. 512 // from the net.
425 // TODO(mmenke): This doesn't release the lock on the cache entry, so a 513 // TODO(mmenke): This doesn't release the lock on the cache entry, so a
426 // future request for the resource will be blocked on this one. 514 // future request for the resource will be blocked on this one.
427 // Fix this. 515 // Fix this.
428 if (cache_.get() && entry_ && (mode_ & WRITE) && network_trans_.get() && 516 if (shared_) {
429 !is_sparse_ && !range_requested_) { 517 // This might or might not stop caching based on whether other consumers
518 // exist for this resource or not. If it does, shared_ will be set to false.
519 entry_->shared_writers->StopCaching(this);
520 }
521 if (!shared_ && cache_.get() && entry_ && (mode_ & WRITE) &&
522 network_trans_.get() && !is_sparse_ && !range_requested_) {
430 mode_ = NONE; 523 mode_ = NONE;
431 } 524 }
432 } 525 }
433 526
434 bool HttpCache::Transaction::GetFullRequestHeaders( 527 bool HttpCache::Transaction::GetFullRequestHeaders(
435 HttpRequestHeaders* headers) const { 528 HttpRequestHeaders* headers) const {
436 if (network_trans_) 529 HttpTransaction* network_transaction = GetCurrentNetworkTransaction();
437 return network_trans_->GetFullRequestHeaders(headers); 530 if (network_transaction) {
438 531 return network_transaction->GetFullRequestHeaders(headers);
532 } else if (have_full_request_headers_) {
533 *headers = full_request_headers_;
534 return true;
535 }
439 // TODO(juliatuttle): Read headers from cache. 536 // TODO(juliatuttle): Read headers from cache.
440 return false; 537 return false;
441 } 538 }
442 539
443 int64_t HttpCache::Transaction::GetTotalReceivedBytes() const { 540 int64_t HttpCache::Transaction::GetTotalReceivedBytes() const {
444 int64_t total_received_bytes = total_received_bytes_; 541 int64_t total_received_bytes = total_received_bytes_;
445 if (network_trans_) 542 HttpTransaction* network_transaction = GetCurrentNetworkTransaction();
446 total_received_bytes += network_trans_->GetTotalReceivedBytes(); 543 if (network_transaction)
544 total_received_bytes += network_transaction->GetTotalReceivedBytes();
447 return total_received_bytes; 545 return total_received_bytes;
448 } 546 }
449 547
450 int64_t HttpCache::Transaction::GetTotalSentBytes() const { 548 int64_t HttpCache::Transaction::GetTotalSentBytes() const {
451 int64_t total_sent_bytes = total_sent_bytes_; 549 int64_t total_sent_bytes = total_sent_bytes_;
452 if (network_trans_) 550 HttpTransaction* network_transaction = GetCurrentNetworkTransaction();
453 total_sent_bytes += network_trans_->GetTotalSentBytes(); 551 if (network_transaction)
552 total_sent_bytes += network_transaction->GetTotalSentBytes();
454 return total_sent_bytes; 553 return total_sent_bytes;
455 } 554 }
456 555
457 void HttpCache::Transaction::DoneReading() { 556 void HttpCache::Transaction::DoneReading() {
458 if (cache_.get() && entry_) { 557 if (cache_.get() && entry_) {
459 DCHECK_NE(mode_, UPDATE); 558 DCHECK_NE(mode_, UPDATE);
559 bool perform_entry_cleanup = true;
560 if (shared_) {
561 entry_->shared_writers->DoneReading(this);
562
563 // shared_ should have been set to false.
564 DCHECK(!shared_);
565
566 DoneWritingToEntry(true, false);
567 return;
568 }
569
460 if (mode_ & WRITE) { 570 if (mode_ & WRITE) {
461 DoneWritingToEntry(true); 571 DoneWritingToEntry(true, perform_entry_cleanup);
462 } else if (mode_ & READ) { 572 } else if (mode_ & READ) {
463 // It is necessary to check mode_ & READ because it is possible 573 // It is necessary to check mode_ & READ because it is possible
464 // for mode_ to be NONE and entry_ non-NULL with a write entry 574 // for mode_ to be NONE and entry_ non-NULL with a write entry
465 // if StopCaching was called. 575 // if StopCaching was called.
466 cache_->DoneReadingFromEntry(entry_, this); 576 cache_->DoneReadingFromEntry(entry_, this);
467 entry_ = NULL; 577 entry_ = NULL;
468 } 578 }
469 } 579 }
470 } 580 }
471 581
(...skipping 18 matching lines...) Expand all
490 return cache_->GetLoadStateForPendingTransaction(this); 600 return cache_->GetLoadStateForPendingTransaction(this);
491 601
492 return LOAD_STATE_IDLE; 602 return LOAD_STATE_IDLE;
493 } 603 }
494 604
495 void HttpCache::Transaction::SetQuicServerInfo( 605 void HttpCache::Transaction::SetQuicServerInfo(
496 QuicServerInfo* quic_server_info) {} 606 QuicServerInfo* quic_server_info) {}
497 607
498 bool HttpCache::Transaction::GetLoadTimingInfo( 608 bool HttpCache::Transaction::GetLoadTimingInfo(
499 LoadTimingInfo* load_timing_info) const { 609 LoadTimingInfo* load_timing_info) const {
500 if (network_trans_) 610 HttpTransaction* network_transaction = GetCurrentNetworkTransaction();
501 return network_trans_->GetLoadTimingInfo(load_timing_info); 611 if (network_transaction)
612 return network_transaction->GetLoadTimingInfo(load_timing_info);
502 613
503 if (old_network_trans_load_timing_) { 614 if (old_network_trans_load_timing_) {
504 *load_timing_info = *old_network_trans_load_timing_; 615 *load_timing_info = *old_network_trans_load_timing_;
505 return true; 616 return true;
506 } 617 }
507 618
508 if (first_cache_access_since_.is_null()) 619 if (first_cache_access_since_.is_null())
509 return false; 620 return false;
510 621
511 // If the cache entry was opened, return that time. 622 // If the cache entry was opened, return that time.
512 load_timing_info->send_start = first_cache_access_since_; 623 load_timing_info->send_start = first_cache_access_since_;
513 // This time doesn't make much sense when reading from the cache, so just use 624 // This time doesn't make much sense when reading from the cache, so just use
514 // the same time as send_start. 625 // the same time as send_start.
515 load_timing_info->send_end = first_cache_access_since_; 626 load_timing_info->send_end = first_cache_access_since_;
516 return true; 627 return true;
517 } 628 }
518 629
519 bool HttpCache::Transaction::GetRemoteEndpoint(IPEndPoint* endpoint) const { 630 bool HttpCache::Transaction::GetRemoteEndpoint(IPEndPoint* endpoint) const {
520 if (network_trans_) 631 HttpTransaction* network_transaction = GetCurrentNetworkTransaction();
521 return network_trans_->GetRemoteEndpoint(endpoint); 632 if (network_transaction)
633 return network_transaction->GetRemoteEndpoint(endpoint);
522 634
523 if (!old_remote_endpoint_.address().empty()) { 635 if (!old_remote_endpoint_.address().empty()) {
524 *endpoint = old_remote_endpoint_; 636 *endpoint = old_remote_endpoint_;
525 return true; 637 return true;
526 } 638 }
527 639
528 return false; 640 return false;
529 } 641 }
530 642
531 void HttpCache::Transaction::PopulateNetErrorDetails( 643 void HttpCache::Transaction::PopulateNetErrorDetails(
532 NetErrorDetails* details) const { 644 NetErrorDetails* details) const {
533 if (network_trans_) 645 HttpTransaction* network_transaction = GetCurrentNetworkTransaction();
534 return network_trans_->PopulateNetErrorDetails(details); 646 if (network_transaction)
647 network_transaction->PopulateNetErrorDetails(details);
535 return; 648 return;
536 } 649 }
537 650
538 void HttpCache::Transaction::SetPriority(RequestPriority priority) { 651 void HttpCache::Transaction::SetPriority(RequestPriority priority) {
539 priority_ = priority; 652 priority_ = priority;
540 if (network_trans_) 653 if (network_trans_)
541 network_trans_->SetPriority(priority_); 654 network_trans_->SetPriority(priority_);
655 else if (shared_ && entry_ && entry_->shared_writers)
656 entry_->shared_writers->PriorityChanged();
542 } 657 }
543 658
544 void HttpCache::Transaction::SetWebSocketHandshakeStreamCreateHelper( 659 void HttpCache::Transaction::SetWebSocketHandshakeStreamCreateHelper(
545 WebSocketHandshakeStreamBase::CreateHelper* create_helper) { 660 WebSocketHandshakeStreamBase::CreateHelper* create_helper) {
546 websocket_handshake_stream_base_create_helper_ = create_helper; 661 websocket_handshake_stream_base_create_helper_ = create_helper;
547 if (network_trans_) 662 if (network_trans_)
548 network_trans_->SetWebSocketHandshakeStreamCreateHelper(create_helper); 663 network_trans_->SetWebSocketHandshakeStreamCreateHelper(create_helper);
549 } 664 }
550 665
551 void HttpCache::Transaction::SetBeforeNetworkStartCallback( 666 void HttpCache::Transaction::SetBeforeNetworkStartCallback(
(...skipping 10 matching lines...) Expand all
562 677
563 int HttpCache::Transaction::ResumeNetworkStart() { 678 int HttpCache::Transaction::ResumeNetworkStart() {
564 if (network_trans_) 679 if (network_trans_)
565 return network_trans_->ResumeNetworkStart(); 680 return network_trans_->ResumeNetworkStart();
566 return ERR_UNEXPECTED; 681 return ERR_UNEXPECTED;
567 } 682 }
568 683
569 void HttpCache::Transaction::GetConnectionAttempts( 684 void HttpCache::Transaction::GetConnectionAttempts(
570 ConnectionAttempts* out) const { 685 ConnectionAttempts* out) const {
571 ConnectionAttempts new_connection_attempts; 686 ConnectionAttempts new_connection_attempts;
572 if (network_trans_) 687 HttpTransaction* network_transaction = GetCurrentNetworkTransaction();
573 network_trans_->GetConnectionAttempts(&new_connection_attempts); 688 if (network_transaction)
689 network_transaction->GetConnectionAttempts(&new_connection_attempts);
574 690
575 out->swap(new_connection_attempts); 691 out->swap(new_connection_attempts);
576 out->insert(out->begin(), old_connection_attempts_.begin(), 692 out->insert(out->begin(), old_connection_attempts_.begin(),
577 old_connection_attempts_.end()); 693 old_connection_attempts_.end());
578 } 694 }
579 695
580 //----------------------------------------------------------------------------- 696 //-----------------------------------------------------------------------------
581 697
582 // A few common patterns: (Foo* means Foo -> FooComplete) 698 // A few common patterns: (Foo* means Foo -> FooComplete)
583 // 699 //
584 // 1. Not-cached entry: 700 // 1. Not-cached entry:
585 // Start(): 701 // Start():
586 // GetBackend* -> InitEntry -> OpenEntry* -> CreateEntry* -> AddToEntry* -> 702 // GetBackend* -> InitEntry -> OpenEntry* -> CreateEntry* -> AddToEntry* ->
587 // SendRequest* -> SuccessfulSendRequest -> OverwriteCachedResponse -> 703 // SendRequest* -> SuccessfulSendRequest -> OverwriteCachedResponse ->
588 // CacheWriteResponse* -> TruncateCachedData* -> TruncateCachedMetadata* -> 704 // CacheWriteResponse* -> TruncateCachedData* -> TruncateCachedMetadata* ->
589 // PartialHeadersReceived 705 // PartialHeadersReceived
590 // 706 //
591 // Read(): 707 // Read(): (For transactions that are not eligible for shared writing)
592 // NetworkRead* -> CacheWriteData* 708 // NetworkRead* -> CacheWriteData*
593 // 709 //
710 // Read(): (For transactions that are eligible for shared writing)
711 // SharedNetworkRead* -> SharedCacheWriteData*
712 //
713 // Read(): (For a transaction that is shared and another read is already in
714 // progress)
715 // SharedNetworkRead -> SharedNetworkReadWaitComplete
716 //
594 // 2. Cached entry, no validation: 717 // 2. Cached entry, no validation:
595 // Start(): 718 // Start():
596 // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse* 719 // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse*
597 // -> CacheDispatchValidation -> BeginPartialCacheValidation() -> 720 // -> CacheDispatchValidation -> BeginPartialCacheValidation() ->
598 // BeginCacheValidation() -> SetupEntryForRead() 721 // BeginCacheValidation() -> SetupEntryForRead()
599 // 722 //
600 // Read(): 723 // Read(): (When response is already written to the cache.)
601 // CacheReadData* 724 // CacheReadData*
602 // 725 //
726 // Read(): (When response is currently being written to the cache by shared
727 // writing.)
728 // SharedNetworkRead* -> SharedCacheWriteData*
729 //
603 // 3. Cached entry, validation (304): 730 // 3. Cached entry, validation (304):
604 // Start(): 731 // Start():
605 // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse* 732 // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse*
606 // -> CacheDispatchValidation -> BeginPartialCacheValidation() -> 733 // -> CacheDispatchValidation -> BeginPartialCacheValidation() ->
607 // BeginCacheValidation() -> SendRequest* -> SuccessfulSendRequest -> 734 // BeginCacheValidation() -> SendRequest* -> SuccessfulSendRequest ->
608 // UpdateCachedResponse -> CacheWriteUpdatedResponse* -> 735 // UpdateCachedResponse -> CacheWriteUpdatedResponse* ->
609 // UpdateCachedResponseComplete -> OverwriteCachedResponse -> 736 // UpdateCachedResponseComplete -> OverwriteCachedResponse ->
610 // PartialHeadersReceived 737 // PartialHeadersReceived
611 // 738 //
612 // Read(): 739 // Read(): () (When response is already written to the cache.)
613 // CacheReadData* 740 // CacheReadData*
614 // 741 //
742 // Read(): (When response is currently being written to the cache by shared
743 // writing.)
744 // SharedNetworkRead* -> SharedCacheWriteData*
745 //
615 // 4. Cached entry, validation and replace (200): 746 // 4. Cached entry, validation and replace (200):
616 // Start(): 747 // Start():
617 // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse* 748 // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse*
618 // -> CacheDispatchValidation -> BeginPartialCacheValidation() -> 749 // -> CacheDispatchValidation -> BeginPartialCacheValidation() ->
619 // BeginCacheValidation() -> SendRequest* -> SuccessfulSendRequest -> 750 // BeginCacheValidation() -> SendRequest* -> SuccessfulSendRequest ->
620 // OverwriteCachedResponse -> CacheWriteResponse* -> DoTruncateCachedData* -> 751 // OverwriteCachedResponse -> CacheWriteResponse* -> DoTruncateCachedData* ->
621 // TruncateCachedMetadata* -> PartialHeadersReceived 752 // TruncateCachedMetadata* -> PartialHeadersReceived
622 // 753 //
623 // Read(): 754 // Read():
624 // NetworkRead* -> CacheWriteData* 755 // NetworkRead* -> CacheWriteData*
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
866 case STATE_CACHE_WRITE_DATA_COMPLETE: 997 case STATE_CACHE_WRITE_DATA_COMPLETE:
867 rv = DoCacheWriteDataComplete(rv); 998 rv = DoCacheWriteDataComplete(rv);
868 break; 999 break;
869 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE: 1000 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE:
870 DCHECK_EQ(OK, rv); 1001 DCHECK_EQ(OK, rv);
871 rv = DoCacheWriteTruncatedResponse(); 1002 rv = DoCacheWriteTruncatedResponse();
872 break; 1003 break;
873 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE: 1004 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE:
874 rv = DoCacheWriteTruncatedResponseComplete(rv); 1005 rv = DoCacheWriteTruncatedResponseComplete(rv);
875 break; 1006 break;
1007 case STATE_SHARED_NETWORK_READ:
1008 DCHECK_EQ(OK, rv);
1009 rv = DoSharedNetworkRead();
1010 break;
1011 case STATE_SHARED_NETWORK_READ_COMPLETE:
1012 rv = DoSharedNetworkReadComplete(rv);
1013 break;
1014 case STATE_SHARED_NETWORK_READ_WAIT_COMPLETE:
1015 rv = DoSharedNetworkReadWaitComplete(rv);
1016 break;
1017 case STATE_SHARED_CACHE_WRITE_DATA:
1018 rv = DoSharedCacheWriteData(rv);
1019 break;
1020 case STATE_SHARED_CACHE_WRITE_DATA_COMPLETE:
1021 rv = DoSharedCacheWriteDataComplete(rv);
1022 break;
1023 case STATE_SHARED_READ_WRITE_FAILED:
1024 rv = DoSharedReadWriteFailed();
1025 break;
876 default: 1026 default:
877 NOTREACHED() << "bad state"; 1027 NOTREACHED() << "bad state";
878 rv = ERR_FAILED; 1028 rv = ERR_FAILED;
879 break; 1029 break;
880 } 1030 }
881 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 1031 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
882 1032
883 if (rv != ERR_IO_PENDING && !callback_.is_null()) { 1033 if (rv != ERR_IO_PENDING && !callback_.is_null()) {
884 read_buf_ = NULL; // Release the buffer before invoking the callback. 1034 read_buf_ = NULL; // Release the buffer before invoking the callback.
885 base::ResetAndReturn(&callback_).Run(rv); 1035 base::ResetAndReturn(&callback_).Run(rv);
(...skipping 617 matching lines...) Expand 10 before | Expand all | Expand 10 after
1503 1653
1504 RecordNoStoreHeaderHistogram(request_->load_flags, new_response); 1654 RecordNoStoreHeaderHistogram(request_->load_flags, new_response);
1505 1655
1506 if (new_response_->headers->response_code() == 416 && 1656 if (new_response_->headers->response_code() == 416 &&
1507 (request_->method == "GET" || request_->method == "POST")) { 1657 (request_->method == "GET" || request_->method == "POST")) {
1508 // If there is an active entry it may be destroyed with this transaction. 1658 // If there is an active entry it may be destroyed with this transaction.
1509 SetResponse(*new_response_); 1659 SetResponse(*new_response_);
1510 return OK; 1660 return OK;
1511 } 1661 }
1512 1662
1663 // If the transaction is shared and it is a 200 or an error response, then
1664 // doom the entry and let this transaction continue without writing to the
1665 // cache if shared writers contain more transactions. If not, continue
1666 // writing to the cache and also transfer the network transaction to shared
1667 // writers.
1668 if (shared_ && new_response->headers->response_code() != 304) {
1669 network_trans_ = entry_->shared_writers->OnValidationNoMatch(
1670 cache_key_, this, std::move(network_trans_), priority_);
1671 if (!shared_) {
1672 DCHECK(network_trans_);
1673 if (cache_entry_status_ == CacheEntryStatus::ENTRY_UNDEFINED) {
1674 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_DOOM_SHARED_WRITING);
1675 }
1676 DoneWritingToEntry(false, false);
1677 return OK;
1678 } else {
1679 DCHECK(!network_trans_);
1680 }
1681 }
1682
1513 // Are we expecting a response to a conditional query? 1683 // Are we expecting a response to a conditional query?
1514 if (mode_ == READ_WRITE || mode_ == UPDATE) { 1684 if (mode_ == READ_WRITE || mode_ == UPDATE) {
1515 if (new_response->headers->response_code() == 304 || handling_206_) { 1685 if (new_response->headers->response_code() == 304 || handling_206_) {
1516 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_VALIDATED); 1686 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_VALIDATED);
1517 next_state_ = STATE_UPDATE_CACHED_RESPONSE; 1687 next_state_ = STATE_UPDATE_CACHED_RESPONSE;
1518 return OK; 1688 return OK;
1519 } 1689 }
1520 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_UPDATED); 1690 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_UPDATED);
1521 mode_ = WRITE; 1691 mode_ = WRITE;
1522 } 1692 }
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1625 SetResponse(*new_response_); 1795 SetResponse(*new_response_);
1626 1796
1627 if (request_->method == "HEAD") { 1797 if (request_->method == "HEAD") {
1628 // This response is replacing the cached one. 1798 // This response is replacing the cached one.
1629 DoneWritingToEntry(false); 1799 DoneWritingToEntry(false);
1630 mode_ = NONE; 1800 mode_ = NONE;
1631 new_response_ = NULL; 1801 new_response_ = NULL;
1632 return OK; 1802 return OK;
1633 } 1803 }
1634 1804
1635 if (handling_206_ && !CanResume(false)) { 1805 if (handling_206_ &&
1806 !cache_->CanResumeEntry(false, request_->method, &response_, entry_)) {
1636 // There is no point in storing this resource because it will never be used. 1807 // There is no point in storing this resource because it will never be used.
1637 // This may change if we support LOAD_ONLY_FROM_CACHE with sparse entries. 1808 // This may change if we support LOAD_ONLY_FROM_CACHE with sparse entries.
1638 DoneWritingToEntry(false); 1809 DoneWritingToEntry(false);
1639 if (partial_) 1810 if (partial_)
1640 partial_->FixResponseHeaders(response_.headers.get(), true); 1811 partial_->FixResponseHeaders(response_.headers.get(), true);
1641 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED; 1812 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
1642 return OK; 1813 return OK;
1643 } 1814 }
1644 1815
1645 next_state_ = STATE_CACHE_WRITE_RESPONSE; 1816 next_state_ = STATE_CACHE_WRITE_RESPONSE;
1646 return OK; 1817 return OK;
1647 } 1818 }
1648 1819
1649 int HttpCache::Transaction::DoCacheWriteResponse() { 1820 int HttpCache::Transaction::DoCacheWriteResponse() {
1650 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponse"); 1821 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponse");
1651 next_state_ = STATE_CACHE_WRITE_RESPONSE_COMPLETE; 1822 next_state_ = STATE_CACHE_WRITE_RESPONSE_COMPLETE;
1652 return WriteResponseInfoToEntry(truncated_); 1823 return WriteResponseInfoToEntry(truncated_);
1653 } 1824 }
1654 1825
1655 int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) { 1826 int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) {
1656 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponseComplete"); 1827 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponseComplete");
1657 next_state_ = STATE_TRUNCATE_CACHED_DATA; 1828 next_state_ = STATE_TRUNCATE_CACHED_DATA;
1658 return OnWriteResponseInfoToEntryComplete(result); 1829 return OnWriteResponseInfoToEntryComplete(result);
1659 } 1830 }
1660 1831
1832 void HttpCache::Transaction::SetShared() {
1833 shared_ = true;
1834 }
1835
1836 void HttpCache::Transaction::ResetShared(bool continue_network_reading,
1837 bool continue_cache_reading) {
1838 if (!continue_network_reading) {
1839 SaveSharedNetworkTransactionInfo();
1840 }
1841 if (continue_cache_reading) {
1842 mode_ = READ;
1843 }
1844 shared_ = false;
1845 }
1846
1661 int HttpCache::Transaction::DoTruncateCachedData() { 1847 int HttpCache::Transaction::DoTruncateCachedData() {
1662 TRACE_EVENT0("io", "HttpCacheTransaction::DoTruncateCachedData"); 1848 TRACE_EVENT0("io", "HttpCacheTransaction::DoTruncateCachedData");
1663 next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE; 1849 next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE;
1664 if (!entry_) 1850 if (!entry_)
1665 return OK; 1851 return OK;
1666 if (net_log_.IsCapturing()) 1852 if (net_log_.IsCapturing())
1667 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_WRITE_DATA); 1853 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_WRITE_DATA);
1668 // Truncate the stream. 1854 // Truncate the stream.
1669 return WriteToEntry(kResponseContentIndex, 0, NULL, 0, io_callback_); 1855 return WriteToEntry(kResponseContentIndex, 0, NULL, 0, io_callback_);
1670 } 1856 }
(...skipping 28 matching lines...) Expand all
1699 if (net_log_.IsCapturing()) { 1885 if (net_log_.IsCapturing()) {
1700 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO, 1886 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO,
1701 result); 1887 result);
1702 } 1888 }
1703 } 1889 }
1704 1890
1705 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED; 1891 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
1706 return OK; 1892 return OK;
1707 } 1893 }
1708 1894
1895 void HttpCache::Transaction::ProcessForSharedWriting() {
1896 // Should not be already reading.
1897 if (reading_)
1898 return;
1899
1900 // If not already part of SharedWriters, then check if one should be
1901 // created.
1902 if (!shared_ && !IsEligibleForSharedWriting())
1903 return;
1904
1905 if (shared_) {
1906 // Non 304 case is already handled in DoSuccessfulSendRequest.
1907 if (response_.headers->response_code() != 304) {
1908 return;
1909 }
1910 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_JOIN_SHARED_WRITING);
1911 entry_->shared_writers->OnValidationMatch(this, priority_);
1912 network_trans_.reset();
1913 return;
1914 }
1915
1916 // Do not create a SharedWriters if its a Redirect response or if its a
1917 // no-store response.
1918 if (response_.headers->response_code() != 200)
1919 return;
1920
1921 if (!entry_)
1922 return;
1923
1924 DCHECK(cache_entry_status_ == CacheEntryStatus::ENTRY_NOT_IN_CACHE ||
1925 cache_entry_status_ == CacheEntryStatus::ENTRY_UPDATED ||
1926 cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE ||
1927 cache_entry_status_ == CacheEntryStatus::ENTRY_OTHER);
1928 // Measure how many requests out of the total of "not cached" and "updated"
1929 // are initiating shared writing.
1930 initiate_shared_writing_ = true;
1931 DCHECK(entry_ && network_trans_);
1932
1933 // An instance of SharedWriters will be created when the first writer has
1934 // written the new response headers in the cache. Transfer network
1935 // transaction’s ownership to SharedWriters so it can be used by any of the
1936 // transactions for subsequent reading from the network.
1937 SharedWriters::Create(this, std::move(network_trans_), cache_, priority_);
1938 }
1939
1709 int HttpCache::Transaction::DoPartialHeadersReceived() { 1940 int HttpCache::Transaction::DoPartialHeadersReceived() {
1710 new_response_ = NULL; 1941 new_response_ = NULL;
1711 if (entry_ && !partial_ && entry_->disk_entry->GetDataSize(kMetadataIndex)) 1942 if (entry_ && !partial_ && entry_->disk_entry->GetDataSize(kMetadataIndex))
1712 next_state_ = STATE_CACHE_READ_METADATA; 1943 next_state_ = STATE_CACHE_READ_METADATA;
1713 1944
1945 ProcessForSharedWriting();
1946
1714 if (!partial_) 1947 if (!partial_)
1715 return OK; 1948 return OK;
1716 1949
1717 if (reading_) { 1950 if (reading_) {
1718 if (network_trans_.get()) { 1951 if (network_trans_.get()) {
1719 next_state_ = STATE_NETWORK_READ; 1952 next_state_ = STATE_NETWORK_READ;
1720 } else { 1953 } else {
1721 next_state_ = STATE_CACHE_READ_DATA; 1954 next_state_ = STATE_CACHE_READ_DATA;
1722 } 1955 }
1723 } else if (mode_ != NONE) { 1956 } else if (mode_ != NONE) {
(...skipping 30 matching lines...) Expand all
1754 } 1987 }
1755 1988
1756 int HttpCache::Transaction::DoNetworkRead() { 1989 int HttpCache::Transaction::DoNetworkRead() {
1757 TRACE_EVENT0("io", "HttpCacheTransaction::DoNetworkRead"); 1990 TRACE_EVENT0("io", "HttpCacheTransaction::DoNetworkRead");
1758 next_state_ = STATE_NETWORK_READ_COMPLETE; 1991 next_state_ = STATE_NETWORK_READ_COMPLETE;
1759 return network_trans_->Read(read_buf_.get(), io_buf_len_, io_callback_); 1992 return network_trans_->Read(read_buf_.get(), io_buf_len_, io_callback_);
1760 } 1993 }
1761 1994
1762 int HttpCache::Transaction::DoNetworkReadComplete(int result) { 1995 int HttpCache::Transaction::DoNetworkReadComplete(int result) {
1763 TRACE_EVENT0("io", "HttpCacheTransaction::DoNetworkReadComplete"); 1996 TRACE_EVENT0("io", "HttpCacheTransaction::DoNetworkReadComplete");
1997 if (net_log_.IsCapturing())
1998 net_log_.EndEventWithNetErrorCode(
1999 NetLogEventType::HTTP_CACHE_NETWORK_READ_COMPLETE, result);
2000
1764 DCHECK(mode_ & WRITE || mode_ == NONE); 2001 DCHECK(mode_ & WRITE || mode_ == NONE);
1765 2002
1766 if (!cache_.get()) 2003 if (!cache_.get())
1767 return ERR_UNEXPECTED; 2004 return ERR_UNEXPECTED;
1768 2005
1769 // If there is an error or we aren't saving the data, we are done; just wait 2006 // If there is an error or we aren't saving the data, we are done; just wait
1770 // until the destructor runs to see if we can keep the data. 2007 // until the destructor runs to see if we can keep the data.
1771 if (mode_ == NONE || result < 0) 2008 if (mode_ == NONE || result < 0)
1772 return result; 2009 return result;
1773 2010
1774 next_state_ = STATE_CACHE_WRITE_DATA; 2011 next_state_ = STATE_CACHE_WRITE_DATA;
1775 return result; 2012 return result;
1776 } 2013 }
1777 2014
2015 int HttpCache::Transaction::DoSharedNetworkRead() {
2016 TRACE_EVENT0("io", "HttpCacheTransaction::DoSharedNetworkRead");
2017 if (net_log_.IsCapturing())
2018 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_SHARED_NETWORK_READ);
2019
2020 next_state_ = STATE_SHARED_NETWORK_READ_COMPLETE;
2021 bool shared_read_in_progress = false;
2022 int result = entry_->shared_writers->Read(
2023 read_buf_, io_buf_len_, io_callback_, this, &shared_read_in_progress);
2024 if (shared_read_in_progress) {
2025 next_state_ = STATE_SHARED_NETWORK_READ_WAIT_COMPLETE;
2026 }
2027 return result;
2028 }
2029
2030 int HttpCache::Transaction::DoSharedNetworkReadComplete(int result) {
2031 TRACE_EVENT0("io", "HttpCacheTransaction::DoSharedNetworkReadComplete");
2032 if (net_log_.IsCapturing())
2033 net_log_.EndEventWithNetErrorCode(
2034 NetLogEventType::HTTP_CACHE_SHARED_NETWORK_READ_COMPLETE, result);
2035
2036 if (result <= 0) {
2037 // Set entry as null so that the destructor does not invoke DoneWithEntry
2038 // again as entry_ is already cleaned up by SharedWriters.
2039 entry_ = nullptr;
2040 return result;
2041 }
2042
2043 read_offset_ += result;
2044
2045 next_state_ = STATE_SHARED_CACHE_WRITE_DATA;
2046 return result;
2047 }
2048
2049 int HttpCache::Transaction::DoSharedCacheWriteData(int result) {
2050 TRACE_EVENT0("io", "HttpCacheTransaction::DoSharedCacheWriteData");
2051 if (net_log_.IsCapturing())
2052 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_SHARED_CACHE_WRITE_DATA);
2053
2054 next_state_ = STATE_SHARED_CACHE_WRITE_DATA_COMPLETE;
2055 write_len_ = result;
2056 return entry_->shared_writers->CacheWrite(read_buf_, write_len_, io_callback_,
2057 this);
2058 }
2059
2060 int HttpCache::Transaction::DoSharedCacheWriteDataComplete(int result) {
2061 TRACE_EVENT0("io", "HttpCacheTransaction::DoSharedCacheWriteDataComplete");
2062 if (net_log_.IsCapturing())
2063 net_log_.EndEventWithNetErrorCode(
2064 NetLogEventType::HTTP_CACHE_SHARED_CACHE_WRITE_DATA_COMPLETE, result);
2065
2066 OnCacheWriteDataComplete(true, &result);
2067
2068 if (result == 0) {
2069 DoneWritingToEntry(true, false);
2070 }
2071 return result;
2072 }
2073
2074 void HttpCache::Transaction::OnCacheWriteDataComplete(bool was_shared,
2075 int* result) {
2076 if (*result != write_len_) {
2077 DoneWritingToEntry(false, !was_shared);
2078 // We want to ignore errors writing to disk and just keep reading from
2079 // the network.
2080 *result = write_len_;
2081 } else if (!done_reading_ && entry_ && (!partial_ || truncated_)) {
2082 done_reading_ = cache_->IsResponseCompleted(entry_, &response_);
2083 }
2084 }
2085
2086 int HttpCache::Transaction::DoSharedNetworkReadWaitComplete(int result) {
2087 TRACE_EVENT0("io", "HttpCacheTransaction::DoSharedNetworkReadWaitComplete");
2088 if (net_log_.IsCapturing())
2089 net_log_.EndEventWithNetErrorCode(
2090 NetLogEventType::HTTP_CACHE_SHARED_NETWORK_READ_WAIT_COMPLETE, result);
2091
2092 // If its a network read failure or cache write failure, we just return the
2093 // result. If its a cache write success, read_buf_ would have been filled
2094 // with the read data by SharedWriters.
2095 if (result == 0) { // response is complete.
2096 DoneWritingToEntry(true, false); // changes the mode_ to NONE.
2097 } else if (result > 0) {
2098 read_offset_ += result;
2099 } else {
2100 // Set entry as null so that the destructor does not invoke DoneWithEntry
2101 // again as entry_ is already cleaned up by SharedWriters.
2102 entry_ = nullptr;
2103 }
2104
2105 return result;
2106 }
2107
1778 int HttpCache::Transaction::DoCacheReadData() { 2108 int HttpCache::Transaction::DoCacheReadData() {
1779 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheReadData"); 2109 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheReadData");
1780 if (request_->method == "HEAD") 2110 if (request_->method == "HEAD")
1781 return 0; 2111 return 0;
1782 2112
1783 DCHECK(entry_); 2113 DCHECK(entry_);
1784 next_state_ = STATE_CACHE_READ_DATA_COMPLETE; 2114 next_state_ = STATE_CACHE_READ_DATA_COMPLETE;
1785 2115
1786 if (net_log_.IsCapturing()) 2116 if (net_log_.IsCapturing())
1787 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_READ_DATA); 2117 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_READ_DATA);
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1829 next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE; 2159 next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE;
1830 write_len_ = num_bytes; 2160 write_len_ = num_bytes;
1831 if (entry_) { 2161 if (entry_) {
1832 if (net_log_.IsCapturing()) 2162 if (net_log_.IsCapturing())
1833 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_WRITE_DATA); 2163 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_WRITE_DATA);
1834 } 2164 }
1835 2165
1836 if (!entry_ || !num_bytes) 2166 if (!entry_ || !num_bytes)
1837 return num_bytes; 2167 return num_bytes;
1838 2168
2169 if (partial_) {
2170 return partial_->CacheWrite(entry_->disk_entry, read_buf_.get(), num_bytes,
2171 io_callback_);
2172 }
2173
1839 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); 2174 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
1840 return WriteToEntry(kResponseContentIndex, current_size, read_buf_.get(), 2175 return entry_->disk_entry->WriteData(kResponseContentIndex, current_size,
1841 num_bytes, io_callback_); 2176 read_buf_.get(), num_bytes, io_callback_,
2177 true);
1842 } 2178 }
1843 2179
1844 int HttpCache::Transaction::DoCacheWriteDataComplete(int result) { 2180 int HttpCache::Transaction::DoCacheWriteDataComplete(int result) {
1845 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteDataComplete"); 2181 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteDataComplete");
1846 if (entry_) { 2182 if (entry_) {
1847 if (net_log_.IsCapturing()) { 2183 if (net_log_.IsCapturing()) {
1848 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_DATA, 2184 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_DATA,
1849 result); 2185 result);
1850 } 2186 }
1851 } 2187 }
1852 if (!cache_.get()) 2188 if (!cache_.get())
1853 return ERR_UNEXPECTED; 2189 return ERR_UNEXPECTED;
1854 2190
1855 if (result != write_len_) { 2191 OnCacheWriteDataComplete(false, &result);
1856 DLOG(ERROR) << "failed to write response data to cache";
1857 DoneWritingToEntry(false);
1858
1859 // We want to ignore errors writing to disk and just keep reading from
1860 // the network.
1861 result = write_len_;
1862 } else if (!done_reading_ && entry_ && (!partial_ || truncated_)) {
1863 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
1864 int64_t body_size = response_.headers->GetContentLength();
1865 if (body_size >= 0 && body_size <= current_size)
1866 done_reading_ = true;
1867 }
1868 2192
1869 if (partial_) { 2193 if (partial_) {
1870 // This may be the last request. 2194 // This may be the last request.
1871 if (result != 0 || truncated_ || 2195 if (result != 0 || truncated_ ||
1872 !(partial_->IsLastRange() || mode_ == WRITE)) { 2196 !(partial_->IsLastRange() || mode_ == WRITE)) {
1873 return DoPartialNetworkReadCompleted(result); 2197 return DoPartialNetworkReadCompleted(result);
1874 } 2198 }
1875 } 2199 }
1876 2200
2201 // End of file. This may be the result of a connection problem so see if we
2202 // have to keep the entry around to be flagged as truncated later on.
1877 if (result == 0) { 2203 if (result == 0) {
1878 // End of file. This may be the result of a connection problem so see if we
1879 // have to keep the entry around to be flagged as truncated later on.
1880 if (done_reading_ || !entry_ || partial_ || 2204 if (done_reading_ || !entry_ || partial_ ||
1881 response_.headers->GetContentLength() <= 0) { 2205 response_.headers->GetContentLength() <= 0)
1882 DoneWritingToEntry(true); 2206 DoneWritingToEntry(true);
1883 }
1884 } 2207 }
1885 2208
1886 return result; 2209 return result;
1887 } 2210 }
1888 2211
1889 int HttpCache::Transaction::DoCacheWriteTruncatedResponse() { 2212 int HttpCache::Transaction::DoCacheWriteTruncatedResponse() {
1890 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteTruncatedResponse"); 2213 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteTruncatedResponse");
1891 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE; 2214 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE;
1892 return WriteResponseInfoToEntry(true); 2215 return WriteResponseInfoToEntry(true);
1893 } 2216 }
1894 2217
1895 int HttpCache::Transaction::DoCacheWriteTruncatedResponseComplete(int result) { 2218 int HttpCache::Transaction::DoCacheWriteTruncatedResponseComplete(int result) {
1896 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteTruncatedResponse"); 2219 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteTruncatedResponse");
1897 2220
1898 return OnWriteResponseInfoToEntryComplete(result); 2221 return OnWriteResponseInfoToEntryComplete(result);
1899 } 2222 }
1900 2223
2224 int HttpCache::Transaction::DoSharedReadWriteFailed() {
2225 if (net_log_.IsCapturing())
2226 net_log_.EndEventWithNetErrorCode(
2227 NetLogEventType::HTTP_CACHE_SHARED_READ_WRITE_FAILED,
2228 shared_read_write_failure_result_);
2229
2230 return shared_read_write_failure_result_;
2231 }
2232
1901 //----------------------------------------------------------------------------- 2233 //-----------------------------------------------------------------------------
1902 2234
1903 void HttpCache::Transaction::SetRequest(const NetLogWithSource& net_log, 2235 void HttpCache::Transaction::SetRequest(const NetLogWithSource& net_log,
1904 const HttpRequestInfo* request) { 2236 const HttpRequestInfo* request) {
1905 net_log_ = net_log; 2237 net_log_ = net_log;
1906 request_ = request; 2238 request_ = request;
1907 effective_load_flags_ = request_->load_flags; 2239 effective_load_flags_ = request_->load_flags;
1908 2240
1909 if (cache_->mode() == DISABLE) 2241 if (cache_->mode() == DISABLE)
1910 effective_load_flags_ |= LOAD_DISABLE_CACHE; 2242 effective_load_flags_ |= LOAD_DISABLE_CACHE;
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
2084 2416
2085 if (partial_ && (is_sparse_ || truncated_) && 2417 if (partial_ && (is_sparse_ || truncated_) &&
2086 (!partial_->IsCurrentRangeCached() || invalid_range_)) { 2418 (!partial_->IsCurrentRangeCached() || invalid_range_)) {
2087 // Force revalidation for sparse or truncated entries. Note that we don't 2419 // Force revalidation for sparse or truncated entries. Note that we don't
2088 // want to ignore the regular validation logic just because a byte range was 2420 // want to ignore the regular validation logic just because a byte range was
2089 // part of the request. 2421 // part of the request.
2090 skip_validation = false; 2422 skip_validation = false;
2091 } 2423 }
2092 2424
2093 if (skip_validation) { 2425 if (skip_validation) {
2094 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_USED); 2426 if (shared_) {
2095 return SetupEntryForRead(); 2427 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_JOIN_SHARED_WRITING);
2428 entry_->shared_writers->OnValidationMatch(this, priority_);
2429 } else {
2430 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_USED);
2431 return SetupEntryForRead();
2432 }
2096 } else { 2433 } else {
2097 // Make the network request conditional, to see if we may reuse our cached 2434 // Make the network request conditional, to see if we may reuse our cached
2098 // response. If we cannot do so, then we just resort to a normal fetch. 2435 // response. If we cannot do so, then we just resort to a normal fetch.
2099 // Our mode remains READ_WRITE for a conditional request. Even if the 2436 // Our mode remains READ_WRITE for a conditional request. Even if the
2100 // conditionalization fails, we don't switch to WRITE mode until we 2437 // conditionalization fails, we don't switch to WRITE mode until we
2101 // know we won't be falling back to using the cache entry in the 2438 // know we won't be falling back to using the cache entry in the
2102 // LOAD_FROM_CACHE_IF_OFFLINE case. 2439 // LOAD_FROM_CACHE_IF_OFFLINE case.
2103 if (!ConditionalizeRequest()) { 2440 if (!ConditionalizeRequest()) {
2104 couldnt_conditionalize_request_ = true; 2441 couldnt_conditionalize_request_ = true;
2105 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE); 2442 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE);
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after
2604 IsCertStatusError(response_.ssl_info.cert_status)) { 2941 IsCertStatusError(response_.ssl_info.cert_status)) {
2605 DoneWritingToEntry(false); 2942 DoneWritingToEntry(false);
2606 if (net_log_.IsCapturing()) 2943 if (net_log_.IsCapturing())
2607 net_log_.EndEvent(NetLogEventType::HTTP_CACHE_WRITE_INFO); 2944 net_log_.EndEvent(NetLogEventType::HTTP_CACHE_WRITE_INFO);
2608 return OK; 2945 return OK;
2609 } 2946 }
2610 2947
2611 if (truncated) 2948 if (truncated)
2612 DCHECK_EQ(200, response_.headers->response_code()); 2949 DCHECK_EQ(200, response_.headers->response_code());
2613 2950
2614 // When writing headers, we normally only write the non-transient headers. 2951 return cache_->WriteResponseInfo(entry_, &response_, io_callback_, truncated,
2615 bool skip_transient_headers = true; 2952 &io_buf_len_);
2616 scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer());
2617 response_.Persist(data->pickle(), skip_transient_headers, truncated);
2618 data->Done();
2619
2620 io_buf_len_ = data->pickle()->size();
2621 return entry_->disk_entry->WriteData(kResponseInfoIndex, 0, data.get(),
2622 io_buf_len_, io_callback_, true);
2623 } 2953 }
2624 2954
2625 int HttpCache::Transaction::OnWriteResponseInfoToEntryComplete(int result) { 2955 int HttpCache::Transaction::OnWriteResponseInfoToEntryComplete(int result) {
2626 if (!entry_) 2956 if (!entry_)
2627 return OK; 2957 return OK;
2628 if (net_log_.IsCapturing()) { 2958 if (net_log_.IsCapturing()) {
2629 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO, 2959 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO,
2630 result); 2960 result);
2631 } 2961 }
2632 2962
2633 if (result != io_buf_len_) { 2963 if (result != io_buf_len_) {
2634 DLOG(ERROR) << "failed to write response info to cache"; 2964 DLOG(ERROR) << "failed to write response info to cache";
2635 DoneWritingToEntry(false); 2965 DoneWritingToEntry(false);
2636 } 2966 }
2637 return OK; 2967 return OK;
2638 } 2968 }
2639 2969
2640 void HttpCache::Transaction::DoneWritingToEntry(bool success) { 2970 void HttpCache::Transaction::DoneWritingToEntry(bool success,
2971 bool perform_entry_cleanup) {
2641 if (!entry_) 2972 if (!entry_)
2642 return; 2973 return;
2643 2974
2644 RecordHistograms(); 2975 RecordHistograms();
2645 2976
2646 cache_->DoneWritingToEntry(entry_, success); 2977 if (perform_entry_cleanup) {
2647 entry_ = NULL; 2978 cache_->DoneWritingToEntry(entry_, success);
2979 }
2980 entry_ = nullptr;
2648 mode_ = NONE; // switch to 'pass through' mode 2981 mode_ = NONE; // switch to 'pass through' mode
2649 } 2982 }
2650 2983
2984 void HttpCache::Transaction::ContinueWithoutSharedWriting(
2985 std::unique_ptr<HttpTransaction> network_transaction,
2986 bool needs_entry) {
2987 shared_ = false;
2988 if (!needs_entry)
2989 entry_ = nullptr;
2990 mode_ = NONE;
2991 network_trans_ = std::move(network_transaction);
2992 }
2993
2651 int HttpCache::Transaction::OnCacheReadError(int result, bool restart) { 2994 int HttpCache::Transaction::OnCacheReadError(int result, bool restart) {
2652 DLOG(ERROR) << "ReadData failed: " << result; 2995 DLOG(ERROR) << "ReadData failed: " << result;
2653 const int result_for_histogram = std::max(0, -result); 2996 const int result_for_histogram = std::max(0, -result);
2654 if (restart) { 2997 if (restart) {
2655 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorRestartable", 2998 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorRestartable",
2656 result_for_histogram); 2999 result_for_histogram);
2657 } else { 3000 } else {
2658 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorNonRestartable", 3001 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorNonRestartable",
2659 result_for_histogram); 3002 result_for_histogram);
2660 } 3003 }
2661 3004
2662 // Avoid using this entry in the future. 3005 // Avoid using this entry in the future.
2663 if (cache_.get()) 3006 if (cache_.get())
2664 cache_->DoomActiveEntry(cache_key_); 3007 cache_->DoomActiveEntry(cache_key_);
2665 3008
2666 if (restart) { 3009 if (restart) {
2667 DCHECK(!reading_); 3010 DCHECK(!reading_);
2668 DCHECK(!network_trans_.get()); 3011 DCHECK(!network_trans_.get());
2669 cache_->DoneWithEntry(entry_, this, false); 3012 if (shared_) {
3013 entry_->shared_writers->RemoveValidatingTransaction(this);
3014 } else {
3015 cache_->DoneWithEntry(entry_, this, false);
3016 }
2670 entry_ = NULL; 3017 entry_ = NULL;
2671 is_sparse_ = false; 3018 is_sparse_ = false;
2672 partial_.reset(); 3019 partial_.reset();
2673 next_state_ = STATE_GET_BACKEND; 3020 next_state_ = STATE_GET_BACKEND;
2674 return OK; 3021 return OK;
2675 } 3022 }
2676 3023
2677 return ERR_CACHE_READ_FAILURE; 3024 return ERR_CACHE_READ_FAILURE;
2678 } 3025 }
2679 3026
2680 void HttpCache::Transaction::OnAddToEntryTimeout(base::TimeTicks start_time) { 3027 void HttpCache::Transaction::OnAddToEntryTimeout(base::TimeTicks start_time) {
2681 if (entry_lock_waiting_since_ != start_time) 3028 if (entry_lock_waiting_since_ != start_time)
2682 return; 3029 return;
2683 3030
2684 DCHECK_EQ(next_state_, STATE_ADD_TO_ENTRY_COMPLETE); 3031 DCHECK_EQ(next_state_, STATE_ADD_TO_ENTRY_COMPLETE);
2685 3032
2686 if (!cache_) 3033 if (!cache_)
2687 return; 3034 return;
2688 3035
2689 cache_->RemovePendingTransaction(this); 3036 cache_->RemovePendingTransaction(this);
2690 OnIOComplete(ERR_CACHE_LOCK_TIMEOUT); 3037 OnIOComplete(ERR_CACHE_LOCK_TIMEOUT);
2691 } 3038 }
2692 3039
2693 void HttpCache::Transaction::DoomPartialEntry(bool delete_object) { 3040 void HttpCache::Transaction::DoomPartialEntry(bool delete_object) {
3041 // Partial requests not supported with shared writing as of now.
3042 DCHECK(!shared_);
2694 DVLOG(2) << "DoomPartialEntry"; 3043 DVLOG(2) << "DoomPartialEntry";
2695 int rv = cache_->DoomEntry(cache_key_, NULL); 3044 int rv = cache_->DoomEntry(cache_key_, NULL);
2696 DCHECK_EQ(OK, rv); 3045 DCHECK_EQ(OK, rv);
2697 cache_->DoneWithEntry(entry_, this, false); 3046 cache_->DoneWithEntry(entry_, this, false);
2698 entry_ = NULL; 3047 entry_ = NULL;
2699 is_sparse_ = false; 3048 is_sparse_ = false;
2700 truncated_ = false; 3049 truncated_ = false;
2701 if (delete_object) 3050 if (delete_object)
2702 partial_.reset(NULL); 3051 partial_.reset(NULL);
2703 } 3052 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2744 if (!delete_object) { 3093 if (!delete_object) {
2745 // The simplest way to re-initialize partial_ is to create a new object. 3094 // The simplest way to re-initialize partial_ is to create a new object.
2746 partial_.reset(new PartialData()); 3095 partial_.reset(new PartialData());
2747 if (partial_->Init(request_->extra_headers)) 3096 if (partial_->Init(request_->extra_headers))
2748 partial_->SetHeaders(custom_request_->extra_headers); 3097 partial_->SetHeaders(custom_request_->extra_headers);
2749 else 3098 else
2750 partial_.reset(); 3099 partial_.reset();
2751 } 3100 }
2752 } 3101 }
2753 3102
2754 void HttpCache::Transaction::ResetNetworkTransaction() { 3103 void HttpCache::Transaction::SaveNetworkTransactionInfo(
3104 const HttpTransaction* transaction) {
2755 DCHECK(!old_network_trans_load_timing_); 3105 DCHECK(!old_network_trans_load_timing_);
2756 DCHECK(network_trans_); 3106 DCHECK(transaction);
2757 LoadTimingInfo load_timing; 3107 LoadTimingInfo load_timing;
2758 if (network_trans_->GetLoadTimingInfo(&load_timing)) 3108 if (transaction->GetLoadTimingInfo(&load_timing))
2759 old_network_trans_load_timing_.reset(new LoadTimingInfo(load_timing)); 3109 old_network_trans_load_timing_.reset(new LoadTimingInfo(load_timing));
2760 total_received_bytes_ += network_trans_->GetTotalReceivedBytes(); 3110 total_received_bytes_ += transaction->GetTotalReceivedBytes();
2761 total_sent_bytes_ += network_trans_->GetTotalSentBytes(); 3111 total_sent_bytes_ += transaction->GetTotalSentBytes();
2762 ConnectionAttempts attempts; 3112 ConnectionAttempts attempts;
2763 network_trans_->GetConnectionAttempts(&attempts); 3113 transaction->GetConnectionAttempts(&attempts);
2764 for (const auto& attempt : attempts) 3114 for (const auto& attempt : attempts)
2765 old_connection_attempts_.push_back(attempt); 3115 old_connection_attempts_.push_back(attempt);
2766 old_remote_endpoint_ = IPEndPoint(); 3116 old_remote_endpoint_ = IPEndPoint();
2767 network_trans_->GetRemoteEndpoint(&old_remote_endpoint_); 3117 transaction->GetRemoteEndpoint(&old_remote_endpoint_);
3118 }
3119
3120 void HttpCache::Transaction::SaveSharedNetworkTransactionInfo() {
3121 // If network_trans_ is still present, this transaction has not started using
3122 // the "shared" network transaction.
3123 if (network_trans_) {
3124 SaveNetworkTransactionInfo(network_trans_.get());
3125 return;
3126 }
3127
3128 DCHECK(!old_network_trans_load_timing_);
3129
3130 // If the transaction is being deleted while still in the waiting queue,
3131 // entry_ is not yet set, do nothing.
3132 if (!entry_)
3133 return;
3134 DCHECK(entry_->shared_writers);
3135 HttpTransaction* network_transaction =
3136 entry_->shared_writers->network_transaction();
3137 SaveNetworkTransactionInfo(network_transaction);
3138 have_full_request_headers_ =
3139 network_transaction->GetFullRequestHeaders(&full_request_headers_);
3140 }
3141
3142 void HttpCache::Transaction::ResetNetworkTransaction() {
3143 SaveNetworkTransactionInfo(network_trans_.get());
2768 network_trans_.reset(); 3144 network_trans_.reset();
2769 } 3145 }
2770 3146
2771 // Histogram data from the end of 2010 show the following distribution of 3147 HttpTransaction* HttpCache::Transaction::GetCurrentNetworkTransaction() const {
2772 // response headers: 3148 if (network_trans_)
2773 // 3149 return network_trans_.get();
2774 // Content-Length............... 87% 3150 if (shared_ && entry_ && entry_->shared_writers)
2775 // Date......................... 98% 3151 return entry_->shared_writers->network_transaction();
2776 // Last-Modified................ 49% 3152 return nullptr;
2777 // Etag......................... 19%
2778 // Accept-Ranges: bytes......... 25%
2779 // Accept-Ranges: none.......... 0.4%
2780 // Strong Validator............. 50%
2781 // Strong Validator + ranges.... 24%
2782 // Strong Validator + CL........ 49%
2783 //
2784 bool HttpCache::Transaction::CanResume(bool has_data) {
2785 // Double check that there is something worth keeping.
2786 if (has_data && !entry_->disk_entry->GetDataSize(kResponseContentIndex))
2787 return false;
2788
2789 if (request_->method != "GET")
2790 return false;
2791
2792 // Note that if this is a 206, content-length was already fixed after calling
2793 // PartialData::ResponseHeadersOK().
2794 if (response_.headers->GetContentLength() <= 0 ||
2795 response_.headers->HasHeaderValue("Accept-Ranges", "none") ||
2796 !response_.headers->HasStrongValidators()) {
2797 return false;
2798 }
2799
2800 return true;
2801 } 3153 }
2802 3154
2803 void HttpCache::Transaction::SetResponse(const HttpResponseInfo& response) { 3155 void HttpCache::Transaction::SetResponse(const HttpResponseInfo& response) {
2804 response_ = response; 3156 response_ = response;
2805 SyncCacheEntryStatusToResponse(); 3157 SyncCacheEntryStatusToResponse();
2806 } 3158 }
2807 3159
2808 void HttpCache::Transaction::SetAuthResponse( 3160 void HttpCache::Transaction::SetAuthResponse(
2809 const HttpResponseInfo& auth_response) { 3161 const HttpResponseInfo& auth_response) {
2810 auth_response_ = auth_response; 3162 auth_response_ = auth_response;
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
2916 } 3268 }
2917 } 3269 }
2918 3270
2919 CACHE_STATUS_HISTOGRAMS(""); 3271 CACHE_STATUS_HISTOGRAMS("");
2920 3272
2921 if (cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE) { 3273 if (cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE) {
2922 UMA_HISTOGRAM_ENUMERATION("HttpCache.CantConditionalizeCause", 3274 UMA_HISTOGRAM_ENUMERATION("HttpCache.CantConditionalizeCause",
2923 validation_cause_, VALIDATION_CAUSE_MAX); 3275 validation_cause_, VALIDATION_CAUSE_MAX);
2924 } 3276 }
2925 3277
3278 // This may also exclude shared writing counts for these cases.
2926 if (cache_entry_status_ == CacheEntryStatus::ENTRY_OTHER) 3279 if (cache_entry_status_ == CacheEntryStatus::ENTRY_OTHER)
2927 return; 3280 return;
3281
2928 DCHECK(!range_requested_); 3282 DCHECK(!range_requested_);
2929 DCHECK(!first_cache_access_since_.is_null()); 3283 DCHECK(!first_cache_access_since_.is_null());
2930 3284
2931 TimeDelta total_time = base::TimeTicks::Now() - first_cache_access_since_; 3285 TimeDelta total_time = base::TimeTicks::Now() - first_cache_access_since_;
2932 3286
2933 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone", total_time); 3287 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone", total_time);
2934 3288
3289 if (cache_entry_status_ == CacheEntryStatus::ENTRY_JOIN_SHARED_WRITING) {
3290 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.JoinSharedWriting", total_time);
3291 } else if (cache_entry_status_ ==
3292 CacheEntryStatus::ENTRY_DOOM_SHARED_WRITING) {
3293 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.DoomSharedWriting", total_time);
3294 } else if (initiate_shared_writing_) {
3295 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.InitiateSharedWriting",
3296 total_time);
3297 }
3298
2935 bool did_send_request = !send_request_since_.is_null(); 3299 bool did_send_request = !send_request_since_.is_null();
2936 DCHECK( 3300 DCHECK(
2937 (did_send_request && 3301 (did_send_request &&
2938 (cache_entry_status_ == CacheEntryStatus::ENTRY_NOT_IN_CACHE || 3302 (cache_entry_status_ == CacheEntryStatus::ENTRY_NOT_IN_CACHE ||
2939 cache_entry_status_ == CacheEntryStatus::ENTRY_VALIDATED || 3303 cache_entry_status_ == CacheEntryStatus::ENTRY_VALIDATED ||
2940 cache_entry_status_ == CacheEntryStatus::ENTRY_UPDATED || 3304 cache_entry_status_ == CacheEntryStatus::ENTRY_UPDATED ||
2941 cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE)) || 3305 cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE ||
3306 cache_entry_status_ == CacheEntryStatus::ENTRY_JOIN_SHARED_WRITING ||
3307 cache_entry_status_ == CacheEntryStatus::ENTRY_DOOM_SHARED_WRITING)) ||
2942 (!did_send_request && 3308 (!did_send_request &&
2943 cache_entry_status_ == CacheEntryStatus::ENTRY_USED)); 3309 (cache_entry_status_ == CacheEntryStatus::ENTRY_USED ||
3310 cache_entry_status_ == CacheEntryStatus::ENTRY_JOIN_SHARED_WRITING)));
2944 3311
2945 if (!did_send_request) { 3312 if (!did_send_request) {
2946 DCHECK(cache_entry_status_ == CacheEntryStatus::ENTRY_USED); 3313 if (cache_entry_status_ == CacheEntryStatus::ENTRY_USED) {
2947 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.Used", total_time); 3314 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.Used", total_time);
3315 }
2948 return; 3316 return;
2949 } 3317 }
2950 3318
2951 TimeDelta before_send_time = send_request_since_ - first_cache_access_since_; 3319 TimeDelta before_send_time = send_request_since_ - first_cache_access_since_;
2952 int64_t before_send_percent = (total_time.ToInternalValue() == 0) 3320 int64_t before_send_percent = (total_time.ToInternalValue() == 0)
2953 ? 0 3321 ? 0
2954 : before_send_time * 100 / total_time; 3322 : before_send_time * 100 / total_time;
2955 DCHECK_GE(before_send_percent, 0); 3323 DCHECK_GE(before_send_percent, 0);
2956 DCHECK_LE(before_send_percent, 100); 3324 DCHECK_LE(before_send_percent, 100);
2957 base::HistogramBase::Sample before_send_sample = 3325 base::HistogramBase::Sample before_send_sample =
2958 static_cast<base::HistogramBase::Sample>(before_send_percent); 3326 static_cast<base::HistogramBase::Sample>(before_send_percent);
2959 3327
2960 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.SentRequest", total_time); 3328 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.SentRequest", total_time);
2961 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend", before_send_time); 3329 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend", before_send_time);
2962 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend", before_send_sample); 3330 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend", before_send_sample);
2963 3331
2964 // TODO(gavinp): Remove or minimize these histograms, particularly the ones 3332 // TODO(gavinp): Remove or minimize these histograms, particularly the ones
2965 // below this comment after we have received initial data. 3333 // below this comment after we have received initial data.
2966 switch (cache_entry_status_) { 3334 switch (cache_entry_status_) {
2967 case CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE: { 3335 case CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE: {
2968 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.CantConditionalize", 3336 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.CantConditionalize",
2969 before_send_time); 3337 before_send_time);
2970 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.CantConditionalize", 3338 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.CantConditionalize",
2971 before_send_sample); 3339 before_send_sample);
3340 if (initiate_shared_writing_) {
3341 UMA_HISTOGRAM_TIMES(
3342 "HttpCache.BeforeSend.CantConditionalize.InitiateSharedWriting",
3343 before_send_time);
3344 UMA_HISTOGRAM_PERCENTAGE(
3345 "HttpCache.PercentBeforeSend.CantConditionalize."
3346 "InitiateSharedWriting",
3347 before_send_sample);
3348 }
3349
2972 break; 3350 break;
2973 } 3351 }
2974 case CacheEntryStatus::ENTRY_NOT_IN_CACHE: { 3352 case CacheEntryStatus::ENTRY_NOT_IN_CACHE: {
2975 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.NotCached", before_send_time); 3353 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.NotCached", before_send_time);
2976 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.NotCached", 3354 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.NotCached",
2977 before_send_sample); 3355 before_send_sample);
3356 if (initiate_shared_writing_) {
3357 UMA_HISTOGRAM_TIMES(
3358 "HttpCache.BeforeSend.NotCached.InitiateSharedWriting",
3359 before_send_time);
3360 UMA_HISTOGRAM_PERCENTAGE(
3361 "HttpCache.PercentBeforeSend.NotCached.InitiateSharedWriting",
3362 before_send_sample);
3363 }
3364
2978 break; 3365 break;
2979 } 3366 }
2980 case CacheEntryStatus::ENTRY_VALIDATED: { 3367 case CacheEntryStatus::ENTRY_VALIDATED: {
2981 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Validated", before_send_time); 3368 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Validated", before_send_time);
2982 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.Validated", 3369 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.Validated",
2983 before_send_sample); 3370 before_send_sample);
2984 break; 3371 break;
2985 } 3372 }
2986 case CacheEntryStatus::ENTRY_UPDATED: { 3373 case CacheEntryStatus::ENTRY_UPDATED: {
2987 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Updated", before_send_time); 3374 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Updated", before_send_time);
2988 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.Updated", 3375 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.Updated",
2989 before_send_sample); 3376 before_send_sample);
3377 if (initiate_shared_writing_) {
3378 UMA_HISTOGRAM_TIMES(
3379 "HttpCache.BeforeSend.Updated.InitiateSharedWriting",
3380 before_send_time);
3381 UMA_HISTOGRAM_PERCENTAGE(
3382 "HttpCache.PercentBeforeSend.Updated.InitiateSharedWriting",
3383 before_send_sample);
3384 }
3385 break;
3386 }
3387 case CacheEntryStatus::ENTRY_JOIN_SHARED_WRITING: {
3388 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.JoinSharedWriting",
3389 before_send_time);
3390 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.JoinSharedWriting",
3391 before_send_sample);
3392 break;
3393 }
3394 case CacheEntryStatus::ENTRY_DOOM_SHARED_WRITING: {
3395 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.DoomSharedWriting",
3396 before_send_time);
3397 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.DoomSharedWriting",
3398 before_send_sample);
2990 break; 3399 break;
2991 } 3400 }
2992 default: 3401 default:
2993 NOTREACHED(); 3402 NOTREACHED();
2994 } 3403 }
2995 } 3404 }
2996 3405
3406 bool HttpCache::Transaction::IsEligibleForSharedWriting() const {
3407 if (!(mode_ & WRITE))
3408 return false;
3409
3410 DCHECK(request_);
3411 if (request_->method != "GET")
3412 return false;
3413
3414 if (partial_ || range_requested_)
3415 return false;
3416
3417 if (truncated_)
3418 return false;
3419
3420 return true;
3421 }
3422
3423 void HttpCache::Transaction::SetSharedWritingFailState(int result) {
3424 next_state_ = STATE_SHARED_READ_WRITE_FAILED;
3425 shared_read_write_failure_result_ = result;
3426 entry_ = nullptr;
3427 }
3428
2997 void HttpCache::Transaction::OnIOComplete(int result) { 3429 void HttpCache::Transaction::OnIOComplete(int result) {
2998 DoLoop(result); 3430 DoLoop(result);
2999 } 3431 }
3000 3432
3001 } // namespace net 3433 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_cache_transaction.h ('k') | net/http/http_cache_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698