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 14 matching lines...) Expand all Loading... | |
| 25 | 25 |
| 26 #if defined(OS_POSIX) | 26 #if defined(OS_POSIX) |
| 27 #include <sys/stat.h> | 27 #include <sys/stat.h> |
| 28 #include <sys/time.h> | 28 #include <sys/time.h> |
| 29 #endif | 29 #endif |
| 30 | 30 |
| 31 namespace { | 31 namespace { |
| 32 | 32 |
| 33 // How many seconds we delay writing the index to disk since the last cache | 33 // How many seconds we delay writing the index to disk since the last cache |
| 34 // operation has happened. | 34 // operation has happened. |
| 35 const int kWriteToDiskDelaySecs = 20; | 35 const int kWriteToDiskDelayMSecs = 20000; |
| 36 | 36 const int kWriteToDiskOnBackgroundDelayMSecs = 100; |
| 37 // WriteToDisk at lest every 5 minutes. | |
| 38 const int kMaxWriteToDiskDelaySecs = 300; | |
| 39 | 37 |
| 40 // Divides the cache space into this amount of parts to evict when only one part | 38 // Divides the cache space into this amount of parts to evict when only one part |
| 41 // is left. | 39 // is left. |
| 42 const uint32 kEvictionMarginDivisor = 20; | 40 const uint32 kEvictionMarginDivisor = 20; |
| 43 | 41 |
| 44 // Utility class used for timestamp comparisons in entry metadata while sorting. | 42 // Utility class used for timestamp comparisons in entry metadata while sorting. |
| 45 class CompareHashesForTimestamp { | 43 class CompareHashesForTimestamp { |
| 46 typedef disk_cache::SimpleIndex SimpleIndex; | 44 typedef disk_cache::SimpleIndex SimpleIndex; |
| 47 typedef disk_cache::SimpleIndex::EntrySet EntrySet; | 45 typedef disk_cache::SimpleIndex::EntrySet EntrySet; |
| 48 public: | 46 public: |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 150 DCHECK_EQ(hash_key_, from.hash_key_); | 148 DCHECK_EQ(hash_key_, from.hash_key_); |
| 151 if (last_used_time_ == 0) | 149 if (last_used_time_ == 0) |
| 152 last_used_time_ = from.last_used_time_; | 150 last_used_time_ = from.last_used_time_; |
| 153 if (entry_size_ == 0) | 151 if (entry_size_ == 0) |
| 154 entry_size_ = from.entry_size_; | 152 entry_size_ = from.entry_size_; |
| 155 } | 153 } |
| 156 | 154 |
| 157 SimpleIndex::SimpleIndex( | 155 SimpleIndex::SimpleIndex( |
| 158 base::SingleThreadTaskRunner* cache_thread, | 156 base::SingleThreadTaskRunner* cache_thread, |
| 159 base::SingleThreadTaskRunner* io_thread, | 157 base::SingleThreadTaskRunner* io_thread, |
| 160 const base::FilePath& path) | 158 const base::FilePath& path) : |
| 161 : cache_size_(0), | 159 #if defined(OS_ANDROID) |
| 160 activity_status_listener_( | |
| 161 base::Bind(&SimpleIndex::OnActivityStateChange, AsWeakPtr())), | |
|
pasko-google - do not use
2013/05/03 10:30:54
this operation feels a bit too non-trivial for a c
gavinp
2013/05/03 12:16:53
Done.
| |
| 162 #endif | |
| 163 cache_size_(0), | |
| 162 max_size_(0), | 164 max_size_(0), |
| 163 high_watermark_(0), | 165 high_watermark_(0), |
| 164 low_watermark_(0), | 166 low_watermark_(0), |
| 165 eviction_in_progress_(false), | 167 eviction_in_progress_(false), |
| 166 initialized_(false), | 168 initialized_(false), |
| 167 index_filename_(path.AppendASCII("the-real-index")), | 169 index_filename_(path.AppendASCII("the-real-index")), |
| 168 cache_thread_(cache_thread), | 170 cache_thread_(cache_thread), |
| 169 io_thread_(io_thread) { | 171 io_thread_(io_thread), |
| 172 app_on_background_(false) { | |
| 170 } | 173 } |
| 171 | 174 |
| 172 SimpleIndex::~SimpleIndex() { | 175 SimpleIndex::~SimpleIndex() { |
| 173 DCHECK(io_thread_checker_.CalledOnValidThread()); | 176 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 174 | 177 |
| 175 // Fail all callbacks waiting for the index to come up. | 178 // Fail all callbacks waiting for the index to come up. |
| 176 for (CallbackList::iterator it = to_run_when_initialized_.begin(), | 179 for (CallbackList::iterator it = to_run_when_initialized_.begin(), |
| 177 end = to_run_when_initialized_.end(); it != end; ++it) { | 180 end = to_run_when_initialized_.end(); it != end; ++it) { |
| 178 it->Run(net::ERR_ABORTED); | 181 it->Run(net::ERR_ABORTED); |
| 179 } | 182 } |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 367 const disk_cache::EntryMetadata& entry_metadata, | 370 const disk_cache::EntryMetadata& entry_metadata, |
| 368 EntrySet* entry_set) { | 371 EntrySet* entry_set) { |
| 369 DCHECK(entry_set); | 372 DCHECK(entry_set); |
| 370 entry_set->insert( | 373 entry_set->insert( |
| 371 std::make_pair(entry_metadata.GetHashKey(), entry_metadata)); | 374 std::make_pair(entry_metadata.GetHashKey(), entry_metadata)); |
| 372 } | 375 } |
| 373 | 376 |
| 374 void SimpleIndex::PostponeWritingToDisk() { | 377 void SimpleIndex::PostponeWritingToDisk() { |
| 375 if (!initialized_) | 378 if (!initialized_) |
| 376 return; | 379 return; |
| 377 const base::TimeDelta file_age = base::Time::Now() - last_write_to_disk_; | 380 const int delay = app_on_background_ ? kWriteToDiskOnBackgroundDelayMSecs |
| 378 if (file_age > base::TimeDelta::FromSeconds(kMaxWriteToDiskDelaySecs) && | 381 : kWriteToDiskDelayMSecs; |
| 379 write_to_disk_timer_.IsRunning()) { | |
| 380 // If the index file is too old and there is a timer programmed to run a | |
| 381 // WriteToDisk soon, we don't postpone it, so we always WriteToDisk | |
| 382 // approximately every kMaxWriteToDiskDelaySecs. | |
| 383 return; | |
| 384 } | |
| 385 | |
| 386 // If the timer is already active, Start() will just Reset it, postponing it. | 382 // If the timer is already active, Start() will just Reset it, postponing it. |
| 387 write_to_disk_timer_.Start( | 383 write_to_disk_timer_.Start( |
| 388 FROM_HERE, | 384 FROM_HERE, |
| 389 base::TimeDelta::FromSeconds(kWriteToDiskDelaySecs), | 385 base::TimeDelta::FromMilliseconds(delay), |
|
pasko-google - do not use
2013/05/03 10:30:54
So at maximum it can write the index every 100ms,
gavinp
2013/05/03 12:16:53
I think in a followup; we currently measure index
| |
| 390 base::Bind(&SimpleIndex::WriteToDisk, AsWeakPtr())); | 386 base::Bind(&SimpleIndex::WriteToDisk, AsWeakPtr())); |
| 391 } | 387 } |
| 392 | 388 |
| 393 // static | 389 // static |
| 394 bool SimpleIndex::IsIndexFileStale(const base::FilePath& index_filename) { | 390 bool SimpleIndex::IsIndexFileStale(const base::FilePath& index_filename) { |
| 395 base::Time index_mtime; | 391 base::Time index_mtime; |
| 396 base::Time dir_mtime; | 392 base::Time dir_mtime; |
| 397 if (!GetMTime(index_filename.DirName(), &dir_mtime)) | 393 if (!GetMTime(index_filename.DirName(), &dir_mtime)) |
| 398 return true; | 394 return true; |
| 399 if (!GetMTime(index_filename, &index_mtime)) | 395 if (!GetMTime(index_filename, &index_mtime)) |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 539 if (current_entry != entries_set_.end()) { | 535 if (current_entry != entries_set_.end()) { |
| 540 // When Merging, existing valid data in the |current_entry| will prevail. | 536 // When Merging, existing valid data in the |current_entry| will prevail. |
| 541 cache_size_ -= current_entry->second.GetEntrySize(); | 537 cache_size_ -= current_entry->second.GetEntrySize(); |
| 542 current_entry->second.MergeWith(it->second); | 538 current_entry->second.MergeWith(it->second); |
| 543 cache_size_ += current_entry->second.GetEntrySize(); | 539 cache_size_ += current_entry->second.GetEntrySize(); |
| 544 } else { | 540 } else { |
| 545 InsertInEntrySet(it->second, &entries_set_); | 541 InsertInEntrySet(it->second, &entries_set_); |
| 546 cache_size_ += it->second.GetEntrySize(); | 542 cache_size_ += it->second.GetEntrySize(); |
| 547 } | 543 } |
| 548 } | 544 } |
| 549 last_write_to_disk_ = base::Time::Now(); | |
| 550 initialized_ = true; | 545 initialized_ = true; |
| 551 removed_entries_.clear(); | 546 removed_entries_.clear(); |
| 552 | 547 |
| 553 // The actual IO is asynchronous, so calling WriteToDisk() shouldn't slow down | 548 // The actual IO is asynchronous, so calling WriteToDisk() shouldn't slow down |
| 554 // much the merge. | 549 // much the merge. |
| 555 if (force_index_flush) | 550 if (force_index_flush) |
| 556 WriteToDisk(); | 551 WriteToDisk(); |
| 557 | 552 |
| 558 UMA_HISTOGRAM_CUSTOM_COUNTS("SimpleCache.IndexInitializationWaiters", | 553 UMA_HISTOGRAM_CUSTOM_COUNTS("SimpleCache.IndexInitializationWaiters", |
| 559 to_run_when_initialized_.size(), 0, 100, 20); | 554 to_run_when_initialized_.size(), 0, 100, 20); |
| 560 // Run all callbacks waiting for the index to come up. | 555 // Run all callbacks waiting for the index to come up. |
| 561 for (CallbackList::iterator it = to_run_when_initialized_.begin(), | 556 for (CallbackList::iterator it = to_run_when_initialized_.begin(), |
| 562 end = to_run_when_initialized_.end(); it != end; ++it) { | 557 end = to_run_when_initialized_.end(); it != end; ++it) { |
| 563 io_thread_->PostTask(FROM_HERE, base::Bind((*it), net::OK)); | 558 io_thread_->PostTask(FROM_HERE, base::Bind((*it), net::OK)); |
| 564 } | 559 } |
| 565 to_run_when_initialized_.clear(); | 560 to_run_when_initialized_.clear(); |
| 566 } | 561 } |
| 567 | 562 |
| 563 #if defined(OS_ANDROID) | |
| 564 void SimpleIndex::OnActivityStateChange( | |
| 565 base::android::ActivityState state) { | |
| 566 DCHECK(io_thread_checker_.CalledOnValidThread()); | |
| 567 // For more info about android activities, see: | |
| 568 // developer.android.com/training/basics/activity-lifecycle/pausing.html | |
| 569 // These values are defined in the file ActivityStatus.java | |
| 570 if (state == base::android::ACTIVITY_STATE_RESUMED) { | |
| 571 app_on_background_ = false; | |
| 572 } else if (state == base::android::ACTIVITY_STATE_STOPPED) { | |
|
felipeg
2013/05/03 10:03:00
I know Philippe told you that STATE_STOPPED is eno
Philippe
2013/05/03 10:11:47
STOPPED is supposed to be enough. Its support was
| |
| 573 app_on_background_ = true; | |
| 574 WriteToDisk(); | |
| 575 } | |
| 576 } | |
| 577 #endif | |
| 578 | |
| 568 void SimpleIndex::WriteToDisk() { | 579 void SimpleIndex::WriteToDisk() { |
| 569 DCHECK(io_thread_checker_.CalledOnValidThread()); | 580 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 570 if (!initialized_) | 581 if (!initialized_) |
| 571 return; | 582 return; |
| 572 UMA_HISTOGRAM_CUSTOM_COUNTS("SimpleCache.IndexNumEntriesOnWrite", | 583 UMA_HISTOGRAM_CUSTOM_COUNTS("SimpleCache.IndexNumEntriesOnWrite", |
| 573 entries_set_.size(), 0, 100000, 50); | 584 entries_set_.size(), 0, 100000, 50); |
| 574 const base::TimeTicks start = base::TimeTicks::Now(); | 585 const base::TimeTicks start = base::TimeTicks::Now(); |
| 575 last_write_to_disk_ = base::Time::Now(); | 586 last_write_to_disk_ = base::Time::Now(); |
| 576 SimpleIndexFile::IndexMetadata index_metadata(entries_set_.size(), | 587 SimpleIndexFile::IndexMetadata index_metadata(entries_set_.size(), |
| 577 cache_size_); | 588 cache_size_); |
| 578 scoped_ptr<Pickle> pickle = SimpleIndexFile::Serialize(index_metadata, | 589 scoped_ptr<Pickle> pickle = SimpleIndexFile::Serialize(index_metadata, |
| 579 entries_set_); | 590 entries_set_); |
| 580 cache_thread_->PostTask(FROM_HERE, base::Bind( | 591 cache_thread_->PostTask(FROM_HERE, base::Bind( |
| 581 &SimpleIndex::WriteToDiskInternal, | 592 &SimpleIndex::WriteToDiskInternal, |
| 582 index_filename_, | 593 index_filename_, |
| 583 base::Passed(&pickle), | 594 base::Passed(&pickle), |
| 584 start)); | 595 start)); |
| 585 } | 596 } |
| 586 | 597 |
| 587 } // namespace disk_cache | 598 } // namespace disk_cache |
| OLD | NEW |