| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/drive/file_cache_metadata.h" | 5 #include "chrome/browser/chromeos/drive/file_cache_metadata.h" |
| 6 | 6 |
| 7 #include "base/callback.h" | 7 #include "base/callback.h" |
| 8 #include "base/file_util.h" | 8 #include "base/file_util.h" |
| 9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/sequenced_task_runner.h" | 10 #include "base/sequenced_task_runner.h" |
| 11 #include "chrome/browser/chromeos/drive/drive.pb.h" | 11 #include "chrome/browser/chromeos/drive/drive.pb.h" |
| 12 #include "chrome/browser/chromeos/drive/file_cache.h" | 12 #include "chrome/browser/chromeos/drive/file_cache.h" |
| 13 #include "chrome/browser/chromeos/drive/file_system_util.h" | 13 #include "chrome/browser/chromeos/drive/file_system_util.h" |
| 14 #include "third_party/leveldatabase/src/include/leveldb/db.h" | 14 #include "third_party/leveldatabase/src/include/leveldb/db.h" |
| 15 | 15 |
| 16 namespace drive { | 16 namespace drive { |
| 17 namespace internal { | 17 namespace internal { |
| 18 | 18 |
| 19 namespace { | 19 namespace { |
| 20 | 20 |
| 21 typedef std::map<std::string, FileCacheEntry> CacheMap; |
| 22 |
| 21 enum DBOpenStatus { | 23 enum DBOpenStatus { |
| 22 DB_OPEN_SUCCESS, | 24 DB_OPEN_SUCCESS, |
| 23 DB_OPEN_FAILURE_CORRUPTION, | 25 DB_OPEN_FAILURE_CORRUPTION, |
| 24 DB_OPEN_FAILURE_OTHER, | 26 DB_OPEN_FAILURE_OTHER, |
| 25 DB_OPEN_FAILURE_UNRECOVERABLE, | 27 DB_OPEN_FAILURE_UNRECOVERABLE, |
| 26 DB_OPEN_MAX_VALUE, | 28 DB_OPEN_MAX_VALUE, |
| 27 }; | 29 }; |
| 28 | 30 |
| 29 // A map table of resource ID to file path. | 31 // A map table of resource ID to file path. |
| 30 typedef std::map<std::string, base::FilePath> ResourceIdToFilePathMap; | 32 typedef std::map<std::string, base::FilePath> ResourceIdToFilePathMap; |
| 31 | 33 |
| 32 // Scans cache subdirectory and build or update |cache_map| with found files. | 34 // Scans cache subdirectory and build or update |cache_map| with found files. |
| 33 // | 35 // |
| 34 // The resource IDs and file paths of discovered files are collected as a | 36 // The resource IDs and file paths of discovered files are collected as a |
| 35 // ResourceIdToFilePathMap, if these are processed properly. | 37 // ResourceIdToFilePathMap, if these are processed properly. |
| 36 void ScanCacheDirectory( | 38 void ScanCacheDirectory(const std::vector<base::FilePath>& cache_paths, |
| 37 const std::vector<base::FilePath>& cache_paths, | 39 FileCache::CacheSubDirectoryType sub_dir_type, |
| 38 FileCache::CacheSubDirectoryType sub_dir_type, | 40 CacheMap* cache_map, |
| 39 FileCacheMetadata::CacheMap* cache_map, | 41 ResourceIdToFilePathMap* processed_file_map) { |
| 40 ResourceIdToFilePathMap* processed_file_map) { | |
| 41 DCHECK(cache_map); | 42 DCHECK(cache_map); |
| 42 DCHECK(processed_file_map); | 43 DCHECK(processed_file_map); |
| 43 | 44 |
| 44 file_util::FileEnumerator enumerator(cache_paths[sub_dir_type], | 45 file_util::FileEnumerator enumerator(cache_paths[sub_dir_type], |
| 45 false, // not recursive | 46 false, // not recursive |
| 46 file_util::FileEnumerator::FILES, | 47 file_util::FileEnumerator::FILES, |
| 47 util::kWildCard); | 48 util::kWildCard); |
| 48 for (base::FilePath current = enumerator.Next(); !current.empty(); | 49 for (base::FilePath current = enumerator.Next(); !current.empty(); |
| 49 current = enumerator.Next()) { | 50 current = enumerator.Next()) { |
| 50 // Extract resource_id and md5 from filename. | 51 // Extract resource_id and md5 from filename. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 } | 84 } |
| 84 } | 85 } |
| 85 | 86 |
| 86 // Create and insert new entry into cache map. | 87 // Create and insert new entry into cache map. |
| 87 cache_map->insert(std::make_pair(resource_id, cache_entry)); | 88 cache_map->insert(std::make_pair(resource_id, cache_entry)); |
| 88 processed_file_map->insert(std::make_pair(resource_id, current)); | 89 processed_file_map->insert(std::make_pair(resource_id, current)); |
| 89 } | 90 } |
| 90 } | 91 } |
| 91 | 92 |
| 92 void ScanCachePaths(const std::vector<base::FilePath>& cache_paths, | 93 void ScanCachePaths(const std::vector<base::FilePath>& cache_paths, |
| 93 FileCacheMetadata::CacheMap* cache_map) { | 94 CacheMap* cache_map) { |
| 94 DVLOG(1) << "Scanning directories"; | 95 DVLOG(1) << "Scanning directories"; |
| 95 | 96 |
| 96 // Scan cache persistent and tmp directories to enumerate all files and create | 97 // Scan cache persistent and tmp directories to enumerate all files and create |
| 97 // corresponding entries for cache map. | 98 // corresponding entries for cache map. |
| 98 ResourceIdToFilePathMap persistent_file_map; | 99 ResourceIdToFilePathMap persistent_file_map; |
| 99 ScanCacheDirectory(cache_paths, | 100 ScanCacheDirectory(cache_paths, |
| 100 FileCache::CACHE_TYPE_PERSISTENT, | 101 FileCache::CACHE_TYPE_PERSISTENT, |
| 101 cache_map, | 102 cache_map, |
| 102 &persistent_file_map); | 103 &persistent_file_map); |
| 103 ResourceIdToFilePathMap tmp_file_map; | 104 ResourceIdToFilePathMap tmp_file_map; |
| 104 ScanCacheDirectory(cache_paths, | 105 ScanCacheDirectory(cache_paths, |
| 105 FileCache::CACHE_TYPE_TMP, | 106 FileCache::CACHE_TYPE_TMP, |
| 106 cache_map, | 107 cache_map, |
| 107 &tmp_file_map); | 108 &tmp_file_map); |
| 108 | 109 |
| 109 // On DB corruption, keep only dirty-and-committed files in persistent | 110 // On DB corruption, keep only dirty-and-committed files in persistent |
| 110 // directory. Other files are deleted or moved to temporary directory. | 111 // directory. Other files are deleted or moved to temporary directory. |
| 111 for (ResourceIdToFilePathMap::const_iterator iter = | 112 for (ResourceIdToFilePathMap::const_iterator iter = |
| 112 persistent_file_map.begin(); | 113 persistent_file_map.begin(); |
| 113 iter != persistent_file_map.end(); ++iter) { | 114 iter != persistent_file_map.end(); ++iter) { |
| 114 const std::string& resource_id = iter->first; | 115 const std::string& resource_id = iter->first; |
| 115 const base::FilePath& file_path = iter->second; | 116 const base::FilePath& file_path = iter->second; |
| 116 | 117 |
| 117 FileCacheMetadata::CacheMap::iterator cache_map_iter = | 118 CacheMap::iterator cache_map_iter = cache_map->find(resource_id); |
| 118 cache_map->find(resource_id); | |
| 119 if (cache_map_iter != cache_map->end()) { | 119 if (cache_map_iter != cache_map->end()) { |
| 120 FileCacheEntry* cache_entry = &cache_map_iter->second; | 120 FileCacheEntry* cache_entry = &cache_map_iter->second; |
| 121 const bool is_dirty = cache_entry->is_dirty(); | 121 const bool is_dirty = cache_entry->is_dirty(); |
| 122 if (!is_dirty) { | 122 if (!is_dirty) { |
| 123 // If the file is not dirty, move to temporary directory. | 123 // If the file is not dirty, move to temporary directory. |
| 124 base::FilePath new_file_path = | 124 base::FilePath new_file_path = |
| 125 cache_paths[FileCache::CACHE_TYPE_TMP].Append( | 125 cache_paths[FileCache::CACHE_TYPE_TMP].Append( |
| 126 file_path.BaseName()); | 126 file_path.BaseName()); |
| 127 DLOG(WARNING) << "Moving: " << file_path.value() | 127 DLOG(WARNING) << "Moving: " << file_path.value() |
| 128 << " to: " << new_file_path.value(); | 128 << " to: " << new_file_path.value(); |
| 129 file_util::Move(file_path, new_file_path); | 129 file_util::Move(file_path, new_file_path); |
| 130 cache_entry->set_is_persistent(false); | 130 cache_entry->set_is_persistent(false); |
| 131 } | 131 } |
| 132 } | 132 } |
| 133 } | 133 } |
| 134 DVLOG(1) << "Directory scan finished"; | 134 DVLOG(1) << "Directory scan finished"; |
| 135 } | 135 } |
| 136 | 136 |
| 137 // Returns true if |md5| matches the one in |cache_entry| with some | 137 // Returns true if |md5| matches the one in |cache_entry| with some |
| 138 // exceptions. See the function definition for details. | 138 // exceptions. See the function definition for details. |
| 139 bool CheckIfMd5Matches( | 139 bool CheckIfMd5Matches(const std::string& md5, |
| 140 const std::string& md5, | 140 const FileCacheEntry& cache_entry) { |
| 141 const FileCacheEntry& cache_entry) { | |
| 142 if (cache_entry.is_dirty()) { | 141 if (cache_entry.is_dirty()) { |
| 143 // If the entry is dirty, its MD5 may have been replaced by "local" | 142 // If the entry is dirty, its MD5 may have been replaced by "local" |
| 144 // during cache initialization, so we don't compare MD5. | 143 // during cache initialization, so we don't compare MD5. |
| 145 return true; | 144 return true; |
| 146 } else if (cache_entry.is_pinned() && cache_entry.md5().empty()) { | 145 } else if (cache_entry.is_pinned() && cache_entry.md5().empty()) { |
| 147 // If the entry is pinned, it's ok for the entry to have an empty | 146 // If the entry is pinned, it's ok for the entry to have an empty |
| 148 // MD5. This can happen if the pinned file is not fetched. MD5 for pinned | 147 // MD5. This can happen if the pinned file is not fetched. MD5 for pinned |
| 149 // files are collected from files in "persistent" directory, but the | 148 // files are collected from files in "persistent" directory, but the |
| 150 // persistent files do not exist if these are not fetched yet. | 149 // persistent files do not exist if these are not fetched yet. |
| 151 return true; | 150 return true; |
| 152 } else if (md5.empty()) { | 151 } else if (md5.empty()) { |
| 153 // If the MD5 matching is not requested, don't check MD5. | 152 // If the MD5 matching is not requested, don't check MD5. |
| 154 return true; | 153 return true; |
| 155 } else if (md5 == cache_entry.md5()) { | 154 } else if (md5 == cache_entry.md5()) { |
| 156 // Otherwise, compare the MD5. | 155 // Otherwise, compare the MD5. |
| 157 return true; | 156 return true; |
| 158 } | 157 } |
| 159 return false; | 158 return false; |
| 160 } | 159 } |
| 161 | 160 |
| 162 //////////////////////////////////////////////////////////////////////////////// | 161 } // namespace |
| 163 // FileCacheMetadata implementation with std::map. | |
| 164 // Used for testing. | |
| 165 | 162 |
| 166 class FakeCacheMetadata : public FileCacheMetadata { | 163 // static |
| 167 public: | 164 const base::FilePath::CharType* FileCacheMetadata::kCacheMetadataDBPath = |
| 168 explicit FakeCacheMetadata( | 165 FILE_PATH_LITERAL("cache_metadata.db"); |
| 169 base::SequencedTaskRunner* blocking_task_runner); | |
| 170 | 166 |
| 171 private: | 167 FileCacheMetadata::FileCacheMetadata( |
| 172 virtual ~FakeCacheMetadata(); | |
| 173 | |
| 174 // FileCacheMetadata overrides: | |
| 175 virtual bool Initialize( | |
| 176 const std::vector<base::FilePath>& cache_paths) OVERRIDE; | |
| 177 virtual void AddOrUpdateCacheEntry( | |
| 178 const std::string& resource_id, | |
| 179 const FileCacheEntry& cache_entry) OVERRIDE; | |
| 180 virtual void RemoveCacheEntry(const std::string& resource_id) OVERRIDE; | |
| 181 virtual bool GetCacheEntry(const std::string& resource_id, | |
| 182 const std::string& md5, | |
| 183 FileCacheEntry* cache_entry) OVERRIDE; | |
| 184 virtual void RemoveTemporaryFiles() OVERRIDE; | |
| 185 virtual void Iterate(const CacheIterateCallback& callback) OVERRIDE; | |
| 186 | |
| 187 CacheMap cache_map_; | |
| 188 | |
| 189 DISALLOW_COPY_AND_ASSIGN(FakeCacheMetadata); | |
| 190 }; | |
| 191 | |
| 192 FakeCacheMetadata::FakeCacheMetadata( | |
| 193 base::SequencedTaskRunner* blocking_task_runner) | 168 base::SequencedTaskRunner* blocking_task_runner) |
| 194 : FileCacheMetadata(blocking_task_runner) { | 169 : blocking_task_runner_(blocking_task_runner) { |
| 195 AssertOnSequencedWorkerPool(); | 170 AssertOnSequencedWorkerPool(); |
| 196 } | 171 } |
| 197 | 172 |
| 198 FakeCacheMetadata::~FakeCacheMetadata() { | 173 FileCacheMetadata::~FileCacheMetadata() { |
| 199 AssertOnSequencedWorkerPool(); | 174 AssertOnSequencedWorkerPool(); |
| 200 } | 175 } |
| 201 | 176 |
| 202 bool FakeCacheMetadata::Initialize( | 177 bool FileCacheMetadata::Initialize( |
| 203 const std::vector<base::FilePath>& cache_paths) { | |
| 204 AssertOnSequencedWorkerPool(); | |
| 205 | |
| 206 ScanCachePaths(cache_paths, &cache_map_); | |
| 207 return true; | |
| 208 } | |
| 209 | |
| 210 void FakeCacheMetadata::AddOrUpdateCacheEntry( | |
| 211 const std::string& resource_id, | |
| 212 const FileCacheEntry& cache_entry) { | |
| 213 AssertOnSequencedWorkerPool(); | |
| 214 | |
| 215 CacheMap::iterator iter = cache_map_.find(resource_id); | |
| 216 if (iter == cache_map_.end()) { // New resource, create new entry. | |
| 217 cache_map_.insert(std::make_pair(resource_id, cache_entry)); | |
| 218 } else { // Resource exists. | |
| 219 cache_map_[resource_id] = cache_entry; | |
| 220 } | |
| 221 } | |
| 222 | |
| 223 void FakeCacheMetadata::RemoveCacheEntry(const std::string& resource_id) { | |
| 224 AssertOnSequencedWorkerPool(); | |
| 225 | |
| 226 CacheMap::iterator iter = cache_map_.find(resource_id); | |
| 227 if (iter != cache_map_.end()) { | |
| 228 // Delete the FileCacheEntry and remove it from the map. | |
| 229 cache_map_.erase(iter); | |
| 230 } | |
| 231 } | |
| 232 | |
| 233 bool FakeCacheMetadata::GetCacheEntry(const std::string& resource_id, | |
| 234 const std::string& md5, | |
| 235 FileCacheEntry* entry) { | |
| 236 DCHECK(entry); | |
| 237 AssertOnSequencedWorkerPool(); | |
| 238 | |
| 239 CacheMap::iterator iter = cache_map_.find(resource_id); | |
| 240 if (iter == cache_map_.end()) { | |
| 241 DVLOG(1) << "Can't find " << resource_id << " in cache map"; | |
| 242 return false; | |
| 243 } | |
| 244 | |
| 245 const FileCacheEntry& cache_entry = iter->second; | |
| 246 | |
| 247 if (!CheckIfMd5Matches(md5, cache_entry)) { | |
| 248 return false; | |
| 249 } | |
| 250 | |
| 251 *entry = cache_entry; | |
| 252 return true; | |
| 253 } | |
| 254 | |
| 255 void FakeCacheMetadata::RemoveTemporaryFiles() { | |
| 256 AssertOnSequencedWorkerPool(); | |
| 257 | |
| 258 CacheMap::iterator iter = cache_map_.begin(); | |
| 259 while (iter != cache_map_.end()) { | |
| 260 if (!iter->second.is_persistent()) { | |
| 261 // Post-increment the iterator to avoid iterator invalidation. | |
| 262 cache_map_.erase(iter++); | |
| 263 } else { | |
| 264 ++iter; | |
| 265 } | |
| 266 } | |
| 267 } | |
| 268 | |
| 269 void FakeCacheMetadata::Iterate(const CacheIterateCallback& callback) { | |
| 270 AssertOnSequencedWorkerPool(); | |
| 271 | |
| 272 for (CacheMap::const_iterator iter = cache_map_.begin(); | |
| 273 iter != cache_map_.end(); ++iter) { | |
| 274 callback.Run(iter->first, iter->second); | |
| 275 } | |
| 276 } | |
| 277 | |
| 278 //////////////////////////////////////////////////////////////////////////////// | |
| 279 // FileCacheMetadata implementation with level::db. | |
| 280 | |
| 281 class FileCacheMetadataDB : public FileCacheMetadata { | |
| 282 public: | |
| 283 explicit FileCacheMetadataDB( | |
| 284 base::SequencedTaskRunner* blocking_task_runner); | |
| 285 | |
| 286 private: | |
| 287 virtual ~FileCacheMetadataDB(); | |
| 288 | |
| 289 // FileCacheMetadata overrides: | |
| 290 virtual bool Initialize( | |
| 291 const std::vector<base::FilePath>& cache_paths) OVERRIDE; | |
| 292 virtual void AddOrUpdateCacheEntry( | |
| 293 const std::string& resource_id, | |
| 294 const FileCacheEntry& cache_entry) OVERRIDE; | |
| 295 virtual void RemoveCacheEntry(const std::string& resource_id) OVERRIDE; | |
| 296 virtual bool GetCacheEntry(const std::string& resource_id, | |
| 297 const std::string& md5, | |
| 298 FileCacheEntry* cache_entry) OVERRIDE; | |
| 299 virtual void RemoveTemporaryFiles() OVERRIDE; | |
| 300 virtual void Iterate(const CacheIterateCallback& callback) OVERRIDE; | |
| 301 | |
| 302 // Helper function to insert |cache_map| entries into the database. | |
| 303 void InsertMapIntoDB(const CacheMap& cache_map); | |
| 304 | |
| 305 scoped_ptr<leveldb::DB> level_db_; | |
| 306 | |
| 307 DISALLOW_COPY_AND_ASSIGN(FileCacheMetadataDB); | |
| 308 }; | |
| 309 | |
| 310 FileCacheMetadataDB::FileCacheMetadataDB( | |
| 311 base::SequencedTaskRunner* blocking_task_runner) | |
| 312 : FileCacheMetadata(blocking_task_runner) { | |
| 313 AssertOnSequencedWorkerPool(); | |
| 314 } | |
| 315 | |
| 316 FileCacheMetadataDB::~FileCacheMetadataDB() { | |
| 317 AssertOnSequencedWorkerPool(); | |
| 318 } | |
| 319 | |
| 320 bool FileCacheMetadataDB::Initialize( | |
| 321 const std::vector<base::FilePath>& cache_paths) { | 178 const std::vector<base::FilePath>& cache_paths) { |
| 322 AssertOnSequencedWorkerPool(); | 179 AssertOnSequencedWorkerPool(); |
| 323 | 180 |
| 324 const base::FilePath db_path = | 181 const base::FilePath db_path = |
| 325 cache_paths[FileCache::CACHE_TYPE_META].Append( | 182 cache_paths[FileCache::CACHE_TYPE_META].Append(kCacheMetadataDBPath); |
| 326 kCacheMetadataDBPath); | |
| 327 DVLOG(1) << "db path=" << db_path.value(); | 183 DVLOG(1) << "db path=" << db_path.value(); |
| 328 | 184 |
| 329 bool scan_cache = !file_util::PathExists(db_path); | 185 bool scan_cache = !file_util::PathExists(db_path); |
| 330 | 186 |
| 331 leveldb::DB* level_db = NULL; | 187 leveldb::DB* level_db = NULL; |
| 332 leveldb::Options options; | 188 leveldb::Options options; |
| 333 options.create_if_missing = true; | 189 options.create_if_missing = true; |
| 334 leveldb::Status db_status = leveldb::DB::Open(options, db_path.AsUTF8Unsafe(), | 190 leveldb::Status db_status = leveldb::DB::Open(options, db_path.AsUTF8Unsafe(), |
| 335 &level_db); | 191 &level_db); |
| 336 | 192 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 358 UMA_HISTOGRAM_ENUMERATION("Drive.CacheDBOpenStatus", uma_status, | 214 UMA_HISTOGRAM_ENUMERATION("Drive.CacheDBOpenStatus", uma_status, |
| 359 DB_OPEN_MAX_VALUE); | 215 DB_OPEN_MAX_VALUE); |
| 360 DCHECK(level_db); | 216 DCHECK(level_db); |
| 361 level_db_.reset(level_db); | 217 level_db_.reset(level_db); |
| 362 | 218 |
| 363 // We scan the cache directories to initialize the cache database if we | 219 // We scan the cache directories to initialize the cache database if we |
| 364 // were previously using the cache map. | 220 // were previously using the cache map. |
| 365 if (scan_cache) { | 221 if (scan_cache) { |
| 366 CacheMap cache_map; | 222 CacheMap cache_map; |
| 367 ScanCachePaths(cache_paths, &cache_map); | 223 ScanCachePaths(cache_paths, &cache_map); |
| 368 InsertMapIntoDB(cache_map); | 224 for (CacheMap::const_iterator it = cache_map.begin(); |
| 225 it != cache_map.end(); ++it) { |
| 226 AddOrUpdateCacheEntry(it->first, it->second); |
| 227 } |
| 369 } | 228 } |
| 370 | 229 |
| 371 return true; | 230 return true; |
| 372 } | 231 } |
| 373 | 232 |
| 374 void FileCacheMetadataDB::InsertMapIntoDB(const CacheMap& cache_map) { | 233 void FileCacheMetadata::AddOrUpdateCacheEntry( |
| 375 DVLOG(1) << "InsertMapIntoDB"; | |
| 376 for (CacheMap::const_iterator it = cache_map.begin(); | |
| 377 it != cache_map.end(); ++it) { | |
| 378 AddOrUpdateCacheEntry(it->first, it->second); | |
| 379 } | |
| 380 } | |
| 381 | |
| 382 void FileCacheMetadataDB::AddOrUpdateCacheEntry( | |
| 383 const std::string& resource_id, | 234 const std::string& resource_id, |
| 384 const FileCacheEntry& cache_entry) { | 235 const FileCacheEntry& cache_entry) { |
| 385 AssertOnSequencedWorkerPool(); | 236 AssertOnSequencedWorkerPool(); |
| 386 | 237 |
| 387 DVLOG(1) << "AddOrUpdateCacheEntry, resource_id=" << resource_id; | 238 DVLOG(1) << "AddOrUpdateCacheEntry, resource_id=" << resource_id; |
| 388 std::string serialized; | 239 std::string serialized; |
| 389 const bool ok = cache_entry.SerializeToString(&serialized); | 240 const bool ok = cache_entry.SerializeToString(&serialized); |
| 390 if (ok) | 241 if (ok) |
| 391 level_db_->Put(leveldb::WriteOptions(), | 242 level_db_->Put(leveldb::WriteOptions(), |
| 392 leveldb::Slice(resource_id), | 243 leveldb::Slice(resource_id), |
| 393 leveldb::Slice(serialized)); | 244 leveldb::Slice(serialized)); |
| 394 } | 245 } |
| 395 | 246 |
| 396 void FileCacheMetadataDB::RemoveCacheEntry(const std::string& resource_id) { | 247 void FileCacheMetadata::RemoveCacheEntry(const std::string& resource_id) { |
| 397 AssertOnSequencedWorkerPool(); | 248 AssertOnSequencedWorkerPool(); |
| 398 | 249 |
| 399 DVLOG(1) << "RemoveCacheEntry, resource_id=" << resource_id; | 250 DVLOG(1) << "RemoveCacheEntry, resource_id=" << resource_id; |
| 400 level_db_->Delete(leveldb::WriteOptions(), leveldb::Slice(resource_id)); | 251 level_db_->Delete(leveldb::WriteOptions(), leveldb::Slice(resource_id)); |
| 401 } | 252 } |
| 402 | 253 |
| 403 bool FileCacheMetadataDB::GetCacheEntry(const std::string& resource_id, | 254 bool FileCacheMetadata::GetCacheEntry(const std::string& resource_id, |
| 404 const std::string& md5, | 255 const std::string& md5, |
| 405 FileCacheEntry* entry) { | 256 FileCacheEntry* entry) { |
| 406 DCHECK(entry); | 257 DCHECK(entry); |
| 407 AssertOnSequencedWorkerPool(); | 258 AssertOnSequencedWorkerPool(); |
| 408 | 259 |
| 409 std::string serialized; | 260 std::string serialized; |
| 410 const leveldb::Status status = level_db_->Get( | 261 const leveldb::Status status = level_db_->Get( |
| 411 leveldb::ReadOptions(), | 262 leveldb::ReadOptions(), |
| 412 leveldb::Slice(resource_id), &serialized); | 263 leveldb::Slice(resource_id), &serialized); |
| 413 if (!status.ok()) { | 264 if (!status.ok()) { |
| 414 DVLOG(1) << "Can't find " << resource_id << " in cache db"; | 265 DVLOG(1) << "Can't find " << resource_id << " in cache db"; |
| 415 return false; | 266 return false; |
| 416 } | 267 } |
| 417 | 268 |
| 418 FileCacheEntry cache_entry; | 269 FileCacheEntry cache_entry; |
| 419 const bool ok = cache_entry.ParseFromString(serialized); | 270 const bool ok = cache_entry.ParseFromString(serialized); |
| 420 if (!ok) { | 271 if (!ok) { |
| 421 LOG(ERROR) << "Failed to parse " << serialized; | 272 LOG(ERROR) << "Failed to parse " << serialized; |
| 422 return false; | 273 return false; |
| 423 } | 274 } |
| 424 | 275 |
| 425 if (!CheckIfMd5Matches(md5, cache_entry)) { | 276 if (!CheckIfMd5Matches(md5, cache_entry)) { |
| 426 return false; | 277 return false; |
| 427 } | 278 } |
| 428 | 279 |
| 429 *entry = cache_entry; | 280 *entry = cache_entry; |
| 430 return true; | 281 return true; |
| 431 } | 282 } |
| 432 | 283 |
| 433 void FileCacheMetadataDB::RemoveTemporaryFiles() { | 284 void FileCacheMetadata::RemoveTemporaryFiles() { |
| 434 AssertOnSequencedWorkerPool(); | 285 AssertOnSequencedWorkerPool(); |
| 435 | 286 |
| 436 scoped_ptr<leveldb::Iterator> iter(level_db_->NewIterator( | 287 scoped_ptr<leveldb::Iterator> iter(level_db_->NewIterator( |
| 437 leveldb::ReadOptions())); | 288 leveldb::ReadOptions())); |
| 438 for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { | 289 for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { |
| 439 FileCacheEntry cache_entry; | 290 FileCacheEntry cache_entry; |
| 440 const bool ok = cache_entry.ParseFromArray(iter->value().data(), | 291 const bool ok = cache_entry.ParseFromArray(iter->value().data(), |
| 441 iter->value().size()); | 292 iter->value().size()); |
| 442 if (ok && !cache_entry.is_persistent()) | 293 if (ok && !cache_entry.is_persistent()) |
| 443 level_db_->Delete(leveldb::WriteOptions(), iter->key()); | 294 level_db_->Delete(leveldb::WriteOptions(), iter->key()); |
| 444 } | 295 } |
| 445 } | 296 } |
| 446 | 297 |
| 447 void FileCacheMetadataDB::Iterate(const CacheIterateCallback& callback) { | 298 void FileCacheMetadata::Iterate(const CacheIterateCallback& callback) { |
| 448 AssertOnSequencedWorkerPool(); | 299 AssertOnSequencedWorkerPool(); |
| 449 | 300 |
| 450 scoped_ptr<leveldb::Iterator> iter(level_db_->NewIterator( | 301 scoped_ptr<leveldb::Iterator> iter(level_db_->NewIterator( |
| 451 leveldb::ReadOptions())); | 302 leveldb::ReadOptions())); |
| 452 for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { | 303 for (iter->SeekToFirst(); iter->Valid(); iter->Next()) { |
| 453 FileCacheEntry cache_entry; | 304 FileCacheEntry cache_entry; |
| 454 const bool ok = cache_entry.ParseFromArray(iter->value().data(), | 305 const bool ok = cache_entry.ParseFromArray(iter->value().data(), |
| 455 iter->value().size()); | 306 iter->value().size()); |
| 456 if (ok) | 307 if (ok) |
| 457 callback.Run(iter->key().ToString(), cache_entry); | 308 callback.Run(iter->key().ToString(), cache_entry); |
| 458 } | 309 } |
| 459 } | 310 } |
| 460 | 311 |
| 461 } // namespace | |
| 462 | |
| 463 // static | |
| 464 const base::FilePath::CharType* FileCacheMetadata::kCacheMetadataDBPath = | |
| 465 FILE_PATH_LITERAL("cache_metadata.db"); | |
| 466 | |
| 467 | |
| 468 FileCacheMetadata::FileCacheMetadata( | |
| 469 base::SequencedTaskRunner* blocking_task_runner) | |
| 470 : blocking_task_runner_(blocking_task_runner) { | |
| 471 AssertOnSequencedWorkerPool(); | |
| 472 } | |
| 473 | |
| 474 FileCacheMetadata::~FileCacheMetadata() { | |
| 475 AssertOnSequencedWorkerPool(); | |
| 476 } | |
| 477 | |
| 478 // static | |
| 479 scoped_ptr<FileCacheMetadata> FileCacheMetadata::CreateCacheMetadata( | |
| 480 base::SequencedTaskRunner* blocking_task_runner) { | |
| 481 return scoped_ptr<FileCacheMetadata>( | |
| 482 new FileCacheMetadataDB(blocking_task_runner)); | |
| 483 } | |
| 484 | |
| 485 // static | |
| 486 scoped_ptr<FileCacheMetadata> | |
| 487 FileCacheMetadata::CreateCacheMetadataForTesting( | |
| 488 base::SequencedTaskRunner* blocking_task_runner) { | |
| 489 return scoped_ptr<FileCacheMetadata>( | |
| 490 new FakeCacheMetadata(blocking_task_runner)); | |
| 491 } | |
| 492 | |
| 493 void FileCacheMetadata::AssertOnSequencedWorkerPool() { | 312 void FileCacheMetadata::AssertOnSequencedWorkerPool() { |
| 494 DCHECK(!blocking_task_runner_ || | 313 DCHECK(!blocking_task_runner_ || |
| 495 blocking_task_runner_->RunsTasksOnCurrentThread()); | 314 blocking_task_runner_->RunsTasksOnCurrentThread()); |
| 496 } | 315 } |
| 497 | 316 |
| 498 } // namespace internal | 317 } // namespace internal |
| 499 } // namespace drive | 318 } // namespace drive |
| OLD | NEW |