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 EntryMetadata& metadata = it->second; |
| 231 base::Time entry_time = metadata.GetLastUsedTime(); | 219 base::Time entry_time = metadata.GetLastUsedTime(); |
| 232 if (initial_time <= entry_time && entry_time < extended_end_time) { | 220 if (initial_time <= entry_time && entry_time < extended_end_time) { |
| 233 ret_hashes->push_back(metadata.GetHashKey()); | 221 ret_hashes->push_back(it->first); |
| 222 cache_size_ -= metadata.GetEntrySize(); | |
| 234 entries_set_.erase(it++); | 223 entries_set_.erase(it++); |
| 235 cache_size_ -= metadata.GetEntrySize(); | |
| 236 } else { | 224 } else { |
| 237 it++; | 225 it++; |
| 238 } | 226 } |
| 239 } | 227 } |
| 240 return ret_hashes.Pass(); | 228 return ret_hashes.Pass(); |
| 241 } | 229 } |
| 242 | 230 |
| 243 int32 SimpleIndex::GetEntryCount() const { | 231 int32 SimpleIndex::GetEntryCount() const { |
| 244 // TODO(pasko): return a meaningful initial estimate before initialized. | 232 // TODO(pasko): return a meaningful initial estimate before initialized. |
| 245 return entries_set_.size(); | 233 return entries_set_.size(); |
| 246 } | 234 } |
| 247 | 235 |
| 248 void SimpleIndex::Insert(const std::string& key) { | 236 void SimpleIndex::Insert(const std::string& key) { |
| 249 DCHECK(io_thread_checker_.CalledOnValidThread()); | 237 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 250 // Upon insert we don't know yet the size of the entry. | 238 // Upon insert we don't know yet the size of the entry. |
| 251 // It will be updated later when the SimpleEntryImpl finishes opening or | 239 // It will be updated later when the SimpleEntryImpl finishes opening or |
| 252 // creating the new entry, and then UpdateEntrySize will be called. | 240 // creating the new entry, and then UpdateEntrySize will be called. |
| 253 const uint64 hash_key = simple_util::GetEntryHashKey(key); | 241 const uint64 hash_key = simple_util::GetEntryHashKey(key); |
| 254 InsertInEntrySet(EntryMetadata(hash_key, base::Time::Now(), 0), | 242 InsertInEntrySet( |
| 255 &entries_set_); | 243 hash_key, EntryMetadata(base::Time::Now(), 0), &entries_set_); |
| 256 if (!initialized_) | 244 if (!initialized_) |
| 257 removed_entries_.erase(hash_key); | 245 removed_entries_.erase(hash_key); |
| 258 PostponeWritingToDisk(); | 246 PostponeWritingToDisk(); |
| 259 } | 247 } |
| 260 | 248 |
| 261 void SimpleIndex::Remove(const std::string& key) { | 249 void SimpleIndex::Remove(const std::string& key) { |
| 262 DCHECK(io_thread_checker_.CalledOnValidThread()); | 250 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 263 UpdateEntrySize(key, 0); | 251 UpdateEntrySize(key, 0); |
| 264 const uint64 hash_key = simple_util::GetEntryHashKey(key); | 252 const uint64 hash_key = simple_util::GetEntryHashKey(key); |
| 265 entries_set_.erase(hash_key); | 253 entries_set_.erase(hash_key); |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 295 return; | 283 return; |
| 296 | 284 |
| 297 // Take all live key hashes from the index and sort them by time. | 285 // Take all live key hashes from the index and sort them by time. |
| 298 eviction_in_progress_ = true; | 286 eviction_in_progress_ = true; |
| 299 eviction_start_time_ = base::TimeTicks::Now(); | 287 eviction_start_time_ = base::TimeTicks::Now(); |
| 300 UMA_HISTOGRAM_COUNTS("SimpleCache.Eviction.CacheSizeOnStart", cache_size_); | 288 UMA_HISTOGRAM_COUNTS("SimpleCache.Eviction.CacheSizeOnStart", cache_size_); |
| 301 UMA_HISTOGRAM_COUNTS("SimpleCache.Eviction.MaxCacheSizeOnStart", max_size_); | 289 UMA_HISTOGRAM_COUNTS("SimpleCache.Eviction.MaxCacheSizeOnStart", max_size_); |
| 302 scoped_ptr<std::vector<uint64> > entry_hashes(new std::vector<uint64>()); | 290 scoped_ptr<std::vector<uint64> > entry_hashes(new std::vector<uint64>()); |
| 303 for (EntrySet::const_iterator it = entries_set_.begin(), | 291 for (EntrySet::const_iterator it = entries_set_.begin(), |
| 304 end = entries_set_.end(); it != end; ++it) { | 292 end = entries_set_.end(); it != end; ++it) { |
| 305 entry_hashes->push_back(it->second.GetHashKey()); | 293 entry_hashes->push_back(it->first); |
| 306 } | 294 } |
| 307 std::sort(entry_hashes->begin(), entry_hashes->end(), | 295 std::sort(entry_hashes->begin(), entry_hashes->end(), |
| 308 CompareHashesForTimestamp(entries_set_)); | 296 CompareHashesForTimestamp(entries_set_)); |
| 309 | 297 |
| 310 // Remove as many entries from the index to get below |low_watermark_|. | 298 // Remove as many entries from the index to get below |low_watermark_|. |
| 311 std::vector<uint64>::iterator it = entry_hashes->begin(); | 299 std::vector<uint64>::iterator it = entry_hashes->begin(); |
| 312 uint64 evicted_so_far_size = 0; | 300 uint64 evicted_so_far_size = 0; |
| 313 while (evicted_so_far_size < cache_size_ - low_watermark_) { | 301 while (evicted_so_far_size < cache_size_ - low_watermark_) { |
| 314 DCHECK(it != entry_hashes->end()); | 302 DCHECK(it != entry_hashes->end()); |
| 315 EntrySet::iterator found_meta = entries_set_.find(*it); | 303 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. | 349 // Ignore the result of eviction. We did our best. |
| 362 eviction_in_progress_ = false; | 350 eviction_in_progress_ = false; |
| 363 UMA_HISTOGRAM_BOOLEAN("SimpleCache.Eviction.Result", *result == net::OK); | 351 UMA_HISTOGRAM_BOOLEAN("SimpleCache.Eviction.Result", *result == net::OK); |
| 364 UMA_HISTOGRAM_TIMES("SimpleCache.Eviction.TimeToDone", | 352 UMA_HISTOGRAM_TIMES("SimpleCache.Eviction.TimeToDone", |
| 365 base::TimeTicks::Now() - eviction_start_time_); | 353 base::TimeTicks::Now() - eviction_start_time_); |
| 366 UMA_HISTOGRAM_COUNTS("SimpleCache.Eviction.SizeWhenDone", cache_size_); | 354 UMA_HISTOGRAM_COUNTS("SimpleCache.Eviction.SizeWhenDone", cache_size_); |
| 367 } | 355 } |
| 368 | 356 |
| 369 // static | 357 // static |
| 370 void SimpleIndex::InsertInEntrySet( | 358 void SimpleIndex::InsertInEntrySet( |
| 359 uint64 hash_key, | |
| 371 const disk_cache::EntryMetadata& entry_metadata, | 360 const disk_cache::EntryMetadata& entry_metadata, |
| 372 EntrySet* entry_set) { | 361 EntrySet* entry_set) { |
| 373 DCHECK(entry_set); | 362 DCHECK(entry_set); |
| 374 entry_set->insert( | 363 entry_set->insert(std::make_pair(hash_key, entry_metadata)); |
| 375 std::make_pair(entry_metadata.GetHashKey(), entry_metadata)); | |
| 376 } | 364 } |
| 377 | 365 |
| 378 void SimpleIndex::PostponeWritingToDisk() { | 366 void SimpleIndex::PostponeWritingToDisk() { |
| 379 if (!initialized_) | 367 if (!initialized_) |
| 380 return; | 368 return; |
| 381 const int delay = app_on_background_ ? kWriteToDiskOnBackgroundDelayMSecs | 369 const int delay = app_on_background_ ? kWriteToDiskOnBackgroundDelayMSecs |
| 382 : kWriteToDiskDelayMSecs; | 370 : kWriteToDiskDelayMSecs; |
| 383 // If the timer is already active, Start() will just Reset it, postponing it. | 371 // If the timer is already active, Start() will just Reset it, postponing it. |
| 384 write_to_disk_timer_.Start( | 372 write_to_disk_timer_.Start( |
| 385 FROM_HERE, | 373 FROM_HERE, |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 505 base::Time last_used_time; | 493 base::Time last_used_time; |
| 506 #if defined(OS_POSIX) | 494 #if defined(OS_POSIX) |
| 507 // For POSIX systems, a last access time is available. However, it's not | 495 // 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. | 496 // guaranteed to be more accurate than mtime. It is no worse though. |
| 509 last_used_time = base::Time::FromTimeT(find_info.stat.st_atime); | 497 last_used_time = base::Time::FromTimeT(find_info.stat.st_atime); |
| 510 #endif | 498 #endif |
| 511 if (last_used_time.is_null()) | 499 if (last_used_time.is_null()) |
| 512 last_used_time = FileEnumerator::GetLastModifiedTime(find_info); | 500 last_used_time = FileEnumerator::GetLastModifiedTime(find_info); |
| 513 | 501 |
| 514 int64 file_size = FileEnumerator::GetFilesize(find_info); | 502 int64 file_size = FileEnumerator::GetFilesize(find_info); |
| 515 EntrySet::iterator it = index_file_entries->find(hash_key); | 503 std::pair<EntrySet::iterator, bool> ret = index_file_entries->insert( |
| 516 if (it == index_file_entries->end()) { | 504 std::make_pair(hash_key, EntryMetadata(last_used_time, file_size))); |
| 517 InsertInEntrySet(EntryMetadata(hash_key, last_used_time, file_size), | 505 if (ret.second == false) { |
| 518 index_file_entries.get()); | 506 EntryMetadata* current_entry = &ret.first->second; |
| 519 } else { | 507 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 } | 508 } |
| 523 } | 509 } |
| 524 return index_file_entries.Pass(); | 510 return index_file_entries.Pass(); |
| 525 } | 511 } |
| 526 | 512 |
| 527 | 513 |
| 528 // static | 514 // static |
| 529 void SimpleIndex::WriteToDiskInternal(const base::FilePath& index_filename, | 515 void SimpleIndex::WriteToDiskInternal(const base::FilePath& index_filename, |
| 530 scoped_ptr<Pickle> pickle, | 516 scoped_ptr<Pickle> pickle, |
| 531 const base::TimeTicks& start_time, | 517 const base::TimeTicks& start_time, |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 548 // sets. | 534 // sets. |
| 549 for (base::hash_set<uint64>::const_iterator it = | 535 for (base::hash_set<uint64>::const_iterator it = |
| 550 removed_entries_.begin(); it != removed_entries_.end(); ++it) { | 536 removed_entries_.begin(); it != removed_entries_.end(); ++it) { |
| 551 entries_set_.erase(*it); | 537 entries_set_.erase(*it); |
| 552 index_file_entries->erase(*it); | 538 index_file_entries->erase(*it); |
| 553 } | 539 } |
| 554 | 540 |
| 555 // Recalculate the cache size while merging the two sets. | 541 // Recalculate the cache size while merging the two sets. |
| 556 for (EntrySet::const_iterator it = index_file_entries->begin(); | 542 for (EntrySet::const_iterator it = index_file_entries->begin(); |
| 557 it != index_file_entries->end(); ++it) { | 543 it != index_file_entries->end(); ++it) { |
| 558 // If there is already an entry in the current entries_set_, we need to | 544 std::pair<EntrySet::iterator, bool> ret = entries_set_.insert(*it); |
| 559 // merge the new data there with the data loaded in the initialization. | 545 EntryMetadata& current_entry = ret.first->second; |
|
gavinp
2013/05/17 14:54:17
This is more a comment, and less a request. I woul
| |
| 560 EntrySet::iterator current_entry = entries_set_.find(it->first); | 546 if (ret.second == false) { |
| 561 if (current_entry != entries_set_.end()) { | |
| 562 // When Merging, existing valid data in the |current_entry| will prevail. | 547 // When Merging, existing valid data in the |current_entry| will prevail. |
| 563 cache_size_ -= current_entry->second.GetEntrySize(); | 548 cache_size_ -= current_entry.GetEntrySize(); |
| 564 current_entry->second.MergeWith(it->second); | 549 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 } | 550 } |
| 551 cache_size_ += current_entry.GetEntrySize(); | |
| 570 } | 552 } |
| 571 initialized_ = true; | 553 initialized_ = true; |
| 572 removed_entries_.clear(); | 554 removed_entries_.clear(); |
| 573 | 555 |
| 574 // The actual IO is asynchronous, so calling WriteToDisk() shouldn't slow down | 556 // The actual IO is asynchronous, so calling WriteToDisk() shouldn't slow down |
| 575 // much the merge. | 557 // much the merge. |
| 576 if (force_index_flush) | 558 if (force_index_flush) |
| 577 WriteToDisk(); | 559 WriteToDisk(); |
| 578 | 560 |
| 579 UMA_HISTOGRAM_CUSTOM_COUNTS("SimpleCache.IndexInitializationWaiters", | 561 UMA_HISTOGRAM_CUSTOM_COUNTS("SimpleCache.IndexInitializationWaiters", |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 626 entries_set_); | 608 entries_set_); |
| 627 cache_thread_->PostTask(FROM_HERE, base::Bind( | 609 cache_thread_->PostTask(FROM_HERE, base::Bind( |
| 628 &SimpleIndex::WriteToDiskInternal, | 610 &SimpleIndex::WriteToDiskInternal, |
| 629 index_filename_, | 611 index_filename_, |
| 630 base::Passed(&pickle), | 612 base::Passed(&pickle), |
| 631 start, | 613 start, |
| 632 app_on_background_)); | 614 app_on_background_)); |
| 633 } | 615 } |
| 634 | 616 |
| 635 } // namespace disk_cache | 617 } // namespace disk_cache |
| OLD | NEW |