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 |