diff options
author | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-08 23:07:39 +0000 |
---|---|---|
committer | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-08 23:07:39 +0000 |
commit | 06e62baf611d6fca8698d50765bca81989155845 (patch) | |
tree | 5516ccda32e56e7dae301b8b30f5fd24a4c8b83c /net/disk_cache/sparse_control.cc | |
parent | 681d3b6b072e17a5de40be8794550f781bf28d87 (diff) | |
download | chromium_src-06e62baf611d6fca8698d50765bca81989155845.zip chromium_src-06e62baf611d6fca8698d50765bca81989155845.tar.gz chromium_src-06e62baf611d6fca8698d50765bca81989155845.tar.bz2 |
Disk cache: Add a method to cancel pending sparse operations.
The sparse IO methods require exclusive use of the cache entry
and they complain when that requirement is violated. When the
user cancels a request and reissues another one to the same entry,
we may be waiting for the previous operation to finish when we
receive a new IO request, so we fail.
This CL add a way for the HTTP cache to cancel IO operations and
get a notification when the disk cache is able to operate on that
entry again.
BUG=23862
TEST=unittests
Review URL: http://codereview.chromium.org/256090
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@28475 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/disk_cache/sparse_control.cc')
-rw-r--r-- | net/disk_cache/sparse_control.cc | 42 |
1 files changed, 41 insertions, 1 deletions
diff --git a/net/disk_cache/sparse_control.cc b/net/disk_cache/sparse_control.cc index 7648f4e..3c1dd8c 100644 --- a/net/disk_cache/sparse_control.cc +++ b/net/disk_cache/sparse_control.cc @@ -192,6 +192,7 @@ int SparseControl::StartIO(SparseOperation op, int64 offset, net::IOBuffer* buf, result_ = 0; pending_ = false; finished_ = false; + abort_ = false; DoChildrenIO(); @@ -226,6 +227,24 @@ int SparseControl::GetAvailableRange(int64 offset, int len, int64* start) { return result < 0 ? result : 0; // Don't mask error codes to the caller. } +void SparseControl::CancelIO() { + if (operation_ == kNoOperation) + return; + abort_ = true; +} + +int SparseControl::ReadyToUse(net::CompletionCallback* completion_callback) { + if (!abort_) + return net::OK; + + // We'll grab another reference to keep this object alive because we just have + // one extra reference due to the pending IO operation itself, but we'll + // release that one before invoking user_callback_. + entry_->AddRef(); // Balanced in DoAbortCallbacks. + abort_callbacks_.push_back(completion_callback); + return net::ERR_IO_PENDING; +} + // Static void SparseControl::DeleteChildren(EntryImpl* entry) { DCHECK(entry->GetEntryFlags() & PARENT_ENTRY); @@ -601,7 +620,7 @@ bool SparseControl::DoChildIO() { // progress. However, this entry can still be closed, and that would not // be a good thing for us, so we increase the refcount until we're // finished doing sparse stuff. - entry_->AddRef(); + entry_->AddRef(); // Balanced in DoUserCallback. } return false; } @@ -681,6 +700,14 @@ void SparseControl::OnChildIOCompleted(int result) { DCHECK_NE(net::ERR_IO_PENDING, result); DoChildIOCompleted(result); + if (abort_) { + // We'll return the current result of the operation, which may be less than + // the bytes to read or write, but the user cancelled the operation. + abort_ = false; + DoUserCallback(); + return DoAbortCallbacks(); + } + // We are running a callback from the message loop. It's time to restart what // we were doing before. DoChildrenIO(); @@ -697,4 +724,17 @@ void SparseControl::DoUserCallback() { c->Run(result_); } +void SparseControl::DoAbortCallbacks() { + for (size_t i = 0; i < abort_callbacks_.size(); i++) { + // Releasing all references to entry_ may result in the destruction of this + // object so we should not be touching it after the last Release(). + net::CompletionCallback* c = abort_callbacks_[i]; + if (i == abort_callbacks_.size() - 1) + abort_callbacks_.clear(); + + entry_->Release(); // Don't touch object after this line. + c->Run(net::OK); + } +} + } // namespace disk_cache |