Chromium Code Reviews| Index: net/disk_cache/very_simple/very_simple_entry_impl.cc |
| diff --git a/net/disk_cache/very_simple/very_simple_entry_impl.cc b/net/disk_cache/very_simple/very_simple_entry_impl.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..d85cc4b87493c7a28bd83ef6fe73fb7f2939cd2c |
| --- /dev/null |
| +++ b/net/disk_cache/very_simple/very_simple_entry_impl.cc |
| @@ -0,0 +1,312 @@ |
| +// 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/very_simple/very_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/net_errors.h" |
| +#include "net/disk_cache/very_simple/very_simple_synchronous_entry.h" |
| + |
| +namespace disk_cache { |
| + |
| +using base::Bind; |
| +using base::Callback; |
| +using base::FilePath; |
| +using base::MessageLoopProxy; |
| +using base::Owned; |
| +using base::Time; |
| +using base::Unretained; |
| +using base::WorkerPool; |
| + |
| +namespace { |
|
rvargas (doing something else)
2013/02/06 03:28:40
nit: can this be out of disk_cache?
gavinp
2013/02/08 23:17:51
Done.
|
| + |
| +typedef Entry::CompletionCallback CompletionCallback; |
| +typedef VerySimpleSynchronousEntry::SynchronousEntryCallback |
| + SynchronousEntryCallback; |
| +typedef Callback<VerySimpleEntryImpl*(VerySimpleSynchronousEntry*)> |
| + EntryFactoryCallback; |
| +typedef Callback<void(VerySimpleSynchronousEntry*)> SetSyncCallback; |
| + |
| +// PendingCreationOperation represents a pending operation that is creating a |
| +// new VerySimpleSynchronousEntry, such as OpenEntry() or CreateEntry(). After |
| +// the new synchronous entry has been created, it uses its factory to create |
| +// a VerySimpleEntryImpl and pass it back to the original caller. |
| +class PendingCreationOperation { |
| + public: |
| + static SynchronousEntryCallback Create( |
| + const EntryFactoryCallback& entry_factory_callback, |
| + const CompletionCallback& completion_callback, |
| + Entry** out_entry) { |
| + PendingCreationOperation* operation = |
|
rvargas (doing something else)
2013/02/06 03:28:40
Could you separate the implementation from the dec
gavinp
2013/02/08 23:17:51
Done.
|
| + new PendingCreationOperation(entry_factory_callback, |
| + completion_callback, |
| + out_entry); |
| + DCHECK(operation); |
| + return Bind(&PendingCreationOperation::OnIOComplete, |
| + Owned(operation)); |
| + } |
| + |
| + private: |
| + PendingCreationOperation(const EntryFactoryCallback& entry_factory_callback, |
| + const CompletionCallback& completion_callback, |
| + Entry** out_entry) |
| + : entry_factory_callback_(entry_factory_callback), |
| + completion_callback_(completion_callback), |
| + out_entry_(out_entry) { |
| + } |
| + |
| + void OnIOComplete(VerySimpleSynchronousEntry* sync_entry, int result) { |
| + DCHECK_NE(net::ERR_IO_PENDING, result); |
| + |
| + if (result != net::OK) { |
| + DCHECK_EQ(static_cast<VerySimpleSynchronousEntry*>(NULL), sync_entry); |
|
rvargas (doing something else)
2013/02/06 03:28:40
nit: DCHECK(!sync_entry)
gavinp
2013/02/08 23:17:51
Done. I had to add some printing cruft, since othe
|
| + completion_callback_.Run(result); |
| + return; |
| + } |
| + DCHECK(sync_entry); |
| + *out_entry_ = entry_factory_callback_.Run(sync_entry); |
|
rvargas (doing something else)
2013/02/06 03:28:40
I'm not so happy with this pattern of run a task a
gavinp
2013/02/08 23:17:51
I'm sorry to hear you're unhappy with this pattern
|
| + DCHECK(*out_entry_); |
| + completion_callback_.Run(net::OK); |
| + } |
| + |
| + EntryFactoryCallback entry_factory_callback_; |
| + CompletionCallback completion_callback_; |
| + Entry** out_entry_; |
| +}; |
| + |
| +class PendingOperation { |
|
rvargas (doing something else)
2013/02/06 03:28:40
nit: class description
gavinp
2013/02/08 23:17:51
Done.
|
| + public: |
| + static SynchronousEntryCallback Create( |
| + const SetSyncCallback& set_sync_callback, |
| + const CompletionCallback& completion_callback) { |
| + PendingOperation* operation = new PendingOperation(set_sync_callback, |
|
rvargas (doing something else)
2013/02/06 03:28:40
ditto (implementation vs declaration)
gavinp
2013/02/08 23:17:51
Done.
|
| + completion_callback); |
| + DCHECK(operation); |
| + return Bind(&PendingOperation::OnIOComplete, Owned(operation)); |
| + } |
| + |
| + private: |
| + PendingOperation(const SetSyncCallback& set_sync_callback, |
| + const CompletionCallback& completion_callback) |
| + : set_sync_callback_(set_sync_callback), |
| + completion_callback_(completion_callback) { |
| + } |
| + |
| + void OnIOComplete(VerySimpleSynchronousEntry* sync_entry, int result) { |
| + set_sync_callback_.Run(sync_entry); |
|
rvargas (doing something else)
2013/02/06 03:28:40
ditto
|
| + completion_callback_.Run(result); |
| + } |
| + |
| + SetSyncCallback set_sync_callback_; |
| + CompletionCallback completion_callback_; |
| +}; |
| + |
| +} // namespace |
| + |
| +// static |
| +int VerySimpleEntryImpl::OpenEntry(const FilePath& path, |
| + const std::string& key, |
| + Entry** entry, |
| + const CompletionCallback& callback) { |
| + SynchronousEntryCallback sync_entry_callback = |
| + PendingCreationOperation::Create( |
| + Bind(&VerySimpleEntryImpl::Create), callback, entry); |
| + WorkerPool::PostTask(FROM_HERE, |
|
rvargas (doing something else)
2013/02/06 03:28:40
You know that in general we don't like the worker
gavinp
2013/02/08 23:17:51
I don't know this. Can you expand on this?
rvargas (doing something else)
2013/02/13 01:48:46
That is documented on the header of worker pool.
|
| + Bind(&VerySimpleSynchronousEntry::OpenEntry, path, key, |
| + MessageLoopProxy::current(), |
| + sync_entry_callback), |
| + true); |
| + return net::ERR_IO_PENDING; |
| +} |
| + |
| +// static |
| +int VerySimpleEntryImpl::CreateEntry(const FilePath& path, |
| + const std::string& key, |
| + Entry** entry, |
| + const CompletionCallback& callback) { |
| + SynchronousEntryCallback sync_entry_callback = |
| + PendingCreationOperation::Create( |
| + Bind(&VerySimpleEntryImpl::Create), callback, entry); |
| + WorkerPool::PostTask(FROM_HERE, |
| + Bind(&VerySimpleSynchronousEntry::CreateEntry, path, key, |
| + MessageLoopProxy::current(), |
| + sync_entry_callback), |
| + true); |
| + return net::ERR_IO_PENDING; |
| +} |
| + |
| +// static |
| +int VerySimpleEntryImpl::DoomEntry(const FilePath& path, |
| + const std::string& key, |
| + const CompletionCallback& callback) { |
| + WorkerPool::PostTask(FROM_HERE, |
| + Bind(&VerySimpleSynchronousEntry::DoomEntry, path, key, |
| + MessageLoopProxy::current(), callback), |
| + true); |
| + return net::ERR_IO_PENDING; |
| +} |
| + |
| +void VerySimpleEntryImpl::Doom() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + WorkerPool::PostTask(FROM_HERE, |
| + Bind(&VerySimpleSynchronousEntry::DoomAndClose, |
|
rvargas (doing something else)
2013/02/06 03:28:40
DoomAndClose?
gavinp
2013/02/08 23:17:51
DoomAndClose!
rvargas (doing something else)
2013/02/13 01:48:46
I meant it was surprising behavior. As far as I ca
|
| + Unretained(ReleaseSynchronousEntry())), |
| + true); |
| + has_been_doomed_ = true; |
| +} |
| + |
| +void VerySimpleEntryImpl::Close() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + if (!has_been_doomed_) { |
| + WorkerPool::PostTask(FROM_HERE, |
| + Bind(&VerySimpleSynchronousEntry::Close, |
| + Unretained(ReleaseSynchronousEntry())), |
| + true); |
| + } |
| + // Entry::Close() is expected to release this entry. See disk_cache.h for |
| + // details. |
| + delete this; |
| +} |
| + |
| +std::string VerySimpleEntryImpl::GetKey() const { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + return key_; |
| +} |
| + |
| +Time VerySimpleEntryImpl::GetLastUsed() const { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + DCHECK(synchronous_entry_); |
| + return synchronous_entry_->last_used(); |
| +} |
| + |
| +Time VerySimpleEntryImpl::GetLastModified() const { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + DCHECK(synchronous_entry_); |
| + return synchronous_entry_->last_modified(); |
| +} |
| + |
| +int32 VerySimpleEntryImpl::GetDataSize(int index) const { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + DCHECK(synchronous_entry_); |
| + return synchronous_entry_->data_size(index); |
| +} |
| + |
| +int VerySimpleEntryImpl::ReadData(int index, |
| + int offset, |
| + net::IOBuffer* buf, |
| + int buf_len, |
| + const CompletionCallback& callback) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + DCHECK(synchronous_entry_); |
| + SynchronousEntryCallback sync_entry_callback = |
| + PendingOperation::Create(Bind(&VerySimpleEntryImpl::SetSynchronousEntry, |
| + weak_ptr_factory_.GetWeakPtr()), |
| + callback); |
| + WorkerPool::PostTask(FROM_HERE, |
| + Bind(&VerySimpleSynchronousEntry::ReadData, |
| + Unretained(ReleaseSynchronousEntry()), index, |
|
rvargas (doing something else)
2013/02/06 03:28:40
is this intended to enforce exclusive access to si
gavinp
2013/02/08 23:17:51
This is intended to enforce thread safety, and the
|
| + offset, Unretained(buf), buf_len, |
|
rvargas (doing something else)
2013/02/06 03:28:40
cannot be unretained
gavinp
2013/02/08 23:17:51
Tell me more?
rvargas (doing something else)
2013/02/13 01:48:46
that would mean keeping the buffer without grabbin
|
| + sync_entry_callback), |
| + true); |
| + return net::ERR_IO_PENDING; |
| +} |
| + |
| +int VerySimpleEntryImpl::WriteData(int index, |
| + int offset, |
| + net::IOBuffer* buf, |
| + int buf_len, |
| + const CompletionCallback& callback, |
| + bool truncate) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + DCHECK(synchronous_entry_); |
| + SynchronousEntryCallback sync_entry_callback = |
| + PendingOperation::Create(Bind(&VerySimpleEntryImpl::SetSynchronousEntry, |
| + weak_ptr_factory_.GetWeakPtr()), |
| + callback); |
| + WorkerPool::PostTask(FROM_HERE, |
| + Bind(&VerySimpleSynchronousEntry::WriteData, |
| + Unretained(ReleaseSynchronousEntry()), index, |
| + offset, Unretained(buf), buf_len, |
| + sync_entry_callback, truncate), |
| + true); |
| + return net::ERR_IO_PENDING; |
| +} |
| + |
| +int VerySimpleEntryImpl::ReadSparseData(int64 offset, |
| + net::IOBuffer* buf, |
| + int buf_len, |
| + const CompletionCallback& callback) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + return net::ERR_FAILED; |
| +} |
| + |
| +int VerySimpleEntryImpl::WriteSparseData(int64 offset, |
| + net::IOBuffer* buf, |
| + int buf_len, |
| + const CompletionCallback& callback) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + return net::ERR_FAILED; |
| +} |
| + |
| +int VerySimpleEntryImpl::GetAvailableRange(int64 offset, |
| + int len, |
| + int64* start, |
| + const CompletionCallback& callback) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + return net::ERR_FAILED; |
| +} |
| + |
| +bool VerySimpleEntryImpl::CouldBeSparse() const { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + return false; |
| +} |
| + |
| +void VerySimpleEntryImpl::CancelSparseIO() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| +} |
| + |
| +int VerySimpleEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + return net::ERR_FAILED; |
| +} |
| + |
| +VerySimpleEntryImpl::VerySimpleEntryImpl( |
| + VerySimpleSynchronousEntry* synchronous_entry) |
| + : ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), |
| + key_(synchronous_entry->key()), |
|
rvargas (doing something else)
2013/02/06 03:28:40
why duplicate the key?
gavinp
2013/02/08 23:17:51
Thread safe access. In practice, if SimpleSynchron
rvargas (doing something else)
2013/02/13 01:48:46
The code is happy to reach into access times and s
|
| + synchronous_entry_(synchronous_entry), |
| + has_been_doomed_(false) { |
| + DCHECK(synchronous_entry); |
| +} |
| + |
| +VerySimpleEntryImpl::~VerySimpleEntryImpl() { |
| + DCHECK(thread_checker_.CalledOnValidThread()); |
| + DCHECK_EQ(static_cast<VerySimpleSynchronousEntry*>(NULL), synchronous_entry_); |
|
rvargas (doing something else)
2013/02/06 03:28:40
!sync_entry_
gavinp
2013/02/08 23:17:51
Done.
|
| +} |
| + |
| +// static |
| +VerySimpleEntryImpl* VerySimpleEntryImpl::Create( |
| + VerySimpleSynchronousEntry* synchronous_entry) { |
| + return new VerySimpleEntryImpl(synchronous_entry); |
| +} |
| + |
| +VerySimpleSynchronousEntry* VerySimpleEntryImpl::ReleaseSynchronousEntry() { |
| + DCHECK(synchronous_entry_); |
| + VerySimpleSynchronousEntry* retval = synchronous_entry_; |
| + synchronous_entry_ = NULL; |
| + return retval; |
| +} |
| + |
| +void VerySimpleEntryImpl::SetSynchronousEntry( |
| + VerySimpleSynchronousEntry* synchronous_entry) { |
| + DCHECK_EQ(static_cast<VerySimpleSynchronousEntry*>(NULL), synchronous_entry_); |
| + synchronous_entry_ = synchronous_entry; |
| +} |
| + |
| +} // namespace disk_cache |