| 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 // Divides the cache space into this amount of parts to evict when only one part | 45 // Divides the cache space into this amount of parts to evict when only one part |
| 46 // is left. | 46 // is left. |
| 47 const uint32 kEvictionMarginDivisor = 20; | 47 const uint32 kEvictionMarginDivisor = 20; |
| 48 | 48 |
| 49 const uint32 kBytesInKb = 1024; | 49 const uint32 kBytesInKb = 1024; |
| 50 | 50 |
| 51 // Utility class used for timestamp comparisons in entry metadata while sorting. | 51 // Utility class used for timestamp comparisons in entry metadata while sorting. |
| 52 class CompareHashesForTimestamp { | 52 class CompareHashesForTimestamp { |
| 53 typedef disk_cache::SimpleIndex SimpleIndex; | 53 typedef disk_cache::SimpleIndex SimpleIndex; |
| 54 typedef disk_cache::SimpleIndex::EntrySet EntrySet; | 54 typedef disk_cache::SimpleIndex::EntrySet EntrySet; |
| 55 |
| 55 public: | 56 public: |
| 56 explicit CompareHashesForTimestamp(const EntrySet& set); | 57 explicit CompareHashesForTimestamp(const EntrySet& set); |
| 57 | 58 |
| 58 bool operator()(uint64 hash1, uint64 hash2); | 59 bool operator()(uint64 hash1, uint64 hash2); |
| 60 |
| 59 private: | 61 private: |
| 60 const EntrySet& entry_set_; | 62 const EntrySet& entry_set_; |
| 61 }; | 63 }; |
| 62 | 64 |
| 63 CompareHashesForTimestamp::CompareHashesForTimestamp(const EntrySet& set) | 65 CompareHashesForTimestamp::CompareHashesForTimestamp(const EntrySet& set) |
| 64 : entry_set_(set) { | 66 : entry_set_(set) { |
| 65 } | 67 } |
| 66 | 68 |
| 67 bool CompareHashesForTimestamp::operator()(uint64 hash1, uint64 hash2) { | 69 bool CompareHashesForTimestamp::operator()(uint64 hash1, uint64 hash2) { |
| 68 EntrySet::const_iterator it1 = entry_set_.find(hash1); | 70 EntrySet::const_iterator it1 = entry_set_.find(hash1); |
| 69 DCHECK(it1 != entry_set_.end()); | 71 DCHECK(it1 != entry_set_.end()); |
| 70 EntrySet::const_iterator it2 = entry_set_.find(hash2); | 72 EntrySet::const_iterator it2 = entry_set_.find(hash2); |
| 71 DCHECK(it2 != entry_set_.end()); | 73 DCHECK(it2 != entry_set_.end()); |
| 72 return it1->second.GetLastUsedTime() < it2->second.GetLastUsedTime(); | 74 return it1->second.GetLastUsedTime() < it2->second.GetLastUsedTime(); |
| 73 } | 75 } |
| 74 | 76 |
| 75 } // namespace | 77 } // namespace |
| 76 | 78 |
| 77 namespace disk_cache { | 79 namespace disk_cache { |
| 78 | 80 |
| 79 EntryMetadata::EntryMetadata() | 81 EntryMetadata::EntryMetadata() |
| 80 : last_used_time_seconds_since_epoch_(0), | 82 : last_used_time_seconds_since_epoch_(0), entry_size_(0) { |
| 81 entry_size_(0) { | |
| 82 } | 83 } |
| 83 | 84 |
| 84 EntryMetadata::EntryMetadata(base::Time last_used_time, int entry_size) | 85 EntryMetadata::EntryMetadata(base::Time last_used_time, int entry_size) |
| 85 : last_used_time_seconds_since_epoch_(0), | 86 : last_used_time_seconds_since_epoch_(0), entry_size_(entry_size) { |
| 86 entry_size_(entry_size) { | |
| 87 SetLastUsedTime(last_used_time); | 87 SetLastUsedTime(last_used_time); |
| 88 } | 88 } |
| 89 | 89 |
| 90 base::Time EntryMetadata::GetLastUsedTime() const { | 90 base::Time EntryMetadata::GetLastUsedTime() const { |
| 91 // Preserve nullity. | 91 // Preserve nullity. |
| 92 if (last_used_time_seconds_since_epoch_ == 0) | 92 if (last_used_time_seconds_since_epoch_ == 0) |
| 93 return base::Time(); | 93 return base::Time(); |
| 94 | 94 |
| 95 return base::Time::UnixEpoch() + | 95 return base::Time::UnixEpoch() + |
| 96 base::TimeDelta::FromSeconds(last_used_time_seconds_since_epoch_); | 96 base::TimeDelta::FromSeconds(last_used_time_seconds_since_epoch_); |
| 97 } | 97 } |
| 98 | 98 |
| 99 void EntryMetadata::SetLastUsedTime(const base::Time& last_used_time) { | 99 void EntryMetadata::SetLastUsedTime(const base::Time& last_used_time) { |
| 100 // Preserve nullity. | 100 // Preserve nullity. |
| 101 if (last_used_time.is_null()) { | 101 if (last_used_time.is_null()) { |
| 102 last_used_time_seconds_since_epoch_ = 0; | 102 last_used_time_seconds_since_epoch_ = 0; |
| 103 return; | 103 return; |
| 104 } | 104 } |
| 105 | 105 |
| 106 const base::TimeDelta since_unix_epoch = | 106 const base::TimeDelta since_unix_epoch = |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 145 max_size_(0), | 145 max_size_(0), |
| 146 high_watermark_(0), | 146 high_watermark_(0), |
| 147 low_watermark_(0), | 147 low_watermark_(0), |
| 148 eviction_in_progress_(false), | 148 eviction_in_progress_(false), |
| 149 initialized_(false), | 149 initialized_(false), |
| 150 index_file_(index_file.Pass()), | 150 index_file_(index_file.Pass()), |
| 151 io_thread_(io_thread), | 151 io_thread_(io_thread), |
| 152 // Creating the callback once so it is reused every time | 152 // Creating the callback once so it is reused every time |
| 153 // write_to_disk_timer_.Start() is called. | 153 // write_to_disk_timer_.Start() is called. |
| 154 write_to_disk_cb_(base::Bind(&SimpleIndex::WriteToDisk, AsWeakPtr())), | 154 write_to_disk_cb_(base::Bind(&SimpleIndex::WriteToDisk, AsWeakPtr())), |
| 155 app_on_background_(false) {} | 155 app_on_background_(false) { |
| 156 } |
| 156 | 157 |
| 157 SimpleIndex::~SimpleIndex() { | 158 SimpleIndex::~SimpleIndex() { |
| 158 DCHECK(io_thread_checker_.CalledOnValidThread()); | 159 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 159 | 160 |
| 160 // Fail all callbacks waiting for the index to come up. | 161 // Fail all callbacks waiting for the index to come up. |
| 161 for (CallbackList::iterator it = to_run_when_initialized_.begin(), | 162 for (CallbackList::iterator it = to_run_when_initialized_.begin(), |
| 162 end = to_run_when_initialized_.end(); it != end; ++it) { | 163 end = to_run_when_initialized_.end(); |
| 164 it != end; |
| 165 ++it) { |
| 163 it->Run(net::ERR_ABORTED); | 166 it->Run(net::ERR_ABORTED); |
| 164 } | 167 } |
| 165 } | 168 } |
| 166 | 169 |
| 167 void SimpleIndex::Initialize(base::Time cache_mtime) { | 170 void SimpleIndex::Initialize(base::Time cache_mtime) { |
| 168 DCHECK(io_thread_checker_.CalledOnValidThread()); | 171 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 169 | 172 |
| 170 // Take the foreground and background index flush delays from the experiment | 173 // Take the foreground and background index flush delays from the experiment |
| 171 // settings only if both are valid. | 174 // settings only if both are valid. |
| 172 foreground_flush_delay_ = kDefaultWriteToDiskDelayMSecs; | 175 foreground_flush_delay_ = kDefaultWriteToDiskDelayMSecs; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 187 | 190 |
| 188 #if defined(OS_ANDROID) | 191 #if defined(OS_ANDROID) |
| 189 if (base::android::IsVMInitialized()) { | 192 if (base::android::IsVMInitialized()) { |
| 190 app_status_listener_.reset(new base::android::ApplicationStatusListener( | 193 app_status_listener_.reset(new base::android::ApplicationStatusListener( |
| 191 base::Bind(&SimpleIndex::OnApplicationStateChange, AsWeakPtr()))); | 194 base::Bind(&SimpleIndex::OnApplicationStateChange, AsWeakPtr()))); |
| 192 } | 195 } |
| 193 #endif | 196 #endif |
| 194 | 197 |
| 195 SimpleIndexLoadResult* load_result = new SimpleIndexLoadResult(); | 198 SimpleIndexLoadResult* load_result = new SimpleIndexLoadResult(); |
| 196 scoped_ptr<SimpleIndexLoadResult> load_result_scoped(load_result); | 199 scoped_ptr<SimpleIndexLoadResult> load_result_scoped(load_result); |
| 197 base::Closure reply = base::Bind( | 200 base::Closure reply = base::Bind(&SimpleIndex::MergeInitializingSet, |
| 198 &SimpleIndex::MergeInitializingSet, | 201 AsWeakPtr(), |
| 199 AsWeakPtr(), | 202 base::Passed(&load_result_scoped)); |
| 200 base::Passed(&load_result_scoped)); | |
| 201 index_file_->LoadIndexEntries(cache_mtime, reply, load_result); | 203 index_file_->LoadIndexEntries(cache_mtime, reply, load_result); |
| 202 } | 204 } |
| 203 | 205 |
| 204 bool SimpleIndex::SetMaxSize(int max_bytes) { | 206 bool SimpleIndex::SetMaxSize(int max_bytes) { |
| 205 if (max_bytes < 0) | 207 if (max_bytes < 0) |
| 206 return false; | 208 return false; |
| 207 | 209 |
| 208 // Zero size means use the default. | 210 // Zero size means use the default. |
| 209 if (!max_bytes) | 211 if (!max_bytes) |
| 210 return true; | 212 return true; |
| 211 | 213 |
| 212 max_size_ = max_bytes; | 214 max_size_ = max_bytes; |
| 213 high_watermark_ = max_size_ - max_size_ / kEvictionMarginDivisor; | 215 high_watermark_ = max_size_ - max_size_ / kEvictionMarginDivisor; |
| 214 low_watermark_ = max_size_ - 2 * (max_size_ / kEvictionMarginDivisor); | 216 low_watermark_ = max_size_ - 2 * (max_size_ / kEvictionMarginDivisor); |
| 215 return true; | 217 return true; |
| 216 } | 218 } |
| 217 | 219 |
| 218 int SimpleIndex::ExecuteWhenReady(const net::CompletionCallback& task) { | 220 int SimpleIndex::ExecuteWhenReady(const net::CompletionCallback& task) { |
| 219 DCHECK(io_thread_checker_.CalledOnValidThread()); | 221 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 220 if (initialized_) | 222 if (initialized_) |
| 221 io_thread_->PostTask(FROM_HERE, base::Bind(task, net::OK)); | 223 io_thread_->PostTask(FROM_HERE, base::Bind(task, net::OK)); |
| 222 else | 224 else |
| 223 to_run_when_initialized_.push_back(task); | 225 to_run_when_initialized_.push_back(task); |
| 224 return net::ERR_IO_PENDING; | 226 return net::ERR_IO_PENDING; |
| 225 } | 227 } |
| 226 | 228 |
| 227 scoped_ptr<SimpleIndex::HashList> SimpleIndex::GetEntriesBetween( | 229 scoped_ptr<SimpleIndex::HashList> SimpleIndex::GetEntriesBetween( |
| 228 base::Time initial_time, base::Time end_time) { | 230 base::Time initial_time, |
| 231 base::Time end_time) { |
| 229 DCHECK_EQ(true, initialized_); | 232 DCHECK_EQ(true, initialized_); |
| 230 | 233 |
| 231 if (!initial_time.is_null()) | 234 if (!initial_time.is_null()) |
| 232 initial_time -= EntryMetadata::GetLowerEpsilonForTimeComparisons(); | 235 initial_time -= EntryMetadata::GetLowerEpsilonForTimeComparisons(); |
| 233 if (end_time.is_null()) | 236 if (end_time.is_null()) |
| 234 end_time = base::Time::Max(); | 237 end_time = base::Time::Max(); |
| 235 else | 238 else |
| 236 end_time += EntryMetadata::GetUpperEpsilonForTimeComparisons(); | 239 end_time += EntryMetadata::GetUpperEpsilonForTimeComparisons(); |
| 237 const base::Time extended_end_time = | 240 const base::Time extended_end_time = |
| 238 end_time.is_null() ? base::Time::Max() : end_time; | 241 end_time.is_null() ? base::Time::Max() : end_time; |
| 239 DCHECK(extended_end_time >= initial_time); | 242 DCHECK(extended_end_time >= initial_time); |
| 240 scoped_ptr<HashList> ret_hashes(new HashList()); | 243 scoped_ptr<HashList> ret_hashes(new HashList()); |
| 241 for (EntrySet::iterator it = entries_set_.begin(), end = entries_set_.end(); | 244 for (EntrySet::iterator it = entries_set_.begin(), end = entries_set_.end(); |
| 242 it != end; ++it) { | 245 it != end; |
| 246 ++it) { |
| 243 EntryMetadata& metadata = it->second; | 247 EntryMetadata& metadata = it->second; |
| 244 base::Time entry_time = metadata.GetLastUsedTime(); | 248 base::Time entry_time = metadata.GetLastUsedTime(); |
| 245 if (initial_time <= entry_time && entry_time < extended_end_time) | 249 if (initial_time <= entry_time && entry_time < extended_end_time) |
| 246 ret_hashes->push_back(it->first); | 250 ret_hashes->push_back(it->first); |
| 247 } | 251 } |
| 248 return ret_hashes.Pass(); | 252 return ret_hashes.Pass(); |
| 249 } | 253 } |
| 250 | 254 |
| 251 scoped_ptr<SimpleIndex::HashList> SimpleIndex::GetAllHashes() { | 255 scoped_ptr<SimpleIndex::HashList> SimpleIndex::GetAllHashes() { |
| 252 return GetEntriesBetween(base::Time(), base::Time()); | 256 return GetEntriesBetween(base::Time(), base::Time()); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 } | 306 } |
| 303 | 307 |
| 304 void SimpleIndex::StartEvictionIfNeeded() { | 308 void SimpleIndex::StartEvictionIfNeeded() { |
| 305 DCHECK(io_thread_checker_.CalledOnValidThread()); | 309 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 306 if (eviction_in_progress_ || cache_size_ <= high_watermark_) | 310 if (eviction_in_progress_ || cache_size_ <= high_watermark_) |
| 307 return; | 311 return; |
| 308 // Take all live key hashes from the index and sort them by time. | 312 // Take all live key hashes from the index and sort them by time. |
| 309 eviction_in_progress_ = true; | 313 eviction_in_progress_ = true; |
| 310 eviction_start_time_ = base::TimeTicks::Now(); | 314 eviction_start_time_ = base::TimeTicks::Now(); |
| 311 SIMPLE_CACHE_UMA(MEMORY_KB, | 315 SIMPLE_CACHE_UMA(MEMORY_KB, |
| 312 "Eviction.CacheSizeOnStart2", cache_type_, | 316 "Eviction.CacheSizeOnStart2", |
| 317 cache_type_, |
| 313 cache_size_ / kBytesInKb); | 318 cache_size_ / kBytesInKb); |
| 314 SIMPLE_CACHE_UMA(MEMORY_KB, | 319 SIMPLE_CACHE_UMA(MEMORY_KB, |
| 315 "Eviction.MaxCacheSizeOnStart2", cache_type_, | 320 "Eviction.MaxCacheSizeOnStart2", |
| 321 cache_type_, |
| 316 max_size_ / kBytesInKb); | 322 max_size_ / kBytesInKb); |
| 317 std::vector<uint64> entry_hashes; | 323 std::vector<uint64> entry_hashes; |
| 318 entry_hashes.reserve(entries_set_.size()); | 324 entry_hashes.reserve(entries_set_.size()); |
| 319 for (EntrySet::const_iterator it = entries_set_.begin(), | 325 for (EntrySet::const_iterator it = entries_set_.begin(), |
| 320 end = entries_set_.end(); it != end; ++it) { | 326 end = entries_set_.end(); |
| 327 it != end; |
| 328 ++it) { |
| 321 entry_hashes.push_back(it->first); | 329 entry_hashes.push_back(it->first); |
| 322 } | 330 } |
| 323 std::sort(entry_hashes.begin(), entry_hashes.end(), | 331 std::sort(entry_hashes.begin(), |
| 332 entry_hashes.end(), |
| 324 CompareHashesForTimestamp(entries_set_)); | 333 CompareHashesForTimestamp(entries_set_)); |
| 325 | 334 |
| 326 // Remove as many entries from the index to get below |low_watermark_|. | 335 // Remove as many entries from the index to get below |low_watermark_|. |
| 327 std::vector<uint64>::iterator it = entry_hashes.begin(); | 336 std::vector<uint64>::iterator it = entry_hashes.begin(); |
| 328 uint64 evicted_so_far_size = 0; | 337 uint64 evicted_so_far_size = 0; |
| 329 while (evicted_so_far_size < cache_size_ - low_watermark_) { | 338 while (evicted_so_far_size < cache_size_ - low_watermark_) { |
| 330 DCHECK(it != entry_hashes.end()); | 339 DCHECK(it != entry_hashes.end()); |
| 331 EntrySet::iterator found_meta = entries_set_.find(*it); | 340 EntrySet::iterator found_meta = entries_set_.find(*it); |
| 332 DCHECK(found_meta != entries_set_.end()); | 341 DCHECK(found_meta != entries_set_.end()); |
| 333 uint64 to_evict_size = found_meta->second.GetEntrySize(); | 342 uint64 to_evict_size = found_meta->second.GetEntrySize(); |
| 334 evicted_so_far_size += to_evict_size; | 343 evicted_so_far_size += to_evict_size; |
| 335 ++it; | 344 ++it; |
| 336 } | 345 } |
| 337 | 346 |
| 338 // Take out the rest of hashes from the eviction list. | 347 // Take out the rest of hashes from the eviction list. |
| 339 entry_hashes.erase(it, entry_hashes.end()); | 348 entry_hashes.erase(it, entry_hashes.end()); |
| 340 SIMPLE_CACHE_UMA(COUNTS, | 349 SIMPLE_CACHE_UMA( |
| 341 "Eviction.EntryCount", cache_type_, entry_hashes.size()); | 350 COUNTS, "Eviction.EntryCount", cache_type_, entry_hashes.size()); |
| 342 SIMPLE_CACHE_UMA(TIMES, | 351 SIMPLE_CACHE_UMA(TIMES, |
| 343 "Eviction.TimeToSelectEntries", cache_type_, | 352 "Eviction.TimeToSelectEntries", |
| 353 cache_type_, |
| 344 base::TimeTicks::Now() - eviction_start_time_); | 354 base::TimeTicks::Now() - eviction_start_time_); |
| 345 SIMPLE_CACHE_UMA(MEMORY_KB, | 355 SIMPLE_CACHE_UMA(MEMORY_KB, |
| 346 "Eviction.SizeOfEvicted2", cache_type_, | 356 "Eviction.SizeOfEvicted2", |
| 357 cache_type_, |
| 347 evicted_so_far_size / kBytesInKb); | 358 evicted_so_far_size / kBytesInKb); |
| 348 | 359 |
| 349 delegate_->DoomEntries(&entry_hashes, base::Bind(&SimpleIndex::EvictionDone, | 360 delegate_->DoomEntries(&entry_hashes, |
| 350 AsWeakPtr())); | 361 base::Bind(&SimpleIndex::EvictionDone, AsWeakPtr())); |
| 351 } | 362 } |
| 352 | 363 |
| 353 bool SimpleIndex::UpdateEntrySize(uint64 entry_hash, int entry_size) { | 364 bool SimpleIndex::UpdateEntrySize(uint64 entry_hash, int entry_size) { |
| 354 DCHECK(io_thread_checker_.CalledOnValidThread()); | 365 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 355 EntrySet::iterator it = entries_set_.find(entry_hash); | 366 EntrySet::iterator it = entries_set_.find(entry_hash); |
| 356 if (it == entries_set_.end()) | 367 if (it == entries_set_.end()) |
| 357 return false; | 368 return false; |
| 358 | 369 |
| 359 UpdateEntryIteratorSize(&it, entry_size); | 370 UpdateEntryIteratorSize(&it, entry_size); |
| 360 PostponeWritingToDisk(); | 371 PostponeWritingToDisk(); |
| 361 StartEvictionIfNeeded(); | 372 StartEvictionIfNeeded(); |
| 362 return true; | 373 return true; |
| 363 } | 374 } |
| 364 | 375 |
| 365 void SimpleIndex::EvictionDone(int result) { | 376 void SimpleIndex::EvictionDone(int result) { |
| 366 DCHECK(io_thread_checker_.CalledOnValidThread()); | 377 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 367 | 378 |
| 368 // Ignore the result of eviction. We did our best. | 379 // Ignore the result of eviction. We did our best. |
| 369 eviction_in_progress_ = false; | 380 eviction_in_progress_ = false; |
| 370 SIMPLE_CACHE_UMA(BOOLEAN, "Eviction.Result", cache_type_, result == net::OK); | 381 SIMPLE_CACHE_UMA(BOOLEAN, "Eviction.Result", cache_type_, result == net::OK); |
| 371 SIMPLE_CACHE_UMA(TIMES, | 382 SIMPLE_CACHE_UMA(TIMES, |
| 372 "Eviction.TimeToDone", cache_type_, | 383 "Eviction.TimeToDone", |
| 384 cache_type_, |
| 373 base::TimeTicks::Now() - eviction_start_time_); | 385 base::TimeTicks::Now() - eviction_start_time_); |
| 374 SIMPLE_CACHE_UMA(MEMORY_KB, | 386 SIMPLE_CACHE_UMA(MEMORY_KB, |
| 375 "Eviction.SizeWhenDone2", cache_type_, | 387 "Eviction.SizeWhenDone2", |
| 388 cache_type_, |
| 376 cache_size_ / kBytesInKb); | 389 cache_size_ / kBytesInKb); |
| 377 } | 390 } |
| 378 | 391 |
| 379 // static | 392 // static |
| 380 void SimpleIndex::InsertInEntrySet( | 393 void SimpleIndex::InsertInEntrySet( |
| 381 uint64 entry_hash, | 394 uint64 entry_hash, |
| 382 const disk_cache::EntryMetadata& entry_metadata, | 395 const disk_cache::EntryMetadata& entry_metadata, |
| 383 EntrySet* entry_set) { | 396 EntrySet* entry_set) { |
| 384 DCHECK(entry_set); | 397 DCHECK(entry_set); |
| 385 entry_set->insert(std::make_pair(entry_hash, entry_metadata)); | 398 entry_set->insert(std::make_pair(entry_hash, entry_metadata)); |
| 386 } | 399 } |
| 387 | 400 |
| 388 void SimpleIndex::PostponeWritingToDisk() { | 401 void SimpleIndex::PostponeWritingToDisk() { |
| 389 if (!initialized_) | 402 if (!initialized_) |
| 390 return; | 403 return; |
| 391 const int delay = app_on_background_ ? background_flush_delay_ | 404 const int delay = |
| 392 : foreground_flush_delay_; | 405 app_on_background_ ? background_flush_delay_ : foreground_flush_delay_; |
| 393 // If the timer is already active, Start() will just Reset it, postponing it. | 406 // If the timer is already active, Start() will just Reset it, postponing it. |
| 394 write_to_disk_timer_.Start( | 407 write_to_disk_timer_.Start( |
| 395 FROM_HERE, base::TimeDelta::FromMilliseconds(delay), write_to_disk_cb_); | 408 FROM_HERE, base::TimeDelta::FromMilliseconds(delay), write_to_disk_cb_); |
| 396 } | 409 } |
| 397 | 410 |
| 398 void SimpleIndex::UpdateEntryIteratorSize(EntrySet::iterator* it, | 411 void SimpleIndex::UpdateEntryIteratorSize(EntrySet::iterator* it, |
| 399 int entry_size) { | 412 int entry_size) { |
| 400 // Update the total cache size with the new entry size. | 413 // Update the total cache size with the new entry size. |
| 401 DCHECK(io_thread_checker_.CalledOnValidThread()); | 414 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 402 DCHECK_GE(cache_size_, implicit_cast<uint64>((*it)->second.GetEntrySize())); | 415 DCHECK_GE(cache_size_, implicit_cast<uint64>((*it)->second.GetEntrySize())); |
| 403 cache_size_ -= (*it)->second.GetEntrySize(); | 416 cache_size_ -= (*it)->second.GetEntrySize(); |
| 404 cache_size_ += entry_size; | 417 cache_size_ += entry_size; |
| 405 (*it)->second.SetEntrySize(entry_size); | 418 (*it)->second.SetEntrySize(entry_size); |
| 406 } | 419 } |
| 407 | 420 |
| 408 void SimpleIndex::MergeInitializingSet( | 421 void SimpleIndex::MergeInitializingSet( |
| 409 scoped_ptr<SimpleIndexLoadResult> load_result) { | 422 scoped_ptr<SimpleIndexLoadResult> load_result) { |
| 410 DCHECK(io_thread_checker_.CalledOnValidThread()); | 423 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 411 DCHECK(load_result->did_load); | 424 DCHECK(load_result->did_load); |
| 412 | 425 |
| 413 EntrySet* index_file_entries = &load_result->entries; | 426 EntrySet* index_file_entries = &load_result->entries; |
| 414 | 427 |
| 415 for (base::hash_set<uint64>::const_iterator it = removed_entries_.begin(); | 428 for (base::hash_set<uint64>::const_iterator it = removed_entries_.begin(); |
| 416 it != removed_entries_.end(); ++it) { | 429 it != removed_entries_.end(); |
| 430 ++it) { |
| 417 index_file_entries->erase(*it); | 431 index_file_entries->erase(*it); |
| 418 } | 432 } |
| 419 removed_entries_.clear(); | 433 removed_entries_.clear(); |
| 420 | 434 |
| 421 for (EntrySet::const_iterator it = entries_set_.begin(); | 435 for (EntrySet::const_iterator it = entries_set_.begin(); |
| 422 it != entries_set_.end(); ++it) { | 436 it != entries_set_.end(); |
| 437 ++it) { |
| 423 const uint64 entry_hash = it->first; | 438 const uint64 entry_hash = it->first; |
| 424 std::pair<EntrySet::iterator, bool> insert_result = | 439 std::pair<EntrySet::iterator, bool> insert_result = |
| 425 index_file_entries->insert(EntrySet::value_type(entry_hash, | 440 index_file_entries->insert( |
| 426 EntryMetadata())); | 441 EntrySet::value_type(entry_hash, EntryMetadata())); |
| 427 EntrySet::iterator& possibly_inserted_entry = insert_result.first; | 442 EntrySet::iterator& possibly_inserted_entry = insert_result.first; |
| 428 possibly_inserted_entry->second = it->second; | 443 possibly_inserted_entry->second = it->second; |
| 429 } | 444 } |
| 430 | 445 |
| 431 uint64 merged_cache_size = 0; | 446 uint64 merged_cache_size = 0; |
| 432 for (EntrySet::iterator it = index_file_entries->begin(); | 447 for (EntrySet::iterator it = index_file_entries->begin(); |
| 433 it != index_file_entries->end(); ++it) { | 448 it != index_file_entries->end(); |
| 449 ++it) { |
| 434 merged_cache_size += it->second.GetEntrySize(); | 450 merged_cache_size += it->second.GetEntrySize(); |
| 435 } | 451 } |
| 436 | 452 |
| 437 entries_set_.swap(*index_file_entries); | 453 entries_set_.swap(*index_file_entries); |
| 438 cache_size_ = merged_cache_size; | 454 cache_size_ = merged_cache_size; |
| 439 initialized_ = true; | 455 initialized_ = true; |
| 440 | 456 |
| 441 // The actual IO is asynchronous, so calling WriteToDisk() shouldn't slow the | 457 // The actual IO is asynchronous, so calling WriteToDisk() shouldn't slow the |
| 442 // merge down much. | 458 // merge down much. |
| 443 if (load_result->flush_required) | 459 if (load_result->flush_required) |
| 444 WriteToDisk(); | 460 WriteToDisk(); |
| 445 | 461 |
| 446 SIMPLE_CACHE_UMA(CUSTOM_COUNTS, | 462 SIMPLE_CACHE_UMA(CUSTOM_COUNTS, |
| 447 "IndexInitializationWaiters", cache_type_, | 463 "IndexInitializationWaiters", |
| 448 to_run_when_initialized_.size(), 0, 100, 20); | 464 cache_type_, |
| 465 to_run_when_initialized_.size(), |
| 466 0, |
| 467 100, |
| 468 20); |
| 449 // Run all callbacks waiting for the index to come up. | 469 // Run all callbacks waiting for the index to come up. |
| 450 for (CallbackList::iterator it = to_run_when_initialized_.begin(), | 470 for (CallbackList::iterator it = to_run_when_initialized_.begin(), |
| 451 end = to_run_when_initialized_.end(); it != end; ++it) { | 471 end = to_run_when_initialized_.end(); |
| 472 it != end; |
| 473 ++it) { |
| 452 io_thread_->PostTask(FROM_HERE, base::Bind((*it), net::OK)); | 474 io_thread_->PostTask(FROM_HERE, base::Bind((*it), net::OK)); |
| 453 } | 475 } |
| 454 to_run_when_initialized_.clear(); | 476 to_run_when_initialized_.clear(); |
| 455 } | 477 } |
| 456 | 478 |
| 457 #if defined(OS_ANDROID) | 479 #if defined(OS_ANDROID) |
| 458 void SimpleIndex::OnApplicationStateChange( | 480 void SimpleIndex::OnApplicationStateChange( |
| 459 base::android::ApplicationState state) { | 481 base::android::ApplicationState state) { |
| 460 DCHECK(io_thread_checker_.CalledOnValidThread()); | 482 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 461 // For more info about android activities, see: | 483 // For more info about android activities, see: |
| 462 // developer.android.com/training/basics/activity-lifecycle/pausing.html | 484 // developer.android.com/training/basics/activity-lifecycle/pausing.html |
| 463 if (state == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES) { | 485 if (state == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES) { |
| 464 app_on_background_ = false; | 486 app_on_background_ = false; |
| 465 } else if (state == | 487 } else if (state == base::android::APPLICATION_STATE_HAS_STOPPED_ACTIVITIES) { |
| 466 base::android::APPLICATION_STATE_HAS_STOPPED_ACTIVITIES) { | |
| 467 app_on_background_ = true; | 488 app_on_background_ = true; |
| 468 WriteToDisk(); | 489 WriteToDisk(); |
| 469 } | 490 } |
| 470 } | 491 } |
| 471 #endif | 492 #endif |
| 472 | 493 |
| 473 void SimpleIndex::WriteToDisk() { | 494 void SimpleIndex::WriteToDisk() { |
| 474 DCHECK(io_thread_checker_.CalledOnValidThread()); | 495 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 475 if (!initialized_) | 496 if (!initialized_) |
| 476 return; | 497 return; |
| 477 SIMPLE_CACHE_UMA(CUSTOM_COUNTS, | 498 SIMPLE_CACHE_UMA(CUSTOM_COUNTS, |
| 478 "IndexNumEntriesOnWrite", cache_type_, | 499 "IndexNumEntriesOnWrite", |
| 479 entries_set_.size(), 0, 100000, 50); | 500 cache_type_, |
| 501 entries_set_.size(), |
| 502 0, |
| 503 100000, |
| 504 50); |
| 480 const base::TimeTicks start = base::TimeTicks::Now(); | 505 const base::TimeTicks start = base::TimeTicks::Now(); |
| 481 if (!last_write_to_disk_.is_null()) { | 506 if (!last_write_to_disk_.is_null()) { |
| 482 if (app_on_background_) { | 507 if (app_on_background_) { |
| 483 SIMPLE_CACHE_UMA(MEDIUM_TIMES, | 508 SIMPLE_CACHE_UMA(MEDIUM_TIMES, |
| 484 "IndexWriteInterval.Background", cache_type_, | 509 "IndexWriteInterval.Background", |
| 510 cache_type_, |
| 485 start - last_write_to_disk_); | 511 start - last_write_to_disk_); |
| 486 } else { | 512 } else { |
| 487 SIMPLE_CACHE_UMA(MEDIUM_TIMES, | 513 SIMPLE_CACHE_UMA(MEDIUM_TIMES, |
| 488 "IndexWriteInterval.Foreground", cache_type_, | 514 "IndexWriteInterval.Foreground", |
| 515 cache_type_, |
| 489 start - last_write_to_disk_); | 516 start - last_write_to_disk_); |
| 490 } | 517 } |
| 491 } | 518 } |
| 492 last_write_to_disk_ = start; | 519 last_write_to_disk_ = start; |
| 493 | 520 |
| 494 index_file_->WriteToDisk(entries_set_, cache_size_, | 521 index_file_->WriteToDisk( |
| 495 start, app_on_background_); | 522 entries_set_, cache_size_, start, app_on_background_); |
| 496 } | 523 } |
| 497 | 524 |
| 498 } // namespace disk_cache | 525 } // namespace disk_cache |
| OLD | NEW |