| 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
|
|
|