| 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 |