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

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

Issue 2922973003: RFC: use some in-memory state in SimpleCache to quickly cache-miss some CantConditionalize cases
Patch Set: - Implement support for oracle bytes in MockHttpCache, so the code actually gets exercised in tests… Created 3 years, 6 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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 62
63 void RecordNoStoreHeaderHistogram(int load_flags, 63 void RecordNoStoreHeaderHistogram(int load_flags,
64 const HttpResponseInfo* response) { 64 const HttpResponseInfo* response) {
65 if (load_flags & LOAD_MAIN_FRAME_DEPRECATED) { 65 if (load_flags & LOAD_MAIN_FRAME_DEPRECATED) {
66 UMA_HISTOGRAM_BOOLEAN( 66 UMA_HISTOGRAM_BOOLEAN(
67 "Net.MainFrameNoStore", 67 "Net.MainFrameNoStore",
68 response->headers->HasHeaderValue("cache-control", "no-store")); 68 response->headers->HasHeaderValue("cache-control", "no-store"));
69 } 69 }
70 } 70 }
71 71
72 disk_cache::Backend::OracleJudgement CheckIfUnusable(uint8_t flags) {
73 // If the entry is marked as an unused prefetch, we have to open it up
74 // to check.
75 if (flags & HttpCache::OBH_UNUSED_SINCE_PREFETCH)
76 return disk_cache::Backend::OracleJudgement::HIT;
77 if ((flags & HttpCache::OBH_ZERO_LIFETIME) &&
78 (flags & HttpCache::OBH_RESPONSE_CANT_CONDITIONALIZE)) {
79 // TODO(morlovich): Just zero-lifetime is sufficient for e.g.
80 // PUT/DELETE, also could potentially encode vary-mismatch case.
81 return disk_cache::Backend::OracleJudgement::MISS_AND_DOOM;
82 }
83
84 // Default
85 return disk_cache::Backend::OracleJudgement::HIT;
86 }
87
72 } // namespace 88 } // namespace
73 89
74 #define CACHE_STATUS_HISTOGRAMS(type) \ 90 #define CACHE_STATUS_HISTOGRAMS(type) \
75 do { \ 91 do { \
76 UMA_HISTOGRAM_ENUMERATION("HttpCache.Pattern" type, cache_entry_status_, \ 92 UMA_HISTOGRAM_ENUMERATION("HttpCache.Pattern" type, cache_entry_status_, \
77 CacheEntryStatus::ENTRY_MAX); \ 93 CacheEntryStatus::ENTRY_MAX); \
78 if (validation_request) { \ 94 if (validation_request) { \
79 UMA_HISTOGRAM_ENUMERATION("HttpCache.ValidationCause" type, \ 95 UMA_HISTOGRAM_ENUMERATION("HttpCache.ValidationCause" type, \
80 validation_cause_, VALIDATION_CAUSE_MAX); \ 96 validation_cause_, VALIDATION_CAUSE_MAX); \
81 } \ 97 } \
(...skipping 902 matching lines...) Expand 10 before | Expand all | Expand 10 after
984 return OK; 1000 return OK;
985 } 1001 }
986 1002
987 int HttpCache::Transaction::DoOpenEntry() { 1003 int HttpCache::Transaction::DoOpenEntry() {
988 TRACE_EVENT0("io", "HttpCacheTransaction::DoOpenEntry"); 1004 TRACE_EVENT0("io", "HttpCacheTransaction::DoOpenEntry");
989 DCHECK(!new_entry_); 1005 DCHECK(!new_entry_);
990 TransitionToState(STATE_OPEN_ENTRY_COMPLETE); 1006 TransitionToState(STATE_OPEN_ENTRY_COMPLETE);
991 cache_pending_ = true; 1007 cache_pending_ = true;
992 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_OPEN_ENTRY); 1008 net_log_.BeginEvent(NetLogEventType::HTTP_CACHE_OPEN_ENTRY);
993 first_cache_access_since_ = TimeTicks::Now(); 1009 first_cache_access_since_ = TimeTicks::Now();
994 return cache_->OpenEntry(cache_key_, &new_entry_, this); 1010 // See if we could potentially quick reject the entry.
1011 if (!(effective_load_flags_ & LOAD_SKIP_CACHE_VALIDATION))
1012 return cache_->OpenEntry(cache_key_, &new_entry_,
1013 base::Bind(&CheckIfUnusable), this);
1014 return cache_->OpenEntry(cache_key_, &new_entry_,
1015 disk_cache::Backend::OracleCallback(), this);
995 } 1016 }
996 1017
997 int HttpCache::Transaction::DoOpenEntryComplete(int result) { 1018 int HttpCache::Transaction::DoOpenEntryComplete(int result) {
998 TRACE_EVENT0("io", "HttpCacheTransaction::DoOpenEntryComplete"); 1019 TRACE_EVENT0("io", "HttpCacheTransaction::DoOpenEntryComplete");
999 // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is 1020 // It is important that we go to STATE_ADD_TO_ENTRY whenever the result is
1000 // OK, otherwise the cache will end up with an active entry without any 1021 // OK, otherwise the cache will end up with an active entry without any
1001 // transaction attached. 1022 // transaction attached.
1002 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_OPEN_ENTRY, 1023 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_OPEN_ENTRY,
1003 result); 1024 result);
1004 cache_pending_ = false; 1025 cache_pending_ = false;
(...skipping 1325 matching lines...) Expand 10 before | Expand all | Expand 10 after
2330 stale_entry_freshness_ = lifetimes.freshness; 2351 stale_entry_freshness_ = lifetimes.freshness;
2331 stale_entry_age_ = response_.headers->GetCurrentAge( 2352 stale_entry_age_ = response_.headers->GetCurrentAge(
2332 response_.request_time, response_.response_time, 2353 response_.request_time, response_.response_time,
2333 cache_->clock_->Now()); 2354 cache_->clock_->Now());
2334 } 2355 }
2335 } 2356 }
2336 2357
2337 return validation_required_by_headers; 2358 return validation_required_by_headers;
2338 } 2359 }
2339 2360
2361 bool HttpCache::Transaction::ResponseConditionalizable(
2362 std::string* etag_value,
2363 std::string* last_modified_value) {
2364 DCHECK(response_.headers.get());
2365
2366 // This only makes sense for cached 200 or 206 responses.
2367 if (response_.headers->response_code() != 200 &&
2368 response_.headers->response_code() != 206) {
2369 return false;
2370 }
2371
2372 // ### this looks scary.
2373 DCHECK(response_.headers->response_code() != 206 ||
2374 response_.headers->HasStrongValidators());
2375
2376 // Just use the first available ETag and/or Last-Modified header value.
2377 // TODO(darin): Or should we use the last?
2378
2379 if (response_.headers->GetHttpVersion() >= HttpVersion(1, 1))
2380 response_.headers->EnumerateHeader(NULL, "etag", etag_value);
2381
2382 response_.headers->EnumerateHeader(NULL, "last-modified",
2383 last_modified_value);
2384
2385 if (etag_value->empty() && last_modified_value->empty())
2386 return false;
2387
2388 return true;
2389 }
2390
2340 bool HttpCache::Transaction::ConditionalizeRequest() { 2391 bool HttpCache::Transaction::ConditionalizeRequest() {
2341 DCHECK(response_.headers.get()); 2392 DCHECK(response_.headers.get());
2342 2393
2343 if (request_->method == "PUT" || request_->method == "DELETE") 2394 if (request_->method == "PUT" || request_->method == "DELETE")
2344 return false; 2395 return false;
2345 2396
2346 // This only makes sense for cached 200 or 206 responses.
2347 if (response_.headers->response_code() != 200 &&
2348 response_.headers->response_code() != 206) {
2349 return false;
2350 }
2351
2352 if (fail_conditionalization_for_test_) 2397 if (fail_conditionalization_for_test_)
2353 return false; 2398 return false;
2354 2399
2355 DCHECK(response_.headers->response_code() != 206 || 2400 std::string etag_value;
2356 response_.headers->HasStrongValidators()); 2401 std::string last_modified_value;
2402 if (!ResponseConditionalizable(&etag_value, &last_modified_value))
2403 return false;
2357 2404
2358 // Just use the first available ETag and/or Last-Modified header value. 2405 if (vary_mismatch_) {
2359 // TODO(darin): Or should we use the last? 2406 // Can't rely on last-modified if vary is different.
2360 2407 last_modified_value.clear();
2361 std::string etag_value; 2408 if (etag_value.empty())
2362 if (response_.headers->GetHttpVersion() >= HttpVersion(1, 1)) 2409 return false;
2363 response_.headers->EnumerateHeader(NULL, "etag", &etag_value);
2364
2365 std::string last_modified_value;
2366 if (!vary_mismatch_) {
2367 response_.headers->EnumerateHeader(NULL, "last-modified",
2368 &last_modified_value);
2369 } 2410 }
2370 2411
2371 if (etag_value.empty() && last_modified_value.empty())
2372 return false;
2373
2374 if (!partial_) { 2412 if (!partial_) {
2375 // Need to customize the request, so this forces us to allocate :( 2413 // Need to customize the request, so this forces us to allocate :(
2376 custom_request_.reset(new HttpRequestInfo(*request_)); 2414 custom_request_.reset(new HttpRequestInfo(*request_));
2377 request_ = custom_request_.get(); 2415 request_ = custom_request_.get();
2378 } 2416 }
2379 DCHECK(custom_request_.get()); 2417 DCHECK(custom_request_.get());
2380 2418
2381 bool use_if_range = 2419 bool use_if_range =
2382 partial_ && !partial_->IsCurrentRangeCached() && !invalid_range_; 2420 partial_ && !partial_->IsCurrentRangeCached() && !invalid_range_;
2383 2421
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
2624 if (truncated) 2662 if (truncated)
2625 DCHECK_EQ(200, response_.headers->response_code()); 2663 DCHECK_EQ(200, response_.headers->response_code());
2626 2664
2627 // When writing headers, we normally only write the non-transient headers. 2665 // When writing headers, we normally only write the non-transient headers.
2628 bool skip_transient_headers = true; 2666 bool skip_transient_headers = true;
2629 scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer()); 2667 scoped_refptr<PickledIOBuffer> data(new PickledIOBuffer());
2630 response_.Persist(data->pickle(), skip_transient_headers, truncated); 2668 response_.Persist(data->pickle(), skip_transient_headers, truncated);
2631 data->Done(); 2669 data->Done();
2632 2670
2633 io_buf_len_ = data->pickle()->size(); 2671 io_buf_len_ = data->pickle()->size();
2672
2673 uint8_t hints = 0;
2674 // ### recomputing this too much?
2675 if (response_.headers->GetFreshnessLifetimes(response_.response_time)
2676 .freshness.is_zero())
2677 hints |= HttpCache::OBH_ZERO_LIFETIME;
2678 std::string etag_ignored, last_modified_ignored;
2679 if (!ResponseConditionalizable(&etag_ignored, &last_modified_ignored))
2680 hints |= HttpCache::OBH_RESPONSE_CANT_CONDITIONALIZE;
2681 if (response_.unused_since_prefetch)
2682 hints |= HttpCache::OBH_UNUSED_SINCE_PREFETCH;
2683 entry_->disk_entry->SetOracleByte(hints);
2684
2634 return entry_->disk_entry->WriteData(kResponseInfoIndex, 0, data.get(), 2685 return entry_->disk_entry->WriteData(kResponseInfoIndex, 0, data.get(),
2635 io_buf_len_, io_callback_, true); 2686 io_buf_len_, io_callback_, true);
2636 } 2687 }
2637 2688
2638 int HttpCache::Transaction::OnWriteResponseInfoToEntryComplete(int result) { 2689 int HttpCache::Transaction::OnWriteResponseInfoToEntryComplete(int result) {
2639 if (!entry_) 2690 if (!entry_)
2640 return OK; 2691 return OK;
2641 if (net_log_.IsCapturing()) { 2692 if (net_log_.IsCapturing()) {
2642 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO, 2693 net_log_.EndEventWithNetErrorCode(NetLogEventType::HTTP_CACHE_WRITE_INFO,
2643 result); 2694 result);
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after
3017 } 3068 }
3018 3069
3019 void HttpCache::Transaction::TransitionToState(State state) { 3070 void HttpCache::Transaction::TransitionToState(State state) {
3020 // Ensure that the state is only set once per Do* state. 3071 // Ensure that the state is only set once per Do* state.
3021 DCHECK(in_do_loop_); 3072 DCHECK(in_do_loop_);
3022 DCHECK_EQ(STATE_UNSET, next_state_) << "Next state is " << state; 3073 DCHECK_EQ(STATE_UNSET, next_state_) << "Next state is " << state;
3023 next_state_ = state; 3074 next_state_ = state;
3024 } 3075 }
3025 3076
3026 } // namespace net 3077 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698