diff options
21 files changed, 346 insertions, 353 deletions
diff --git a/content/browser/gpu/shader_disk_cache.cc b/content/browser/gpu/shader_disk_cache.cc index 9c942a0..a7f240c 100644 --- a/content/browser/gpu/shader_disk_cache.cc +++ b/content/browser/gpu/shader_disk_cache.cc @@ -95,7 +95,7 @@ class ShaderDiskReadHelper base::WeakPtr<ShaderDiskCache> cache_; OpType op_type_; - scoped_ptr<disk_cache::Backend::Iterator> iter_; + void* iter_; scoped_refptr<net::IOBufferWithSize> buf_; int host_id_; disk_cache::Entry* entry_; @@ -243,6 +243,7 @@ ShaderDiskReadHelper::ShaderDiskReadHelper( int host_id) : cache_(cache), op_type_(OPEN_NEXT), + iter_(NULL), buf_(NULL), host_id_(host_id), entry_(NULL) { @@ -290,10 +291,10 @@ int ShaderDiskReadHelper::OpenNextEntry() { DCHECK(CalledOnValidThread()); // Called through OnOpComplete, so we know |cache_| is valid. op_type_ = OPEN_NEXT_COMPLETE; - if (!iter_) - iter_ = cache_->backend()->CreateIterator(); - return iter_->OpenNextEntry( - &entry_, base::Bind(&ShaderDiskReadHelper::OnOpComplete, this)); + return cache_->backend()->OpenNextEntry( + &iter_, + &entry_, + base::Bind(&ShaderDiskReadHelper::OnOpComplete, this)); } int ShaderDiskReadHelper::OpenNextEntryComplete(int rv) { @@ -338,7 +339,8 @@ int ShaderDiskReadHelper::ReadComplete(int rv) { int ShaderDiskReadHelper::IterationComplete(int rv) { DCHECK(CalledOnValidThread()); // Called through OnOpComplete, so we know |cache_| is valid. - iter_.reset(); + cache_->backend()->EndEnumeration(&iter_); + iter_ = NULL; op_type_ = TERMINATE; return net::OK; } diff --git a/content/browser/service_worker/service_worker_cache.cc b/content/browser/service_worker/service_worker_cache.cc index e9989fa..2fb5216d 100644 --- a/content/browser/service_worker/service_worker_cache.cc +++ b/content/browser/service_worker/service_worker_cache.cc @@ -597,6 +597,7 @@ struct ServiceWorkerCache::KeysContext { : original_callback(callback), cache(cache), out_keys(new ServiceWorkerCache::Requests()), + backend_iterator(NULL), enumerated_entry(NULL) {} ~KeysContext() { @@ -604,6 +605,8 @@ struct ServiceWorkerCache::KeysContext { entries[i]->Close(); if (enumerated_entry) enumerated_entry->Close(); + if (cache && backend_iterator && cache->backend_) + cache->backend_->EndEnumeration(&backend_iterator); } // The callback passed to the Keys() function. @@ -619,7 +622,7 @@ struct ServiceWorkerCache::KeysContext { scoped_ptr<ServiceWorkerCache::Requests> out_keys; // Used for enumerating cache entries. - scoped_ptr<disk_cache::Backend::Iterator> backend_iterator; + void* backend_iterator; disk_cache::Entry* enumerated_entry; }; @@ -771,14 +774,14 @@ void ServiceWorkerCache::Keys(const RequestsCallback& callback) { scoped_ptr<KeysContext> keys_context( new KeysContext(callback, weak_ptr_factory_.GetWeakPtr())); - keys_context->backend_iterator = backend_->CreateIterator(); - disk_cache::Backend::Iterator& iterator = *keys_context->backend_iterator; + void** backend_iterator = &keys_context->backend_iterator; disk_cache::Entry** enumerated_entry = &keys_context->enumerated_entry; net::CompletionCallback open_entry_callback = base::Bind(KeysDidOpenNextEntry, base::Passed(keys_context.Pass())); - int rv = iterator.OpenNextEntry(enumerated_entry, open_entry_callback); + int rv = backend_->OpenNextEntry( + backend_iterator, enumerated_entry, open_entry_callback); if (rv != net::ERR_IO_PENDING) open_entry_callback.Run(rv); @@ -861,12 +864,14 @@ void ServiceWorkerCache::KeysDidOpenNextEntry( keys_context->enumerated_entry = NULL; // Enumerate the next entry. - disk_cache::Backend::Iterator& iterator = *keys_context->backend_iterator; + void** backend_iterator = &keys_context->backend_iterator; disk_cache::Entry** enumerated_entry = &keys_context->enumerated_entry; + net::CompletionCallback open_entry_callback = base::Bind(KeysDidOpenNextEntry, base::Passed(keys_context.Pass())); - rv = iterator.OpenNextEntry(enumerated_entry, open_entry_callback); + rv = cache->backend_->OpenNextEntry( + backend_iterator, enumerated_entry, open_entry_callback); if (rv != net::ERR_IO_PENDING) open_entry_callback.Run(rv); diff --git a/net/disk_cache/backend_unittest.cc b/net/disk_cache/backend_unittest.cc index 572691c..c3f2cfa 100644 --- a/net/disk_cache/backend_unittest.cc +++ b/net/disk_cache/backend_unittest.cc @@ -81,7 +81,7 @@ class DiskCacheBackendTest : public DiskCacheTestWithCache { bool CreateSetOfRandomEntries(std::set<std::string>* key_pool); bool EnumerateAndMatchKeys(int max_to_open, - TestIterator* iter, + void** iter, std::set<std::string>* keys_to_match, size_t* count); @@ -256,14 +256,12 @@ bool DiskCacheBackendTest::CreateSetOfRandomEntries( // OpenNextEntry stops returning net::OK. bool DiskCacheBackendTest::EnumerateAndMatchKeys( int max_to_open, - TestIterator* iter, + void** iter, std::set<std::string>* keys_to_match, size_t* count) { disk_cache::Entry* entry; - if (!iter) - return false; - while (iter->OpenNextEntry(&entry) == net::OK) { + while (OpenNextEntry(iter, &entry) == net::OK) { if (!entry) return false; EXPECT_EQ(1U, keys_to_match->erase(entry->GetKey())); @@ -1239,11 +1237,11 @@ void DiskCacheBackendTest::BackendEnumerations() { Time final = Time::Now(); disk_cache::Entry* entry; - scoped_ptr<TestIterator> iter = CreateIterator(); + void* iter = NULL; int count = 0; Time last_modified[kNumEntries]; Time last_used[kNumEntries]; - while (iter->OpenNextEntry(&entry) == net::OK) { + while (OpenNextEntry(&iter, &entry) == net::OK) { ASSERT_TRUE(NULL != entry); if (count < kNumEntries) { last_modified[count] = entry->GetLastModified(); @@ -1257,10 +1255,10 @@ void DiskCacheBackendTest::BackendEnumerations() { }; EXPECT_EQ(kNumEntries, count); - iter = CreateIterator(); + iter = NULL; count = 0; // The previous enumeration should not have changed the timestamps. - while (iter->OpenNextEntry(&entry) == net::OK) { + while (OpenNextEntry(&iter, &entry) == net::OK) { ASSERT_TRUE(NULL != entry); if (count < kNumEntries) { EXPECT_TRUE(last_modified[count] == entry->GetLastModified()); @@ -1311,8 +1309,8 @@ void DiskCacheBackendTest::BackendEnumerations2() { // Make sure that the timestamp is not the same. AddDelay(); ASSERT_EQ(net::OK, OpenEntry(second, &entry1)); - scoped_ptr<TestIterator> iter = CreateIterator(); - ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry2)); + void* iter = NULL; + ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry2)); EXPECT_EQ(entry2->GetKey(), second); // Two entries and the iterator pointing at "first". @@ -1320,15 +1318,15 @@ void DiskCacheBackendTest::BackendEnumerations2() { entry2->Close(); // The iterator should still be valid, so we should not crash. - ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry2)); + ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry2)); EXPECT_EQ(entry2->GetKey(), first); entry2->Close(); - iter = CreateIterator(); + cache_->EndEnumeration(&iter); // Modify the oldest entry and get the newest element. ASSERT_EQ(net::OK, OpenEntry(first, &entry1)); EXPECT_EQ(0, WriteData(entry1, 0, 200, NULL, 0, false)); - ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry2)); + ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry2)); if (type_ == net::APP_CACHE) { // The list is not updated. EXPECT_EQ(entry2->GetKey(), second); @@ -1338,6 +1336,7 @@ void DiskCacheBackendTest::BackendEnumerations2() { entry1->Close(); entry2->Close(); + cache_->EndEnumeration(&iter); } TEST_F(DiskCacheBackendTest, Enumerations2) { @@ -1392,10 +1391,11 @@ TEST_F(DiskCacheBackendTest, ShaderCacheEnumerationReadData) { EXPECT_EQ(kSize, ReadData(entry1, 0, 0, buffer1.get(), kSize)); entry1->Close(); - scoped_ptr<TestIterator> iter = CreateIterator(); - ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry2)); + void* iter = NULL; + ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry2)); EXPECT_EQ(entry2->GetKey(), second); entry2->Close(); + cache_->EndEnumeration(&iter); } #if !defined(LEAK_SANITIZER) @@ -1424,9 +1424,9 @@ void DiskCacheBackendTest::BackendInvalidEntryEnumeration() { SimulateCrash(); - scoped_ptr<TestIterator> iter = CreateIterator(); + void* iter = NULL; int count = 0; - while (iter->OpenNextEntry(&entry) == net::OK) { + while (OpenNextEntry(&iter, &entry) == net::OK) { ASSERT_TRUE(NULL != entry); EXPECT_EQ(key2, entry->GetKey()); entry->Close(); @@ -1466,8 +1466,9 @@ void DiskCacheBackendTest::BackendFixEnumerators() { EXPECT_EQ(kNumEntries, cache_->GetEntryCount()); disk_cache::Entry *entry1, *entry2; - scoped_ptr<TestIterator> iter1 = CreateIterator(), iter2 = CreateIterator(); - ASSERT_EQ(net::OK, iter1->OpenNextEntry(&entry1)); + void* iter1 = NULL; + void* iter2 = NULL; + ASSERT_EQ(net::OK, OpenNextEntry(&iter1, &entry1)); ASSERT_TRUE(NULL != entry1); entry1->Close(); entry1 = NULL; @@ -1476,17 +1477,17 @@ void DiskCacheBackendTest::BackendFixEnumerators() { for (int i = 0; i < kNumEntries / 2; i++) { if (entry1) entry1->Close(); - ASSERT_EQ(net::OK, iter1->OpenNextEntry(&entry1)); + ASSERT_EQ(net::OK, OpenNextEntry(&iter1, &entry1)); ASSERT_TRUE(NULL != entry1); - ASSERT_EQ(net::OK, iter2->OpenNextEntry(&entry2)); + ASSERT_EQ(net::OK, OpenNextEntry(&iter2, &entry2)); ASSERT_TRUE(NULL != entry2); entry2->Close(); } // Messing up with entry1 will modify entry2->next. entry1->Doom(); - ASSERT_EQ(net::OK, iter2->OpenNextEntry(&entry2)); + ASSERT_EQ(net::OK, OpenNextEntry(&iter2, &entry2)); ASSERT_TRUE(NULL != entry2); // The link entry2->entry1 should be broken. @@ -1495,9 +1496,12 @@ void DiskCacheBackendTest::BackendFixEnumerators() { entry2->Close(); // And the second iterator should keep working. - ASSERT_EQ(net::OK, iter2->OpenNextEntry(&entry2)); + ASSERT_EQ(net::OK, OpenNextEntry(&iter2, &entry2)); ASSERT_TRUE(NULL != entry2); entry2->Close(); + + cache_->EndEnumeration(&iter1); + cache_->EndEnumeration(&iter2); } TEST_F(DiskCacheBackendTest, FixEnumerators) { @@ -2023,8 +2027,8 @@ void DiskCacheBackendTest::BackendInvalidEntry3() { InitCache(); disk_cache::Entry* entry; - scoped_ptr<TestIterator> iter = CreateIterator(); - while (iter->OpenNextEntry(&entry) == net::OK) { + void* iter = NULL; + while (OpenNextEntry(&iter, &entry) == net::OK) { entry->Close(); } } @@ -2168,8 +2172,8 @@ void DiskCacheBackendTest::BackendInvalidEntry7() { EXPECT_EQ(1, cache_->GetEntryCount()); // We should delete the cache. The list still has a corrupt node. - scoped_ptr<TestIterator> iter = CreateIterator(); - EXPECT_NE(net::OK, iter->OpenNextEntry(&entry)); + void* iter = NULL; + EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry)); FlushQueueForTest(); EXPECT_EQ(0, cache_->GetEntryCount()); } @@ -2212,10 +2216,10 @@ void DiskCacheBackendTest::BackendInvalidEntry8() { EXPECT_EQ(1, cache_->GetEntryCount()); // We should not delete the cache. - scoped_ptr<TestIterator> iter = CreateIterator(); - ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry)); + void* iter = NULL; + ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry)); entry->Close(); - EXPECT_NE(net::OK, iter->OpenNextEntry(&entry)); + EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry)); EXPECT_EQ(1, cache_->GetEntryCount()); } @@ -2262,13 +2266,13 @@ void DiskCacheBackendTest::BackendInvalidEntry9(bool eviction) { } else { // We should detect the problem through the list, but we should not delete // the entry, just fail the iteration. - scoped_ptr<TestIterator> iter = CreateIterator(); - EXPECT_NE(net::OK, iter->OpenNextEntry(&entry)); + void* iter = NULL; + EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry)); // Now a full iteration will work, and return one entry. - ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry)); + ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry)); entry->Close(); - EXPECT_NE(net::OK, iter->OpenNextEntry(&entry)); + EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry)); // This should detect what's left of the bad entry. EXPECT_NE(net::OK, OpenEntry(second, &entry)); @@ -2339,13 +2343,13 @@ void DiskCacheBackendTest::BackendInvalidEntry10(bool eviction) { // Detection order: third -> second -> first. // We should detect the problem through the list, but we should not delete // the entry. - scoped_ptr<TestIterator> iter = CreateIterator(); - ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry)); + void* iter = NULL; + ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry)); entry->Close(); - ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry)); + ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry)); EXPECT_EQ(first, entry->GetKey()); entry->Close(); - EXPECT_NE(net::OK, iter->OpenNextEntry(&entry)); + EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry)); } DisableIntegrityCheck(); } @@ -2406,17 +2410,17 @@ void DiskCacheBackendTest::BackendInvalidEntry11(bool eviction) { // Detection order: third -> second. // We should detect the problem through the list, but we should not delete // the entry, just fail the iteration. - scoped_ptr<TestIterator> iter = CreateIterator(); - ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry)); + void* iter = NULL; + ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry)); entry->Close(); - EXPECT_NE(net::OK, iter->OpenNextEntry(&entry)); + EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry)); // Now a full iteration will work, and return two entries. - ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry)); + ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry)); entry->Close(); - ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry)); + ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry)); entry->Close(); - EXPECT_NE(net::OK, iter->OpenNextEntry(&entry)); + EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry)); } DisableIntegrityCheck(); } @@ -2494,12 +2498,12 @@ TEST_F(DiskCacheBackendTest, NewEvictionInvalidRankings2) { // If the LRU is corrupt, we delete the cache. void DiskCacheBackendTest::BackendInvalidRankings() { disk_cache::Entry* entry; - scoped_ptr<TestIterator> iter = CreateIterator(); - ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry)); + void* iter = NULL; + ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry)); entry->Close(); EXPECT_EQ(2, cache_->GetEntryCount()); - EXPECT_NE(net::OK, iter->OpenNextEntry(&entry)); + EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry)); FlushQueueForTest(); // Allow the restart to finish. EXPECT_EQ(0, cache_->GetEntryCount()); } @@ -2539,10 +2543,10 @@ TEST_F(DiskCacheBackendTest, NewEvictionInvalidRankingsFailure) { // If the LRU is corrupt and we have open entries, we disable the cache. void DiskCacheBackendTest::BackendDisable() { disk_cache::Entry *entry1, *entry2; - scoped_ptr<TestIterator> iter = CreateIterator(); - ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry1)); + void* iter = NULL; + ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry1)); - EXPECT_NE(net::OK, iter->OpenNextEntry(&entry2)); + EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry2)); EXPECT_EQ(0, cache_->GetEntryCount()); EXPECT_NE(net::OK, CreateEntry("Something new", &entry2)); @@ -2590,9 +2594,9 @@ void DiskCacheBackendTest::BackendDisable2() { EXPECT_EQ(8, cache_->GetEntryCount()); disk_cache::Entry* entry; - scoped_ptr<TestIterator> iter = CreateIterator(); + void* iter = NULL; int count = 0; - while (iter->OpenNextEntry(&entry) == net::OK) { + while (OpenNextEntry(&iter, &entry) == net::OK) { ASSERT_TRUE(NULL != entry); entry->Close(); count++; @@ -2638,12 +2642,12 @@ TEST_F(DiskCacheBackendTest, NewEvictionDisableFailure2) { // If the index size changes when we disable the cache, we should not crash. void DiskCacheBackendTest::BackendDisable3() { disk_cache::Entry *entry1, *entry2; - scoped_ptr<TestIterator> iter = CreateIterator(); + void* iter = NULL; EXPECT_EQ(2, cache_->GetEntryCount()); - ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry1)); + ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry1)); entry1->Close(); - EXPECT_NE(net::OK, iter->OpenNextEntry(&entry2)); + EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry2)); FlushQueueForTest(); ASSERT_EQ(net::OK, CreateEntry("Something new", &entry2)); @@ -2672,8 +2676,8 @@ TEST_F(DiskCacheBackendTest, NewEvictionDisableSuccess3) { // If we disable the cache, already open entries should work as far as possible. void DiskCacheBackendTest::BackendDisable4() { disk_cache::Entry *entry1, *entry2, *entry3, *entry4; - scoped_ptr<TestIterator> iter = CreateIterator(); - ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry1)); + void* iter = NULL; + ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry1)); char key2[2000]; char key3[20000]; @@ -2691,7 +2695,7 @@ void DiskCacheBackendTest::BackendDisable4() { EXPECT_EQ(kBufSize, WriteData(entry3, 0, 0, buf.get(), kBufSize, false)); // This line should disable the cache but not delete it. - EXPECT_NE(net::OK, iter->OpenNextEntry(&entry4)); + EXPECT_NE(net::OK, OpenNextEntry(&iter, &entry4)); EXPECT_EQ(0, cache_->GetEntryCount()); EXPECT_NE(net::OK, CreateEntry("cache is disabled", &entry4)); @@ -3372,29 +3376,29 @@ TEST_F(DiskCacheBackendTest, SimpleCacheEnumerationBasics) { // Check that enumeration returns all entries. std::set<std::string> keys_to_match(key_pool); - scoped_ptr<TestIterator> iter = CreateIterator(); + void* iter = NULL; size_t count = 0; - ASSERT_TRUE(EnumerateAndMatchKeys(-1, iter.get(), &keys_to_match, &count)); - iter.reset(); + ASSERT_TRUE(EnumerateAndMatchKeys(-1, &iter, &keys_to_match, &count)); + cache_->EndEnumeration(&iter); EXPECT_EQ(key_pool.size(), count); EXPECT_TRUE(keys_to_match.empty()); // Check that opening entries does not affect enumeration. keys_to_match = key_pool; - iter = CreateIterator(); + iter = NULL; count = 0; disk_cache::Entry* entry_opened_before; ASSERT_EQ(net::OK, OpenEntry(*(key_pool.begin()), &entry_opened_before)); ASSERT_TRUE(EnumerateAndMatchKeys(key_pool.size()/2, - iter.get(), + &iter, &keys_to_match, &count)); disk_cache::Entry* entry_opened_middle; ASSERT_EQ(net::OK, OpenEntry(*(keys_to_match.begin()), &entry_opened_middle)); - ASSERT_TRUE(EnumerateAndMatchKeys(-1, iter.get(), &keys_to_match, &count)); - iter.reset(); + ASSERT_TRUE(EnumerateAndMatchKeys(-1, &iter, &keys_to_match, &count)); + cache_->EndEnumeration(&iter); entry_opened_before->Close(); entry_opened_middle->Close(); @@ -3412,10 +3416,10 @@ TEST_F(DiskCacheBackendTest, SimpleCacheEnumerationWhileDoomed) { // Check that enumeration returns all entries but the doomed one. std::set<std::string> keys_to_match(key_pool); - scoped_ptr<TestIterator> iter = CreateIterator(); + void* iter = NULL; size_t count = 0; ASSERT_TRUE(EnumerateAndMatchKeys(key_pool.size()/2, - iter.get(), + &iter, &keys_to_match, &count)); @@ -3423,8 +3427,8 @@ TEST_F(DiskCacheBackendTest, SimpleCacheEnumerationWhileDoomed) { DoomEntry(key_to_delete); keys_to_match.erase(key_to_delete); key_pool.erase(key_to_delete); - ASSERT_TRUE(EnumerateAndMatchKeys(-1, iter.get(), &keys_to_match, &count)); - iter.reset(); + ASSERT_TRUE(EnumerateAndMatchKeys(-1, &iter, &keys_to_match, &count)); + cache_->EndEnumeration(&iter); EXPECT_EQ(key_pool.size(), count); EXPECT_TRUE(keys_to_match.empty()); @@ -3460,10 +3464,10 @@ TEST_F(DiskCacheBackendTest, SimpleCacheEnumerationCorruption) { // Check that enumeration returns all entries but the corrupt one. std::set<std::string> keys_to_match(key_pool); - scoped_ptr<TestIterator> iter = CreateIterator(); + void* iter = NULL; size_t count = 0; - ASSERT_TRUE(EnumerateAndMatchKeys(-1, iter.get(), &keys_to_match, &count)); - iter.reset(); + ASSERT_TRUE(EnumerateAndMatchKeys(-1, &iter, &keys_to_match, &count)); + cache_->EndEnumeration(&iter); EXPECT_EQ(key_pool.size(), count); EXPECT_TRUE(keys_to_match.empty()); @@ -3477,9 +3481,9 @@ TEST_F(DiskCacheBackendTest, SimpleCacheEnumerationDestruction) { std::set<std::string> key_pool; ASSERT_TRUE(CreateSetOfRandomEntries(&key_pool)); - scoped_ptr<TestIterator> iter = CreateIterator(); + void* iter = NULL; disk_cache::Entry* entry = NULL; - ASSERT_EQ(net::OK, iter->OpenNextEntry(&entry)); + ASSERT_EQ(net::OK, OpenNextEntry(&iter, &entry)); EXPECT_TRUE(entry); disk_cache::ScopedEntryPtr entry_closer(entry); diff --git a/net/disk_cache/blockfile/backend_impl.cc b/net/disk_cache/blockfile/backend_impl.cc index e368328..c38b2bb 100644 --- a/net/disk_cache/blockfile/backend_impl.cc +++ b/net/disk_cache/blockfile/backend_impl.cc @@ -1250,27 +1250,16 @@ int BackendImpl::DoomEntriesSince(const base::Time initial_time, return net::ERR_IO_PENDING; } -class BackendImpl::IteratorImpl : public Backend::Iterator { - public: - explicit IteratorImpl(base::WeakPtr<InFlightBackendIO> background_queue) - : background_queue_(background_queue), data_(NULL) { - } - - virtual int OpenNextEntry(Entry** next_entry, - const net::CompletionCallback& callback) OVERRIDE { - if (!background_queue_) - return net::ERR_FAILED; - background_queue_->OpenNextEntry(&data_, next_entry, callback); - return net::ERR_IO_PENDING; - } - - private: - const base::WeakPtr<InFlightBackendIO> background_queue_; - void* data_; -}; +int BackendImpl::OpenNextEntry(void** iter, Entry** next_entry, + const CompletionCallback& callback) { + DCHECK(!callback.is_null()); + background_queue_.OpenNextEntry(iter, next_entry, callback); + return net::ERR_IO_PENDING; +} -scoped_ptr<Backend::Iterator> BackendImpl::CreateIterator() { - return scoped_ptr<Backend::Iterator>(new IteratorImpl(GetBackgroundQueue())); +void BackendImpl::EndEnumeration(void** iter) { + background_queue_.EndEnumeration(*iter); + *iter = NULL; } void BackendImpl::GetStats(StatsItems* stats) { diff --git a/net/disk_cache/blockfile/backend_impl.h b/net/disk_cache/blockfile/backend_impl.h index 775374e..e2304ff 100644 --- a/net/disk_cache/blockfile/backend_impl.h +++ b/net/disk_cache/blockfile/backend_impl.h @@ -273,21 +273,14 @@ class NET_EXPORT_PRIVATE BackendImpl : public Backend { const CompletionCallback& callback) OVERRIDE; virtual int DoomEntriesSince(base::Time initial_time, const CompletionCallback& callback) OVERRIDE; - // NOTE: The blockfile Backend::Iterator::OpenNextEntry method does not modify - // the last_used field of the entry, and therefore it does not impact the - // eviction ranking of the entry. However, an enumeration will go through all - // entries on the cache only if the cache is not modified while the - // enumeration is taking place. Significantly altering the entry pointed by - // the iterator (for example, deleting the entry) will invalidate the - // iterator. Performing operations on an entry that modify the entry may - // result in loops in the iteration, skipped entries or similar. - virtual scoped_ptr<Iterator> CreateIterator() OVERRIDE; + virtual int OpenNextEntry(void** iter, Entry** next_entry, + const CompletionCallback& callback) OVERRIDE; + virtual void EndEnumeration(void** iter) OVERRIDE; virtual void GetStats(StatsItems* stats) OVERRIDE; virtual void OnExternalCacheHit(const std::string& key) OVERRIDE; private: typedef base::hash_map<CacheAddr, EntryImpl*> EntriesMap; - class IteratorImpl; // Creates a new backing file for the cache index. bool CreateBackingStore(disk_cache::File* file); diff --git a/net/disk_cache/blockfile/backend_impl_v3.cc b/net/disk_cache/blockfile/backend_impl_v3.cc index b44b195..9a7cff1 100644 --- a/net/disk_cache/blockfile/backend_impl_v3.cc +++ b/net/disk_cache/blockfile/backend_impl_v3.cc @@ -660,27 +660,17 @@ int BackendImplV3::DoomEntriesSince(base::Time initial_time, } } -class BackendImplV3::IteratorImpl : public Backend::Iterator { - public: - explicit IteratorImpl(base::WeakPtr<InFlightBackendIO> background_queue) - : background_queue_(background_queue), data_(NULL) { - } - - virtual int OpenNextEntry(Entry** next_entry, - const net::CompletionCallback& callback) OVERRIDE { - if (!background_queue_) - return net::ERR_FAILED; - background_queue_->OpenNextEntry(&data_, next_entry, callback); - return net::ERR_IO_PENDING; - } - - private: - const base::WeakPtr<InFlightBackendIO> background_queue_; - void* data_; -}; +int BackendImplV3::OpenNextEntry(void** iter, Entry** next_entry, + const CompletionCallback& callback) { + DCHECK(!callback.is_null()); + background_queue_.OpenNextEntry(iter, next_entry, callback); + return net::ERR_IO_PENDING; +} -scoped_ptr<Backend::Iterator> BackendImplV3::CreateIterator() { - return scoped_ptr<Backend::Iterator>(new IteratorImpl(GetBackgroundQueue())); +void BackendImplV3::EndEnumeration(void** iter) { + scoped_ptr<IndexIterator> iterator( + reinterpret_cast<IndexIterator*>(*iter)); + *iter = NULL; } void BackendImplV3::GetStats(StatsItems* stats) { @@ -1507,17 +1497,13 @@ int BackendImplV3::DoomEntriesSince(base::Time initial_time, return net::ERR_FAILED; } +int BackendImplV3::OpenNextEntry(void** iter, Entry** next_entry, + const CompletionCallback& callback) { + return net::ERR_FAILED; +} -class BackendImplV3::NotImplementedIterator : public Backend::Iterator { - public: - virtual int OpenNextEntry(disk_cache::Entry** next_entry, - const net::CompletionCallback& callback) OVERRIDE { - return net::ERR_NOT_IMPLEMENTED; - } -}; - -scoped_ptr<Backend::Iterator> BackendImplV3::CreateIterator() { - return scoped_ptr<Iterator>(new NotImplementedIterator()); +void BackendImplV3::EndEnumeration(void** iter) { + NOTIMPLEMENTED(); } void BackendImplV3::GetStats(StatsItems* stats) { diff --git a/net/disk_cache/blockfile/backend_impl_v3.h b/net/disk_cache/blockfile/backend_impl_v3.h index ca64997..b57bb89 100644 --- a/net/disk_cache/blockfile/backend_impl_v3.h +++ b/net/disk_cache/blockfile/backend_impl_v3.h @@ -186,15 +186,15 @@ class NET_EXPORT_PRIVATE BackendImplV3 : public Backend { const CompletionCallback& callback) OVERRIDE; virtual int DoomEntriesSince(base::Time initial_time, const CompletionCallback& callback) OVERRIDE; - virtual scoped_ptr<Iterator> CreateIterator() OVERRIDE; + virtual int OpenNextEntry(void** iter, Entry** next_entry, + const CompletionCallback& callback) OVERRIDE; + virtual void EndEnumeration(void** iter) OVERRIDE; virtual void GetStats(StatsItems* stats) OVERRIDE; virtual void OnExternalCacheHit(const std::string& key) OVERRIDE; private: friend class EvictionV3; typedef base::hash_map<CacheAddr, EntryImplV3*> EntriesMap; - class IteratorImpl; - class NotImplementedIterator; class Worker; void AdjustMaxCacheSize(); diff --git a/net/disk_cache/disk_cache.h b/net/disk_cache/disk_cache.h index 769ab36..4f64b9a 100644 --- a/net/disk_cache/disk_cache.h +++ b/net/disk_cache/disk_cache.h @@ -13,7 +13,6 @@ #include "base/basictypes.h" #include "base/memory/ref_counted.h" -#include "base/memory/scoped_ptr.h" #include "base/time/time.h" #include "net/base/cache_type.h" #include "net/base/completion_callback.h" @@ -65,26 +64,6 @@ class NET_EXPORT Backend { public: typedef net::CompletionCallback CompletionCallback; - class Iterator { - public: - virtual ~Iterator() {} - - // OpenNextEntry returns |net::OK| and provides |next_entry| if there is an - // entry to enumerate. It returns |net::ERR_FAILED| at the end of - // enumeration. If the function returns |net::ERR_IO_PENDING|, then the - // final result will be passed to the provided |callback|, otherwise - // |callback| will not be called. If any entry in the cache is modified - // during iteration, the result of this function is thereafter undefined. - // - // Calling OpenNextEntry after the backend which created it is destroyed - // may fail with |net::ERR_FAILED|; however it should not crash. - // - // Some cache backends make stronger guarantees about mutation during - // iteration, see top comment in simple_backend_impl.h for details. - virtual int OpenNextEntry(Entry** next_entry, - const CompletionCallback& callback) = 0; - }; - // If the backend is destroyed when there are operations in progress (any // callback that has not been invoked yet), this method cancels said // operations so the callbacks are not invoked, possibly leaving the work @@ -144,9 +123,31 @@ class NET_EXPORT Backend { virtual int DoomEntriesSince(base::Time initial_time, const CompletionCallback& callback) = 0; - // Returns an iterator which will enumerate all entries of the cache in an - // undefined order. - virtual scoped_ptr<Iterator> CreateIterator() = 0; + // Enumerates the cache. Initialize |iter| to NULL before calling this method + // the first time. That will cause the enumeration to start at the head of + // the cache. For subsequent calls, pass the same |iter| pointer again without + // changing its value. This method returns ERR_FAILED when there are no more + // entries to enumerate. When the entry pointer is no longer needed, its + // Close method should be called. The return value is a net error code. If + // this method returns ERR_IO_PENDING, the |callback| will be invoked when the + // |next_entry| is available. The pointer to receive the |next_entry| must + // remain valid until the operation completes. + // + // NOTE: This method does not modify the last_used field of the entry, and + // therefore it does not impact the eviction ranking of the entry. However, + // an enumeration will go through all entries on the cache only if the cache + // is not modified while the enumeration is taking place. Significantly + // altering the entry pointed by |iter| (for example, deleting the entry) will + // invalidate |iter|. Performing operations on an entry that modify the entry + // may result in loops in the iteration, skipped entries or similar. + virtual int OpenNextEntry(void** iter, Entry** next_entry, + const CompletionCallback& callback) = 0; + + // Releases iter without returning the next entry. Whenever OpenNextEntry() + // returns true, but the caller is not interested in continuing the + // enumeration by calling OpenNextEntry() again, the enumeration must be + // ended by calling this method with iter returned by OpenNextEntry(). + virtual void EndEnumeration(void** iter) = 0; // Return a list of cache statistics. virtual void GetStats( diff --git a/net/disk_cache/disk_cache_test_base.cc b/net/disk_cache/disk_cache_test_base.cc index c3d94e6..d0f9842 100644 --- a/net/disk_cache/disk_cache_test_base.cc +++ b/net/disk_cache/disk_cache_test_base.cc @@ -52,20 +52,6 @@ void DiskCacheTest::TearDown() { base::RunLoop().RunUntilIdle(); } -DiskCacheTestWithCache::TestIterator::TestIterator( - scoped_ptr<disk_cache::Backend::Iterator> iterator) - : iterator_(iterator.Pass()) { -} - -DiskCacheTestWithCache::TestIterator::~TestIterator() {} - -int DiskCacheTestWithCache::TestIterator::OpenNextEntry( - disk_cache::Entry** next_entry) { - net::TestCompletionCallback cb; - int rv = iterator_->OpenNextEntry(next_entry, cb.callback()); - return cb.GetResult(rv); -} - DiskCacheTestWithCache::DiskCacheTestWithCache() : cache_impl_(NULL), simple_cache_impl_(NULL), @@ -167,9 +153,11 @@ int DiskCacheTestWithCache::DoomEntriesSince(const base::Time initial_time) { return cb.GetResult(rv); } -scoped_ptr<DiskCacheTestWithCache::TestIterator> - DiskCacheTestWithCache::CreateIterator() { - return scoped_ptr<TestIterator>(new TestIterator(cache_->CreateIterator())); +int DiskCacheTestWithCache::OpenNextEntry(void** iter, + disk_cache::Entry** next_entry) { + net::TestCompletionCallback cb; + int rv = cache_->OpenNextEntry(iter, next_entry, cb.callback()); + return cb.GetResult(rv); } void DiskCacheTestWithCache::FlushQueueForTest() { diff --git a/net/disk_cache/disk_cache_test_base.h b/net/disk_cache/disk_cache_test_base.h index 225d37f..b724906 100644 --- a/net/disk_cache/disk_cache_test_base.h +++ b/net/disk_cache/disk_cache_test_base.h @@ -11,7 +11,6 @@ #include "base/memory/scoped_ptr.h" #include "base/threading/thread.h" #include "net/base/cache_type.h" -#include "net/disk_cache/disk_cache.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -58,17 +57,6 @@ class DiskCacheTest : public PlatformTest { // Provides basic support for cache related tests. class DiskCacheTestWithCache : public DiskCacheTest { protected: - class TestIterator { - public: - explicit TestIterator(scoped_ptr<disk_cache::Backend::Iterator> iterator); - ~TestIterator(); - - int OpenNextEntry(disk_cache::Entry** next_entry); - - private: - scoped_ptr<disk_cache::Backend::Iterator> iterator_; - }; - DiskCacheTestWithCache(); virtual ~DiskCacheTestWithCache(); @@ -129,7 +117,7 @@ class DiskCacheTestWithCache : public DiskCacheTest { int DoomEntriesBetween(const base::Time initial_time, const base::Time end_time); int DoomEntriesSince(const base::Time initial_time); - scoped_ptr<TestIterator> CreateIterator(); + int OpenNextEntry(void** iter, disk_cache::Entry** next_entry); void FlushQueueForTest(); void RunTaskForTest(const base::Closure& closure); int ReadData(disk_cache::Entry* entry, int index, int offset, diff --git a/net/disk_cache/entry_unittest.cc b/net/disk_cache/entry_unittest.cc index afe93ac..803f98f 100644 --- a/net/disk_cache/entry_unittest.cc +++ b/net/disk_cache/entry_unittest.cc @@ -1617,10 +1617,10 @@ TEST_F(DiskCacheEntryTest, MemoryOnlyEnumerationWithSparseEntries) { parent_entry->Close(); // Perform the enumerations. - scoped_ptr<TestIterator> iter = CreateIterator(); + void* iter = NULL; disk_cache::Entry* entry = NULL; int count = 0; - while (iter->OpenNextEntry(&entry) == net::OK) { + while (OpenNextEntry(&iter, &entry) == net::OK) { ASSERT_TRUE(entry != NULL); ++count; disk_cache::MemEntryImpl* mem_entry = @@ -2217,10 +2217,10 @@ TEST_F(DiskCacheEntryTest, CleanupSparseEntry) { entry->Close(); EXPECT_EQ(4, cache_->GetEntryCount()); - scoped_ptr<TestIterator> iter = CreateIterator(); + void* iter = NULL; int count = 0; std::string child_key[2]; - while (iter->OpenNextEntry(&entry) == net::OK) { + while (OpenNextEntry(&iter, &entry) == net::OK) { ASSERT_TRUE(entry != NULL); // Writing to an entry will alter the LRU list and invalidate the iterator. if (entry->GetKey() != key && count < 2) diff --git a/net/disk_cache/memory/mem_backend_impl.cc b/net/disk_cache/memory/mem_backend_impl.cc index 848ef98..e69c00e 100644 --- a/net/disk_cache/memory/mem_backend_impl.cc +++ b/net/disk_cache/memory/mem_backend_impl.cc @@ -29,8 +29,7 @@ int LowWaterAdjust(int high_water) { namespace disk_cache { MemBackendImpl::MemBackendImpl(net::NetLog* net_log) - : max_size_(0), current_size_(0), net_log_(net_log), weak_factory_(this) { -} + : max_size_(0), current_size_(0), net_log_(net_log) {} MemBackendImpl::~MemBackendImpl() { EntryMap::iterator it = entries_.begin(); @@ -181,40 +180,16 @@ int MemBackendImpl::DoomEntriesSince(const base::Time initial_time, return net::ERR_FAILED; } -class MemBackendImpl::MemIterator : public Backend::Iterator { - public: - explicit MemIterator(base::WeakPtr<MemBackendImpl> backend) - : backend_(backend), current_(NULL) { - } - - virtual int OpenNextEntry(Entry** next_entry, - const CompletionCallback& callback) OVERRIDE { - if (!backend_) - return net::ERR_FAILED; - - MemEntryImpl* node = backend_->rankings_.GetNext(current_); - // We should never return a child entry so iterate until we hit a parent - // entry. - while (node && node->type() != MemEntryImpl::kParentEntry) - node = backend_->rankings_.GetNext(node); - *next_entry = node; - current_ = node; - - if (node) { - node->Open(); - return net::OK; - } - return net::ERR_FAILED; - } +int MemBackendImpl::OpenNextEntry(void** iter, Entry** next_entry, + const CompletionCallback& callback) { + if (OpenNextEntry(iter, next_entry)) + return net::OK; - private: - base::WeakPtr<MemBackendImpl> backend_; - MemEntryImpl* current_; -}; + return net::ERR_FAILED; +} -scoped_ptr<Backend::Iterator> MemBackendImpl::CreateIterator() { - return scoped_ptr<Backend::Iterator>( - new MemIterator(weak_factory_.GetWeakPtr())); +void MemBackendImpl::EndEnumeration(void** iter) { + *iter = NULL; } void MemBackendImpl::OnExternalCacheHit(const std::string& key) { @@ -312,6 +287,23 @@ bool MemBackendImpl::DoomEntriesSince(const Time initial_time) { } } +bool MemBackendImpl::OpenNextEntry(void** iter, Entry** next_entry) { + MemEntryImpl* current = reinterpret_cast<MemEntryImpl*>(*iter); + MemEntryImpl* node = rankings_.GetNext(current); + // We should never return a child entry so iterate until we hit a parent + // entry. + while (node && node->type() != MemEntryImpl::kParentEntry) { + node = rankings_.GetNext(node); + } + *next_entry = node; + *iter = node; + + if (node) + node->Open(); + + return NULL != node; +} + void MemBackendImpl::TrimCache(bool empty) { MemEntryImpl* next = rankings_.GetPrev(NULL); if (!next) diff --git a/net/disk_cache/memory/mem_backend_impl.h b/net/disk_cache/memory/mem_backend_impl.h index 10946c5..5f31be5 100644 --- a/net/disk_cache/memory/mem_backend_impl.h +++ b/net/disk_cache/memory/mem_backend_impl.h @@ -9,7 +9,6 @@ #include "base/compiler_specific.h" #include "base/containers/hash_tables.h" -#include "base/memory/weak_ptr.h" #include "net/disk_cache/disk_cache.h" #include "net/disk_cache/memory/mem_rankings.h" @@ -77,15 +76,14 @@ class NET_EXPORT_PRIVATE MemBackendImpl : public Backend { const CompletionCallback& callback) OVERRIDE; virtual int DoomEntriesSince(base::Time initial_time, const CompletionCallback& callback) OVERRIDE; - virtual scoped_ptr<Iterator> CreateIterator() OVERRIDE; + virtual int OpenNextEntry(void** iter, Entry** next_entry, + const CompletionCallback& callback) OVERRIDE; + virtual void EndEnumeration(void** iter) OVERRIDE; virtual void GetStats( std::vector<std::pair<std::string, std::string> >* stats) OVERRIDE {} virtual void OnExternalCacheHit(const std::string& key) OVERRIDE; private: - class MemIterator; - friend class MemIterator; - typedef base::hash_map<std::string, MemEntryImpl*> EntryMap; // Old Backend interface. @@ -96,6 +94,7 @@ class NET_EXPORT_PRIVATE MemBackendImpl : public Backend { bool DoomEntriesBetween(const base::Time initial_time, const base::Time end_time); bool DoomEntriesSince(const base::Time initial_time); + bool OpenNextEntry(void** iter, Entry** next_entry); // Deletes entries from the cache until the current size is below the limit. // If empty is true, the whole cache will be trimmed, regardless of being in @@ -113,8 +112,6 @@ class NET_EXPORT_PRIVATE MemBackendImpl : public Backend { net::NetLog* net_log_; - base::WeakPtrFactory<MemBackendImpl> weak_factory_; - DISALLOW_COPY_AND_ASSIGN(MemBackendImpl); }; diff --git a/net/disk_cache/simple/simple_backend_impl.cc b/net/disk_cache/simple/simple_backend_impl.cc index e84211b..2e16576 100644 --- a/net/disk_cache/simple/simple_backend_impl.cc +++ b/net/disk_cache/simple/simple_backend_impl.cc @@ -473,78 +473,18 @@ int SimpleBackendImpl::DoomEntriesSince( return DoomEntriesBetween(initial_time, Time(), callback); } -class SimpleBackendImpl::SimpleIterator FINAL : public Iterator { - public: - explicit SimpleIterator(base::WeakPtr<SimpleBackendImpl> backend) - : backend_(backend), - weak_factory_(this) { - } - - // From Backend::Iterator: - virtual int OpenNextEntry(Entry** next_entry, - const CompletionCallback& callback) OVERRIDE { - CompletionCallback open_next_entry_impl = - base::Bind(&SimpleIterator::OpenNextEntryImpl, - weak_factory_.GetWeakPtr(), next_entry, callback); - return backend_->index_->ExecuteWhenReady(open_next_entry_impl); - } - - void OpenNextEntryImpl(Entry** next_entry, - const CompletionCallback& callback, - int index_initialization_error_code) { - if (!backend_) { - callback.Run(net::ERR_FAILED); - return; - } - if (index_initialization_error_code != net::OK) { - callback.Run(index_initialization_error_code); - return; - } - if (!hashes_to_enumerate_) - hashes_to_enumerate_ = backend_->index()->GetAllHashes().Pass(); - - while (!hashes_to_enumerate_->empty()) { - uint64 entry_hash = hashes_to_enumerate_->back(); - hashes_to_enumerate_->pop_back(); - if (backend_->index()->Has(entry_hash)) { - *next_entry = NULL; - CompletionCallback continue_iteration = base::Bind( - &SimpleIterator::CheckIterationReturnValue, - weak_factory_.GetWeakPtr(), - next_entry, - callback); - int error_code_open = backend_->OpenEntryFromHash(entry_hash, - next_entry, - continue_iteration); - if (error_code_open == net::ERR_IO_PENDING) - return; - if (error_code_open != net::ERR_FAILED) { - callback.Run(error_code_open); - return; - } - } - } - callback.Run(net::ERR_FAILED); - } - - void CheckIterationReturnValue(Entry** entry, - const CompletionCallback& callback, - int error_code) { - if (error_code == net::ERR_FAILED) { - OpenNextEntry(entry, callback); - return; - } - callback.Run(error_code); - } - - private: - base::WeakPtr<SimpleBackendImpl> backend_; - scoped_ptr<std::vector<uint64> > hashes_to_enumerate_; - base::WeakPtrFactory<SimpleIterator> weak_factory_; -}; +int SimpleBackendImpl::OpenNextEntry(void** iter, + Entry** next_entry, + const CompletionCallback& callback) { + CompletionCallback get_next_entry = + base::Bind(&SimpleBackendImpl::GetNextEntryInIterator, AsWeakPtr(), iter, + next_entry, callback); + return index_->ExecuteWhenReady(get_next_entry); +} -scoped_ptr<Backend::Iterator> SimpleBackendImpl::CreateIterator() { - return scoped_ptr<Iterator>(new SimpleIterator(AsWeakPtr())); +void SimpleBackendImpl::EndEnumeration(void** iter) { + active_enumerations_.Remove(IteratorToEnumerationId(iter)); + *iter = NULL; } void SimpleBackendImpl::GetStats( @@ -559,6 +499,27 @@ void SimpleBackendImpl::OnExternalCacheHit(const std::string& key) { index_->UseIfExists(simple_util::GetEntryHashKey(key)); } +// static +SimpleBackendImpl::ActiveEnumerationMap::KeyType + SimpleBackendImpl::IteratorToEnumerationId(void** iter) { + COMPILE_ASSERT(sizeof(ptrdiff_t) >= sizeof(*iter), + integer_type_must_fit_ptr_type_for_cast_to_be_reversible); + const ptrdiff_t ptrdiff_enumeration_id = reinterpret_cast<ptrdiff_t>(*iter); + const ActiveEnumerationMap::KeyType enumeration_id = ptrdiff_enumeration_id; + DCHECK_EQ(enumeration_id, ptrdiff_enumeration_id); + return enumeration_id; +} + +// static +void* SimpleBackendImpl::EnumerationIdToIterator( + ActiveEnumerationMap::KeyType enumeration_id) { + const ptrdiff_t ptrdiff_enumeration_id = enumeration_id; + DCHECK_EQ(enumeration_id, ptrdiff_enumeration_id); + COMPILE_ASSERT(sizeof(ptrdiff_t) >= sizeof(void*), + integer_type_must_fit_ptr_type_for_cast_to_be_reversible); + return reinterpret_cast<void*>(ptrdiff_enumeration_id); +} + void SimpleBackendImpl::InitializeIndex(const CompletionCallback& callback, const DiskStatResult& result) { if (result.net_error == net::OK) { @@ -672,6 +633,49 @@ int SimpleBackendImpl::DoomEntryFromHash(uint64 entry_hash, return net::ERR_IO_PENDING; } +void SimpleBackendImpl::GetNextEntryInIterator( + void** iter, + Entry** next_entry, + const CompletionCallback& callback, + int error_code) { + if (error_code != net::OK) { + callback.Run(error_code); + return; + } + std::vector<uint64>* entry_list = NULL; + if (*iter == NULL) { + const ActiveEnumerationMap::KeyType new_enumeration_id = + active_enumerations_.Add( + entry_list = index()->GetAllHashes().release()); + *iter = EnumerationIdToIterator(new_enumeration_id); + } else { + entry_list = active_enumerations_.Lookup(IteratorToEnumerationId(iter)); + } + while (entry_list->size() > 0) { + uint64 entry_hash = entry_list->back(); + entry_list->pop_back(); + if (index()->Has(entry_hash)) { + *next_entry = NULL; + CompletionCallback continue_iteration = base::Bind( + &SimpleBackendImpl::CheckIterationReturnValue, + AsWeakPtr(), + iter, + next_entry, + callback); + int error_code_open = OpenEntryFromHash(entry_hash, + next_entry, + continue_iteration); + if (error_code_open == net::ERR_IO_PENDING) + return; + if (error_code_open != net::ERR_FAILED) { + callback.Run(error_code_open); + return; + } + } + } + callback.Run(net::ERR_FAILED); +} + void SimpleBackendImpl::OnEntryOpenedFromHash( uint64 hash, Entry** entry, @@ -725,6 +729,18 @@ void SimpleBackendImpl::OnEntryOpenedFromKey( callback.Run(final_code); } +void SimpleBackendImpl::CheckIterationReturnValue( + void** iter, + Entry** entry, + const CompletionCallback& callback, + int error_code) { + if (error_code == net::ERR_FAILED) { + OpenNextEntry(iter, entry, callback); + return; + } + callback.Run(error_code); +} + void SimpleBackendImpl::DoomEntriesComplete( scoped_ptr<std::vector<uint64> > entry_hashes, const net::CompletionCallback& callback, diff --git a/net/disk_cache/simple/simple_backend_impl.h b/net/disk_cache/simple/simple_backend_impl.h index 48c422f..907ee5a 100644 --- a/net/disk_cache/simple/simple_backend_impl.h +++ b/net/disk_cache/simple/simple_backend_impl.h @@ -13,6 +13,7 @@ #include "base/compiler_specific.h" #include "base/containers/hash_tables.h" #include "base/files/file_path.h" +#include "base/id_map.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" @@ -34,11 +35,6 @@ namespace disk_cache { // files. // See http://www.chromium.org/developers/design-documents/network-stack/disk-cache/very-simple-backend // -// The SimpleBackendImpl provides safe iteration; mutating entries during -// iteration cannot cause a crash. It is undefined whether entries created or -// destroyed during the iteration will be included in any pre-existing -// iterations. -// // The non-static functions below must be called on the IO thread unless // otherwise stated. @@ -102,17 +98,18 @@ class NET_EXPORT_PRIVATE SimpleBackendImpl : public Backend, const CompletionCallback& callback) OVERRIDE; virtual int DoomEntriesSince(base::Time initial_time, const CompletionCallback& callback) OVERRIDE; - virtual scoped_ptr<Iterator> CreateIterator() OVERRIDE; + virtual int OpenNextEntry(void** iter, Entry** next_entry, + const CompletionCallback& callback) OVERRIDE; + virtual void EndEnumeration(void** iter) OVERRIDE; virtual void GetStats( std::vector<std::pair<std::string, std::string> >* stats) OVERRIDE; virtual void OnExternalCacheHit(const std::string& key) OVERRIDE; private: - class SimpleIterator; - friend class SimpleIterator; - typedef base::hash_map<uint64, SimpleEntryImpl*> EntryMap; + typedef IDMap<std::vector<uint64>, IDMapOwnPointer> ActiveEnumerationMap; + typedef base::Callback<void(base::Time mtime, uint64 max_size, int result)> InitializeIndexCallback; @@ -127,6 +124,17 @@ class NET_EXPORT_PRIVATE SimpleBackendImpl : public Backend, int net_error; }; + // Convert an iterator from OpenNextEntry() to the key type for + // ActiveEnumerationMap. Note it takes a void** argument; this is for safety; + // if it took a void*, that would be type compatible with a void** permitting + // easy calls missing the dereference. + static ActiveEnumerationMap::KeyType IteratorToEnumerationId(void** iter); + + // Convert a key from ActiveEnumerationMap back to a void*, suitable for + // storing in the iterator argument to OpenNextEntry(). + static void* EnumerationIdToIterator( + ActiveEnumerationMap::KeyType enumeration_id); + void InitializeIndex(const CompletionCallback& callback, const DiskStatResult& result); @@ -161,6 +169,14 @@ class NET_EXPORT_PRIVATE SimpleBackendImpl : public Backend, // which is very important to prevent races in DoomEntries() above. int DoomEntryFromHash(uint64 entry_hash, const CompletionCallback & callback); + // Called when the index is initilized to find the next entry in the iterator + // |iter|. If there are no more hashes in the iterator list, net::ERR_FAILED + // is returned. Otherwise, calls OpenEntryFromHash. + void GetNextEntryInIterator(void** iter, + Entry** next_entry, + const CompletionCallback& callback, + int error_code); + // Called when we tried to open an entry with hash alone. When a blank entry // has been created and filled in with information from the disk - based on a // hash alone - this checks that a duplicate active entry was not created @@ -179,6 +195,14 @@ class NET_EXPORT_PRIVATE SimpleBackendImpl : public Backend, const CompletionCallback& callback, int error_code); + // Called at the end of the asynchronous operation triggered by + // OpenEntryFromHash. Makes sure to continue iterating if the open entry was + // not a success. + void CheckIterationReturnValue(void** iter, + Entry** entry, + const CompletionCallback& callback, + int error_code); + // A callback thunk used by DoomEntries to clear the |entries_pending_doom_| // after a mass doom. void DoomEntriesComplete(scoped_ptr<std::vector<uint64> > entry_hashes, @@ -196,6 +220,9 @@ class NET_EXPORT_PRIVATE SimpleBackendImpl : public Backend, EntryMap active_entries_; + // One entry for every enumeration in progress. + ActiveEnumerationMap active_enumerations_; + // The set of all entries which are currently being doomed. To avoid races, // these entries cannot have Doom/Create/Open operations run until the doom // is complete. The base::Closure map target is used to store deferred diff --git a/net/http/mock_http_cache.cc b/net/http/mock_http_cache.cc index cbae9b8..a91b2c1 100644 --- a/net/http/mock_http_cache.cc +++ b/net/http/mock_http_cache.cc @@ -457,16 +457,12 @@ int MockDiskCache::DoomEntriesSince(const base::Time initial_time, return net::ERR_NOT_IMPLEMENTED; } -class MockDiskCache::NotImplementedIterator : public Iterator { - public: - virtual int OpenNextEntry(disk_cache::Entry** next_entry, - const net::CompletionCallback& callback) OVERRIDE { - return net::ERR_NOT_IMPLEMENTED; - } -}; +int MockDiskCache::OpenNextEntry(void** iter, disk_cache::Entry** next_entry, + const net::CompletionCallback& callback) { + return net::ERR_NOT_IMPLEMENTED; +} -scoped_ptr<disk_cache::Backend::Iterator> MockDiskCache::CreateIterator() { - return scoped_ptr<Iterator>(new NotImplementedIterator()); +void MockDiskCache::EndEnumeration(void** iter) { } void MockDiskCache::GetStats( diff --git a/net/http/mock_http_cache.h b/net/http/mock_http_cache.h index ab63b11..5ead727 100644 --- a/net/http/mock_http_cache.h +++ b/net/http/mock_http_cache.h @@ -114,7 +114,9 @@ class MockDiskCache : public disk_cache::Backend { virtual int DoomEntriesSince( base::Time initial_time, const net::CompletionCallback& callback) OVERRIDE; - virtual scoped_ptr<Iterator> CreateIterator() OVERRIDE; + virtual int OpenNextEntry(void** iter, disk_cache::Entry** next_entry, + const net::CompletionCallback& callback) OVERRIDE; + virtual void EndEnumeration(void** iter) OVERRIDE; virtual void GetStats( std::vector<std::pair<std::string, std::string> >* stats) OVERRIDE; virtual void OnExternalCacheHit(const std::string& key) OVERRIDE; @@ -141,7 +143,6 @@ class MockDiskCache : public disk_cache::Backend { private: typedef base::hash_map<std::string, MockDiskEntry*> EntryMap; - class NotImplementedIterator; void CallbackLater(const net::CompletionCallback& callback, int result); diff --git a/net/tools/dump_cache/simple_cache_dumper.cc b/net/tools/dump_cache/simple_cache_dumper.cc index dd5ecbf..56162ca 100644 --- a/net/tools/dump_cache/simple_cache_dumper.cc +++ b/net/tools/dump_cache/simple_cache_dumper.cc @@ -26,6 +26,7 @@ SimpleCacheDumper::SimpleCacheDumper(base::FilePath input_path, output_path_(output_path), writer_(new DiskDumper(output_path)), cache_thread_(new base::Thread("CacheThead")), + iter_(NULL), src_entry_(NULL), dst_entry_(NULL), io_callback_(base::Bind(&SimpleCacheDumper::OnIOComplete, @@ -149,15 +150,15 @@ int SimpleCacheDumper::DoOpenEntry() { DCHECK(!dst_entry_); DCHECK(!src_entry_); state_ = STATE_OPEN_ENTRY_COMPLETE; - if (!iter_) - iter_ = cache_->CreateIterator(); - return iter_->OpenNextEntry(&src_entry_, io_callback_); + return cache_->OpenNextEntry(&iter_, &src_entry_, io_callback_); } int SimpleCacheDumper::DoOpenEntryComplete(int rv) { // ERR_FAILED indicates iteration finished. - if (rv == ERR_FAILED) + if (rv == ERR_FAILED) { + cache_->EndEnumeration(&iter_); return OK; + } if (rv < 0) return rv; diff --git a/net/tools/dump_cache/simple_cache_dumper.h b/net/tools/dump_cache/simple_cache_dumper.h index cc865a3..c95e6a9 100644 --- a/net/tools/dump_cache/simple_cache_dumper.h +++ b/net/tools/dump_cache/simple_cache_dumper.h @@ -9,10 +9,14 @@ #include "base/memory/scoped_ptr.h" #include "base/threading/thread.h" #include "net/base/completion_callback.h" -#include "net/disk_cache/disk_cache.h" class DiskDumper; +namespace disk_cache { +class Backend; +class Entry; +} // namespace disk_cache + namespace net { class IOBufferWithSize; @@ -75,7 +79,7 @@ class SimpleCacheDumper { scoped_ptr<disk_cache::Backend> cache_; scoped_ptr<DiskDumper> writer_; base::Thread* cache_thread_; - scoped_ptr<disk_cache::Backend::Iterator> iter_; + void* iter_; disk_cache::Entry* src_entry_; disk_cache::Entry* dst_entry_; CompletionCallback io_callback_; diff --git a/net/url_request/view_cache_helper.cc b/net/url_request/view_cache_helper.cc index 36d3ae5..346c7cd 100644 --- a/net/url_request/view_cache_helper.cc +++ b/net/url_request/view_cache_helper.cc @@ -45,6 +45,7 @@ ViewCacheHelper::ViewCacheHelper() : context_(NULL), disk_cache_(NULL), entry_(NULL), + iter_(NULL), buf_len_(0), index_(0), data_(NULL), @@ -241,11 +242,9 @@ int ViewCacheHelper::DoGetBackendComplete(int result) { int ViewCacheHelper::DoOpenNextEntry() { next_state_ = STATE_OPEN_NEXT_ENTRY_COMPLETE; - if (!iter_) - iter_ = disk_cache_->CreateIterator(); - return - iter_->OpenNextEntry(&entry_, base::Bind(&ViewCacheHelper::OnIOComplete, - base::Unretained(this))); + return disk_cache_->OpenNextEntry( + &iter_, &entry_, + base::Bind(&ViewCacheHelper::OnIOComplete, base::Unretained(this))); } int ViewCacheHelper::DoOpenNextEntryComplete(int result) { diff --git a/net/url_request/view_cache_helper.h b/net/url_request/view_cache_helper.h index 18db22e..d5a7c42 100644 --- a/net/url_request/view_cache_helper.h +++ b/net/url_request/view_cache_helper.h @@ -11,7 +11,11 @@ #include "net/base/completion_callback.h" #include "net/base/io_buffer.h" #include "net/base/net_export.h" -#include "net/disk_cache/disk_cache.h" + +namespace disk_cache { +class Backend; +class Entry; +} // namespace disk_cache namespace net { @@ -98,7 +102,7 @@ class NET_EXPORT ViewCacheHelper { const URLRequestContext* context_; disk_cache::Backend* disk_cache_; disk_cache::Entry* entry_; - scoped_ptr<disk_cache::Backend::Iterator> iter_; + void* iter_; scoped_refptr<IOBuffer> buf_; int buf_len_; int index_; |