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 |
deleted file mode 100644 |
index b149fc95ae211e39a78ef9fa35e31add15508f28..0000000000000000000000000000000000000000 |
--- a/net/http/disk_cache_based_quic_server_info.cc |
+++ /dev/null |
@@ -1,450 +0,0 @@ |
-// Copyright 2014 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "net/http/disk_cache_based_quic_server_info.h" |
- |
-#include "base/bind.h" |
-#include "base/callback.h" |
-#include "base/callback_helpers.h" |
-#include "base/logging.h" |
-#include "base/metrics/histogram_macros.h" |
-#include "base/stl_util.h" |
-#include "base/trace_event/memory_usage_estimator.h" |
-#include "net/base/completion_callback.h" |
-#include "net/base/io_buffer.h" |
-#include "net/base/net_errors.h" |
-#include "net/http/http_cache.h" |
-#include "net/http/http_network_session.h" |
-#include "net/quic/core/quic_server_id.h" |
- |
-namespace net { |
- |
-// Some APIs inside disk_cache take a handle that the caller must keep alive |
-// until the API has finished its asynchronous execution. |
-// |
-// Unfortunately, DiskCacheBasedQuicServerInfo may be deleted before the |
-// operation completes causing a use-after-free. |
-// |
-// This data shim struct is meant to provide a location for the disk_cache |
-// APIs to write into even if the originating DiskCacheBasedQuicServerInfo |
-// object has been deleted. The lifetime for instances of this struct |
-// should be bound to the CompletionCallback that is passed to the disk_cache |
-// API. We do this by binding an instance of this struct to an unused |
-// parameter for OnIOComplete() using base::Owned(). |
-// |
-// This is a hack. A better fix is to make it so that the disk_cache APIs |
-// take a Callback to a mutator for setting the output value rather than |
-// writing into a raw handle. Then the caller can just pass in a Callback |
-// bound to WeakPtr for itself. This callback would correctly "no-op" itself |
-// when the DiskCacheBasedQuicServerInfo object is deleted. |
-// |
-// TODO(ajwong): Change disk_cache's API to return results via Callback. |
-struct DiskCacheBasedQuicServerInfo::CacheOperationDataShim { |
- CacheOperationDataShim() : backend(NULL), entry(NULL) {} |
- |
- disk_cache::Backend* backend; |
- disk_cache::Entry* entry; |
-}; |
- |
-DiskCacheBasedQuicServerInfo::DiskCacheBasedQuicServerInfo( |
- const QuicServerId& server_id, |
- HttpCache* http_cache) |
- : QuicServerInfo(server_id), |
- data_shim_(new CacheOperationDataShim()), |
- state_(GET_BACKEND), |
- ready_(false), |
- found_entry_(false), |
- server_id_(server_id), |
- http_cache_(http_cache), |
- backend_(NULL), |
- entry_(NULL), |
- last_failure_(NO_FAILURE), |
- weak_factory_(this) { |
- io_callback_ = |
- base::Bind(&DiskCacheBasedQuicServerInfo::OnIOComplete, |
- weak_factory_.GetWeakPtr(), |
- base::Owned(data_shim_)); // Ownership assigned. |
-} |
- |
-DiskCacheBasedQuicServerInfo::~DiskCacheBasedQuicServerInfo() { |
- DCHECK(wait_for_ready_callback_.is_null()); |
- if (entry_) |
- entry_->Close(); |
-} |
- |
-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); |
-} |
- |
-int DiskCacheBasedQuicServerInfo::WaitForDataReady( |
- const CompletionCallback& callback) { |
- DCHECK(CalledOnValidThread()); |
- DCHECK_NE(GET_BACKEND, state_); |
- wait_for_data_start_time_ = base::TimeTicks::Now(); |
- |
- RecordQuicServerInfoStatus(QUIC_SERVER_INFO_WAIT_FOR_DATA_READY); |
- if (ready_) { |
- wait_for_data_end_time_ = base::TimeTicks::Now(); |
- RecordLastFailure(); |
- return OK; |
- } |
- |
- if (!callback.is_null()) { |
- // Prevent a new callback for WaitForDataReady overwriting an existing |
- // 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; |
- } |
- wait_for_ready_callback_ = callback; |
- } |
- |
- return ERR_IO_PENDING; |
-} |
- |
-void DiskCacheBasedQuicServerInfo::ResetWaitForDataReadyCallback() { |
- DCHECK(CalledOnValidThread()); |
- wait_for_ready_callback_.Reset(); |
-} |
- |
-void DiskCacheBasedQuicServerInfo::CancelWaitForDataReadyCallback() { |
- DCHECK(CalledOnValidThread()); |
- |
- RecordQuicServerInfoStatus(QUIC_SERVER_INFO_WAIT_FOR_DATA_READY_CANCEL); |
- if (!wait_for_ready_callback_.is_null()) { |
- RecordLastFailure(); |
- wait_for_ready_callback_.Reset(); |
- } |
-} |
- |
-bool DiskCacheBasedQuicServerInfo::IsDataReady() { |
- return ready_; |
-} |
- |
-bool DiskCacheBasedQuicServerInfo::IsReadyToPersist() { |
- // 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); |
- if (ready_ && new_data_.empty()) |
- return true; |
- RecordQuicServerInfoFailure(READY_TO_PERSIST_FAILURE); |
- return false; |
-} |
- |
-void DiskCacheBasedQuicServerInfo::Persist() { |
- DCHECK(CalledOnValidThread()); |
- 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(wait_for_ready_callback_.is_null()); |
- |
- if (pending_write_data_.empty()) { |
- new_data_ = Serialize(); |
- } else { |
- new_data_ = pending_write_data_; |
- base::STLClearObject(&pending_write_data_); |
- } |
- |
- RecordQuicServerInfoStatus(QUIC_SERVER_INFO_PERSIST); |
- if (!backend_) { |
- RecordQuicServerInfoFailure(PERSIST_NO_BACKEND_FAILURE); |
- return; |
- } |
- |
- state_ = CREATE_OR_OPEN; |
- 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()); |
-} |
- |
-size_t DiskCacheBasedQuicServerInfo::EstimateMemoryUsage() const { |
- return base::trace_event::EstimateMemoryUsage(new_data_) + |
- base::trace_event::EstimateMemoryUsage(pending_write_data_) + |
- base::trace_event::EstimateMemoryUsage(server_id_) + |
- (read_buffer_ == nullptr ? 0 : read_buffer_->size()) + |
- (write_buffer_ == nullptr ? 0 : write_buffer_->size()) + |
- base::trace_event::EstimateMemoryUsage(data_); |
-} |
- |
-std::string DiskCacheBasedQuicServerInfo::key() const { |
- return "quicserverinfo:" + server_id_.ToString(); |
-} |
- |
-void DiskCacheBasedQuicServerInfo::OnIOComplete(CacheOperationDataShim* unused, |
- int rv) { |
- DCHECK_NE(NONE, state_); |
- rv = DoLoop(rv); |
- if (rv == ERR_IO_PENDING) |
- return; |
- |
- base::WeakPtr<DiskCacheBasedQuicServerInfo> weak_this = |
- weak_factory_.GetWeakPtr(); |
- |
- if (!wait_for_ready_callback_.is_null()) { |
- wait_for_data_end_time_ = base::TimeTicks::Now(); |
- RecordLastFailure(); |
- base::ResetAndReturn(&wait_for_ready_callback_).Run(rv); |
- } |
- // |wait_for_ready_callback_| could delete the object if there is an error. |
- // Check if |weak_this| still exists before accessing it. |
- if (weak_this.get() && ready_ && !pending_write_data_.empty()) { |
- DCHECK_EQ(NONE, state_); |
- PersistInternal(); |
- } |
-} |
- |
-int DiskCacheBasedQuicServerInfo::DoLoop(int rv) { |
- do { |
- switch (state_) { |
- case GET_BACKEND: |
- rv = DoGetBackend(); |
- break; |
- case GET_BACKEND_COMPLETE: |
- rv = DoGetBackendComplete(rv); |
- break; |
- case OPEN: |
- rv = DoOpen(); |
- break; |
- case OPEN_COMPLETE: |
- rv = DoOpenComplete(rv); |
- break; |
- case READ: |
- rv = DoRead(); |
- break; |
- case READ_COMPLETE: |
- rv = DoReadComplete(rv); |
- break; |
- case WAIT_FOR_DATA_READY_DONE: |
- rv = DoWaitForDataReadyDone(); |
- break; |
- case CREATE_OR_OPEN: |
- rv = DoCreateOrOpen(); |
- break; |
- case CREATE_OR_OPEN_COMPLETE: |
- rv = DoCreateOrOpenComplete(rv); |
- break; |
- case WRITE: |
- rv = DoWrite(); |
- break; |
- case WRITE_COMPLETE: |
- rv = DoWriteComplete(rv); |
- break; |
- case SET_DONE: |
- rv = DoSetDone(); |
- break; |
- default: |
- rv = OK; |
- NOTREACHED(); |
- } |
- } while (rv != ERR_IO_PENDING && state_ != NONE); |
- |
- return rv; |
-} |
- |
-int DiskCacheBasedQuicServerInfo::DoGetBackendComplete(int rv) { |
- if (rv == OK) { |
- backend_ = data_shim_->backend; |
- state_ = OPEN; |
- } else { |
- RecordQuicServerInfoFailure(GET_BACKEND_FAILURE); |
- state_ = WAIT_FOR_DATA_READY_DONE; |
- } |
- return OK; |
-} |
- |
-int DiskCacheBasedQuicServerInfo::DoOpenComplete(int rv) { |
- if (rv == OK) { |
- entry_ = data_shim_->entry; |
- state_ = READ; |
- found_entry_ = true; |
- } else { |
- RecordQuicServerInfoFailure(OPEN_FAILURE); |
- state_ = WAIT_FOR_DATA_READY_DONE; |
- } |
- |
- return OK; |
-} |
- |
-int DiskCacheBasedQuicServerInfo::DoReadComplete(int rv) { |
- if (rv > 0) |
- data_.assign(read_buffer_->data(), rv); |
- else if (rv < 0) |
- RecordQuicServerInfoFailure(READ_FAILURE); |
- |
- read_buffer_ = nullptr; |
- state_ = WAIT_FOR_DATA_READY_DONE; |
- return OK; |
-} |
- |
-int DiskCacheBasedQuicServerInfo::DoWriteComplete(int rv) { |
- if (rv < 0) |
- RecordQuicServerInfoFailure(WRITE_FAILURE); |
- write_buffer_ = nullptr; |
- state_ = SET_DONE; |
- return OK; |
-} |
- |
-int DiskCacheBasedQuicServerInfo::DoCreateOrOpenComplete(int rv) { |
- if (rv != OK) { |
- RecordQuicServerInfoFailure(CREATE_OR_OPEN_FAILURE); |
- state_ = SET_DONE; |
- } else { |
- if (!entry_) { |
- entry_ = data_shim_->entry; |
- found_entry_ = true; |
- } |
- DCHECK(entry_); |
- state_ = WRITE; |
- } |
- return OK; |
-} |
- |
-int DiskCacheBasedQuicServerInfo::DoGetBackend() { |
- state_ = GET_BACKEND_COMPLETE; |
- return http_cache_->GetBackend(&data_shim_->backend, io_callback_); |
-} |
- |
-int DiskCacheBasedQuicServerInfo::DoOpen() { |
- state_ = OPEN_COMPLETE; |
- return backend_->OpenEntry(key(), &data_shim_->entry, io_callback_); |
-} |
- |
-int DiskCacheBasedQuicServerInfo::DoRead() { |
- const int32_t size = entry_->GetDataSize(0 /* index */); |
- if (!size) { |
- state_ = WAIT_FOR_DATA_READY_DONE; |
- return OK; |
- } |
- |
- read_buffer_ = new IOBufferWithSize(size); |
- state_ = READ_COMPLETE; |
- return entry_->ReadData( |
- 0 /* index */, 0 /* offset */, read_buffer_.get(), size, io_callback_); |
-} |
- |
-int DiskCacheBasedQuicServerInfo::DoWrite() { |
- write_buffer_ = new IOBufferWithSize(new_data_.size()); |
- memcpy(write_buffer_->data(), new_data_.data(), new_data_.size()); |
- state_ = WRITE_COMPLETE; |
- |
- return entry_->WriteData(0 /* index */, |
- 0 /* offset */, |
- write_buffer_.get(), |
- new_data_.size(), |
- io_callback_, |
- true /* truncate */); |
-} |
- |
-int DiskCacheBasedQuicServerInfo::DoCreateOrOpen() { |
- state_ = CREATE_OR_OPEN_COMPLETE; |
- if (entry_) |
- return OK; |
- |
- if (found_entry_) { |
- return backend_->OpenEntry(key(), &data_shim_->entry, io_callback_); |
- } |
- |
- return backend_->CreateEntry(key(), &data_shim_->entry, io_callback_); |
-} |
- |
-int DiskCacheBasedQuicServerInfo::DoWaitForDataReadyDone() { |
- DCHECK(!ready_); |
- state_ = NONE; |
- ready_ = true; |
- // We close the entry because, if we shutdown before ::Persist is called, |
- // then we might leak a cache reference, which causes a DCHECK on shutdown. |
- if (entry_) |
- entry_->Close(); |
- entry_ = NULL; |
- |
- RecordQuicServerInfoStatus(QUIC_SERVER_INFO_PARSE); |
- if (!Parse(data_)) { |
- if (data_.empty()) |
- RecordQuicServerInfoFailure(PARSE_NO_DATA_FAILURE); |
- else |
- RecordQuicServerInfoFailure(PARSE_FAILURE); |
- } |
- |
- UMA_HISTOGRAM_TIMES("Net.QuicServerInfo.DiskCacheLoadTime", |
- base::TimeTicks::Now() - load_start_time_); |
- return OK; |
-} |
- |
-int DiskCacheBasedQuicServerInfo::DoSetDone() { |
- if (entry_) |
- entry_->Close(); |
- entry_ = NULL; |
- base::STLClearObject(&new_data_); |
- state_ = NONE; |
- 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() == 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() == 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 |