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

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

Issue 1230113012: [net] Better StopCaching() handling for HttpCache::Transaction. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 3 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>
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 reading_(false), 259 reading_(false),
260 invalid_range_(false), 260 invalid_range_(false),
261 truncated_(false), 261 truncated_(false),
262 is_sparse_(false), 262 is_sparse_(false),
263 range_requested_(false), 263 range_requested_(false),
264 handling_206_(false), 264 handling_206_(false),
265 cache_pending_(false), 265 cache_pending_(false),
266 done_reading_(false), 266 done_reading_(false),
267 vary_mismatch_(false), 267 vary_mismatch_(false),
268 couldnt_conditionalize_request_(false), 268 couldnt_conditionalize_request_(false),
269 stopped_caching_(false),
269 bypass_lock_for_test_(false), 270 bypass_lock_for_test_(false),
270 fail_conditionalization_for_test_(false), 271 fail_conditionalization_for_test_(false),
272 read_buf_len_(0),
271 io_buf_len_(0), 273 io_buf_len_(0),
272 read_offset_(0), 274 read_offset_(0),
273 effective_load_flags_(0), 275 effective_load_flags_(0),
274 write_len_(0), 276 write_len_(0),
275 transaction_pattern_(PATTERN_UNDEFINED), 277 transaction_pattern_(PATTERN_UNDEFINED),
276 total_received_bytes_(0), 278 total_received_bytes_(0),
277 websocket_handshake_stream_base_create_helper_(NULL), 279 websocket_handshake_stream_base_create_helper_(NULL),
278 weak_factory_(this) { 280 weak_factory_(this) {
279 static_assert(HttpCache::Transaction::kNumValidationHeaders == 281 static_assert(HttpCache::Transaction::kNumValidationHeaders ==
280 arraysize(kValidationHeaders), 282 arraysize(kValidationHeaders),
281 "invalid number of validation headers"); 283 "invalid number of validation headers");
282 284
283 io_callback_ = base::Bind(&Transaction::OnIOComplete, 285 io_callback_ = base::Bind(&Transaction::OnIOComplete,
284 weak_factory_.GetWeakPtr()); 286 weak_factory_.GetWeakPtr());
285 } 287 }
286 288
287 HttpCache::Transaction::~Transaction() { 289 HttpCache::Transaction::~Transaction() {
288 // We may have to issue another IO, but we should never invoke the callback_ 290 // We may have to issue another IO, but we should never invoke the callback_
289 // after this point. 291 // after this point.
290 callback_.Reset(); 292 callback_.Reset();
291 293
292 if (cache_) { 294 RecordHistograms();
293 if (entry_) {
294 bool cancel_request = reading_ && response_.headers.get();
295 if (cancel_request) {
296 if (partial_) {
297 entry_->disk_entry->CancelSparseIO();
298 } else {
299 cancel_request &= (response_.headers->response_code() == 200);
300 }
301 }
302 295
303 cache_->DoneWithEntry(entry_, this, cancel_request); 296 if (!cache_)
304 } else if (cache_pending_) { 297 return;
298
299 if (!entry_) {
300 if (cache_pending_)
305 cache_->RemovePendingTransaction(this); 301 cache_->RemovePendingTransaction(this);
306 } 302 return;
307 } 303 }
304
305 bool cancel_request = reading_ && response_.headers.get() &&
306 (response_.headers->response_code() == 200 || partial_);
307 if (cancel_request) {
308 if (partial_)
309 entry_->disk_entry->CancelSparseIO();
310
311 AbandonCacheEntry(CompletionCallback());
312 return;
313 }
314
315 ReleaseCacheEntry(EntryState::DOOMED);
308 } 316 }
309 317
310 int HttpCache::Transaction::WriteMetadata(IOBuffer* buf, int buf_len, 318 int HttpCache::Transaction::WriteMetadata(IOBuffer* buf, int buf_len,
311 const CompletionCallback& callback) { 319 const CompletionCallback& callback) {
312 DCHECK(buf); 320 DCHECK(buf);
313 DCHECK_GT(buf_len, 0); 321 DCHECK_GT(buf_len, 0);
314 DCHECK(!callback.is_null()); 322 DCHECK(!callback.is_null());
315 if (!cache_.get() || !entry_) 323 if (!cache_.get() || !entry_)
316 return ERR_UNEXPECTED; 324 return ERR_UNEXPECTED;
317 325
318 // We don't need to track this operation for anything. 326 // We don't need to track this operation for anything.
319 // It could be possible to check if there is something already written and 327 // It could be possible to check if there is something already written and
320 // avoid writing again (it should be the same, right?), but let's allow the 328 // avoid writing again (it should be the same, right?), but let's allow the
321 // caller to "update" the contents with something new. 329 // caller to "update" the contents with something new.
322 return entry_->disk_entry->WriteData(kMetadataIndex, 0, buf, buf_len, 330 return entry_->disk_entry->WriteData(kMetadataIndex, 0, buf, buf_len,
323 callback, true); 331 callback, true);
324 } 332 }
325 333
326 bool HttpCache::Transaction::AddTruncatedFlag() {
327 DCHECK(mode_ & WRITE || mode_ == NONE);
328
329 // Don't set the flag for sparse entries.
330 if (partial_ && !truncated_)
331 return true;
332
333 if (!CanResume(true))
334 return false;
335
336 // We may have received the whole resource already.
337 if (done_reading_)
338 return true;
339
340 truncated_ = true;
341 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE;
342 DoLoop(OK);
343 return true;
344 }
345
346 LoadState HttpCache::Transaction::GetWriterLoadState() const { 334 LoadState HttpCache::Transaction::GetWriterLoadState() const {
347 if (network_trans_.get()) 335 if (network_trans_.get())
348 return network_trans_->GetLoadState(); 336 return network_trans_->GetLoadState();
349 if (entry_ || !request_) 337 if (entry_ || !request_)
350 return LOAD_STATE_IDLE; 338 return LOAD_STATE_IDLE;
351 return LOAD_STATE_WAITING_FOR_CACHE; 339 return LOAD_STATE_WAITING_FOR_CACHE;
352 } 340 }
353 341
354 const BoundNetLog& HttpCache::Transaction::net_log() const { 342 const BoundNetLog& HttpCache::Transaction::net_log() const {
355 return net_log_; 343 return net_log_;
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 return false; 438 return false;
451 return network_trans_->IsReadyToRestartForAuth(); 439 return network_trans_->IsReadyToRestartForAuth();
452 } 440 }
453 441
454 int HttpCache::Transaction::Read(IOBuffer* buf, int buf_len, 442 int HttpCache::Transaction::Read(IOBuffer* buf, int buf_len,
455 const CompletionCallback& callback) { 443 const CompletionCallback& callback) {
456 DCHECK_EQ(next_state_, STATE_NONE); 444 DCHECK_EQ(next_state_, STATE_NONE);
457 DCHECK(buf); 445 DCHECK(buf);
458 DCHECK_GT(buf_len, 0); 446 DCHECK_GT(buf_len, 0);
459 DCHECK(!callback.is_null()); 447 DCHECK(!callback.is_null());
460
461 DCHECK(callback_.is_null()); 448 DCHECK(callback_.is_null());
462 449
463 if (!cache_.get()) 450 if (!cache_.get())
464 return ERR_UNEXPECTED; 451 return ERR_UNEXPECTED;
465 452
466 // If we have an intermediate auth response at this point, then it means the 453 // If we have an intermediate auth response at this point, then it means the
467 // user wishes to read the network response (the error page). If there is a 454 // user wishes to read the network response (the error page). If there is a
468 // previous response in the cache then we should leave it intact. 455 // previous response in the cache then we should leave it intact.
469 if (auth_response_.headers.get() && mode_ != NONE) { 456 if (auth_response_.headers.get() && mode_ != NONE) {
470 UpdateTransactionPattern(PATTERN_NOT_COVERED); 457 UpdateTransactionPattern(PATTERN_NOT_COVERED);
471 DCHECK(mode_ & WRITE); 458 DCHECK(mode_ & WRITE);
472 DoneWritingToEntry(mode_ == READ_WRITE); 459 ReleaseCacheEntry(mode_ == READ_WRITE ? EntryState::SUCCEEDED
473 mode_ = NONE; 460 : EntryState::DOOMED);
474 } 461 }
475 462
476 reading_ = true; 463 reading_ = true;
477 read_buf_ = buf; 464 read_buf_ = buf;
478 io_buf_len_ = buf_len; 465 read_buf_len_ = buf_len;
rvargas (doing something else) 2015/09/11 23:56:18 Why do we need another member? (vs io_buf_len_)
asanka 2015/09/17 21:59:41 When we are switching to a single network request,
rvargas (doing something else) 2015/09/21 22:05:59 Acknowledged.
479 if (network_trans_) { 466 if (stopped_caching_ && (mode_ & WRITE) && entry_) {
rvargas (doing something else) 2015/09/11 23:56:18 Shouldn't this look closer to line 1483? (aka, wha
467 next_state_ = STATE_SWITCH_TO_NETWORK;
468 } else if (network_trans_) {
480 DCHECK(mode_ == WRITE || mode_ == NONE || 469 DCHECK(mode_ == WRITE || mode_ == NONE ||
481 (mode_ == READ_WRITE && partial_)); 470 (mode_ == READ_WRITE && partial_));
482 next_state_ = STATE_NETWORK_READ; 471 next_state_ = STATE_NETWORK_READ;
483 } else { 472 } else {
484 DCHECK(mode_ == READ || (mode_ == READ_WRITE && partial_)); 473 DCHECK(mode_ == READ || (mode_ == READ_WRITE && partial_));
485 next_state_ = STATE_CACHE_READ_DATA; 474 next_state_ = STATE_CACHE_READ_DATA;
486 } 475 }
487 476
488 int rv = DoLoop(OK); 477 int rv = DoLoop(OK);
489 478
490 if (rv == ERR_IO_PENDING) { 479 if (rv == ERR_IO_PENDING) {
491 DCHECK(callback_.is_null()); 480 DCHECK(callback_.is_null());
492 callback_ = callback; 481 callback_ = callback;
493 } 482 }
494 return rv; 483 return rv;
495 } 484 }
496 485
497 void HttpCache::Transaction::StopCaching() { 486 void HttpCache::Transaction::StopCaching() {
498 // We really don't know where we are now. Hopefully there is no operation in 487 DCHECK(callback_.is_null());
499 // progress, but nothing really prevents this method to be called after we 488 stopped_caching_ = true;
500 // returned ERR_IO_PENDING. We cannot attempt to truncate the entry at this
501 // point because we need the state machine for that (and even if we are really
502 // free, that would be an asynchronous operation). In other words, keep the
503 // entry how it is (it will be marked as truncated at destruction), and let
504 // the next piece of code that executes know that we are now reading directly
505 // from the net.
506 // TODO(mmenke): This doesn't release the lock on the cache entry, so a
507 // future request for the resource will be blocked on this one.
508 // Fix this.
509 if (cache_.get() && entry_ && (mode_ & WRITE) && network_trans_.get() &&
510 !is_sparse_ && !range_requested_) {
511 mode_ = NONE;
512 }
513 } 489 }
514 490
515 bool HttpCache::Transaction::GetFullRequestHeaders( 491 bool HttpCache::Transaction::GetFullRequestHeaders(
516 HttpRequestHeaders* headers) const { 492 HttpRequestHeaders* headers) const {
517 if (network_trans_) 493 if (network_trans_)
518 return network_trans_->GetFullRequestHeaders(headers); 494 return network_trans_->GetFullRequestHeaders(headers);
519 495
520 // TODO(ttuttle): Read headers from cache. 496 // TODO(ttuttle): Read headers from cache.
521 return false; 497 return false;
522 } 498 }
523 499
524 int64 HttpCache::Transaction::GetTotalReceivedBytes() const { 500 int64 HttpCache::Transaction::GetTotalReceivedBytes() const {
525 int64 total_received_bytes = total_received_bytes_; 501 int64 total_received_bytes = total_received_bytes_;
526 if (network_trans_) 502 if (network_trans_)
527 total_received_bytes += network_trans_->GetTotalReceivedBytes(); 503 total_received_bytes += network_trans_->GetTotalReceivedBytes();
528 return total_received_bytes; 504 return total_received_bytes;
529 } 505 }
530 506
531 void HttpCache::Transaction::DoneReading() { 507 void HttpCache::Transaction::DoneReading() {
532 if (cache_.get() && entry_) { 508 DCHECK_NE(mode_, UPDATE);
533 DCHECK_NE(mode_, UPDATE); 509 if (!cache_ || !entry_)
534 if (mode_ & WRITE) { 510 return;
535 DoneWritingToEntry(true); 511 done_reading_ = true;
536 } else if (mode_ & READ) { 512 ReleaseCacheEntry(EntryState::SUCCEEDED);
537 // It is necessary to check mode_ & READ because it is possible
538 // for mode_ to be NONE and entry_ non-NULL with a write entry
539 // if StopCaching was called.
540 cache_->DoneReadingFromEntry(entry_, this);
541 entry_ = NULL;
542 }
543 }
544 } 513 }
545 514
546 const HttpResponseInfo* HttpCache::Transaction::GetResponseInfo() const { 515 const HttpResponseInfo* HttpCache::Transaction::GetResponseInfo() const {
547 // Null headers means we encountered an error or haven't a response yet 516 // Null headers means we encountered an error or haven't a response yet
548 if (auth_response_.headers.get()) 517 if (auth_response_.headers.get())
549 return &auth_response_; 518 return &auth_response_;
550 return &response_; 519 return &response_;
551 } 520 }
552 521
553 LoadState HttpCache::Transaction::GetLoadState() const { 522 LoadState HttpCache::Transaction::GetLoadState() const {
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
895 DCHECK_EQ(OK, rv); 864 DCHECK_EQ(OK, rv);
896 rv = DoPartialHeadersReceived(); 865 rv = DoPartialHeadersReceived();
897 break; 866 break;
898 case STATE_CACHE_READ_METADATA: 867 case STATE_CACHE_READ_METADATA:
899 DCHECK_EQ(OK, rv); 868 DCHECK_EQ(OK, rv);
900 rv = DoCacheReadMetadata(); 869 rv = DoCacheReadMetadata();
901 break; 870 break;
902 case STATE_CACHE_READ_METADATA_COMPLETE: 871 case STATE_CACHE_READ_METADATA_COMPLETE:
903 rv = DoCacheReadMetadataComplete(rv); 872 rv = DoCacheReadMetadataComplete(rv);
904 break; 873 break;
874 case STATE_SWITCH_TO_NETWORK:
875 rv = DoSwitchToNetwork();
876 break;
905 case STATE_NETWORK_READ: 877 case STATE_NETWORK_READ:
906 DCHECK_EQ(OK, rv); 878 DCHECK_EQ(OK, rv);
907 rv = DoNetworkRead(); 879 rv = DoNetworkRead();
908 break; 880 break;
909 case STATE_NETWORK_READ_COMPLETE: 881 case STATE_NETWORK_READ_COMPLETE:
910 rv = DoNetworkReadComplete(rv); 882 rv = DoNetworkReadComplete(rv);
911 break; 883 break;
912 case STATE_CACHE_READ_DATA: 884 case STATE_CACHE_READ_DATA:
913 DCHECK_EQ(OK, rv); 885 DCHECK_EQ(OK, rv);
914 rv = DoCacheReadData(); 886 rv = DoCacheReadData();
915 break; 887 break;
916 case STATE_CACHE_READ_DATA_COMPLETE: 888 case STATE_CACHE_READ_DATA_COMPLETE:
917 rv = DoCacheReadDataComplete(rv); 889 rv = DoCacheReadDataComplete(rv);
918 break; 890 break;
919 case STATE_CACHE_WRITE_DATA: 891 case STATE_CACHE_WRITE_DATA:
920 rv = DoCacheWriteData(rv); 892 rv = DoCacheWriteData(rv);
921 break; 893 break;
922 case STATE_CACHE_WRITE_DATA_COMPLETE: 894 case STATE_CACHE_WRITE_DATA_COMPLETE:
923 rv = DoCacheWriteDataComplete(rv); 895 rv = DoCacheWriteDataComplete(rv);
924 break; 896 break;
925 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE:
926 DCHECK_EQ(OK, rv);
927 rv = DoCacheWriteTruncatedResponse();
928 break;
929 case STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE:
930 rv = DoCacheWriteTruncatedResponseComplete(rv);
931 break;
932 default: 897 default:
933 NOTREACHED() << "bad state"; 898 NOTREACHED() << "bad state";
934 rv = ERR_FAILED; 899 rv = ERR_FAILED;
935 break; 900 break;
936 } 901 }
937 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); 902 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
938 903
939 if (rv != ERR_IO_PENDING && !callback_.is_null()) { 904 if (rv != ERR_IO_PENDING && !callback_.is_null()) {
940 read_buf_ = NULL; // Release the buffer before invoking the callback. 905 read_buf_ = nullptr; // Release the buffer before invoking the callback.
906 read_buf_len_ = 0;
941 base::ResetAndReturn(&callback_).Run(rv); 907 base::ResetAndReturn(&callback_).Run(rv);
942 } 908 }
943 909
944 return rv; 910 return rv;
945 } 911 }
946 912
947 int HttpCache::Transaction::DoGetBackend() { 913 int HttpCache::Transaction::DoGetBackend() {
948 cache_pending_ = true; 914 cache_pending_ = true;
949 next_state_ = STATE_GET_BACKEND_COMPLETE; 915 next_state_ = STATE_GET_BACKEND_COMPLETE;
950 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_GET_BACKEND); 916 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_GET_BACKEND);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
993 // the cache. If we receive 200, it doesn't matter if there was a validation 959 // the cache. If we receive 200, it doesn't matter if there was a validation
994 // header or not. 960 // header or not.
995 if (request_->method == "HEAD" && mode_ == WRITE) 961 if (request_->method == "HEAD" && mode_ == WRITE)
996 mode_ = NONE; 962 mode_ = NONE;
997 963
998 // If must use cache, then we must fail. This can happen for back/forward 964 // If must use cache, then we must fail. This can happen for back/forward
999 // navigations to a page generated via a form post. 965 // navigations to a page generated via a form post.
1000 if (!(mode_ & READ) && effective_load_flags_ & LOAD_ONLY_FROM_CACHE) 966 if (!(mode_ & READ) && effective_load_flags_ & LOAD_ONLY_FROM_CACHE)
1001 return ERR_CACHE_MISS; 967 return ERR_CACHE_MISS;
1002 968
969 // The client may have already decided not to write anything to the cache.
970 if (stopped_caching_ && mode_ != NONE) {
rvargas (doing something else) 2015/09/11 23:56:17 Is this for restart? We should not allow StopCachi
971 // Avoid touching the cache at all in this case unless the requestor has
972 // also requested that we prefer the cache entry. The transaction interprets
973 // the latter case as "Don't write any more response data to the cache."
974 if (mode_ != READ && !(effective_load_flags_ & LOAD_PREFERRING_CACHE))
975 mode_ = NONE;
976
977 // If the WRITE bit is still set, then the transaction has to roll forward
978 // until the first Read() to decide what to do because it needs to examine
979 // the cache entry. We could conceivably deal with StopCaching() prior to
980 // the first Read(), but we are going to wait till the first Read() since
981 // that allows us to also deal with the case where the requestor calls
982 // StopCaching() after Start() or Read().
983 stopped_caching_ = !!(mode_ & WRITE);
rvargas (doing something else) 2015/09/11 23:56:18 nit: I hate !!x; How about x != 0 (if we need to k
984 DCHECK_IMPLIES(stopped_caching_,
985 effective_load_flags_ & LOAD_PREFERRING_CACHE);
986 }
987
1003 if (mode_ == NONE) { 988 if (mode_ == NONE) {
1004 if (partial_) { 989 if (partial_) {
1005 partial_->RestoreHeaders(&custom_request_->extra_headers); 990 partial_->RestoreHeaders(&custom_request_->extra_headers);
1006 partial_.reset(); 991 partial_.reset();
1007 } 992 }
1008 next_state_ = STATE_SEND_REQUEST; 993 next_state_ = STATE_SEND_REQUEST;
1009 } else { 994 } else {
1010 next_state_ = STATE_INIT_ENTRY; 995 next_state_ = STATE_INIT_ENTRY;
1011 } 996 }
1012 997
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1044 // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is 1029 // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is
1045 // OK, otherwise the cache will end up with an active entry without any 1030 // OK, otherwise the cache will end up with an active entry without any
1046 // transaction attached. 1031 // transaction attached.
1047 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY, result); 1032 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY, result);
1048 cache_pending_ = false; 1033 cache_pending_ = false;
1049 if (result == OK) { 1034 if (result == OK) {
1050 next_state_ = STATE_ADD_TO_ENTRY; 1035 next_state_ = STATE_ADD_TO_ENTRY;
1051 return OK; 1036 return OK;
1052 } 1037 }
1053 1038
1039 // No need to create a cache entry if the transaction has already decided not
1040 // to write to it.
1041 if (stopped_caching_) {
rvargas (doing something else) 2015/09/11 23:56:18 same thing about start.
1042 // stopped_caching_ should've been unset in DoGetBackendComplete() if mode_
1043 // didn't have the WRITE bit set.
1044 DCHECK(mode_ & WRITE);
1045 mode_ = NONE;
1046 next_state_ = STATE_SEND_REQUEST;
1047 return OK;
1048 }
1049
1054 if (result == ERR_CACHE_RACE) { 1050 if (result == ERR_CACHE_RACE) {
1055 next_state_ = STATE_INIT_ENTRY; 1051 next_state_ = STATE_INIT_ENTRY;
1056 return OK; 1052 return OK;
1057 } 1053 }
1058 1054
1059 if (request_->method == "PUT" || request_->method == "DELETE" || 1055 if (request_->method == "PUT" || request_->method == "DELETE" ||
1060 (request_->method == "HEAD" && mode_ == READ_WRITE)) { 1056 (request_->method == "HEAD" && mode_ == READ_WRITE)) {
1061 DCHECK(mode_ == READ_WRITE || mode_ == WRITE || request_->method == "HEAD"); 1057 DCHECK(mode_ == READ_WRITE || mode_ == WRITE || request_->method == "HEAD");
1062 mode_ = NONE; 1058 mode_ = NONE;
1063 next_state_ = STATE_SEND_REQUEST; 1059 next_state_ = STATE_SEND_REQUEST;
1064 return OK; 1060 return OK;
1065 } 1061 }
1066 1062
1067 if (mode_ == READ_WRITE) { 1063 if (mode_ == READ_WRITE) {
1068 mode_ = WRITE; 1064 mode_ = WRITE;
1069 next_state_ = STATE_CREATE_ENTRY; 1065 next_state_ = STATE_CREATE_ENTRY;
1070 return OK; 1066 return OK;
1071 } 1067 }
1068
1072 if (mode_ == UPDATE) { 1069 if (mode_ == UPDATE) {
1073 // There is no cache entry to update; proceed without caching. 1070 // There is no cache entry to update; proceed without caching.
1074 mode_ = NONE; 1071 mode_ = NONE;
1075 next_state_ = STATE_SEND_REQUEST; 1072 next_state_ = STATE_SEND_REQUEST;
1076 return OK; 1073 return OK;
1077 } 1074 }
1078 1075
1079 // The entry does not exist, and we are not permitted to create a new entry, 1076 // The entry does not exist, and we are not permitted to create a new entry,
1080 // so we must fail. 1077 // so we must fail.
1081 return ERR_CACHE_MISS; 1078 return ERR_CACHE_MISS;
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
1279 // TODO(jkarlin): If DoUpdateCachedResponse is also called for this 1276 // TODO(jkarlin): If DoUpdateCachedResponse is also called for this
1280 // transaction then metadata will be written to cache twice. If prefetching 1277 // transaction then metadata will be written to cache twice. If prefetching
1281 // becomes more common, consider combining the writes. 1278 // becomes more common, consider combining the writes.
1282 1279
1283 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed. 1280 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed.
1284 tracked_objects::ScopedTracker tracking_profile( 1281 tracked_objects::ScopedTracker tracking_profile(
1285 FROM_HERE_WITH_EXPLICIT_FUNCTION( 1282 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1286 "422516 HttpCache::Transaction::DoCacheToggleUnusedSincePrefetch")); 1283 "422516 HttpCache::Transaction::DoCacheToggleUnusedSincePrefetch"));
1287 1284
1288 next_state_ = STATE_TOGGLE_UNUSED_SINCE_PREFETCH_COMPLETE; 1285 next_state_ = STATE_TOGGLE_UNUSED_SINCE_PREFETCH_COMPLETE;
1289 return WriteResponseInfoToEntry(false); 1286 return WriteResponseInfoToEntry(false, io_callback_);
1290 } 1287 }
1291 1288
1292 int HttpCache::Transaction::DoCacheToggleUnusedSincePrefetchComplete( 1289 int HttpCache::Transaction::DoCacheToggleUnusedSincePrefetchComplete(
1293 int result) { 1290 int result) {
1294 // Restore the original value for this transaction. 1291 // Restore the original value for this transaction.
1295 response_.unused_since_prefetch = !response_.unused_since_prefetch; 1292 response_.unused_since_prefetch = !response_.unused_since_prefetch;
1296 next_state_ = STATE_CACHE_DISPATCH_VALIDATION; 1293 next_state_ = STATE_CACHE_DISPATCH_VALIDATION;
1297 return OnWriteResponseInfoToEntryComplete(result); 1294 return OnWriteResponseInfoToEntryComplete(result);
1298 } 1295 }
1299 1296
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1347 int HttpCache::Transaction::DoStartPartialCacheValidation() { 1344 int HttpCache::Transaction::DoStartPartialCacheValidation() {
1348 if (mode_ == NONE) 1345 if (mode_ == NONE)
1349 return OK; 1346 return OK;
1350 1347
1351 next_state_ = STATE_COMPLETE_PARTIAL_CACHE_VALIDATION; 1348 next_state_ = STATE_COMPLETE_PARTIAL_CACHE_VALIDATION;
1352 return partial_->ShouldValidateCache(entry_->disk_entry, io_callback_); 1349 return partial_->ShouldValidateCache(entry_->disk_entry, io_callback_);
1353 } 1350 }
1354 1351
1355 int HttpCache::Transaction::DoCompletePartialCacheValidation(int result) { 1352 int HttpCache::Transaction::DoCompletePartialCacheValidation(int result) {
1356 if (!result) { 1353 if (!result) {
1357 // This is the end of the request. 1354 ReleaseCacheEntry(EntryState::SUCCEEDED);
1358 if (mode_ & WRITE) { 1355 return 0;
rvargas (doing something else) 2015/09/11 23:56:18 nit: OK (or result).
rvargas (doing something else) 2015/09/21 22:05:59 Missed?
1359 DoneWritingToEntry(true);
1360 } else {
1361 cache_->DoneReadingFromEntry(entry_, this);
1362 entry_ = NULL;
1363 }
1364 return result;
1365 } 1356 }
1366 1357
1367 if (result < 0) 1358 if (result < 0)
1368 return result; 1359 return result;
1369 1360
1370 partial_->PrepareCacheValidation(entry_->disk_entry, 1361 partial_->PrepareCacheValidation(entry_->disk_entry,
1371 &custom_request_->extra_headers); 1362 &custom_request_->extra_headers);
1372 1363
1373 if (reading_ && partial_->IsCurrentRangeCached()) { 1364 if (reading_ && partial_->IsCurrentRangeCached()) {
1374 next_state_ = STATE_CACHE_READ_DATA; 1365 next_state_ = STATE_CACHE_READ_DATA;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1426 UpdateTransactionPattern(PATTERN_NOT_COVERED); 1417 UpdateTransactionPattern(PATTERN_NOT_COVERED);
1427 if (IsCertificateError(result)) { 1418 if (IsCertificateError(result)) {
1428 // If we get a certificate error, then there is a certificate in ssl_info, 1419 // If we get a certificate error, then there is a certificate in ssl_info,
1429 // so GetResponseInfo() should never return NULL here. 1420 // so GetResponseInfo() should never return NULL here.
1430 DCHECK(response); 1421 DCHECK(response);
1431 response_.ssl_info = response->ssl_info; 1422 response_.ssl_info = response->ssl_info;
1432 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { 1423 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
1433 DCHECK(response); 1424 DCHECK(response);
1434 response_.cert_request_info = response->cert_request_info; 1425 response_.cert_request_info = response->cert_request_info;
1435 } else if (response_.was_cached) { 1426 } else if (response_.was_cached) {
1436 DoneWritingToEntry(true); 1427 ReleaseCacheEntry(EntryState::SUCCEEDED);
1437 } 1428 }
1438 1429
1439 return result; 1430 return result;
1440 } 1431 }
1441 1432
1442 // We received the response headers and there is no error. 1433 // We received the response headers and there is no error.
1443 int HttpCache::Transaction::DoSuccessfulSendRequest() { 1434 int HttpCache::Transaction::DoSuccessfulSendRequest() {
1444 DCHECK(!new_response_); 1435 DCHECK(!new_response_);
1445 const HttpResponseInfo* new_response = network_trans_->GetResponseInfo(); 1436 const HttpResponseInfo* new_response = network_trans_->GetResponseInfo();
1446 1437
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1482 // the new response. 1473 // the new response.
1483 net_log_.AddEvent(NetLog::TYPE_HTTP_CACHE_RE_SEND_PARTIAL_REQUEST); 1474 net_log_.AddEvent(NetLog::TYPE_HTTP_CACHE_RE_SEND_PARTIAL_REQUEST);
1484 UpdateTransactionPattern(PATTERN_NOT_COVERED); 1475 UpdateTransactionPattern(PATTERN_NOT_COVERED);
1485 response_ = HttpResponseInfo(); 1476 response_ = HttpResponseInfo();
1486 ResetNetworkTransaction(); 1477 ResetNetworkTransaction();
1487 new_response_ = NULL; 1478 new_response_ = NULL;
1488 next_state_ = STATE_SEND_REQUEST; 1479 next_state_ = STATE_SEND_REQUEST;
1489 return OK; 1480 return OK;
1490 } 1481 }
1491 1482
1483 if (handling_206_ && stopped_caching_ && partial_ &&
1484 partial_->IsLastRange() && !partial_->IsCurrentRangeCached() &&
1485 (mode_ & WRITE) && entry_) {
1486 // The current state of the transaction is:
1487 // * The client has requested that no addtional data be cached.
1488 // * The current network transaction spans the entire remainder of the
1489 // requested range.
1490 // * A cache entry exists and was being written to or updated.
1491 // * The current range is not cached.
1492 //
1493 // At this point it is safe to abandon the cache entry and proceed with just
1494 // the network transaction.
1495 next_state_ = STATE_NETWORK_READ;
rvargas (doing something else) 2015/09/11 23:56:18 without returning data to the caller?
asanka 2015/09/17 21:59:40 We do. Once AbadonCacheEntry() completes, the SM w
rvargas (doing something else) 2015/09/19 01:09:34 The confusing thing is that we may be doing Start(
1496 return AbandonCacheEntry(io_callback_);
1497 }
1498
1492 if (handling_206_ && mode_ == READ_WRITE && !truncated_ && !is_sparse_) { 1499 if (handling_206_ && mode_ == READ_WRITE && !truncated_ && !is_sparse_) {
1493 // We have stored the full entry, but it changed and the server is 1500 // We have stored the full entry, but it changed and the server is
1494 // sending a range. We have to delete the old entry. 1501 // sending a range. We have to delete the old entry.
1495 UpdateTransactionPattern(PATTERN_NOT_COVERED); 1502 UpdateTransactionPattern(PATTERN_NOT_COVERED);
1496 DoneWritingToEntry(false); 1503 ReleaseCacheEntry(EntryState::DOOMED);
1497 } 1504 }
1498 1505
1499 if (mode_ == WRITE && 1506 if (mode_ == WRITE &&
1500 transaction_pattern_ != PATTERN_ENTRY_CANT_CONDITIONALIZE) { 1507 transaction_pattern_ != PATTERN_ENTRY_CANT_CONDITIONALIZE) {
1501 UpdateTransactionPattern(PATTERN_ENTRY_NOT_CACHED); 1508 UpdateTransactionPattern(PATTERN_ENTRY_NOT_CACHED);
1502 } 1509 }
1503 1510
1504 // Invalidate any cached GET with a successful PUT or DELETE. 1511 // Invalidate any cached GET with a successful PUT or DELETE.
1505 if (mode_ == WRITE && 1512 if (mode_ == WRITE &&
1506 (request_->method == "PUT" || request_->method == "DELETE")) { 1513 (request_->method == "PUT" || request_->method == "DELETE")) {
1507 if (NonErrorResponse(new_response->headers->response_code())) { 1514 if (NonErrorResponse(new_response->headers->response_code())) {
1508 int ret = cache_->DoomEntry(cache_key_, NULL); 1515 int ret = cache_->DoomEntry(cache_key_, NULL);
1509 DCHECK_EQ(OK, ret); 1516 DCHECK_EQ(OK, ret);
1510 } 1517 }
1511 cache_->DoneWritingToEntry(entry_, true); 1518 ReleaseCacheEntry(EntryState::SUCCEEDED);
1512 entry_ = NULL;
1513 mode_ = NONE;
1514 } 1519 }
1515 1520
1516 // Invalidate any cached GET with a successful POST. 1521 // Invalidate any cached GET with a successful POST.
1517 if (!(effective_load_flags_ & LOAD_DISABLE_CACHE) && 1522 if (!(effective_load_flags_ & LOAD_DISABLE_CACHE) &&
1518 request_->method == "POST" && 1523 request_->method == "POST" &&
1519 NonErrorResponse(new_response->headers->response_code())) { 1524 NonErrorResponse(new_response->headers->response_code())) {
1520 cache_->DoomMainEntryForUrl(request_->url); 1525 cache_->DoomMainEntryForUrl(request_->url);
1521 } 1526 }
1522 1527
1523 RecordNoStoreHeaderHistogram(request_->load_flags, new_response); 1528 RecordNoStoreHeaderHistogram(request_->load_flags, new_response);
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1582 return rv; 1587 return rv;
1583 } 1588 }
1584 1589
1585 int HttpCache::Transaction::DoCacheWriteUpdatedResponse() { 1590 int HttpCache::Transaction::DoCacheWriteUpdatedResponse() {
1586 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed. 1591 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed.
1587 tracked_objects::ScopedTracker tracking_profile( 1592 tracked_objects::ScopedTracker tracking_profile(
1588 FROM_HERE_WITH_EXPLICIT_FUNCTION( 1593 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1589 "422516 HttpCache::Transaction::DoCacheWriteUpdatedResponse")); 1594 "422516 HttpCache::Transaction::DoCacheWriteUpdatedResponse"));
1590 1595
1591 next_state_ = STATE_CACHE_WRITE_UPDATED_RESPONSE_COMPLETE; 1596 next_state_ = STATE_CACHE_WRITE_UPDATED_RESPONSE_COMPLETE;
1592 return WriteResponseInfoToEntry(false); 1597 return WriteResponseInfoToEntry(false, io_callback_);
1593 } 1598 }
1594 1599
1595 int HttpCache::Transaction::DoCacheWriteUpdatedResponseComplete(int result) { 1600 int HttpCache::Transaction::DoCacheWriteUpdatedResponseComplete(int result) {
1596 next_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE; 1601 next_state_ = STATE_UPDATE_CACHED_RESPONSE_COMPLETE;
1597 return OnWriteResponseInfoToEntryComplete(result); 1602 return OnWriteResponseInfoToEntryComplete(result);
1598 } 1603 }
1599 1604
1600 int HttpCache::Transaction::DoUpdateCachedResponseComplete(int result) { 1605 int HttpCache::Transaction::DoUpdateCachedResponseComplete(int result) {
1601 if (mode_ == UPDATE) { 1606 if (mode_ == UPDATE) {
1602 DCHECK(!handling_206_); 1607 DCHECK(!handling_206_);
1603 // We got a "not modified" response and already updated the corresponding 1608 // We got a "not modified" response and already updated the corresponding
1604 // cache entry above. 1609 // cache entry above.
1605 // 1610 //
1606 // By closing the cached entry now, we make sure that the 304 rather than 1611 // By closing the cached entry now, we make sure that the 304 rather than
1607 // the cached 200 response, is what will be returned to the user. 1612 // the cached 200 response, is what will be returned to the user.
1608 DoneWritingToEntry(true); 1613 ReleaseCacheEntry(EntryState::SUCCEEDED);
1609 } else if (entry_ && !handling_206_) { 1614 } else if (entry_ && !handling_206_) {
1610 DCHECK_EQ(READ_WRITE, mode_); 1615 DCHECK_EQ(READ_WRITE, mode_);
1611 if (!partial_ || partial_->IsLastRange()) { 1616 if (!partial_ || partial_->IsLastRange()) {
1612 cache_->ConvertWriterToReader(entry_); 1617 cache_->ConvertWriterToReader(entry_);
1613 mode_ = READ; 1618 mode_ = READ;
1614 } 1619 }
1615 // We no longer need the network transaction, so destroy it. 1620 // We no longer need the network transaction, so destroy it.
1616 final_upload_progress_ = network_trans_->GetUploadProgress(); 1621 final_upload_progress_ = network_trans_->GetUploadProgress();
1617 ResetNetworkTransaction(); 1622 ResetNetworkTransaction();
1618 } else if (entry_ && handling_206_ && truncated_ && 1623 } else if (entry_ && handling_206_ && truncated_ &&
(...skipping 18 matching lines...) Expand all
1637 } 1642 }
1638 1643
1639 // We change the value of Content-Length for partial content. 1644 // We change the value of Content-Length for partial content.
1640 if (handling_206_ && partial_) 1645 if (handling_206_ && partial_)
1641 partial_->FixContentLength(new_response_->headers.get()); 1646 partial_->FixContentLength(new_response_->headers.get());
1642 1647
1643 response_ = *new_response_; 1648 response_ = *new_response_;
1644 1649
1645 if (request_->method == "HEAD") { 1650 if (request_->method == "HEAD") {
1646 // This response is replacing the cached one. 1651 // This response is replacing the cached one.
1647 DoneWritingToEntry(false); 1652 ReleaseCacheEntry(EntryState::DOOMED);
1648 mode_ = NONE; 1653 new_response_ = nullptr;
1649 new_response_ = NULL;
1650 return OK; 1654 return OK;
1651 } 1655 }
1652 1656
1653 if (handling_206_ && !CanResume(false)) { 1657 if (handling_206_ && !CanResume(false)) {
1654 // There is no point in storing this resource because it will never be used. 1658 // There is no point in storing this resource because it will never be used.
1655 // This may change if we support LOAD_ONLY_FROM_CACHE with sparse entries. 1659 // This may change if we support LOAD_ONLY_FROM_CACHE with sparse entries.
1656 DoneWritingToEntry(false); 1660 ReleaseCacheEntry(EntryState::DOOMED);
1657 if (partial_) 1661 if (partial_)
1658 partial_->FixResponseHeaders(response_.headers.get(), true); 1662 partial_->FixResponseHeaders(response_.headers.get(), true);
1659 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED; 1663 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
1660 return OK; 1664 return OK;
1661 } 1665 }
1662 1666
1663 next_state_ = STATE_CACHE_WRITE_RESPONSE; 1667 next_state_ = STATE_CACHE_WRITE_RESPONSE;
1664 return OK; 1668 return OK;
1665 } 1669 }
1666 1670
1667 int HttpCache::Transaction::DoCacheWriteResponse() { 1671 int HttpCache::Transaction::DoCacheWriteResponse() {
1668 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed. 1672 // TODO(rtenneti): Remove ScopedTracker below once crbug.com/422516 is fixed.
1669 tracked_objects::ScopedTracker tracking_profile( 1673 tracked_objects::ScopedTracker tracking_profile(
1670 FROM_HERE_WITH_EXPLICIT_FUNCTION( 1674 FROM_HERE_WITH_EXPLICIT_FUNCTION(
1671 "422516 HttpCache::Transaction::DoCacheWriteResponse")); 1675 "422516 HttpCache::Transaction::DoCacheWriteResponse"));
1672 1676
1673 next_state_ = STATE_CACHE_WRITE_RESPONSE_COMPLETE; 1677 next_state_ = STATE_CACHE_WRITE_RESPONSE_COMPLETE;
1674 return WriteResponseInfoToEntry(truncated_); 1678 return WriteResponseInfoToEntry(truncated_, io_callback_);
1675 } 1679 }
1676 1680
1677 int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) { 1681 int HttpCache::Transaction::DoCacheWriteResponseComplete(int result) {
1678 next_state_ = STATE_TRUNCATE_CACHED_DATA; 1682 next_state_ = STATE_TRUNCATE_CACHED_DATA;
1679 return OnWriteResponseInfoToEntryComplete(result); 1683 return OnWriteResponseInfoToEntryComplete(result);
1680 } 1684 }
1681 1685
1682 int HttpCache::Transaction::DoTruncateCachedData() { 1686 int HttpCache::Transaction::DoTruncateCachedData() {
1683 next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE; 1687 next_state_ = STATE_TRUNCATE_CACHED_DATA_COMPLETE;
1684 if (!entry_) 1688 if (!entry_)
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1760 io_callback_); 1764 io_callback_);
1761 } 1765 }
1762 1766
1763 int HttpCache::Transaction::DoCacheReadMetadataComplete(int result) { 1767 int HttpCache::Transaction::DoCacheReadMetadataComplete(int result) {
1764 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result); 1768 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result);
1765 if (result != response_.metadata->size()) 1769 if (result != response_.metadata->size())
1766 return OnCacheReadError(result, false); 1770 return OnCacheReadError(result, false);
1767 return OK; 1771 return OK;
1768 } 1772 }
1769 1773
1774 int HttpCache::Transaction::DoSwitchToNetwork() {
1775 // Prerequisites of a switch to network:
1776 // * A valid cache entry must exist. Otherwise we'd already be exclusively
1777 // dealing with the network.
rvargas (doing something else) 2015/09/11 23:56:18 Do we really need this comment (and the next one)?
asanka 2015/09/17 21:59:41 Removed. I suppose those two should be obvious. Al
1778 DCHECK(entry_);
1779 // * Need to be writing to the cache entry. If the transaction was exclusively
1780 // reading from the cache, then the transaction should continue doing so
1781 // without trying to switch to the network.
1782 DCHECK(mode_ & WRITE);
1783
1784 // If the transaction is currently reading from the cache, then it should have
1785 // a valid partial state. I.e. only part of the requested resource could be
1786 // fulfiled via the cache. If the entire request was being fulfiled via the
1787 // cache, the transaction shouldn't be trying to switch to the network at this
1788 // point, and mode_ should be READ.
1789 DCHECK_IMPLIES(!network_trans_, partial_);
1790
1791 // The network transaction can be trivially reused if it can promise to
1792 // deliver all the bits necessary to fulfil the original request. If so,
1793 // abandon the cache entry and continue with a network read.
1794 if (network_trans_ && (!partial_ || partial_->IsLastRange())) {
1795 next_state_ = STATE_NETWORK_READ;
1796 return AbandonCacheEntry(io_callback_);
1797 }
1798
1799 if (request_->method != "GET") {
rvargas (doing something else) 2015/09/11 23:56:18 Isn't it easier to check for this in StopCaching?
asanka 2015/09/17 21:59:41 Check moved there. See earlier confusion about whe
rvargas (doing something else) 2015/09/21 22:05:59 but PS14 still has the if here...
1800 // We have a non-GET request that the cache or network can partially fulfil.
1801 // In other words, at some point the transaction is going to have to issue a
1802 // partial network request to fulfil this non-GET request. Let's just ignore
rvargas (doing something else) 2015/09/11 23:56:17 I don't think this ever happens. (partial && !get)
asanka 2015/09/17 21:59:40 Yeah. The condition we check now is: (!partial_
1803 // the StopCaching() directive for now.
1804 stopped_caching_ = false;
1805 next_state_ = network_trans_ ? STATE_NETWORK_READ : STATE_CACHE_READ_DATA;
1806 return OK;
1807 }
1808
1809 // The existing network transaction doesn't cover the entire range we wanted.
1810 // Let's discard the network transaction and create a new one that will cover
1811 // the entire range we need.
1812 if (network_trans_)
1813 ResetNetworkTransaction();
1814
1815 if (!partial_->SkipCacheForRemainder()) {
1816 // PartialData only refuses to switch to network reads if the entire
1817 // resource has been accounted for. There's nothing more to do.
1818 // ** Caveat: This assumes that there's a strict agreement between the
1819 // server indicated length of the resource and the actual length of the
1820 // resource.
rvargas (doing something else) 2015/09/11 23:56:18 This is a pre-requisite for byte range requests
asanka 2015/09/17 21:59:41 Caveat removed.
1821 return OK;
1822 }
1823
1824 // The new network request that's going to be issued has to be validated
1825 // against the existing cache entry. By extension, this also validates the new
1826 // request against the portion that has already been sent to our client.
1827 partial_->PrepareCacheValidation(entry_->disk_entry,
1828 &custom_request_->extra_headers);
1829
1830 // Since we called SkipCacheForRemainder(), the partial_ state should now
1831 // assume that the remainder of the resource is not cached.
1832 DCHECK(!partial_->IsCurrentRangeCached());
1833 DCHECK(partial_->IsLastRange());
1834
1835 // READ shouldn't reach here at all. WRITE/UPDATE require a network_trans_
1836 // that spans the entire request range and is handled at the top of this
1837 // function. At this point we should be left with just READ_WRITE.
1838 DCHECK_EQ(mode_, READ_WRITE);
1839
1840 // Start validating the cache. DoSuccessfulSendRequest() will now bear the
1841 // responsibility of abandoning the cache entry if the new network transaction
1842 // is successfully validated.
1843 return BeginCacheValidation();
1844 }
1845
1770 int HttpCache::Transaction::DoNetworkRead() { 1846 int HttpCache::Transaction::DoNetworkRead() {
1847 DCHECK_GT(read_buf_len_, 0);
1848
1849 io_buf_len_ = read_buf_len_;
1771 next_state_ = STATE_NETWORK_READ_COMPLETE; 1850 next_state_ = STATE_NETWORK_READ_COMPLETE;
1772 return network_trans_->Read(read_buf_.get(), io_buf_len_, io_callback_); 1851 return network_trans_->Read(read_buf_.get(), io_buf_len_, io_callback_);
1773 } 1852 }
1774 1853
1775 int HttpCache::Transaction::DoNetworkReadComplete(int result) { 1854 int HttpCache::Transaction::DoNetworkReadComplete(int result) {
1776 DCHECK(mode_ & WRITE || mode_ == NONE); 1855 DCHECK(mode_ & WRITE || mode_ == NONE);
1777 1856
1778 if (!cache_.get()) 1857 if (!cache_.get())
1779 return ERR_UNEXPECTED; 1858 return ERR_UNEXPECTED;
1780 1859
1781 // If there is an error or we aren't saving the data, we are done; just wait 1860 // If there is an error or we aren't saving the data, we are done; just wait
1782 // until the destructor runs to see if we can keep the data. 1861 // until the destructor runs to see if we can keep the data.
1783 if (mode_ == NONE || result < 0) 1862 if (mode_ == NONE || result < 0)
1784 return result; 1863 return result;
1785 1864
1786 next_state_ = STATE_CACHE_WRITE_DATA; 1865 next_state_ = STATE_CACHE_WRITE_DATA;
1787 return result; 1866 return result;
1788 } 1867 }
1789 1868
1790 int HttpCache::Transaction::DoCacheReadData() { 1869 int HttpCache::Transaction::DoCacheReadData() {
1870 DCHECK_GT(read_buf_len_, 0);
1871
1791 if (request_->method == "HEAD") 1872 if (request_->method == "HEAD")
1792 return 0; 1873 return 0;
1793 1874
1794 DCHECK(entry_); 1875 DCHECK(entry_);
1795 next_state_ = STATE_CACHE_READ_DATA_COMPLETE; 1876 next_state_ = STATE_CACHE_READ_DATA_COMPLETE;
1877 io_buf_len_ = read_buf_len_;
1796 1878
1797 if (net_log_.IsCapturing()) 1879 if (net_log_.IsCapturing())
1798 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_DATA); 1880 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_DATA);
1799 if (partial_) { 1881 if (partial_) {
1800 return partial_->CacheRead(entry_->disk_entry, read_buf_.get(), io_buf_len_, 1882 return partial_->CacheRead(entry_->disk_entry, read_buf_.get(), io_buf_len_,
1801 io_callback_); 1883 io_callback_);
1802 } 1884 }
1803 1885
1804 return entry_->disk_entry->ReadData(kResponseContentIndex, read_offset_, 1886 return entry_->disk_entry->ReadData(kResponseContentIndex, read_offset_,
1805 read_buf_.get(), io_buf_len_, 1887 read_buf_.get(), io_buf_len_,
1806 io_callback_); 1888 io_callback_);
1807 } 1889 }
1808 1890
1809 int HttpCache::Transaction::DoCacheReadDataComplete(int result) { 1891 int HttpCache::Transaction::DoCacheReadDataComplete(int result) {
1810 if (net_log_.IsCapturing()) { 1892 if (net_log_.IsCapturing()) {
1811 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_DATA, 1893 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_DATA,
1812 result); 1894 result);
1813 } 1895 }
1814 1896
1815 if (!cache_.get()) 1897 if (!cache_.get())
1816 return ERR_UNEXPECTED; 1898 return ERR_UNEXPECTED;
1817 1899
1818 if (partial_) { 1900 if (partial_) {
1819 // Partial requests are confusing to report in histograms because they may 1901 // Partial requests are confusing to report in histograms because they may
1820 // have multiple underlying requests. 1902 // have multiple underlying requests.
1821 UpdateTransactionPattern(PATTERN_NOT_COVERED); 1903 UpdateTransactionPattern(PATTERN_NOT_COVERED);
1822 return DoPartialCacheReadCompleted(result); 1904 return DoPartialCacheReadCompleted(result);
1823 } 1905 }
1824 1906
1825 if (result > 0) { 1907 if (result < 0)
1826 read_offset_ += result;
1827 } else if (result == 0) { // End of file.
1828 RecordHistograms();
1829 cache_->DoneReadingFromEntry(entry_, this);
1830 entry_ = NULL;
1831 } else {
1832 return OnCacheReadError(result, false); 1908 return OnCacheReadError(result, false);
1833 } 1909
1910 if (result == 0)
1911 ReleaseCacheEntry(EntryState::SUCCEEDED);
1912
1913 read_offset_ += result;
1834 return result; 1914 return result;
1835 } 1915 }
1836 1916
1837 int HttpCache::Transaction::DoCacheWriteData(int num_bytes) { 1917 int HttpCache::Transaction::DoCacheWriteData(int num_bytes) {
1838 next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE; 1918 next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE;
1839 write_len_ = num_bytes; 1919 write_len_ = num_bytes;
1840 if (entry_) { 1920 if (entry_) {
1841 if (net_log_.IsCapturing()) 1921 if (net_log_.IsCapturing())
1842 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_DATA); 1922 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_DATA);
1843 } 1923 }
1844 1924
1845 if (!entry_ || !num_bytes) 1925 if (!entry_ || !num_bytes)
1846 return num_bytes; 1926 return num_bytes;
1847 1927
1848 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); 1928 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
1849 return WriteToEntry(kResponseContentIndex, current_size, read_buf_.get(), 1929 return WriteToEntry(kResponseContentIndex, current_size, read_buf_.get(),
1850 num_bytes, io_callback_); 1930 num_bytes, io_callback_);
1851 } 1931 }
1852 1932
1853 int HttpCache::Transaction::DoCacheWriteDataComplete(int result) { 1933 int HttpCache::Transaction::DoCacheWriteDataComplete(int result) {
1854 if (entry_) { 1934 if (entry_ && net_log_.IsCapturing()) {
1855 if (net_log_.IsCapturing()) { 1935 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA,
1856 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_DATA, 1936 result);
1857 result);
1858 }
1859 } 1937 }
1938
1860 if (!cache_.get()) 1939 if (!cache_.get())
1861 return ERR_UNEXPECTED; 1940 return ERR_UNEXPECTED;
1862 1941
1863 if (result != write_len_) { 1942 if (result != write_len_) {
1864 DLOG(ERROR) << "failed to write response data to cache"; 1943 DLOG(ERROR) << "failed to write response data to cache";
1865 DoneWritingToEntry(false); 1944 ReleaseCacheEntry(EntryState::DOOMED);
1866 1945
1867 // We want to ignore errors writing to disk and just keep reading from 1946 // We want to ignore errors writing to disk and just keep reading from
1868 // the network. 1947 // the network.
1869 result = write_len_; 1948 result = write_len_;
1949
1950 // TODO(asanka): More needs to be done to ignore the error and keep reading
1951 // from the network. E.g. if the cache entry was sparse, it is possible that
1952 // the current network_trans_ can't fulfil the entire requested range.
1953 // Consider setting up state to perform an immediate STATE_SWITCH_TO_NETWORK
1954 // at the next Read() instead of releasing the entry now.
1870 } else if (!done_reading_ && entry_) { 1955 } else if (!done_reading_ && entry_) {
1871 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); 1956 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
1872 int64 body_size = response_.headers->GetContentLength(); 1957 int64 body_size = response_.headers->GetContentLength();
1873 if (body_size >= 0 && body_size <= current_size) 1958 if (body_size >= 0 && body_size <= current_size)
1874 done_reading_ = true; 1959 done_reading_ = true;
1875 } 1960 }
1876 1961
1877 if (partial_) { 1962 if (partial_) {
1878 // This may be the last request. 1963 // The transaction needs to update partial state under the following
1879 if (result != 0 || truncated_ || 1964 // circumstances:
1880 !(partial_->IsLastRange() || mode_ == WRITE)) { 1965 const bool need_to_update_partial_state =
1966 // Still reading. The partial state needs to be updated to account for
1967 // the data read so far.
1968 result != 0 ||
1969
1970 // Reached the end of one network request, but more transactions may be
1971 // necessary to fulfil the request. DoPartialNetworkReadCompleted()
1972 // initiates additional network transactions as needed.
1973 truncated_ ||
1974
1975 // If this isn't the last range, then more network transactions may be
1976 // necessary. But skip this step for new cache entries (mode_ == WRITE).
1977 // Range requests with new cache entries will have
1978 // partial_->IsLastRange() set to false. IsLastRange() is only set to
1979 // true when validating the last range of an existing cache entry.
1980 (!partial_->IsLastRange() && mode_ != WRITE);
1981
1982 if (need_to_update_partial_state)
1881 return DoPartialNetworkReadCompleted(result); 1983 return DoPartialNetworkReadCompleted(result);
1882 }
1883 } 1984 }
1884 1985
1885 if (result == 0) { 1986 if (result == 0) {
1886 // End of file. This may be the result of a connection problem so see if we 1987 // If the entire response body was successfully read, then the transaction
1887 // have to keep the entry around to be flagged as truncated later on. 1988 // should release the cache entry.
1888 if (done_reading_ || !entry_ || partial_ || 1989 //
1889 response_.headers->GetContentLength() <= 0) { 1990 // While response == 0 typically indicates EOF, it is possible for that to
1890 DoneWritingToEntry(true); 1991 // happen due to a connection problem. In the latter case the transaction
1992 // should retain ownership of entry_ until the transaction is destroyed so
rvargas (doing something else) 2015/09/11 23:56:17 But now AbandonCacheEntry is called from here.
asanka 2015/09/17 21:59:40 Comment updated.
1993 // that the resulting AbandonCacheEntry() call would cause the entry to be
1994 // marked as truncated.
1995 //
1996 // A succesful receipt of the response body is considered to be indicated by
1997 // one of:
1998 // * done_reading_ : Received response body was of expected size.
1999 // * Content-Length <= 0 : Response body size was not known.
2000 // * partial_ :
2001 if (entry_ && (done_reading_ || partial_ ||
2002 response_.headers->GetContentLength() <= 0)) {
2003 ReleaseCacheEntry(EntryState::SUCCEEDED);
2004 } else {
2005 AbandonCacheEntry(CompletionCallback());
rvargas (doing something else) 2015/09/11 23:56:18 This is not doing the same checks that the dtor pe
asanka 2015/09/17 21:59:40 Different circumstances. When we get here, the net
rvargas (doing something else) 2015/09/21 22:05:59 Poor wording on my part. The destructor ends up lo
1891 } 2006 }
1892 } 2007 }
1893 2008
1894 return result; 2009 return result;
1895 } 2010 }
1896 2011
1897 int HttpCache::Transaction::DoCacheWriteTruncatedResponse() {
1898 next_state_ = STATE_CACHE_WRITE_TRUNCATED_RESPONSE_COMPLETE;
1899 return WriteResponseInfoToEntry(true);
1900 }
1901
1902 int HttpCache::Transaction::DoCacheWriteTruncatedResponseComplete(int result) {
1903 return OnWriteResponseInfoToEntryComplete(result);
1904 }
1905
1906 //----------------------------------------------------------------------------- 2012 //-----------------------------------------------------------------------------
1907 2013
1908 void HttpCache::Transaction::ReadCertChain() { 2014 void HttpCache::Transaction::ReadCertChain() {
1909 std::string key = 2015 std::string key =
1910 GetCacheKeyForCert(response_.ssl_info.cert->os_cert_handle()); 2016 GetCacheKeyForCert(response_.ssl_info.cert->os_cert_handle());
1911 const X509Certificate::OSCertHandles& intermediates = 2017 const X509Certificate::OSCertHandles& intermediates =
1912 response_.ssl_info.cert->GetIntermediateCertificates(); 2018 response_.ssl_info.cert->GetIntermediateCertificates();
1913 int dist_from_root = intermediates.size(); 2019 int dist_from_root = intermediates.size();
1914 2020
1915 scoped_refptr<SharedChainData> shared_chain_data( 2021 scoped_refptr<SharedChainData> shared_chain_data(
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
2153 UpdateTransactionPattern(PATTERN_ENTRY_USED); 2259 UpdateTransactionPattern(PATTERN_ENTRY_USED);
2154 return SetupEntryForRead(); 2260 return SetupEntryForRead();
2155 } else { 2261 } else {
2156 // Make the network request conditional, to see if we may reuse our cached 2262 // Make the network request conditional, to see if we may reuse our cached
2157 // response. If we cannot do so, then we just resort to a normal fetch. 2263 // response. If we cannot do so, then we just resort to a normal fetch.
2158 // Our mode remains READ_WRITE for a conditional request. Even if the 2264 // Our mode remains READ_WRITE for a conditional request. Even if the
2159 // conditionalization fails, we don't switch to WRITE mode until we 2265 // conditionalization fails, we don't switch to WRITE mode until we
2160 // know we won't be falling back to using the cache entry in the 2266 // know we won't be falling back to using the cache entry in the
2161 // LOAD_FROM_CACHE_IF_OFFLINE case. 2267 // LOAD_FROM_CACHE_IF_OFFLINE case.
2162 if (!ConditionalizeRequest()) { 2268 if (!ConditionalizeRequest()) {
2269 // Conditionalization should only depend on the state of the cache prior
2270 // to starting the request and the request method. Failure is unexpected
2271 // after the client has started reading the stream.
2272 DCHECK(!reading_);
2273
2163 couldnt_conditionalize_request_ = true; 2274 couldnt_conditionalize_request_ = true;
2164 UpdateTransactionPattern(PATTERN_ENTRY_CANT_CONDITIONALIZE); 2275 UpdateTransactionPattern(PATTERN_ENTRY_CANT_CONDITIONALIZE);
2165 if (partial_) 2276 if (partial_)
2166 return DoRestartPartialRequest(); 2277 return DoRestartPartialRequest();
2167 2278
2168 DCHECK_NE(206, response_.headers->response_code()); 2279 DCHECK_NE(206, response_.headers->response_code());
2169 } 2280 }
2170 next_state_ = STATE_SEND_REQUEST; 2281 next_state_ = STATE_SEND_REQUEST;
2171 } 2282 }
2172 return OK; 2283 return OK;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
2231 response_.headers->EnumerateHeader( 2342 response_.headers->EnumerateHeader(
2232 NULL, 2343 NULL,
2233 kValidationHeaders[i].related_response_header_name, 2344 kValidationHeaders[i].related_response_header_name,
2234 &validator); 2345 &validator);
2235 2346
2236 if (response_.headers->response_code() != 200 || truncated_ || 2347 if (response_.headers->response_code() != 200 || truncated_ ||
2237 validator.empty() || validator != external_validation_.values[i]) { 2348 validator.empty() || validator != external_validation_.values[i]) {
2238 // The externally conditionalized request is not a validation request 2349 // The externally conditionalized request is not a validation request
2239 // for our existing cache entry. Proceed with caching disabled. 2350 // for our existing cache entry. Proceed with caching disabled.
2240 UpdateTransactionPattern(PATTERN_NOT_COVERED); 2351 UpdateTransactionPattern(PATTERN_NOT_COVERED);
2241 DoneWritingToEntry(true); 2352 ReleaseCacheEntry(EntryState::SUCCEEDED);
2242 } 2353 }
2243 } 2354 }
2244 2355
2245 // TODO(ricea): This calculation is expensive to perform just to collect 2356 // TODO(ricea): This calculation is expensive to perform just to collect
2246 // statistics. Either remove it or use the result, depending on the result of 2357 // statistics. Either remove it or use the result, depending on the result of
2247 // the experiment. 2358 // the experiment.
2248 ExternallyConditionalizedType type = 2359 ExternallyConditionalizedType type =
2249 EXTERNALLY_CONDITIONALIZED_CACHE_USABLE; 2360 EXTERNALLY_CONDITIONALIZED_CACHE_USABLE;
2250 if (mode_ == NONE) 2361 if (mode_ == NONE)
2251 type = EXTERNALLY_CONDITIONALIZED_MISMATCHED_VALIDATORS; 2362 type = EXTERNALLY_CONDITIONALIZED_MISMATCHED_VALIDATORS;
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
2559 IgnoreRangeRequest(); 2670 IgnoreRangeRequest();
2560 return true; 2671 return true;
2561 } 2672 }
2562 2673
2563 void HttpCache::Transaction::IgnoreRangeRequest() { 2674 void HttpCache::Transaction::IgnoreRangeRequest() {
2564 // We have a problem. We may or may not be reading already (in which case we 2675 // We have a problem. We may or may not be reading already (in which case we
2565 // returned the headers), but we'll just pretend that this request is not 2676 // returned the headers), but we'll just pretend that this request is not
2566 // using the cache and see what happens. Most likely this is the first 2677 // using the cache and see what happens. Most likely this is the first
2567 // response from the server (it's not changing its mind midway, right?). 2678 // response from the server (it's not changing its mind midway, right?).
2568 UpdateTransactionPattern(PATTERN_NOT_COVERED); 2679 UpdateTransactionPattern(PATTERN_NOT_COVERED);
2569 if (mode_ & WRITE) 2680 ReleaseCacheEntry(mode_ == WRITE ? EntryState::DOOMED
rvargas (doing something else) 2015/09/11 23:56:18 wasn't the argument irrelevant for readers? In whi
asanka 2015/09/17 21:59:41 mode_ == READ_WRITE also keeps the entry.
rvargas (doing something else) 2015/09/21 22:05:59 Acknowledged.
2570 DoneWritingToEntry(mode_ != WRITE); 2681 : EntryState::SUCCEEDED);
2571 else if (mode_ & READ && entry_) 2682 partial_.reset();
2572 cache_->DoneReadingFromEntry(entry_, this);
2573
2574 partial_.reset(NULL);
2575 entry_ = NULL;
2576 mode_ = NONE;
2577 } 2683 }
2578 2684
2579 void HttpCache::Transaction::FixHeadersForHead() { 2685 void HttpCache::Transaction::FixHeadersForHead() {
2580 if (response_.headers->response_code() == 206) { 2686 if (response_.headers->response_code() == 206) {
2581 response_.headers->RemoveHeader("Content-Range"); 2687 response_.headers->RemoveHeader("Content-Range");
2582 response_.headers->ReplaceStatusLine("HTTP/1.1 200 OK"); 2688 response_.headers->ReplaceStatusLine("HTTP/1.1 200 OK");
2583 } 2689 }
2584 } 2690 }
2585 2691
2586 int HttpCache::Transaction::SetupEntryForRead() { 2692 int HttpCache::Transaction::SetupEntryForRead() {
(...skipping 29 matching lines...) Expand all
2616 int rv = 0; 2722 int rv = 0;
2617 if (!partial_ || !data_len) { 2723 if (!partial_ || !data_len) {
2618 rv = entry_->disk_entry->WriteData(index, offset, data, data_len, callback, 2724 rv = entry_->disk_entry->WriteData(index, offset, data, data_len, callback,
2619 true); 2725 true);
2620 } else { 2726 } else {
2621 rv = partial_->CacheWrite(entry_->disk_entry, data, data_len, callback); 2727 rv = partial_->CacheWrite(entry_->disk_entry, data, data_len, callback);
2622 } 2728 }
2623 return rv; 2729 return rv;
2624 } 2730 }
2625 2731
2626 int HttpCache::Transaction::WriteResponseInfoToEntry(bool truncated) { 2732 int HttpCache::Transaction::WriteResponseInfoToEntry(
2733 bool truncated,
2734 const CompletionCallback& callback) {
2627 if (!entry_) 2735 if (!entry_)
2628 return OK; 2736 return OK;
2629 2737
2630 if (net_log_.IsCapturing()) 2738 if (net_log_.IsCapturing())
2631 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO); 2739 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO);
2632 2740
2633 // Do not cache no-store content. Do not cache content with cert errors 2741 // Do not cache no-store content. Do not cache content with cert errors
2634 // either. This is to prevent not reporting net errors when loading a 2742 // either. This is to prevent not reporting net errors when loading a
2635 // resource from the cache. When we load a page over HTTPS with a cert error 2743 // resource from the cache. When we load a page over HTTPS with a cert error
2636 // we show an SSL blocking page. If the user clicks proceed we reload the 2744 // we show an SSL blocking page. If the user clicks proceed we reload the
2637 // resource ignoring the errors. The loaded resource is then cached. If that 2745 // resource ignoring the errors. The loaded resource is then cached. If that
2638 // resource is subsequently loaded from the cache, no net error is reported 2746 // resource is subsequently loaded from the cache, no net error is reported
2639 // (even though the cert status contains the actual errors) and no SSL 2747 // (even though the cert status contains the actual errors) and no SSL
2640 // blocking page is shown. An alternative would be to reverse-map the cert 2748 // blocking page is shown. An alternative would be to reverse-map the cert
2641 // status to a net error and replay the net error. 2749 // status to a net error and replay the net error.
2642 if ((response_.headers->HasHeaderValue("cache-control", "no-store")) || 2750 if ((response_.headers->HasHeaderValue("cache-control", "no-store")) ||
2643 IsCertStatusError(response_.ssl_info.cert_status)) { 2751 IsCertStatusError(response_.ssl_info.cert_status)) {
2644 DoneWritingToEntry(false); 2752 ReleaseCacheEntry(EntryState::DOOMED);
2645 if (net_log_.IsCapturing()) 2753 if (net_log_.IsCapturing())
2646 net_log_.EndEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO); 2754 net_log_.EndEvent(NetLog::TYPE_HTTP_CACHE_WRITE_INFO);
2647 return OK; 2755 return OK;
2648 } 2756 }
2649 2757
2650 // cert_cache() will be null if the CertCacheTrial field trial is disabled. 2758 // cert_cache() will be null if the CertCacheTrial field trial is disabled.
2651 if (cache_->cert_cache() && response_.ssl_info.is_valid()) 2759 if (cache_->cert_cache() && response_.ssl_info.is_valid())
2652 WriteCertChain(); 2760 WriteCertChain();
2653 2761
2654 if (truncated) 2762 if (truncated)
2655 DCHECK_EQ(200, response_.headers->response_code()); 2763 DCHECK_EQ(200, response_.headers->response_code());
2656 2764
2657 // When writing headers, we normally only write the non-transient headers. 2765 // When writing headers, we normally only write the non-transient headers.
2658 bool skip_transient_headers = true; 2766 bool skip_transient_headers = true;
2659 scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer()); 2767 scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer());
2660 response_.Persist(data->pickle(), skip_transient_headers, truncated); 2768 response_.Persist(data->pickle(), skip_transient_headers, truncated);
2661 data->Done(); 2769 data->Done();
2662 2770
2663 io_buf_len_ = data->pickle()->size(); 2771 io_buf_len_ = data->pickle()->size();
2664 return entry_->disk_entry->WriteData(kResponseInfoIndex, 0, data.get(), 2772 return entry_->disk_entry->WriteData(kResponseInfoIndex, 0, data.get(),
2665 io_buf_len_, io_callback_, true); 2773 io_buf_len_, callback, true);
2666 } 2774 }
2667 2775
2668 int HttpCache::Transaction::OnWriteResponseInfoToEntryComplete(int result) { 2776 int HttpCache::Transaction::OnWriteResponseInfoToEntryComplete(int result) {
2669 if (!entry_) 2777 if (!entry_)
2670 return OK; 2778 return OK;
2671 if (net_log_.IsCapturing()) { 2779 if (net_log_.IsCapturing()) {
2672 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO, 2780 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_WRITE_INFO,
2673 result); 2781 result);
2674 } 2782 }
2675 2783
2676 if (result != io_buf_len_) { 2784 if (result != io_buf_len_) {
2677 DLOG(ERROR) << "failed to write response info to cache"; 2785 DLOG(ERROR) << "failed to write response info to cache";
2678 DoneWritingToEntry(false); 2786 ReleaseCacheEntry(EntryState::DOOMED);
2679 } 2787 }
2680 return OK; 2788 return OK;
2681 } 2789 }
2682 2790
2683 void HttpCache::Transaction::DoneWritingToEntry(bool success) { 2791 void HttpCache::Transaction::ReleaseCacheEntry(EntryState entry_state) {
2684 if (!entry_) 2792 if (!cache_ || !entry_)
2685 return; 2793 return;
2686 2794
2687 RecordHistograms(); 2795 cache_->DoneWithEntry(entry_, this, entry_state);
2688 2796 entry_ = nullptr;
2689 cache_->DoneWritingToEntry(entry_, success); 2797 stopped_caching_ = false;
2690 entry_ = NULL; 2798 mode_ = NONE;
2691 mode_ = NONE; // switch to 'pass through' mode 2799 return;
rvargas (doing something else) 2015/09/11 23:56:18 remove
asanka 2015/09/17 21:59:41 Done.
2692 } 2800 }
2693 2801
2694 int HttpCache::Transaction::OnCacheReadError(int result, bool restart) { 2802 int HttpCache::Transaction::OnCacheReadError(int result, bool restart) {
2695 DLOG(ERROR) << "ReadData failed: " << result; 2803 DLOG(ERROR) << "ReadData failed: " << result;
2696 const int result_for_histogram = std::max(0, -result); 2804 const int result_for_histogram = std::max(0, -result);
2697 if (restart) { 2805 if (restart) {
2698 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorRestartable", 2806 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorRestartable",
2699 result_for_histogram); 2807 result_for_histogram);
2700 } else { 2808 } else {
2701 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorNonRestartable", 2809 UMA_HISTOGRAM_SPARSE_SLOWLY("HttpCache.ReadErrorNonRestartable",
2702 result_for_histogram); 2810 result_for_histogram);
2703 } 2811 }
2704 2812
2705 // Avoid using this entry in the future. 2813 // Avoid using this entry in the future.
2706 if (cache_.get()) 2814 if (cache_.get())
2707 cache_->DoomActiveEntry(cache_key_); 2815 cache_->DoomActiveEntry(cache_key_);
2708 2816
2709 if (restart) { 2817 if (restart) {
2710 DCHECK(!reading_); 2818 DCHECK(!reading_);
2711 DCHECK(!network_trans_.get()); 2819 DCHECK(!network_trans_.get());
2712 cache_->DoneWithEntry(entry_, this, false); 2820 ReleaseCacheEntry(EntryState::DOOMED);
2713 entry_ = NULL;
2714 is_sparse_ = false; 2821 is_sparse_ = false;
2715 partial_.reset(); 2822 partial_.reset();
2716 next_state_ = STATE_GET_BACKEND; 2823 next_state_ = STATE_GET_BACKEND;
2717 return OK; 2824 return OK;
2718 } 2825 }
2719 2826
2720 return ERR_CACHE_READ_FAILURE; 2827 return ERR_CACHE_READ_FAILURE;
2721 } 2828 }
2722 2829
2723 void HttpCache::Transaction::OnAddToEntryTimeout(base::TimeTicks start_time) { 2830 void HttpCache::Transaction::OnAddToEntryTimeout(base::TimeTicks start_time) {
2724 if (entry_lock_waiting_since_ != start_time) 2831 if (entry_lock_waiting_since_ != start_time)
2725 return; 2832 return;
2726 2833
2727 DCHECK_EQ(next_state_, STATE_ADD_TO_ENTRY_COMPLETE); 2834 DCHECK_EQ(next_state_, STATE_ADD_TO_ENTRY_COMPLETE);
2728 2835
2729 if (!cache_) 2836 if (!cache_)
2730 return; 2837 return;
2731 2838
2732 cache_->RemovePendingTransaction(this); 2839 cache_->RemovePendingTransaction(this);
2733 OnIOComplete(ERR_CACHE_LOCK_TIMEOUT); 2840 OnIOComplete(ERR_CACHE_LOCK_TIMEOUT);
2734 } 2841 }
2735 2842
2736 void HttpCache::Transaction::DoomPartialEntry(bool delete_object) { 2843 void HttpCache::Transaction::DoomPartialEntry(bool delete_object) {
2737 DVLOG(2) << "DoomPartialEntry"; 2844 DVLOG(2) << "DoomPartialEntry";
2738 int rv = cache_->DoomEntry(cache_key_, NULL); 2845 ReleaseCacheEntry(EntryState::DOOMED);
2739 DCHECK_EQ(OK, rv);
2740 cache_->DoneWithEntry(entry_, this, false);
2741 entry_ = NULL;
2742 is_sparse_ = false; 2846 is_sparse_ = false;
2743 truncated_ = false; 2847 truncated_ = false;
2744 if (delete_object) 2848 if (delete_object)
2745 partial_.reset(NULL); 2849 partial_.reset();
2746 } 2850 }
2747 2851
2748 int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) { 2852 int HttpCache::Transaction::DoPartialNetworkReadCompleted(int result) {
2749 partial_->OnNetworkReadCompleted(result); 2853 partial_->OnNetworkReadCompleted(result);
2750 2854
2751 if (result == 0) { 2855 if (result == 0) {
2752 // We need to move on to the next range. 2856 // We need to move on to the next range.
2753 ResetNetworkTransaction(); 2857 ResetNetworkTransaction();
2754 next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION; 2858 next_state_ = STATE_START_PARTIAL_CACHE_VALIDATION;
2755 } 2859 }
(...skipping 11 matching lines...) Expand all
2767 } 2871 }
2768 return result; 2872 return result;
2769 } 2873 }
2770 2874
2771 int HttpCache::Transaction::DoRestartPartialRequest() { 2875 int HttpCache::Transaction::DoRestartPartialRequest() {
2772 // The stored data cannot be used. Get rid of it and restart this request. 2876 // The stored data cannot be used. Get rid of it and restart this request.
2773 net_log_.AddEvent(NetLog::TYPE_HTTP_CACHE_RESTART_PARTIAL_REQUEST); 2877 net_log_.AddEvent(NetLog::TYPE_HTTP_CACHE_RESTART_PARTIAL_REQUEST);
2774 2878
2775 // WRITE + Doom + STATE_INIT_ENTRY == STATE_CREATE_ENTRY (without an attempt 2879 // WRITE + Doom + STATE_INIT_ENTRY == STATE_CREATE_ENTRY (without an attempt
2776 // to Doom the entry again). 2880 // to Doom the entry again).
2881 ResetPartialState(!range_requested_);
2777 mode_ = WRITE; 2882 mode_ = WRITE;
2778 ResetPartialState(!range_requested_);
2779 next_state_ = STATE_CREATE_ENTRY; 2883 next_state_ = STATE_CREATE_ENTRY;
2780 return OK; 2884 return OK;
2781 } 2885 }
2782 2886
2783 void HttpCache::Transaction::ResetPartialState(bool delete_object) { 2887 void HttpCache::Transaction::ResetPartialState(bool delete_object) {
2784 partial_->RestoreHeaders(&custom_request_->extra_headers); 2888 partial_->RestoreHeaders(&custom_request_->extra_headers);
2785 DoomPartialEntry(delete_object); 2889 DoomPartialEntry(delete_object);
2786 2890
2787 if (!delete_object) { 2891 if (!delete_object) {
2788 // The simplest way to re-initialize partial_ is to create a new object. 2892 // The simplest way to re-initialize partial_ is to create a new object.
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
2843 void HttpCache::Transaction::UpdateTransactionPattern( 2947 void HttpCache::Transaction::UpdateTransactionPattern(
2844 TransactionPattern new_transaction_pattern) { 2948 TransactionPattern new_transaction_pattern) {
2845 if (transaction_pattern_ == PATTERN_NOT_COVERED) 2949 if (transaction_pattern_ == PATTERN_NOT_COVERED)
2846 return; 2950 return;
2847 DCHECK(transaction_pattern_ == PATTERN_UNDEFINED || 2951 DCHECK(transaction_pattern_ == PATTERN_UNDEFINED ||
2848 new_transaction_pattern == PATTERN_NOT_COVERED); 2952 new_transaction_pattern == PATTERN_NOT_COVERED);
2849 transaction_pattern_ = new_transaction_pattern; 2953 transaction_pattern_ = new_transaction_pattern;
2850 } 2954 }
2851 2955
2852 void HttpCache::Transaction::RecordHistograms() { 2956 void HttpCache::Transaction::RecordHistograms() {
2853 DCHECK_NE(PATTERN_UNDEFINED, transaction_pattern_); 2957 if (transaction_pattern_ == PATTERN_UNDEFINED || !cache_.get() ||
2854 if (!cache_.get() || !cache_->GetCurrentBackend() || 2958 !cache_->GetCurrentBackend() ||
2855 cache_->GetCurrentBackend()->GetCacheType() != DISK_CACHE || 2959 cache_->GetCurrentBackend()->GetCacheType() != DISK_CACHE ||
2856 cache_->mode() != NORMAL || request_->method != "GET") { 2960 cache_->mode() != NORMAL || request_->method != "GET") {
2857 return; 2961 return;
2858 } 2962 }
2859 UMA_HISTOGRAM_ENUMERATION( 2963 UMA_HISTOGRAM_ENUMERATION("HttpCache.Pattern", transaction_pattern_,
2860 "HttpCache.Pattern", transaction_pattern_, PATTERN_MAX); 2964 PATTERN_MAX);
2861 if (transaction_pattern_ == PATTERN_NOT_COVERED) 2965 if (transaction_pattern_ == PATTERN_NOT_COVERED)
2862 return; 2966 return;
2863 DCHECK(!range_requested_); 2967 DCHECK(!range_requested_);
2864 DCHECK(!first_cache_access_since_.is_null()); 2968 DCHECK(!first_cache_access_since_.is_null());
2865 2969
2866 TimeDelta total_time = base::TimeTicks::Now() - first_cache_access_since_; 2970 TimeDelta total_time = base::TimeTicks::Now() - first_cache_access_since_;
2867 2971
2868 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone", total_time); 2972 UMA_HISTOGRAM_TIMES("HttpCache.AccessToDone", total_time);
2869 2973
2870 bool did_send_request = !send_request_since_.is_null(); 2974 bool did_send_request = !send_request_since_.is_null();
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
2924 } 3028 }
2925 default: 3029 default:
2926 NOTREACHED(); 3030 NOTREACHED();
2927 } 3031 }
2928 } 3032 }
2929 3033
2930 void HttpCache::Transaction::OnIOComplete(int result) { 3034 void HttpCache::Transaction::OnIOComplete(int result) {
2931 DoLoop(result); 3035 DoLoop(result);
2932 } 3036 }
2933 3037
3038 int HttpCache::Transaction::AbandonCacheEntry(
3039 const CompletionCallback& callback) {
3040 if (is_sparse_ || done_reading_ || !(mode_ & WRITE)) {
rvargas (doing something else) 2015/09/11 23:56:18 is_sparse != partial_ && !truncated_ (which is wha
asanka 2015/09/17 21:59:40 Condition updated with explanation.
3041 ReleaseCacheEntry(EntryState::SUCCEEDED);
3042 return OK;
3043 }
3044 if (!reading_ || !CanResume(true)) {
3045 ReleaseCacheEntry(EntryState::DOOMED);
3046 return OK;
3047 }
3048 if (stopped_caching_ && ((mode_ == WRITE && !truncated_) ||
rvargas (doing something else) 2015/09/11 23:56:18 why write vs rw? why write && truncated_ is ok?
asanka 2015/09/17 21:59:41 Removed this condition block. This "if" is trying
3049 (mode_ == READ_WRITE && truncated_))) {
3050 ReleaseCacheEntry(EntryState::DOOMED);
rvargas (doing something else) 2015/09/11 23:56:18 This deserves a comment (what we're after with the
asanka 2015/09/17 21:59:41 (removed)
3051 return OK;
3052 }
3053
3054 truncated_ = true;
3055 int result = WriteResponseInfoToEntry(
3056 true, base::Bind(&HttpCache::Transaction::OnAbandonCacheEntryIOComplete,
3057 weak_factory_.GetWeakPtr()));
3058 if (result == ERR_IO_PENDING) {
3059 if (!callback.is_null()) {
rvargas (doing something else) 2015/09/11 23:56:17 nit: invert the logic
asanka 2015/09/17 21:59:41 Done.
3060 abandon_cache_entry_callback_ = callback;
3061 } else {
3062 ReleaseCacheEntry(EntryState::SUCCEEDED);
3063 }
3064 }
3065 return result;
3066 }
3067
3068 void HttpCache::Transaction::OnAbandonCacheEntryIOComplete(int result) {
3069 OnWriteResponseInfoToEntryComplete(result);
3070 ReleaseCacheEntry(EntryState::SUCCEEDED);
3071 if (!abandon_cache_entry_callback_.is_null())
3072 base::ResetAndReturn(&abandon_cache_entry_callback_).Run(result);
3073 }
3074
2934 } // namespace net 3075 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698