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

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: remediate to review Created 8 years, 4 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') | net/http/mock_http_cache.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/http/http_cache_transaction.h" 5 #include "net/http/http_cache_transaction.h"
6 6
7 #include "build/build_config.h" 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 21 matching lines...) Expand all
32 #include "net/http/http_request_info.h" 32 #include "net/http/http_request_info.h"
33 #include "net/http/http_response_headers.h" 33 #include "net/http/http_response_headers.h"
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 {
43
44 // The cutoff for tagging small transactions in histograms; this size was chosen
45 // to cover resources likely to be received in a single TCP window. With an
46 // initial CWND of 10, and an MTU of 1500 bytes, with TCP and HTTP framing
47 // overhead this is a size relatively likely to take only one RTT.
48 const int kSmallResourceMaxBytes = 14 * 1024;
49
50 } // namespace
51
42 namespace net { 52 namespace net {
43 53
44 struct HeaderNameAndValue { 54 struct HeaderNameAndValue {
45 const char* name; 55 const char* name;
46 const char* value; 56 const char* value;
47 }; 57 };
48 58
49 // If the request includes one of these request headers, then avoid caching 59 // If the request includes one of these request headers, then avoid caching
50 // to avoid getting confused. 60 // to avoid getting confused.
51 static const HeaderNameAndValue kPassThroughHeaders[] = { 61 static const HeaderNameAndValue kPassThroughHeaders[] = {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 handling_206_(false), 129 handling_206_(false),
120 cache_pending_(false), 130 cache_pending_(false),
121 done_reading_(false), 131 done_reading_(false),
122 read_offset_(0), 132 read_offset_(0),
123 effective_load_flags_(0), 133 effective_load_flags_(0),
124 write_len_(0), 134 write_len_(0),
125 final_upload_progress_(0), 135 final_upload_progress_(0),
126 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), 136 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
127 ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_( 137 ALLOW_THIS_IN_INITIALIZER_LIST(io_callback_(
128 base::Bind(&Transaction::OnIOComplete, 138 base::Bind(&Transaction::OnIOComplete,
129 weak_factory_.GetWeakPtr()))) { 139 weak_factory_.GetWeakPtr()))),
140 transaction_pattern_(PATTERN_UNDEFINED),
141 bytes_read_from_cache_(0),
142 bytes_read_from_network_(0) {
130 COMPILE_ASSERT(HttpCache::Transaction::kNumValidationHeaders == 143 COMPILE_ASSERT(HttpCache::Transaction::kNumValidationHeaders ==
131 arraysize(kValidationHeaders), 144 arraysize(kValidationHeaders),
132 Invalid_number_of_validation_headers); 145 Invalid_number_of_validation_headers);
133 } 146 }
134 147
135 HttpCache::Transaction::~Transaction() { 148 HttpCache::Transaction::~Transaction() {
136 // We may have to issue another IO, but we should never invoke the callback_ 149 // We may have to issue another IO, but we should never invoke the callback_
137 // after this point. 150 // after this point.
138 callback_.Reset(); 151 callback_.Reset();
139 152
(...skipping 571 matching lines...) Expand 10 before | Expand all | Expand 10 after
711 // This is only set if we have something to do with the response. 724 // This is only set if we have something to do with the response.
712 range_requested_ = (partial_.get() != NULL); 725 range_requested_ = (partial_.get() != NULL);
713 726
714 return OK; 727 return OK;
715 } 728 }
716 729
717 int HttpCache::Transaction::DoSendRequest() { 730 int HttpCache::Transaction::DoSendRequest() {
718 DCHECK(mode_ & WRITE || mode_ == NONE); 731 DCHECK(mode_ & WRITE || mode_ == NONE);
719 DCHECK(!network_trans_.get()); 732 DCHECK(!network_trans_.get());
720 733
734 send_request_since_ = TimeTicks::Now();
735
721 // Create a network transaction. 736 // Create a network transaction.
722 int rv = cache_->network_layer_->CreateTransaction(&network_trans_); 737 int rv = cache_->network_layer_->CreateTransaction(&network_trans_);
723 if (rv != OK) 738 if (rv != OK)
724 return rv; 739 return rv;
725 740
726 next_state_ = STATE_SEND_REQUEST_COMPLETE; 741 next_state_ = STATE_SEND_REQUEST_COMPLETE;
727 rv = network_trans_->Start(request_, io_callback_, net_log_); 742 rv = network_trans_->Start(request_, io_callback_, net_log_);
728 return rv; 743 return rv;
729 } 744 }
730 745
731 int HttpCache::Transaction::DoSendRequestComplete(int result) { 746 int HttpCache::Transaction::DoSendRequestComplete(int result) {
732 if (!cache_) 747 if (!cache_)
733 return ERR_UNEXPECTED; 748 return ERR_UNEXPECTED;
734 749
735 if (result == OK) { 750 if (result == OK) {
736 next_state_ = STATE_SUCCESSFUL_SEND_REQUEST; 751 next_state_ = STATE_SUCCESSFUL_SEND_REQUEST;
737 return OK; 752 return OK;
738 } 753 }
739 754
755 // Do not record requests that have network errors or restarts.
756 UpdateTransactionPattern(PATTERN_NOT_COVERED);
740 if (IsCertificateError(result)) { 757 if (IsCertificateError(result)) {
741 const HttpResponseInfo* response = network_trans_->GetResponseInfo(); 758 const HttpResponseInfo* response = network_trans_->GetResponseInfo();
742 // If we get a certificate error, then there is a certificate in ssl_info, 759 // If we get a certificate error, then there is a certificate in ssl_info,
743 // so GetResponseInfo() should never return NULL here. 760 // so GetResponseInfo() should never return NULL here.
744 DCHECK(response); 761 DCHECK(response);
745 response_.ssl_info = response->ssl_info; 762 response_.ssl_info = response->ssl_info;
746 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) { 763 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
747 const HttpResponseInfo* response = network_trans_->GetResponseInfo(); 764 const HttpResponseInfo* response = network_trans_->GetResponseInfo();
748 DCHECK(response); 765 DCHECK(response);
749 response_.cert_request_info = response->cert_request_info; 766 response_.cert_request_info = response->cert_request_info;
(...skipping 10 matching lines...) Expand all
760 auth_response_ = *new_response; 777 auth_response_ = *new_response;
761 return OK; 778 return OK;
762 } 779 }
763 780
764 new_response_ = new_response; 781 new_response_ = new_response;
765 if (!ValidatePartialResponse() && !auth_response_.headers) { 782 if (!ValidatePartialResponse() && !auth_response_.headers) {
766 // Something went wrong with this request and we have to restart it. 783 // 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 784 // If we have an authentication response, we are exposed to weird things
768 // hapenning if the user cancels the authentication before we receive 785 // hapenning if the user cancels the authentication before we receive
769 // the new response. 786 // the new response.
787 UpdateTransactionPattern(PATTERN_NOT_COVERED);
770 response_ = HttpResponseInfo(); 788 response_ = HttpResponseInfo();
771 network_trans_.reset(); 789 network_trans_.reset();
772 new_response_ = NULL; 790 new_response_ = NULL;
773 next_state_ = STATE_SEND_REQUEST; 791 next_state_ = STATE_SEND_REQUEST;
774 return OK; 792 return OK;
775 } 793 }
794 bytes_read_from_network_ += new_response_->headers->raw_headers().size();
776 if (handling_206_ && mode_ == READ_WRITE && !truncated_ && !is_sparse_) { 795 if (handling_206_ && mode_ == READ_WRITE && !truncated_ && !is_sparse_) {
777 // We have stored the full entry, but it changed and the server is 796 // We have stored the full entry, but it changed and the server is
778 // sending a range. We have to delete the old entry. 797 // sending a range. We have to delete the old entry.
779 DoneWritingToEntry(false); 798 DoneWritingToEntry(false);
780 } 799 }
781
782 if (new_response_->headers->response_code() == 416) { 800 if (new_response_->headers->response_code() == 416) {
783 DCHECK_EQ(NONE, mode_); 801 DCHECK_EQ(NONE, mode_);
784 response_ = *new_response_; 802 response_ = *new_response_;
785 return OK; 803 return OK;
786 } 804 }
787 805
806 DCHECK(mode_ != WRITE || transaction_pattern_ == PATTERN_ENTRY_NOT_CACHED ||
807 transaction_pattern_ == PATTERN_NOT_COVERED);
rvargas (doing something else) 2012/07/31 17:43:57 What I really don't like about not handling WRITE
gavinp 2012/07/31 20:16:31 You're right about the state machine. My new uploa
788 if (mode_ == WRITE && 808 if (mode_ == WRITE &&
789 (request_->method == "PUT" || request_->method == "DELETE")) { 809 (request_->method == "PUT" || request_->method == "DELETE")) {
790 if (new_response->headers->response_code() == 200) { 810 if (new_response->headers->response_code() == 200) {
791 int ret = cache_->DoomEntry(cache_key_, NULL); 811 int ret = cache_->DoomEntry(cache_key_, NULL);
792 DCHECK_EQ(OK, ret); 812 DCHECK_EQ(OK, ret);
793 } 813 }
794 mode_ = NONE; 814 mode_ = NONE;
795 } 815 }
796 816
797 // Are we expecting a response to a conditional query? 817 // Are we expecting a response to a conditional query?
798 if (mode_ == READ_WRITE || mode_ == UPDATE) { 818 if (mode_ == READ_WRITE || mode_ == UPDATE) {
799 if (new_response->headers->response_code() == 304 || handling_206_) { 819 if (new_response->headers->response_code() == 304 || handling_206_) {
820 UpdateTransactionPattern(PATTERN_ENTRY_VALIDATED);
800 next_state_ = STATE_UPDATE_CACHED_RESPONSE; 821 next_state_ = STATE_UPDATE_CACHED_RESPONSE;
801 return OK; 822 return OK;
802 } 823 }
824 UpdateTransactionPattern(PATTERN_ENTRY_UPDATED);
803 mode_ = WRITE; 825 mode_ = WRITE;
804 } 826 }
805 827
806 next_state_ = STATE_OVERWRITE_CACHED_RESPONSE; 828 next_state_ = STATE_OVERWRITE_CACHED_RESPONSE;
807 return OK; 829 return OK;
808 } 830 }
809 831
810 int HttpCache::Transaction::DoNetworkRead() { 832 int HttpCache::Transaction::DoNetworkRead() {
811 next_state_ = STATE_NETWORK_READ_COMPLETE; 833 next_state_ = STATE_NETWORK_READ_COMPLETE;
812 return network_trans_->Read(read_buf_, io_buf_len_, io_callback_); 834 return network_trans_->Read(read_buf_, io_buf_len_, io_callback_);
813 } 835 }
814 836
815 int HttpCache::Transaction::DoNetworkReadComplete(int result) { 837 int HttpCache::Transaction::DoNetworkReadComplete(int result) {
816 DCHECK(mode_ & WRITE || mode_ == NONE); 838 DCHECK(mode_ & WRITE || mode_ == NONE);
817 839
818 if (!cache_) 840 if (!cache_)
819 return ERR_UNEXPECTED; 841 return ERR_UNEXPECTED;
820 842
843 if (result > 0)
844 bytes_read_from_network_ += result;
845
821 // If there is an error or we aren't saving the data, we are done; just wait 846 // If there is an error or we aren't saving the data, we are done; just wait
822 // until the destructor runs to see if we can keep the data. 847 // until the destructor runs to see if we can keep the data.
823 if (mode_ == NONE || result < 0) 848 if (mode_ == NONE || result < 0)
824 return result; 849 return result;
825 850
826 next_state_ = STATE_CACHE_WRITE_DATA; 851 next_state_ = STATE_CACHE_WRITE_DATA;
827 return result; 852 return result;
828 } 853 }
829 854
830 int HttpCache::Transaction::DoInitEntry() { 855 int HttpCache::Transaction::DoInitEntry() {
831 DCHECK(!new_entry_); 856 DCHECK(!new_entry_);
832 857
833 if (!cache_) 858 if (!cache_)
834 return ERR_UNEXPECTED; 859 return ERR_UNEXPECTED;
835 860
836 if (mode_ == WRITE) { 861 if (mode_ == WRITE) {
837 next_state_ = STATE_DOOM_ENTRY; 862 next_state_ = STATE_DOOM_ENTRY;
838 return OK; 863 return OK;
839 } 864 }
840 865
841 next_state_ = STATE_OPEN_ENTRY; 866 next_state_ = STATE_OPEN_ENTRY;
842 return OK; 867 return OK;
843 } 868 }
844 869
845 int HttpCache::Transaction::DoOpenEntry() { 870 int HttpCache::Transaction::DoOpenEntry() {
846 DCHECK(!new_entry_); 871 DCHECK(!new_entry_);
847 next_state_ = STATE_OPEN_ENTRY_COMPLETE; 872 next_state_ = STATE_OPEN_ENTRY_COMPLETE;
848 cache_pending_ = true; 873 cache_pending_ = true;
849 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY); 874 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY);
875 open_entry_since_ = TimeTicks::Now();
850 return cache_->OpenEntry(cache_key_, &new_entry_, this); 876 return cache_->OpenEntry(cache_key_, &new_entry_, this);
851 } 877 }
852 878
853 int HttpCache::Transaction::DoOpenEntryComplete(int result) { 879 int HttpCache::Transaction::DoOpenEntryComplete(int result) {
854 // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is 880 // 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 881 // OK, otherwise the cache will end up with an active entry without any
856 // transaction attached. 882 // transaction attached.
857 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY, result); 883 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_OPEN_ENTRY, result);
858 cache_pending_ = false; 884 cache_pending_ = false;
859 if (result == OK) { 885 if (result == OK) {
860 next_state_ = STATE_ADD_TO_ENTRY; 886 next_state_ = STATE_ADD_TO_ENTRY;
861 return OK; 887 return OK;
862 } 888 }
863 889
864 if (result == ERR_CACHE_RACE) { 890 if (result == ERR_CACHE_RACE) {
865 next_state_ = STATE_INIT_ENTRY; 891 next_state_ = STATE_INIT_ENTRY;
866 return OK; 892 return OK;
867 } 893 }
868 894
895 UpdateTransactionPattern(PATTERN_ENTRY_NOT_CACHED);
869 if (request_->method == "PUT" || request_->method == "DELETE") { 896 if (request_->method == "PUT" || request_->method == "DELETE") {
870 DCHECK(mode_ == READ_WRITE || mode_ == WRITE); 897 DCHECK(mode_ == READ_WRITE || mode_ == WRITE);
871 mode_ = NONE; 898 mode_ = NONE;
872 next_state_ = STATE_SEND_REQUEST; 899 next_state_ = STATE_SEND_REQUEST;
873 return OK; 900 return OK;
874 } 901 }
875 902
876 if (mode_ == READ_WRITE) { 903 if (mode_ == READ_WRITE) {
877 mode_ = WRITE; 904 mode_ = WRITE;
878 next_state_ = STATE_CREATE_ENTRY; 905 next_state_ = STATE_CREATE_ENTRY;
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
924 if (partial_.get()) 951 if (partial_.get())
925 partial_->RestoreHeaders(&custom_request_->extra_headers); 952 partial_->RestoreHeaders(&custom_request_->extra_headers);
926 next_state_ = STATE_SEND_REQUEST; 953 next_state_ = STATE_SEND_REQUEST;
927 } 954 }
928 return OK; 955 return OK;
929 } 956 }
930 957
931 int HttpCache::Transaction::DoDoomEntry() { 958 int HttpCache::Transaction::DoDoomEntry() {
932 next_state_ = STATE_DOOM_ENTRY_COMPLETE; 959 next_state_ = STATE_DOOM_ENTRY_COMPLETE;
933 cache_pending_ = true; 960 cache_pending_ = true;
961 doom_entry_since_ = TimeTicks::Now();
934 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY); 962 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY);
935 return cache_->DoomEntry(cache_key_, this); 963 return cache_->DoomEntry(cache_key_, this);
936 } 964 }
937 965
938 int HttpCache::Transaction::DoDoomEntryComplete(int result) { 966 int HttpCache::Transaction::DoDoomEntryComplete(int result) {
939 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY, result); 967 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_DOOM_ENTRY, result);
940 next_state_ = STATE_CREATE_ENTRY; 968 next_state_ = STATE_CREATE_ENTRY;
941 cache_pending_ = false; 969 cache_pending_ = false;
942 if (result == ERR_CACHE_RACE) 970 if (result == ERR_CACHE_RACE)
943 next_state_ = STATE_INIT_ENTRY; 971 next_state_ = STATE_INIT_ENTRY;
944 972 else
973 UpdateTransactionPattern(PATTERN_ENTRY_NOT_CACHED);
945 return OK; 974 return OK;
946 } 975 }
947 976
948 int HttpCache::Transaction::DoAddToEntry() { 977 int HttpCache::Transaction::DoAddToEntry() {
949 DCHECK(new_entry_); 978 DCHECK(new_entry_);
950 cache_pending_ = true; 979 cache_pending_ = true;
951 next_state_ = STATE_ADD_TO_ENTRY_COMPLETE; 980 next_state_ = STATE_ADD_TO_ENTRY_COMPLETE;
952 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY); 981 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_ADD_TO_ENTRY);
953 DCHECK(entry_lock_waiting_since_.is_null()); 982 DCHECK(entry_lock_waiting_since_.is_null());
954 entry_lock_waiting_since_ = TimeTicks::Now(); 983 entry_lock_waiting_since_ = TimeTicks::Now();
(...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after
1211 io_buf_len_, io_callback_); 1240 io_buf_len_, io_callback_);
1212 } 1241 }
1213 1242
1214 int HttpCache::Transaction::DoCacheReadResponseComplete(int result) { 1243 int HttpCache::Transaction::DoCacheReadResponseComplete(int result) {
1215 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result); 1244 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result);
1216 if (result != io_buf_len_ || 1245 if (result != io_buf_len_ ||
1217 !HttpCache::ParseResponseInfo(read_buf_->data(), io_buf_len_, 1246 !HttpCache::ParseResponseInfo(read_buf_->data(), io_buf_len_,
1218 &response_, &truncated_)) { 1247 &response_, &truncated_)) {
1219 return OnCacheReadError(result, true); 1248 return OnCacheReadError(result, true);
1220 } 1249 }
1250 bytes_read_from_cache_ += result;
1221 1251
1222 // Some resources may have slipped in as truncated when they're not. 1252 // Some resources may have slipped in as truncated when they're not.
1223 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); 1253 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
1224 if (response_.headers->GetContentLength() == current_size) 1254 if (response_.headers->GetContentLength() == current_size)
1225 truncated_ = false; 1255 truncated_ = false;
1226 1256
1227 // We now have access to the cache entry. 1257 // We now have access to the cache entry.
1228 // 1258 //
1229 // o if we are a reader for the transaction, then we can start reading the 1259 // o if we are a reader for the transaction, then we can start reading the
1230 // cache entry. 1260 // cache entry.
1231 // 1261 //
1232 // o if we can read or write, then we should check if the cache entry needs 1262 // 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 1263 // 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. 1264 // from the cache if the cache entry is already valid.
1235 // 1265 //
1236 // o if we are set to UPDATE, then we are handling an externally 1266 // o if we are set to UPDATE, then we are handling an externally
1237 // conditionalized request (if-modified-since / if-none-match). We check 1267 // conditionalized request (if-modified-since / if-none-match). We check
1238 // if the request headers define a validation request. 1268 // if the request headers define a validation request.
1239 // 1269 //
1240 switch (mode_) { 1270 switch (mode_) {
1241 case READ: 1271 case READ:
1272 UpdateTransactionPattern(PATTERN_ENTRY_USED);
1242 result = BeginCacheRead(); 1273 result = BeginCacheRead();
1243 break; 1274 break;
1244 case READ_WRITE: 1275 case READ_WRITE:
1245 result = BeginPartialCacheValidation(); 1276 result = BeginPartialCacheValidation();
1246 break; 1277 break;
1247 case UPDATE: 1278 case UPDATE:
1248 result = BeginExternallyConditionalizedRequest(); 1279 result = BeginExternallyConditionalizedRequest();
1249 break; 1280 break;
1250 case WRITE: 1281 case WRITE:
1251 default: 1282 default:
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1296 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO); 1327 net_log_.BeginEvent(NetLog::TYPE_HTTP_CACHE_READ_INFO);
1297 return entry_->disk_entry->ReadData(kMetadataIndex, 0, response_.metadata, 1328 return entry_->disk_entry->ReadData(kMetadataIndex, 0, response_.metadata,
1298 response_.metadata->size(), 1329 response_.metadata->size(),
1299 io_callback_); 1330 io_callback_);
1300 } 1331 }
1301 1332
1302 int HttpCache::Transaction::DoCacheReadMetadataComplete(int result) { 1333 int HttpCache::Transaction::DoCacheReadMetadataComplete(int result) {
1303 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result); 1334 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_INFO, result);
1304 if (result != response_.metadata->size()) 1335 if (result != response_.metadata->size())
1305 return OnCacheReadError(result, false); 1336 return OnCacheReadError(result, false);
1306
1307 return OK; 1337 return OK;
1308 } 1338 }
1309 1339
1310 int HttpCache::Transaction::DoCacheQueryData() { 1340 int HttpCache::Transaction::DoCacheQueryData() {
1311 next_state_ = STATE_CACHE_QUERY_DATA_COMPLETE; 1341 next_state_ = STATE_CACHE_QUERY_DATA_COMPLETE;
1312 1342
1313 // Balanced in DoCacheQueryDataComplete. 1343 // Balanced in DoCacheQueryDataComplete.
1314 return entry_->disk_entry->ReadyForSparseIO(io_callback_); 1344 return entry_->disk_entry->ReadyForSparseIO(io_callback_);
1315 } 1345 }
1316 1346
(...skipping 22 matching lines...) Expand all
1339 1369
1340 int HttpCache::Transaction::DoCacheReadDataComplete(int result) { 1370 int HttpCache::Transaction::DoCacheReadDataComplete(int result) {
1341 if (net_log_.IsLoggingAllEvents()) { 1371 if (net_log_.IsLoggingAllEvents()) {
1342 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_DATA, 1372 net_log_.EndEventWithNetErrorCode(NetLog::TYPE_HTTP_CACHE_READ_DATA,
1343 result); 1373 result);
1344 } 1374 }
1345 1375
1346 if (!cache_) 1376 if (!cache_)
1347 return ERR_UNEXPECTED; 1377 return ERR_UNEXPECTED;
1348 1378
1349 if (partial_.get()) 1379 if (partial_.get()) {
1380 // Partial requests are confusing to report in histograms because they may
1381 // have multiple underlying requests.
1382 UpdateTransactionPattern(PATTERN_NOT_COVERED);
1350 return DoPartialCacheReadCompleted(result); 1383 return DoPartialCacheReadCompleted(result);
1384 }
1351 1385
1352 if (result > 0) { 1386 if (result > 0) {
1353 read_offset_ += result; 1387 read_offset_ += result;
1388 bytes_read_from_cache_ += result;
1354 } else if (result == 0) { // End of file. 1389 } else if (result == 0) { // End of file.
1390 RecordHistograms();
1355 cache_->DoneReadingFromEntry(entry_, this); 1391 cache_->DoneReadingFromEntry(entry_, this);
1356 entry_ = NULL; 1392 entry_ = NULL;
1357 } else { 1393 } else {
1358 return OnCacheReadError(result, false); 1394 return OnCacheReadError(result, false);
1359 } 1395 }
1360 return result; 1396 return result;
1361 } 1397 }
1362 1398
1363 int HttpCache::Transaction::DoCacheWriteData(int num_bytes) { 1399 int HttpCache::Transaction::DoCacheWriteData(int num_bytes) {
1364 next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE; 1400 next_state_ = STATE_CACHE_WRITE_DATA_COMPLETE;
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
1492 1528
1493 // If there is more than one validation header, we can't treat this request as 1529 // 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 1530 // 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). 1531 // will give us a response for (and they could be contradictory).
1496 if (external_validation_error) { 1532 if (external_validation_error) {
1497 LOG(WARNING) << "Multiple or malformed validation headers found."; 1533 LOG(WARNING) << "Multiple or malformed validation headers found.";
1498 effective_load_flags_ |= LOAD_DISABLE_CACHE; 1534 effective_load_flags_ |= LOAD_DISABLE_CACHE;
1499 } 1535 }
1500 1536
1501 if (range_found && !(effective_load_flags_ & LOAD_DISABLE_CACHE)) { 1537 if (range_found && !(effective_load_flags_ & LOAD_DISABLE_CACHE)) {
1538 UpdateTransactionPattern(PATTERN_NOT_COVERED);
1502 partial_.reset(new PartialData); 1539 partial_.reset(new PartialData);
1503 if (request_->method == "GET" && partial_->Init(request_->extra_headers)) { 1540 if (request_->method == "GET" && partial_->Init(request_->extra_headers)) {
1504 // We will be modifying the actual range requested to the server, so 1541 // We will be modifying the actual range requested to the server, so
1505 // let's remove the header here. 1542 // let's remove the header here.
1506 custom_request_.reset(new HttpRequestInfo(*request_)); 1543 custom_request_.reset(new HttpRequestInfo(*request_));
1507 custom_request_->extra_headers.RemoveHeader(HttpRequestHeaders::kRange); 1544 custom_request_->extra_headers.RemoveHeader(HttpRequestHeaders::kRange);
1508 request_ = custom_request_.get(); 1545 request_ = custom_request_.get();
1509 partial_->SetHeaders(custom_request_->extra_headers); 1546 partial_->SetHeaders(custom_request_->extra_headers);
1510 } else { 1547 } else {
1511 // The range is invalid or we cannot handle it properly. 1548 // The range is invalid or we cannot handle it properly.
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1563 1600
1564 return OK; 1601 return OK;
1565 } 1602 }
1566 1603
1567 int HttpCache::Transaction::BeginCacheValidation() { 1604 int HttpCache::Transaction::BeginCacheValidation() {
1568 DCHECK(mode_ == READ_WRITE); 1605 DCHECK(mode_ == READ_WRITE);
1569 1606
1570 bool skip_validation = effective_load_flags_ & LOAD_PREFERRING_CACHE || 1607 bool skip_validation = effective_load_flags_ & LOAD_PREFERRING_CACHE ||
1571 !RequiresValidation(); 1608 !RequiresValidation();
1572 1609
1573 if (truncated_) 1610 if (truncated_) {
1611 // Truncated entries can cause partial gets, so we shouldn't record this
1612 // load in histograms.
1613 UpdateTransactionPattern(PATTERN_NOT_COVERED);
1574 skip_validation = !partial_->initial_validation(); 1614 skip_validation = !partial_->initial_validation();
1615 }
1575 1616
1576 if ((partial_.get() && !partial_->IsCurrentRangeCached()) || invalid_range_) 1617 if ((partial_.get() && !partial_->IsCurrentRangeCached()) || invalid_range_)
1577 skip_validation = false; 1618 skip_validation = false;
1578 1619
1579 if (skip_validation) { 1620 if (skip_validation) {
1621 UpdateTransactionPattern(PATTERN_ENTRY_USED);
1580 if (partial_.get()) { 1622 if (partial_.get()) {
1581 // We are going to return the saved response headers to the caller, so 1623 // We are going to return the saved response headers to the caller, so
1582 // we may need to adjust them first. 1624 // we may need to adjust them first.
1583 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED; 1625 next_state_ = STATE_PARTIAL_HEADERS_RECEIVED;
1584 return OK; 1626 return OK;
1585 } 1627 }
1586 cache_->ConvertWriterToReader(entry_); 1628 cache_->ConvertWriterToReader(entry_);
1587 mode_ = READ; 1629 mode_ = READ;
1588 1630
1589 if (entry_->disk_entry->GetDataSize(kMetadataIndex)) 1631 if (entry_->disk_entry->GetDataSize(kMetadataIndex))
1590 next_state_ = STATE_CACHE_READ_METADATA; 1632 next_state_ = STATE_CACHE_READ_METADATA;
1591 } else { 1633 } else {
1592 // Make the network request conditional, to see if we may reuse our cached 1634 // 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. 1635 // 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 1636 // 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. 1637 // either READ or WRITE mode once we hear back from the server.
1596 if (!ConditionalizeRequest()) { 1638 if (!ConditionalizeRequest()) {
1639 UpdateTransactionPattern(PATTERN_NOT_COVERED);
1597 DCHECK(!partial_.get()); 1640 DCHECK(!partial_.get());
1598 DCHECK_NE(206, response_.headers->response_code()); 1641 DCHECK_NE(206, response_.headers->response_code());
1599 mode_ = WRITE; 1642 mode_ = WRITE;
1600 } 1643 }
1601 next_state_ = STATE_SEND_REQUEST; 1644 next_state_ = STATE_SEND_REQUEST;
1602 } 1645 }
1603 return OK; 1646 return OK;
1604 } 1647 }
1605 1648
1606 int HttpCache::Transaction::BeginPartialCacheValidation() { 1649 int HttpCache::Transaction::BeginPartialCacheValidation() {
1607 DCHECK(mode_ == READ_WRITE); 1650 DCHECK(mode_ == READ_WRITE);
1608 1651
1609 if (response_.headers->response_code() != 206 && !partial_.get() && 1652 if (response_.headers->response_code() != 206 && !partial_.get() &&
1610 !truncated_) 1653 !truncated_)
1611 return BeginCacheValidation(); 1654 return BeginCacheValidation();
1612 1655
1656 // Partial requests should not be recorded in histograms.
1657 UpdateTransactionPattern(PATTERN_NOT_COVERED);
1613 if (range_requested_) { 1658 if (range_requested_) {
1614 next_state_ = STATE_CACHE_QUERY_DATA; 1659 next_state_ = STATE_CACHE_QUERY_DATA;
1615 return OK; 1660 return OK;
1616 } 1661 }
1617 // The request is not for a range, but we have stored just ranges. 1662 // The request is not for a range, but we have stored just ranges.
1618 partial_.reset(new PartialData()); 1663 partial_.reset(new PartialData());
1619 partial_->SetHeaders(request_->extra_headers); 1664 partial_->SetHeaders(request_->extra_headers);
1620 if (!custom_request_.get()) { 1665 if (!custom_request_.get()) {
1621 custom_request_.reset(new HttpRequestInfo(*request_)); 1666 custom_request_.reset(new HttpRequestInfo(*request_));
1622 request_ = custom_request_.get(); 1667 request_ = custom_request_.get();
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1663 std::string validator; 1708 std::string validator;
1664 response_.headers->EnumerateHeader( 1709 response_.headers->EnumerateHeader(
1665 NULL, 1710 NULL,
1666 kValidationHeaders[i].related_response_header_name, 1711 kValidationHeaders[i].related_response_header_name,
1667 &validator); 1712 &validator);
1668 1713
1669 if (response_.headers->response_code() != 200 || truncated_ || 1714 if (response_.headers->response_code() != 200 || truncated_ ||
1670 validator.empty() || validator != external_validation_.values[i]) { 1715 validator.empty() || validator != external_validation_.values[i]) {
1671 // The externally conditionalized request is not a validation request 1716 // The externally conditionalized request is not a validation request
1672 // for our existing cache entry. Proceed with caching disabled. 1717 // for our existing cache entry. Proceed with caching disabled.
1718 UpdateTransactionPattern(PATTERN_NOT_COVERED);
1673 DoneWritingToEntry(true); 1719 DoneWritingToEntry(true);
1674 } 1720 }
1675 } 1721 }
1676 1722
1677 next_state_ = STATE_SEND_REQUEST; 1723 next_state_ = STATE_SEND_REQUEST;
1678 return OK; 1724 return OK;
1679 } 1725 }
1680 1726
1681 int HttpCache::Transaction::RestartNetworkRequest() { 1727 int HttpCache::Transaction::RestartNetworkRequest() {
1682 DCHECK(mode_ & WRITE || mode_ == NONE); 1728 DCHECK(mode_ & WRITE || mode_ == NONE);
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
1886 } 1932 }
1887 1933
1888 // 304 is not expected here, but we'll spare the entry (unless it was 1934 // 304 is not expected here, but we'll spare the entry (unless it was
1889 // truncated). 1935 // truncated).
1890 if (truncated_) 1936 if (truncated_)
1891 failure = true; 1937 failure = true;
1892 } 1938 }
1893 1939
1894 if (failure) { 1940 if (failure) {
1895 // We cannot truncate this entry, it has to be deleted. 1941 // We cannot truncate this entry, it has to be deleted.
1942 UpdateTransactionPattern(PATTERN_NOT_COVERED);
1896 DoomPartialEntry(false); 1943 DoomPartialEntry(false);
1897 mode_ = NONE; 1944 mode_ = NONE;
1898 if (!reading_ && !partial_->IsLastRange()) { 1945 if (!reading_ && !partial_->IsLastRange()) {
1899 // We'll attempt to issue another network request, this time without us 1946 // We'll attempt to issue another network request, this time without us
1900 // messing up the headers. 1947 // messing up the headers.
1901 partial_->RestoreHeaders(&custom_request_->extra_headers); 1948 partial_->RestoreHeaders(&custom_request_->extra_headers);
1902 partial_.reset(); 1949 partial_.reset();
1903 truncated_ = false; 1950 truncated_ = false;
1904 return false; 1951 return false;
1905 } 1952 }
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
2008 2055
2009 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex); 2056 int current_size = entry_->disk_entry->GetDataSize(kResponseContentIndex);
2010 return WriteToEntry(kResponseContentIndex, current_size, data, data_len, 2057 return WriteToEntry(kResponseContentIndex, current_size, data, data_len,
2011 callback); 2058 callback);
2012 } 2059 }
2013 2060
2014 void HttpCache::Transaction::DoneWritingToEntry(bool success) { 2061 void HttpCache::Transaction::DoneWritingToEntry(bool success) {
2015 if (!entry_) 2062 if (!entry_)
2016 return; 2063 return;
2017 2064
2018 if (cache_->mode() == RECORD) 2065 RecordHistograms();
2019 DVLOG(1) << "Recorded: " << request_->method << request_->url
2020 << " status: " << response_.headers->response_code();
2021 2066
2022 cache_->DoneWritingToEntry(entry_, success); 2067 cache_->DoneWritingToEntry(entry_, success);
2023 entry_ = NULL; 2068 entry_ = NULL;
2024 mode_ = NONE; // switch to 'pass through' mode 2069 mode_ = NONE; // switch to 'pass through' mode
2025 } 2070 }
2026 2071
2027 int HttpCache::Transaction::OnCacheReadError(int result, bool restart) { 2072 int HttpCache::Transaction::OnCacheReadError(int result, bool restart) {
2028 DLOG(ERROR) << "ReadData failed: " << result; 2073 DLOG(ERROR) << "ReadData failed: " << result;
2029 2074
2030 // Avoid using this entry in the future. 2075 // Avoid using this entry in the future.
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
2105 !response_.headers->HasStrongValidators()) 2150 !response_.headers->HasStrongValidators())
2106 return false; 2151 return false;
2107 2152
2108 return true; 2153 return true;
2109 } 2154 }
2110 2155
2111 void HttpCache::Transaction::OnIOComplete(int result) { 2156 void HttpCache::Transaction::OnIOComplete(int result) {
2112 DoLoop(result); 2157 DoLoop(result);
2113 } 2158 }
2114 2159
2160 void HttpCache::Transaction::UpdateTransactionPattern(
2161 TransactionPattern new_transaction_pattern) {
2162 if (transaction_pattern_ == PATTERN_NOT_COVERED)
2163 return;
2164 DCHECK(transaction_pattern_ == PATTERN_UNDEFINED ||
2165 new_transaction_pattern == PATTERN_NOT_COVERED);
2166 transaction_pattern_ = new_transaction_pattern;
2167 }
2168
2169 void HttpCache::Transaction::RecordHistograms() {
2170 DCHECK_NE(PATTERN_UNDEFINED, transaction_pattern_);
2171 if (!cache_ || !cache_->GetCurrentBackend() ||
2172 cache_->GetCurrentBackend()->GetCacheType() != DISK_CACHE ||
2173 cache_->mode() != NORMAL || request_->method != "GET") {
2174 return;
2175 }
2176 UMA_HISTOGRAM_BOOLEAN("HttpCache.HasPattern",
2177 transaction_pattern_ != PATTERN_NOT_COVERED);
2178 if (transaction_pattern_ == PATTERN_NOT_COVERED)
2179 return;
2180 DCHECK(!range_requested_);
2181 DCHECK(!open_entry_since_.is_null() || !doom_entry_since_.is_null());
2182
2183 TimeTicks start_time = !open_entry_since_.is_null() ? open_entry_since_ :
2184 doom_entry_since_;
2185 TimeDelta total_time = base::TimeTicks::Now() - start_time;
2186
2187 UMA_HISTOGRAM_TIMES("HttpCache.TransactionTime", total_time);
2188
2189 bool did_send_request = !send_request_since_.is_null();
2190 DCHECK(
2191 (did_send_request && (transaction_pattern_ == PATTERN_ENTRY_NOT_CACHED ||
2192 transaction_pattern_ == PATTERN_ENTRY_VALIDATED ||
2193 transaction_pattern_ == PATTERN_ENTRY_UPDATED)) ||
2194 (!did_send_request && transaction_pattern_ == PATTERN_ENTRY_USED));
2195
2196 int resource_size;
2197 if (transaction_pattern_ == PATTERN_ENTRY_NOT_CACHED ||
2198 transaction_pattern_ == PATTERN_ENTRY_UPDATED) {
2199 resource_size = bytes_read_from_network_;
2200 } else {
2201 DCHECK(transaction_pattern_ == PATTERN_ENTRY_VALIDATED ||
2202 transaction_pattern_ == PATTERN_ENTRY_USED);
2203 resource_size = bytes_read_from_cache_;
2204 }
2205
2206 bool is_small_resource = resource_size < kSmallResourceMaxBytes;
2207 if (is_small_resource)
2208 UMA_HISTOGRAM_TIMES("HttpCache.TransactionTime.SmallResource", total_time);
2209
2210 if (!did_send_request) {
2211 DCHECK(transaction_pattern_ == PATTERN_ENTRY_USED);
2212 UMA_HISTOGRAM_TIMES("HttpCache.TransactionTime.Used", total_time);
2213 if (is_small_resource) {
2214 UMA_HISTOGRAM_TIMES(
2215 "HttpCache.TransactionTime.Used.SmallResource", total_time);
2216 }
2217 return;
2218 }
2219
2220 TimeDelta before_send_time = send_request_since_ - start_time;
2221 int before_send_percent = before_send_time * 100 / total_time;
2222 DCHECK_LE(0, before_send_percent);
2223 DCHECK_GE(100, before_send_percent);
2224
2225 UMA_HISTOGRAM_TIMES("HttpCache.TransactionTime.SentRequest", total_time);
2226 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend", before_send_time);
2227 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend", before_send_percent);
2228 if (is_small_resource) {
2229 UMA_HISTOGRAM_TIMES("HttpCache.TransactionTime.SentRequest.SmallResource",
2230 total_time);
2231 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.SmallResource",
2232 before_send_time);
2233 UMA_HISTOGRAM_PERCENTAGE("HttpCache.PercentBeforeSend.SmallResource",
2234 before_send_percent);
2235 }
2236
2237 // TODO(gavinp): Remove or minimize these histograms, particularly the ones
2238 // below this comment after we have received initial data.
2239 switch (transaction_pattern_) {
2240 case PATTERN_ENTRY_NOT_CACHED: {
2241 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.NotCached", before_send_time);
2242 UMA_HISTOGRAM_PERCENTAGE(
2243 "HttpCache.PercentBeforeSend.NotCached", before_send_percent);
2244 if (is_small_resource) {
2245 UMA_HISTOGRAM_TIMES(
2246 "HttpCache.BeforeSend.NotCached.SmallResource", before_send_time);
2247 UMA_HISTOGRAM_PERCENTAGE(
2248 "HttpCache.PercentBeforeSend.NotCached.SmallResource",
2249 before_send_percent);
2250 }
2251 break;
2252 }
2253 case PATTERN_ENTRY_VALIDATED: {
2254 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Validated", before_send_time);
2255 UMA_HISTOGRAM_PERCENTAGE(
2256 "HttpCache.PercentBeforeSend.Validated", before_send_percent);
2257 if (is_small_resource) {
2258 UMA_HISTOGRAM_TIMES(
2259 "HttpCache.BeforeSend.Validated.SmallResource", before_send_time);
2260 UMA_HISTOGRAM_PERCENTAGE(
2261 "HttpCache.PercentBeforeSend.Validated.SmallResource",
2262 before_send_percent);
2263 }
2264 break;
2265 }
2266 case PATTERN_ENTRY_UPDATED: {
2267 UMA_HISTOGRAM_TIMES("HttpCache.BeforeSend.Updated", before_send_time);
2268 UMA_HISTOGRAM_PERCENTAGE(
2269 "HttpCache.PercentBeforeSend.Updated", before_send_percent);
2270 if (is_small_resource) {
2271 UMA_HISTOGRAM_TIMES(
2272 "HttpCache.BeforeSend.Updated.SmallResource", before_send_time);
2273 UMA_HISTOGRAM_PERCENTAGE(
2274 "HttpCache.PercentBeforeSend.Updated.SmallResource",
2275 before_send_percent);
2276 }
2277 break;
2278 }
2279 default:
2280 NOTREACHED();
2281 }
2282 }
2283
2115 } // namespace net 2284 } // namespace net
OLDNEW
« no previous file with comments | « net/http/http_cache_transaction.h ('k') | net/http/mock_http_cache.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698