Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
|
rvargas (doing something else)
2013/03/13 19:36:01
Could you copy this file from backend_impl.cc? (sv
pasko-google - do not use
2013/03/18 15:47:07
Done.
| |
| 5 #include "base/command_line.h" | |
| 6 #include "base/file_util.h" | |
| 7 #include "base/stringprintf.h" | |
| 8 #include "base/string_util.h" | |
| 9 #include "base/threading/thread_restrictions.h" | |
| 10 #include "base/threading/worker_pool.h" | |
| 11 #include "net/base/net_errors.h" | |
| 12 #include "net/disk_cache/backend_impl.h" | |
| 13 #include "net/disk_cache/cache_util.h" | |
| 14 #include "net/disk_cache/disk_cache.h" | |
| 15 #include "net/disk_cache/mem_backend_impl.h" | |
| 16 #include "net/disk_cache/simple/simple_backend_impl.h" | |
| 17 | |
| 18 namespace { | |
| 19 | |
| 20 const int kMaxOldFolders = 100; | |
| 21 const char kUseSimpleCacheBackend[] = "use-simple-cache-backend"; | |
|
gavinp
2013/03/13 18:36:12
I'm a bit uncomfortable with the command line opti
pasko-google - do not use
2013/03/18 15:47:07
Switches are committed in the previous CL, about:f
| |
| 22 | |
| 23 // Returns a fully qualified name from path and name, using a given name prefix | |
| 24 // and index number. For instance, if the arguments are "/foo", "bar" and 5, it | |
| 25 // will return "/foo/old_bar_005". | |
| 26 base::FilePath GetPrefixedName(const base::FilePath& path, | |
| 27 const std::string& name, | |
| 28 int index) { | |
| 29 std::string tmp = base::StringPrintf("%s%s_%03d", "old_", | |
| 30 name.c_str(), index); | |
| 31 return path.AppendASCII(tmp); | |
| 32 } | |
| 33 | |
| 34 // This is a simple callback to cleanup old caches. | |
| 35 void CleanupCallback(const base::FilePath& path, const std::string& name) { | |
| 36 for (int i = 0; i < kMaxOldFolders; i++) { | |
| 37 base::FilePath to_delete = GetPrefixedName(path, name, i); | |
| 38 disk_cache::DeleteCache(to_delete, true); | |
| 39 } | |
| 40 } | |
| 41 | |
| 42 base::FilePath GetTempCacheName(const base::FilePath& path, | |
|
gavinp
2013/03/13 18:36:12
The comment for this function has been orphaned ov
pasko-google - do not use
2013/03/18 15:47:07
Oops. Done.
| |
| 43 const std::string& name) { | |
| 44 // We'll attempt to have up to kMaxOldFolders directories for deletion. | |
| 45 for (int i = 0; i < kMaxOldFolders; i++) { | |
| 46 base::FilePath to_delete = GetPrefixedName(path, name, i); | |
| 47 if (!file_util::PathExists(to_delete)) | |
| 48 return to_delete; | |
| 49 } | |
| 50 return base::FilePath(); | |
| 51 } | |
| 52 | |
| 53 // Builds the instance of the backend depending on command-line option. Takes | |
|
gavinp
2013/03/13 18:36:12
"Builds an instance of the backend depending on co
pasko-google - do not use
2013/03/18 15:47:07
Done.
| |
| 54 // care of the retry state. This object will self-destroy when finished. | |
| 55 class CacheCreator { | |
| 56 public: | |
| 57 CacheCreator(const base::FilePath& path, bool force, int max_bytes, | |
|
gavinp
2013/03/13 18:36:12
This declaration is formally a violation of our co
pasko-google - do not use
2013/03/18 15:47:07
Can you be more specific about the violation?
| |
| 58 net::CacheType type, uint32 flags, | |
| 59 base::MessageLoopProxy* thread, net::NetLog* net_log, | |
| 60 disk_cache::Backend** backend, | |
| 61 const net::CompletionCallback& callback); | |
| 62 | |
| 63 // Creates the backend. | |
| 64 int Run(); | |
| 65 | |
| 66 private: | |
| 67 ~CacheCreator(); | |
| 68 | |
| 69 void DoCallback(int result); | |
| 70 | |
| 71 // Callback implementation. | |
| 72 void OnIOComplete(int result); | |
| 73 | |
| 74 const base::FilePath& path_; | |
| 75 bool force_; | |
| 76 bool retry_; | |
| 77 int max_bytes_; | |
| 78 net::CacheType type_; | |
| 79 uint32 flags_; | |
| 80 scoped_refptr<base::MessageLoopProxy> thread_; | |
| 81 disk_cache::Backend** backend_; | |
| 82 net::CompletionCallback callback_; | |
| 83 disk_cache::Backend* created_cache_; | |
| 84 net::NetLog* net_log_; | |
| 85 | |
| 86 DISALLOW_COPY_AND_ASSIGN(CacheCreator); | |
| 87 }; | |
| 88 | |
| 89 CacheCreator::CacheCreator( | |
| 90 const base::FilePath& path, bool force, int max_bytes, | |
| 91 net::CacheType type, uint32 flags, | |
| 92 base::MessageLoopProxy* thread, net::NetLog* net_log, | |
| 93 disk_cache::Backend** backend, | |
| 94 const net::CompletionCallback& callback) | |
| 95 : path_(path), | |
| 96 force_(force), | |
| 97 retry_(false), | |
| 98 max_bytes_(max_bytes), | |
| 99 type_(type), | |
| 100 flags_(flags), | |
| 101 thread_(thread), | |
| 102 backend_(backend), | |
| 103 callback_(callback), | |
| 104 created_cache_(NULL), | |
| 105 net_log_(net_log) { | |
| 106 } | |
| 107 | |
| 108 CacheCreator::~CacheCreator() { | |
| 109 } | |
| 110 | |
| 111 int CacheCreator::Run() { | |
| 112 if (type_ == net::MEMORY_CACHE) { | |
| 113 *backend_ = disk_cache::MemBackendImpl::CreateBackend(max_bytes_, net_log_); | |
| 114 return *backend_ ? net::OK : net::ERR_FAILED; | |
| 115 } | |
| 116 #if defined(USE_SIMPLE_CACHE_BACKEND) | |
|
gavinp
2013/03/13 18:36:12
This #define probably needs to be renamed now to B
pasko-google - do not use
2013/03/18 15:47:07
Removed altogether as per other discussions.
| |
| 117 if (CommandLine::ForCurrentProcess()->HasSwitch(kUseSimpleCacheBackend)) { | |
| 118 // TODO(gavinp,pasko): While simple backend development proceeds, we're only | |
| 119 // testing it against net::DISK_CACHE. Turn it on for more cache types as | |
| 120 // appropriate. | |
| 121 if (type_ == net::DISK_CACHE) { | |
| 122 VLOG(1) << "Using the Simple Cache Backend."; | |
| 123 return disk_cache::SimpleBackendImpl::CreateBackend(path_, max_bytes_, | |
| 124 type_, disk_cache::kNone, thread_, net_log_, backend_, callback_); | |
| 125 } | |
| 126 } | |
| 127 #endif | |
| 128 disk_cache::BackendImpl* new_cache = new disk_cache::BackendImpl( | |
|
gavinp
2013/03/13 18:36:12
Why the automatic? Why not:
created_cache_ = new
pasko-google - do not use
2013/03/18 15:47:07
We use a few methods that are not present in Backe
| |
| 129 path_, thread_, net_log_); | |
| 130 created_cache_ = new_cache; | |
| 131 new_cache->SetMaxSize(max_bytes_); | |
| 132 new_cache->SetType(type_); | |
| 133 new_cache->SetFlags(flags_); | |
| 134 int rv = new_cache->Init( | |
| 135 base::Bind(&CacheCreator::OnIOComplete, base::Unretained(this))); | |
| 136 DCHECK_EQ(net::ERR_IO_PENDING, rv); | |
| 137 return rv; | |
| 138 } | |
| 139 | |
| 140 void CacheCreator::DoCallback(int result) { | |
| 141 DCHECK_NE(net::ERR_IO_PENDING, result); | |
| 142 if (result == net::OK) { | |
| 143 *backend_ = created_cache_; | |
| 144 } else { | |
| 145 LOG(ERROR) << "Unable to create cache"; | |
| 146 *backend_ = NULL; | |
| 147 delete created_cache_; | |
| 148 } | |
| 149 callback_.Run(result); | |
| 150 delete this; | |
| 151 } | |
| 152 | |
| 153 void CacheCreator::OnIOComplete(int result) { | |
| 154 if (result == net::OK || !force_ || retry_) | |
| 155 return DoCallback(result); | |
| 156 | |
| 157 // This is a failure and we are supposed to try again, so delete the object, | |
| 158 // delete all the files, and try again. | |
| 159 retry_ = true; | |
| 160 delete created_cache_; | |
| 161 created_cache_ = NULL; | |
| 162 if (!disk_cache::DelayedCacheCleanup(path_)) | |
| 163 return DoCallback(result); | |
| 164 | |
| 165 // The worker thread will start deleting files soon, but the original | |
| 166 // directory is not there anymore... let's create a new set of files. | |
| 167 int rv = Run(); | |
| 168 DCHECK_EQ(net::ERR_IO_PENDING, rv); | |
| 169 } | |
| 170 | |
| 171 } // namespace | |
| 172 | |
| 173 namespace disk_cache { | |
| 174 | |
| 175 // If the initialization of the cache fails, and |force| is true, we will | |
| 176 // discard the whole cache and create a new one. In order to process a | |
| 177 // potentially large number of files, we'll rename the cache directory to old_ + | |
| 178 // original_name + number, (located on the same parent directory), and spawn a | |
| 179 // worker thread to delete all the files on all the stale cache directories. The | |
| 180 // whole process can still fail if we are not able to rename the cache directory | |
| 181 // (for instance due to a sharing violation), and in that case a cache for this | |
| 182 // profile (on the desired path) cannot be created. | |
| 183 int CreateCacheBackendWithFlags(net::CacheType type, const base::FilePath& path, | |
| 184 int max_bytes, bool force, uint32 flags, base::MessageLoopProxy* thread, | |
| 185 net::NetLog* net_log, Backend** backend, | |
| 186 const net::CompletionCallback& callback) { | |
| 187 DCHECK(!callback.is_null()); | |
| 188 DCHECK(thread || type == net::MEMORY_CACHE); | |
| 189 CacheCreator* creator = new CacheCreator(path, force, max_bytes, type, flags, | |
| 190 thread, net_log, backend, callback); | |
| 191 return creator->Run(); | |
| 192 } | |
| 193 | |
| 194 int CreateCacheBackend(net::CacheType type, const base::FilePath& path, | |
| 195 int max_bytes, bool force, base::MessageLoopProxy* thread, | |
| 196 net::NetLog* net_log, Backend** backend, | |
| 197 const net::CompletionCallback& callback) { | |
| 198 return CreateCacheBackendWithFlags(type, path, max_bytes, force, kNone, | |
| 199 thread, net_log, backend, callback); | |
| 200 } | |
| 201 | |
| 202 // Moves the cache files to a new directory and creates a task to delete them. | |
| 203 bool DelayedCacheCleanup(const base::FilePath& full_path) { | |
| 204 // GetTempCacheName() and MoveCache() use synchronous file | |
| 205 // operations. | |
| 206 base::ThreadRestrictions::ScopedAllowIO allow_io; | |
| 207 | |
| 208 base::FilePath current_path = full_path.StripTrailingSeparators(); | |
| 209 | |
| 210 base::FilePath path = current_path.DirName(); | |
| 211 base::FilePath name = current_path.BaseName(); | |
| 212 #if defined(OS_POSIX) | |
| 213 std::string name_str = name.value(); | |
| 214 #elif defined(OS_WIN) | |
| 215 // We created this file so it should only contain ASCII. | |
| 216 std::string name_str = WideToASCII(name.value()); | |
| 217 #endif | |
| 218 | |
| 219 base::FilePath to_delete = GetTempCacheName(path, name_str); | |
| 220 if (to_delete.empty()) { | |
| 221 LOG(ERROR) << "Unable to get another cache folder"; | |
| 222 return false; | |
| 223 } | |
| 224 | |
| 225 if (!disk_cache::MoveCache(full_path, to_delete)) { | |
| 226 LOG(ERROR) << "Unable to move cache folder " << full_path.value() << " to " | |
| 227 << to_delete.value(); | |
| 228 return false; | |
| 229 } | |
| 230 | |
| 231 base::WorkerPool::PostTask( | |
| 232 FROM_HERE, base::Bind(&CleanupCallback, path, name_str), true); | |
| 233 return true; | |
| 234 } | |
| 235 | |
| 236 } // namespace disk_cache | |
| OLD | NEW |