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

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

Issue 10808047: Add HttpCache histograms focussed on blocking and transaction type. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: catch more special cases Created 8 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « net/http/http_cache_transaction.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/http/http_cache_transaction.h" 5 #include "net/http/http_cache_transaction.h"
6 6
7 #include "build/build_config.h" 7 #include "build/build_config.h"
8 8
9 #if defined(OS_POSIX) 9 #if defined(OS_POSIX)
10 #include <unistd.h> 10 #include <unistd.h>
(...skipping 23 matching lines...) Expand all
34 #include "net/http/http_transaction.h" 34 #include "net/http/http_transaction.h"
35 #include "net/http/http_util.h" 35 #include "net/http/http_util.h"
36 #include "net/http/partial_data.h" 36 #include "net/http/partial_data.h"
37 37
38 using base::Time; 38 using base::Time;
39 using base::TimeDelta; 39 using base::TimeDelta;
40 using base::TimeTicks; 40 using base::TimeTicks;
41 41
42 namespace net { 42 namespace net {
43 43
44 namespace {
rvargas (doing something else) 2012/07/21 02:24:21 Move this outside of net
gavinp 2012/07/25 01:07:01 Done. You didn't say why: is it because it doesn't
rvargas (doing something else) 2012/07/25 19:41:04 In part because it's the common pattern everywhere
45
46 // The cutoff for tagging small transactions in histograms; this size was chosen
47 // to cover resources likely to be received in a single TCP window. With an
48 // initial CWND of 10, and an MTU of 1500 bytes, with TCP and HTTP framing
49 // overhead this is a size relatively likely to take only one RTT.
50 const int kSmallResourceMaxBytes = 14 * 1024;
51
52 // Requests faster than this do not report as many performance histograms.
53 const int kFastRequestCutoffMs = 5;
54
55 }
56
44 struct HeaderNameAndValue { 57 struct HeaderNameAndValue {
45 const char* name; 58 const char* name;
46 const char* value; 59 const char* value;
47 }; 60 };
48 61
49 // If the request includes one of these request headers, then avoid caching 62 // If the request includes one of these request headers, then avoid caching
50 // to avoid getting confused. 63 // to avoid getting confused.
51 static const HeaderNameAndValue kPassThroughHeaders[] = { 64 static const HeaderNameAndValue kPassThroughHeaders[] = {
52 { "if-unmodified-since", NULL }, // causes unexpected 412s 65 { "if-unmodified-since", NULL }, // causes unexpected 412s
53 { "if-match", NULL }, // causes unexpected 412s 66 { "if-match", NULL }, // causes unexpected 412s
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 handling_206_(false), 132 handling_206_(false),
120 cache_pending_(false), 133 cache_pending_(false),
121 done_reading_(false), 134 done_reading_(false),
122 read_offset_(0), 135 read_offset_(0),
123 effective_load_flags_(0), 136 effective_load_flags_(0),
124 write_len_(0), 137 write_len_(0),
125 final_upload_progress_(0), 138 final_upload_progress_(0),
126 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), 139 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
127 ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_( 140 ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_(
128 base::Bind(&Transaction::OnIOComplete, 141 base::Bind(&Transaction::OnIOComplete,
129 weak_factory_.GetWeakPtr()))) { 142 weak_factory_.GetWeakPtr()))),
143 disposition_(DISPOSITION_UNDEFINED) {
130 COMPILE_ASSERT(HttpCache::Transaction::kNumValidationHeaders == 144 COMPILE_ASSERT(HttpCache::Transaction::kNumValidationHeaders ==
131 arraysize(kValidationHeaders), 145 arraysize(kValidationHeaders),
132 Invalid_number_of_validation_headers); 146 Invalid_number_of_validation_headers);
133 } 147 }
134 148
135 HttpCache::Transaction::~Transaction() { 149 HttpCache::Transaction::~Transaction() {
136 // We may have to issue another IO, but we should never invoke the callback_ 150 // We may have to issue another IO, but we should never invoke the callback_
137 // after this point. 151 // after this point.
138 callback_.Reset(); 152 callback_.Reset();
139 153
(...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after
663 result); 677 result);
664 cache_pending_ = false; 678 cache_pending_ = false;
665 679
666 if (!ShouldPassThrough()) { 680 if (!ShouldPassThrough()) {
667 cache_key_ = cache_->GenerateCacheKey(request_); 681 cache_key_ = cache_->GenerateCacheKey(request_);
668 682
669 // Requested cache access mode. 683 // Requested cache access mode.
670 if (effective_load_flags_ & LOAD_ONLY_FROM_CACHE) { 684 if (effective_load_flags_ & LOAD_ONLY_FROM_CACHE) {
671 mode_ = READ; 685 mode_ = READ;
672 } else if (effective_load_flags_ & LOAD_BYPASS_CACHE) { 686 } else if (effective_load_flags_ & LOAD_BYPASS_CACHE) {
687 // Don't record a load that isn't really testing the cache.
rvargas (doing something else) 2012/07/21 02:24:21 This goes through the cache.
gavinp 2012/07/25 01:07:01 Good point. Comment fixed. Srsly fixed.
688 MaybeUpdateDisposition(DISPOSITION_DO_NOT_RECORD);
673 mode_ = WRITE; 689 mode_ = WRITE;
674 } else { 690 } else {
675 mode_ = READ_WRITE; 691 mode_ = READ_WRITE;
676 } 692 }
677 693
678 // Downgrade to UPDATE if the request has been externally conditionalized. 694 // Downgrade to UPDATE if the request has been externally conditionalized.
679 if (external_validation_.initialized) { 695 if (external_validation_.initialized) {
680 if (mode_ & WRITE) { 696 if (mode_ & WRITE) {
681 // Strip off the READ_DATA bit (and maybe add back a READ_META bit 697 // Strip off the READ_DATA bit (and maybe add back a READ_META bit
682 // in case READ was off). 698 // in case READ was off).
(...skipping 28 matching lines...) Expand all
711 // This is only set if we have something to do with the response. 727 // This is only set if we have something to do with the response.
712 range_requested_ = (partial_.get() != NULL); 728 range_requested_ = (partial_.get() != NULL);
713 729
714 return OK; 730 return OK;
715 } 731 }
716 732
717 int HttpCache::Transaction::DoSendRequest() { 733 int HttpCache::Transaction::DoSendRequest() {
718 DCHECK(mode_ & WRITE || mode_ == NONE); 734 DCHECK(mode_ & WRITE || mode_ == NONE);
719 DCHECK(!network_trans_.get()); 735 DCHECK(!network_trans_.get());
720 736
737 started_reading_since_ = TimeTicks::Now();
rvargas (doing something else) 2012/07/21 02:24:21 The name is weird for what it is measuring.
gavinp 2012/07/25 01:07:01 Yup. Do you like the new name and use?
738
721 // Create a network transaction. 739 // Create a network transaction.
722 int rv = cache_->network_layer_->CreateTransaction(&network_trans_); 740 int rv = cache_->network_layer_->CreateTransaction(&network_trans_);
723 if (rv != OK) 741 if (rv != OK)
724 return rv; 742 return rv;
725 743
726 next_state_ = STATE_SEND_REQUEST_COMPLETE; 744 next_state_ = STATE_SEND_REQUEST_COMPLETE;
727 rv = network_trans_->Start(request_, io_callback_, net_log_); 745 rv = network_trans_->Start(request_, io_callback_, net_log_);
728 return rv; 746 return rv;
729 } 747 }
730 748
731 int HttpCache::Transaction::DoSendRequestComplete(int result) { 749 int HttpCache::Transaction::DoSendRequestComplete(int result) {
732 if (!cache_) 750 if (!cache_)
733 return ERR_UNEXPECTED; 751 return ERR_UNEXPECTED;
734 752
735 if (result == OK) { 753 if (result == OK) {
736 next_state_ = STATE_SUCCESSFUL_SEND_REQUEST; 754 next_state_ = STATE_SUCCESSFUL_SEND_REQUEST;
737 return OK; 755 return OK;
738 } 756 }
739 757
758 // Do not record requests that have network errors or restarts.
759 MaybeUpdateDisposition(DISPOSITION_DO_NOT_RECORD);
740 if (IsCertificateError(result)) { 760 if (IsCertificateError(result)) {
741 const HttpResponseInfo* response = network_trans_->GetResponseInfo(); 761 const HttpResponseInfo* response = network_trans_->GetResponseInfo();
742 // If we get a certificate error, then there is a certificate in ssl_info, 762 // If we get a certificate error, then there is a certificate in ssl_info,
743 // so GetResponseInfo() should never return NULL here. 763 // so GetResponseInfo() should never return NULL here.
744 DCHECK(response); 764 DCHECK(response);
745 response_.ssl_info = response->ssl_info; 765 response_.ssl_info = response->ssl_info;
746 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { 766 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
747 const HttpResponseInfo* response = network_trans_->GetResponseInfo(); 767 const HttpResponseInfo* response = network_trans_->GetResponseInfo();
748 DCHECK(response); 768 DCHECK(response);
749 response_.cert_request_info = response->cert_request_info; 769 response_.cert_request_info = response->cert_request_info;
(...skipping 10 matching lines...) Expand all
760 auth_response_ = *new_response; 780 auth_response_ = *new_response;
761 return OK; 781 return OK;
762 } 782 }
763 783
764 new_response_ = new_response; 784 new_response_ = new_response;
765 if (!ValidatePartialResponse() && !auth_response_.headers) { 785 if (!ValidatePartialResponse() && !auth_response_.headers) {
766 // Something went wrong with this request and we have to restart it. 786 // Something went wrong with this request and we have to restart it.
767 // If we have an authentication response, we are exposed to weird things 787 // If we have an authentication response, we are exposed to weird things
768 // hapenning if the user cancels the authentication before we receive 788 // hapenning if the user cancels the authentication before we receive
769 // the new response. 789 // the new response.
790 MaybeUpdateDisposition(DISPOSITION_DO_NOT_RECORD);
770 response_ = HttpResponseInfo(); 791 response_ = HttpResponseInfo();
771 network_trans_.reset(); 792 network_trans_.reset();
772 new_response_ = NULL; 793 new_response_ = NULL;
773 next_state_ = STATE_SEND_REQUEST; 794 next_state_ = STATE_SEND_REQUEST;
774 return OK; 795 return OK;
775 } 796 }
776 if (handling_206_ && mode_ == READ_WRITE && !truncated_ && !is_sparse_) { 797 if (handling_206_ && mode_ == READ_WRITE && !truncated_ && !is_sparse_) {
777 // We have stored the full entry, but it changed and the server is 798 // We have stored the full entry, but it changed and the server is
778 // sending a range. We have to delete the old entry. 799 // sending a range. We have to delete the old entry.
779 DoneWritingToEntry(false); 800 DoneWritingToEntry(false);
780 } 801 }
781 802
rvargas (doing something else) 2012/07/25 19:41:04 Do you mind keeping this line?
gavinp 2012/07/28 01:36:06 Done.
782 if (new_response_->headers->response_code() == 416) { 803 if (new_response_->headers->response_code() == 416) {
783 DCHECK_EQ(NONE, mode_); 804 DCHECK_EQ(NONE, mode_);
784 response_ = *new_response_; 805 response_ = *new_response_;
785 return OK; 806 return OK;
786 } 807 }
787 808
788 if (mode_ == WRITE && 809 if (mode_ == WRITE &&
789 (request_->method == "PUT" || request_->method == "DELETE")) { 810 (request_->method == "PUT" || request_->method == "DELETE")) {
790 if (new_response->headers->response_code() == 200) { 811 if (new_response->headers->response_code() == 200) {
791 int ret = cache_->DoomEntry(cache_key_, NULL); 812 int ret = cache_->DoomEntry(cache_key_, NULL);
792 DCHECK_EQ(OK, ret); 813 DCHECK_EQ(OK, ret);
793 } 814 }
794 mode_ = NONE; 815 mode_ = NONE;
795 } 816 }
796 817
797 // Are we expecting a response to a conditional query? 818 // Are we expecting a response to a conditional query?
798 if (mode_ == READ_WRITE || mode_ == UPDATE) { 819 if (mode_ == READ_WRITE || mode_ == UPDATE) {
799 if (new_response->headers->response_code() == 304 || handling_206_) { 820 if (new_response->headers->response_code() == 304 || handling_206_) {
821 MaybeUpdateDisposition(DISPOSITION_ENTRY_VALIDATED_304);
rvargas (doing something else) 2012/07/21 02:24:21 This is more than just 304. Why not drop the 304 p
gavinp 2012/07/25 01:07:01 Done, the new more consistant names are good. Than
rvargas (doing something else) 2012/07/25 19:41:04 No other case, but to know that 206 doesn't matter
800 next_state_ = STATE_UPDATE_CACHED_RESPONSE; 822 next_state_ = STATE_UPDATE_CACHED_RESPONSE;
801 return OK; 823 return OK;
802 } 824 }
825 MaybeUpdateDisposition(DISPOSITION_ENTRY_VALIDATED_200);
rvargas (doing something else) 2012/07/21 02:24:21 What about names that match the histogram? used, v
gavinp 2012/07/25 01:07:01 Done.
803 mode_ = WRITE; 826 mode_ = WRITE;
804 } 827 }
805 828
806 next_state_ = STATE_OVERWRITE_CACHED_RESPONSE; 829 next_state_ = STATE_OVERWRITE_CACHED_RESPONSE;
807 return OK; 830 return OK;
808 } 831 }
809 832
810 int HttpCache::Transaction::DoNetworkRead() { 833 int HttpCache::Transaction::DoNetworkRead() {
811 next_state_ = STATE_NETWORK_READ_COMPLETE; 834 next_state_ = STATE_NETWORK_READ_COMPLETE;
812 return network_trans_->Read(read_buf_, io_buf_len_, io_callback_); 835 return network_trans_->Read(read_buf_, io_buf_len_, io_callback_);
(...skipping 27 matching lines...) Expand all
840 863
841 next_state_ = STATE_OPEN_ENTRY; 864 next_state_ = STATE_OPEN_ENTRY;
842 return OK; 865 return OK;
843 } 866 }
844 867
845 int HttpCache::Transaction::DoOpenEntry() { 868 int HttpCache::Transaction::DoOpenEntry() {
846 DCHECK(!new_entry_); 869 DCHECK(!new_entry_);
847 next_state_ = STATE_OPEN_ENTRY_COMPLETE; 870 next_state_ = STATE_OPEN_ENTRY_COMPLETE;
848 cache_pending_ = true; 871 cache_pending_ = true;
849 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY); 872 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY);
873 open_entry_since_ = TimeTicks::Now();
850 return cache_->OpenEntry(cache_key_, &new_entry_, this); 874 return cache_->OpenEntry(cache_key_, &new_entry_, this);
851 } 875 }
852 876
853 int HttpCache::Transaction::DoOpenEntryComplete(int result) { 877 int HttpCache::Transaction::DoOpenEntryComplete(int result) {
854 // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is 878 // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is
855 // OK, otherwise the cache will end up with an active entry without any 879 // OK, otherwise the cache will end up with an active entry without any
856 // transaction attached. 880 // transaction attached.
857 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY, result); 881 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY, result);
858 cache_pending_ = false; 882 cache_pending_ = false;
859 if (result == OK) { 883 if (result == OK) {
860 next_state_ = STATE_ADD_TO_ENTRY; 884 next_state_ = STATE_ADD_TO_ENTRY;
861 return OK; 885 return OK;
862 } 886 }
863 887
864 if (result == ERR_CACHE_RACE) { 888 if (result == ERR_CACHE_RACE) {
865 next_state_ = STATE_INIT_ENTRY; 889 next_state_ = STATE_INIT_ENTRY;
866 return OK; 890 return OK;
867 } 891 }
868 892
893 MaybeUpdateDisposition(DISPOSITION_NO_ENTRY);
869 if (request_->method == "PUT" || request_->method == "DELETE") { 894 if (request_->method == "PUT" || request_->method == "DELETE") {
870 DCHECK(mode_ == READ_WRITE || mode_ == WRITE); 895 DCHECK(mode_ == READ_WRITE || mode_ == WRITE);
871 mode_ = NONE; 896 mode_ = NONE;
872 next_state_ = STATE_SEND_REQUEST; 897 next_state_ = STATE_SEND_REQUEST;
873 return OK; 898 return OK;
874 } 899 }
875 900
876 if (mode_ == READ_WRITE) { 901 if (mode_ == READ_WRITE) {
877 mode_ = WRITE; 902 mode_ = WRITE;
878 next_state_ = STATE_CREATE_ENTRY; 903 next_state_ = STATE_CREATE_ENTRY;
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after
1232 // o if we can read or write, then we should check if the cache entry needs 1257 // o if we can read or write, then we should check if the cache entry needs
1233 // to be validated and then issue a network request if needed or just read 1258 // to be validated and then issue a network request if needed or just read
1234 // from the cache if the cache entry is already valid. 1259 // from the cache if the cache entry is already valid.
1235 // 1260 //
1236 // o if we are set to UPDATE, then we are handling an externally 1261 // o if we are set to UPDATE, then we are handling an externally
1237 // conditionalized request (if-modified-since / if-none-match). We check 1262 // conditionalized request (if-modified-since / if-none-match). We check
1238 // if the request headers define a validation request. 1263 // if the request headers define a validation request.
1239 // 1264 //
1240 switch (mode_) { 1265 switch (mode_) {
1241 case READ: 1266 case READ:
1267 MaybeUpdateDisposition(DISPOSITION_ENTRY_UNCONDITIONALLY_USED);
1268 started_reading_since_ = TimeTicks::Now();
rvargas (doing something else) 2012/07/21 02:24:21 Now I'm confused about what do you want to measure
gavinp 2012/07/25 01:07:01 You're right, it was too confusing. I came into th
1242 result = BeginCacheRead(); 1269 result = BeginCacheRead();
1243 break; 1270 break;
1244 case READ_WRITE: 1271 case READ_WRITE:
1245 result = BeginPartialCacheValidation(); 1272 result = BeginPartialCacheValidation();
1246 break; 1273 break;
1247 case UPDATE: 1274 case UPDATE:
1248 result = BeginExternallyConditionalizedRequest(); 1275 result = BeginExternallyConditionalizedRequest();
1249 break; 1276 break;
1250 case WRITE: 1277 case WRITE:
1251 default: 1278 default:
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1296 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO); 1323 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO);
1297 return entry_->disk_entry->ReadData(kMetadataIndex, 0, response_.metadata, 1324 return entry_->disk_entry->ReadData(kMetadataIndex, 0, response_.metadata,
1298 response_.metadata->size(), 1325 response_.metadata->size(),
1299 io_callback_); 1326 io_callback_);
1300 } 1327 }
1301 1328
1302 int HttpCache::Transaction::DoCacheReadMetadataComplete(int result) { 1329 int HttpCache::Transaction::DoCacheReadMetadataComplete(int result) {
1303 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result); 1330 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result);
1304 if (result != response_.metadata->size()) 1331 if (result != response_.metadata->size())
1305 return OnCacheReadError(result, false); 1332 return OnCacheReadError(result, false);
1306 1333
rvargas (doing something else) 2012/07/25 19:41:04 do you mind keeping the line?
1307 return OK; 1334 return OK;
1308 } 1335 }
1309 1336
1310 int HttpCache::Transaction::DoCacheQueryData() { 1337 int HttpCache::Transaction::DoCacheQueryData() {
1311 next_state_ = STATE_CACHE_QUERY_DATA_COMPLETE; 1338 next_state_ = STATE_CACHE_QUERY_DATA_COMPLETE;
1312 1339
1313 // Balanced in DoCacheQueryDataComplete. 1340 // Balanced in DoCacheQueryDataComplete.
1314 return entry_->disk_entry->ReadyForSparseIO(io_callback_); 1341 return entry_->disk_entry->ReadyForSparseIO(io_callback_);
1315 } 1342 }
1316 1343
(...skipping 22 matching lines...) Expand all
1339 1366
1340 int HttpCache::Transaction::DoCacheReadDataComplete(int result) { 1367 int HttpCache::Transaction::DoCacheReadDataComplete(int result) {
1341 if (net_log_.IsLoggingAllEvents()) { 1368 if (net_log_.IsLoggingAllEvents()) {
1342 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_DATA, 1369 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_DATA,
1343 result); 1370 result);
1344 } 1371 }
1345 1372
1346 if (!cache_) 1373 if (!cache_)
1347 return ERR_UNEXPECTED; 1374 return ERR_UNEXPECTED;
1348 1375
1349 if (partial_.get()) 1376 if (partial_.get()) {
1377 // Partial requests are confusing to report in histograms because they may
1378 // have multiple underlying requests.
1379 MaybeUpdateDisposition(DISPOSITION_DO_NOT_RECORD);
1350 return DoPartialCacheReadCompleted(result); 1380 return DoPartialCacheReadCompleted(result);
1381 }
1351 1382
1352 if (result > 0) { 1383 if (result > 0) {
1353 read_offset_ += result; 1384 read_offset_ += result;
1354 } else if (result == 0) { // End of file. 1385 } else if (result == 0) { // End of file.
1386 RecordHistograms(read_offset_);
1355 cache_->DoneReadingFromEntry(entry_, this); 1387 cache_->DoneReadingFromEntry(entry_, this);
1356 entry_ = NULL; 1388 entry_ = NULL;
1357 } else { 1389 } else {
1358 return OnCacheReadError(result, false); 1390 return OnCacheReadError(result, false);
1359 } 1391 }
1360 return result; 1392 return result;
1361 } 1393 }
1362 1394
1363 int HttpCache::Transaction::DoCacheWriteData(int num_bytes) { 1395 int HttpCache::Transaction::DoCacheWriteData(int num_bytes) {
1364 next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE; 1396 next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE;
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
1492 1524
1493 // If there is more than one validation header, we can't treat this request as 1525 // If there is more than one validation header, we can't treat this request as
1494 // a cache validation, since we don't know for sure which header the server 1526 // a cache validation, since we don't know for sure which header the server
1495 // will give us a response for (and they could be contradictory). 1527 // will give us a response for (and they could be contradictory).
1496 if (external_validation_error) { 1528 if (external_validation_error) {
1497 LOG(WARNING) << "Multiple or malformed validation headers found."; 1529 LOG(WARNING) << "Multiple or malformed validation headers found.";
1498 effective_load_flags_ |= LOAD_DISABLE_CACHE; 1530 effective_load_flags_ |= LOAD_DISABLE_CACHE;
1499 } 1531 }
1500 1532
1501 if (range_found && !(effective_load_flags_ & LOAD_DISABLE_CACHE)) { 1533 if (range_found && !(effective_load_flags_ & LOAD_DISABLE_CACHE)) {
1534 MaybeUpdateDisposition(DISPOSITION_DO_NOT_RECORD);
1502 partial_.reset(new PartialData); 1535 partial_.reset(new PartialData);
1503 if (request_->method == "GET" && partial_->Init(request_->extra_headers)) { 1536 if (request_->method == "GET" && partial_->Init(request_->extra_headers)) {
1504 // We will be modifying the actual range requested to the server, so 1537 // We will be modifying the actual range requested to the server, so
1505 // let's remove the header here. 1538 // let's remove the header here.
1506 custom_request_.reset(new HttpRequestInfo(*request_)); 1539 custom_request_.reset(new HttpRequestInfo(*request_));
1507 custom_request_->extra_headers.RemoveHeader(HttpRequestHeaders::kRange); 1540 custom_request_->extra_headers.RemoveHeader(HttpRequestHeaders::kRange);
1508 request_ = custom_request_.get(); 1541 request_ = custom_request_.get();
1509 partial_->SetHeaders(custom_request_->extra_headers); 1542 partial_->SetHeaders(custom_request_->extra_headers);
1510 } else { 1543 } else {
1511 // The range is invalid or we cannot handle it properly. 1544 // The range is invalid or we cannot handle it properly.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1563 1596
1564 return OK; 1597 return OK;
1565 } 1598 }
1566 1599
1567 int HttpCache::Transaction::BeginCacheValidation() { 1600 int HttpCache::Transaction::BeginCacheValidation() {
1568 DCHECK(mode_ == READ_WRITE); 1601 DCHECK(mode_ == READ_WRITE);
1569 1602
1570 bool skip_validation = effective_load_flags_ & LOAD_PREFERRING_CACHE || 1603 bool skip_validation = effective_load_flags_ & LOAD_PREFERRING_CACHE ||
1571 !RequiresValidation(); 1604 !RequiresValidation();
1572 1605
1573 if (truncated_) 1606 if (truncated_) {
1607 // Truncated entries can cause partial gets, so we shouldn't record this
1608 // load in histograms.
1609 MaybeUpdateDisposition(DISPOSITION_DO_NOT_RECORD);
1574 skip_validation = !partial_->initial_validation(); 1610 skip_validation = !partial_->initial_validation();
1611 }
1575 1612
1576 if ((partial_.get() && !partial_->IsCurrentRangeCached()) || invalid_range_) 1613 if ((partial_.get() && !partial_->IsCurrentRangeCached()) || invalid_range_)
1577 skip_validation = false; 1614 skip_validation = false;
1578 1615
1579 if (skip_validation) { 1616 if (skip_validation) {
1617 MaybeUpdateDisposition(DISPOSITION_ENTRY_UNCONDITIONALLY_USED);
1618 started_reading_since_ = TimeTicks::Now();
1580 if (partial_.get()) { 1619 if (partial_.get()) {
1581 // We are going to return the saved response headers to the caller, so 1620 // We are going to return the saved response headers to the caller, so
1582 // we may need to adjust them first. 1621 // we may need to adjust them first.
1583 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED; 1622 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
1584 return OK; 1623 return OK;
1585 } 1624 }
1586 cache_->ConvertWriterToReader(entry_); 1625 cache_->ConvertWriterToReader(entry_);
1587 mode_ = READ; 1626 mode_ = READ;
1588 1627
1589 if (entry_->disk_entry->GetDataSize(kMetadataIndex)) 1628 if (entry_->disk_entry->GetDataSize(kMetadataIndex))
1590 next_state_ = STATE_CACHE_READ_METADATA; 1629 next_state_ = STATE_CACHE_READ_METADATA;
1591 } else { 1630 } else {
1592 // Make the network request conditional, to see if we may reuse our cached 1631 // Make the network request conditional, to see if we may reuse our cached
1593 // response. If we cannot do so, then we just resort to a normal fetch. 1632 // response. If we cannot do so, then we just resort to a normal fetch.
1594 // Our mode remains READ_WRITE for a conditional request. We'll switch to 1633 // Our mode remains READ_WRITE for a conditional request. We'll switch to
1595 // either READ or WRITE mode once we hear back from the server. 1634 // either READ or WRITE mode once we hear back from the server.
1596 if (!ConditionalizeRequest()) { 1635 if (!ConditionalizeRequest()) {
1636 MaybeUpdateDisposition(DISPOSITION_ENTRY_UNCONDITIONALLY_USED);
1597 DCHECK(!partial_.get()); 1637 DCHECK(!partial_.get());
1598 DCHECK_NE(206, response_.headers->response_code()); 1638 DCHECK_NE(206, response_.headers->response_code());
1599 mode_ = WRITE; 1639 mode_ = WRITE;
1600 } 1640 }
1601 next_state_ = STATE_SEND_REQUEST; 1641 next_state_ = STATE_SEND_REQUEST;
1602 } 1642 }
1603 return OK; 1643 return OK;
1604 } 1644 }
1605 1645
1606 int HttpCache::Transaction::BeginPartialCacheValidation() { 1646 int HttpCache::Transaction::BeginPartialCacheValidation() {
1607 DCHECK(mode_ == READ_WRITE); 1647 DCHECK(mode_ == READ_WRITE);
1608 1648
1609 if (response_.headers->response_code() != 206 && !partial_.get() && 1649 if (response_.headers->response_code() != 206 && !partial_.get() &&
1610 !truncated_) 1650 !truncated_)
1611 return BeginCacheValidation(); 1651 return BeginCacheValidation();
1612 1652
1653 // Partial requests should not be recorded in histograms.
1654 MaybeUpdateDisposition(DISPOSITION_DO_NOT_RECORD);
1613 if (range_requested_) { 1655 if (range_requested_) {
1614 next_state_ = STATE_CACHE_QUERY_DATA; 1656 next_state_ = STATE_CACHE_QUERY_DATA;
1615 return OK; 1657 return OK;
1616 } 1658 }
1617 // The request is not for a range, but we have stored just ranges. 1659 // The request is not for a range, but we have stored just ranges.
1618 partial_.reset(new PartialData()); 1660 partial_.reset(new PartialData());
1619 partial_->SetHeaders(request_->extra_headers); 1661 partial_->SetHeaders(request_->extra_headers);
1620 if (!custom_request_.get()) { 1662 if (!custom_request_.get()) {
1621 custom_request_.reset(new HttpRequestInfo(*request_)); 1663 custom_request_.reset(new HttpRequestInfo(*request_));
1622 request_ = custom_request_.get(); 1664 request_ = custom_request_.get();
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1663 std::string validator; 1705 std::string validator;
1664 response_.headers->EnumerateHeader( 1706 response_.headers->EnumerateHeader(
1665 NULL, 1707 NULL,
1666 kValidationHeaders[i].related_response_header_name, 1708 kValidationHeaders[i].related_response_header_name,
1667 &validator); 1709 &validator);
1668 1710
1669 if (response_.headers->response_code() != 200 || truncated_ || 1711 if (response_.headers->response_code() != 200 || truncated_ ||
1670 validator.empty() || validator != external_validation_.values[i]) { 1712 validator.empty() || validator != external_validation_.values[i]) {
1671 // The externally conditionalized request is not a validation request 1713 // The externally conditionalized request is not a validation request
1672 // for our existing cache entry. Proceed with caching disabled. 1714 // for our existing cache entry. Proceed with caching disabled.
1715 MaybeUpdateDisposition(DISPOSITION_DO_NOT_RECORD);
1673 DoneWritingToEntry(true); 1716 DoneWritingToEntry(true);
1674 } 1717 }
1675 } 1718 }
1676 1719
1677 next_state_ = STATE_SEND_REQUEST; 1720 next_state_ = STATE_SEND_REQUEST;
1678 return OK; 1721 return OK;
1679 } 1722 }
1680 1723
1681 int HttpCache::Transaction::RestartNetworkRequest() { 1724 int HttpCache::Transaction::RestartNetworkRequest() {
1682 DCHECK(mode_ & WRITE || mode_ == NONE); 1725 DCHECK(mode_ & WRITE || mode_ == NONE);
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
1886 } 1929 }
1887 1930
1888 // 304 is not expected here, but we'll spare the entry (unless it was 1931 // 304 is not expected here, but we'll spare the entry (unless it was
1889 // truncated). 1932 // truncated).
1890 if (truncated_) 1933 if (truncated_)
1891 failure = true; 1934 failure = true;
1892 } 1935 }
1893 1936
1894 if (failure) { 1937 if (failure) {
1895 // We cannot truncate this entry, it has to be deleted. 1938 // We cannot truncate this entry, it has to be deleted.
1939 MaybeUpdateDisposition(DISPOSITION_DO_NOT_RECORD);
1896 DoomPartialEntry(false); 1940 DoomPartialEntry(false);
1897 mode_ = NONE; 1941 mode_ = NONE;
1898 if (!reading_ && !partial_->IsLastRange()) { 1942 if (!reading_ && !partial_->IsLastRange()) {
1899 // We'll attempt to issue another network request, this time without us 1943 // We'll attempt to issue another network request, this time without us
1900 // messing up the headers. 1944 // messing up the headers.
1901 partial_->RestoreHeaders(&custom_request_->extra_headers); 1945 partial_->RestoreHeaders(&custom_request_->extra_headers);
1902 partial_.reset(); 1946 partial_.reset();
1903 truncated_ = false; 1947 truncated_ = false;
1904 return false; 1948 return false;
1905 } 1949 }
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
2008 2052
2009 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); 2053 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
2010 return WriteToEntry(kResponseContentIndex, current_size, data, data_len, 2054 return WriteToEntry(kResponseContentIndex, current_size, data, data_len,
2011 callback); 2055 callback);
2012 } 2056 }
2013 2057
2014 void HttpCache::Transaction::DoneWritingToEntry(bool success) { 2058 void HttpCache::Transaction::DoneWritingToEntry(bool success) {
2015 if (!entry_) 2059 if (!entry_)
2016 return; 2060 return;
2017 2061
2018 if (cache_->mode() == RECORD) 2062 RecordHistograms(entry_->disk_entry->GetDataSize(kResponseContentIndex));
2063 if (cache_->mode() == RECORD) {
2019 DVLOG(1) << "Recorded: " << request_->method << request_->url 2064 DVLOG(1) << "Recorded: " << request_->method << request_->url
rvargas (doing something else) 2012/07/21 02:24:21 unrelated: we should just delete this log.
gavinp 2012/07/25 01:07:01 Done.
2020 << " status: " << response_.headers->response_code(); 2065 << " status: " << response_.headers->response_code();
2066 }
2021 2067
2022 cache_->DoneWritingToEntry(entry_, success); 2068 cache_->DoneWritingToEntry(entry_, success);
2023 entry_ = NULL; 2069 entry_ = NULL;
2024 mode_ = NONE; // switch to 'pass through' mode 2070 mode_ = NONE; // switch to 'pass through' mode
2025 } 2071 }
2026 2072
2027 int HttpCache::Transaction::OnCacheReadError(int result, bool restart) { 2073 int HttpCache::Transaction::OnCacheReadError(int result, bool restart) {
2028 DLOG(ERROR) << "ReadData failed: " << result; 2074 DLOG(ERROR) << "ReadData failed: " << result;
2029 2075
2030 // Avoid using this entry in the future. 2076 // Avoid using this entry in the future.
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
2105 !response_.headers->HasStrongValidators()) 2151 !response_.headers->HasStrongValidators())
2106 return false; 2152 return false;
2107 2153
2108 return true; 2154 return true;
2109 } 2155 }
2110 2156
2111 void HttpCache::Transaction::OnIOComplete(int result) { 2157 void HttpCache::Transaction::OnIOComplete(int result) {
2112 DoLoop(result); 2158 DoLoop(result);
2113 } 2159 }
2114 2160
2161 void HttpCache::Transaction::MaybeUpdateDisposition(
rvargas (doing something else) 2012/07/21 02:24:21 Remove the "maybe" part from the name.
gavinp 2012/07/25 01:07:01 Done.
2162 const Disposition disposition) {
rvargas (doing something else) 2012/07/21 02:24:21 Drop the const
gavinp 2012/07/25 01:07:01 Done.
2163 // Once a transaction has been found to have a complicated disposition, it
2164 // can't change to any other simpler disposition.
2165 if (disposition_ == DISPOSITION_DO_NOT_RECORD)
rvargas (doing something else) 2012/07/21 02:24:21 is this really worth the extra work?. We could jus
gavinp 2012/07/25 01:07:01 Done. Having both and the DCHECK was very good for
gavinp 2012/07/25 14:00:27 I should have updated this comment before uploadin
2166 return;
2167 DCHECK(disposition_ == DISPOSITION_UNDEFINED ||
2168 disposition == DISPOSITION_DO_NOT_RECORD);
rvargas (doing something else) 2012/07/21 02:24:21 cannot reach do_not_record
gavinp 2012/07/25 01:07:01 Hrm, you are wrong. Does this mean I'm naming my p
rvargas (doing something else) 2012/07/25 19:41:04 Why am I wrong? the previous line returns if p_not
gavinp 2012/07/28 01:36:06 The previous line compares the member variable |di
2169 disposition_ = disposition;
2170 }
2171
2172 void HttpCache::Transaction::RecordHistograms(const int resource_size) {
rvargas (doing something else) 2012/07/21 02:24:21 Drop the const
gavinp 2012/07/25 01:07:01 Done.
2173 if (cache_->mode() != NORMAL || request_->method != "GET")
2174 return;
2175
2176 UMA_HISTOGRAM_BOOLEAN(
2177 "HttpCache.DoNotRecord", disposition_ == DISPOSITION_DO_NOT_RECORD);
2178 if (disposition_ == DISPOSITION_DO_NOT_RECORD)
2179 return;
2180 DCHECK(!range_requested_);
2181 DCHECK_NE(DISPOSITION_UNDEFINED, disposition_);
gavinp 2012/07/20 17:19:24 Should these DCHECKs be changed into early returns
rvargas (doing something else) 2012/07/21 02:24:21 DCHECKS seem file to me.
gavinp 2012/07/25 01:07:01 What I found very interesting was how many differe
2182 DCHECK(!open_entry_since_.is_null());
2183 DCHECK(!started_reading_since_.is_null());
2184
2185 const TimeDelta before_reading_time =
rvargas (doing something else) 2012/07/21 02:24:21 I also think we should drop the const on these var
gavinp 2012/07/25 01:07:01 Done.
2186 started_reading_since_ - open_entry_since_;
2187 const TimeDelta reading_time = TimeTicks::Now() - started_reading_since_;
2188 const TimeDelta total_time = before_reading_time + reading_time;
2189
2190 UMA_HISTOGRAM_TIMES("HttpCache.TimeBlocked", before_reading_time);
rvargas (doing something else) 2012/07/21 02:24:21 This puts together all cache types under the same
2191 UMA_HISTOGRAM_TIMES("HttpCache.TimeReading", reading_time);
2192
2193 const bool is_small_resource = resource_size < kSmallResourceMaxBytes;
rvargas (doing something else) 2012/07/21 02:24:21 This is not what the caller is passing... I mean,
gavinp 2012/07/25 01:07:01 Good point. It's also undefined since I don't real
2194 if (is_small_resource) {
2195 UMA_HISTOGRAM_TIMES(
2196 "HttpCache.TimeBlocked.SmallResource", before_reading_time);
rvargas (doing something else) 2012/07/21 02:24:21 nit: TimeBlocked?
2197 UMA_HISTOGRAM_TIMES("HttpCache.TimeReading.SmallResource", reading_time);
2198 }
2199
2200 // The more detailed histograms are only interesting for requests that are not
rvargas (doing something else) 2012/07/21 02:24:21 why?
gavinp 2012/07/25 01:07:01 Good point I had no reason whatsoever to actually
2201 // fast.
2202 if (total_time.InMilliseconds() < kFastRequestCutoffMs)
2203 return;
2204
2205 const int before_reading_percent = before_reading_time * 100 / total_time;
2206 DCHECK_LE(0, before_reading_percent);
2207 DCHECK_GE(100, before_reading_percent);
2208
2209 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBlocked", before_reading_percent);
rvargas (doing something else) 2012/07/21 02:24:21 nit: Not really blocked
gavinp 2012/07/25 01:07:01 Now named how long before send. The request isn't
2210 if (is_small_resource)
2211 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBlocked.SmallResource",
2212 before_reading_percent);
2213
2214 // TODO(gavinp): Remove or minimize these histograms, particularly the ones
2215 // below this comment after we have received initial data.
2216 switch (disposition_) {
rvargas (doing something else) 2012/07/21 02:24:21 nit: I'm not really happy with the term "dispositi
gavinp 2012/07/25 01:07:01 Now that you point it out, I hate the name too. T
2217 case DISPOSITION_NO_ENTRY: {
2218 UMA_HISTOGRAM_TIMES(
2219 "HttpCache.TimeBlocked.NotCached", before_reading_time);
2220 UMA_HISTOGRAM_PERCENTAGE(
2221 "HttpCache.PercentBlocked.NotCached", before_reading_percent);
rvargas (doing something else) 2012/07/21 02:24:21 Id suggest just dropping the absolute times.
gavinp 2012/07/25 01:07:01 You might be right. I'd like to wait for results.
2222 if (is_small_resource) {
2223 UMA_HISTOGRAM_PERCENTAGE(
2224 "HttpCache.PercentBlocked.NotCached.SmallResource",
2225 before_reading_percent);
2226 }
2227 break;
2228 }
2229 case DISPOSITION_ENTRY_UNCONDITIONALLY_USED: {
2230 UMA_HISTOGRAM_TIMES(
2231 "HttpCache.TimeBlocked.Used", before_reading_time);
2232 UMA_HISTOGRAM_PERCENTAGE(
2233 "HttpCache.PercentBlocked.Used", before_reading_percent);
2234 if (is_small_resource) {
2235 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBlocked.Used.SmallResource",
2236 before_reading_percent);
2237 }
2238 break;
2239 }
2240 case DISPOSITION_ENTRY_VALIDATED_304: {
2241 UMA_HISTOGRAM_TIMES(
2242 "HttpCache.TimeBlocked.Validated", before_reading_time);
2243 UMA_HISTOGRAM_PERCENTAGE(
2244 "HttpCache.PercentBlocked.Validated", before_reading_percent);
2245 if (is_small_resource) {
2246 UMA_HISTOGRAM_PERCENTAGE(
2247 "HttpCache.PercentBlocked.Validated.SmallResource",
2248 before_reading_percent);
2249 }
2250 break;
2251 }
2252 case DISPOSITION_ENTRY_VALIDATED_200: {
2253 UMA_HISTOGRAM_TIMES(
2254 "HttpCache.TimeBlocked.Updated", before_reading_time);
2255 UMA_HISTOGRAM_PERCENTAGE(
2256 "HttpCache.PercentBlocked.Updated", before_reading_percent);
2257 if (is_small_resource) {
2258 UMA_HISTOGRAM_PERCENTAGE(
2259 "HttpCache.PercentBlocked.Updated.SmallResource",
2260 before_reading_percent);
2261 }
2262 break;
2263 }
2264 case DISPOSITION_UNDEFINED:
2265 default:
2266 NOTREACHED();
2267 }
2268 }
2269
2115 } // namespace net 2270 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_cache_transaction.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698