summaryrefslogtreecommitdiffstats
path: root/net/disk_cache
diff options
context:
space:
mode:
Diffstat (limited to 'net/disk_cache')
-rw-r--r--net/disk_cache/backend_impl.cc18
-rw-r--r--net/disk_cache/backend_impl.h7
-rw-r--r--net/disk_cache/backend_unittest.cc87
-rw-r--r--net/disk_cache/entry_impl.cc84
-rw-r--r--net/disk_cache/entry_impl.h10
-rw-r--r--net/disk_cache/file.h5
-rw-r--r--net/disk_cache/file_posix.cc12
-rw-r--r--net/disk_cache/file_win.cc7
-rw-r--r--net/disk_cache/in_flight_backend_io.cc57
-rw-r--r--net/disk_cache/in_flight_backend_io.h18
-rw-r--r--net/disk_cache/in_flight_io.cc29
-rw-r--r--net/disk_cache/in_flight_io.h17
-rw-r--r--net/disk_cache/sparse_control.cc8
-rw-r--r--net/disk_cache/storage_block-inl.h6
-rw-r--r--net/disk_cache/storage_block.h5
15 files changed, 297 insertions, 73 deletions
diff --git a/net/disk_cache/backend_impl.cc b/net/disk_cache/backend_impl.cc
index 170b03d..7f36741 100644
--- a/net/disk_cache/backend_impl.cc
+++ b/net/disk_cache/backend_impl.cc
@@ -352,7 +352,15 @@ BackendImpl::BackendImpl(const FilePath& path,
}
BackendImpl::~BackendImpl() {
- background_queue_.WaitForPendingIO();
+ if (user_flags_ & kNoRandom) {
+ // This is a unit test, so we want to be strict about not leaking entries
+ // and completing all the work.
+ background_queue_.WaitForPendingIO();
+ } else {
+ // This is most likely not a test, so we want to do as little work as
+ // possible at this time, at the price of leaving dirty entries behind.
+ background_queue_.DropPendingIO();
+ }
if (background_queue_.BackgroundIsCurrentThread()) {
// Unit tests may use the same thread for everything.
@@ -496,10 +504,12 @@ void BackendImpl::CleanupCache() {
if (data_)
data_->header.crash = 0;
- File::WaitForPendingIO(&num_pending_io_);
if (user_flags_ & kNoRandom) {
// This is a net_unittest, verify that we are not 'leaking' entries.
+ File::WaitForPendingIO(&num_pending_io_);
DCHECK(!num_refs_);
+ } else {
+ File::DropPendingIO();
}
}
block_files_.CloseFiles();
@@ -826,6 +836,10 @@ MappedFile* BackendImpl::File(Addr address) {
return block_files_.GetFile(address);
}
+base::WeakPtr<InFlightBackendIO> BackendImpl::GetBackgroundQueue() {
+ return background_queue_.GetWeakPtr();
+}
+
bool BackendImpl::CreateExternalFile(Addr* address) {
int file_number = data_->header.last_file + 1;
Addr file_address(0);
diff --git a/net/disk_cache/backend_impl.h b/net/disk_cache/backend_impl.h
index 53c8893..cc822d5 100644
--- a/net/disk_cache/backend_impl.h
+++ b/net/disk_cache/backend_impl.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -100,9 +100,8 @@ class NET_EXPORT_PRIVATE BackendImpl : public Backend {
// Returns the actual file used to store a given (non-external) address.
MappedFile* File(Addr address);
- InFlightBackendIO* background_queue() {
- return &background_queue_;
- }
+ // Returns a weak pointer to the background queue.
+ base::WeakPtr<InFlightBackendIO> GetBackgroundQueue();
// Creates an external storage file.
bool CreateExternalFile(Addr* address);
diff --git a/net/disk_cache/backend_unittest.cc b/net/disk_cache/backend_unittest.cc
index 4bc5955..ea617fd 100644
--- a/net/disk_cache/backend_unittest.cc
+++ b/net/disk_cache/backend_unittest.cc
@@ -35,6 +35,9 @@ class DiskCacheBackendTest : public DiskCacheTestWithCache {
protected:
void BackendBasics();
void BackendKeying();
+ void BackendShutdownWithPendingFileIO(bool fast);
+ void BackendShutdownWithPendingIO(bool fast);
+ void BackendShutdownWithPendingCreate(bool fast);
void BackendSetSize();
void BackendLoad();
void BackendChain();
@@ -275,7 +278,7 @@ TEST_F(DiskCacheBackendTest, ExternalFiles) {
}
// Tests that we deal with file-level pending operations at destruction time.
-TEST_F(DiskCacheTest, ShutdownWithPendingIO) {
+void DiskCacheBackendTest::BackendShutdownWithPendingFileIO(bool fast) {
net::TestCompletionCallback cb;
{
@@ -285,8 +288,11 @@ TEST_F(DiskCacheTest, ShutdownWithPendingIO) {
base::Thread::Options(MessageLoop::TYPE_IO, 0)));
disk_cache::Backend* cache;
+ uint32 flags = disk_cache::kNoBuffering;
+ if (!fast)
+ flags |= disk_cache::kNoRandom;
int rv = disk_cache::BackendImpl::CreateBackend(
- cache_path_, false, 0, net::DISK_CACHE, disk_cache::kNoRandom,
+ cache_path_, false, 0, net::DISK_CACHE, flags,
base::MessageLoopProxy::current(), NULL,
&cache, cb.callback());
ASSERT_EQ(net::OK, cb.GetResult(rv));
@@ -319,15 +325,30 @@ TEST_F(DiskCacheTest, ShutdownWithPendingIO) {
delete cache;
if (rv == net::ERR_IO_PENDING) {
- EXPECT_TRUE(cb.have_result());
+ if (fast)
+ EXPECT_FALSE(cb.have_result());
+ else
+ EXPECT_TRUE(cb.have_result());
}
}
MessageLoop::current()->RunAllPending();
}
+TEST_F(DiskCacheBackendTest, ShutdownWithPendingFileIO) {
+ BackendShutdownWithPendingFileIO(false);
+}
+
+// We'll be leaking from this test.
+TEST_F(DiskCacheBackendTest, ShutdownWithPendingFileIO_Fast) {
+ // The integrity test sets kNoRandom so there's a version mismatch if we don't
+ // force new eviction.
+ SetNewEviction();
+ BackendShutdownWithPendingFileIO(true);
+}
+
// Tests that we deal with background-thread pending operations.
-TEST_F(DiskCacheTest, ShutdownWithPendingIO2) {
+void DiskCacheBackendTest::BackendShutdownWithPendingIO(bool fast) {
net::TestCompletionCallback cb;
{
@@ -337,8 +358,11 @@ TEST_F(DiskCacheTest, ShutdownWithPendingIO2) {
base::Thread::Options(MessageLoop::TYPE_IO, 0)));
disk_cache::Backend* cache;
+ uint32 flags = disk_cache::kNoBuffering;
+ if (!fast)
+ flags |= disk_cache::kNoRandom;
int rv = disk_cache::BackendImpl::CreateBackend(
- cache_path_, false, 0, net::DISK_CACHE, disk_cache::kNoRandom,
+ cache_path_, false, 0, net::DISK_CACHE, flags,
cache_thread.message_loop_proxy(), NULL, &cache, cb.callback());
ASSERT_EQ(net::OK, cb.GetResult(rv));
@@ -362,6 +386,59 @@ TEST_F(DiskCacheTest, ShutdownWithPendingIO2) {
MessageLoop::current()->RunAllPending();
}
+TEST_F(DiskCacheBackendTest, ShutdownWithPendingIO) {
+ BackendShutdownWithPendingIO(false);
+}
+
+// We'll be leaking from this test.
+TEST_F(DiskCacheBackendTest, ShutdownWithPendingIO_Fast) {
+ // The integrity test sets kNoRandom so there's a version mismatch if we don't
+ // force new eviction.
+ SetNewEviction();
+ BackendShutdownWithPendingIO(true);
+}
+
+// Tests that we deal with create-type pending operations.
+void DiskCacheBackendTest::BackendShutdownWithPendingCreate(bool fast) {
+ net::TestCompletionCallback cb;
+
+ {
+ ASSERT_TRUE(CleanupCacheDir());
+ base::Thread cache_thread("CacheThread");
+ ASSERT_TRUE(cache_thread.StartWithOptions(
+ base::Thread::Options(MessageLoop::TYPE_IO, 0)));
+
+ disk_cache::Backend* cache;
+ disk_cache::BackendFlags flags =
+ fast ? disk_cache::kNone : disk_cache::kNoRandom;
+ int rv = disk_cache::BackendImpl::CreateBackend(
+ cache_path_, false, 0, net::DISK_CACHE, flags,
+ cache_thread.message_loop_proxy(), NULL, &cache, cb.callback());
+ ASSERT_EQ(net::OK, cb.GetResult(rv));
+
+ disk_cache::Entry* entry;
+ rv = cache->CreateEntry("some key", &entry, cb.callback());
+ ASSERT_EQ(net::ERR_IO_PENDING, rv);
+
+ delete cache;
+ EXPECT_FALSE(cb.have_result());
+ }
+
+ MessageLoop::current()->RunAllPending();
+}
+
+TEST_F(DiskCacheBackendTest, ShutdownWithPendingCreate) {
+ BackendShutdownWithPendingCreate(false);
+}
+
+// We'll be leaking an entry from this test.
+TEST_F(DiskCacheBackendTest, ShutdownWithPendingCreate_Fast) {
+ // The integrity test sets kNoRandom so there's a version mismatch if we don't
+ // force new eviction.
+ SetNewEviction();
+ BackendShutdownWithPendingCreate(true);
+}
+
TEST_F(DiskCacheTest, TruncatedIndex) {
ASSERT_TRUE(CleanupCacheDir());
FilePath index = cache_path_.AppendASCII("index");
diff --git a/net/disk_cache/entry_impl.cc b/net/disk_cache/entry_impl.cc
index 1718370..d0e5856 100644
--- a/net/disk_cache/entry_impl.cc
+++ b/net/disk_cache/entry_impl.cc
@@ -292,8 +292,9 @@ bool EntryImpl::UserBuffer::GrowBuffer(int required, int limit) {
// ------------------------------------------------------------------------
EntryImpl::EntryImpl(BackendImpl* backend, Addr address, bool read_only)
- : entry_(NULL, Addr(0)), node_(NULL, Addr(0)), backend_(backend),
- doomed_(false), read_only_(read_only), dirty_(false) {
+ : entry_(NULL, Addr(0)), node_(NULL, Addr(0)),
+ backend_(backend->GetWeakPtr()), doomed_(false), read_only_(read_only),
+ dirty_(false) {
entry_.LazyInit(backend->File(address), address);
for (int i = 0; i < kNumStreams; i++) {
unreported_size_[i] = 0;
@@ -301,7 +302,7 @@ EntryImpl::EntryImpl(BackendImpl* backend, Addr address, bool read_only)
}
void EntryImpl::DoomImpl() {
- if (doomed_)
+ if (doomed_ || !backend_)
return;
SetPointerForInvalidEntry(backend_->GetCurrentEntryId());
@@ -678,7 +679,13 @@ void EntryImpl::IncrementIoCount() {
}
void EntryImpl::DecrementIoCount() {
- backend_->DecrementIoCount();
+ if (backend_)
+ backend_->DecrementIoCount();
+}
+
+void EntryImpl::OnEntryCreated(BackendImpl* backend) {
+ // Just grab a reference to the backround queue.
+ background_queue_ = backend->GetBackgroundQueue();
}
void EntryImpl::SetTimes(base::Time last_used, base::Time last_modified) {
@@ -688,6 +695,9 @@ void EntryImpl::SetTimes(base::Time last_used, base::Time last_modified) {
}
void EntryImpl::ReportIOTime(Operation op, const base::TimeTicks& start) {
+ if (!backend_)
+ return;
+
int group = backend_->GetSizeGroup();
switch (op) {
case kRead:
@@ -744,11 +754,13 @@ int EntryImpl::NumBlocksForEntry(int key_size) {
// ------------------------------------------------------------------------
void EntryImpl::Doom() {
- backend_->background_queue()->DoomEntryImpl(this);
+ if (background_queue_)
+ background_queue_->DoomEntryImpl(this);
}
void EntryImpl::Close() {
- backend_->background_queue()->CloseEntryImpl(this);
+ if (background_queue_)
+ background_queue_->CloseEntryImpl(this);
}
std::string EntryImpl::GetKey() const {
@@ -817,8 +829,10 @@ int EntryImpl::ReadData(int index, int offset, net::IOBuffer* buf, int buf_len,
if (buf_len < 0)
return net::ERR_INVALID_ARGUMENT;
- backend_->background_queue()->ReadData(this, index, offset, buf, buf_len,
- callback);
+ if (!background_queue_)
+ return net::ERR_UNEXPECTED;
+
+ background_queue_->ReadData(this, index, offset, buf, buf_len, callback);
return net::ERR_IO_PENDING;
}
@@ -835,8 +849,11 @@ int EntryImpl::WriteData(
if (offset < 0 || buf_len < 0)
return net::ERR_INVALID_ARGUMENT;
- backend_->background_queue()->WriteData(this, index, offset, buf, buf_len,
- truncate, callback);
+ if (!background_queue_)
+ return net::ERR_UNEXPECTED;
+
+ background_queue_->WriteData(this, index, offset, buf, buf_len, truncate,
+ callback);
return net::ERR_IO_PENDING;
}
@@ -845,8 +862,10 @@ int EntryImpl::ReadSparseData(int64 offset, net::IOBuffer* buf, int buf_len,
if (callback.is_null())
return ReadSparseDataImpl(offset, buf, buf_len, callback);
- backend_->background_queue()->ReadSparseData(this, offset, buf, buf_len,
- callback);
+ if (!background_queue_)
+ return net::ERR_UNEXPECTED;
+
+ background_queue_->ReadSparseData(this, offset, buf, buf_len, callback);
return net::ERR_IO_PENDING;
}
@@ -855,15 +874,19 @@ int EntryImpl::WriteSparseData(int64 offset, net::IOBuffer* buf, int buf_len,
if (callback.is_null())
return WriteSparseDataImpl(offset, buf, buf_len, callback);
- backend_->background_queue()->WriteSparseData(this, offset, buf, buf_len,
- callback);
+ if (!background_queue_)
+ return net::ERR_UNEXPECTED;
+
+ background_queue_->WriteSparseData(this, offset, buf, buf_len, callback);
return net::ERR_IO_PENDING;
}
int EntryImpl::GetAvailableRange(int64 offset, int len, int64* start,
const net::CompletionCallback& callback) {
- backend_->background_queue()->GetAvailableRange(this, offset, len, start,
- callback);
+ if (!background_queue_)
+ return net::ERR_UNEXPECTED;
+
+ background_queue_->GetAvailableRange(this, offset, len, start, callback);
return net::ERR_IO_PENDING;
}
@@ -877,14 +900,18 @@ bool EntryImpl::CouldBeSparse() const {
}
void EntryImpl::CancelSparseIO() {
- backend_->background_queue()->CancelSparseIO(this);
+ if (background_queue_)
+ background_queue_->CancelSparseIO(this);
}
int EntryImpl::ReadyForSparseIO(const net::CompletionCallback& callback) {
if (!sparse_.get())
return net::OK;
- backend_->background_queue()->ReadyForSparseIO(this, callback);
+ if (!background_queue_)
+ return net::ERR_UNEXPECTED;
+
+ background_queue_->ReadyForSparseIO(this, callback);
return net::ERR_IO_PENDING;
}
@@ -895,6 +922,11 @@ int EntryImpl::ReadyForSparseIO(const net::CompletionCallback& callback) {
// data related to a previous cache entry because the range was not fully
// written before).
EntryImpl::~EntryImpl() {
+ if (!backend_) {
+ entry_.clear_modified();
+ node_.clear_modified();
+ return;
+ }
Log("~EntryImpl in");
// Save the sparse info to disk. This will generate IO for this entry and
@@ -958,6 +990,9 @@ int EntryImpl::InternalReadData(
if (buf_len < 0)
return net::ERR_INVALID_ARGUMENT;
+ if (!backend_)
+ return net::ERR_UNEXPECTED;
+
TimeTicks start = TimeTicks::Now();
if (offset + buf_len > entry_size)
@@ -1035,6 +1070,9 @@ int EntryImpl::InternalWriteData(
if (offset < 0 || buf_len < 0)
return net::ERR_INVALID_ARGUMENT;
+ if (!backend_)
+ return net::ERR_UNEXPECTED;
+
int max_file_size = backend_->MaxFileSize();
// offset or buf_len could be negative numbers.
@@ -1140,6 +1178,8 @@ bool EntryImpl::CreateDataBlock(int index, int size) {
bool EntryImpl::CreateBlock(int size, Addr* address) {
DCHECK(!address->is_initialized());
+ if (!backend_)
+ return false;
FileType file_type = Addr::RequiredFileType(size);
if (EXTERNAL == file_type) {
@@ -1164,6 +1204,7 @@ bool EntryImpl::CreateBlock(int size, Addr* address) {
// important that the entry doesn't keep a reference to this address, or we'll
// end up deleting the contents of |address| once again.
void EntryImpl::DeleteData(Addr address, int index) {
+ DCHECK(backend_);
if (!address.is_initialized())
return;
if (address.is_separate_file()) {
@@ -1181,6 +1222,9 @@ void EntryImpl::DeleteData(Addr address, int index) {
}
void EntryImpl::UpdateRank(bool modified) {
+ if (!backend_)
+ return;
+
if (!doomed_) {
// Everything is handled by the backend.
backend_->UpdateRank(this, modified);
@@ -1195,6 +1239,9 @@ void EntryImpl::UpdateRank(bool modified) {
}
File* EntryImpl::GetBackingFile(Addr address, int index) {
+ if (!backend_)
+ return NULL;
+
File* file;
if (address.is_separate_file())
file = GetExternalFile(address, index);
@@ -1466,6 +1513,7 @@ uint32 EntryImpl::GetEntryFlags() {
}
void EntryImpl::GetData(int index, char** buffer, Addr* address) {
+ DCHECK(backend_);
if (user_buffers_[index].get() && user_buffers_[index]->Size() &&
!user_buffers_[index]->Start()) {
// The data is already in memory, just copy it and we're done.
diff --git a/net/disk_cache/entry_impl.h b/net/disk_cache/entry_impl.h
index 3083b23..8296200 100644
--- a/net/disk_cache/entry_impl.h
+++ b/net/disk_cache/entry_impl.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -15,6 +15,7 @@
namespace disk_cache {
class BackendImpl;
+class InFlightBackendIO;
class SparseControl;
// This class implements the Entry interface. An object of this
@@ -121,6 +122,10 @@ class NET_EXPORT_PRIVATE EntryImpl
void IncrementIoCount();
void DecrementIoCount();
+ // This entry is being returned to the user. It is always called from the
+ // primary thread (not the dedicated cache thread).
+ void OnEntryCreated(BackendImpl* backend);
+
// Set the access times for this entry. This method provides support for
// the upgrade tool.
void SetTimes(base::Time last_used, base::Time last_modified);
@@ -254,7 +259,8 @@ class NET_EXPORT_PRIVATE EntryImpl
CacheEntryBlock entry_; // Key related information for this entry.
CacheRankingsBlock node_; // Rankings related information for this entry.
- BackendImpl* backend_; // Back pointer to the cache.
+ base::WeakPtr<BackendImpl> backend_; // Back pointer to the cache.
+ base::WeakPtr<InFlightBackendIO> background_queue_; // In-progress queue.
scoped_ptr<UserBuffer> user_buffers_[kNumStreams]; // Stores user data.
// Files to store external user data and key.
scoped_refptr<File> files_[kNumStreams + 1];
diff --git a/net/disk_cache/file.h b/net/disk_cache/file.h
index dc50133..3617e0c 100644
--- a/net/disk_cache/file.h
+++ b/net/disk_cache/file.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -68,6 +68,9 @@ class NET_EXPORT_PRIVATE File : public base::RefCounted<File> {
// Blocks until |num_pending_io| IO operations complete.
static void WaitForPendingIO(int* num_pending_io);
+ // Drops current pending operations without waiting for them to complete.
+ static void DropPendingIO();
+
protected:
virtual ~File();
diff --git a/net/disk_cache/file_posix.cc b/net/disk_cache/file_posix.cc
index 39c5159..e03d955 100644
--- a/net/disk_cache/file_posix.cc
+++ b/net/disk_cache/file_posix.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -97,7 +97,7 @@ void FileBackgroundIO::Read() {
} else {
result_ = net::ERR_CACHE_READ_FAILURE;
}
- controller_->OnIOComplete(this);
+ NotifyController();
}
// Runs on a worker thread.
@@ -105,7 +105,7 @@ void FileBackgroundIO::Write() {
bool rv = file_->Write(buf_, buf_len_, offset_);
result_ = rv ? static_cast<int>(buf_len_) : net::ERR_CACHE_WRITE_FAILURE;
- controller_->OnIOComplete(this);
+ NotifyController();
}
// ---------------------------------------------------------------------------
@@ -282,6 +282,12 @@ void File::WaitForPendingIO(int* num_pending_io) {
DeleteFileInFlightIO();
}
+// Static.
+void File::DropPendingIO() {
+ GetFileInFlightIO()->DropPendingIO();
+ DeleteFileInFlightIO();
+}
+
File::~File() {
if (IsValid())
base::ClosePlatformFile(platform_file_);
diff --git a/net/disk_cache/file_win.cc b/net/disk_cache/file_win.cc
index d12f82c8..071b4ef 100644
--- a/net/disk_cache/file_win.cc
+++ b/net/disk_cache/file_win.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -264,4 +264,9 @@ void File::WaitForPendingIO(int* num_pending_io) {
}
}
+// Static.
+void File::DropPendingIO() {
+ // Nothing to do here.
+}
+
} // namespace disk_cache
diff --git a/net/disk_cache/in_flight_backend_io.cc b/net/disk_cache/in_flight_backend_io.cc
index 0e5e969..e9fbd73 100644
--- a/net/disk_cache/in_flight_backend_io.cc
+++ b/net/disk_cache/in_flight_backend_io.cc
@@ -42,7 +42,23 @@ void BackendIO::OnIOComplete(int result) {
DCHECK(IsEntryOperation());
DCHECK_NE(result, net::ERR_IO_PENDING);
result_ = result;
- controller_->OnIOComplete(this);
+ NotifyController();
+}
+
+// Runs on the primary thread.
+void BackendIO::OnDone(bool cancel) {
+ if (IsEntryOperation()) {
+ CACHE_UMA(TIMES, "TotalIOTime", 0, ElapsedTime());
+ }
+
+ if (!ReturnsEntry())
+ return;
+
+ if (result() == net::OK) {
+ static_cast<EntryImpl*>(*entry_ptr_)->OnEntryCreated(backend_);
+ if (cancel)
+ (*entry_ptr_)->Close();
+ }
}
bool BackendIO::IsEntryOperation() {
@@ -54,10 +70,6 @@ void BackendIO::ReferenceEntry() {
entry_->AddRef();
}
-base::TimeDelta BackendIO::ElapsedTime() const {
- return base::TimeTicks::Now() - start_time_;
-}
-
void BackendIO::Init() {
operation_ = OP_INIT;
}
@@ -196,6 +208,15 @@ void BackendIO::ReadyForSparseIO(EntryImpl* entry) {
BackendIO::~BackendIO() {}
+bool BackendIO::ReturnsEntry() {
+ return (operation_ == OP_OPEN || operation_ == OP_CREATE ||
+ operation_ == OP_OPEN_NEXT || operation_ == OP_OPEN_PREV);
+}
+
+base::TimeDelta BackendIO::ElapsedTime() const {
+ return base::TimeTicks::Now() - start_time_;
+}
+
// Runs on the background thread.
void BackendIO::ExecuteBackendOperation() {
switch (operation_) {
@@ -254,7 +275,7 @@ void BackendIO::ExecuteBackendOperation() {
result_ = net::ERR_UNEXPECTED;
}
DCHECK_NE(net::ERR_IO_PENDING, result_);
- controller_->OnIOComplete(this);
+ NotifyController();
}
// Runs on the background thread.
@@ -263,23 +284,23 @@ void BackendIO::ExecuteEntryOperation() {
case OP_READ:
result_ = entry_->ReadDataImpl(
index_, offset_, buf_, buf_len_,
- base::Bind(&BackendIO::OnIOComplete, base::Unretained(this)));
+ base::Bind(&BackendIO::OnIOComplete, this));
break;
case OP_WRITE:
result_ = entry_->WriteDataImpl(
index_, offset_, buf_, buf_len_,
- base::Bind(&BackendIO::OnIOComplete, base::Unretained(this)),
+ base::Bind(&BackendIO::OnIOComplete, this),
truncate_);
break;
case OP_READ_SPARSE:
result_ = entry_->ReadSparseDataImpl(
offset64_, buf_, buf_len_,
- base::Bind(&BackendIO::OnIOComplete, base::Unretained(this)));
+ base::Bind(&BackendIO::OnIOComplete, this));
break;
case OP_WRITE_SPARSE:
result_ = entry_->WriteSparseDataImpl(
offset64_, buf_, buf_len_,
- base::Bind(&BackendIO::OnIOComplete, base::Unretained(this)));
+ base::Bind(&BackendIO::OnIOComplete, this));
break;
case OP_GET_RANGE:
result_ = entry_->GetAvailableRangeImpl(offset64_, buf_len_, start_);
@@ -290,20 +311,21 @@ void BackendIO::ExecuteEntryOperation() {
break;
case OP_IS_READY:
result_ = entry_->ReadyForSparseIOImpl(
- base::Bind(&BackendIO::OnIOComplete, base::Unretained(this)));
+ base::Bind(&BackendIO::OnIOComplete, this));
break;
default:
NOTREACHED() << "Invalid Operation";
result_ = net::ERR_UNEXPECTED;
}
if (result_ != net::ERR_IO_PENDING)
- controller_->OnIOComplete(this);
+ NotifyController();
}
InFlightBackendIO::InFlightBackendIO(BackendImpl* backend,
base::MessageLoopProxy* background_thread)
: backend_(backend),
- background_thread_(background_thread) {
+ background_thread_(background_thread),
+ ALLOW_THIS_IN_INITIALIZER_LIST(ptr_factory_(this)) {
}
InFlightBackendIO::~InFlightBackendIO() {
@@ -475,10 +497,7 @@ void InFlightBackendIO::WaitForPendingIO() {
void InFlightBackendIO::OnOperationComplete(BackgroundIO* operation,
bool cancel) {
BackendIO* op = static_cast<BackendIO*>(operation);
-
- if (op->IsEntryOperation()) {
- CACHE_UMA(TIMES, "TotalIOTime", 0, op->ElapsedTime());
- }
+ op->OnDone(cancel);
if (!op->callback().is_null() && (!cancel || op->IsEntryOperation()))
op->callback().Run(op->result());
@@ -490,4 +509,8 @@ void InFlightBackendIO::PostOperation(BackendIO* operation) {
OnOperationPosted(operation);
}
+base::WeakPtr<InFlightBackendIO> InFlightBackendIO::GetWeakPtr() {
+ return ptr_factory_.GetWeakPtr();
+}
+
} // namespace
diff --git a/net/disk_cache/in_flight_backend_io.h b/net/disk_cache/in_flight_backend_io.h
index 4e6f904..0e2eec6 100644
--- a/net/disk_cache/in_flight_backend_io.h
+++ b/net/disk_cache/in_flight_backend_io.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -34,6 +34,10 @@ class BackendIO : public BackgroundIO {
// Callback implementation.
void OnIOComplete(int result);
+ // Called when we are finishing this operation. If |cancel| is true, the user
+ // callback will not be invoked.
+ void OnDone(bool cancel);
+
// Returns true if this operation is directed to an entry (vs. the backend).
bool IsEntryOperation();
@@ -42,9 +46,6 @@ class BackendIO : public BackgroundIO {
// Grabs an extra reference of entry_.
void ReferenceEntry();
- // Returns the time that has passed since the operation was created.
- base::TimeDelta ElapsedTime() const;
-
// The operations we proxy:
void Init();
void OpenEntry(const std::string& key, Entry** entry);
@@ -109,6 +110,12 @@ class BackendIO : public BackgroundIO {
virtual ~BackendIO();
+ // Returns true if this operation returns an entry.
+ bool ReturnsEntry();
+
+ // Returns the time that has passed since the operation was created.
+ base::TimeDelta ElapsedTime() const;
+
void ExecuteBackendOperation();
void ExecuteEntryOperation();
@@ -196,6 +203,8 @@ class InFlightBackendIO : public InFlightIO {
return background_thread_->BelongsToCurrentThread();
}
+ base::WeakPtr<InFlightBackendIO> GetWeakPtr();
+
protected:
virtual void OnOperationComplete(BackgroundIO* operation,
bool cancel) OVERRIDE;
@@ -205,6 +214,7 @@ class InFlightBackendIO : public InFlightIO {
BackendImpl* backend_;
scoped_refptr<base::MessageLoopProxy> background_thread_;
+ base::WeakPtrFactory<InFlightBackendIO> ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(InFlightBackendIO);
};
diff --git a/net/disk_cache/in_flight_io.cc b/net/disk_cache/in_flight_io.cc
index 0f5185f..636cb4f 100644
--- a/net/disk_cache/in_flight_io.cc
+++ b/net/disk_cache/in_flight_io.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -11,7 +11,7 @@
namespace disk_cache {
BackgroundIO::BackgroundIO(InFlightIO* controller)
- : controller_(controller), result_(-1), io_completed_(true, false) {
+ : result_(-1), io_completed_(true, false), controller_(controller) {
}
// Runs on the primary thread.
@@ -21,15 +21,13 @@ void BackgroundIO::OnIOSignalled() {
}
void BackgroundIO::Cancel() {
+ // controller_ may be in use from the background thread at this time.
+ base::AutoLock lock(controller_lock_);
DCHECK(controller_);
controller_ = NULL;
}
-BackgroundIO::~BackgroundIO() {}
-
-// Runs on the background thread.
-void BackgroundIO::NotifyController() {
- controller_->OnIOComplete(this);
+BackgroundIO::~BackgroundIO() {
}
// ---------------------------------------------------------------------------
@@ -42,6 +40,13 @@ InFlightIO::InFlightIO()
InFlightIO::~InFlightIO() {
}
+// Runs on the background thread.
+void BackgroundIO::NotifyController() {
+ base::AutoLock lock(controller_lock_);
+ if (controller_)
+ controller_->OnIOComplete(this);
+}
+
void InFlightIO::WaitForPendingIO() {
while (!io_list_.empty()) {
// Block the current thread until all pending IO completes.
@@ -50,6 +55,16 @@ void InFlightIO::WaitForPendingIO() {
}
}
+void InFlightIO::DropPendingIO() {
+ while (!io_list_.empty()) {
+ IOList::iterator it = io_list_.begin();
+ BackgroundIO* operation = *it;
+ operation->Cancel();
+ DCHECK(io_list_.find(operation) != io_list_.end());
+ io_list_.erase(make_scoped_refptr(operation));
+ }
+}
+
// Runs on a background thread.
void InFlightIO::OnIOComplete(BackgroundIO* operation) {
#ifndef NDEBUG
diff --git a/net/disk_cache/in_flight_io.h b/net/disk_cache/in_flight_io.h
index a361cbd..c007cb9 100644
--- a/net/disk_cache/in_flight_io.h
+++ b/net/disk_cache/in_flight_io.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -9,6 +9,7 @@
#include <set>
#include "base/message_loop_proxy.h"
+#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
namespace disk_cache {
@@ -48,18 +49,19 @@ class BackgroundIO : public base::RefCountedThreadSafe<BackgroundIO> {
protected:
virtual ~BackgroundIO();
- InFlightIO* controller_; // The controller that tracks all operations.
+ // Notifies the controller about the end of the operation, from the background
+ // thread.
+ void NotifyController();
+
int result_; // Final operation result.
private:
friend class base::RefCountedThreadSafe<BackgroundIO>;
- // Notifies the controller about the end of the operation, from the background
- // thread.
- void NotifyController();
-
// An event to signal when the operation completes.
base::WaitableEvent io_completed_;
+ InFlightIO* controller_; // The controller that tracks all operations.
+ base::Lock controller_lock_; // A lock protecting clearing of controller_.
DISALLOW_COPY_AND_ASSIGN(BackgroundIO);
};
@@ -95,6 +97,9 @@ class InFlightIO {
// complete.
void WaitForPendingIO();
+ // Drops current pending operations without waiting for them to complete.
+ void DropPendingIO();
+
// Called on a background thread when |operation| completes.
void OnIOComplete(BackgroundIO* operation);
diff --git a/net/disk_cache/sparse_control.cc b/net/disk_cache/sparse_control.cc
index ee558ba..a45ba1f 100644
--- a/net/disk_cache/sparse_control.cc
+++ b/net/disk_cache/sparse_control.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -442,6 +442,9 @@ bool SparseControl::OpenChild() {
if (!ChildPresent())
return ContinueWithoutChild(key);
+ if (!entry_->backend_)
+ return false;
+
child_ = entry_->backend_->OpenEntryImpl(key);
if (!child_)
return ContinueWithoutChild(key);
@@ -514,6 +517,9 @@ bool SparseControl::ContinueWithoutChild(const std::string& key) {
if (kGetRangeOperation == operation_)
return true;
+ if (!entry_->backend_)
+ return false;
+
child_ = entry_->backend_->CreateEntryImpl(key);
if (!child_) {
child_ = NULL;
diff --git a/net/disk_cache/storage_block-inl.h b/net/disk_cache/storage_block-inl.h
index 614b143..388aa24 100644
--- a/net/disk_cache/storage_block-inl.h
+++ b/net/disk_cache/storage_block-inl.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -89,6 +89,10 @@ template<typename T> void StorageBlock<T>::set_modified() {
modified_ = true;
}
+template<typename T> void StorageBlock<T>::clear_modified() {
+ modified_ = false;
+}
+
template<typename T> T* StorageBlock<T>::Data() {
if (!data_)
AllocateData();
diff --git a/net/disk_cache/storage_block.h b/net/disk_cache/storage_block.h
index 2cf3c3a..f32c0fc 100644
--- a/net/disk_cache/storage_block.h
+++ b/net/disk_cache/storage_block.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 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.
@@ -55,6 +55,9 @@ class StorageBlock : public FileBlock {
// Sets the object to lazily save the in-memory data on destruction.
void set_modified();
+ // Forgets that the data was modified, so it's not lazily saved.
+ void clear_modified();
+
// Gets a pointer to the internal storage (allocates storage if needed).
T* Data();