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

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

Issue 2519473002: Fixes the cache lock issue. (Closed)
Patch Set: Josh's early 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
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:
jkarlin 2017/02/07 15:20:31 Ah, I'm not sure that I appreciated just how large
shivanisha 2017/02/07 20:56:48 Yes, there are lots of states and this switch only
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 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
699 // -> CacheToggleUnusedSincePrefetch* -> CacheDispatchValidation -> 830 // -> CacheToggleUnusedSincePrefetch* -> CacheDispatchValidation ->
700 // BeginPartialCacheValidation() -> BeginCacheValidation() -> 831 // BeginPartialCacheValidation() -> BeginCacheValidation() ->
701 // SetupEntryForRead() 832 // SetupEntryForRead()
702 // 833 //
703 // Read(): 834 // Read():
704 // CacheReadData* 835 // CacheReadData*
705 // 836 //
706 // 14. Cached entry more than 5 minutes old, unused_since_prefetch is true: 837 // 14. Cached entry more than 5 minutes old, unused_since_prefetch is true:
707 // Like examples 2-4, only CacheToggleUnusedSincePrefetch* is inserted between 838 // Like examples 2-4, only CacheToggleUnusedSincePrefetch* is inserted between
708 // CacheReadResponse* and CacheDispatchValidation. 839 // CacheReadResponse* and CacheDispatchValidation.
840 //
709 int HttpCache::Transaction::DoLoop(int result) { 841 int HttpCache::Transaction::DoLoop(int result) {
710 DCHECK(next_state_ != STATE_NONE); 842 DCHECK(next_state_ != STATE_NONE);
711 843
712 int rv = result; 844 int rv = result;
713 do { 845 do {
714 State state = next_state_; 846 State state = next_state_;
715 next_state_ = STATE_NONE; 847 next_state_ = STATE_NONE;
716 switch (state) { 848 switch (state) {
717 case STATE_GET_BACKEND: 849 case STATE_GET_BACKEND:
718 DCHECK_EQ(OK, rv); 850 DCHECK_EQ(OK, rv);
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
866 case STATE_CACHE_WRITE_DATA_COMPLETE: 998 case STATE_CACHE_WRITE_DATA_COMPLETE:
867 rv = DoCacheWriteDataComplete(rv); 999 rv = DoCacheWriteDataComplete(rv);
868 break; 1000 break;
869 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE: 1001 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE:
870 DCHECK_EQ(OK, rv); 1002 DCHECK_EQ(OK, rv);
871 rv = DoCacheWriteTruncatedResponse(); 1003 rv = DoCacheWriteTruncatedResponse();
872 break; 1004 break;
873 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE: 1005 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE:
874 rv = DoCacheWriteTruncatedResponseComplete(rv); 1006 rv = DoCacheWriteTruncatedResponseComplete(rv);
875 break; 1007 break;
1008 case STATE_SHARED_NETWORK_READ:
1009 DCHECK_EQ(OK, rv);
1010 rv = DoSharedNetworkRead();
1011 break;
1012 case STATE_SHARED_NETWORK_READ_COMPLETE:
1013 rv = DoSharedNetworkReadComplete(rv);
1014 break;
1015 case STATE_SHARED_NETWORK_READ_WAIT_COMPLETE:
1016 rv = DoSharedNetworkReadWaitComplete(rv);
1017 break;
1018 case STATE_SHARED_CACHE_WRITE_DATA:
1019 rv = DoSharedCacheWriteData(rv);
1020 break;
1021 case STATE_SHARED_CACHE_WRITE_DATA_COMPLETE:
1022 rv = DoSharedCacheWriteDataComplete(rv);
1023 break;
1024 case STATE_SHARED_READ_WRITE_FAILED:
1025 rv = DoSharedReadWriteFailed();
1026 break;
876 default: 1027 default:
877 NOTREACHED() << "bad state"; 1028 NOTREACHED() << "bad state";
878 rv = ERR_FAILED; 1029 rv = ERR_FAILED;
879 break; 1030 break;
880 } 1031 }
881 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 1032 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
882 1033
883 if (rv != ERR_IO_PENDING && !callback_.is_null()) { 1034 if (rv != ERR_IO_PENDING && !callback_.is_null()) {
884 read_buf_ = NULL; // Release the buffer before invoking the callback. 1035 read_buf_ = NULL; // Release the buffer before invoking the callback.
885 base::ResetAndReturn(&callback_).Run(rv); 1036 base::ResetAndReturn(&callback_).Run(rv);
(...skipping 617 matching lines...) Expand 10 before | Expand all | Expand 10 after
1503 1654
1504 RecordNoStoreHeaderHistogram(request_->load_flags, new_response); 1655 RecordNoStoreHeaderHistogram(request_->load_flags, new_response);
1505 1656
1506 if (new_response_->headers->response_code() == 416 && 1657 if (new_response_->headers->response_code() == 416 &&
1507 (request_->method == "GET" || request_->method == "POST")) { 1658 (request_->method == "GET" || request_->method == "POST")) {
1508 // If there is an active entry it may be destroyed with this transaction. 1659 // If there is an active entry it may be destroyed with this transaction.
1509 SetResponse(*new_response_); 1660 SetResponse(*new_response_);
1510 return OK; 1661 return OK;
1511 } 1662 }
1512 1663
1664 // If the transaction is shared and it is a 200 or an error response, then
1665 // doom the entry and let this transaction continue without writing to the
1666 // cache if shared writers contain more transactions. If not, continue
1667 // writing to the cache and also transfer the network transaction to shared
1668 // writers.
1669 if (shared_ && new_response->headers->response_code() != 304) {
1670 network_trans_ = entry_->shared_writers->OnValidationNoMatch(
1671 cache_key_, this, std::move(network_trans_), priority_);
1672 if (!shared_) {
1673 DCHECK(network_trans_);
1674 if (cache_entry_status_ == CacheEntryStatus::ENTRY_UNDEFINED) {
1675 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_DOOM_SHARED_WRITING);
1676 }
1677 DoneWritingToEntry(false, false);
1678 return OK;
1679 } else {
1680 DCHECK(!network_trans_);
1681 }
1682 }
1683
1513 // Are we expecting a response to a conditional query? 1684 // Are we expecting a response to a conditional query?
1514 if (mode_ == READ_WRITE || mode_ == UPDATE) { 1685 if (mode_ == READ_WRITE || mode_ == UPDATE) {
1515 if (new_response->headers->response_code() == 304 || handling_206_) { 1686 if (new_response->headers->response_code() == 304 || handling_206_) {
1516 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_VALIDATED); 1687 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_VALIDATED);
1517 next_state_ = STATE_UPDATE_CACHED_RESPONSE; 1688 next_state_ = STATE_UPDATE_CACHED_RESPONSE;
1518 return OK; 1689 return OK;
1519 } 1690 }
1520 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_UPDATED); 1691 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_UPDATED);
1521 mode_ = WRITE; 1692 mode_ = WRITE;
1522 } 1693 }
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
1625 SetResponse(*new_response_); 1796 SetResponse(*new_response_);
1626 1797
1627 if (request_->method == "HEAD") { 1798 if (request_->method == "HEAD") {
1628 // This response is replacing the cached one. 1799 // This response is replacing the cached one.
1629 DoneWritingToEntry(false); 1800 DoneWritingToEntry(false);
1630 mode_ = NONE; 1801 mode_ = NONE;
1631 new_response_ = NULL; 1802 new_response_ = NULL;
1632 return OK; 1803 return OK;
1633 } 1804 }
1634 1805
1635 if (handling_206_ && !CanResume(false)) { 1806 if (handling_206_ &&
1807 !cache_->CanResumeEntry(false, request_->method, &response_, entry_)) {
1636 // There is no point in storing this resource because it will never be used. 1808 // 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. 1809 // This may change if we support LOAD_ONLY_FROM_CACHE with sparse entries.
1638 DoneWritingToEntry(false); 1810 DoneWritingToEntry(false);
1639 if (partial_) 1811 if (partial_)
1640 partial_->FixResponseHeaders(response_.headers.get(), true); 1812 partial_->FixResponseHeaders(response_.headers.get(), true);
1641 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED; 1813 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
1642 return OK; 1814 return OK;
1643 } 1815 }
1644 1816
1645 next_state_ = STATE_CACHE_WRITE_RESPONSE; 1817 next_state_ = STATE_CACHE_WRITE_RESPONSE;
1646 return OK; 1818 return OK;
1647 } 1819 }
1648 1820
1649 int HttpCache::Transaction::DoCacheWriteResponse() { 1821 int HttpCache::Transaction::DoCacheWriteResponse() {
1650 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponse"); 1822 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponse");
1651 next_state_ = STATE_CACHE_WRITE_RESPONSE_COMPLETE; 1823 next_state_ = STATE_CACHE_WRITE_RESPONSE_COMPLETE;
1652 return WriteResponseInfoToEntry(truncated_); 1824 return WriteResponseInfoToEntry(truncated_);
1653 } 1825 }
1654 1826
1655 int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) { 1827 int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) {
1656 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponseComplete"); 1828 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteResponseComplete");
1657 next_state_ = STATE_TRUNCATE_CACHED_DATA; 1829 next_state_ = STATE_TRUNCATE_CACHED_DATA;
1658 return OnWriteResponseInfoToEntryComplete(result); 1830 return OnWriteResponseInfoToEntryComplete(result);
1659 } 1831 }
1660 1832
1833 void HttpCache::Transaction::SetShared() {
1834 shared_ = true;
1835 }
1836
1837 void HttpCache::Transaction::ResetShared(bool continue_network_reading,
1838 bool continue_cache_reading) {
1839 if (!continue_network_reading) {
1840 SaveSharedNetworkTransactionInfo();
1841 }
1842 if (continue_cache_reading) {
1843 mode_ = READ;
1844 }
1845 shared_ = false;
1846 }
1847
1661 int HttpCache::Transaction::DoTruncateCachedData() { 1848 int HttpCache::Transaction::DoTruncateCachedData() {
1662 TRACE_EVENT0("io", "HttpCacheTransaction::DoTruncateCachedData"); 1849 TRACE_EVENT0("io", "HttpCacheTransaction::DoTruncateCachedData");
1663 next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE; 1850 next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE;
1664 if (!entry_) 1851 if (!entry_)
1665 return OK; 1852 return OK;
1666 if (net_log_.IsCapturing()) 1853 if (net_log_.IsCapturing())
1667 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_WRITE_DATA); 1854 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_WRITE_DATA);
1668 // Truncate the stream. 1855 // Truncate the stream.
1669 return WriteToEntry(kResponseContentIndex, 0, NULL, 0, io_callback_); 1856 return WriteToEntry(kResponseContentIndex, 0, NULL, 0, io_callback_);
1670 } 1857 }
(...skipping 28 matching lines...) Expand all
1699 if (net_log_.IsCapturing()) { 1886 if (net_log_.IsCapturing()) {
1700 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO, 1887 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO,
1701 result); 1888 result);
1702 } 1889 }
1703 } 1890 }
1704 1891
1705 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED; 1892 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
1706 return OK; 1893 return OK;
1707 } 1894 }
1708 1895
1896 void HttpCache::Transaction::ProcessForSharedWriting() {
1897 // Should not be already reading.
1898 if (reading_)
1899 return;
1900
1901 // If not already part of SharedWriters, then check if one should be
1902 // created.
1903 if (!shared_ && !IsEligibleForSharedWriting())
1904 return;
1905
1906 if (shared_) {
1907 // Non 304 case is already handled in DoSuccessfulSendRequest.
1908 if (response_.headers->response_code() != 304) {
1909 return;
1910 }
1911 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_JOIN_SHARED_WRITING);
1912 entry_->shared_writers->OnValidationMatch(this, priority_);
1913 network_trans_.reset();
1914 return;
1915 }
1916
1917 // Do not create a SharedWriters if its a Redirect response.
1918 if (response_.headers->response_code() != 200)
1919 return;
1920
1921 // or if its a no-store response.
1922 if (!entry_)
1923 return;
1924
1925 DCHECK(cache_entry_status_ == CacheEntryStatus::ENTRY_NOT_IN_CACHE ||
1926 cache_entry_status_ == CacheEntryStatus::ENTRY_UPDATED ||
1927 cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE ||
1928 cache_entry_status_ == CacheEntryStatus::ENTRY_OTHER);
1929 // Measure how many requests out of the total of "not cached" and "updated"
1930 // are initiating Shared Writing.
1931 initiate_shared_writing_ = true;
1932 DCHECK(entry_ && network_trans_);
1933
1934 // An instance of SharedWriters will be created when the first writer has
1935 // written the new response headers in the cache. Transfer network
1936 // transaction’s ownership to SharedWriters so it can be used by any of the
1937 // transactions for subsequent reading from the network.
1938 cache_->CreateSharedWriters(this, std::move(network_trans_), priority_);
1939 }
1940
1709 int HttpCache::Transaction::DoPartialHeadersReceived() { 1941 int HttpCache::Transaction::DoPartialHeadersReceived() {
1710 new_response_ = NULL; 1942 new_response_ = NULL;
1711 if (entry_ && !partial_ && entry_->disk_entry->GetDataSize(kMetadataIndex)) 1943 if (entry_ && !partial_ && entry_->disk_entry->GetDataSize(kMetadataIndex))
1712 next_state_ = STATE_CACHE_READ_METADATA; 1944 next_state_ = STATE_CACHE_READ_METADATA;
1713 1945
1946 ProcessForSharedWriting();
1947
1714 if (!partial_) 1948 if (!partial_)
1715 return OK; 1949 return OK;
1716 1950
1717 if (reading_) { 1951 if (reading_) {
1718 if (network_trans_.get()) { 1952 if (network_trans_.get()) {
1719 next_state_ = STATE_NETWORK_READ; 1953 next_state_ = STATE_NETWORK_READ;
1720 } else { 1954 } else {
1721 next_state_ = STATE_CACHE_READ_DATA; 1955 next_state_ = STATE_CACHE_READ_DATA;
1722 } 1956 }
1723 } else if (mode_ != NONE) { 1957 } else if (mode_ != NONE) {
(...skipping 30 matching lines...) Expand all
1754 } 1988 }
1755 1989
1756 int HttpCache::Transaction::DoNetworkRead() { 1990 int HttpCache::Transaction::DoNetworkRead() {
1757 TRACE_EVENT0("io", "HttpCacheTransaction::DoNetworkRead"); 1991 TRACE_EVENT0("io", "HttpCacheTransaction::DoNetworkRead");
1758 next_state_ = STATE_NETWORK_READ_COMPLETE; 1992 next_state_ = STATE_NETWORK_READ_COMPLETE;
1759 return network_trans_->Read(read_buf_.get(), io_buf_len_, io_callback_); 1993 return network_trans_->Read(read_buf_.get(), io_buf_len_, io_callback_);
1760 } 1994 }
1761 1995
1762 int HttpCache::Transaction::DoNetworkReadComplete(int result) { 1996 int HttpCache::Transaction::DoNetworkReadComplete(int result) {
1763 TRACE_EVENT0("io", "HttpCacheTransaction::DoNetworkReadComplete"); 1997 TRACE_EVENT0("io", "HttpCacheTransaction::DoNetworkReadComplete");
1998 if (net_log_.IsCapturing())
1999 net_log_.EndEventWithNetErrorCode(
2000 NetLogEventType::HTTP_CACHE_NETWORK_READ_COMPLETE, result);
2001
1764 DCHECK(mode_ & WRITE || mode_ == NONE); 2002 DCHECK(mode_ & WRITE || mode_ == NONE);
1765 2003
1766 if (!cache_.get()) 2004 if (!cache_.get())
1767 return ERR_UNEXPECTED; 2005 return ERR_UNEXPECTED;
1768 2006
1769 // If there is an error or we aren't saving the data, we are done; just wait 2007 // 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. 2008 // until the destructor runs to see if we can keep the data.
1771 if (mode_ == NONE || result < 0) 2009 if (mode_ == NONE || result < 0)
1772 return result; 2010 return result;
1773 2011
1774 next_state_ = STATE_CACHE_WRITE_DATA; 2012 next_state_ = STATE_CACHE_WRITE_DATA;
1775 return result; 2013 return result;
1776 } 2014 }
1777 2015
2016 int HttpCache::Transaction::DoSharedNetworkRead() {
2017 TRACE_EVENT0("io", "HttpCacheTransaction::DoSharedNetworkRead");
2018 if (net_log_.IsCapturing())
2019 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_SHARED_NETWORK_READ);
2020
2021 next_state_ = STATE_SHARED_NETWORK_READ_COMPLETE;
2022 bool shared_read_in_progress = false;
2023 int result = entry_->shared_writers->Read(
2024 read_buf_, io_buf_len_, io_callback_, this, &shared_read_in_progress);
2025 if (shared_read_in_progress) {
2026 next_state_ = STATE_SHARED_NETWORK_READ_WAIT_COMPLETE;
2027 }
2028 return result;
2029 }
2030
2031 int HttpCache::Transaction::DoSharedNetworkReadComplete(int result) {
2032 TRACE_EVENT0("io", "HttpCacheTransaction::DoSharedNetworkReadComplete");
2033 if (net_log_.IsCapturing())
2034 net_log_.EndEventWithNetErrorCode(
2035 NetLogEventType::HTTP_CACHE_SHARED_NETWORK_READ_COMPLETE, result);
2036
2037 if (result <= 0) {
2038 // Set entry as null so that the destructor does not invoke DoneWithEntry
2039 // again as entry_ is already cleaned up by SharedWriters.
2040 entry_ = nullptr;
2041 return result;
2042 }
2043
2044 read_offset_ += result;
2045
2046 next_state_ = STATE_SHARED_CACHE_WRITE_DATA;
2047 return result;
2048 }
2049
2050 int HttpCache::Transaction::DoSharedCacheWriteData(int result) {
2051 TRACE_EVENT0("io", "HttpCacheTransaction::DoSharedCacheWriteData");
2052 if (net_log_.IsCapturing())
2053 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_SHARED_CACHE_WRITE_DATA);
2054
2055 next_state_ = STATE_SHARED_CACHE_WRITE_DATA_COMPLETE;
2056 write_len_ = result;
2057 return entry_->shared_writers->CacheWrite(read_buf_, write_len_, io_callback_,
2058 this);
2059 }
2060
2061 int HttpCache::Transaction::DoSharedCacheWriteDataComplete(int result) {
2062 TRACE_EVENT0("io", "HttpCacheTransaction::DoSharedCacheWriteDataComplete");
2063 if (net_log_.IsCapturing())
2064 net_log_.EndEventWithNetErrorCode(
2065 NetLogEventType::HTTP_CACHE_SHARED_CACHE_WRITE_DATA_COMPLETE, result);
2066
2067 OnCacheWriteDataComplete(true, &result);
2068
2069 if (result == 0) {
2070 DoneWritingToEntry(true, false);
2071 }
2072 return result;
2073 }
2074
2075 void HttpCache::Transaction::OnCacheWriteDataComplete(bool was_shared,
2076 int* result) {
2077 if (*result != write_len_) {
2078 DoneWritingToEntry(false, !was_shared);
2079 // We want to ignore errors writing to disk and just keep reading from
2080 // the network.
2081 *result = write_len_;
2082 } else if (!done_reading_ && entry_ && (!partial_ || truncated_)) {
2083 done_reading_ = cache_->IsResponseCompleted(entry_, &response_);
2084 }
2085 }
2086
2087 int HttpCache::Transaction::DoSharedNetworkReadWaitComplete(int result) {
2088 TRACE_EVENT0("io", "HttpCacheTransaction::DoSharedNetworkReadWaitComplete");
2089 if (net_log_.IsCapturing())
2090 net_log_.EndEventWithNetErrorCode(
2091 NetLogEventType::HTTP_CACHE_SHARED_NETWORK_READ_WAIT_COMPLETE, result);
2092
2093 // If its a network read failure or cache write failure, we just return the
2094 // result. If its a cache write success, read_buf_ would have been filled
2095 // with the read data by SharedWriters.
2096 if (result == 0) { // response is complete.
2097 DoneWritingToEntry(true, false); // changes the mode_ to NONE.
2098 } else if (result > 0) {
2099 read_offset_ += result;
2100 } else {
2101 // Set entry as null so that the destructor does not invoke DoneWithEntry
2102 // again as entry_ is already cleaned up by SharedWriters.
2103 entry_ = nullptr;
2104 }
2105
2106 return result;
2107 }
2108
1778 int HttpCache::Transaction::DoCacheReadData() { 2109 int HttpCache::Transaction::DoCacheReadData() {
1779 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheReadData"); 2110 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheReadData");
1780 if (request_->method == "HEAD") 2111 if (request_->method == "HEAD")
1781 return 0; 2112 return 0;
1782 2113
1783 DCHECK(entry_); 2114 DCHECK(entry_);
1784 next_state_ = STATE_CACHE_READ_DATA_COMPLETE; 2115 next_state_ = STATE_CACHE_READ_DATA_COMPLETE;
1785 2116
1786 if (net_log_.IsCapturing()) 2117 if (net_log_.IsCapturing())
1787 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_READ_DATA); 2118 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; 2160 next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE;
1830 write_len_ = num_bytes; 2161 write_len_ = num_bytes;
1831 if (entry_) { 2162 if (entry_) {
1832 if (net_log_.IsCapturing()) 2163 if (net_log_.IsCapturing())
1833 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_WRITE_DATA); 2164 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_WRITE_DATA);
1834 } 2165 }
1835 2166
1836 if (!entry_ || !num_bytes) 2167 if (!entry_ || !num_bytes)
1837 return num_bytes; 2168 return num_bytes;
1838 2169
2170 if (partial_) {
2171 return partial_->CacheWrite(entry_->disk_entry, read_buf_.get(), num_bytes,
2172 io_callback_);
2173 }
2174
1839 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); 2175 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
1840 return WriteToEntry(kResponseContentIndex, current_size, read_buf_.get(), 2176 return entry_->disk_entry->WriteData(kResponseContentIndex, current_size,
1841 num_bytes, io_callback_); 2177 read_buf_.get(), num_bytes, io_callback_,
2178 true);
1842 } 2179 }
1843 2180
1844 int HttpCache::Transaction::DoCacheWriteDataComplete(int result) { 2181 int HttpCache::Transaction::DoCacheWriteDataComplete(int result) {
1845 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteDataComplete"); 2182 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteDataComplete");
1846 if (entry_) { 2183 if (entry_) {
1847 if (net_log_.IsCapturing()) { 2184 if (net_log_.IsCapturing()) {
1848 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_DATA, 2185 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_DATA,
1849 result); 2186 result);
1850 } 2187 }
1851 } 2188 }
1852 if (!cache_.get()) 2189 if (!cache_.get())
1853 return ERR_UNEXPECTED; 2190 return ERR_UNEXPECTED;
1854 2191
1855 if (result != write_len_) { 2192 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 2193
1869 if (partial_) { 2194 if (partial_) {
1870 // This may be the last request. 2195 // This may be the last request.
1871 if (result != 0 || truncated_ || 2196 if (result != 0 || truncated_ ||
1872 !(partial_->IsLastRange() || mode_ == WRITE)) { 2197 !(partial_->IsLastRange() || mode_ == WRITE)) {
1873 return DoPartialNetworkReadCompleted(result); 2198 return DoPartialNetworkReadCompleted(result);
1874 } 2199 }
1875 } 2200 }
1876 2201
2202 // End of file. This may be the result of a connection problem so see if we
2203 // have to keep the entry around to be flagged as truncated later on.
1877 if (result == 0) { 2204 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_ || 2205 if (done_reading_ || !entry_ || partial_ ||
1881 response_.headers->GetContentLength() <= 0) { 2206 response_.headers->GetContentLength() <= 0)
1882 DoneWritingToEntry(true); 2207 DoneWritingToEntry(true);
1883 }
1884 } 2208 }
1885 2209
1886 return result; 2210 return result;
1887 } 2211 }
1888 2212
1889 int HttpCache::Transaction::DoCacheWriteTruncatedResponse() { 2213 int HttpCache::Transaction::DoCacheWriteTruncatedResponse() {
1890 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteTruncatedResponse"); 2214 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteTruncatedResponse");
1891 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE; 2215 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE;
1892 return WriteResponseInfoToEntry(true); 2216 return WriteResponseInfoToEntry(true);
1893 } 2217 }
1894 2218
1895 int HttpCache::Transaction::DoCacheWriteTruncatedResponseComplete(int result) { 2219 int HttpCache::Transaction::DoCacheWriteTruncatedResponseComplete(int result) {
1896 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteTruncatedResponse"); 2220 TRACE_EVENT0("io", "HttpCacheTransaction::DoCacheWriteTruncatedResponse");
1897 2221
1898 return OnWriteResponseInfoToEntryComplete(result); 2222 return OnWriteResponseInfoToEntryComplete(result);
1899 } 2223 }
1900 2224
2225 int HttpCache::Transaction::DoSharedReadWriteFailed() {
2226 if (net_log_.IsCapturing())
2227 net_log_.EndEventWithNetErrorCode(
2228 NetLogEventType::HTTP_CACHE_SHARED_READ_WRITE_FAILED,
2229 shared_read_write_failure_result_);
2230
2231 return shared_read_write_failure_result_;
2232 }
2233
1901 //----------------------------------------------------------------------------- 2234 //-----------------------------------------------------------------------------
1902 2235
1903 void HttpCache::Transaction::SetRequest(const NetLogWithSource& net_log, 2236 void HttpCache::Transaction::SetRequest(const NetLogWithSource& net_log,
1904 const HttpRequestInfo* request) { 2237 const HttpRequestInfo* request) {
1905 net_log_ = net_log; 2238 net_log_ = net_log;
1906 request_ = request; 2239 request_ = request;
1907 effective_load_flags_ = request_->load_flags; 2240 effective_load_flags_ = request_->load_flags;
1908 2241
1909 if (cache_->mode() == DISABLE) 2242 if (cache_->mode() == DISABLE)
1910 effective_load_flags_ |= LOAD_DISABLE_CACHE; 2243 effective_load_flags_ |= LOAD_DISABLE_CACHE;
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
2084 2417
2085 if (partial_ && (is_sparse_ || truncated_) && 2418 if (partial_ && (is_sparse_ || truncated_) &&
2086 (!partial_->IsCurrentRangeCached() || invalid_range_)) { 2419 (!partial_->IsCurrentRangeCached() || invalid_range_)) {
2087 // Force revalidation for sparse or truncated entries. Note that we don't 2420 // 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 2421 // want to ignore the regular validation logic just because a byte range was
2089 // part of the request. 2422 // part of the request.
2090 skip_validation = false; 2423 skip_validation = false;
2091 } 2424 }
2092 2425
2093 if (skip_validation) { 2426 if (skip_validation) {
2094 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_USED); 2427 if (shared_) {
2095 return SetupEntryForRead(); 2428 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_JOIN_SHARED_WRITING);
2429 entry_->shared_writers->OnValidationMatch(this, priority_);
2430 } else {
2431 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_USED);
2432 return SetupEntryForRead();
2433 }
2096 } else { 2434 } else {
2097 // Make the network request conditional, to see if we may reuse our cached 2435 // 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. 2436 // 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 2437 // Our mode remains READ_WRITE for a conditional request. Even if the
2100 // conditionalization fails, we don't switch to WRITE mode until we 2438 // 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 2439 // know we won't be falling back to using the cache entry in the
2102 // LOAD_FROM_CACHE_IF_OFFLINE case. 2440 // LOAD_FROM_CACHE_IF_OFFLINE case.
2103 if (!ConditionalizeRequest()) { 2441 if (!ConditionalizeRequest()) {
2104 couldnt_conditionalize_request_ = true; 2442 couldnt_conditionalize_request_ = true;
2105 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE); 2443 UpdateCacheEntryStatus(CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE);
(...skipping 498 matching lines...) Expand 10 before | Expand all | Expand 10 after
2604 IsCertStatusError(response_.ssl_info.cert_status)) { 2942 IsCertStatusError(response_.ssl_info.cert_status)) {
2605 DoneWritingToEntry(false); 2943 DoneWritingToEntry(false);
2606 if (net_log_.IsCapturing()) 2944 if (net_log_.IsCapturing())
2607 net_log_.EndEvent(NetLogEventType::HTTP_CACHE_WRITE_INFO); 2945 net_log_.EndEvent(NetLogEventType::HTTP_CACHE_WRITE_INFO);
2608 return OK; 2946 return OK;
2609 } 2947 }
2610 2948
2611 if (truncated) 2949 if (truncated)
2612 DCHECK_EQ(200, response_.headers->response_code()); 2950 DCHECK_EQ(200, response_.headers->response_code());
2613 2951
2614 // When writing headers, we normally only write the non-transient headers. 2952 return cache_->WriteResponseInfo(entry_, &response_, io_callback_, truncated,
2615 bool skip_transient_headers = true; 2953 &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 } 2954 }
2624 2955
2625 int HttpCache::Transaction::OnWriteResponseInfoToEntryComplete(int result) { 2956 int HttpCache::Transaction::OnWriteResponseInfoToEntryComplete(int result) {
2626 if (!entry_) 2957 if (!entry_)
2627 return OK; 2958 return OK;
2628 if (net_log_.IsCapturing()) { 2959 if (net_log_.IsCapturing()) {
2629 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO, 2960 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO,
2630 result); 2961 result);
2631 } 2962 }
2632 2963
2633 if (result != io_buf_len_) { 2964 if (result != io_buf_len_) {
2634 DLOG(ERROR) << "failed to write response info to cache"; 2965 DLOG(ERROR) << "failed to write response info to cache";
2635 DoneWritingToEntry(false); 2966 DoneWritingToEntry(false);
2636 } 2967 }
2637 return OK; 2968 return OK;
2638 } 2969 }
2639 2970
2640 void HttpCache::Transaction::DoneWritingToEntry(bool success) { 2971 void HttpCache::Transaction::DoneWritingToEntry(bool success,
2972 bool perform_entry_cleanup) {
2641 if (!entry_) 2973 if (!entry_)
2642 return; 2974 return;
2643 2975
2644 RecordHistograms(); 2976 RecordHistograms();
2645 2977
2646 cache_->DoneWritingToEntry(entry_, success); 2978 if (perform_entry_cleanup) {
2647 entry_ = NULL; 2979 cache_->DoneWritingToEntry(entry_, success);
2980 }
2981 entry_ = nullptr;
2648 mode_ = NONE; // switch to 'pass through' mode 2982 mode_ = NONE; // switch to 'pass through' mode
2649 } 2983 }
2650 2984
2985 void HttpCache::Transaction::ContinueWithoutSharedWriting(
2986 std::unique_ptr<HttpTransaction> network_transaction,
2987 bool needs_entry) {
2988 shared_ = false;
2989 if (!needs_entry)
2990 entry_ = nullptr;
2991 mode_ = NONE;
2992 network_trans_ = std::move(network_transaction);
2993 }
2994
2651 int HttpCache::Transaction::OnCacheReadError(int result, bool restart) { 2995 int HttpCache::Transaction::OnCacheReadError(int result, bool restart) {
2652 DLOG(ERROR) << "ReadData failed: " << result; 2996 DLOG(ERROR) << "ReadData failed: " << result;
2653 const int result_for_histogram = std::max(0, -result); 2997 const int result_for_histogram = std::max(0, -result);
2654 if (restart) { 2998 if (restart) {
2655 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorRestartable", 2999 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorRestartable",
2656 result_for_histogram); 3000 result_for_histogram);
2657 } else { 3001 } else {
2658 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorNonRestartable", 3002 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorNonRestartable",
2659 result_for_histogram); 3003 result_for_histogram);
2660 } 3004 }
2661 3005
2662 // Avoid using this entry in the future. 3006 // Avoid using this entry in the future.
2663 if (cache_.get()) 3007 if (cache_.get())
2664 cache_->DoomActiveEntry(cache_key_); 3008 cache_->DoomActiveEntry(cache_key_);
2665 3009
2666 if (restart) { 3010 if (restart) {
2667 DCHECK(!reading_); 3011 DCHECK(!reading_);
2668 DCHECK(!network_trans_.get()); 3012 DCHECK(!network_trans_.get());
2669 cache_->DoneWithEntry(entry_, this, false); 3013 if (shared_) {
3014 entry_->shared_writers->RemoveValidatingTransaction(this);
3015 } else {
3016 cache_->DoneWithEntry(entry_, this, false);
3017 }
2670 entry_ = NULL; 3018 entry_ = NULL;
2671 is_sparse_ = false; 3019 is_sparse_ = false;
2672 partial_.reset(); 3020 partial_.reset();
2673 next_state_ = STATE_GET_BACKEND; 3021 next_state_ = STATE_GET_BACKEND;
2674 return OK; 3022 return OK;
2675 } 3023 }
2676 3024
2677 return ERR_CACHE_READ_FAILURE; 3025 return ERR_CACHE_READ_FAILURE;
2678 } 3026 }
2679 3027
2680 void HttpCache::Transaction::OnAddToEntryTimeout(base::TimeTicks start_time) { 3028 void HttpCache::Transaction::OnAddToEntryTimeout(base::TimeTicks start_time) {
2681 if (entry_lock_waiting_since_ != start_time) 3029 if (entry_lock_waiting_since_ != start_time)
2682 return; 3030 return;
2683 3031
2684 DCHECK_EQ(next_state_, STATE_ADD_TO_ENTRY_COMPLETE); 3032 DCHECK_EQ(next_state_, STATE_ADD_TO_ENTRY_COMPLETE);
2685 3033
2686 if (!cache_) 3034 if (!cache_)
2687 return; 3035 return;
2688 3036
2689 cache_->RemovePendingTransaction(this); 3037 cache_->RemovePendingTransaction(this);
2690 OnIOComplete(ERR_CACHE_LOCK_TIMEOUT); 3038 OnIOComplete(ERR_CACHE_LOCK_TIMEOUT);
2691 } 3039 }
2692 3040
2693 void HttpCache::Transaction::DoomPartialEntry(bool delete_object) { 3041 void HttpCache::Transaction::DoomPartialEntry(bool delete_object) {
3042 // Partial requests not supported with shared writing as of now.
3043 DCHECK(!shared_);
2694 DVLOG(2) << "DoomPartialEntry"; 3044 DVLOG(2) << "DoomPartialEntry";
2695 int rv = cache_->DoomEntry(cache_key_, NULL); 3045 int rv = cache_->DoomEntry(cache_key_, NULL);
2696 DCHECK_EQ(OK, rv); 3046 DCHECK_EQ(OK, rv);
2697 cache_->DoneWithEntry(entry_, this, false); 3047 cache_->DoneWithEntry(entry_, this, false);
2698 entry_ = NULL; 3048 entry_ = NULL;
2699 is_sparse_ = false; 3049 is_sparse_ = false;
2700 truncated_ = false; 3050 truncated_ = false;
2701 if (delete_object) 3051 if (delete_object)
2702 partial_.reset(NULL); 3052 partial_.reset(NULL);
2703 } 3053 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2744 if (!delete_object) { 3094 if (!delete_object) {
2745 // The simplest way to re-initialize partial_ is to create a new object. 3095 // The simplest way to re-initialize partial_ is to create a new object.
2746 partial_.reset(new PartialData()); 3096 partial_.reset(new PartialData());
2747 if (partial_->Init(request_->extra_headers)) 3097 if (partial_->Init(request_->extra_headers))
2748 partial_->SetHeaders(custom_request_->extra_headers); 3098 partial_->SetHeaders(custom_request_->extra_headers);
2749 else 3099 else
2750 partial_.reset(); 3100 partial_.reset();
2751 } 3101 }
2752 } 3102 }
2753 3103
2754 void HttpCache::Transaction::ResetNetworkTransaction() { 3104 void HttpCache::Transaction::SaveNetworkTransactionInfo(
3105 const HttpTransaction* transaction) {
2755 DCHECK(!old_network_trans_load_timing_); 3106 DCHECK(!old_network_trans_load_timing_);
2756 DCHECK(network_trans_); 3107 DCHECK(transaction);
2757 LoadTimingInfo load_timing; 3108 LoadTimingInfo load_timing;
2758 if (network_trans_->GetLoadTimingInfo(&load_timing)) 3109 if (transaction->GetLoadTimingInfo(&load_timing))
2759 old_network_trans_load_timing_.reset(new LoadTimingInfo(load_timing)); 3110 old_network_trans_load_timing_.reset(new LoadTimingInfo(load_timing));
2760 total_received_bytes_ += network_trans_->GetTotalReceivedBytes(); 3111 total_received_bytes_ += transaction->GetTotalReceivedBytes();
2761 total_sent_bytes_ += network_trans_->GetTotalSentBytes(); 3112 total_sent_bytes_ += transaction->GetTotalSentBytes();
2762 ConnectionAttempts attempts; 3113 ConnectionAttempts attempts;
2763 network_trans_->GetConnectionAttempts(&attempts); 3114 transaction->GetConnectionAttempts(&attempts);
2764 for (const auto& attempt : attempts) 3115 for (const auto& attempt : attempts)
2765 old_connection_attempts_.push_back(attempt); 3116 old_connection_attempts_.push_back(attempt);
2766 old_remote_endpoint_ = IPEndPoint(); 3117 old_remote_endpoint_ = IPEndPoint();
2767 network_trans_->GetRemoteEndpoint(&old_remote_endpoint_); 3118 transaction->GetRemoteEndpoint(&old_remote_endpoint_);
3119 }
3120
3121 void HttpCache::Transaction::SaveSharedNetworkTransactionInfo() {
3122 // If network_trans_ is still present, this transaction has not started using
3123 // the "shared" network transaction.
3124 if (network_trans_) {
3125 SaveNetworkTransactionInfo(network_trans_.get());
3126 return;
3127 }
3128
3129 DCHECK(!old_network_trans_load_timing_);
3130
3131 // If the transaction is being deleted while still in the waiting queue,
3132 // entry_ is not yet set, do nothing.
3133 if (!entry_)
3134 return;
3135 DCHECK(entry_->shared_writers);
3136 HttpTransaction* network_transaction =
3137 entry_->shared_writers->network_transaction();
3138 SaveNetworkTransactionInfo(network_transaction);
3139 have_full_request_headers_ =
3140 network_transaction->GetFullRequestHeaders(&full_request_headers_);
3141 }
3142
3143 void HttpCache::Transaction::ResetNetworkTransaction() {
3144 SaveNetworkTransactionInfo(network_trans_.get());
2768 network_trans_.reset(); 3145 network_trans_.reset();
2769 } 3146 }
2770 3147
2771 // Histogram data from the end of 2010 show the following distribution of 3148 HttpTransaction* HttpCache::Transaction::GetCurrentNetworkTransaction() const {
2772 // response headers: 3149 if (network_trans_)
2773 // 3150 return network_trans_.get();
2774 // Content-Length............... 87% 3151 if (shared_ && entry_ && entry_->shared_writers)
2775 // Date......................... 98% 3152 return entry_->shared_writers->network_transaction();
2776 // Last-Modified................ 49% 3153 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 } 3154 }
2802 3155
2803 void HttpCache::Transaction::SetResponse(const HttpResponseInfo& response) { 3156 void HttpCache::Transaction::SetResponse(const HttpResponseInfo& response) {
2804 response_ = response; 3157 response_ = response;
2805 SyncCacheEntryStatusToResponse(); 3158 SyncCacheEntryStatusToResponse();
2806 } 3159 }
2807 3160
2808 void HttpCache::Transaction::SetAuthResponse( 3161 void HttpCache::Transaction::SetAuthResponse(
2809 const HttpResponseInfo& auth_response) { 3162 const HttpResponseInfo& auth_response) {
2810 auth_response_ = auth_response; 3163 auth_response_ = auth_response;
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
2916 } 3269 }
2917 } 3270 }
2918 3271
2919 CACHE_STATUS_HISTOGRAMS(""); 3272 CACHE_STATUS_HISTOGRAMS("");
2920 3273
2921 if (cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE) { 3274 if (cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE) {
2922 UMA_HISTOGRAM_ENUMERATION("HttpCache.CantConditionalizeCause", 3275 UMA_HISTOGRAM_ENUMERATION("HttpCache.CantConditionalizeCause",
2923 validation_cause_, VALIDATION_CAUSE_MAX); 3276 validation_cause_, VALIDATION_CAUSE_MAX);
2924 } 3277 }
2925 3278
3279 // This may also exclude shared writing counts for these cases.
2926 if (cache_entry_status_ == CacheEntryStatus::ENTRY_OTHER) 3280 if (cache_entry_status_ == CacheEntryStatus::ENTRY_OTHER)
2927 return; 3281 return;
3282
2928 DCHECK(!range_requested_); 3283 DCHECK(!range_requested_);
2929 DCHECK(!first_cache_access_since_.is_null()); 3284 DCHECK(!first_cache_access_since_.is_null());
2930 3285
2931 TimeDelta total_time = base::TimeTicks::Now() - first_cache_access_since_; 3286 TimeDelta total_time = base::TimeTicks::Now() - first_cache_access_since_;
2932 3287
2933 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone", total_time); 3288 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone", total_time);
2934 3289
3290 if (cache_entry_status_ == CacheEntryStatus::ENTRY_JOIN_SHARED_WRITING) {
3291 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.JoinSharedWriting", total_time);
3292 } else if (cache_entry_status_ ==
3293 CacheEntryStatus::ENTRY_DOOM_SHARED_WRITING) {
3294 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.DoomSharedWriting", total_time);
3295 } else if (initiate_shared_writing_) {
3296 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.InitiateSharedWriting",
3297 total_time);
3298 }
3299
2935 bool did_send_request = !send_request_since_.is_null(); 3300 bool did_send_request = !send_request_since_.is_null();
2936 DCHECK( 3301 DCHECK(
2937 (did_send_request && 3302 (did_send_request &&
2938 (cache_entry_status_ == CacheEntryStatus::ENTRY_NOT_IN_CACHE || 3303 (cache_entry_status_ == CacheEntryStatus::ENTRY_NOT_IN_CACHE ||
2939 cache_entry_status_ == CacheEntryStatus::ENTRY_VALIDATED || 3304 cache_entry_status_ == CacheEntryStatus::ENTRY_VALIDATED ||
2940 cache_entry_status_ == CacheEntryStatus::ENTRY_UPDATED || 3305 cache_entry_status_ == CacheEntryStatus::ENTRY_UPDATED ||
2941 cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE)) || 3306 cache_entry_status_ == CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE ||
3307 cache_entry_status_ == CacheEntryStatus::ENTRY_JOIN_SHARED_WRITING ||
3308 cache_entry_status_ == CacheEntryStatus::ENTRY_DOOM_SHARED_WRITING)) ||
2942 (!did_send_request && 3309 (!did_send_request &&
2943 cache_entry_status_ == CacheEntryStatus::ENTRY_USED)); 3310 (cache_entry_status_ == CacheEntryStatus::ENTRY_USED ||
3311 cache_entry_status_ == CacheEntryStatus::ENTRY_JOIN_SHARED_WRITING)));
2944 3312
2945 if (!did_send_request) { 3313 if (!did_send_request) {
2946 DCHECK(cache_entry_status_ == CacheEntryStatus::ENTRY_USED); 3314 if (cache_entry_status_ == CacheEntryStatus::ENTRY_USED) {
2947 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.Used", total_time); 3315 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.Used", total_time);
3316 }
2948 return; 3317 return;
2949 } 3318 }
2950 3319
2951 TimeDelta before_send_time = send_request_since_ - first_cache_access_since_; 3320 TimeDelta before_send_time = send_request_since_ - first_cache_access_since_;
2952 int64_t before_send_percent = (total_time.ToInternalValue() == 0) 3321 int64_t before_send_percent = (total_time.ToInternalValue() == 0)
2953 ? 0 3322 ? 0
2954 : before_send_time * 100 / total_time; 3323 : before_send_time * 100 / total_time;
2955 DCHECK_GE(before_send_percent, 0); 3324 DCHECK_GE(before_send_percent, 0);
2956 DCHECK_LE(before_send_percent, 100); 3325 DCHECK_LE(before_send_percent, 100);
2957 base::HistogramBase::Sample before_send_sample = 3326 base::HistogramBase::Sample before_send_sample =
2958 static_cast<base::HistogramBase::Sample>(before_send_percent); 3327 static_cast<base::HistogramBase::Sample>(before_send_percent);
2959 3328
2960 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.SentRequest", total_time); 3329 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone.SentRequest", total_time);
2961 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend", before_send_time); 3330 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend", before_send_time);
2962 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend", before_send_sample); 3331 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend", before_send_sample);
2963 3332
2964 // TODO(gavinp): Remove or minimize these histograms, particularly the ones 3333 // TODO(gavinp): Remove or minimize these histograms, particularly the ones
2965 // below this comment after we have received initial data. 3334 // below this comment after we have received initial data.
2966 switch (cache_entry_status_) { 3335 switch (cache_entry_status_) {
2967 case CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE: { 3336 case CacheEntryStatus::ENTRY_CANT_CONDITIONALIZE: {
2968 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.CantConditionalize", 3337 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.CantConditionalize",
2969 before_send_time); 3338 before_send_time);
2970 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.CantConditionalize", 3339 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.CantConditionalize",
2971 before_send_sample); 3340 before_send_sample);
3341 if (initiate_shared_writing_) {
3342 UMA_HISTOGRAM_TIMES(
3343 "HttpCache.BeforeSend.CantConditionalize.InitiateSharedWriting",
3344 before_send_time);
3345 UMA_HISTOGRAM_PERCENTAGE(
3346 "HttpCache.PercentBeforeSend.CantConditionalize."
3347 "InitiateSharedWriting",
3348 before_send_sample);
3349 }
3350
2972 break; 3351 break;
2973 } 3352 }
2974 case CacheEntryStatus::ENTRY_NOT_IN_CACHE: { 3353 case CacheEntryStatus::ENTRY_NOT_IN_CACHE: {
2975 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.NotCached", before_send_time); 3354 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.NotCached", before_send_time);
2976 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.NotCached", 3355 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.NotCached",
2977 before_send_sample); 3356 before_send_sample);
3357 if (initiate_shared_writing_) {
3358 UMA_HISTOGRAM_TIMES(
3359 "HttpCache.BeforeSend.NotCached.InitiateSharedWriting",
3360 before_send_time);
3361 UMA_HISTOGRAM_PERCENTAGE(
3362 "HttpCache.PercentBeforeSend.NotCached.InitiateSharedWriting",
3363 before_send_sample);
3364 }
3365
2978 break; 3366 break;
2979 } 3367 }
2980 case CacheEntryStatus::ENTRY_VALIDATED: { 3368 case CacheEntryStatus::ENTRY_VALIDATED: {
2981 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Validated", before_send_time); 3369 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Validated", before_send_time);
2982 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.Validated", 3370 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.Validated",
2983 before_send_sample); 3371 before_send_sample);
2984 break; 3372 break;
2985 } 3373 }
2986 case CacheEntryStatus::ENTRY_UPDATED: { 3374 case CacheEntryStatus::ENTRY_UPDATED: {
2987 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Updated", before_send_time); 3375 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Updated", before_send_time);
2988 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.Updated", 3376 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.Updated",
2989 before_send_sample); 3377 before_send_sample);
3378 if (initiate_shared_writing_) {
3379 UMA_HISTOGRAM_TIMES(
3380 "HttpCache.BeforeSend.Updated.InitiateSharedWriting",
3381 before_send_time);
3382 UMA_HISTOGRAM_PERCENTAGE(
3383 "HttpCache.PercentBeforeSend.Updated.InitiateSharedWriting",
3384 before_send_sample);
3385 }
3386 break;
3387 }
3388 case CacheEntryStatus::ENTRY_JOIN_SHARED_WRITING: {
3389 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.JoinSharedWriting",
3390 before_send_time);
3391 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.JoinSharedWriting",
3392 before_send_sample);
3393 break;
3394 }
3395 case CacheEntryStatus::ENTRY_DOOM_SHARED_WRITING: {
3396 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.DoomSharedWriting",
3397 before_send_time);
3398 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.DoomSharedWriting",
3399 before_send_sample);
2990 break; 3400 break;
2991 } 3401 }
2992 default: 3402 default:
2993 NOTREACHED(); 3403 NOTREACHED();
2994 } 3404 }
2995 } 3405 }
2996 3406
3407 bool HttpCache::Transaction::IsEligibleForSharedWriting() const {
3408 if (!(mode_ & WRITE))
3409 return false;
3410
3411 DCHECK(request_);
3412 if (request_->method != "GET")
3413 return false;
3414
3415 if (partial_ || range_requested_)
3416 return false;
3417
3418 if (truncated_)
3419 return false;
3420
3421 return true;
3422 }
3423
3424 void HttpCache::Transaction::SetSharedWritingFailState(int result) {
3425 next_state_ = STATE_SHARED_READ_WRITE_FAILED;
3426 shared_read_write_failure_result_ = result;
3427 entry_ = nullptr;
3428 }
3429
2997 void HttpCache::Transaction::OnIOComplete(int result) { 3430 void HttpCache::Transaction::OnIOComplete(int result) {
2998 DoLoop(result); 3431 DoLoop(result);
2999 } 3432 }
3000 3433
3001 } // namespace net 3434 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698