Chromium Code Reviews| Index: net/disk_cache/simple/simple_entry_impl.cc |
| diff --git a/net/disk_cache/simple/simple_entry_impl.cc b/net/disk_cache/simple/simple_entry_impl.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..50222449106c2ae0adafd5d6cd40f9e9b931252c |
| --- /dev/null |
| +++ b/net/disk_cache/simple/simple_entry_impl.cc |
| @@ -0,0 +1,334 @@ |
| +// Copyright (c) 2013 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/disk_cache/simple/simple_entry_impl.h" |
| + |
| +#include "base/bind.h" |
| +#include "base/bind_helpers.h" |
| +#include "base/callback.h" |
| +#include "base/location.h" |
| +#include "base/message_loop_proxy.h" |
| +#include "base/threading/worker_pool.h" |
| +#include "net/base/io_buffer.h" |
| +#include "net/base/net_errors.h" |
| +#include "net/disk_cache/simple/simple_synchronous_entry.h" |
| + |
| + |
| +namespace { |
| + |
| +typedef disk_cache::Entry::CompletionCallback CompletionCallback; |
| +typedef disk_cache::SimpleSynchronousEntry::SynchronousEntryCallback |
| + SynchronousEntryCallback; |
| + |
| +} // namespace |
| + |
| +namespace disk_cache { |
| + |
| +using base::FilePath; |
| +using base::MessageLoopProxy; |
| +using base::Time; |
| +using base::WeakPtr; |
| +using base::WorkerPool; |
| + |
| +// A PendingOperation represents an operation on a SynchronousEntry while it is |
| +// in flight. It informs the owning SimpleEntryImpl of IO completion if |
| +// necessary, as well as calling the IO completion callback. |
| +class SimpleEntryImpl::PendingOperation { |
|
pasko-google - do not use
2013/02/11 13:59:25
maybe a PendingEntryOperation would be a better na
gavinp
2013/02/11 17:55:50
Done.
|
| + public: |
| + static SynchronousEntryCallback Create( |
| + const WeakPtr<SimpleEntryImpl>& entry, |
| + const CompletionCallback& completion_callback); |
| + |
| + private: |
| + PendingOperation(const WeakPtr<SimpleEntryImpl>& entry, |
| + const CompletionCallback& completion_callback); |
| + |
| + void OnIOComplete(SimpleSynchronousEntry* sync_entry, int result); |
| + |
| + WeakPtr<SimpleEntryImpl> entry_; |
| + CompletionCallback completion_callback_; |
| +}; |
| + |
| +// A PendingCreationOperation represents a pending operation that is creating a |
| +// new SimpleSynchronousEntry, such as OpenEntry() or CreateEntry(). It ensures |
| +// that a SimpleEntryImpl is only created after the underlying synchronous |
| +// operation has succeeded. |
| +class SimpleEntryImpl::PendingCreationOperation { |
| + public: |
| + static SynchronousEntryCallback Create( |
| + const CompletionCallback& completion_callback, |
| + Entry** out_entry); |
| + |
| + private: |
| + PendingCreationOperation(const CompletionCallback& completion_callback, |
| + Entry** out_entry); |
| + |
| + void OnIOComplete(SimpleSynchronousEntry* sync_entry, int result); |
| + |
| + CompletionCallback completion_callback_; |
| + Entry** out_entry_; |
| +}; |
| + |
| +// static |
| +SynchronousEntryCallback SimpleEntryImpl::PendingOperation::Create( |
| + const WeakPtr<SimpleEntryImpl>& entry, |
| + const CompletionCallback& completion_callback) { |
| + PendingOperation* operation = new PendingOperation(entry, |
| + completion_callback); |
| + DCHECK(operation); |
| + return base::Bind(&PendingOperation::OnIOComplete, base::Owned(operation)); |
| +} |
| + |
| +SimpleEntryImpl::PendingOperation::PendingOperation( |
| + const WeakPtr<SimpleEntryImpl>& entry, |
| + const CompletionCallback& completion_callback) |
| + : entry_(entry), |
| + completion_callback_(completion_callback) { |
| +} |
| + |
| +void SimpleEntryImpl::PendingOperation::OnIOComplete( |
| + SimpleSynchronousEntry* sync_entry, |
| + int result) { |
| + DCHECK(sync_entry); |
| + if (entry_) |
| + entry_->SetSynchronousEntry(sync_entry); |
| + completion_callback_.Run(result); |
| +} |
| + |
| +// static |
| +SynchronousEntryCallback SimpleEntryImpl::PendingCreationOperation::Create( |
| + const CompletionCallback& completion_callback, |
| + Entry** out_entry) { |
| + PendingCreationOperation* operation = |
| + new PendingCreationOperation(completion_callback, out_entry); |
| + DCHECK(operation); |
| + return base::Bind(&PendingCreationOperation::OnIOComplete, |
| + base::Owned(operation)); |
| +} |
| + |
| +SimpleEntryImpl::PendingCreationOperation::PendingCreationOperation( |
| + const CompletionCallback& completion_callback, |
| + Entry** out_entry) : completion_callback_(completion_callback), |
| + out_entry_(out_entry) { |
| +} |
| + |
| +void SimpleEntryImpl::PendingCreationOperation::OnIOComplete( |
| + SimpleSynchronousEntry* sync_entry, |
| + int result) { |
| + DCHECK_NE(net::ERR_IO_PENDING, result); |
| + |
| + if (result != net::OK) { |
| + DCHECK(!sync_entry) << "sync_entry = " << sync_entry; |
| + completion_callback_.Run(result); |
| + return; |
| + } |
| + DCHECK(sync_entry); |
| + *out_entry_ = new SimpleEntryImpl(sync_entry); |
| + DCHECK(*out_entry_); |
| + completion_callback_.Run(net::OK); |
| +} |
| + |
| +// static |
| +int SimpleEntryImpl::OpenEntry(const FilePath& path, |
| + const std::string& key, |
| + Entry** entry, |
| + const CompletionCallback& callback) { |
| + SynchronousEntryCallback sync_entry_callback = |
| + PendingCreationOperation::Create(callback, entry); |
| + |
| + WorkerPool::PostTask(FROM_HERE, |
| + base::Bind(&SimpleSynchronousEntry::OpenEntry, path, key, |
| + MessageLoopProxy::current(), |
| + sync_entry_callback), |
| + true); |
| + return net::ERR_IO_PENDING; |
| +} |
| + |
| +// static |
| +int SimpleEntryImpl::CreateEntry(const FilePath& path, |
| + const std::string& key, |
| + Entry** entry, |
| + const CompletionCallback& callback) { |
| + SynchronousEntryCallback sync_entry_callback = |
| + PendingCreationOperation::Create(callback, entry); |
| + WorkerPool::PostTask(FROM_HERE, |
| + base::Bind(&SimpleSynchronousEntry::CreateEntry, path, |
| + key, MessageLoopProxy::current(), |
| + sync_entry_callback), |
| + true); |
| + return net::ERR_IO_PENDING; |
| +} |
| + |
| +// static |
| +int SimpleEntryImpl::DoomEntry(const FilePath& path, |
| + const std::string& key, |
| + const CompletionCallback& callback) { |
| + WorkerPool::PostTask(FROM_HERE, |
| + base::Bind(&SimpleSynchronousEntry::DoomEntry, path, key, |
| + MessageLoopProxy::current(), callback), |
| + true); |
| + return net::ERR_IO_PENDING; |
| +} |
| + |
| +void SimpleEntryImpl::Doom() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + WorkerPool::PostTask(FROM_HERE, |
| + base::Bind(&SimpleSynchronousEntry::DoomAndClose, |
| + base::Unretained(ReleaseSynchronousEntry())), |
| + true); |
| + has_been_doomed_ = true; |
| +} |
| + |
| +void SimpleEntryImpl::Close() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + if (!has_been_doomed_) { |
| + WorkerPool::PostTask(FROM_HERE, |
| + base::Bind(&SimpleSynchronousEntry::Close, |
| + base::Unretained( |
| + ReleaseSynchronousEntry())), |
| + true); |
| + } |
| + // Entry::Close() is expected to release this entry. See disk_cache.h for |
| + // details. |
| + delete this; |
| +} |
| + |
| +std::string SimpleEntryImpl::GetKey() const { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + return key_; |
| +} |
| + |
| +Time SimpleEntryImpl::GetLastUsed() const { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + DCHECK(synchronous_entry_); |
| + return synchronous_entry_->last_used(); |
|
pasko-google - do not use
2013/02/11 13:59:25
is there a hidden assumption that last used cannot
gavinp
2013/02/11 17:55:50
Hopefully. The reads will change a bit once checks
|
| +} |
| + |
| +Time SimpleEntryImpl::GetLastModified() const { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + DCHECK(synchronous_entry_); |
| + return synchronous_entry_->last_modified(); |
| +} |
| + |
| +int32 SimpleEntryImpl::GetDataSize(int index) const { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + DCHECK(synchronous_entry_); |
| + return synchronous_entry_->data_size(index); |
| +} |
| + |
| +int SimpleEntryImpl::ReadData(int index, |
| + int offset, |
| + net::IOBuffer* buf, |
| + int buf_len, |
| + const CompletionCallback& callback) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + // TODO(gavinp): Add support for overlapping reads. The net::HttpCache does |
| + // make overlapping read requests when multiple transactions access the same |
| + // entry as read only. |
|
pasko-google - do not use
2013/02/11 13:59:25
does it happen often? on what occasion?
gavinp
2013/02/11 17:55:50
Yes, if for instance a page uses google served jQu
|
| + DCHECK(synchronous_entry_); |
| + SynchronousEntryCallback sync_entry_callback = |
| + PendingOperation::Create(weak_ptr_factory_.GetWeakPtr(), callback); |
| + WorkerPool::PostTask(FROM_HERE, |
| + base::Bind(&SimpleSynchronousEntry::ReadData, |
| + base::Unretained(ReleaseSynchronousEntry()), |
| + index, offset, scoped_refptr<IOBuffer>(buf), |
| + buf_len, sync_entry_callback), |
| + true); |
| + return net::ERR_IO_PENDING; |
| +} |
| + |
| +int SimpleEntryImpl::WriteData(int index, |
| + int offset, |
| + net::IOBuffer* buf, |
| + int buf_len, |
| + const CompletionCallback& callback, |
| + bool truncate) { |
| + for (int i = 0; i < buf_len; ++i) { |
| + char c ALLOW_UNUSED = buf->data()[i]; |
|
pasko-google - do not use
2013/02/11 13:59:25
It is hard to believe that this will be optimized
gavinp
2013/02/11 17:55:50
That is debugging code that made it into this uplo
|
| + } |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + DCHECK(synchronous_entry_); |
| + SynchronousEntryCallback sync_entry_callback = |
| + PendingOperation::Create(weak_ptr_factory_.GetWeakPtr(), callback); |
| + WorkerPool::PostTask(FROM_HERE, |
| + base::Bind(&SimpleSynchronousEntry::WriteData, |
| + base::Unretained(ReleaseSynchronousEntry()), |
| + index, offset, scoped_refptr<IOBuffer>(buf), |
| + buf_len, sync_entry_callback, truncate), |
| + true); |
| + return net::ERR_IO_PENDING; |
| +} |
| + |
| +int SimpleEntryImpl::ReadSparseData(int64 offset, |
| + net::IOBuffer* buf, |
| + int buf_len, |
| + const CompletionCallback& callback) { |
| + // TODO(gavinp): Determine if the simple backend should support sparse data. |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + return net::ERR_FAILED; |
| +} |
| + |
| +int SimpleEntryImpl::WriteSparseData(int64 offset, |
| + net::IOBuffer* buf, |
| + int buf_len, |
| + const CompletionCallback& callback) { |
| + // TODO(gavinp): Determine if the simple backend should support sparse data. |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + return net::ERR_FAILED; |
| +} |
| + |
| +int SimpleEntryImpl::GetAvailableRange(int64 offset, |
| + int len, |
| + int64* start, |
| + const CompletionCallback& callback) { |
| + // TODO(gavinp): Determine if the simple backend should support sparse data. |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + return net::ERR_FAILED; |
| +} |
| + |
| +bool SimpleEntryImpl::CouldBeSparse() const { |
| + // TODO(gavinp): Determine if the simple backend should support sparse data. |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + return false; |
| +} |
| + |
| +void SimpleEntryImpl::CancelSparseIO() { |
| + // TODO(gavinp): Determine if the simple backend should support sparse data. |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| +} |
| + |
| +int SimpleEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) { |
| + // TODO(gavinp): Determine if the simple backend should support sparse data. |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + return net::ERR_FAILED; |
| +} |
| + |
| +SimpleEntryImpl::SimpleEntryImpl( |
| + SimpleSynchronousEntry* synchronous_entry) |
| + : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), |
| + key_(synchronous_entry->key()), |
| + synchronous_entry_(synchronous_entry), |
| + has_been_doomed_(false) { |
| + DCHECK(synchronous_entry); |
| +} |
| + |
| +SimpleEntryImpl::~SimpleEntryImpl() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + DCHECK(!synchronous_entry_) << "synchronous_entry_ = " << synchronous_entry_; |
| +} |
| + |
| +SimpleSynchronousEntry* SimpleEntryImpl::ReleaseSynchronousEntry() { |
| + DCHECK(synchronous_entry_); |
| + SimpleSynchronousEntry* retval = synchronous_entry_; |
| + synchronous_entry_ = NULL; |
| + return retval; |
| +} |
| + |
| +void SimpleEntryImpl::SetSynchronousEntry( |
| + SimpleSynchronousEntry* synchronous_entry) { |
| + DCHECK(!synchronous_entry_) << "synchronous_entry_ = " << synchronous_entry_; |
| + synchronous_entry_ = synchronous_entry; |
| +} |
| + |
| +} // namespace disk_cache |