OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/backend_impl.h" | 5 #include "net/disk_cache/backend_impl.h" |
6 | 6 |
7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
8 #include "base/histogram.h" | 8 #include "base/histogram.h" |
9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
425 return true; | 425 return true; |
426 } | 426 } |
427 | 427 |
428 entry->Doom(); | 428 entry->Doom(); |
429 entry->Close(); | 429 entry->Close(); |
430 EndEnumeration(&iter); // Dooming the entry invalidates the iterator. | 430 EndEnumeration(&iter); // Dooming the entry invalidates the iterator. |
431 } | 431 } |
432 } | 432 } |
433 | 433 |
434 bool BackendImpl::OpenNextEntry(void** iter, Entry** next_entry) { | 434 bool BackendImpl::OpenNextEntry(void** iter, Entry** next_entry) { |
435 if (disabled_) | 435 return OpenFollowingEntry(true, iter, next_entry); |
436 return false; | |
437 | |
438 Rankings::ScopedRankingsBlock rankings(&rankings_, | |
439 reinterpret_cast<CacheRankingsBlock*>(*iter)); | |
440 Rankings::ScopedRankingsBlock next(&rankings_, | |
441 rankings_.GetNext(rankings.get())); | |
442 *next_entry = NULL; | |
443 *iter = NULL; | |
444 if (!next.get()) | |
445 return false; | |
446 | |
447 scoped_refptr<EntryImpl> entry; | |
448 if (next->Data()->pointer) { | |
449 entry = reinterpret_cast<EntryImpl*>(next->Data()->pointer); | |
450 } else { | |
451 bool dirty; | |
452 EntryImpl* temp = NULL; | |
453 if (NewEntry(Addr(next->Data()->contents), &temp, &dirty)) | |
454 return false; | |
455 entry.swap(&temp); | |
456 | |
457 if (dirty) { | |
458 // We cannot trust this entry. Call MatchEntry to go through the regular | |
459 // path and take the appropriate action. | |
460 std::string key = entry->GetKey(); | |
461 uint32 hash = entry->GetHash(); | |
462 entry = NULL; // Release the entry. | |
463 temp = MatchEntry(key, hash, false); | |
464 if (temp) | |
465 temp->Release(); | |
466 | |
467 return false; | |
468 } | |
469 | |
470 entry.swap(&temp); | |
471 temp = EntryImpl::Update(temp); // Update returns an adref'd entry. | |
472 entry.swap(&temp); | |
473 if (!entry.get()) | |
474 return false; | |
475 } | |
476 | |
477 entry.swap(reinterpret_cast<EntryImpl**>(next_entry)); | |
478 *iter = next.release(); | |
479 return true; | |
480 } | 436 } |
481 | 437 |
482 void BackendImpl::EndEnumeration(void** iter) { | 438 void BackendImpl::EndEnumeration(void** iter) { |
483 Rankings::ScopedRankingsBlock rankings(&rankings_, | 439 Rankings::ScopedRankingsBlock rankings(&rankings_, |
484 reinterpret_cast<CacheRankingsBlock*>(*iter)); | 440 reinterpret_cast<CacheRankingsBlock*>(*iter)); |
485 *iter = NULL; | 441 *iter = NULL; |
486 } | 442 } |
487 | 443 |
488 void BackendImpl::GetStats(StatsItems* stats) { | 444 void BackendImpl::GetStats(StatsItems* stats) { |
489 if (disabled_) | 445 if (disabled_) |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
540 MappedFile* BackendImpl::File(Addr address) { | 496 MappedFile* BackendImpl::File(Addr address) { |
541 if (disabled_) | 497 if (disabled_) |
542 return NULL; | 498 return NULL; |
543 return block_files_.GetFile(address); | 499 return block_files_.GetFile(address); |
544 } | 500 } |
545 | 501 |
546 bool BackendImpl::CreateExternalFile(Addr* address) { | 502 bool BackendImpl::CreateExternalFile(Addr* address) { |
547 int file_number = data_->header.last_file + 1; | 503 int file_number = data_->header.last_file + 1; |
548 Addr file_address(0); | 504 Addr file_address(0); |
549 bool success = false; | 505 bool success = false; |
550 for (int i = 0; (i < 0x0fffffff) && !success; i++, file_number++) { | 506 for (int i = 0; i < 0x0fffffff; i++, file_number++) { |
551 if (!file_address.SetFileNumber(file_number)) { | 507 if (!file_address.SetFileNumber(file_number)) { |
552 file_number = 1; | 508 file_number = 1; |
553 continue; | 509 continue; |
554 } | 510 } |
555 std::wstring name = GetFileName(file_address); | 511 std::wstring name = GetFileName(file_address); |
556 int flags = base::PLATFORM_FILE_READ | | 512 int flags = base::PLATFORM_FILE_READ | |
557 base::PLATFORM_FILE_WRITE | | 513 base::PLATFORM_FILE_WRITE | |
558 base::PLATFORM_FILE_CREATE | | 514 base::PLATFORM_FILE_CREATE | |
559 base::PLATFORM_FILE_EXCLUSIVE_WRITE; | 515 base::PLATFORM_FILE_EXCLUSIVE_WRITE; |
560 scoped_refptr<disk_cache::File> file(new disk_cache::File( | 516 scoped_refptr<disk_cache::File> file(new disk_cache::File( |
561 base::CreatePlatformFile(name.c_str(), flags, NULL))); | 517 base::CreatePlatformFile(name.c_str(), flags, NULL))); |
562 if (!file->IsValid()) | 518 if (!file->IsValid()) |
563 continue; | 519 continue; |
564 | 520 |
565 success = true; | 521 success = true; |
| 522 break; |
566 } | 523 } |
567 | 524 |
568 DCHECK(success); | 525 DCHECK(success); |
569 if (!success) | 526 if (!success) |
570 return false; | 527 return false; |
571 | 528 |
572 data_->header.last_file = file_number; | 529 data_->header.last_file = file_number; |
573 address->set_value(file_address.value()); | 530 address->set_value(file_address.value()); |
574 return true; | 531 return true; |
575 } | 532 } |
576 | 533 |
577 bool BackendImpl::CreateBlock(FileType block_type, int block_count, | 534 bool BackendImpl::CreateBlock(FileType block_type, int block_count, |
578 Addr* block_address) { | 535 Addr* block_address) { |
579 return block_files_.CreateBlock(block_type, block_count, block_address); | 536 return block_files_.CreateBlock(block_type, block_count, block_address); |
580 } | 537 } |
581 | 538 |
582 void BackendImpl::DeleteBlock(Addr block_address, bool deep) { | 539 void BackendImpl::DeleteBlock(Addr block_address, bool deep) { |
583 block_files_.DeleteBlock(block_address, deep); | 540 block_files_.DeleteBlock(block_address, deep); |
584 } | 541 } |
585 | 542 |
586 void BackendImpl::UpdateRank(CacheRankingsBlock* node, bool modified) { | 543 void BackendImpl::UpdateRank(CacheRankingsBlock* node, bool modified) { |
587 rankings_.UpdateRank(node, modified); | 544 if (!read_only_) |
| 545 rankings_.UpdateRank(node, modified); |
588 } | 546 } |
589 | 547 |
590 void BackendImpl::RecoveredEntry(CacheRankingsBlock* rankings) { | 548 void BackendImpl::RecoveredEntry(CacheRankingsBlock* rankings) { |
591 Addr address(rankings->Data()->contents); | 549 Addr address(rankings->Data()->contents); |
592 EntryImpl* cache_entry = NULL; | 550 EntryImpl* cache_entry = NULL; |
593 bool dirty; | 551 bool dirty; |
594 if (NewEntry(address, &cache_entry, &dirty)) | 552 if (NewEntry(address, &cache_entry, &dirty)) |
595 return; | 553 return; |
596 | 554 |
597 uint32 hash = cache_entry->GetHash(); | 555 uint32 hash = cache_entry->GetHash(); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
701 } | 659 } |
702 | 660 |
703 void BackendImpl::DecrementIoCount() { | 661 void BackendImpl::DecrementIoCount() { |
704 num_pending_io_--; | 662 num_pending_io_--; |
705 } | 663 } |
706 | 664 |
707 void BackendImpl::SetUnitTestMode() { | 665 void BackendImpl::SetUnitTestMode() { |
708 unit_test_ = true; | 666 unit_test_ = true; |
709 } | 667 } |
710 | 668 |
| 669 void BackendImpl::SetUpgradeMode() { |
| 670 read_only_ = true; |
| 671 } |
| 672 |
711 void BackendImpl::ClearRefCountForTest() { | 673 void BackendImpl::ClearRefCountForTest() { |
712 num_refs_ = 0; | 674 num_refs_ = 0; |
713 } | 675 } |
714 | 676 |
715 int BackendImpl::SelfCheck() { | 677 int BackendImpl::SelfCheck() { |
716 if (!init_) { | 678 if (!init_) { |
717 LOG(ERROR) << "Init failed"; | 679 LOG(ERROR) << "Init failed"; |
718 return ERR_INIT_FAILED; | 680 return ERR_INIT_FAILED; |
719 } | 681 } |
720 | 682 |
721 int num_entries = rankings_.SelfCheck(); | 683 int num_entries = rankings_.SelfCheck(); |
722 if (num_entries < 0) { | 684 if (num_entries < 0) { |
723 LOG(ERROR) << "Invalid rankings list, error " << num_entries; | 685 LOG(ERROR) << "Invalid rankings list, error " << num_entries; |
724 return num_entries; | 686 return num_entries; |
725 } | 687 } |
726 | 688 |
727 if (num_entries != data_->header.num_entries) { | 689 if (num_entries != data_->header.num_entries) { |
728 LOG(ERROR) << "Number of entries mismatch"; | 690 LOG(ERROR) << "Number of entries mismatch"; |
729 return ERR_NUM_ENTRIES_MISMATCH; | 691 return ERR_NUM_ENTRIES_MISMATCH; |
730 } | 692 } |
731 | 693 |
732 return CheckAllEntries(); | 694 return CheckAllEntries(); |
733 } | 695 } |
734 | 696 |
| 697 bool BackendImpl::OpenPrevEntry(void** iter, Entry** prev_entry) { |
| 698 return OpenFollowingEntry(false, iter, prev_entry); |
| 699 } |
| 700 |
735 // ------------------------------------------------------------------------ | 701 // ------------------------------------------------------------------------ |
736 | 702 |
737 // We just created a new file so we're going to write the header and set the | 703 // We just created a new file so we're going to write the header and set the |
738 // file length to include the hash table (zero filled). | 704 // file length to include the hash table (zero filled). |
739 bool BackendImpl::CreateBackingStore(disk_cache::File* file) { | 705 bool BackendImpl::CreateBackingStore(disk_cache::File* file) { |
740 AdjustMaxCacheSize(0); | 706 AdjustMaxCacheSize(0); |
741 | 707 |
742 IndexHeader header; | 708 IndexHeader header; |
743 header.table_len = DesiredIndexTableLen(max_size_); | 709 header.table_len = DesiredIndexTableLen(max_size_); |
744 | 710 |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
859 cache_entry->ClearDirtyFlag(); | 825 cache_entry->ClearDirtyFlag(); |
860 | 826 |
861 if (!rankings_.SanityCheck(cache_entry->rankings(), false)) | 827 if (!rankings_.SanityCheck(cache_entry->rankings(), false)) |
862 return ERR_INVALID_LINKS; | 828 return ERR_INVALID_LINKS; |
863 | 829 |
864 cache_entry.swap(entry); | 830 cache_entry.swap(entry); |
865 return 0; | 831 return 0; |
866 } | 832 } |
867 | 833 |
868 EntryImpl* BackendImpl::MatchEntry(const std::string& key, uint32 hash, | 834 EntryImpl* BackendImpl::MatchEntry(const std::string& key, uint32 hash, |
869 bool find_parent) { | 835 bool find_parent) { |
870 Addr address(data_->table[hash & mask_]); | 836 Addr address(data_->table[hash & mask_]); |
871 EntryImpl* cache_entry = NULL; | 837 EntryImpl* cache_entry = NULL; |
872 EntryImpl* parent_entry = NULL; | 838 EntryImpl* parent_entry = NULL; |
873 bool found = false; | 839 bool found = false; |
874 | 840 |
875 for (;;) { | 841 for (;;) { |
876 if (disabled_) | 842 if (disabled_) |
877 break; | 843 break; |
878 | 844 |
879 if (!address.is_initialized()) { | 845 if (!address.is_initialized()) { |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
937 } | 903 } |
938 | 904 |
939 if (cache_entry && (find_parent || !found)) { | 905 if (cache_entry && (find_parent || !found)) { |
940 cache_entry->Release(); | 906 cache_entry->Release(); |
941 cache_entry = NULL; | 907 cache_entry = NULL; |
942 } | 908 } |
943 | 909 |
944 return find_parent ? parent_entry : cache_entry; | 910 return find_parent ? parent_entry : cache_entry; |
945 } | 911 } |
946 | 912 |
| 913 // This is the actual implementation for OpenNextEntry and OpenPrevEntry. |
| 914 bool BackendImpl::OpenFollowingEntry(bool forward, void** iter, |
| 915 Entry** next_entry) { |
| 916 if (disabled_) |
| 917 return false; |
| 918 |
| 919 Rankings::ScopedRankingsBlock rankings(&rankings_, |
| 920 reinterpret_cast<CacheRankingsBlock*>(*iter)); |
| 921 CacheRankingsBlock* next_block = forward ? rankings_.GetNext(rankings.get()) : |
| 922 rankings_.GetPrev(rankings.get()); |
| 923 Rankings::ScopedRankingsBlock next(&rankings_, next_block); |
| 924 *next_entry = NULL; |
| 925 *iter = NULL; |
| 926 if (!next.get()) |
| 927 return false; |
| 928 |
| 929 scoped_refptr<EntryImpl> entry; |
| 930 if (next->Data()->pointer) { |
| 931 entry = reinterpret_cast<EntryImpl*>(next->Data()->pointer); |
| 932 } else { |
| 933 bool dirty; |
| 934 EntryImpl* temp = NULL; |
| 935 if (NewEntry(Addr(next->Data()->contents), &temp, &dirty)) |
| 936 return false; |
| 937 entry.swap(&temp); |
| 938 |
| 939 if (dirty) { |
| 940 // We cannot trust this entry. Call MatchEntry to go through the regular |
| 941 // path and take the appropriate action. |
| 942 std::string key = entry->GetKey(); |
| 943 uint32 hash = entry->GetHash(); |
| 944 entry = NULL; // Release the entry. |
| 945 temp = MatchEntry(key, hash, false); |
| 946 if (temp) |
| 947 temp->Release(); |
| 948 |
| 949 return false; |
| 950 } |
| 951 |
| 952 entry.swap(&temp); |
| 953 temp = EntryImpl::Update(temp); // Update returns an adref'd entry. |
| 954 entry.swap(&temp); |
| 955 if (!entry.get()) |
| 956 return false; |
| 957 } |
| 958 |
| 959 entry.swap(reinterpret_cast<EntryImpl**>(next_entry)); |
| 960 *iter = next.release(); |
| 961 return true; |
| 962 } |
| 963 |
947 void BackendImpl::DestroyInvalidEntry(Addr address, EntryImpl* entry) { | 964 void BackendImpl::DestroyInvalidEntry(Addr address, EntryImpl* entry) { |
948 LOG(WARNING) << "Destroying invalid entry."; | 965 LOG(WARNING) << "Destroying invalid entry."; |
949 Trace("Destroying invalid entry 0x%p", entry); | 966 Trace("Destroying invalid entry 0x%p", entry); |
950 | 967 |
951 rankings_.Remove(entry->rankings()); | 968 rankings_.Remove(entry->rankings()); |
952 entry->SetPointerForInvalidEntry(GetCurrentEntryId()); | 969 entry->SetPointerForInvalidEntry(GetCurrentEntryId()); |
953 | 970 |
954 entry->InternalDoom(); | 971 entry->InternalDoom(); |
955 | 972 |
956 data_->header.num_entries--; | 973 data_->header.num_entries--; |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1126 | 1143 |
1127 return num_dirty; | 1144 return num_dirty; |
1128 } | 1145 } |
1129 | 1146 |
1130 bool BackendImpl::CheckEntry(EntryImpl* cache_entry) { | 1147 bool BackendImpl::CheckEntry(EntryImpl* cache_entry) { |
1131 RankingsNode* rankings = cache_entry->rankings()->Data(); | 1148 RankingsNode* rankings = cache_entry->rankings()->Data(); |
1132 return !rankings->pointer; | 1149 return !rankings->pointer; |
1133 } | 1150 } |
1134 | 1151 |
1135 } // namespace disk_cache | 1152 } // namespace disk_cache |
OLD | NEW |