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

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

Issue 2519473002: Fixes the cache lock issue. (Closed)
Patch Set: Redesigned the fix using DataAccess class for eliminating Orphan API.(Rebased till refs/heads/master@{#442607}) Created 3 years, 11 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
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_data_access.h"
44 #include "net/http/http_cache_shared_writers.h"
41 #include "net/http/http_network_session.h" 45 #include "net/http/http_network_session.h"
42 #include "net/http/http_request_info.h" 46 #include "net/http/http_request_info.h"
43 #include "net/http/http_util.h" 47 #include "net/http/http_util.h"
44 #include "net/log/net_log_event_type.h" 48 #include "net/log/net_log_event_type.h"
45 #include "net/ssl/ssl_cert_request_info.h" 49 #include "net/ssl/ssl_cert_request_info.h"
46 #include "net/ssl/ssl_config_service.h" 50 #include "net/ssl/ssl_config_service.h"
47 51
48 using base::Time; 52 using base::Time;
49 using base::TimeDelta; 53 using base::TimeDelta;
50 using base::TimeTicks; 54 using base::TimeTicks;
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 truncated_(false), 178 truncated_(false),
175 is_sparse_(false), 179 is_sparse_(false),
176 range_requested_(false), 180 range_requested_(false),
177 handling_206_(false), 181 handling_206_(false),
178 cache_pending_(false), 182 cache_pending_(false),
179 done_reading_(false), 183 done_reading_(false),
180 vary_mismatch_(false), 184 vary_mismatch_(false),
181 couldnt_conditionalize_request_(false), 185 couldnt_conditionalize_request_(false),
182 bypass_lock_for_test_(false), 186 bypass_lock_for_test_(false),
183 fail_conditionalization_for_test_(false), 187 fail_conditionalization_for_test_(false),
188 shared_(false),
189 initiate_shared_writing_(false),
190 shared_read_write_failure_result_(0),
184 io_buf_len_(0), 191 io_buf_len_(0),
185 read_offset_(0), 192 read_offset_(0),
186 effective_load_flags_(0), 193 effective_load_flags_(0),
187 write_len_(0), 194 write_len_(0),
188 cache_entry_status_(CacheEntryStatus::ENTRY_UNDEFINED), 195 cache_entry_status_(CacheEntryStatus::ENTRY_UNDEFINED),
189 validation_cause_(VALIDATION_CAUSE_UNDEFINED), 196 validation_cause_(VALIDATION_CAUSE_UNDEFINED),
190 total_received_bytes_(0), 197 total_received_bytes_(0),
191 total_sent_bytes_(0), 198 total_sent_bytes_(0),
192 websocket_handshake_stream_base_create_helper_(NULL), 199 websocket_handshake_stream_base_create_helper_(NULL),
200 have_full_request_headers_(false),
193 weak_factory_(this) { 201 weak_factory_(this) {
194 TRACE_EVENT0("io", "HttpCacheTransaction::Transaction"); 202 TRACE_EVENT0("io", "HttpCacheTransaction::Transaction");
195 static_assert(HttpCache::Transaction::kNumValidationHeaders == 203 static_assert(HttpCache::Transaction::kNumValidationHeaders ==
196 arraysize(kValidationHeaders), 204 arraysize(kValidationHeaders),
197 "invalid number of validation headers"); 205 "invalid number of validation headers");
198 206
199 io_callback_ = base::Bind(&Transaction::OnIOComplete, 207 io_callback_ = base::Bind(&Transaction::OnIOComplete,
200 weak_factory_.GetWeakPtr()); 208 weak_factory_.GetWeakPtr());
201 } 209 }
202 210
203 HttpCache::Transaction::~Transaction() { 211 HttpCache::Transaction::~Transaction() {
204 TRACE_EVENT0("io", "HttpCacheTransaction::~Transaction"); 212 TRACE_EVENT0("io", "HttpCacheTransaction::~Transaction");
213
214 if (shared_) {
215 // Remove transaction from shared writers and do any cleanup, if needed, for
216 // entry_->shared_writers and entry_.
217 RemoveTransactionFromSharedWriters();
218 }
219
205 // We may have to issue another IO, but we should never invoke the callback_ 220 // We may have to issue another IO, but we should never invoke the callback_
206 // after this point. 221 // after this point.
207 callback_.Reset(); 222 callback_.Reset();
208 223
209 if (cache_) { 224 if (cache_) {
210 if (entry_) { 225 if (entry_) {
211 bool cancel_request = reading_ && response_.headers.get(); 226 bool cancel_request = reading_ && response_.headers.get();
212 if (cancel_request) { 227 if (cancel_request) {
213 if (partial_) { 228 if (partial_) {
214 entry_->disk_entry->CancelSparseIO(); 229 entry_->disk_entry->CancelSparseIO();
215 } else { 230 } else {
216 cancel_request &= (response_.headers->response_code() == 200); 231 cancel_request &= (response_.headers->response_code() == 200);
217 } 232 }
218 } 233 }
219
220 cache_->DoneWithEntry(entry_, this, cancel_request); 234 cache_->DoneWithEntry(entry_, this, cancel_request);
221 } else if (cache_pending_) { 235 } else if (cache_pending_) {
222 cache_->RemovePendingTransaction(this); 236 cache_->RemovePendingTransaction(this);
223 } 237 }
224 } 238 }
225 } 239 }
226 240
241 void HttpCache::Transaction::RemoveTransactionFromSharedWriters() {
242 // Current shared data_access_ consumer.
243 if (next_state_ == STATE_SHARED_NETWORK_READ_COMPLETE ||
244 next_state_ == STATE_SHARED_CACHE_WRITE_DATA_COMPLETE) {
245 cache_->RemoveCurrentSharedWriter(this, entry_);
246 } else if (next_state_ == STATE_SHARED_NETWORK_READ_WAIT_COMPLETE) {
247 // Waiting on data_access_ operation to be completed by another
248 // transaction.
249 entry_->shared_writers->RemoveWaitingWriter(this);
250 } else if (next_state_ != STATE_NONE &&
251 next_state_ <= STATE_ADD_TO_ENTRY_COMPLETE) {
252 // Pending transaction not yet to added to an entry.
253 cache_->RemovePendingTransaction(this);
254 // Set cache_pending_ to false so that more cleanup is not attempted in
255 // the destructor.
256 cache_pending_ = false;
257 } else if (validating_shared()) {
258 cache_->RemoveValidatingTransSharedWriters(this, entry_);
259 } else {
260 cache_->RemoveIdleSharedWriter(this, entry_);
261 }
262
263 DCHECK(!shared_);
264
265 // Since any cleanup needed in entry_ and shared_writers is already done,
266 // set entry_ to null.
267 entry_ = nullptr;
268 }
269
227 int HttpCache::Transaction::WriteMetadata(IOBuffer* buf, int buf_len, 270 int HttpCache::Transaction::WriteMetadata(IOBuffer* buf, int buf_len,
228 const CompletionCallback& callback) { 271 const CompletionCallback& callback) {
229 DCHECK(buf); 272 DCHECK(buf);
230 DCHECK_GT(buf_len, 0); 273 DCHECK_GT(buf_len, 0);
231 DCHECK(!callback.is_null()); 274 DCHECK(!callback.is_null());
232 if (!cache_.get() || !entry_) 275 if (!cache_.get() || !entry_)
233 return ERR_UNEXPECTED; 276 return ERR_UNEXPECTED;
234 277
235 // We don't need to track this operation for anything. 278 // We don't need to track this operation for anything.
236 // It could be possible to check if there is something already written and 279 // 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 280 // avoid writing again (it should be the same, right?), but let's allow the
238 // caller to "update" the contents with something new. 281 // caller to "update" the contents with something new.
239 return entry_->disk_entry->WriteData(kMetadataIndex, 0, buf, buf_len, 282 return entry_->disk_entry->WriteData(kMetadataIndex, 0, buf, buf_len,
240 callback, true); 283 callback, true);
241 } 284 }
242 285
243 bool HttpCache::Transaction::AddTruncatedFlag() { 286 bool HttpCache::Transaction::AddTruncatedFlag() {
244 DCHECK(mode_ & WRITE || mode_ == NONE); 287 DCHECK(mode_ & WRITE || mode_ == NONE);
245 288
246 // Don't set the flag for sparse entries. 289 // Don't set the flag for sparse entries.
247 if (partial_ && !truncated_) 290 if (partial_ && !truncated_)
248 return true; 291 return true;
249 292
250 if (!CanResume(true)) 293 if (!cache_->CanResumeEntry(true, request_->method, &response_, entry_))
251 return false; 294 return false;
252 295
253 // We may have received the whole resource already. 296 // We may have received the whole resource already.
254 if (done_reading_) 297 if (done_reading_)
255 return true; 298 return true;
256 299
257 truncated_ = true; 300 truncated_ = true;
258 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE; 301 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE;
259 DoLoop(OK); 302 DoLoop(OK);
260 return true; 303 return true;
261 } 304 }
262 305
263 LoadState HttpCache::Transaction::GetWriterLoadState() const { 306 LoadState HttpCache::Transaction::GetWriterLoadState() const {
264 if (network_trans_.get()) 307 HttpTransaction* network_transaction = GetCurrentNetworkTransaction();
265 return network_trans_->GetLoadState(); 308 if (network_transaction)
309 return network_transaction->GetLoadState();
266 if (entry_ || !request_) 310 if (entry_ || !request_)
267 return LOAD_STATE_IDLE; 311 return LOAD_STATE_IDLE;
268 return LOAD_STATE_WAITING_FOR_CACHE; 312 return LOAD_STATE_WAITING_FOR_CACHE;
269 } 313 }
270 314
271 const NetLogWithSource& HttpCache::Transaction::net_log() const { 315 const NetLogWithSource& HttpCache::Transaction::net_log() const {
272 return net_log_; 316 return net_log_;
273 } 317 }
274 318
275 int HttpCache::Transaction::Start(const HttpRequestInfo* request, 319 int HttpCache::Transaction::Start(const HttpRequestInfo* request,
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 } 409 }
366 410
367 bool HttpCache::Transaction::IsReadyToRestartForAuth() { 411 bool HttpCache::Transaction::IsReadyToRestartForAuth() {
368 if (!network_trans_.get()) 412 if (!network_trans_.get())
369 return false; 413 return false;
370 return network_trans_->IsReadyToRestartForAuth(); 414 return network_trans_->IsReadyToRestartForAuth();
371 } 415 }
372 416
373 int HttpCache::Transaction::Read(IOBuffer* buf, int buf_len, 417 int HttpCache::Transaction::Read(IOBuffer* buf, int buf_len,
374 const CompletionCallback& callback) { 418 const CompletionCallback& callback) {
419 if (next_state_ == STATE_SHARED_READ_WRITE_FAILED) {
420 if (net_log_.IsCapturing())
421 net_log_.EndEventWithNetErrorCode(
422 NetLogEventType::HTTP_CACHE_SHARED_READ_WRITE_FAILED,
423 shared_read_write_failure_result_);
424
425 return shared_read_write_failure_result_;
426 }
427
375 DCHECK_EQ(next_state_, STATE_NONE); 428 DCHECK_EQ(next_state_, STATE_NONE);
376 DCHECK(buf); 429 DCHECK(buf);
377 DCHECK_GT(buf_len, 0); 430 DCHECK_GT(buf_len, 0);
378 DCHECK(!callback.is_null()); 431 DCHECK(!callback.is_null());
379 432
380 DCHECK(callback_.is_null()); 433 DCHECK(callback_.is_null());
381 434
382 if (!cache_.get()) 435 if (!cache_.get())
383 return ERR_UNEXPECTED; 436 return ERR_UNEXPECTED;
384 437
385 // If we have an intermediate auth response at this point, then it means the 438 // 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 439 // 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. 440 // previous response in the cache then we should leave it intact.
388 if (auth_response_.headers.get() && mode_ != NONE) { 441 if (auth_response_.headers.get() && mode_ != NONE) {
389 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER); 442 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_OTHER);
390 DCHECK(mode_ & WRITE); 443 DCHECK(mode_ & WRITE);
391 DoneWritingToEntry(mode_ == READ_WRITE); 444 DoneWritingToEntry(mode_ == READ_WRITE);
392 mode_ = NONE; 445 mode_ = NONE;
393 } 446 }
394 447
395 reading_ = true; 448 reading_ = true;
396 read_buf_ = buf; 449 read_buf_ = buf;
397 io_buf_len_ = buf_len; 450 io_buf_len_ = buf_len;
398 if (network_trans_) { 451
399 DCHECK(mode_ == WRITE || mode_ == NONE || 452 if (shared_) {
400 (mode_ == READ_WRITE && partial_)); 453 int disk_entry_size =
401 next_state_ = STATE_NETWORK_READ; 454 entry_->disk_entry->GetDataSize(kResponseContentIndex);
402 } else { 455 if (read_offset_ == disk_entry_size) {
403 DCHECK(mode_ == READ || (mode_ == READ_WRITE && partial_)); 456 next_state_ = STATE_SHARED_NETWORK_READ;
404 next_state_ = STATE_CACHE_READ_DATA; 457 } else {
458 DCHECK_LT(read_offset_, disk_entry_size);
459 next_state_ = STATE_CACHE_READ_DATA;
460 }
461 } else { // not shared.
462 if (network_trans_ || data_access_) {
463 DCHECK(mode_ == WRITE || mode_ == NONE ||
464 (mode_ == READ_WRITE && partial_));
465 next_state_ = STATE_NETWORK_READ;
466 } else { // read-only
467 DCHECK(mode_ == READ || (mode_ == READ_WRITE && partial_));
468 next_state_ = STATE_CACHE_READ_DATA;
469 }
405 } 470 }
406 471
407 int rv = DoLoop(OK); 472 int rv = DoLoop(OK);
408 473
409 if (rv == ERR_IO_PENDING) { 474 if (rv == ERR_IO_PENDING) {
410 DCHECK(callback_.is_null()); 475 DCHECK(callback_.is_null());
411 callback_ = callback; 476 callback_ = callback;
412 } 477 }
413 return rv; 478 return rv;
414 } 479 }
415 480
416 void HttpCache::Transaction::StopCaching() { 481 void HttpCache::Transaction::StopCaching() {
417 // We really don't know where we are now. Hopefully there is no operation in 482 // 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 483 // 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 484 // 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 485 // 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 486 // 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 487 // 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 488 // the next piece of code that executes know that we are now reading directly
424 // from the net. 489 // from the net.
425 // TODO(mmenke): This doesn't release the lock on the cache entry, so a 490 // 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. 491 // future request for the resource will be blocked on this one.
427 // Fix this. 492 // Fix this.
428 if (cache_.get() && entry_ && (mode_ & WRITE) && network_trans_.get() && 493 if (shared_) {
429 !is_sparse_ && !range_requested_) { 494 // This might or might not stop caching based on whether other consumers
495 // exist for this resource or not. If it does, shared_ will be set to false.
496 cache_->StopCachingSharedWriters(this, entry_);
Randy Smith (Not in Mondays) 2017/01/19 00:53:43 Why not delegate to entry_->shared_writers? That
shivanisha 2017/01/19 21:13:06 Going through HttpCache in this case basically ens
Randy Smith (Not in Mondays) 2017/01/20 19:54:31 Meaning that StopCachingSharedWriters() might dest
shivanisha 2017/01/25 19:46:13 Done. (Response in detail in the higher level feed
497 }
498 if (!shared_ && cache_.get() && entry_ && (mode_ & WRITE) &&
499 network_trans_.get() && !is_sparse_ && !range_requested_) {
430 mode_ = NONE; 500 mode_ = NONE;
431 } 501 }
432 } 502 }
433 503
434 bool HttpCache::Transaction::GetFullRequestHeaders( 504 bool HttpCache::Transaction::GetFullRequestHeaders(
435 HttpRequestHeaders* headers) const { 505 HttpRequestHeaders* headers) const {
436 if (network_trans_) 506 HttpTransaction* network_transaction = GetCurrentNetworkTransaction();
437 return network_trans_->GetFullRequestHeaders(headers); 507 if (network_transaction) {
438 508 return network_transaction->GetFullRequestHeaders(headers);
509 } else if (have_full_request_headers_) {
510 *headers = full_request_headers_;
511 return true;
512 }
439 // TODO(juliatuttle): Read headers from cache. 513 // TODO(juliatuttle): Read headers from cache.
440 return false; 514 return false;
441 } 515 }
442 516
443 int64_t HttpCache::Transaction::GetTotalReceivedBytes() const { 517 int64_t HttpCache::Transaction::GetTotalReceivedBytes() const {
444 int64_t total_received_bytes = total_received_bytes_; 518 int64_t total_received_bytes = total_received_bytes_;
445 if (network_trans_) 519 HttpTransaction* network_transaction = GetCurrentNetworkTransaction();
446 total_received_bytes += network_trans_->GetTotalReceivedBytes(); 520 if (network_transaction)
521 total_received_bytes += network_transaction->GetTotalReceivedBytes();
447 return total_received_bytes; 522 return total_received_bytes;
448 } 523 }
449 524
450 int64_t HttpCache::Transaction::GetTotalSentBytes() const { 525 int64_t HttpCache::Transaction::GetTotalSentBytes() const {
451 int64_t total_sent_bytes = total_sent_bytes_; 526 int64_t total_sent_bytes = total_sent_bytes_;
452 if (network_trans_) 527 HttpTransaction* network_transaction = GetCurrentNetworkTransaction();
453 total_sent_bytes += network_trans_->GetTotalSentBytes(); 528 if (network_transaction)
529 total_sent_bytes += network_transaction->GetTotalSentBytes();
454 return total_sent_bytes; 530 return total_sent_bytes;
455 } 531 }
456 532
457 void HttpCache::Transaction::DoneReading() { 533 void HttpCache::Transaction::DoneReading() {
458 if (cache_.get() && entry_) { 534 if (cache_.get() && entry_) {
459 DCHECK_NE(mode_, UPDATE); 535 DCHECK_NE(mode_, UPDATE);
536 bool perform_entry_cleanup = true;
537 if (shared_) {
538 cache_->DoneReadingSharedWriters(this, entry_);
539
540 // shared_ should have been set to false.
541 DCHECK(!shared_);
542
543 // entry_ cleanup already performed, if any.
544 perform_entry_cleanup = false;
545 }
546
460 if (mode_ & WRITE) { 547 if (mode_ & WRITE) {
461 DoneWritingToEntry(true); 548 DoneWritingToEntry(true, perform_entry_cleanup);
462 } else if (mode_ & READ) { 549 } else if (mode_ & READ) {
463 // It is necessary to check mode_ & READ because it is possible 550 // 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 551 // for mode_ to be NONE and entry_ non-NULL with a write entry
465 // if StopCaching was called. 552 // if StopCaching was called.
466 cache_->DoneReadingFromEntry(entry_, this); 553 cache_->DoneReadingFromEntry(entry_, this);
467 entry_ = NULL; 554 entry_ = NULL;
468 } 555 }
469 } 556 }
470 } 557 }
471 558
(...skipping 18 matching lines...) Expand all
490 return cache_->GetLoadStateForPendingTransaction(this); 577 return cache_->GetLoadStateForPendingTransaction(this);
491 578
492 return LOAD_STATE_IDLE; 579 return LOAD_STATE_IDLE;
493 } 580 }
494 581
495 void HttpCache::Transaction::SetQuicServerInfo( 582 void HttpCache::Transaction::SetQuicServerInfo(
496 QuicServerInfo* quic_server_info) {} 583 QuicServerInfo* quic_server_info) {}
497 584
498 bool HttpCache::Transaction::GetLoadTimingInfo( 585 bool HttpCache::Transaction::GetLoadTimingInfo(
499 LoadTimingInfo* load_timing_info) const { 586 LoadTimingInfo* load_timing_info) const {
500 if (network_trans_) 587 HttpTransaction* network_transaction = GetCurrentNetworkTransaction();
501 return network_trans_->GetLoadTimingInfo(load_timing_info); 588 if (network_transaction)
589 return network_transaction->GetLoadTimingInfo(load_timing_info);
502 590
503 if (old_network_trans_load_timing_) { 591 if (old_network_trans_load_timing_) {
504 *load_timing_info = *old_network_trans_load_timing_; 592 *load_timing_info = *old_network_trans_load_timing_;
505 return true; 593 return true;
506 } 594 }
507 595
508 if (first_cache_access_since_.is_null()) 596 if (first_cache_access_since_.is_null())
509 return false; 597 return false;
510 598
511 // If the cache entry was opened, return that time. 599 // If the cache entry was opened, return that time.
512 load_timing_info->send_start = first_cache_access_since_; 600 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 601 // This time doesn't make much sense when reading from the cache, so just use
514 // the same time as send_start. 602 // the same time as send_start.
515 load_timing_info->send_end = first_cache_access_since_; 603 load_timing_info->send_end = first_cache_access_since_;
516 return true; 604 return true;
517 } 605 }
518 606
519 bool HttpCache::Transaction::GetRemoteEndpoint(IPEndPoint* endpoint) const { 607 bool HttpCache::Transaction::GetRemoteEndpoint(IPEndPoint* endpoint) const {
520 if (network_trans_) 608 HttpTransaction* network_transaction = GetCurrentNetworkTransaction();
521 return network_trans_->GetRemoteEndpoint(endpoint); 609 if (network_transaction)
610 return network_transaction->GetRemoteEndpoint(endpoint);
522 611
523 if (!old_remote_endpoint_.address().empty()) { 612 if (!old_remote_endpoint_.address().empty()) {
524 *endpoint = old_remote_endpoint_; 613 *endpoint = old_remote_endpoint_;
525 return true; 614 return true;
526 } 615 }
527 616
528 return false; 617 return false;
529 } 618 }
530 619
531 void HttpCache::Transaction::PopulateNetErrorDetails( 620 void HttpCache::Transaction::PopulateNetErrorDetails(
532 NetErrorDetails* details) const { 621 NetErrorDetails* details) const {
533 if (network_trans_) 622 HttpTransaction* network_transaction = GetCurrentNetworkTransaction();
534 return network_trans_->PopulateNetErrorDetails(details); 623 if (network_transaction)
624 network_transaction->PopulateNetErrorDetails(details);
535 return; 625 return;
536 } 626 }
537 627
538 void HttpCache::Transaction::SetPriority(RequestPriority priority) { 628 void HttpCache::Transaction::SetPriority(RequestPriority priority) {
539 priority_ = priority; 629 priority_ = priority;
540 if (network_trans_) 630 HttpTransaction* network_transaction = GetCurrentNetworkTransaction();
541 network_trans_->SetPriority(priority_); 631 if (network_transaction)
632 network_transaction->SetPriority(priority_);
542 } 633 }
543 634
544 void HttpCache::Transaction::SetWebSocketHandshakeStreamCreateHelper( 635 void HttpCache::Transaction::SetWebSocketHandshakeStreamCreateHelper(
545 WebSocketHandshakeStreamBase::CreateHelper* create_helper) { 636 WebSocketHandshakeStreamBase::CreateHelper* create_helper) {
546 websocket_handshake_stream_base_create_helper_ = create_helper; 637 websocket_handshake_stream_base_create_helper_ = create_helper;
547 if (network_trans_) 638 HttpTransaction* network_transaction = GetCurrentNetworkTransaction();
548 network_trans_->SetWebSocketHandshakeStreamCreateHelper(create_helper); 639 if (network_transaction)
640 network_transaction->SetWebSocketHandshakeStreamCreateHelper(create_helper);
549 } 641 }
550 642
551 void HttpCache::Transaction::SetBeforeNetworkStartCallback( 643 void HttpCache::Transaction::SetBeforeNetworkStartCallback(
552 const BeforeNetworkStartCallback& callback) { 644 const BeforeNetworkStartCallback& callback) {
553 DCHECK(!network_trans_); 645 DCHECK(!network_trans_);
554 before_network_start_callback_ = callback; 646 before_network_start_callback_ = callback;
555 } 647 }
556 648
557 void HttpCache::Transaction::SetBeforeHeadersSentCallback( 649 void HttpCache::Transaction::SetBeforeHeadersSentCallback(
558 const BeforeHeadersSentCallback& callback) { 650 const BeforeHeadersSentCallback& callback) {
559 DCHECK(!network_trans_); 651 DCHECK(!network_trans_);
560 before_headers_sent_callback_ = callback; 652 before_headers_sent_callback_ = callback;
561 } 653 }
562 654
563 int HttpCache::Transaction::ResumeNetworkStart() { 655 int HttpCache::Transaction::ResumeNetworkStart() {
564 if (network_trans_) 656 HttpTransaction* network_transaction = GetCurrentNetworkTransaction();
565 return network_trans_->ResumeNetworkStart(); 657 if (network_transaction)
658 network_transaction->ResumeNetworkStart();
566 return ERR_UNEXPECTED; 659 return ERR_UNEXPECTED;
567 } 660 }
568 661
569 void HttpCache::Transaction::GetConnectionAttempts( 662 void HttpCache::Transaction::GetConnectionAttempts(
570 ConnectionAttempts* out) const { 663 ConnectionAttempts* out) const {
571 ConnectionAttempts new_connection_attempts; 664 ConnectionAttempts new_connection_attempts;
572 if (network_trans_) 665 HttpTransaction* network_transaction = GetCurrentNetworkTransaction();
573 network_trans_->GetConnectionAttempts(&new_connection_attempts); 666 if (network_transaction)
667 network_transaction->GetConnectionAttempts(&new_connection_attempts);
574 668
575 out->swap(new_connection_attempts); 669 out->swap(new_connection_attempts);
576 out->insert(out->begin(), old_connection_attempts_.begin(), 670 out->insert(out->begin(), old_connection_attempts_.begin(),
577 old_connection_attempts_.end()); 671 old_connection_attempts_.end());
578 } 672 }
579 673
580 //----------------------------------------------------------------------------- 674 //-----------------------------------------------------------------------------
581 675
582 // A few common patterns: (Foo* means Foo -> FooComplete) 676 // A few common patterns: (Foo* means Foo -> FooComplete)
583 // 677 //
584 // 1. Not-cached entry: 678 // 1. Not-cached entry:
585 // Start(): 679 // Start():
586 // GetBackend* -> InitEntry -> OpenEntry* -> CreateEntry* -> AddToEntry* -> 680 // GetBackend* -> InitEntry -> OpenEntry* -> CreateEntry* -> AddToEntry* ->
587 // SendRequest* -> SuccessfulSendRequest -> OverwriteCachedResponse -> 681 // SendRequest* -> SuccessfulSendRequest -> OverwriteCachedResponse ->
588 // CacheWriteResponse* -> TruncateCachedData* -> TruncateCachedMetadata* -> 682 // CacheWriteResponse* -> TruncateCachedData* -> TruncateCachedMetadata* ->
589 // PartialHeadersReceived 683 // PartialHeadersReceived
590 // 684 //
591 // Read(): 685 // Read(): (For transactions that are not eligible for shared writing)
592 // NetworkRead* -> CacheWriteData* 686 // NetworkRead* -> CacheWriteData*
593 // 687 //
688 // Read(): (For transactions that are eligible for shared writing)
689 // SharedNetworkRead* -> SharedCacheWriteData*
690 //
691 // Read(): (For a transaction that is shared and another read is already in
692 // progress)
693 // SharedNetworkRead -> SharedNetworkReadWaitComplete
694 //
594 // 2. Cached entry, no validation: 695 // 2. Cached entry, no validation:
595 // Start(): 696 // Start():
596 // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse* 697 // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse*
597 // -> CacheDispatchValidation -> BeginPartialCacheValidation() -> 698 // -> CacheDispatchValidation -> BeginPartialCacheValidation() ->
598 // BeginCacheValidation() -> SetupEntryForRead() 699 // BeginCacheValidation() -> SetupEntryForRead()
599 // 700 //
600 // Read(): 701 // Read(): (When response is already written to the cache.)
601 // CacheReadData* 702 // CacheReadData*
602 // 703 //
704 // Read(): (When response is currently being written to the cache by shared
705 // writing.)
706 // SharedNetworkRead* -> SharedCacheWriteData*
707 //
603 // 3. Cached entry, validation (304): 708 // 3. Cached entry, validation (304):
604 // Start(): 709 // Start():
605 // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse* 710 // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse*
606 // -> CacheDispatchValidation -> BeginPartialCacheValidation() -> 711 // -> CacheDispatchValidation -> BeginPartialCacheValidation() ->
607 // BeginCacheValidation() -> SendRequest* -> SuccessfulSendRequest -> 712 // BeginCacheValidation() -> SendRequest* -> SuccessfulSendRequest ->
608 // UpdateCachedResponse -> CacheWriteUpdatedResponse* -> 713 // UpdateCachedResponse -> CacheWriteUpdatedResponse* ->
609 // UpdateCachedResponseComplete -> OverwriteCachedResponse -> 714 // UpdateCachedResponseComplete -> OverwriteCachedResponse ->
610 // PartialHeadersReceived 715 // PartialHeadersReceived
611 // 716 //
612 // Read(): 717 // Read(): () (When response is already written to the cache.)
613 // CacheReadData* 718 // CacheReadData*
614 // 719 //
720 // Read(): (When response is currently being written to the cache by shared
721 // writing.)
722 // SharedNetworkRead* -> SharedCacheWriteData*
723 //
615 // 4. Cached entry, validation and replace (200): 724 // 4. Cached entry, validation and replace (200):
616 // Start(): 725 // Start():
617 // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse* 726 // GetBackend* -> InitEntry -> OpenEntry* -> AddToEntry* -> CacheReadResponse*
618 // -> CacheDispatchValidation -> BeginPartialCacheValidation() -> 727 // -> CacheDispatchValidation -> BeginPartialCacheValidation() ->
619 // BeginCacheValidation() -> SendRequest* -> SuccessfulSendRequest -> 728 // BeginCacheValidation() -> SendRequest* -> SuccessfulSendRequest ->
620 // OverwriteCachedResponse -> CacheWriteResponse* -> DoTruncateCachedData* -> 729 // OverwriteCachedResponse -> CacheWriteResponse* -> DoTruncateCachedData* ->
621 // TruncateCachedMetadata* -> PartialHeadersReceived 730 // TruncateCachedMetadata* -> PartialHeadersReceived
622 // 731 //
623 // Read(): 732 // Read():
624 // NetworkRead* -> CacheWriteData* 733 // NetworkRead* -> CacheWriteData*
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
699 // -> CacheToggleUnusedSincePrefetch* -> CacheDispatchValidation -> 808 // -> CacheToggleUnusedSincePrefetch* -> CacheDispatchValidation ->
700 // BeginPartialCacheValidation() -> BeginCacheValidation() -> 809 // BeginPartialCacheValidation() -> BeginCacheValidation() ->
701 // SetupEntryForRead() 810 // SetupEntryForRead()
702 // 811 //
703 // Read(): 812 // Read():
704 // CacheReadData* 813 // CacheReadData*
705 // 814 //
706 // 14. Cached entry more than 5 minutes old, unused_since_prefetch is true: 815 // 14. Cached entry more than 5 minutes old, unused_since_prefetch is true:
707 // Like examples 2-4, only CacheToggleUnusedSincePrefetch* is inserted between 816 // Like examples 2-4, only CacheToggleUnusedSincePrefetch* is inserted between
708 // CacheReadResponse* and CacheDispatchValidation. 817 // CacheReadResponse* and CacheDispatchValidation.
818 //
709 int HttpCache::Transaction::DoLoop(int result) { 819 int HttpCache::Transaction::DoLoop(int result) {
710 DCHECK(next_state_ != STATE_NONE); 820 DCHECK(next_state_ != STATE_NONE);
711 821
712 int rv = result; 822 int rv = result;
713 do { 823 do {
714 State state = next_state_; 824 State state = next_state_;
715 next_state_ = STATE_NONE; 825 next_state_ = STATE_NONE;
716 switch (state) { 826 switch (state) {
717 case STATE_GET_BACKEND: 827 case STATE_GET_BACKEND:
718 DCHECK_EQ(OK, rv); 828 DCHECK_EQ(OK, rv);
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
866 case STATE_CACHE_WRITE_DATA_COMPLETE: 976 case STATE_CACHE_WRITE_DATA_COMPLETE:
867 rv = DoCacheWriteDataComplete(rv); 977 rv = DoCacheWriteDataComplete(rv);
868 break; 978 break;
869 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE: 979 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE:
870 DCHECK_EQ(OK, rv); 980 DCHECK_EQ(OK, rv);
871 rv = DoCacheWriteTruncatedResponse(); 981 rv = DoCacheWriteTruncatedResponse();
872 break; 982 break;
873 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE: 983 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE:
874 rv = DoCacheWriteTruncatedResponseComplete(rv); 984 rv = DoCacheWriteTruncatedResponseComplete(rv);
875 break; 985 break;
986 case STATE_SHARED_NETWORK_READ:
987 DCHECK_EQ(OK, rv);
988 rv = DoSharedNetworkRead();
989 break;
990 case STATE_SHARED_NETWORK_READ_COMPLETE:
991 rv = DoSharedNetworkReadComplete(rv);
992 break;
993 case STATE_SHARED_NETWORK_READ_WAIT_COMPLETE:
994 rv = DoSharedNetworkReadWaitComplete(rv);
995 break;
996 case STATE_SHARED_CACHE_WRITE_DATA:
997 rv = DoSharedCacheWriteData(rv);
998 break;
999 case STATE_SHARED_CACHE_WRITE_DATA_COMPLETE:
1000 rv = DoSharedCacheWriteDataComplete(rv);
1001 break;
1002 case STATE_SHARED_READ_WRITE_FAILED:
1003 rv = DoSharedReadWriteFailed();
1004 break;
876 default: 1005 default:
877 NOTREACHED() << "bad state"; 1006 NOTREACHED() << "bad state";
878 rv = ERR_FAILED; 1007 rv = ERR_FAILED;
879 break; 1008 break;
880 } 1009 }
881 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 1010 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
882 1011
883 if (rv != ERR_IO_PENDING && !callback_.is_null()) { 1012 if (rv != ERR_IO_PENDING && !callback_.is_null()) {
884 read_buf_ = NULL; // Release the buffer before invoking the callback. 1013 read_buf_ = NULL; // Release the buffer before invoking the callback.
885 base::ResetAndReturn(&callback_).Run(rv); 1014 base::ResetAndReturn(&callback_).Run(rv);
(...skipping 617 matching lines...) Expand 10 before | Expand all | Expand 10 after
1503 1632
1504 RecordNoStoreHeaderHistogram(request_->load_flags, new_response); 1633 RecordNoStoreHeaderHistogram(request_->load_flags, new_response);
1505 1634
1506 if (new_response_->headers->response_code() == 416 && 1635 if (new_response_->headers->response_code() == 416 &&
1507 (request_->method == "GET" || request_->method == "POST")) { 1636 (request_->method == "GET" || request_->method == "POST")) {
1508 // If there is an active entry it may be destroyed with this transaction. 1637 // If there is an active entry it may be destroyed with this transaction.
1509 SetResponse(*new_response_); 1638 SetResponse(*new_response_);
1510 return OK; 1639 return OK;
1511 } 1640 }
1512 1641
1642 // If the transaction is shared and it is a 200 or an error response, then
1643 // doom the entry and let this transaction continue without writing to the
1644 // cache if shared writers contain more transactions. If not, continue
1645 // writing to the cache and also transfer the network transaction to shared
1646 // writers.
1647 if (shared_ && new_response->headers->response_code() != 304) {
1648 network_trans_ = cache_->ValidationNoMatchSharedWriters(
1649 cache_key_, this, std::move(network_trans_), priority_, entry_);
1650 if (!shared_) {
1651 DCHECK(network_trans_);
1652 if (cache_entry_status_ == CacheEntryStatus::ENTRY_UNDEFINED) {
1653 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_DOOM_SHARED_WRITING);
1654 }
1655 DoneWritingToEntry(false, false);
1656 return OK;
1657 } else {
1658 DCHECK(!network_trans_);
1659 }
1660 }
1661
1513 // Are we expecting a response to a conditional query? 1662 // Are we expecting a response to a conditional query?
1514 if (mode_ == READ_WRITE || mode_ == UPDATE) { 1663 if (mode_ == READ_WRITE || mode_ == UPDATE) {
1515 if (new_response->headers->response_code() == 304 || handling_206_) { 1664 if (new_response->headers->response_code() == 304 || handling_206_) {
1516 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_VALIDATED); 1665 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_VALIDATED);
1517 next_state_ = STATE_UPDATE_CACHED_RESPONSE; 1666 next_state_ = STATE_UPDATE_CACHED_RESPONSE;
1518 return OK; 1667 return OK;
1519 } 1668 }
1520 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_UPDATED); 1669 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_UPDATED);
1521 mode_ = WRITE; 1670 mode_ = WRITE;
1522 } 1671 }
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1625 SetResponse(*new_response_); 1774 SetResponse(*new_response_);
1626 1775
1627 if (request_->method == "HEAD") { 1776 if (request_->method == "HEAD") {
1628 // This response is replacing the cached one. 1777 // This response is replacing the cached one.
1629 DoneWritingToEntry(false); 1778 DoneWritingToEntry(false);
1630 mode_ = NONE; 1779 mode_ = NONE;
1631 new_response_ = NULL; 1780 new_response_ = NULL;
1632 return OK; 1781 return OK;
1633 } 1782 }
1634 1783
1635 if (handling_206_ && !CanResume(false)) { 1784 if (handling_206_ &&
1785 !cache_->CanResumeEntry(false, request_->method, &response_, entry_)) {
1636 // There is no point in storing this resource because it will never be used. 1786 // 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. 1787 // This may change if we support LOAD_ONLY_FROM_CACHE with sparse entries.
1638 DoneWritingToEntry(false); 1788 DoneWritingToEntry(false);
1639 if (partial_) 1789 if (partial_)
1640 partial_->FixResponseHeaders(response_.headers.get(), true); 1790 partial_->FixResponseHeaders(response_.headers.get(), true);
1641 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED; 1791 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
1642 return OK; 1792 return OK;
1643 } 1793 }
1644 1794
1645 next_state_ = STATE_CACHE_WRITE_RESPONSE; 1795 next_state_ = STATE_CACHE_WRITE_RESPONSE;
1646 return OK; 1796 return OK;
1647 } 1797 }
1648 1798
1649 int HttpCache::Transaction::DoCacheWriteResponse() { 1799 int HttpCache::Transaction::DoCacheWriteResponse() {
1650 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponse"); 1800 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponse");
1651 next_state_ = STATE_CACHE_WRITE_RESPONSE_COMPLETE; 1801 next_state_ = STATE_CACHE_WRITE_RESPONSE_COMPLETE;
1652 return WriteResponseInfoToEntry(truncated_); 1802 return WriteResponseInfoToEntry(truncated_);
1653 } 1803 }
1654 1804
1655 int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) { 1805 int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) {
1656 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponseComplete"); 1806 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponseComplete");
1657 next_state_ = STATE_TRUNCATE_CACHED_DATA; 1807 next_state_ = STATE_TRUNCATE_CACHED_DATA;
1658 return OnWriteResponseInfoToEntryComplete(result); 1808 return OnWriteResponseInfoToEntryComplete(result);
1659 } 1809 }
1660 1810
1811 void HttpCache::Transaction::ResetShared(bool continue_network_reading,
1812 bool continue_cache_reading) {
1813 if (!continue_network_reading) {
1814 SaveSharedNetworkTransactionInfo();
1815 }
1816 if (continue_cache_reading) {
1817 mode_ = READ;
1818 }
1819 shared_ = false;
1820 }
1821
1822 void HttpCache::Transaction::SetShared() {
1823 shared_ = true;
1824 }
1825
1826 bool HttpCache::Transaction::validating_shared() const {
1827 return shared_ && next_state_ != STATE_NONE &&
1828 next_state_ <= STATE_START_STATE_MACHINE_FINAL;
1829 }
1830
1661 int HttpCache::Transaction::DoTruncateCachedData() { 1831 int HttpCache::Transaction::DoTruncateCachedData() {
1662 TRACE_EVENT0("io", "HttpCacheTransaction::DoTruncateCachedData"); 1832 TRACE_EVENT0("io", "HttpCacheTransaction::DoTruncateCachedData");
1663 next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE; 1833 next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE;
1664 if (!entry_) 1834 if (!entry_)
1665 return OK; 1835 return OK;
1666 if (net_log_.IsCapturing()) 1836 if (net_log_.IsCapturing())
1667 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_WRITE_DATA); 1837 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_WRITE_DATA);
1668 // Truncate the stream. 1838 // Truncate the stream.
1669 return WriteToEntry(kResponseContentIndex, 0, NULL, 0, io_callback_); 1839 return WriteToEntry(kResponseContentIndex, 0, NULL, 0, io_callback_);
1670 } 1840 }
(...skipping 28 matching lines...) Expand all
1699 if (net_log_.IsCapturing()) { 1869 if (net_log_.IsCapturing()) {
1700 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO, 1870 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO,
1701 result); 1871 result);
1702 } 1872 }
1703 } 1873 }
1704 1874
1705 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED; 1875 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
1706 return OK; 1876 return OK;
1707 } 1877 }
1708 1878
1879 void HttpCache::Transaction::ProcessForSharedWriting() {
1880 // Should not be already reading.
1881 if (reading_)
1882 return;
1883
1884 // If not already part of SharedWriters, then check if one should be
1885 // created.
1886 if (!shared_ && !IsEligibleForSharedWriting())
1887 return;
1888
1889 if (shared_) {
1890 // Non 304 case is already handled in DoSuccessfulSendRequest.
1891 if (response_.headers->response_code() != 304) {
1892 return;
1893 }
1894 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_JOIN_SHARED_WRITING);
1895 entry_->shared_writers->OnValidationMatch(this, priority_);
1896 network_trans_.reset();
1897 return;
1898 }
1899
1900 // Do not create a SharedWriters if its a Redirect response.
1901 if (response_.headers->response_code() != 200)
1902 return;
1903
1904 // or if its a no-store response.
1905 if (!entry_)
1906 return;
1907
1908 DCHECK(cache_entry_status_ == CacheEntryStatus::ENTRY_NOT_IN_CACHE ||
1909 cache_entry_status_ == CacheEntryStatus::ENTRY_UPDATED ||
1910 cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE ||
1911 cache_entry_status_ == CacheEntryStatus::ENTRY_OTHER);
1912 // Measure how many requests out of the total of "not cached" and "updated"
1913 // are initiating Shared Writing.
1914 initiate_shared_writing_ = true;
1915 DCHECK(entry_ && network_trans_);
1916 cache_->CreateSharedWriters(this, std::move(network_trans_), priority_);
1917 }
1918
1709 int HttpCache::Transaction::DoPartialHeadersReceived() { 1919 int HttpCache::Transaction::DoPartialHeadersReceived() {
1710 new_response_ = NULL; 1920 new_response_ = NULL;
1711 if (entry_ && !partial_ && entry_->disk_entry->GetDataSize(kMetadataIndex)) 1921 if (entry_ && !partial_ && entry_->disk_entry->GetDataSize(kMetadataIndex))
1712 next_state_ = STATE_CACHE_READ_METADATA; 1922 next_state_ = STATE_CACHE_READ_METADATA;
1713 1923
1924 ProcessForSharedWriting();
1925
1714 if (!partial_) 1926 if (!partial_)
1715 return OK; 1927 return OK;
1716 1928
1717 if (reading_) { 1929 if (reading_) {
1718 if (network_trans_.get()) { 1930 if (network_trans_.get()) {
1719 next_state_ = STATE_NETWORK_READ; 1931 next_state_ = STATE_NETWORK_READ;
1720 } else { 1932 } else {
1721 next_state_ = STATE_CACHE_READ_DATA; 1933 next_state_ = STATE_CACHE_READ_DATA;
1722 } 1934 }
1723 } else if (mode_ != NONE) { 1935 } else if (mode_ != NONE) {
(...skipping 25 matching lines...) Expand all
1749 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_READ_INFO, 1961 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_READ_INFO,
1750 result); 1962 result);
1751 if (result != response_.metadata->size()) 1963 if (result != response_.metadata->size())
1752 return OnCacheReadError(result, false); 1964 return OnCacheReadError(result, false);
1753 return OK; 1965 return OK;
1754 } 1966 }
1755 1967
1756 int HttpCache::Transaction::DoNetworkRead() { 1968 int HttpCache::Transaction::DoNetworkRead() {
1757 TRACE_EVENT0("io", "HttpCacheTransaction::DoNetworkRead"); 1969 TRACE_EVENT0("io", "HttpCacheTransaction::DoNetworkRead");
1758 next_state_ = STATE_NETWORK_READ_COMPLETE; 1970 next_state_ = STATE_NETWORK_READ_COMPLETE;
1759 return network_trans_->Read(read_buf_.get(), io_buf_len_, io_callback_); 1971 if (!data_access_) {
1972 DCHECK(network_trans_);
1973 // Create a DataAccess object if not already done.
1974 data_access_ =
1975 base::MakeUnique<DataAccess>(std::move(network_trans_), entry_);
1976 }
1977 return data_access_->Read(read_buf_, io_buf_len_, io_callback_);
1760 } 1978 }
1761 1979
1762 int HttpCache::Transaction::DoNetworkReadComplete(int result) { 1980 int HttpCache::Transaction::DoNetworkReadComplete(int result) {
1763 TRACE_EVENT0("io", "HttpCacheTransaction::DoNetworkReadComplete"); 1981 TRACE_EVENT0("io", "HttpCacheTransaction::DoNetworkReadComplete");
1982 if (net_log_.IsCapturing())
1983 net_log_.EndEventWithNetErrorCode(
1984 NetLogEventType::HTTP_CACHE_NETWORK_READ_COMPLETE, result);
1985
1764 DCHECK(mode_ & WRITE || mode_ == NONE); 1986 DCHECK(mode_ & WRITE || mode_ == NONE);
1765 1987
1766 if (!cache_.get()) 1988 if (!cache_.get())
1767 return ERR_UNEXPECTED; 1989 return ERR_UNEXPECTED;
1768 1990
1769 // If there is an error or we aren't saving the data, we are done; just wait 1991 // 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. 1992 // until the destructor runs to see if we can keep the data.
1771 if (mode_ == NONE || result < 0) 1993 if (mode_ == NONE || result < 0)
1772 return result; 1994 return result;
1773 1995
1774 next_state_ = STATE_CACHE_WRITE_DATA; 1996 next_state_ = STATE_CACHE_WRITE_DATA;
1775 return result; 1997 return result;
1776 } 1998 }
1777 1999
2000 int HttpCache::Transaction::DoSharedNetworkRead() {
2001 TRACE_EVENT0("io", "HttpCacheTransaction::DoSharedNetworkRead");
2002 if (net_log_.IsCapturing())
2003 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_SHARED_NETWORK_READ);
2004
2005 next_state_ = STATE_SHARED_NETWORK_READ_COMPLETE;
2006 bool shared_read_in_progress = false;
2007 int result = entry_->shared_writers->Read(
2008 read_buf_, io_buf_len_, io_callback_, this, &shared_read_in_progress);
2009 if (shared_read_in_progress) {
2010 next_state_ = STATE_SHARED_NETWORK_READ_WAIT_COMPLETE;
2011 }
2012 return result;
2013 }
2014
2015 int HttpCache::Transaction::DoSharedNetworkReadComplete(int result) {
2016 TRACE_EVENT0("io", "HttpCacheTransaction::DoSharedNetworkReadComplete");
2017 if (net_log_.IsCapturing())
2018 net_log_.EndEventWithNetErrorCode(
2019 NetLogEventType::HTTP_CACHE_SHARED_NETWORK_READ_COMPLETE, result);
2020
2021 if (result <= 0) {
2022 // Set entry as null so that the destructor does not invoke DoneWithEntry
2023 // again as entry_ is already cleaned up by SharedWriters.
2024 entry_ = nullptr;
2025 return result;
2026 }
2027
2028 read_offset_ += result;
2029
2030 next_state_ = STATE_SHARED_CACHE_WRITE_DATA;
2031 return result;
2032 }
2033
2034 int HttpCache::Transaction::DoSharedCacheWriteData(int result) {
2035 TRACE_EVENT0("io", "HttpCacheTransaction::DoSharedCacheWriteData");
2036 if (net_log_.IsCapturing())
2037 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_SHARED_CACHE_WRITE_DATA);
2038
2039 next_state_ = STATE_SHARED_CACHE_WRITE_DATA_COMPLETE;
2040 write_len_ = result;
2041 return entry_->shared_writers->CacheWrite(read_buf_, write_len_, io_callback_,
2042 this);
2043 }
2044
2045 int HttpCache::Transaction::DoSharedCacheWriteDataComplete(int result) {
2046 TRACE_EVENT0("io", "HttpCacheTransaction::DoSharedCacheWriteDataComplete");
2047 if (net_log_.IsCapturing())
2048 net_log_.EndEventWithNetErrorCode(
2049 NetLogEventType::HTTP_CACHE_SHARED_CACHE_WRITE_DATA_COMPLETE, result);
2050
2051 if (result != write_len_) {
2052 DoneWritingToEntry(false, false);
2053 // Consumer need not know that it was a failure since this transaction can
2054 // continue reading from the network.
2055 result = write_len_;
2056 } else {
2057 done_reading_ = cache_->IsResponseCompleted(entry_, &response_);
2058 if (result == 0) {
2059 DoneWritingToEntry(true, false);
2060 }
2061 }
2062 return result;
2063 }
2064
2065 int HttpCache::Transaction::DoSharedNetworkReadWaitComplete(int result) {
2066 TRACE_EVENT0("io", "HttpCacheTransaction::DoSharedNetworkReadWaitComplete");
2067 if (net_log_.IsCapturing())
2068 net_log_.EndEventWithNetErrorCode(
2069 NetLogEventType::HTTP_CACHE_SHARED_NETWORK_READ_WAIT_COMPLETE, result);
2070
2071 // If its a network read failure or cache write failure, we just return the
2072 // result.
2073 // If its a cache write success, read_buf_ would have been filled
2074 // with the read data by SharedWriters.
2075 if (result == 0) { // response is complete.
2076 DoneWritingToEntry(true, false); // changes the mode_ to NONE.
2077 } else if (result > 0) {
2078 read_offset_ += result;
2079 } else {
2080 // Set entry as null so that the destructor does not invoke DoneWithEntry
2081 // again as entry_ is already cleaned up by SharedWriters.
2082 entry_ = nullptr;
2083 }
2084
2085 return result;
2086 }
2087
1778 int HttpCache::Transaction::DoCacheReadData() { 2088 int HttpCache::Transaction::DoCacheReadData() {
1779 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheReadData"); 2089 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheReadData");
1780 if (request_->method == "HEAD") 2090 if (request_->method == "HEAD")
1781 return 0; 2091 return 0;
1782 2092
1783 DCHECK(entry_); 2093 DCHECK(entry_);
1784 next_state_ = STATE_CACHE_READ_DATA_COMPLETE; 2094 next_state_ = STATE_CACHE_READ_DATA_COMPLETE;
1785 2095
1786 if (net_log_.IsCapturing()) 2096 if (net_log_.IsCapturing())
1787 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_READ_DATA); 2097 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; 2139 next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE;
1830 write_len_ = num_bytes; 2140 write_len_ = num_bytes;
1831 if (entry_) { 2141 if (entry_) {
1832 if (net_log_.IsCapturing()) 2142 if (net_log_.IsCapturing())
1833 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_WRITE_DATA); 2143 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_WRITE_DATA);
1834 } 2144 }
1835 2145
1836 if (!entry_ || !num_bytes) 2146 if (!entry_ || !num_bytes)
1837 return num_bytes; 2147 return num_bytes;
1838 2148
1839 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); 2149 if (partial_) {
1840 return WriteToEntry(kResponseContentIndex, current_size, read_buf_.get(), 2150 return partial_->CacheWrite(entry_->disk_entry, read_buf_.get(), num_bytes,
1841 num_bytes, io_callback_); 2151 io_callback_);
2152 }
2153 DCHECK(data_access_);
2154 return data_access_->CacheWrite(read_buf_, num_bytes, io_callback_);
1842 } 2155 }
1843 2156
1844 int HttpCache::Transaction::DoCacheWriteDataComplete(int result) { 2157 int HttpCache::Transaction::DoCacheWriteDataComplete(int result) {
1845 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteDataComplete"); 2158 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteDataComplete");
1846 if (entry_) { 2159 if (entry_) {
1847 if (net_log_.IsCapturing()) { 2160 if (net_log_.IsCapturing()) {
1848 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_DATA, 2161 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_DATA,
1849 result); 2162 result);
1850 } 2163 }
1851 } 2164 }
1852 if (!cache_.get()) 2165 if (!cache_.get())
1853 return ERR_UNEXPECTED; 2166 return ERR_UNEXPECTED;
1854 2167
1855 if (result != write_len_) { 2168 if (result != write_len_) {
1856 DLOG(ERROR) << "failed to write response data to cache"; 2169 DLOG(ERROR) << "failed to write response data to cache";
1857 DoneWritingToEntry(false); 2170 DoneWritingToEntry(false);
1858 2171
1859 // We want to ignore errors writing to disk and just keep reading from 2172 // We want to ignore errors writing to disk and just keep reading from
1860 // the network. 2173 // the network.
1861 result = write_len_; 2174 result = write_len_;
1862 } else if (!done_reading_ && entry_ && (!partial_ || truncated_)) { 2175 } else if (!done_reading_ && entry_ && (!partial_ || truncated_)) {
1863 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); 2176 done_reading_ = cache_->IsResponseCompleted(entry_, &response_);
1864 int64_t body_size = response_.headers->GetContentLength();
1865 if (body_size >= 0 && body_size <= current_size)
1866 done_reading_ = true;
1867 } 2177 }
1868 2178
1869 if (partial_) { 2179 if (partial_) {
1870 // This may be the last request. 2180 // This may be the last request.
1871 if (result != 0 || truncated_ || 2181 if (result != 0 || truncated_ ||
1872 !(partial_->IsLastRange() || mode_ == WRITE)) { 2182 !(partial_->IsLastRange() || mode_ == WRITE)) {
1873 return DoPartialNetworkReadCompleted(result); 2183 return DoPartialNetworkReadCompleted(result);
1874 } 2184 }
1875 } 2185 }
1876 2186
2187 // End of file. This may be the result of a connection problem so see if we
2188 // have to keep the entry around to be flagged as truncated later on.
1877 if (result == 0) { 2189 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_ || 2190 if (done_reading_ || !entry_ || partial_ ||
1881 response_.headers->GetContentLength() <= 0) { 2191 response_.headers->GetContentLength() <= 0)
1882 DoneWritingToEntry(true); 2192 DoneWritingToEntry(true);
1883 }
1884 } 2193 }
1885 2194
1886 return result; 2195 return result;
1887 } 2196 }
1888 2197
1889 int HttpCache::Transaction::DoCacheWriteTruncatedResponse() { 2198 int HttpCache::Transaction::DoCacheWriteTruncatedResponse() {
1890 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteTruncatedResponse"); 2199 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteTruncatedResponse");
1891 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE; 2200 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE;
1892 return WriteResponseInfoToEntry(true); 2201 return WriteResponseInfoToEntry(true);
1893 } 2202 }
1894 2203
1895 int HttpCache::Transaction::DoCacheWriteTruncatedResponseComplete(int result) { 2204 int HttpCache::Transaction::DoCacheWriteTruncatedResponseComplete(int result) {
1896 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteTruncatedResponse"); 2205 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteTruncatedResponse");
1897 2206
1898 return OnWriteResponseInfoToEntryComplete(result); 2207 return OnWriteResponseInfoToEntryComplete(result);
1899 } 2208 }
1900 2209
2210 int HttpCache::Transaction::DoSharedReadWriteFailed() {
2211 if (net_log_.IsCapturing())
2212 net_log_.EndEventWithNetErrorCode(
2213 NetLogEventType::HTTP_CACHE_SHARED_READ_WRITE_FAILED,
2214 shared_read_write_failure_result_);
2215
2216 return shared_read_write_failure_result_;
2217 }
2218
1901 //----------------------------------------------------------------------------- 2219 //-----------------------------------------------------------------------------
1902 2220
1903 void HttpCache::Transaction::SetRequest(const NetLogWithSource& net_log, 2221 void HttpCache::Transaction::SetRequest(const NetLogWithSource& net_log,
1904 const HttpRequestInfo* request) { 2222 const HttpRequestInfo* request) {
1905 net_log_ = net_log; 2223 net_log_ = net_log;
1906 request_ = request; 2224 request_ = request;
1907 effective_load_flags_ = request_->load_flags; 2225 effective_load_flags_ = request_->load_flags;
1908 2226
1909 if (cache_->mode() == DISABLE) 2227 if (cache_->mode() == DISABLE)
1910 effective_load_flags_ |= LOAD_DISABLE_CACHE; 2228 effective_load_flags_ |= LOAD_DISABLE_CACHE;
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
2084 2402
2085 if (partial_ && (is_sparse_ || truncated_) && 2403 if (partial_ && (is_sparse_ || truncated_) &&
2086 (!partial_->IsCurrentRangeCached() || invalid_range_)) { 2404 (!partial_->IsCurrentRangeCached() || invalid_range_)) {
2087 // Force revalidation for sparse or truncated entries. Note that we don't 2405 // 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 2406 // want to ignore the regular validation logic just because a byte range was
2089 // part of the request. 2407 // part of the request.
2090 skip_validation = false; 2408 skip_validation = false;
2091 } 2409 }
2092 2410
2093 if (skip_validation) { 2411 if (skip_validation) {
2094 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_USED); 2412 if (shared_) {
2095 return SetupEntryForRead(); 2413 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_JOIN_SHARED_WRITING);
2414 entry_->shared_writers->OnValidationMatch(this, priority_);
2415 } else {
2416 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_USED);
2417 return SetupEntryForRead();
2418 }
2096 } else { 2419 } else {
2097 // Make the network request conditional, to see if we may reuse our cached 2420 // 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. 2421 // 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 2422 // Our mode remains READ_WRITE for a conditional request. Even if the
2100 // conditionalization fails, we don't switch to WRITE mode until we 2423 // 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 2424 // know we won't be falling back to using the cache entry in the
2102 // LOAD_FROM_CACHE_IF_OFFLINE case. 2425 // LOAD_FROM_CACHE_IF_OFFLINE case.
2103 if (!ConditionalizeRequest()) { 2426 if (!ConditionalizeRequest()) {
2104 couldnt_conditionalize_request_ = true; 2427 couldnt_conditionalize_request_ = true;
2105 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE); 2428 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE);
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after
2604 IsCertStatusError(response_.ssl_info.cert_status)) { 2927 IsCertStatusError(response_.ssl_info.cert_status)) {
2605 DoneWritingToEntry(false); 2928 DoneWritingToEntry(false);
2606 if (net_log_.IsCapturing()) 2929 if (net_log_.IsCapturing())
2607 net_log_.EndEvent(NetLogEventType::HTTP_CACHE_WRITE_INFO); 2930 net_log_.EndEvent(NetLogEventType::HTTP_CACHE_WRITE_INFO);
2608 return OK; 2931 return OK;
2609 } 2932 }
2610 2933
2611 if (truncated) 2934 if (truncated)
2612 DCHECK_EQ(200, response_.headers->response_code()); 2935 DCHECK_EQ(200, response_.headers->response_code());
2613 2936
2614 // When writing headers, we normally only write the non-transient headers. 2937 return cache_->WriteResponseInfo(entry_, &response_, io_callback_, truncated,
2615 bool skip_transient_headers = true; 2938 &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 } 2939 }
2624 2940
2625 int HttpCache::Transaction::OnWriteResponseInfoToEntryComplete(int result) { 2941 int HttpCache::Transaction::OnWriteResponseInfoToEntryComplete(int result) {
2626 if (!entry_) 2942 if (!entry_)
2627 return OK; 2943 return OK;
2628 if (net_log_.IsCapturing()) { 2944 if (net_log_.IsCapturing()) {
2629 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO, 2945 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO,
2630 result); 2946 result);
2631 } 2947 }
2632 2948
2633 if (result != io_buf_len_) { 2949 if (result != io_buf_len_) {
2634 DLOG(ERROR) << "failed to write response info to cache"; 2950 DLOG(ERROR) << "failed to write response info to cache";
2635 DoneWritingToEntry(false); 2951 DoneWritingToEntry(false);
2636 } 2952 }
2637 return OK; 2953 return OK;
2638 } 2954 }
2639 2955
2640 void HttpCache::Transaction::DoneWritingToEntry(bool success) { 2956 void HttpCache::Transaction::DoneWritingToEntry(bool success,
2957 bool perform_entry_cleanup) {
2641 if (!entry_) 2958 if (!entry_)
2642 return; 2959 return;
2643 2960
2644 RecordHistograms(); 2961 RecordHistograms();
2645 2962
2646 cache_->DoneWritingToEntry(entry_, success); 2963 if (perform_entry_cleanup) {
2647 entry_ = NULL; 2964 cache_->DoneWritingToEntry(entry_, success);
2965 }
2966 entry_ = nullptr;
2648 mode_ = NONE; // switch to 'pass through' mode 2967 mode_ = NONE; // switch to 'pass through' mode
2649 } 2968 }
2650 2969
2970 void HttpCache::Transaction::ContinueWithoutSharedWriting(
2971 std::unique_ptr<DataAccess> data_access,
2972 bool needs_entry) {
2973 shared_ = false;
2974 if (!needs_entry)
2975 entry_ = nullptr;
2976 mode_ = NONE;
2977 data_access_ = std::move(data_access);
2978 }
2979
2651 int HttpCache::Transaction::OnCacheReadError(int result, bool restart) { 2980 int HttpCache::Transaction::OnCacheReadError(int result, bool restart) {
2652 DLOG(ERROR) << "ReadData failed: " << result; 2981 DLOG(ERROR) << "ReadData failed: " << result;
2653 const int result_for_histogram = std::max(0, -result); 2982 const int result_for_histogram = std::max(0, -result);
2654 if (restart) { 2983 if (restart) {
2655 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorRestartable", 2984 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorRestartable",
2656 result_for_histogram); 2985 result_for_histogram);
2657 } else { 2986 } else {
2658 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorNonRestartable", 2987 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorNonRestartable",
2659 result_for_histogram); 2988 result_for_histogram);
2660 } 2989 }
2661 2990
2662 // Avoid using this entry in the future. 2991 // Avoid using this entry in the future.
2663 if (cache_.get()) 2992 if (cache_.get())
2664 cache_->DoomActiveEntry(cache_key_); 2993 cache_->DoomActiveEntry(cache_key_);
2665 2994
2666 if (restart) { 2995 if (restart) {
2667 DCHECK(!reading_); 2996 DCHECK(!reading_);
2668 DCHECK(!network_trans_.get()); 2997 DCHECK(!network_trans_.get());
2669 cache_->DoneWithEntry(entry_, this, false); 2998 if (shared_) {
2999 cache_->RemoveValidatingTransSharedWriters(this, entry_);
3000 } else {
3001 cache_->DoneWithEntry(entry_, this, false);
3002 }
2670 entry_ = NULL; 3003 entry_ = NULL;
2671 is_sparse_ = false; 3004 is_sparse_ = false;
2672 partial_.reset(); 3005 partial_.reset();
2673 next_state_ = STATE_GET_BACKEND; 3006 next_state_ = STATE_GET_BACKEND;
2674 return OK; 3007 return OK;
2675 } 3008 }
2676 3009
2677 return ERR_CACHE_READ_FAILURE; 3010 return ERR_CACHE_READ_FAILURE;
2678 } 3011 }
2679 3012
2680 void HttpCache::Transaction::OnAddToEntryTimeout(base::TimeTicks start_time) { 3013 void HttpCache::Transaction::OnAddToEntryTimeout(base::TimeTicks start_time) {
2681 if (entry_lock_waiting_since_ != start_time) 3014 if (entry_lock_waiting_since_ != start_time)
2682 return; 3015 return;
2683 3016
2684 DCHECK_EQ(next_state_, STATE_ADD_TO_ENTRY_COMPLETE); 3017 DCHECK_EQ(next_state_, STATE_ADD_TO_ENTRY_COMPLETE);
2685 3018
2686 if (!cache_) 3019 if (!cache_)
2687 return; 3020 return;
2688 3021
2689 cache_->RemovePendingTransaction(this); 3022 cache_->RemovePendingTransaction(this);
2690 OnIOComplete(ERR_CACHE_LOCK_TIMEOUT); 3023 OnIOComplete(ERR_CACHE_LOCK_TIMEOUT);
2691 } 3024 }
2692 3025
2693 void HttpCache::Transaction::DoomPartialEntry(bool delete_object) { 3026 void HttpCache::Transaction::DoomPartialEntry(bool delete_object) {
3027 // Partial requests not supported with shared writing as of now.
3028 DCHECK(!shared_);
2694 DVLOG(2) << "DoomPartialEntry"; 3029 DVLOG(2) << "DoomPartialEntry";
2695 int rv = cache_->DoomEntry(cache_key_, NULL); 3030 int rv = cache_->DoomEntry(cache_key_, NULL);
2696 DCHECK_EQ(OK, rv); 3031 DCHECK_EQ(OK, rv);
2697 cache_->DoneWithEntry(entry_, this, false); 3032 cache_->DoneWithEntry(entry_, this, false);
2698 entry_ = NULL; 3033 entry_ = NULL;
2699 is_sparse_ = false; 3034 is_sparse_ = false;
2700 truncated_ = false; 3035 truncated_ = false;
2701 if (delete_object) 3036 if (delete_object)
2702 partial_.reset(NULL); 3037 partial_.reset(NULL);
2703 } 3038 }
2704 3039
2705 int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) { 3040 int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) {
2706 partial_->OnNetworkReadCompleted(result); 3041 partial_->OnNetworkReadCompleted(result);
2707 3042
2708 if (result == 0) { 3043 if (result == 0) {
2709 // We need to move on to the next range. 3044 // We need to move on to the next range.
2710 ResetNetworkTransaction(); 3045 ResetDataAccess();
2711 next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION; 3046 next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION;
2712 } 3047 }
2713 return result; 3048 return result;
2714 } 3049 }
2715 3050
2716 int HttpCache::Transaction::DoPartialCacheReadCompleted(int result) { 3051 int HttpCache::Transaction::DoPartialCacheReadCompleted(int result) {
2717 partial_->OnCacheReadCompleted(result); 3052 partial_->OnCacheReadCompleted(result);
2718 3053
2719 if (result == 0 && mode_ == READ_WRITE) { 3054 if (result == 0 && mode_ == READ_WRITE) {
2720 // We need to move on to the next range. 3055 // We need to move on to the next range.
(...skipping 23 matching lines...) Expand all
2744 if (!delete_object) { 3079 if (!delete_object) {
2745 // The simplest way to re-initialize partial_ is to create a new object. 3080 // The simplest way to re-initialize partial_ is to create a new object.
2746 partial_.reset(new PartialData()); 3081 partial_.reset(new PartialData());
2747 if (partial_->Init(request_->extra_headers)) 3082 if (partial_->Init(request_->extra_headers))
2748 partial_->SetHeaders(custom_request_->extra_headers); 3083 partial_->SetHeaders(custom_request_->extra_headers);
2749 else 3084 else
2750 partial_.reset(); 3085 partial_.reset();
2751 } 3086 }
2752 } 3087 }
2753 3088
2754 void HttpCache::Transaction::ResetNetworkTransaction() { 3089 void HttpCache::Transaction::SaveNetworkTransactionInfo(
3090 const HttpTransaction* transaction) {
2755 DCHECK(!old_network_trans_load_timing_); 3091 DCHECK(!old_network_trans_load_timing_);
2756 DCHECK(network_trans_); 3092 DCHECK(transaction);
2757 LoadTimingInfo load_timing; 3093 LoadTimingInfo load_timing;
2758 if (network_trans_->GetLoadTimingInfo(&load_timing)) 3094 if (transaction->GetLoadTimingInfo(&load_timing))
2759 old_network_trans_load_timing_.reset(new LoadTimingInfo(load_timing)); 3095 old_network_trans_load_timing_.reset(new LoadTimingInfo(load_timing));
2760 total_received_bytes_ += network_trans_->GetTotalReceivedBytes(); 3096 total_received_bytes_ += transaction->GetTotalReceivedBytes();
2761 total_sent_bytes_ += network_trans_->GetTotalSentBytes(); 3097 total_sent_bytes_ += transaction->GetTotalSentBytes();
2762 ConnectionAttempts attempts; 3098 ConnectionAttempts attempts;
2763 network_trans_->GetConnectionAttempts(&attempts); 3099 transaction->GetConnectionAttempts(&attempts);
2764 for (const auto& attempt : attempts) 3100 for (const auto& attempt : attempts)
2765 old_connection_attempts_.push_back(attempt); 3101 old_connection_attempts_.push_back(attempt);
2766 old_remote_endpoint_ = IPEndPoint(); 3102 old_remote_endpoint_ = IPEndPoint();
2767 network_trans_->GetRemoteEndpoint(&old_remote_endpoint_); 3103 transaction->GetRemoteEndpoint(&old_remote_endpoint_);
3104 }
3105
3106 void HttpCache::Transaction::SaveSharedNetworkTransactionInfo() {
3107 // If network_trans_ is still present, this transaction has not started using
3108 // the "shared" network transaction.
3109 if (network_trans_) {
3110 SaveNetworkTransactionInfo(network_trans_.get());
3111 return;
3112 }
3113
3114 DCHECK(!old_network_trans_load_timing_);
3115
3116 // If the transaction is being deleted while still in the waiting queue,
3117 // entry_ is not yet set, do nothing.
3118 if (!entry_)
3119 return;
3120 DCHECK(entry_->shared_writers);
3121 HttpTransaction* network_transaction =
3122 entry_->shared_writers->data_access_->network_transaction_.get();
3123 SaveNetworkTransactionInfo(network_transaction);
3124 have_full_request_headers_ =
3125 network_transaction->GetFullRequestHeaders(&full_request_headers_);
3126 }
3127
3128 void HttpCache::Transaction::ResetNetworkTransaction() {
3129 SaveNetworkTransactionInfo(network_trans_.get());
2768 network_trans_.reset(); 3130 network_trans_.reset();
2769 } 3131 }
2770 3132
2771 // Histogram data from the end of 2010 show the following distribution of 3133 void HttpCache::Transaction::ResetDataAccess() {
2772 // response headers: 3134 SaveNetworkTransactionInfo(data_access_->network_transaction_.get());
2773 // 3135 data_access_.reset();
2774 // Content-Length............... 87% 3136 }
2775 // Date......................... 98%
2776 // Last-Modified................ 49%
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 3137
2789 if (request_->method != "GET") 3138 HttpTransaction* HttpCache::Transaction::GetCurrentNetworkTransaction() const {
2790 return false; 3139 if (network_trans_)
2791 3140 return network_trans_.get();
2792 // Note that if this is a 206, content-length was already fixed after calling 3141 if (data_access_)
2793 // PartialData::ResponseHeadersOK(). 3142 return data_access_->network_transaction_.get();
2794 if (response_.headers->GetContentLength() <= 0 || 3143 if (shared_ && entry_ && entry_->shared_writers)
2795 response_.headers->HasHeaderValue("Accept-Ranges", "none") || 3144 return entry_->shared_writers->data_access_->network_transaction_.get();
2796 !response_.headers->HasStrongValidators()) { 3145 return nullptr;
2797 return false;
2798 }
2799
2800 return true;
2801 } 3146 }
2802 3147
2803 void HttpCache::Transaction::SetResponse(const HttpResponseInfo& response) { 3148 void HttpCache::Transaction::SetResponse(const HttpResponseInfo& response) {
2804 response_ = response; 3149 response_ = response;
2805 SyncCacheEntryStatusToResponse(); 3150 SyncCacheEntryStatusToResponse();
2806 } 3151 }
2807 3152
2808 void HttpCache::Transaction::SetAuthResponse( 3153 void HttpCache::Transaction::SetAuthResponse(
2809 const HttpResponseInfo& auth_response) { 3154 const HttpResponseInfo& auth_response) {
2810 auth_response_ = auth_response; 3155 auth_response_ = auth_response;
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
2916 } 3261 }
2917 } 3262 }
2918 3263
2919 CACHE_STATUS_HISTOGRAMS(""); 3264 CACHE_STATUS_HISTOGRAMS("");
2920 3265
2921 if (cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE) { 3266 if (cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE) {
2922 UMA_HISTOGRAM_ENUMERATION("HttpCache.CantConditionalizeCause", 3267 UMA_HISTOGRAM_ENUMERATION("HttpCache.CantConditionalizeCause",
2923 validation_cause_, VALIDATION_CAUSE_MAX); 3268 validation_cause_, VALIDATION_CAUSE_MAX);
2924 } 3269 }
2925 3270
3271 // This may also exclude shared writing counts for these cases.
2926 if (cache_entry_status_ == CacheEntryStatus::ENTRY_OTHER) 3272 if (cache_entry_status_ == CacheEntryStatus::ENTRY_OTHER)
2927 return; 3273 return;
3274
2928 DCHECK(!range_requested_); 3275 DCHECK(!range_requested_);
2929 DCHECK(!first_cache_access_since_.is_null()); 3276 DCHECK(!first_cache_access_since_.is_null());
2930 3277
2931 TimeDelta total_time = base::TimeTicks::Now() - first_cache_access_since_; 3278 TimeDelta total_time = base::TimeTicks::Now() - first_cache_access_since_;
2932 3279
2933 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone", total_time); 3280 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone", total_time);
2934 3281
3282 if (cache_entry_status_ == CacheEntryStatus::ENTRY_JOIN_SHARED_WRITING) {
3283 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.JoinSharedWriting", total_time);
3284 } else if (cache_entry_status_ ==
3285 CacheEntryStatus::ENTRY_DOOM_SHARED_WRITING) {
3286 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.DoomSharedWriting", total_time);
3287 } else if (initiate_shared_writing_) {
3288 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.InitiateSharedWriting",
3289 total_time);
3290 }
3291
2935 bool did_send_request = !send_request_since_.is_null(); 3292 bool did_send_request = !send_request_since_.is_null();
2936 DCHECK( 3293 DCHECK(
2937 (did_send_request && 3294 (did_send_request &&
2938 (cache_entry_status_ == CacheEntryStatus::ENTRY_NOT_IN_CACHE || 3295 (cache_entry_status_ == CacheEntryStatus::ENTRY_NOT_IN_CACHE ||
2939 cache_entry_status_ == CacheEntryStatus::ENTRY_VALIDATED || 3296 cache_entry_status_ == CacheEntryStatus::ENTRY_VALIDATED ||
2940 cache_entry_status_ == CacheEntryStatus::ENTRY_UPDATED || 3297 cache_entry_status_ == CacheEntryStatus::ENTRY_UPDATED ||
2941 cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE)) || 3298 cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE ||
3299 cache_entry_status_ == CacheEntryStatus::ENTRY_JOIN_SHARED_WRITING ||
3300 cache_entry_status_ == CacheEntryStatus::ENTRY_DOOM_SHARED_WRITING)) ||
2942 (!did_send_request && 3301 (!did_send_request &&
2943 cache_entry_status_ == CacheEntryStatus::ENTRY_USED)); 3302 (cache_entry_status_ == CacheEntryStatus::ENTRY_USED ||
3303 cache_entry_status_ == CacheEntryStatus::ENTRY_JOIN_SHARED_WRITING)));
2944 3304
2945 if (!did_send_request) { 3305 if (!did_send_request) {
2946 DCHECK(cache_entry_status_ == CacheEntryStatus::ENTRY_USED); 3306 if (cache_entry_status_ == CacheEntryStatus::ENTRY_USED) {
2947 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.Used", total_time); 3307 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.Used", total_time);
3308 }
2948 return; 3309 return;
2949 } 3310 }
2950 3311
2951 TimeDelta before_send_time = send_request_since_ - first_cache_access_since_; 3312 TimeDelta before_send_time = send_request_since_ - first_cache_access_since_;
2952 int64_t before_send_percent = (total_time.ToInternalValue() == 0) 3313 int64_t before_send_percent = (total_time.ToInternalValue() == 0)
2953 ? 0 3314 ? 0
2954 : before_send_time * 100 / total_time; 3315 : before_send_time * 100 / total_time;
2955 DCHECK_GE(before_send_percent, 0); 3316 DCHECK_GE(before_send_percent, 0);
2956 DCHECK_LE(before_send_percent, 100); 3317 DCHECK_LE(before_send_percent, 100);
2957 base::HistogramBase::Sample before_send_sample = 3318 base::HistogramBase::Sample before_send_sample =
2958 static_cast<base::HistogramBase::Sample>(before_send_percent); 3319 static_cast<base::HistogramBase::Sample>(before_send_percent);
2959 3320
2960 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.SentRequest", total_time); 3321 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.SentRequest", total_time);
2961 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend", before_send_time); 3322 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend", before_send_time);
2962 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend", before_send_sample); 3323 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend", before_send_sample);
2963 3324
2964 // TODO(gavinp): Remove or minimize these histograms, particularly the ones 3325 // TODO(gavinp): Remove or minimize these histograms, particularly the ones
2965 // below this comment after we have received initial data. 3326 // below this comment after we have received initial data.
2966 switch (cache_entry_status_) { 3327 switch (cache_entry_status_) {
2967 case CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE: { 3328 case CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE: {
2968 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.CantConditionalize", 3329 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.CantConditionalize",
2969 before_send_time); 3330 before_send_time);
2970 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.CantConditionalize", 3331 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.CantConditionalize",
2971 before_send_sample); 3332 before_send_sample);
3333 if (initiate_shared_writing_) {
3334 UMA_HISTOGRAM_TIMES(
3335 "HttpCache.BeforeSend.CantConditionalize.InitiateSharedWriting",
3336 before_send_time);
3337 UMA_HISTOGRAM_PERCENTAGE(
3338 "HttpCache.PercentBeforeSend.CantConditionalize."
3339 "InitiateSharedWriting",
3340 before_send_sample);
3341 }
3342
2972 break; 3343 break;
2973 } 3344 }
2974 case CacheEntryStatus::ENTRY_NOT_IN_CACHE: { 3345 case CacheEntryStatus::ENTRY_NOT_IN_CACHE: {
2975 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.NotCached", before_send_time); 3346 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.NotCached", before_send_time);
2976 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.NotCached", 3347 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.NotCached",
2977 before_send_sample); 3348 before_send_sample);
3349 if (initiate_shared_writing_) {
3350 UMA_HISTOGRAM_TIMES(
3351 "HttpCache.BeforeSend.NotCached.InitiateSharedWriting",
3352 before_send_time);
3353 UMA_HISTOGRAM_PERCENTAGE(
3354 "HttpCache.PercentBeforeSend.NotCached.InitiateSharedWriting",
3355 before_send_sample);
3356 }
3357
2978 break; 3358 break;
2979 } 3359 }
2980 case CacheEntryStatus::ENTRY_VALIDATED: { 3360 case CacheEntryStatus::ENTRY_VALIDATED: {
2981 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Validated", before_send_time); 3361 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Validated", before_send_time);
2982 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.Validated", 3362 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.Validated",
2983 before_send_sample); 3363 before_send_sample);
2984 break; 3364 break;
2985 } 3365 }
2986 case CacheEntryStatus::ENTRY_UPDATED: { 3366 case CacheEntryStatus::ENTRY_UPDATED: {
2987 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Updated", before_send_time); 3367 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Updated", before_send_time);
2988 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.Updated", 3368 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.Updated",
2989 before_send_sample); 3369 before_send_sample);
3370 if (initiate_shared_writing_) {
3371 UMA_HISTOGRAM_TIMES(
3372 "HttpCache.BeforeSend.Updated.InitiateSharedWriting",
3373 before_send_time);
3374 UMA_HISTOGRAM_PERCENTAGE(
3375 "HttpCache.PercentBeforeSend.Updated.InitiateSharedWriting",
3376 before_send_sample);
3377 }
3378 break;
3379 }
3380 case CacheEntryStatus::ENTRY_JOIN_SHARED_WRITING: {
3381 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.JoinSharedWriting",
3382 before_send_time);
3383 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.JoinSharedWriting",
3384 before_send_sample);
3385 break;
3386 }
3387 case CacheEntryStatus::ENTRY_DOOM_SHARED_WRITING: {
3388 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.DoomSharedWriting",
3389 before_send_time);
3390 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.DoomSharedWriting",
3391 before_send_sample);
2990 break; 3392 break;
2991 } 3393 }
2992 default: 3394 default:
2993 NOTREACHED(); 3395 NOTREACHED();
2994 } 3396 }
2995 } 3397 }
2996 3398
3399 bool HttpCache::Transaction::IsEligibleForSharedWriting() const {
3400 if (!(mode_ & WRITE))
3401 return false;
3402
3403 DCHECK(request_);
3404 if (request_->method != "GET")
3405 return false;
3406
3407 if (partial_ || range_requested_)
3408 return false;
3409
3410 return true;
3411 }
3412
3413 void HttpCache::Transaction::SetSharedWritingFailState(int result) {
3414 next_state_ = STATE_SHARED_READ_WRITE_FAILED;
3415 shared_read_write_failure_result_ = result;
3416 entry_ = nullptr;
3417 }
3418
2997 void HttpCache::Transaction::OnIOComplete(int result) { 3419 void HttpCache::Transaction::OnIOComplete(int result) {
2998 DoLoop(result); 3420 DoLoop(result);
2999 } 3421 }
3000 3422
3001 } // namespace net 3423 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698