Index: net/http/disk_cache_based_quic_server_info.cc |
diff --git a/net/http/disk_cache_based_quic_server_info.cc b/net/http/disk_cache_based_quic_server_info.cc |
index 2e116daa027baa79ab9150ce91456b11d25ed87f..148df3f68b2a249c1a7b4e3a6994b40a74c8f6cd 100644 |
--- a/net/http/disk_cache_based_quic_server_info.cc |
+++ b/net/http/disk_cache_based_quic_server_info.cc |
@@ -6,6 +6,7 @@ |
#include "base/bind.h" |
#include "base/callback.h" |
+#include "base/callback_helpers.h" |
#include "base/logging.h" |
#include "base/metrics/histogram.h" |
#include "net/base/completion_callback.h" |
@@ -17,44 +18,6 @@ |
namespace net { |
-// Histogram that tracks number of times data read/parse/write API calls of |
-// QuicServerInfo to and from disk cache is called. |
-enum QuicServerInfoAPICall { |
- QUIC_SERVER_INFO_START = 0, |
- QUIC_SERVER_INFO_WAIT_FOR_DATA_READY = 1, |
- QUIC_SERVER_INFO_PARSE = 2, |
- QUIC_SERVER_INFO_WAIT_FOR_DATA_READY_CANCEL = 3, |
- QUIC_SERVER_INFO_READY_TO_PERSIST = 4, |
- QUIC_SERVER_INFO_PERSIST = 5, |
- QUIC_SERVER_INFO_NUM_OF_API_CALLS = 6, |
-}; |
- |
-// Histogram that tracks failure reasons to read/load/write of QuicServerInfo to |
-// and from disk cache. |
-enum FailureReason { |
- WAIT_FOR_DATA_READY_INVALID_ARGUMENT_FAILURE = 0, |
- GET_BACKEND_FAILURE = 1, |
- OPEN_FAILURE = 2, |
- CREATE_OR_OPEN_FAILURE = 3, |
- PARSE_NO_DATA_FAILURE = 4, |
- PARSE_FAILURE = 5, |
- READ_FAILURE = 6, |
- READY_TO_PERSIST_FAILURE = 7, |
- PERSIST_NO_BACKEND_FAILURE = 8, |
- WRITE_FAILURE = 9, |
- NUM_OF_FAILURES = 10, |
-}; |
- |
-void RecordQuicServerInfoStatus(QuicServerInfoAPICall call) { |
- UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.APICall", call, |
- QUIC_SERVER_INFO_NUM_OF_API_CALLS); |
-} |
- |
-void RecordQuicServerInfoFailure(FailureReason failure) { |
- UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.FailureReason", failure, |
- NUM_OF_FAILURES); |
-} |
- |
// Some APIs inside disk_cache take a handle that the caller must keep alive |
// until the API has finished its asynchronous execution. |
// |
@@ -94,6 +57,7 @@ DiskCacheBasedQuicServerInfo::DiskCacheBasedQuicServerInfo( |
http_cache_(http_cache), |
backend_(NULL), |
entry_(NULL), |
+ last_failure_(NO_FAILURE), |
weak_factory_(this) { |
io_callback_ = |
base::Bind(&DiskCacheBasedQuicServerInfo::OnIOComplete, |
@@ -104,6 +68,7 @@ DiskCacheBasedQuicServerInfo::DiskCacheBasedQuicServerInfo( |
void DiskCacheBasedQuicServerInfo::Start() { |
DCHECK(CalledOnValidThread()); |
DCHECK_EQ(GET_BACKEND, state_); |
+ DCHECK_EQ(last_failure_, NO_FAILURE); |
RecordQuicServerInfoStatus(QUIC_SERVER_INFO_START); |
load_start_time_ = base::TimeTicks::Now(); |
DoLoop(OK); |
@@ -115,17 +80,19 @@ int DiskCacheBasedQuicServerInfo::WaitForDataReady( |
DCHECK_NE(GET_BACKEND, state_); |
RecordQuicServerInfoStatus(QUIC_SERVER_INFO_WAIT_FOR_DATA_READY); |
- if (ready_) |
+ if (ready_) { |
+ RecordLastFailure(); |
return OK; |
+ } |
if (!callback.is_null()) { |
// Prevent a new callback for WaitForDataReady overwriting an existing |
- // pending callback (|user_callback_|). |
- if (!user_callback_.is_null()) { |
+ // pending callback (|wait_for_ready_callback_|). |
+ if (!wait_for_ready_callback_.is_null()) { |
RecordQuicServerInfoFailure(WAIT_FOR_DATA_READY_INVALID_ARGUMENT_FAILURE); |
return ERR_INVALID_ARGUMENT; |
} |
- user_callback_ = callback; |
+ wait_for_ready_callback_ = callback; |
} |
return ERR_IO_PENDING; |
@@ -135,8 +102,10 @@ void DiskCacheBasedQuicServerInfo::CancelWaitForDataReadyCallback() { |
DCHECK(CalledOnValidThread()); |
RecordQuicServerInfoStatus(QUIC_SERVER_INFO_WAIT_FOR_DATA_READY_CANCEL); |
- if (!user_callback_.is_null()) |
- user_callback_.Reset(); |
+ if (!wait_for_ready_callback_.is_null()) { |
+ RecordLastFailure(); |
+ wait_for_ready_callback_.Reset(); |
+ } |
} |
bool DiskCacheBasedQuicServerInfo::IsDataReady() { |
@@ -144,10 +113,6 @@ bool DiskCacheBasedQuicServerInfo::IsDataReady() { |
} |
bool DiskCacheBasedQuicServerInfo::IsReadyToPersist() { |
- // TODO(rtenneti): Handle updates while a write is pending. Change |
- // Persist() to save the data to be written into a temporary buffer |
- // and then persist that data when we are ready to persist. |
- // |
// The data can be persisted if it has been loaded from the disk cache |
// and there are no pending writes. |
RecordQuicServerInfoStatus(QUIC_SERVER_INFO_READY_TO_PERSIST); |
@@ -159,12 +124,29 @@ bool DiskCacheBasedQuicServerInfo::IsReadyToPersist() { |
void DiskCacheBasedQuicServerInfo::Persist() { |
DCHECK(CalledOnValidThread()); |
- DCHECK_NE(GET_BACKEND, state_); |
+ if (!IsReadyToPersist()) { |
+ // Handle updates while a write is pending or if we haven't loaded from disk |
+ // cache. Save the data to be written into a temporary buffer and then |
+ // persist that data when we are ready to persist. |
+ pending_write_data_ = Serialize(); |
+ return; |
+ } |
+ PersistInternal(); |
+} |
+void DiskCacheBasedQuicServerInfo::PersistInternal() { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK_NE(GET_BACKEND, state_); |
DCHECK(new_data_.empty()); |
CHECK(ready_); |
- DCHECK(user_callback_.is_null()); |
- new_data_ = Serialize(); |
+ DCHECK(wait_for_ready_callback_.is_null()); |
+ |
+ if (pending_write_data_.empty()) { |
+ new_data_ = Serialize(); |
+ } else { |
+ new_data_ = pending_write_data_; |
+ pending_write_data_.clear(); |
+ } |
RecordQuicServerInfoStatus(QUIC_SERVER_INFO_PERSIST); |
if (!backend_) { |
@@ -176,8 +158,21 @@ void DiskCacheBasedQuicServerInfo::Persist() { |
DoLoop(OK); |
} |
+void DiskCacheBasedQuicServerInfo::OnExternalCacheHit() { |
+ DCHECK(CalledOnValidThread()); |
+ DCHECK_NE(GET_BACKEND, state_); |
+ |
+ RecordQuicServerInfoStatus(QUIC_SERVER_INFO_EXTERNAL_CACHE_HIT); |
+ if (!backend_) { |
+ RecordQuicServerInfoFailure(PERSIST_NO_BACKEND_FAILURE); |
+ return; |
+ } |
+ |
+ backend_->OnExternalCacheHit(key()); |
+} |
+ |
DiskCacheBasedQuicServerInfo::~DiskCacheBasedQuicServerInfo() { |
- DCHECK(user_callback_.is_null()); |
+ DCHECK(wait_for_ready_callback_.is_null()); |
if (entry_) |
entry_->Close(); |
} |
@@ -190,10 +185,15 @@ void DiskCacheBasedQuicServerInfo::OnIOComplete(CacheOperationDataShim* unused, |
int rv) { |
DCHECK_NE(NONE, state_); |
rv = DoLoop(rv); |
- if (rv != ERR_IO_PENDING && !user_callback_.is_null()) { |
- CompletionCallback callback = user_callback_; |
- user_callback_.Reset(); |
- callback.Run(rv); |
+ if (rv == ERR_IO_PENDING) |
+ return; |
+ if (!wait_for_ready_callback_.is_null()) { |
+ RecordLastFailure(); |
+ base::ResetAndReturn(&wait_for_ready_callback_).Run(rv); |
+ } |
+ if (ready_ && !pending_write_data_.empty()) { |
+ DCHECK_EQ(NONE, state_); |
+ PersistInternal(); |
} |
} |
@@ -381,4 +381,43 @@ int DiskCacheBasedQuicServerInfo::DoSetDone() { |
return OK; |
} |
+void DiskCacheBasedQuicServerInfo::RecordQuicServerInfoStatus( |
+ QuicServerInfoAPICall call) { |
+ if (!backend_) { |
+ UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.APICall.NoBackend", call, |
+ QUIC_SERVER_INFO_NUM_OF_API_CALLS); |
+ } else if (backend_->GetCacheType() == net::MEMORY_CACHE) { |
+ UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.APICall.MemoryCache", call, |
+ QUIC_SERVER_INFO_NUM_OF_API_CALLS); |
+ } else { |
+ UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.APICall.DiskCache", call, |
+ QUIC_SERVER_INFO_NUM_OF_API_CALLS); |
+ } |
+} |
+ |
+void DiskCacheBasedQuicServerInfo::RecordLastFailure() { |
+ if (last_failure_ != NO_FAILURE) { |
+ UMA_HISTOGRAM_ENUMERATION( |
+ "Net.QuicDiskCache.FailureReason.WaitForDataReady", |
+ last_failure_, NUM_OF_FAILURES); |
+ } |
+ last_failure_ = NO_FAILURE; |
+} |
+ |
+void DiskCacheBasedQuicServerInfo::RecordQuicServerInfoFailure( |
+ FailureReason failure) { |
+ last_failure_ = failure; |
+ |
+ if (!backend_) { |
+ UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.FailureReason.NoBackend", |
+ failure, NUM_OF_FAILURES); |
+ } else if (backend_->GetCacheType() == net::MEMORY_CACHE) { |
+ UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.FailureReason.MemoryCache", |
+ failure, NUM_OF_FAILURES); |
+ } else { |
+ UMA_HISTOGRAM_ENUMERATION("Net.QuicDiskCache.FailureReason.DiskCache", |
+ failure, NUM_OF_FAILURES); |
+ } |
+} |
+ |
} // namespace net |