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..0639b942f6e17f8d5db7cdeb2a67f8070a959a70 |
--- /dev/null |
+++ b/net/disk_cache/simple/simple_entry_impl.cc |
@@ -0,0 +1,364 @@ |
+// 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 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 { |
felipeg
2013/02/12 13:25:20
As discussed by chat, we don't really need a class
gavinp
2013/02/12 15:45:57
Great suggestion. I was being too ornate.
|
+ 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_; |
+}; |
+ |
+// A PendingEntryOperation 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::PendingEntryOperation { |
felipeg
2013/02/12 13:25:20
ditto.
gavinp
2013/02/12 15:45:57
ditto!
|
+ public: |
+ static SynchronousEntryCallback Create( |
+ const WeakPtr<SimpleEntryImpl>& entry, |
+ const CompletionCallback& completion_callback); |
+ |
+ private: |
+ PendingEntryOperation(const WeakPtr<SimpleEntryImpl>& entry, |
+ const CompletionCallback& completion_callback); |
+ |
+ void OnIOComplete(SimpleSynchronousEntry* sync_entry, int result); |
+ |
+ WeakPtr<SimpleEntryImpl> entry_; |
+ CompletionCallback completion_callback_; |
+}; |
+ |
+// 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 |
+SynchronousEntryCallback SimpleEntryImpl::PendingEntryOperation::Create( |
+ const WeakPtr<SimpleEntryImpl>& entry, |
+ const CompletionCallback& completion_callback) { |
+ PendingEntryOperation* operation = new PendingEntryOperation(entry, |
+ completion_callback); |
+ DCHECK(operation); |
+ return base::Bind(&PendingEntryOperation::OnIOComplete, |
+ base::Owned(operation)); |
+} |
+ |
+SimpleEntryImpl::PendingEntryOperation::PendingEntryOperation( |
+ const WeakPtr<SimpleEntryImpl>& entry, |
+ const CompletionCallback& completion_callback) |
+ : entry_(entry), |
+ completion_callback_(completion_callback) { |
+} |
+ |
+void SimpleEntryImpl::PendingEntryOperation::OnIOComplete( |
+ SimpleSynchronousEntry* sync_entry, |
+ int result) { |
+ DCHECK(sync_entry); |
+ if (entry_) |
+ entry_->SetSynchronousEntry(sync_entry); |
+ completion_callback_.Run(result); |
+} |
+ |
+// 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()); |
+ if (!synchronous_entry_) { |
+ NOTIMPLEMENTED() << ": Overlapping an asynchronous operation."; |
+ return; |
+ } |
+ WorkerPool::PostTask(FROM_HERE, |
+ base::Bind(&SimpleSynchronousEntry::DoomAndClose, |
+ base::Unretained(ReleaseSynchronousEntry())), |
+ true); |
+ has_been_doomed_ = true; |
+} |
+ |
+void SimpleEntryImpl::Close() { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ if (!synchronous_entry_) { |
+ NOTIMPLEMENTED() << ": Overlapping an asynchronous operation."; |
+ delete this; |
+ return; |
+ } |
+ 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()); |
+ if (!synchronous_entry_) { |
+ NOTIMPLEMENTED() << ": Synchronous operations overlapping an asynchronous " |
+ << "operation."; |
+ NOTREACHED(); |
+ } |
+ return synchronous_entry_->last_used(); |
+} |
+ |
+Time SimpleEntryImpl::GetLastModified() const { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ if (!synchronous_entry_) { |
+ NOTIMPLEMENTED() << ": Synchronous operations overlapping an asynchronous " |
+ << "operation."; |
+ NOTREACHED(); |
+ } |
+ return synchronous_entry_->last_modified(); |
+} |
+ |
+int32 SimpleEntryImpl::GetDataSize(int index) const { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ if (!synchronous_entry_) { |
+ NOTIMPLEMENTED() << ": Synchronous operations overlapping an asynchronous " |
+ << "operation."; |
+ NOTREACHED(); |
+ } |
+ 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. |
+ if (!synchronous_entry_) { |
+ NOTIMPLEMENTED() << ": Overlapping calls to ReadData."; |
+ NOTREACHED(); |
+ } |
+ SynchronousEntryCallback sync_entry_callback = |
+ PendingEntryOperation::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) { |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ if (!synchronous_entry_) { |
+ NOTIMPLEMENTED() << ": Overlapping calls to WriteData."; |
+ NOTREACHED(); |
+ } |
+ SynchronousEntryCallback sync_entry_callback = |
+ PendingEntryOperation::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()); |
+ NOTIMPLEMENTED(); |
+ 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()); |
+ NOTIMPLEMENTED(); |
+ 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()); |
+ NOTIMPLEMENTED(); |
+ 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()); |
+ NOTIMPLEMENTED(); |
+} |
+ |
+int SimpleEntryImpl::ReadyForSparseIO(const CompletionCallback& callback) { |
+ // TODO(gavinp): Determine if the simple backend should support sparse data. |
+ DCHECK(thread_checker_.CalledOnValidThread()); |
+ NOTIMPLEMENTED(); |
+ 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 |