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 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 app_on_background_(false) { |
| 168 // Creating the callback once so it is reused every time | |
| 169 // write_to_disk_timer_.Start() is called. | |
| 170 write_to_disk_cb_ = base::Bind(&SimpleIndex::WriteToDisk, AsWeakPtr()); | |
|
gavinp
2013/05/21 19:59:21
Why not place this in the ctor list?
digit1
2013/05/30 13:17:58
Done.
| |
| 168 } | 171 } |
| 169 | 172 |
| 170 SimpleIndex::~SimpleIndex() { | 173 SimpleIndex::~SimpleIndex() { |
| 171 DCHECK(io_thread_checker_.CalledOnValidThread()); | 174 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 172 | 175 |
| 173 // Fail all callbacks waiting for the index to come up. | 176 // Fail all callbacks waiting for the index to come up. |
| 174 for (CallbackList::iterator it = to_run_when_initialized_.begin(), | 177 for (CallbackList::iterator it = to_run_when_initialized_.begin(), |
| 175 end = to_run_when_initialized_.end(); it != end; ++it) { | 178 end = to_run_when_initialized_.end(); it != end; ++it) { |
| 176 it->Run(net::ERR_ABORTED); | 179 it->Run(net::ERR_ABORTED); |
| 177 } | 180 } |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 253 const uint64 hash_key = simple_util::GetEntryHashKey(key); | 256 const uint64 hash_key = simple_util::GetEntryHashKey(key); |
| 254 InsertInEntrySet(EntryMetadata(hash_key, base::Time::Now(), 0), | 257 InsertInEntrySet(EntryMetadata(hash_key, base::Time::Now(), 0), |
| 255 &entries_set_); | 258 &entries_set_); |
| 256 if (!initialized_) | 259 if (!initialized_) |
| 257 removed_entries_.erase(hash_key); | 260 removed_entries_.erase(hash_key); |
| 258 PostponeWritingToDisk(); | 261 PostponeWritingToDisk(); |
| 259 } | 262 } |
| 260 | 263 |
| 261 void SimpleIndex::Remove(const std::string& key) { | 264 void SimpleIndex::Remove(const std::string& key) { |
| 262 DCHECK(io_thread_checker_.CalledOnValidThread()); | 265 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 263 UpdateEntrySize(key, 0); | |
| 264 const uint64 hash_key = simple_util::GetEntryHashKey(key); | 266 const uint64 hash_key = simple_util::GetEntryHashKey(key); |
| 265 entries_set_.erase(hash_key); | 267 EntrySet::iterator it = entries_set_.find(hash_key); |
| 268 if (it != entries_set_.end()) { | |
| 269 UpdateEntryIteratorSize(&it, 0); | |
| 270 entries_set_.erase(it); | |
| 271 } | |
| 266 | 272 |
| 267 if (!initialized_) | 273 if (!initialized_) |
| 268 removed_entries_.insert(hash_key); | 274 removed_entries_.insert(hash_key); |
| 269 PostponeWritingToDisk(); | 275 PostponeWritingToDisk(); |
| 270 } | 276 } |
| 271 | 277 |
| 272 bool SimpleIndex::Has(const std::string& key) const { | 278 bool SimpleIndex::Has(const std::string& key) const { |
| 273 DCHECK(io_thread_checker_.CalledOnValidThread()); | 279 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 274 // If not initialized, always return true, forcing it to go to the disk. | 280 // If not initialized, always return true, forcing it to go to the disk. |
| 275 return !initialized_ || | 281 return !initialized_ || |
| 276 entries_set_.count(simple_util::GetEntryHashKey(key)) != 0; | 282 entries_set_.find(simple_util::GetEntryHashKey(key)) != |
|
gavinp
2013/05/21 19:59:21
I don't think this is an improvement. count() is a
digit1
2013/05/30 13:17:58
count() is actually slowed than find() != end() wi
| |
| 283 entries_set_.end(); | |
| 277 } | 284 } |
| 278 | 285 |
| 279 bool SimpleIndex::UseIfExists(const std::string& key) { | 286 bool SimpleIndex::UseIfExists(const std::string& key) { |
| 280 DCHECK(io_thread_checker_.CalledOnValidThread()); | 287 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 281 // Always update the last used time, even if it is during initialization. | 288 // Always update the last used time, even if it is during initialization. |
| 282 // It will be merged later. | 289 // It will be merged later. |
| 283 EntrySet::iterator it = entries_set_.find(simple_util::GetEntryHashKey(key)); | 290 EntrySet::iterator it = entries_set_.find(simple_util::GetEntryHashKey(key)); |
| 284 if (it == entries_set_.end()) | 291 if (it == entries_set_.end()) |
| 285 // If not initialized, always return true, forcing it to go to the disk. | 292 // If not initialized, always return true, forcing it to go to the disk. |
| 286 return !initialized_; | 293 return !initialized_; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 331 | 338 |
| 332 scoped_ptr<int> result(new int()); | 339 scoped_ptr<int> result(new int()); |
| 333 base::Closure task = base::Bind(&SimpleSynchronousEntry::DoomEntrySet, | 340 base::Closure task = base::Bind(&SimpleSynchronousEntry::DoomEntrySet, |
| 334 base::Passed(&entry_hashes), | 341 base::Passed(&entry_hashes), |
| 335 index_filename_.DirName(), result.get()); | 342 index_filename_.DirName(), result.get()); |
| 336 base::Closure reply = base::Bind(&SimpleIndex::EvictionDone, AsWeakPtr(), | 343 base::Closure reply = base::Bind(&SimpleIndex::EvictionDone, AsWeakPtr(), |
| 337 base::Passed(&result)); | 344 base::Passed(&result)); |
| 338 base::WorkerPool::PostTaskAndReply(FROM_HERE, task, reply, true); | 345 base::WorkerPool::PostTaskAndReply(FROM_HERE, task, reply, true); |
| 339 } | 346 } |
| 340 | 347 |
| 341 bool SimpleIndex::UpdateEntrySize(const std::string& key, uint64 entry_size) { | 348 bool SimpleIndex::UpdateEntrySize(const std::string& key, uint64 entry_size) { |
|
gavinp
2013/05/21 19:59:21
Is there any way to lose this?
digit1
2013/05/30 13:17:58
The only place where it's called is SimpleEntryIm
| |
| 342 DCHECK(io_thread_checker_.CalledOnValidThread()); | 349 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 343 EntrySet::iterator it = entries_set_.find(simple_util::GetEntryHashKey(key)); | 350 EntrySet::iterator it = entries_set_.find(simple_util::GetEntryHashKey(key)); |
| 344 if (it == entries_set_.end()) | 351 if (it == entries_set_.end()) |
| 345 return false; | 352 return false; |
| 346 | 353 |
| 347 // Update the total cache size with the new entry size. | 354 UpdateEntryIteratorSize(&it, entry_size); |
| 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(); | 355 PostponeWritingToDisk(); |
| 353 StartEvictionIfNeeded(); | 356 StartEvictionIfNeeded(); |
| 354 return true; | 357 return true; |
| 355 } | 358 } |
| 356 | 359 |
| 357 void SimpleIndex::EvictionDone(scoped_ptr<int> result) { | 360 void SimpleIndex::EvictionDone(scoped_ptr<int> result) { |
| 358 DCHECK(io_thread_checker_.CalledOnValidThread()); | 361 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 359 DCHECK(result); | 362 DCHECK(result); |
| 360 | 363 |
| 361 // Ignore the result of eviction. We did our best. | 364 // 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)); | 378 std::make_pair(entry_metadata.GetHashKey(), entry_metadata)); |
| 376 } | 379 } |
| 377 | 380 |
| 378 void SimpleIndex::PostponeWritingToDisk() { | 381 void SimpleIndex::PostponeWritingToDisk() { |
| 379 if (!initialized_) | 382 if (!initialized_) |
| 380 return; | 383 return; |
| 381 const int delay = app_on_background_ ? kWriteToDiskOnBackgroundDelayMSecs | 384 const int delay = app_on_background_ ? kWriteToDiskOnBackgroundDelayMSecs |
| 382 : kWriteToDiskDelayMSecs; | 385 : kWriteToDiskDelayMSecs; |
| 383 // If the timer is already active, Start() will just Reset it, postponing it. | 386 // If the timer is already active, Start() will just Reset it, postponing it. |
| 384 write_to_disk_timer_.Start( | 387 write_to_disk_timer_.Start( |
| 385 FROM_HERE, | 388 FROM_HERE, base::TimeDelta::FromMilliseconds(delay), write_to_disk_cb_); |
| 386 base::TimeDelta::FromMilliseconds(delay), | 389 } |
| 387 base::Bind(&SimpleIndex::WriteToDisk, AsWeakPtr())); | 390 |
| 391 void SimpleIndex::UpdateEntryIteratorSize(EntrySet::iterator* it, | |
| 392 uint64 entry_size) { | |
|
gavinp
2013/05/21 19:59:21
Please add a thread checker.
digit1
2013/05/30 13:17:58
Done.
| |
| 393 // Update the total cache size with the new entry size. | |
| 394 DCHECK(cache_size_ - (*it)->second.GetEntrySize() <= cache_size_); | |
|
gavinp
2013/05/21 19:59:21
DCHECK_GE(cache_size, ...);
digit1
2013/05/30 13:17:58
Done.
| |
| 395 cache_size_ -= (*it)->second.GetEntrySize(); | |
| 396 cache_size_ += entry_size; | |
| 397 (*it)->second.SetEntrySize(entry_size); | |
| 388 } | 398 } |
| 389 | 399 |
| 390 // static | 400 // static |
| 391 bool SimpleIndex::IsIndexFileStale(const base::FilePath& index_filename) { | 401 bool SimpleIndex::IsIndexFileStale(const base::FilePath& index_filename) { |
| 392 base::Time index_mtime; | 402 base::Time index_mtime; |
| 393 base::Time dir_mtime; | 403 base::Time dir_mtime; |
| 394 if (!GetMTime(index_filename.DirName(), &dir_mtime)) | 404 if (!GetMTime(index_filename.DirName(), &dir_mtime)) |
| 395 return true; | 405 return true; |
| 396 if (!GetMTime(index_filename, &index_mtime)) | 406 if (!GetMTime(index_filename, &index_mtime)) |
| 397 return true; | 407 return true; |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 470 using file_util::FileEnumerator; | 480 using file_util::FileEnumerator; |
| 471 LOG(INFO) << "Simple Cache Index is being restored from disk."; | 481 LOG(INFO) << "Simple Cache Index is being restored from disk."; |
| 472 | 482 |
| 473 file_util::Delete(index_filename, /* recursive = */ false); | 483 file_util::Delete(index_filename, /* recursive = */ false); |
| 474 scoped_ptr<EntrySet> index_file_entries(new EntrySet()); | 484 scoped_ptr<EntrySet> index_file_entries(new EntrySet()); |
| 475 | 485 |
| 476 // TODO(felipeg,gavinp): Fix this once we have a one-file per entry format. | 486 // TODO(felipeg,gavinp): Fix this once we have a one-file per entry format. |
| 477 COMPILE_ASSERT(kSimpleEntryFileCount == 3, | 487 COMPILE_ASSERT(kSimpleEntryFileCount == 3, |
| 478 file_pattern_must_match_file_count); | 488 file_pattern_must_match_file_count); |
| 479 | 489 |
| 480 const int kFileSuffixLenght = std::string("_0").size(); | 490 const int kFileSuffixLength = strlen("_0"); |
| 481 const base::FilePath::StringType file_pattern = FILE_PATH_LITERAL("*_[0-2]"); | 491 const base::FilePath::StringType file_pattern = FILE_PATH_LITERAL("*_[0-2]"); |
| 482 FileEnumerator enumerator(index_filename.DirName(), | 492 FileEnumerator enumerator(index_filename.DirName(), |
| 483 false /* recursive */, | 493 false /* recursive */, |
| 484 FileEnumerator::FILES, | 494 FileEnumerator::FILES, |
| 485 file_pattern); | 495 file_pattern); |
| 486 for (base::FilePath file_path = enumerator.Next(); !file_path.empty(); | 496 for (base::FilePath file_path = enumerator.Next(); !file_path.empty(); |
| 487 file_path = enumerator.Next()) { | 497 file_path = enumerator.Next()) { |
| 488 const base::FilePath::StringType base_name = file_path.BaseName().value(); | 498 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 | 499 // Converting to std::string is OK since we never use UTF8 wide chars in our |
| 490 // file names. | 500 // file names. |
| 491 const std::string hash_name(base_name.begin(), base_name.end()); | 501 const std::string hash_key_string(base_name.begin(), |
| 492 const std::string hash_key_string = | 502 base_name.end() - kFileSuffixLength); |
| 493 hash_name.substr(0, hash_name.size() - kFileSuffixLenght); | |
| 494 uint64 hash_key = 0; | 503 uint64 hash_key = 0; |
| 495 if (!simple_util::GetEntryHashKeyFromHexString( | 504 if (!simple_util::GetEntryHashKeyFromHexString( |
| 496 hash_key_string, &hash_key)) { | 505 hash_key_string, &hash_key)) { |
| 497 LOG(WARNING) << "Invalid Entry Hash Key filename while restoring " | 506 LOG(WARNING) << "Invalid Entry Hash Key filename while restoring " |
| 498 << "Simple Index from disk: " << hash_name; | 507 << "Simple Index from disk: " << base_name; |
| 499 // TODO(felipeg): Should we delete the invalid file here ? | 508 // TODO(felipeg): Should we delete the invalid file here ? |
| 500 continue; | 509 continue; |
| 501 } | 510 } |
| 502 | 511 |
| 503 FileEnumerator::FindInfo find_info = {}; | 512 FileEnumerator::FindInfo find_info = {}; |
| 504 enumerator.GetFindInfo(&find_info); | 513 enumerator.GetFindInfo(&find_info); |
| 505 base::Time last_used_time; | 514 base::Time last_used_time; |
| 506 #if defined(OS_POSIX) | 515 #if defined(OS_POSIX) |
| 507 // For POSIX systems, a last access time is available. However, it's not | 516 // 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. | 517 // 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_); | 635 entries_set_); |
| 627 cache_thread_->PostTask(FROM_HERE, base::Bind( | 636 cache_thread_->PostTask(FROM_HERE, base::Bind( |
| 628 &SimpleIndex::WriteToDiskInternal, | 637 &SimpleIndex::WriteToDiskInternal, |
| 629 index_filename_, | 638 index_filename_, |
| 630 base::Passed(&pickle), | 639 base::Passed(&pickle), |
| 631 start, | 640 start, |
| 632 app_on_background_)); | 641 app_on_background_)); |
| 633 } | 642 } |
| 634 | 643 |
| 635 } // namespace disk_cache | 644 } // namespace disk_cache |
| OLD | NEW |