Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 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 "net/disk_cache/simple/simple_index.h" | 5 #include "net/disk_cache/simple/simple_index.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 157 const base::FilePath& path) | 157 const base::FilePath& path) |
| 158 : cache_size_(0), | 158 : cache_size_(0), |
| 159 max_size_(0), | 159 max_size_(0), |
| 160 high_watermark_(0), | 160 high_watermark_(0), |
| 161 low_watermark_(0), | 161 low_watermark_(0), |
| 162 eviction_in_progress_(false), | 162 eviction_in_progress_(false), |
| 163 initialized_(false), | 163 initialized_(false), |
| 164 index_filename_(path.AppendASCII("the-real-index")), | 164 index_filename_(path.AppendASCII("the-real-index")), |
| 165 cache_thread_(cache_thread), | 165 cache_thread_(cache_thread), |
| 166 io_thread_(io_thread), | 166 io_thread_(io_thread), |
| 167 app_on_background_(false) { | 167 // Creating the callback once so it is reused every time |
| 168 } | 168 // write_to_disk_timer_.Start() is called. |
| 169 write_to_disk_cb_(base::Bind(&SimpleIndex::WriteToDisk, AsWeakPtr())), | |
| 170 app_on_background_(false) {} | |
| 169 | 171 |
| 170 SimpleIndex::~SimpleIndex() { | 172 SimpleIndex::~SimpleIndex() { |
| 171 DCHECK(io_thread_checker_.CalledOnValidThread()); | 173 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 172 | 174 |
| 173 // Fail all callbacks waiting for the index to come up. | 175 // Fail all callbacks waiting for the index to come up. |
| 174 for (CallbackList::iterator it = to_run_when_initialized_.begin(), | 176 for (CallbackList::iterator it = to_run_when_initialized_.begin(), |
| 175 end = to_run_when_initialized_.end(); it != end; ++it) { | 177 end = to_run_when_initialized_.end(); it != end; ++it) { |
| 176 it->Run(net::ERR_ABORTED); | 178 it->Run(net::ERR_ABORTED); |
| 177 } | 179 } |
| 178 } | 180 } |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 253 const uint64 hash_key = simple_util::GetEntryHashKey(key); | 255 const uint64 hash_key = simple_util::GetEntryHashKey(key); |
| 254 InsertInEntrySet(EntryMetadata(hash_key, base::Time::Now(), 0), | 256 InsertInEntrySet(EntryMetadata(hash_key, base::Time::Now(), 0), |
| 255 &entries_set_); | 257 &entries_set_); |
| 256 if (!initialized_) | 258 if (!initialized_) |
| 257 removed_entries_.erase(hash_key); | 259 removed_entries_.erase(hash_key); |
| 258 PostponeWritingToDisk(); | 260 PostponeWritingToDisk(); |
| 259 } | 261 } |
| 260 | 262 |
| 261 void SimpleIndex::Remove(const std::string& key) { | 263 void SimpleIndex::Remove(const std::string& key) { |
| 262 DCHECK(io_thread_checker_.CalledOnValidThread()); | 264 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 263 UpdateEntrySize(key, 0); | |
| 264 const uint64 hash_key = simple_util::GetEntryHashKey(key); | 265 const uint64 hash_key = simple_util::GetEntryHashKey(key); |
| 265 entries_set_.erase(hash_key); | 266 EntrySet::iterator it = entries_set_.find(hash_key); |
| 267 if (it != entries_set_.end()) { | |
| 268 UpdateEntryIteratorSize(&it, 0); | |
| 269 entries_set_.erase(it); | |
| 270 } | |
| 266 | 271 |
| 267 if (!initialized_) | 272 if (!initialized_) |
| 268 removed_entries_.insert(hash_key); | 273 removed_entries_.insert(hash_key); |
| 269 PostponeWritingToDisk(); | 274 PostponeWritingToDisk(); |
| 270 } | 275 } |
| 271 | 276 |
| 272 bool SimpleIndex::Has(const std::string& key) const { | 277 bool SimpleIndex::Has(const std::string& key) const { |
| 273 DCHECK(io_thread_checker_.CalledOnValidThread()); | 278 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 274 // If not initialized, always return true, forcing it to go to the disk. | 279 // If not initialized, always return true, forcing it to go to the disk. |
| 275 return !initialized_ || | 280 return !initialized_ || |
| 276 entries_set_.count(simple_util::GetEntryHashKey(key)) != 0; | 281 entries_set_.count(simple_util::GetEntryHashKey(key)) > 0; |
| 277 } | 282 } |
| 278 | 283 |
| 279 bool SimpleIndex::UseIfExists(const std::string& key) { | 284 bool SimpleIndex::UseIfExists(const std::string& key) { |
| 280 DCHECK(io_thread_checker_.CalledOnValidThread()); | 285 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 281 // Always update the last used time, even if it is during initialization. | 286 // Always update the last used time, even if it is during initialization. |
| 282 // It will be merged later. | 287 // It will be merged later. |
| 283 EntrySet::iterator it = entries_set_.find(simple_util::GetEntryHashKey(key)); | 288 EntrySet::iterator it = entries_set_.find(simple_util::GetEntryHashKey(key)); |
| 284 if (it == entries_set_.end()) | 289 if (it == entries_set_.end()) |
| 285 // If not initialized, always return true, forcing it to go to the disk. | 290 // If not initialized, always return true, forcing it to go to the disk. |
| 286 return !initialized_; | 291 return !initialized_; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 337 base::Passed(&result)); | 342 base::Passed(&result)); |
| 338 base::WorkerPool::PostTaskAndReply(FROM_HERE, task, reply, true); | 343 base::WorkerPool::PostTaskAndReply(FROM_HERE, task, reply, true); |
| 339 } | 344 } |
| 340 | 345 |
| 341 bool SimpleIndex::UpdateEntrySize(const std::string& key, uint64 entry_size) { | 346 bool SimpleIndex::UpdateEntrySize(const std::string& key, uint64 entry_size) { |
| 342 DCHECK(io_thread_checker_.CalledOnValidThread()); | 347 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 343 EntrySet::iterator it = entries_set_.find(simple_util::GetEntryHashKey(key)); | 348 EntrySet::iterator it = entries_set_.find(simple_util::GetEntryHashKey(key)); |
| 344 if (it == entries_set_.end()) | 349 if (it == entries_set_.end()) |
| 345 return false; | 350 return false; |
| 346 | 351 |
| 347 // Update the total cache size with the new entry size. | 352 UpdateEntryIteratorSize(&it, entry_size); |
|
pasko
2013/05/30 13:47:10
Somehow adding this function looks less awkward to
| |
| 348 DCHECK(cache_size_ - it->second.GetEntrySize() <= cache_size_); | |
| 349 cache_size_ -= it->second.GetEntrySize(); | |
| 350 cache_size_ += entry_size; | |
| 351 it->second.SetEntrySize(entry_size); | |
| 352 PostponeWritingToDisk(); | 353 PostponeWritingToDisk(); |
| 353 StartEvictionIfNeeded(); | 354 StartEvictionIfNeeded(); |
| 354 return true; | 355 return true; |
| 355 } | 356 } |
| 356 | 357 |
| 357 void SimpleIndex::EvictionDone(scoped_ptr<int> result) { | 358 void SimpleIndex::EvictionDone(scoped_ptr<int> result) { |
| 358 DCHECK(io_thread_checker_.CalledOnValidThread()); | 359 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 359 DCHECK(result); | 360 DCHECK(result); |
| 360 | 361 |
| 361 // Ignore the result of eviction. We did our best. | 362 // Ignore the result of eviction. We did our best. |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 375 std::make_pair(entry_metadata.GetHashKey(), entry_metadata)); | 376 std::make_pair(entry_metadata.GetHashKey(), entry_metadata)); |
| 376 } | 377 } |
| 377 | 378 |
| 378 void SimpleIndex::PostponeWritingToDisk() { | 379 void SimpleIndex::PostponeWritingToDisk() { |
| 379 if (!initialized_) | 380 if (!initialized_) |
| 380 return; | 381 return; |
| 381 const int delay = app_on_background_ ? kWriteToDiskOnBackgroundDelayMSecs | 382 const int delay = app_on_background_ ? kWriteToDiskOnBackgroundDelayMSecs |
| 382 : kWriteToDiskDelayMSecs; | 383 : kWriteToDiskDelayMSecs; |
| 383 // If the timer is already active, Start() will just Reset it, postponing it. | 384 // If the timer is already active, Start() will just Reset it, postponing it. |
| 384 write_to_disk_timer_.Start( | 385 write_to_disk_timer_.Start( |
| 385 FROM_HERE, | 386 FROM_HERE, base::TimeDelta::FromMilliseconds(delay), write_to_disk_cb_); |
| 386 base::TimeDelta::FromMilliseconds(delay), | 387 } |
| 387 base::Bind(&SimpleIndex::WriteToDisk, AsWeakPtr())); | 388 |
| 389 void SimpleIndex::UpdateEntryIteratorSize(EntrySet::iterator* it, | |
| 390 uint64 entry_size) { | |
| 391 // Update the total cache size with the new entry size. | |
| 392 DCHECK(io_thread_checker_.CalledOnValidThread()); | |
| 393 DCHECK_GE(cache_size_, (*it)->second.GetEntrySize()); | |
| 394 cache_size_ -= (*it)->second.GetEntrySize(); | |
| 395 cache_size_ += entry_size; | |
| 396 (*it)->second.SetEntrySize(entry_size); | |
| 388 } | 397 } |
| 389 | 398 |
| 390 // static | 399 // static |
| 391 bool SimpleIndex::IsIndexFileStale(const base::FilePath& index_filename) { | 400 bool SimpleIndex::IsIndexFileStale(const base::FilePath& index_filename) { |
| 392 base::Time index_mtime; | 401 base::Time index_mtime; |
| 393 base::Time dir_mtime; | 402 base::Time dir_mtime; |
| 394 if (!GetMTime(index_filename.DirName(), &dir_mtime)) | 403 if (!GetMTime(index_filename.DirName(), &dir_mtime)) |
| 395 return true; | 404 return true; |
| 396 if (!GetMTime(index_filename, &index_mtime)) | 405 if (!GetMTime(index_filename, &index_mtime)) |
| 397 return true; | 406 return true; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 470 using file_util::FileEnumerator; | 479 using file_util::FileEnumerator; |
| 471 LOG(INFO) << "Simple Cache Index is being restored from disk."; | 480 LOG(INFO) << "Simple Cache Index is being restored from disk."; |
| 472 | 481 |
| 473 file_util::Delete(index_filename, /* recursive = */ false); | 482 file_util::Delete(index_filename, /* recursive = */ false); |
| 474 scoped_ptr<EntrySet> index_file_entries(new EntrySet()); | 483 scoped_ptr<EntrySet> index_file_entries(new EntrySet()); |
| 475 | 484 |
| 476 // TODO(felipeg,gavinp): Fix this once we have a one-file per entry format. | 485 // TODO(felipeg,gavinp): Fix this once we have a one-file per entry format. |
| 477 COMPILE_ASSERT(kSimpleEntryFileCount == 3, | 486 COMPILE_ASSERT(kSimpleEntryFileCount == 3, |
| 478 file_pattern_must_match_file_count); | 487 file_pattern_must_match_file_count); |
| 479 | 488 |
| 480 const int kFileSuffixLenght = std::string("_0").size(); | 489 const int kFileSuffixLength = strlen("_0"); |
|
gavinp
2013/05/30 13:50:40
As long as we're playing this game, you could make
| |
| 481 const base::FilePath::StringType file_pattern = FILE_PATH_LITERAL("*_[0-2]"); | 490 const base::FilePath::StringType file_pattern = FILE_PATH_LITERAL("*_[0-2]"); |
| 482 FileEnumerator enumerator(index_filename.DirName(), | 491 FileEnumerator enumerator(index_filename.DirName(), |
| 483 false /* recursive */, | 492 false /* recursive */, |
| 484 FileEnumerator::FILES, | 493 FileEnumerator::FILES, |
| 485 file_pattern); | 494 file_pattern); |
| 486 for (base::FilePath file_path = enumerator.Next(); !file_path.empty(); | 495 for (base::FilePath file_path = enumerator.Next(); !file_path.empty(); |
| 487 file_path = enumerator.Next()) { | 496 file_path = enumerator.Next()) { |
| 488 const base::FilePath::StringType base_name = file_path.BaseName().value(); | 497 const base::FilePath::StringType base_name = file_path.BaseName().value(); |
| 489 // Converting to std::string is OK since we never use UTF8 wide chars in our | 498 // Converting to std::string is OK since we never use UTF8 wide chars in our |
| 490 // file names. | 499 // file names. |
| 491 const std::string hash_name(base_name.begin(), base_name.end()); | 500 const std::string hash_key_string(base_name.begin(), |
| 492 const std::string hash_key_string = | 501 base_name.end() - kFileSuffixLength); |
| 493 hash_name.substr(0, hash_name.size() - kFileSuffixLenght); | |
| 494 uint64 hash_key = 0; | 502 uint64 hash_key = 0; |
| 495 if (!simple_util::GetEntryHashKeyFromHexString( | 503 if (!simple_util::GetEntryHashKeyFromHexString( |
| 496 hash_key_string, &hash_key)) { | 504 hash_key_string, &hash_key)) { |
| 497 LOG(WARNING) << "Invalid Entry Hash Key filename while restoring " | 505 LOG(WARNING) << "Invalid Entry Hash Key filename while restoring " |
| 498 << "Simple Index from disk: " << hash_name; | 506 << "Simple Index from disk: " << base_name; |
| 499 // TODO(felipeg): Should we delete the invalid file here ? | 507 // TODO(felipeg): Should we delete the invalid file here ? |
| 500 continue; | 508 continue; |
| 501 } | 509 } |
| 502 | 510 |
| 503 FileEnumerator::FindInfo find_info = {}; | 511 FileEnumerator::FindInfo find_info = {}; |
| 504 enumerator.GetFindInfo(&find_info); | 512 enumerator.GetFindInfo(&find_info); |
| 505 base::Time last_used_time; | 513 base::Time last_used_time; |
| 506 #if defined(OS_POSIX) | 514 #if defined(OS_POSIX) |
| 507 // For POSIX systems, a last access time is available. However, it's not | 515 // For POSIX systems, a last access time is available. However, it's not |
| 508 // guaranteed to be more accurate than mtime. It is no worse though. | 516 // guaranteed to be more accurate than mtime. It is no worse though. |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 626 entries_set_); | 634 entries_set_); |
| 627 cache_thread_->PostTask(FROM_HERE, base::Bind( | 635 cache_thread_->PostTask(FROM_HERE, base::Bind( |
| 628 &SimpleIndex::WriteToDiskInternal, | 636 &SimpleIndex::WriteToDiskInternal, |
| 629 index_filename_, | 637 index_filename_, |
| 630 base::Passed(&pickle), | 638 base::Passed(&pickle), |
| 631 start, | 639 start, |
| 632 app_on_background_)); | 640 app_on_background_)); |
| 633 } | 641 } |
| 634 | 642 |
| 635 } // namespace disk_cache | 643 } // namespace disk_cache |
| OLD | NEW |