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 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 99 if (!file_util::GetFileInfo(path, &file_info)) | 99 if (!file_util::GetFileInfo(path, &file_info)) |
| 100 return false; | 100 return false; |
| 101 *out_mtime = file_info.last_modified; | 101 *out_mtime = file_info.last_modified; |
| 102 return true; | 102 return true; |
| 103 } | 103 } |
| 104 | 104 |
| 105 } // namespace | 105 } // namespace |
| 106 | 106 |
| 107 namespace disk_cache { | 107 namespace disk_cache { |
| 108 | 108 |
| 109 EntryMetadata::EntryMetadata() : hash_key_(0), | 109 EntryMetadata::EntryMetadata() : last_used_time_(0), entry_size_(0) {} |
| 110 last_used_time_(0), | |
| 111 entry_size_(0) { | |
| 112 } | |
| 113 | 110 |
| 114 EntryMetadata::EntryMetadata(uint64 hash_key, | 111 EntryMetadata::EntryMetadata(base::Time last_used_time, uint64 entry_size) |
| 115 base::Time last_used_time, | 112 : last_used_time_(last_used_time.ToInternalValue()), |
| 116 uint64 entry_size) : | 113 entry_size_(entry_size) {} |
| 117 hash_key_(hash_key), | |
| 118 last_used_time_(last_used_time.ToInternalValue()), | |
| 119 entry_size_(entry_size) { | |
| 120 } | |
| 121 | 114 |
| 122 base::Time EntryMetadata::GetLastUsedTime() const { | 115 base::Time EntryMetadata::GetLastUsedTime() const { |
| 123 return base::Time::FromInternalValue(last_used_time_); | 116 return base::Time::FromInternalValue(last_used_time_); |
| 124 } | 117 } |
| 125 | 118 |
| 126 void EntryMetadata::SetLastUsedTime(const base::Time& last_used_time) { | 119 void EntryMetadata::SetLastUsedTime(const base::Time& last_used_time) { |
| 127 last_used_time_ = last_used_time.ToInternalValue(); | 120 last_used_time_ = last_used_time.ToInternalValue(); |
| 128 } | 121 } |
| 129 | 122 |
| 130 void EntryMetadata::Serialize(Pickle* pickle) const { | 123 void EntryMetadata::Serialize(Pickle* pickle) const { |
| 131 DCHECK(pickle); | 124 DCHECK(pickle); |
| 132 COMPILE_ASSERT(sizeof(EntryMetadata) == | 125 COMPILE_ASSERT(sizeof(EntryMetadata) == (sizeof(int64) + sizeof(uint64)), |
| 133 (sizeof(uint64) + sizeof(int64) + sizeof(uint64)), | 126 EntryMetadata_has_two_member_variables); |
| 134 EntryMetadata_has_three_member_variables); | |
| 135 pickle->WriteUInt64(hash_key_); | |
| 136 pickle->WriteInt64(last_used_time_); | 127 pickle->WriteInt64(last_used_time_); |
| 137 pickle->WriteUInt64(entry_size_); | 128 pickle->WriteUInt64(entry_size_); |
| 138 } | 129 } |
| 139 | 130 |
| 140 bool EntryMetadata::Deserialize(PickleIterator* it) { | 131 bool EntryMetadata::Deserialize(PickleIterator* it) { |
| 141 DCHECK(it); | 132 DCHECK(it); |
| 142 return it->ReadUInt64(&hash_key_) && | 133 return it->ReadInt64(&last_used_time_) && it->ReadUInt64(&entry_size_); |
| 143 it->ReadInt64(&last_used_time_) && | |
| 144 it->ReadUInt64(&entry_size_); | |
| 145 } | 134 } |
| 146 | 135 |
| 147 void EntryMetadata::MergeWith(const EntryMetadata& from) { | 136 void EntryMetadata::MergeWith(const EntryMetadata& from) { |
| 148 DCHECK_EQ(hash_key_, from.hash_key_); | |
| 149 if (last_used_time_ == 0) | 137 if (last_used_time_ == 0) |
| 150 last_used_time_ = from.last_used_time_; | 138 last_used_time_ = from.last_used_time_; |
| 151 if (entry_size_ == 0) | 139 if (entry_size_ == 0) |
| 152 entry_size_ = from.entry_size_; | 140 entry_size_ = from.entry_size_; |
| 153 } | 141 } |
| 154 | 142 |
| 155 SimpleIndex::SimpleIndex(base::SingleThreadTaskRunner* cache_thread, | 143 SimpleIndex::SimpleIndex(base::SingleThreadTaskRunner* cache_thread, |
| 156 base::SingleThreadTaskRunner* io_thread, | 144 base::SingleThreadTaskRunner* io_thread, |
| 157 const base::FilePath& path) | 145 const base::FilePath& path) |
| 158 : cache_size_(0), | 146 : cache_size_(0), |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 220 | 208 |
| 221 scoped_ptr<std::vector<uint64> > SimpleIndex::RemoveEntriesBetween( | 209 scoped_ptr<std::vector<uint64> > SimpleIndex::RemoveEntriesBetween( |
| 222 const base::Time initial_time, const base::Time end_time) { | 210 const base::Time initial_time, const base::Time end_time) { |
| 223 DCHECK_EQ(true, initialized_); | 211 DCHECK_EQ(true, initialized_); |
| 224 const base::Time extended_end_time = | 212 const base::Time extended_end_time = |
| 225 end_time.is_null() ? base::Time::Max() : end_time; | 213 end_time.is_null() ? base::Time::Max() : end_time; |
| 226 DCHECK(extended_end_time >= initial_time); | 214 DCHECK(extended_end_time >= initial_time); |
| 227 scoped_ptr<std::vector<uint64> > ret_hashes(new std::vector<uint64>()); | 215 scoped_ptr<std::vector<uint64> > ret_hashes(new std::vector<uint64>()); |
| 228 for (EntrySet::iterator it = entries_set_.begin(), end = entries_set_.end(); | 216 for (EntrySet::iterator it = entries_set_.begin(), end = entries_set_.end(); |
| 229 it != end;) { | 217 it != end;) { |
| 230 EntryMetadata metadata = it->second; | 218 base::Time entry_time = it->second.GetLastUsedTime(); |
|
pasko
2013/05/16 18:13:21
I would prefer to leave it with a named variable f
digit1
2013/05/17 08:45:38
Sure, no problem. Done.
| |
| 231 base::Time entry_time = metadata.GetLastUsedTime(); | |
| 232 if (initial_time <= entry_time && entry_time < extended_end_time) { | 219 if (initial_time <= entry_time && entry_time < extended_end_time) { |
| 233 ret_hashes->push_back(metadata.GetHashKey()); | 220 ret_hashes->push_back(it->first); |
| 221 cache_size_ -= it->second.GetEntrySize(); | |
| 234 entries_set_.erase(it++); | 222 entries_set_.erase(it++); |
| 235 cache_size_ -= metadata.GetEntrySize(); | |
| 236 } else { | 223 } else { |
| 237 it++; | 224 it++; |
| 238 } | 225 } |
| 239 } | 226 } |
| 240 return ret_hashes.Pass(); | 227 return ret_hashes.Pass(); |
| 241 } | 228 } |
| 242 | 229 |
| 243 int32 SimpleIndex::GetEntryCount() const { | 230 int32 SimpleIndex::GetEntryCount() const { |
| 244 // TODO(pasko): return a meaningful initial estimate before initialized. | 231 // TODO(pasko): return a meaningful initial estimate before initialized. |
| 245 return entries_set_.size(); | 232 return entries_set_.size(); |
| 246 } | 233 } |
| 247 | 234 |
| 248 void SimpleIndex::Insert(const std::string& key) { | 235 void SimpleIndex::Insert(const std::string& key) { |
| 249 DCHECK(io_thread_checker_.CalledOnValidThread()); | 236 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 250 // Upon insert we don't know yet the size of the entry. | 237 // Upon insert we don't know yet the size of the entry. |
| 251 // It will be updated later when the SimpleEntryImpl finishes opening or | 238 // It will be updated later when the SimpleEntryImpl finishes opening or |
| 252 // creating the new entry, and then UpdateEntrySize will be called. | 239 // creating the new entry, and then UpdateEntrySize will be called. |
| 253 const uint64 hash_key = simple_util::GetEntryHashKey(key); | 240 const uint64 hash_key = simple_util::GetEntryHashKey(key); |
| 254 InsertInEntrySet(EntryMetadata(hash_key, base::Time::Now(), 0), | 241 InsertInEntrySet( |
|
gavinp
2013/05/16 13:38:01
This is the only call site for this function now.
digit1
2013/05/16 15:31:02
It's a public function that is also called from si
| |
| 255 &entries_set_); | 242 hash_key, EntryMetadata(base::Time::Now(), 0), &entries_set_); |
| 256 if (!initialized_) | 243 if (!initialized_) |
| 257 removed_entries_.erase(hash_key); | 244 removed_entries_.erase(hash_key); |
| 258 PostponeWritingToDisk(); | 245 PostponeWritingToDisk(); |
| 259 } | 246 } |
| 260 | 247 |
| 261 void SimpleIndex::Remove(const std::string& key) { | 248 void SimpleIndex::Remove(const std::string& key) { |
| 262 DCHECK(io_thread_checker_.CalledOnValidThread()); | 249 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 263 UpdateEntrySize(key, 0); | 250 UpdateEntrySize(key, 0); |
| 264 const uint64 hash_key = simple_util::GetEntryHashKey(key); | 251 const uint64 hash_key = simple_util::GetEntryHashKey(key); |
| 265 entries_set_.erase(hash_key); | 252 entries_set_.erase(hash_key); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 295 return; | 282 return; |
| 296 | 283 |
| 297 // Take all live key hashes from the index and sort them by time. | 284 // Take all live key hashes from the index and sort them by time. |
| 298 eviction_in_progress_ = true; | 285 eviction_in_progress_ = true; |
| 299 eviction_start_time_ = base::TimeTicks::Now(); | 286 eviction_start_time_ = base::TimeTicks::Now(); |
| 300 UMA_HISTOGRAM_COUNTS("SimpleCache.Eviction.CacheSizeOnStart", cache_size_); | 287 UMA_HISTOGRAM_COUNTS("SimpleCache.Eviction.CacheSizeOnStart", cache_size_); |
| 301 UMA_HISTOGRAM_COUNTS("SimpleCache.Eviction.MaxCacheSizeOnStart", max_size_); | 288 UMA_HISTOGRAM_COUNTS("SimpleCache.Eviction.MaxCacheSizeOnStart", max_size_); |
| 302 scoped_ptr<std::vector<uint64> > entry_hashes(new std::vector<uint64>()); | 289 scoped_ptr<std::vector<uint64> > entry_hashes(new std::vector<uint64>()); |
| 303 for (EntrySet::const_iterator it = entries_set_.begin(), | 290 for (EntrySet::const_iterator it = entries_set_.begin(), |
| 304 end = entries_set_.end(); it != end; ++it) { | 291 end = entries_set_.end(); it != end; ++it) { |
| 305 entry_hashes->push_back(it->second.GetHashKey()); | 292 entry_hashes->push_back(it->first); |
| 306 } | 293 } |
| 307 std::sort(entry_hashes->begin(), entry_hashes->end(), | 294 std::sort(entry_hashes->begin(), entry_hashes->end(), |
| 308 CompareHashesForTimestamp(entries_set_)); | 295 CompareHashesForTimestamp(entries_set_)); |
| 309 | 296 |
| 310 // Remove as many entries from the index to get below |low_watermark_|. | 297 // Remove as many entries from the index to get below |low_watermark_|. |
| 311 std::vector<uint64>::iterator it = entry_hashes->begin(); | 298 std::vector<uint64>::iterator it = entry_hashes->begin(); |
| 312 uint64 evicted_so_far_size = 0; | 299 uint64 evicted_so_far_size = 0; |
| 313 while (evicted_so_far_size < cache_size_ - low_watermark_) { | 300 while (evicted_so_far_size < cache_size_ - low_watermark_) { |
| 314 DCHECK(it != entry_hashes->end()); | 301 DCHECK(it != entry_hashes->end()); |
| 315 EntrySet::iterator found_meta = entries_set_.find(*it); | 302 EntrySet::iterator found_meta = entries_set_.find(*it); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 361 // Ignore the result of eviction. We did our best. | 348 // Ignore the result of eviction. We did our best. |
| 362 eviction_in_progress_ = false; | 349 eviction_in_progress_ = false; |
| 363 UMA_HISTOGRAM_BOOLEAN("SimpleCache.Eviction.Result", *result == net::OK); | 350 UMA_HISTOGRAM_BOOLEAN("SimpleCache.Eviction.Result", *result == net::OK); |
| 364 UMA_HISTOGRAM_TIMES("SimpleCache.Eviction.TimeToDone", | 351 UMA_HISTOGRAM_TIMES("SimpleCache.Eviction.TimeToDone", |
| 365 base::TimeTicks::Now() - eviction_start_time_); | 352 base::TimeTicks::Now() - eviction_start_time_); |
| 366 UMA_HISTOGRAM_COUNTS("SimpleCache.Eviction.SizeWhenDone", cache_size_); | 353 UMA_HISTOGRAM_COUNTS("SimpleCache.Eviction.SizeWhenDone", cache_size_); |
| 367 } | 354 } |
| 368 | 355 |
| 369 // static | 356 // static |
| 370 void SimpleIndex::InsertInEntrySet( | 357 void SimpleIndex::InsertInEntrySet( |
| 358 uint64 hash_key, | |
| 371 const disk_cache::EntryMetadata& entry_metadata, | 359 const disk_cache::EntryMetadata& entry_metadata, |
| 372 EntrySet* entry_set) { | 360 EntrySet* entry_set) { |
| 373 DCHECK(entry_set); | 361 DCHECK(entry_set); |
| 374 entry_set->insert( | 362 entry_set->insert(std::make_pair(hash_key, entry_metadata)); |
| 375 std::make_pair(entry_metadata.GetHashKey(), entry_metadata)); | |
| 376 } | 363 } |
| 377 | 364 |
| 378 void SimpleIndex::PostponeWritingToDisk() { | 365 void SimpleIndex::PostponeWritingToDisk() { |
| 379 if (!initialized_) | 366 if (!initialized_) |
| 380 return; | 367 return; |
| 381 const int delay = app_on_background_ ? kWriteToDiskOnBackgroundDelayMSecs | 368 const int delay = app_on_background_ ? kWriteToDiskOnBackgroundDelayMSecs |
| 382 : kWriteToDiskDelayMSecs; | 369 : kWriteToDiskDelayMSecs; |
| 383 // If the timer is already active, Start() will just Reset it, postponing it. | 370 // If the timer is already active, Start() will just Reset it, postponing it. |
| 384 write_to_disk_timer_.Start( | 371 write_to_disk_timer_.Start( |
| 385 FROM_HERE, | 372 FROM_HERE, |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 505 base::Time last_used_time; | 492 base::Time last_used_time; |
| 506 #if defined(OS_POSIX) | 493 #if defined(OS_POSIX) |
| 507 // For POSIX systems, a last access time is available. However, it's not | 494 // 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. | 495 // guaranteed to be more accurate than mtime. It is no worse though. |
| 509 last_used_time = base::Time::FromTimeT(find_info.stat.st_atime); | 496 last_used_time = base::Time::FromTimeT(find_info.stat.st_atime); |
| 510 #endif | 497 #endif |
| 511 if (last_used_time.is_null()) | 498 if (last_used_time.is_null()) |
| 512 last_used_time = FileEnumerator::GetLastModifiedTime(find_info); | 499 last_used_time = FileEnumerator::GetLastModifiedTime(find_info); |
| 513 | 500 |
| 514 int64 file_size = FileEnumerator::GetFilesize(find_info); | 501 int64 file_size = FileEnumerator::GetFilesize(find_info); |
| 515 EntrySet::iterator it = index_file_entries->find(hash_key); | 502 std::pair<EntrySet::iterator, bool> ret = index_file_entries->insert( |
| 516 if (it == index_file_entries->end()) { | 503 std::make_pair(hash_key, EntryMetadata(last_used_time, file_size))); |
| 517 InsertInEntrySet(EntryMetadata(hash_key, last_used_time, file_size), | 504 if (ret.second == false) { |
| 518 index_file_entries.get()); | 505 EntryMetadata* current_entry = &ret.first->second; |
| 519 } else { | 506 current_entry->SetEntrySize(current_entry->GetEntrySize() + file_size); |
| 520 // Summing up the total size of the entry through all the *_[0-2] files | |
| 521 it->second.SetEntrySize(it->second.GetEntrySize() + file_size); | |
| 522 } | 507 } |
| 523 } | 508 } |
| 524 return index_file_entries.Pass(); | 509 return index_file_entries.Pass(); |
| 525 } | 510 } |
| 526 | 511 |
| 527 | 512 |
| 528 // static | 513 // static |
| 529 void SimpleIndex::WriteToDiskInternal(const base::FilePath& index_filename, | 514 void SimpleIndex::WriteToDiskInternal(const base::FilePath& index_filename, |
| 530 scoped_ptr<Pickle> pickle, | 515 scoped_ptr<Pickle> pickle, |
| 531 const base::TimeTicks& start_time, | 516 const base::TimeTicks& start_time, |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 549 for (base::hash_set<uint64>::const_iterator it = | 534 for (base::hash_set<uint64>::const_iterator it = |
| 550 removed_entries_.begin(); it != removed_entries_.end(); ++it) { | 535 removed_entries_.begin(); it != removed_entries_.end(); ++it) { |
| 551 entries_set_.erase(*it); | 536 entries_set_.erase(*it); |
| 552 index_file_entries->erase(*it); | 537 index_file_entries->erase(*it); |
| 553 } | 538 } |
| 554 | 539 |
| 555 // Recalculate the cache size while merging the two sets. | 540 // Recalculate the cache size while merging the two sets. |
| 556 for (EntrySet::const_iterator it = index_file_entries->begin(); | 541 for (EntrySet::const_iterator it = index_file_entries->begin(); |
| 557 it != index_file_entries->end(); ++it) { | 542 it != index_file_entries->end(); ++it) { |
| 558 // If there is already an entry in the current entries_set_, we need to | 543 // If there is already an entry in the current entries_set_, we need to |
| 559 // merge the new data there with the data loaded in the initialization. | 544 // merge the new data there with the data loaded in the initialization. |
|
pasko
2013/05/16 18:13:21
while we are here, please delete this comment, it
digit1
2013/05/17 08:46:59
Done.
| |
| 560 EntrySet::iterator current_entry = entries_set_.find(it->first); | 545 std::pair<EntrySet::iterator, bool> ret = entries_set_.insert(*it); |
| 561 if (current_entry != entries_set_.end()) { | 546 EntryMetadata& current_entry = ret.first->second; |
| 547 if (ret.second == false) { | |
| 562 // When Merging, existing valid data in the |current_entry| will prevail. | 548 // When Merging, existing valid data in the |current_entry| will prevail. |
| 563 cache_size_ -= current_entry->second.GetEntrySize(); | 549 cache_size_ -= current_entry.GetEntrySize(); |
| 564 current_entry->second.MergeWith(it->second); | 550 current_entry.MergeWith(it->second); |
| 565 cache_size_ += current_entry->second.GetEntrySize(); | |
| 566 } else { | |
| 567 InsertInEntrySet(it->second, &entries_set_); | |
| 568 cache_size_ += it->second.GetEntrySize(); | |
| 569 } | 551 } |
| 552 cache_size_ += current_entry.GetEntrySize(); | |
| 570 } | 553 } |
| 571 initialized_ = true; | 554 initialized_ = true; |
| 572 removed_entries_.clear(); | 555 removed_entries_.clear(); |
| 573 | 556 |
| 574 // The actual IO is asynchronous, so calling WriteToDisk() shouldn't slow down | 557 // The actual IO is asynchronous, so calling WriteToDisk() shouldn't slow down |
| 575 // much the merge. | 558 // much the merge. |
| 576 if (force_index_flush) | 559 if (force_index_flush) |
| 577 WriteToDisk(); | 560 WriteToDisk(); |
| 578 | 561 |
| 579 UMA_HISTOGRAM_CUSTOM_COUNTS("SimpleCache.IndexInitializationWaiters", | 562 UMA_HISTOGRAM_CUSTOM_COUNTS("SimpleCache.IndexInitializationWaiters", |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 626 entries_set_); | 609 entries_set_); |
| 627 cache_thread_->PostTask(FROM_HERE, base::Bind( | 610 cache_thread_->PostTask(FROM_HERE, base::Bind( |
| 628 &SimpleIndex::WriteToDiskInternal, | 611 &SimpleIndex::WriteToDiskInternal, |
| 629 index_filename_, | 612 index_filename_, |
| 630 base::Passed(&pickle), | 613 base::Passed(&pickle), |
| 631 start, | 614 start, |
| 632 app_on_background_)); | 615 app_on_background_)); |
| 633 } | 616 } |
| 634 | 617 |
| 635 } // namespace disk_cache | 618 } // namespace disk_cache |
| OLD | NEW |