diff options
author | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-15 19:31:51 +0000 |
---|---|---|
committer | rvargas@google.com <rvargas@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-15 19:31:51 +0000 |
commit | ec44a9a1abaf8ffdc001182b0345295081c6b714 (patch) | |
tree | a14fa1aa0cdee98b8257b5845499bf33e5a36394 | |
parent | eb69ca8e12e0d7a7d42ea328a4597475d5198bc7 (diff) | |
download | chromium_src-ec44a9a1abaf8ffdc001182b0345295081c6b714.zip chromium_src-ec44a9a1abaf8ffdc001182b0345295081c6b714.tar.gz chromium_src-ec44a9a1abaf8ffdc001182b0345295081c6b714.tar.bz2 |
Disk cache: Update the disk cache tools and tests to use
the new interface (provide a cache thread and callback).
BUG=26730
TEST=unit tests
Review URL: http://codereview.chromium.org/2739007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@49819 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | net/disk_cache/backend_impl.cc | 54 | ||||
-rw-r--r-- | net/disk_cache/backend_impl.h | 14 | ||||
-rw-r--r-- | net/disk_cache/backend_unittest.cc | 125 | ||||
-rw-r--r-- | net/disk_cache/disk_cache.h | 21 | ||||
-rw-r--r-- | net/disk_cache/disk_cache_perftest.cc | 26 | ||||
-rw-r--r-- | net/disk_cache/disk_cache_test_base.cc | 25 | ||||
-rw-r--r-- | net/disk_cache/disk_cache_test_base.h | 8 | ||||
-rw-r--r-- | net/disk_cache/disk_cache_test_util.cc | 6 | ||||
-rw-r--r-- | net/disk_cache/mem_backend_impl.cc | 7 | ||||
-rw-r--r-- | net/disk_cache/mem_backend_impl.h | 7 | ||||
-rw-r--r-- | net/disk_cache/stress_cache.cc | 34 | ||||
-rw-r--r-- | net/tools/crash_cache/crash_cache.cc | 114 | ||||
-rw-r--r-- | net/tools/dump_cache/cache_dumper.cc | 30 | ||||
-rw-r--r-- | net/tools/dump_cache/cache_dumper.h | 33 | ||||
-rw-r--r-- | net/tools/dump_cache/upgrade.cc | 101 |
15 files changed, 414 insertions, 191 deletions
diff --git a/net/disk_cache/backend_impl.cc b/net/disk_cache/backend_impl.cc index edd5c59..8fa56f0 100644 --- a/net/disk_cache/backend_impl.cc +++ b/net/disk_cache/backend_impl.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 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. @@ -20,6 +20,7 @@ #include "net/disk_cache/errors.h" #include "net/disk_cache/hash.h" #include "net/disk_cache/file.h" +#include "net/disk_cache/mem_backend_impl.h" // This has to be defined before including histogram_macros.h from this file. #define NET_DISK_CACHE_BACKEND_IMPL_CC_ @@ -167,20 +168,18 @@ void SetFieldTrialInfo(int size_group) { namespace disk_cache { -Backend* CreateCacheBackend(const FilePath& full_path, bool force, - int max_bytes, net::CacheType type) { - // Create a backend without extra flags. - return BackendImpl::CreateBackend(full_path, force, max_bytes, type, kNone); -} - int CreateCacheBackend(net::CacheType type, const FilePath& path, int max_bytes, bool force, base::MessageLoopProxy* thread, Backend** backend, CompletionCallback* callback) { - if (type == net::MEMORY_CACHE) - *backend = CreateInMemoryCacheBackend(max_bytes); - else - *backend = BackendImpl::CreateBackend(path, force, max_bytes, type, kNone); - return *backend ? net::OK : net::ERR_FAILED; + DCHECK(callback); + if (type == net::MEMORY_CACHE) { + *backend = MemBackendImpl::CreateBackend(max_bytes); + return *backend ? net::OK : net::ERR_FAILED; + } + DCHECK(thread); + + return BackendImpl::CreateBackend(path, force, max_bytes, type, kNone, thread, + backend, callback); } // Returns the preferred maximum number of bytes for the cache given the @@ -224,35 +223,42 @@ int PreferedCacheSize(int64 available) { // desired path) cannot be created. // // Static. -Backend* BackendImpl::CreateBackend(const FilePath& full_path, bool force, - int max_bytes, net::CacheType type, - BackendFlags flags) { - BackendImpl* cache = new BackendImpl(full_path); +int BackendImpl::CreateBackend(const FilePath& full_path, bool force, + int max_bytes, net::CacheType type, + uint32 flags, base::MessageLoopProxy* thread, + Backend** backend, + CompletionCallback* callback) { + BackendImpl* cache = new BackendImpl(full_path, thread); cache->SetMaxSize(max_bytes); cache->SetType(type); cache->SetFlags(flags); - if (cache->Init()) - return cache; + if (cache->Init()) { + *backend = cache; + return net::OK; + } + *backend = NULL; delete cache; if (!force) - return NULL; + return net::ERR_FAILED; if (!DelayedCacheCleanup(full_path)) - return NULL; + return net::ERR_FAILED; // The worker thread will start deleting files soon, but the original folder // is not there anymore... let's create a new set of files. - cache = new BackendImpl(full_path); + cache = new BackendImpl(full_path, thread); cache->SetMaxSize(max_bytes); cache->SetType(type); cache->SetFlags(flags); - if (cache->Init()) - return cache; + if (cache->Init()) { + *backend = cache; + return net::OK; + } delete cache; LOG(ERROR) << "Unable to create cache"; - return NULL; + return net::ERR_FAILED; } bool BackendImpl::Init() { diff --git a/net/disk_cache/backend_impl.h b/net/disk_cache/backend_impl.h index 58d81eb..aa87a63 100644 --- a/net/disk_cache/backend_impl.h +++ b/net/disk_cache/backend_impl.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 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. @@ -35,14 +35,15 @@ enum BackendFlags { class BackendImpl : public Backend { friend class Eviction; public: - explicit BackendImpl(const FilePath& path) + BackendImpl(const FilePath& path, base::MessageLoopProxy* cache_thread) : path_(path), block_files_(path), mask_(0), max_size_(0), cache_type_(net::DISK_CACHE), uma_report_(0), user_flags_(0), init_(false), restarted_(false), unit_test_(false), read_only_(false), new_eviction_(false), first_timer_(true), ALLOW_THIS_IN_INITIALIZER_LIST(factory_(this)) {} // mask can be used to limit the usable size of the hash table, for testing. - BackendImpl(const FilePath& path, uint32 mask) + BackendImpl(const FilePath& path, uint32 mask, + base::MessageLoopProxy* cache_thread) : path_(path), block_files_(path), mask_(mask), max_size_(0), cache_type_(net::DISK_CACHE), uma_report_(0), user_flags_(kMask), init_(false), restarted_(false), unit_test_(false), read_only_(false), @@ -52,9 +53,10 @@ class BackendImpl : public Backend { // Returns a new backend with the desired flags. See the declaration of // CreateCacheBackend(). - static Backend* CreateBackend(const FilePath& full_path, bool force, - int max_bytes, net::CacheType type, - BackendFlags flags); + static int CreateBackend(const FilePath& full_path, bool force, + int max_bytes, net::CacheType type, + uint32 flags, base::MessageLoopProxy* thread, + Backend** backend, CompletionCallback* callback); // Performs general initialization for this current instance of the cache. bool Init(); diff --git a/net/disk_cache/backend_unittest.cc b/net/disk_cache/backend_unittest.cc index 41c8069..c659088 100644 --- a/net/disk_cache/backend_unittest.cc +++ b/net/disk_cache/backend_unittest.cc @@ -7,6 +7,7 @@ #include "base/path_service.h" #include "base/platform_thread.h" #include "base/string_util.h" +#include "base/thread.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" #include "net/base/test_completion_callback.h" @@ -15,6 +16,7 @@ #include "net/disk_cache/disk_cache_test_util.h" #include "net/disk_cache/histogram_macros.h" #include "net/disk_cache/mapped_file.h" +#include "net/disk_cache/mem_backend_impl.h" #include "testing/gtest/include/gtest/gtest.h" using base::Time; @@ -187,6 +189,49 @@ TEST_F(DiskCacheBackendTest, MemoryOnlyKeying) { BackendKeying(); } +TEST_F(DiskCacheTest, CreateBackend) { + TestCompletionCallback cb; + + { + FilePath path = GetCacheFilePath(); + ASSERT_TRUE(DeleteCache(path)); + base::Thread cache_thread("CacheThread"); + ASSERT_TRUE(cache_thread.StartWithOptions( + base::Thread::Options(MessageLoop::TYPE_IO, 0))); + + // Test the private factory methods. + disk_cache::Backend* cache = NULL; + int rv = disk_cache::BackendImpl::CreateBackend( + path, false, 0, net::DISK_CACHE, disk_cache::kNoRandom, + cache_thread.message_loop_proxy(), &cache, &cb); + ASSERT_EQ(net::OK, cb.GetResult(rv)); + ASSERT_TRUE(cache); + delete cache; + + cache = disk_cache::MemBackendImpl::CreateBackend(0); + ASSERT_TRUE(cache); + delete cache; + cache = NULL; + + // Now test the public API. + rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, path, 0, false, + cache_thread.message_loop_proxy(), + &cache, &cb); + ASSERT_EQ(net::OK, cb.GetResult(rv)); + ASSERT_TRUE(cache); + delete cache; + cache = NULL; + + rv = disk_cache::CreateCacheBackend(net::MEMORY_CACHE, FilePath(), 0, false, + NULL, &cache, &cb); + ASSERT_EQ(net::OK, cb.GetResult(rv)); + ASSERT_TRUE(cache); + delete cache; + } + + MessageLoop::current()->RunAllPending(); +} + TEST_F(DiskCacheBackendTest, ExternalFiles) { InitCache(); // First, lets create a file on the folder. @@ -215,12 +260,19 @@ TEST_F(DiskCacheTest, ShutdownWithPendingIO) { { FilePath path = GetCacheFilePath(); ASSERT_TRUE(DeleteCache(path)); + base::Thread cache_thread("CacheThread"); + ASSERT_TRUE(cache_thread.StartWithOptions( + base::Thread::Options(MessageLoop::TYPE_IO, 0))); - disk_cache::Backend* cache = - disk_cache::CreateCacheBackend(path, false, 0, net::DISK_CACHE); + disk_cache::Backend* cache; + int rv = disk_cache::BackendImpl::CreateBackend( + path, false, 0, net::DISK_CACHE, disk_cache::kNoRandom, + cache_thread.message_loop_proxy(), &cache, &callback); + ASSERT_EQ(net::OK, callback.GetResult(rv)); disk_cache::Entry* entry; - ASSERT_TRUE(cache->CreateEntry("some key", &entry)); + rv = cache->CreateEntry("some key", &entry, &callback); + ASSERT_EQ(net::OK, callback.GetResult(rv)); const int kSize = 25000; scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kSize); @@ -247,11 +299,20 @@ TEST_F(DiskCacheTest, TruncatedIndex) { ASSERT_TRUE(DeleteCache(path)); FilePath index = path.AppendASCII("index"); ASSERT_EQ(5, file_util::WriteFile(index, "hello", 5)); - scoped_ptr<disk_cache::Backend> backend; - backend.reset(disk_cache::BackendImpl::CreateBackend(path, false, 0, - net::DISK_CACHE, - disk_cache::kNone)); - ASSERT_TRUE(backend.get() == NULL); + + base::Thread cache_thread("CacheThread"); + ASSERT_TRUE(cache_thread.StartWithOptions( + base::Thread::Options(MessageLoop::TYPE_IO, 0))); + TestCompletionCallback cb; + + disk_cache::Backend* backend = NULL; + int rv = disk_cache::BackendImpl::CreateBackend( + path, false, 0, net::DISK_CACHE, disk_cache::kNone, + cache_thread.message_loop_proxy(), &backend, &cb); + ASSERT_NE(net::OK, cb.GetResult(rv)); + + ASSERT_TRUE(backend == NULL); + delete backend; } void DiskCacheBackendTest::BackendSetSize() { @@ -1088,20 +1149,26 @@ TEST_F(DiskCacheBackendTest, NewEvictionRecoverRemove) { } // Tests dealing with cache files that cannot be recovered. -TEST_F(DiskCacheTest, Backend_DeleteOld) { +TEST_F(DiskCacheTest, DeleteOld) { ASSERT_TRUE(CopyTestCache(L"wrong_version")); FilePath path = GetCacheFilePath(); - scoped_ptr<disk_cache::Backend> cache; - cache.reset(disk_cache::CreateCacheBackend(path, true, 0, net::DISK_CACHE)); + base::Thread cache_thread("CacheThread"); + ASSERT_TRUE(cache_thread.StartWithOptions( + base::Thread::Options(MessageLoop::TYPE_IO, 0))); + TestCompletionCallback cb; + + disk_cache::Backend* cache; + int rv = disk_cache::BackendImpl::CreateBackend( + path, true, 0, net::DISK_CACHE, disk_cache::kNoRandom, + cache_thread.message_loop_proxy(), &cache, &cb); + ASSERT_EQ(net::OK, cb.GetResult(rv)); MessageLoopHelper helper; - ASSERT_TRUE(NULL != cache.get()); + ASSERT_TRUE(NULL != cache); ASSERT_EQ(0, cache->GetEntryCount()); - // Wait for a callback that never comes... about 2 secs :). The message loop - // has to run to allow destruction of the cleaner thread. - helper.WaitUntilCacheIoFinished(1); + delete cache; } // We want to be able to deal with messed up entries on disk. @@ -1443,7 +1510,8 @@ TEST_F(DiskCacheTest, Backend_UsageStats) { FilePath path = GetCacheFilePath(); ASSERT_TRUE(DeleteCache(path)); scoped_ptr<disk_cache::BackendImpl> cache; - cache.reset(new disk_cache::BackendImpl(path)); + cache.reset(new disk_cache::BackendImpl( + path, base::MessageLoopProxy::CreateForCurrentThread())); ASSERT_TRUE(NULL != cache.get()); cache->SetUnitTestMode(); ASSERT_TRUE(cache->Init()); @@ -1546,23 +1614,34 @@ TEST_F(DiskCacheTest, MultipleInstances) { ScopedTestCache store1; ScopedTestCache store2("cache_test2"); ScopedTestCache store3("cache_test3"); + base::Thread cache_thread("CacheThread"); + ASSERT_TRUE(cache_thread.StartWithOptions( + base::Thread::Options(MessageLoop::TYPE_IO, 0))); + TestCompletionCallback cb; const int kNumberOfCaches = 2; - scoped_ptr<disk_cache::Backend> cache[kNumberOfCaches]; + disk_cache::Backend* cache[kNumberOfCaches]; - cache[0].reset(disk_cache::CreateCacheBackend(store1.path(), false, 0, - net::DISK_CACHE)); - cache[1].reset(disk_cache::CreateCacheBackend(store2.path(), false, 0, - net::MEDIA_CACHE)); + int rv = disk_cache::BackendImpl::CreateBackend( + store1.path(), false, 0, net::DISK_CACHE, disk_cache::kNone, + cache_thread.message_loop_proxy(), &cache[0], &cb); + ASSERT_EQ(net::OK, cb.GetResult(rv)); + rv = disk_cache::BackendImpl::CreateBackend( + store2.path(), false, 0, net::MEDIA_CACHE, disk_cache::kNone, + cache_thread.message_loop_proxy(), &cache[1], &cb); + ASSERT_EQ(net::OK, cb.GetResult(rv)); - ASSERT_TRUE(cache[0].get() != NULL && cache[1].get() != NULL); + ASSERT_TRUE(cache[0] != NULL && cache[1] != NULL); std::string key("the first key"); disk_cache::Entry* entry; for (int i = 0; i < kNumberOfCaches; i++) { - ASSERT_TRUE(cache[i]->CreateEntry(key, &entry)); + rv = cache[i]->CreateEntry(key, &entry, &cb); + ASSERT_EQ(net::OK, cb.GetResult(rv)); entry->Close(); } + delete cache[0]; + delete cache[1]; } // Test the six regions of the curve that determines the max cache size. diff --git a/net/disk_cache/disk_cache.h b/net/disk_cache/disk_cache.h index 36151ad..2cddf6f 100644 --- a/net/disk_cache/disk_cache.h +++ b/net/disk_cache/disk_cache.h @@ -32,27 +32,6 @@ class Entry; class Backend; typedef net::CompletionCallback CompletionCallback; -// Returns an instance of the Backend. path points to a folder where -// the cached data will be stored. This cache instance must be the only object -// that will be reading or writing files to that folder. The returned object -// should be deleted when not needed anymore. If force is true, and there is -// a problem with the cache initialization, the files will be deleted and a -// new set will be created. max_bytes is the maximum size the cache can grow to. -// If zero is passed in as max_bytes, the cache will determine the value to use -// based on the available disk space. The returned pointer can be NULL if a -// fatal error is found. -// Note: This function is deprecated. -Backend* CreateCacheBackend(const FilePath& path, bool force, - int max_bytes, net::CacheType type); - -// Returns an instance of a Backend implemented only in memory. The returned -// object should be deleted when not needed anymore. max_bytes is the maximum -// size the cache can grow to. If zero is passed in as max_bytes, the cache will -// determine the value to use based on the available memory. The returned -// pointer can be NULL if a fatal error is found. -// Note: This function is deprecated. -Backend* CreateInMemoryCacheBackend(int max_bytes); - // Returns an instance of a Backend of the given |type|. |path| points to a // folder where the cached data will be stored (if appropriate). This cache // instance must be the only object that will be reading or writing files to diff --git a/net/disk_cache/disk_cache_perftest.cc b/net/disk_cache/disk_cache_perftest.cc index 4064341..6e0ca8a 100644 --- a/net/disk_cache/disk_cache_perftest.cc +++ b/net/disk_cache/disk_cache_perftest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 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,10 +9,12 @@ #include "base/file_util.h" #include "base/perftimer.h" #include "base/string_util.h" +#include "base/thread.h" #include "base/test/test_file_util.h" #include "base/timer.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" +#include "net/base/test_completion_callback.h" #include "net/disk_cache/block_files.h" #include "net/disk_cache/disk_cache.h" #include "net/disk_cache/disk_cache_test_util.h" @@ -154,11 +156,18 @@ TEST_F(DiskCacheTest, Hash) { TEST_F(DiskCacheTest, CacheBackendPerformance) { MessageLoopForIO message_loop; + base::Thread cache_thread("CacheThread"); + ASSERT_TRUE(cache_thread.StartWithOptions( + base::Thread::Options(MessageLoop::TYPE_IO, 0))); + ScopedTestCache test_cache; - disk_cache::Backend* cache = - disk_cache::CreateCacheBackend(test_cache.path(), false, 0, - net::DISK_CACHE); - ASSERT_TRUE(NULL != cache); + TestCompletionCallback cb; + disk_cache::Backend* cache; + int rv = disk_cache::CreateCacheBackend( + net::DISK_CACHE, test_cache.path(), 0, false, + cache_thread.message_loop_proxy(), &cache, &cb); + + ASSERT_EQ(net::OK, cb.GetResult(rv)); int seed = static_cast<int>(Time::Now().ToInternalValue()); srand(seed); @@ -183,9 +192,10 @@ TEST_F(DiskCacheTest, CacheBackendPerformance) { ASSERT_TRUE(file_util::EvictFileFromSystemCache( test_cache.path().AppendASCII("data_3"))); - cache = disk_cache::CreateCacheBackend(test_cache.path(), false, 0, - net::DISK_CACHE); - ASSERT_TRUE(NULL != cache); + rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, test_cache.path(), 0, + false, cache_thread.message_loop_proxy(), + &cache, &cb); + ASSERT_EQ(net::OK, cb.GetResult(rv)); ret = TimeRead(num_entries, cache, entries, true); EXPECT_EQ(ret, g_cache_tests_received); diff --git a/net/disk_cache/disk_cache_test_base.cc b/net/disk_cache/disk_cache_test_base.cc index 2738674..7b0cc8e 100644 --- a/net/disk_cache/disk_cache_test_base.cc +++ b/net/disk_cache/disk_cache_test_base.cc @@ -38,7 +38,7 @@ void DiskCacheTestWithCache::InitCache() { void DiskCacheTestWithCache::InitMemoryCache() { if (!implementation_) { - cache_ = disk_cache::CreateInMemoryCacheBackend(size_); + cache_ = disk_cache::MemBackendImpl::CreateBackend(size_); return; } @@ -57,19 +57,30 @@ void DiskCacheTestWithCache::InitDiskCache() { if (first_cleanup_) ASSERT_TRUE(DeleteCache(path)); + if (!cache_thread_.IsRunning()) { + EXPECT_TRUE(cache_thread_.StartWithOptions( + base::Thread::Options(MessageLoop::TYPE_IO, 0))); + } + ASSERT_TRUE(cache_thread_.message_loop() != NULL); + if (implementation_) return InitDiskCacheImpl(path); - cache_ = disk_cache::BackendImpl::CreateBackend(path, force_creation_, size_, - net::DISK_CACHE, - disk_cache::kNoRandom); + TestCompletionCallback cb; + int rv = disk_cache::BackendImpl::CreateBackend( + path, force_creation_, size_, net::DISK_CACHE, + disk_cache::kNoRandom, cache_thread_.message_loop_proxy(), + &cache_, &cb); + ASSERT_EQ(net::OK, cb.GetResult(rv)); } void DiskCacheTestWithCache::InitDiskCacheImpl(const FilePath& path) { if (mask_) - cache_impl_ = new disk_cache::BackendImpl(path, mask_); + cache_impl_ = new disk_cache::BackendImpl( + path, mask_, cache_thread_.message_loop_proxy()); else - cache_impl_ = new disk_cache::BackendImpl(path); + cache_impl_ = new disk_cache::BackendImpl( + path, cache_thread_.message_loop_proxy()); cache_ = cache_impl_; ASSERT_TRUE(NULL != cache_); @@ -87,6 +98,8 @@ void DiskCacheTestWithCache::InitDiskCacheImpl(const FilePath& path) { void DiskCacheTestWithCache::TearDown() { MessageLoop::current()->RunAllPending(); delete cache_; + if (cache_thread_.IsRunning()) + cache_thread_.Stop(); if (!memory_only_ && integrity_) { FilePath path = GetCacheFilePath(); diff --git a/net/disk_cache/disk_cache_test_base.h b/net/disk_cache/disk_cache_test_base.h index 0878a38..f3c8040 100644 --- a/net/disk_cache/disk_cache_test_base.h +++ b/net/disk_cache/disk_cache_test_base.h @@ -6,7 +6,7 @@ #define NET_DISK_CACHE_DISK_CACHE_TEST_BASE_H_ #include "base/basictypes.h" -#include "base/time.h" +#include "base/thread.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" @@ -35,7 +35,8 @@ class DiskCacheTestWithCache : public DiskCacheTest { DiskCacheTestWithCache() : cache_(NULL), cache_impl_(NULL), mem_cache_(NULL), mask_(0), size_(0), memory_only_(false), implementation_(false), force_creation_(false), - new_eviction_(false), first_cleanup_(true), integrity_(true) {} + new_eviction_(false), first_cleanup_(true), integrity_(true), + cache_thread_("CacheThread") {} void InitCache(); virtual void TearDown(); @@ -105,6 +106,9 @@ class DiskCacheTestWithCache : public DiskCacheTest { void InitMemoryCache(); void InitDiskCache(); void InitDiskCacheImpl(const FilePath& path); + + base::Thread cache_thread_; + DISALLOW_COPY_AND_ASSIGN(DiskCacheTestWithCache); }; #endif // NET_DISK_CACHE_DISK_CACHE_TEST_BASE_H_ diff --git a/net/disk_cache/disk_cache_test_util.cc b/net/disk_cache/disk_cache_test_util.cc index 36d28d2..480ba1d 100644 --- a/net/disk_cache/disk_cache_test_util.cc +++ b/net/disk_cache/disk_cache_test_util.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 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. @@ -6,6 +6,7 @@ #include "base/logging.h" #include "base/file_util.h" +#include "base/message_loop_proxy.h" #include "base/path_service.h" #include "net/disk_cache/backend_impl.h" #include "net/disk_cache/cache_util.h" @@ -77,7 +78,8 @@ bool DeleteCache(const FilePath& path) { } bool CheckCacheIntegrity(const FilePath& path, bool new_eviction) { - scoped_ptr<disk_cache::BackendImpl> cache(new disk_cache::BackendImpl(path)); + scoped_ptr<disk_cache::BackendImpl> cache(new disk_cache::BackendImpl( + path, base::MessageLoopProxy::CreateForCurrentThread())); if (!cache.get()) return false; if (new_eviction) diff --git a/net/disk_cache/mem_backend_impl.cc b/net/disk_cache/mem_backend_impl.cc index 875efdc..fe57d7d 100644 --- a/net/disk_cache/mem_backend_impl.cc +++ b/net/disk_cache/mem_backend_impl.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 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. @@ -28,7 +28,8 @@ int LowWaterAdjust(int high_water) { namespace disk_cache { -Backend* CreateInMemoryCacheBackend(int max_bytes) { +// Static. +Backend* MemBackendImpl::CreateBackend(int max_bytes) { MemBackendImpl* cache = new MemBackendImpl(); cache->SetMaxSize(max_bytes); if (cache->Init()) @@ -39,8 +40,6 @@ Backend* CreateInMemoryCacheBackend(int max_bytes) { return NULL; } -// ------------------------------------------------------------------------ - bool MemBackendImpl::Init() { if (max_size_) return true; diff --git a/net/disk_cache/mem_backend_impl.h b/net/disk_cache/mem_backend_impl.h index e687410..2072a56 100644 --- a/net/disk_cache/mem_backend_impl.h +++ b/net/disk_cache/mem_backend_impl.h @@ -23,6 +23,13 @@ class MemBackendImpl : public Backend { MemBackendImpl() : max_size_(0), current_size_(0) {} ~MemBackendImpl(); + // Returns an instance of a Backend implemented only in memory. The returned + // object should be deleted when not needed anymore. max_bytes is the maximum + // size the cache can grow to. If zero is passed in as max_bytes, the cache + // will determine the value to use based on the available memory. The returned + // pointer can be NULL if a fatal error is found. + static Backend* CreateBackend(int max_bytes); + // Performs general initialization for this current instance of the cache. bool Init(); diff --git a/net/disk_cache/stress_cache.cc b/net/disk_cache/stress_cache.cc index 3619a5f..f5c7880 100644 --- a/net/disk_cache/stress_cache.cc +++ b/net/disk_cache/stress_cache.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 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. @@ -24,6 +24,8 @@ #include "base/process_util.h" #include "base/string_util.h" #include "base/thread.h" +#include "net/base/net_errors.h" +#include "net/base/test_completion_callback.h" #include "net/base/io_buffer.h" #include "net/disk_cache/backend_impl.h" #include "net/disk_cache/disk_cache.h" @@ -77,11 +79,20 @@ int MasterCode() { void StressTheCache(int iteration) { int cache_size = 0x800000; // 8MB FilePath path = GetCacheFilePath().AppendASCII("_stress"); - disk_cache::BackendImpl* cache = new disk_cache::BackendImpl(path); - cache->SetFlags(disk_cache::kNoLoadProtection | disk_cache::kNoRandom); - cache->SetMaxSize(cache_size); - cache->SetType(net::DISK_CACHE); - if (!cache->Init()) { + + base::Thread cache_thread("CacheThread"); + if (!cache_thread.StartWithOptions( + base::Thread::Options(MessageLoop::TYPE_IO, 0))) + return; + + TestCompletionCallback cb; + disk_cache::Backend* cache; + int rv = disk_cache::BackendImpl::CreateBackend( + path, false, cache_size, net::DISK_CACHE, + disk_cache::kNoLoadProtection | disk_cache::kNoRandom, + cache_thread.message_loop_proxy(), &cache, &cb); + + if (cb.GetResult(rv) != net::OK) { printf("Unable to initialize cache.\n"); return; } @@ -111,12 +122,15 @@ void StressTheCache(int iteration) { if (entries[slot]) entries[slot]->Close(); - if (!cache->OpenEntry(keys[key], &entries[slot])) - CHECK(cache->CreateEntry(keys[key], &entries[slot])); + rv = cache->OpenEntry(keys[key], &entries[slot], &cb); + if (cb.GetResult(rv) != net::OK) { + rv = cache->CreateEntry(keys[key], &entries[slot], &cb); + CHECK_EQ(net::OK, cb.GetResult(rv)); + } base::snprintf(buffer->data(), kSize, "%d %d", iteration, i); - CHECK_EQ(kSize, - entries[slot]->WriteData(0, 0, buffer, kSize, NULL, false)); + rv = entries[slot]->WriteData(0, 0, buffer, kSize, &cb, false); + CHECK_EQ(kSize, cb.GetResult(rv)); if (rand() % 100 > 80) { key = rand() % kNumKeys; diff --git a/net/tools/crash_cache/crash_cache.cc b/net/tools/crash_cache/crash_cache.cc index 4686d13..a26c873 100644 --- a/net/tools/crash_cache/crash_cache.cc +++ b/net/tools/crash_cache/crash_cache.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2010 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. @@ -17,7 +17,9 @@ #include "base/path_service.h" #include "base/process_util.h" #include "base/string_util.h" - +#include "base/thread.h" +#include "net/base/net_errors.h" +#include "net/base/test_completion_callback.h" #include "net/disk_cache/backend_impl.h" #include "net/disk_cache/disk_cache.h" #include "net/disk_cache/disk_cache_test_util.h" @@ -117,10 +119,14 @@ bool CreateTargetFolder(const FilePath& path, RankCrashes action, } // Generates the files for an empty and one item cache. -int SimpleInsert(const FilePath& path, RankCrashes action) { - disk_cache::Backend* cache = disk_cache::CreateCacheBackend(path, false, 0, - net::DISK_CACHE); - if (!cache || cache->GetEntryCount()) +int SimpleInsert(const FilePath& path, RankCrashes action, + base::Thread* cache_thread) { + TestCompletionCallback cb; + disk_cache::Backend* cache; + int rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, path, 0, false, + cache_thread->message_loop_proxy(), + &cache, &cb); + if (cb.GetResult(rv) != net::OK || cache->GetEntryCount()) return GENERIC; const char* test_name = "some other key"; @@ -131,7 +137,8 @@ int SimpleInsert(const FilePath& path, RankCrashes action) { } disk_cache::Entry* entry; - if (!cache->CreateEntry(test_name, &entry)) + rv = cache->CreateEntry(test_name, &entry, &cb); + if (cb.GetResult(rv) != net::OK) return GENERIC; entry->Close(); @@ -140,36 +147,44 @@ int SimpleInsert(const FilePath& path, RankCrashes action) { g_rankings_crash = action; test_name = kCrashEntryName; - if (!cache->CreateEntry(test_name, &entry)) + rv = cache->CreateEntry(test_name, &entry, &cb); + if (cb.GetResult(rv) != net::OK) return GENERIC; return NOT_REACHED; } // Generates the files for a one item cache, and removing the head. -int SimpleRemove(const FilePath& path, RankCrashes action) { +int SimpleRemove(const FilePath& path, RankCrashes action, + base::Thread* cache_thread) { DCHECK(action >= disk_cache::REMOVE_ONE_1); DCHECK(action <= disk_cache::REMOVE_TAIL_3); - disk_cache::Backend* cache = disk_cache::CreateCacheBackend(path, false, 0, - net::DISK_CACHE); - if (!cache || cache->GetEntryCount()) + TestCompletionCallback cb; + disk_cache::Backend* cache; + int rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, path, 0, false, + cache_thread->message_loop_proxy(), + &cache, &cb); + if (cb.GetResult(rv) != net::OK || cache->GetEntryCount()) return GENERIC; disk_cache::Entry* entry; - if (!cache->CreateEntry(kCrashEntryName, &entry)) + rv = cache->CreateEntry(kCrashEntryName, &entry, &cb); + if (cb.GetResult(rv) != net::OK) return GENERIC; entry->Close(); if (action >= disk_cache::REMOVE_TAIL_1) { - if (!cache->CreateEntry("some other key", &entry)) + rv = cache->CreateEntry("some other key", &entry, &cb); + if (cb.GetResult(rv) != net::OK) return GENERIC; entry->Close(); } - if (!cache->OpenEntry(kCrashEntryName, &entry)) + rv = cache->OpenEntry(kCrashEntryName, &entry, &cb); + if (cb.GetResult(rv) != net::OK) return GENERIC; g_rankings_crash = action; @@ -179,26 +194,33 @@ int SimpleRemove(const FilePath& path, RankCrashes action) { return NOT_REACHED; } -int HeadRemove(const FilePath& path, RankCrashes action) { +int HeadRemove(const FilePath& path, RankCrashes action, + base::Thread* cache_thread) { DCHECK(action >= disk_cache::REMOVE_HEAD_1); DCHECK(action <= disk_cache::REMOVE_HEAD_4); - disk_cache::Backend* cache = disk_cache::CreateCacheBackend(path, false, 0, - net::DISK_CACHE); - if (!cache || cache->GetEntryCount()) + TestCompletionCallback cb; + disk_cache::Backend* cache; + int rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, path, 0, false, + cache_thread->message_loop_proxy(), + &cache, &cb); + if (cb.GetResult(rv) != net::OK || cache->GetEntryCount()) return GENERIC; disk_cache::Entry* entry; - if (!cache->CreateEntry("some other key", &entry)) + rv = cache->CreateEntry("some other key", &entry, &cb); + if (cb.GetResult(rv) != net::OK) return GENERIC; entry->Close(); - if (!cache->CreateEntry(kCrashEntryName, &entry)) + rv = cache->CreateEntry(kCrashEntryName, &entry, &cb); + if (cb.GetResult(rv) != net::OK) return GENERIC; entry->Close(); - if (!cache->OpenEntry(kCrashEntryName, &entry)) + rv = cache->OpenEntry(kCrashEntryName, &entry, &cb); + if (cb.GetResult(rv) != net::OK) return GENERIC; g_rankings_crash = action; @@ -209,27 +231,34 @@ int HeadRemove(const FilePath& path, RankCrashes action) { } // Generates the files for insertion and removals on heavy loaded caches. -int LoadOperations(const FilePath& path, RankCrashes action) { +int LoadOperations(const FilePath& path, RankCrashes action, + base::Thread* cache_thread) { DCHECK(action >= disk_cache::INSERT_LOAD_1); - // Work with a tiny index table (16 entries) - disk_cache::BackendImpl* cache = - new disk_cache::BackendImpl(path, 0xf); - if (!cache || !cache->SetMaxSize(0x100000) || !cache->Init() || - cache->GetEntryCount()) + // Work with a tiny index table (16 entries). + disk_cache::BackendImpl* cache = new disk_cache::BackendImpl( + path, 0xf, cache_thread->message_loop_proxy()); + if (!cache || !cache->SetMaxSize(0x100000)) + return GENERIC; + + if (!cache->Init() || cache->GetEntryCount()) return GENERIC; int seed = static_cast<int>(Time::Now().ToInternalValue()); srand(seed); + TestCompletionCallback cb; + int rv; disk_cache::Entry* entry; for (int i = 0; i < 100; i++) { std::string key = GenerateKey(true); - if (!cache->CreateEntry(key, &entry)) + rv = cache->CreateEntry(key, &entry, &cb); + if (cb.GetResult(rv) != net::OK) return GENERIC; entry->Close(); if (50 == i && action >= disk_cache::REMOVE_LOAD_1) { - if (!cache->CreateEntry(kCrashEntryName, &entry)) + rv = cache->CreateEntry(kCrashEntryName, &entry, &cb); + if (cb.GetResult(rv) != net::OK) return GENERIC; entry->Close(); } @@ -238,11 +267,13 @@ int LoadOperations(const FilePath& path, RankCrashes action) { if (action <= disk_cache::INSERT_LOAD_2) { g_rankings_crash = action; - if (!cache->CreateEntry(kCrashEntryName, &entry)) + rv = cache->CreateEntry(kCrashEntryName, &entry, &cb); + if (cb.GetResult(rv) != net::OK) return GENERIC; } - if (!cache->OpenEntry(kCrashEntryName, &entry)) + rv = cache->OpenEntry(kCrashEntryName, &entry, &cb); + if (cb.GetResult(rv) != net::OK) return GENERIC; g_rankings_crash = action; @@ -255,7 +286,7 @@ int LoadOperations(const FilePath& path, RankCrashes action) { // Main function on the child process. int SlaveCode(const FilePath& path, RankCrashes action) { - MessageLoop message_loop; + MessageLoopForIO message_loop; FilePath full_path; if (!CreateTargetFolder(path, action, &full_path)) { @@ -263,23 +294,28 @@ int SlaveCode(const FilePath& path, RankCrashes action) { return CRASH_OVERWRITE; } + base::Thread cache_thread("CacheThread"); + if (!cache_thread.StartWithOptions( + base::Thread::Options(MessageLoop::TYPE_IO, 0))) + return GENERIC; + if (action <= disk_cache::INSERT_ONE_3) - return SimpleInsert(full_path, action); + return SimpleInsert(full_path, action, &cache_thread); if (action <= disk_cache::INSERT_LOAD_2) - return LoadOperations(full_path, action); + return LoadOperations(full_path, action, &cache_thread); if (action <= disk_cache::REMOVE_ONE_4) - return SimpleRemove(full_path, action); + return SimpleRemove(full_path, action, &cache_thread); if (action <= disk_cache::REMOVE_HEAD_4) - return HeadRemove(full_path, action); + return HeadRemove(full_path, action, &cache_thread); if (action <= disk_cache::REMOVE_TAIL_3) - return SimpleRemove(full_path, action); + return SimpleRemove(full_path, action, &cache_thread); if (action <= disk_cache::REMOVE_LOAD_3) - return LoadOperations(full_path, action); + return LoadOperations(full_path, action, &cache_thread); return NOT_REACHED; } diff --git a/net/tools/dump_cache/cache_dumper.cc b/net/tools/dump_cache/cache_dumper.cc index 74f1482..71720af 100644 --- a/net/tools/dump_cache/cache_dumper.cc +++ b/net/tools/dump_cache/cache_dumper.cc @@ -16,10 +16,10 @@ bool CacheDumper::CreateEntry(const std::string& key, return cache_->CreateEntry(key, entry); } -bool CacheDumper::WriteEntry(disk_cache::Entry* entry, int index, int offset, - net::IOBuffer* buf, int buf_len) { - int written = entry->WriteData(index, offset, buf, buf_len, NULL, false); - return written == buf_len; +int CacheDumper::WriteEntry(disk_cache::Entry* entry, int index, int offset, + net::IOBuffer* buf, int buf_len, + net::CompletionCallback* callback) { + return entry->WriteData(index, offset, buf, buf_len, callback, false); } void CacheDumper::CloseEntry(disk_cache::Entry* entry, base::Time last_used, @@ -48,7 +48,7 @@ bool SafeCreateDirectory(const std::wstring& path) { pos = 4; // Create the subdirectories individually - while((pos = path.find(backslash, pos)) != std::wstring::npos) { + while ((pos = path.find(backslash, pos)) != std::wstring::npos) { std::wstring subdir = path.substr(0, pos); CreateDirectoryW(subdir.c_str(), NULL); // we keep going even if directory creation failed. @@ -141,10 +141,11 @@ void GetNormalizedHeaders(const net::HttpResponseInfo& info, output->append("\r\n"); } -bool DiskDumper::WriteEntry(disk_cache::Entry* entry, int index, int offset, - net::IOBuffer* buf, int buf_len) { +int DiskDumper::WriteEntry(disk_cache::Entry* entry, int index, int offset, + net::IOBuffer* buf, int buf_len, + net::CompletionCallback* callback) { if (!entry_) - return false; + return 0; std::string headers; const char *data; @@ -154,11 +155,11 @@ bool DiskDumper::WriteEntry(disk_cache::Entry* entry, int index, int offset, bool truncated; if (!net::HttpCache::ParseResponseInfo(buf->data(), buf_len, &response_info, &truncated)) - return false; + return 0; // Skip this entry if it was truncated (results in an empty file). if (truncated) - return true; + return buf_len; // Remove the size headers. response_info.headers->RemoveHeader("transfer-encoding"); @@ -188,11 +189,12 @@ bool DiskDumper::WriteEntry(disk_cache::Entry* entry, int index, int offset, } #ifdef WIN32_LARGE_FILENAME_SUPPORT DWORD bytes; - DWORD rv = WriteFile(entry_, data, len, &bytes, 0); - return rv == TRUE && bytes == static_cast<DWORD>(len); + if (!WriteFile(entry_, data, len, &bytes, 0)) + return 0; + + return bytes; #else - int bytes = fwrite(data, 1, len, entry_); - return bytes == len; + return fwrite(data, 1, len, entry_); #endif } diff --git a/net/tools/dump_cache/cache_dumper.h b/net/tools/dump_cache/cache_dumper.h index 916b1b4..1af8573 100644 --- a/net/tools/dump_cache/cache_dumper.h +++ b/net/tools/dump_cache/cache_dumper.h @@ -1,9 +1,9 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 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. -#ifndef NET_TOOLS_DUMP_CACHE_DUMPER_H_ -#define NET_TOOLS_DUMP_CACHE_DUMPER_H_ +#ifndef NET_TOOLS_DUMP_CACHE_CACHE_DUMPER_H_ +#define NET_TOOLS_DUMP_CACHE_CACHE_DUMPER_H_ #include <string> #include "base/file_path.h" @@ -22,6 +22,8 @@ // An abstract class for writing cache dump data. class CacheDumpWriter { public: + virtual ~CacheDumpWriter() {} + // Creates an entry to be written. // On success, populates the |entry|. // Returns true on success, false otherwise. @@ -30,8 +32,9 @@ class CacheDumpWriter { // Write to the current entry. // Returns true on success, false otherwise. - virtual bool WriteEntry(disk_cache::Entry* entry, int stream, int offset, - net::IOBuffer* buf, int buf_len) = 0; + virtual int WriteEntry(disk_cache::Entry* entry, int stream, int offset, + net::IOBuffer* buf, int buf_len, + net::CompletionCallback* callback) = 0; // Close the current entry. virtual void CloseEntry(disk_cache::Entry* entry, base::Time last_used, @@ -41,27 +44,29 @@ class CacheDumpWriter { // Writes data to a cache. class CacheDumper : public CacheDumpWriter { public: - CacheDumper(disk_cache::BackendImpl* cache) : cache_(cache) {}; + explicit CacheDumper(disk_cache::Backend* cache) : cache_(cache) {} virtual bool CreateEntry(const std::string& key, disk_cache::Entry** entry); - virtual bool WriteEntry(disk_cache::Entry* entry, int stream, int offset, - net::IOBuffer* buf, int buf_len); + virtual int WriteEntry(disk_cache::Entry* entry, int stream, int offset, + net::IOBuffer* buf, int buf_len, + net::CompletionCallback* callback); virtual void CloseEntry(disk_cache::Entry* entry, base::Time last_used, base::Time last_modified); private: - disk_cache::BackendImpl* cache_; + disk_cache::Backend* cache_; }; // Writes data to a disk. class DiskDumper : public CacheDumpWriter { public: - DiskDumper(const std::wstring& path) : path_(path), entry_(NULL) { + explicit DiskDumper(const std::wstring& path) : path_(path), entry_(NULL) { file_util::CreateDirectory(FilePath(path)); - }; + } virtual bool CreateEntry(const std::string& key, disk_cache::Entry** entry); - virtual bool WriteEntry(disk_cache::Entry* entry, int stream, int offset, - net::IOBuffer* buf, int buf_len); + virtual int WriteEntry(disk_cache::Entry* entry, int stream, int offset, + net::IOBuffer* buf, int buf_len, + net::CompletionCallback* callback); virtual void CloseEntry(disk_cache::Entry* entry, base::Time last_used, base::Time last_modified); @@ -79,4 +84,4 @@ class DiskDumper : public CacheDumpWriter { #endif }; -#endif // NET_TOOLS_DUMP_CACHE_DUMPER_H_ +#endif // NET_TOOLS_DUMP_CACHE_CACHE_DUMPER_H_ diff --git a/net/tools/dump_cache/upgrade.cc b/net/tools/dump_cache/upgrade.cc index 71031dc..4f565fe 100644 --- a/net/tools/dump_cache/upgrade.cc +++ b/net/tools/dump_cache/upgrade.cc @@ -7,8 +7,10 @@ #include "base/message_loop.h" #include "base/scoped_ptr.h" #include "base/string_util.h" +#include "base/thread.h" #include "googleurl/src/gurl.h" #include "net/base/io_buffer.h" +#include "net/base/test_completion_callback.h" #include "net/disk_cache/backend_impl.h" #include "net/disk_cache/entry_impl.h" #include "net/http/http_cache.h" @@ -109,7 +111,7 @@ enum { class BaseSM : public MessageLoopForIO::IOHandler { public: - BaseSM(HANDLE channel); + explicit BaseSM(HANDLE channel); virtual ~BaseSM(); protected: @@ -128,11 +130,14 @@ class BaseSM : public MessageLoopForIO::IOHandler { scoped_array<char> out_buffer_; IoBuffer* input_; IoBuffer* output_; + base::Thread cache_thread_; + DISALLOW_COPY_AND_ASSIGN(BaseSM); }; BaseSM::BaseSM(HANDLE channel) - : entry_(NULL), channel_(channel), state_(0), pending_count_(0) { + : entry_(NULL), channel_(channel), state_(0), pending_count_(0), + cache_thread_("cache") { in_buffer_.reset(new char[kChannelSize]); out_buffer_.reset(new char[kChannelSize]); input_ = reinterpret_cast<IoBuffer*>(in_buffer_.get()); @@ -143,6 +148,8 @@ BaseSM::BaseSM(HANDLE channel) in_context_.handler = this; out_context_.handler = this; MessageLoopForIO::current()->RegisterIOHandler(channel_, this); + CHECK(cache_thread_.StartWithOptions( + base::Thread::Options(MessageLoop::TYPE_IO, 0))); } BaseSM::~BaseSM() { @@ -200,8 +207,10 @@ bool BaseSM::IsPending() { class MasterSM : public BaseSM { public: - MasterSM(const std::wstring& path, HANDLE channel, bool dump_to_disk) - : BaseSM(channel), path_(path), dump_to_disk_(dump_to_disk) { + MasterSM(const std::wstring& path, HANDLE channel, bool dump_to_disk) + : BaseSM(channel), path_(path), dump_to_disk_(dump_to_disk), + ALLOW_THIS_IN_INITIALIZER_LIST( + write_callback_(this, &MasterSM::DoReadDataComplete)) { } virtual ~MasterSM() { delete writer_; @@ -233,6 +242,7 @@ class MasterSM : public BaseSM { void CloseEntry(); void SendReadData(); void DoReadData(int bytes_read); + void DoReadDataComplete(int ret); void SendQuit(); void DoEnd(); void Fail(); @@ -244,10 +254,12 @@ class MasterSM : public BaseSM { int bytes_remaining_; int offset_; int copied_entries_; - scoped_ptr<disk_cache::BackendImpl> cache_; + int read_size_; + scoped_ptr<disk_cache::Backend> cache_; CacheDumpWriter* writer_; const std::wstring& path_; bool dump_to_disk_; + net::CompletionCallbackImpl<MasterSM> write_callback_; }; void MasterSM::OnIOCompleted(MessageLoopForIO::IOContext* context, @@ -302,11 +314,18 @@ bool MasterSM::DoInit() { if (dump_to_disk_) { writer_ = new DiskDumper(path_); } else { - cache_.reset(new disk_cache::BackendImpl(FilePath::FromWStringHack(path_))); - if (!cache_->Init()) { + disk_cache::Backend* cache; + TestCompletionCallback cb; + int rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, + FilePath::FromWStringHack(path_), 0, + false, + cache_thread_.message_loop_proxy(), + &cache, &cb); + if (cb.GetResult(rv) != net::OK) { printf("Unable to initialize new files\n"); return false; } + cache_.reset(cache); writer_ = new CacheDumper(cache_.get()); } if (!writer_) @@ -474,7 +493,15 @@ void MasterSM::DoReadData(int bytes_read) { scoped_refptr<net::WrappedIOBuffer> buf = new net::WrappedIOBuffer(input_->buffer); - if (!writer_->WriteEntry(entry_, stream_, offset_, buf, read_size)) + int rv = writer_->WriteEntry(entry_, stream_, offset_, buf, read_size, + &write_callback_); + if (rv == net::ERR_IO_PENDING) { + // We'll continue in DoReadDataComplete. + read_size_ = read_size; + return; + } + + if (rv <= 0) return Fail(); offset_ += read_size; @@ -483,6 +510,16 @@ void MasterSM::DoReadData(int bytes_read) { SendReadData(); } +void MasterSM::DoReadDataComplete(int ret) { + if (ret != read_size_) + return Fail(); + + offset_ += ret; + bytes_remaining_ -= ret; + // Read some more. + SendReadData(); +} + void MasterSM::SendQuit() { DEBUGMSG("Master SendQuit\n"); state_ = MASTER_END; @@ -508,15 +545,7 @@ void MasterSM::Fail() { class SlaveSM : public BaseSM { public: - SlaveSM(const std::wstring& path, HANDLE channel) - : BaseSM(channel), iterator_(NULL) { - cache_.reset(new disk_cache::BackendImpl(FilePath::FromWStringHack(path))); - if (!cache_->Init()) { - printf("Unable to open cache files\n"); - return; - } - cache_->SetUpgradeMode(); - } + SlaveSM(const std::wstring& path, HANDLE channel); virtual ~SlaveSM(); bool DoInit(); @@ -538,14 +567,36 @@ class SlaveSM : public BaseSM { void DoGetUseTimes(); void DoGetDataSize(); void DoReadData(); + void DoReadDataComplete(int ret); void DoEnd(); void Fail(); void* iterator_; + Message msg_; // Only used for DoReadDataComplete. + net::CompletionCallbackImpl<SlaveSM> read_callback_; scoped_ptr<disk_cache::BackendImpl> cache_; }; +SlaveSM::SlaveSM(const std::wstring& path, HANDLE channel) + : BaseSM(channel), iterator_(NULL), + ALLOW_THIS_IN_INITIALIZER_LIST( + read_callback_(this, &SlaveSM::DoReadDataComplete)) { + disk_cache::Backend* cache; + TestCompletionCallback cb; + int rv = disk_cache::CreateCacheBackend(net::DISK_CACHE, + FilePath::FromWStringHack(path), 0, + false, + cache_thread_.message_loop_proxy(), + &cache, &cb); + if (cb.GetResult(rv) != net::OK) { + printf("Unable to open cache files\n"); + return; + } + cache_.reset(reinterpret_cast<disk_cache::BackendImpl*>(cache)); + cache_->SetUpgradeMode(); +} + SlaveSM::~SlaveSM() { if (iterator_) cache_->EndEnumeration(&iterator_); @@ -753,7 +804,13 @@ void SlaveSM::DoReadData() { } else { scoped_refptr<net::WrappedIOBuffer> buf = new net::WrappedIOBuffer(output_->buffer); - int ret = entry_->ReadData(stream, input_->msg.arg3, buf, size, NULL); + int ret = entry_->ReadData(stream, input_->msg.arg3, buf, size, + &read_callback_); + if (ret == net::ERR_IO_PENDING) { + // Save the message so we can continue were we left. + msg_ = msg; + return; + } msg.buffer_bytes = (ret < 0) ? 0 : ret; msg.result = RESULT_OK; @@ -761,6 +818,14 @@ void SlaveSM::DoReadData() { SendMsg(msg); } +void SlaveSM::DoReadDataComplete(int ret) { + DEBUGMSG("\t\t\tSlave DoReadDataComplete\n"); + DCHECK_EQ(READ_DATA, msg_.command); + msg_.buffer_bytes = (ret < 0) ? 0 : ret; + msg_.result = RESULT_OK; + SendMsg(msg_); +} + void SlaveSM::DoEnd() { DEBUGMSG("\t\t\tSlave DoEnd\n"); MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask()); |