Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(35)

Side by Side Diff: net/disk_cache/rankings.cc

Issue 10148001: Disk Cache: Add more corruption tracking histograms. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/disk_cache/rankings.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/rankings.h" 5 #include "net/disk_cache/rankings.h"
6 6
7 #include "base/metrics/histogram.h" 7 #include "base/metrics/histogram.h"
8 #include "net/disk_cache/backend_impl.h" 8 #include "net/disk_cache/backend_impl.h"
9 #include "net/disk_cache/entry_impl.h" 9 #include "net/disk_cache/entry_impl.h"
10 #include "net/disk_cache/errors.h" 10 #include "net/disk_cache/errors.h"
(...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after
717 next.Data()->prev = prev.address().value(); 717 next.Data()->prev = prev.address().value();
718 WriteTail(my_list); 718 WriteTail(my_list);
719 } 719 }
720 720
721 next.Store(); 721 next.Store();
722 prev.Store(); 722 prev.Store();
723 control_data_->transaction = 0; 723 control_data_->transaction = 0;
724 control_data_->operation = 0; 724 control_data_->operation = 0;
725 } 725 }
726 726
727 bool Rankings::CheckEntry(CacheRankingsBlock* rankings) {
728 if (rankings->VerifyHash())
729 return true;
730
731 // If this entry is not dirty, it is a serious problem.
732 return backend_->GetCurrentEntryId() != rankings->Data()->dirty;
733 }
734
735 bool Rankings::CheckLinks(CacheRankingsBlock* node, CacheRankingsBlock* prev, 727 bool Rankings::CheckLinks(CacheRankingsBlock* node, CacheRankingsBlock* prev,
736 CacheRankingsBlock* next, List* list) { 728 CacheRankingsBlock* next, List* list) {
737 CacheAddr node_addr = node->address().value(); 729 CacheAddr node_addr = node->address().value();
738 if (prev->Data()->next == node_addr && 730 if (prev->Data()->next == node_addr &&
739 next->Data()->prev == node_addr) { 731 next->Data()->prev == node_addr) {
740 // A regular linked node. 732 // A regular linked node.
741 return true; 733 return true;
742 } 734 }
743 735
744 Trace("CheckLinks 0x%x (0x%x 0x%x)", node_addr, 736 Trace("CheckLinks 0x%x (0x%x 0x%x)", node_addr,
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
780 LOG(ERROR) << "Inconsistent LRU."; 772 LOG(ERROR) << "Inconsistent LRU.";
781 773
782 backend_->CriticalError(ERR_INVALID_LINKS); 774 backend_->CriticalError(ERR_INVALID_LINKS);
783 return false; 775 return false;
784 } 776 }
785 777
786 return true; 778 return true;
787 } 779 }
788 780
789 int Rankings::CheckList(List list) { 781 int Rankings::CheckList(List list) {
790 Addr& my_head = heads_[list]; 782 Addr last1, last2;
791 Addr& my_tail = tails_[list]; 783 bool forward = true;
792 if (!my_head.is_initialized()) { 784 int num_items;
793 if (!my_tail.is_initialized()) 785 int rv = CheckListSection(list, last1, last2, forward,
794 return 0; 786 &last1, &last2, &num_items);
795 // If there is no head, having a tail is an error. 787 if (rv == 0)
796 return ERR_INVALID_TAIL; 788 return num_items;
789
790 Addr last3, last4;
791 int num_items2;
792 forward = false;
gavinp 2012/04/23 19:10:37 forward = false is confusing. You're right that I
rvargas (doing something else) 2012/04/23 21:22:26 why? What would be an appropriate name for a bool
gavinp 2012/04/25 12:40:23 is_forward is definitely a better name. But I sti
793 int rv2 = CheckListSection(list, last1, last2, forward,
794 &last3, &last4, &num_items2);
795
796 if (!num_items && rv != ERR_INVALID_NEXT)
797 rv = ERR_INVALID_HEAD;
798
799 if (!num_items2 && rv2 != ERR_INVALID_NEXT)
800 rv2 = ERR_INVALID_HEAD;
801
802 int expected = control_data_->sizes[list];
803 int total_items = num_items + num_items2;
804
805 if (!count_lists_) {
806 // There's no expected value, so we'll use something else.
807 if (last3 == last1 || last3 == last2 || last4 == last1 || last4 == last2)
808 expected = total_items + 1;
797 } 809 }
798 // If there is no tail, having a head is an error. 810
799 if (!my_tail.is_initialized()) 811 if (expected) {
812 // This histogram has an offset so that we can see small negative values. In
813 // practice, it is linear from -9 to +8.
814 UMA_HISTOGRAM_CUSTOM_COUNTS("DiskCache.LostItems",
815 expected - total_items + 10, 0, 2000, 75);
816 }
817
818 const int kInvalidHead = 1;
819 const int kInvalidTail = 2;
820 const int kInvalidHeadAndTail = 3;
821 const int kOneInvalidEntry = 4;
822 const int kTwoInvalidEntries = 5;
823 const int kOneInvalidLink = 6;
824 const int kTwoInvalidLinks = 7;
825 const int kOneInvalidEntryOneInvalidLink = 8;
826
827 int error = list * 10;
828 if (rv == ERR_INVALID_HEAD && rv2 != ERR_INVALID_HEAD) {
829 error += kInvalidHead;
830 } else if (rv == ERR_INVALID_HEAD && rv2 == ERR_INVALID_HEAD) {
831 error += kInvalidHeadAndTail;
832 } else if (rv != ERR_INVALID_HEAD && rv2 == ERR_INVALID_HEAD) {
833 error += kInvalidTail;
834 } else if (rv == ERR_INVALID_ENTRY && rv2 == ERR_INVALID_ENTRY) {
835 error += kTwoInvalidEntries;
836 } else if (rv == ERR_INVALID_ENTRY && rv2 == 0) {
837 error += kOneInvalidEntry;
838 } else if (rv == ERR_INVALID_ENTRY || rv2 == ERR_INVALID_ENTRY) {
839 error += kOneInvalidEntryOneInvalidLink;
840 } else if (rv2 != 0) {
841 error += kTwoInvalidLinks;
842 } else {
843 error += kOneInvalidLink;
844 }
845 CACHE_UMA(CACHE_ERROR, "ListError", 0, error);
846
847 return rv;
848 }
849
850 // Note that the returned error codes assume a forward walk (from head to tail)
851 // so they have to be adjusted accordingly by the caller. We use two stop values
852 // to be able to detect a corrupt node at the end that is not linked going back.
853 int Rankings::CheckListSection(List list, Addr stop1, Addr stop2, bool forward,
rvargas (doing something else) 2012/04/19 21:45:09 I know you don't like boolean arguments, but this
854 Addr* last1, Addr* last2, int* num_items) {
855 Addr current = forward ? heads_[list] : tails_[list];
856 *last1 = *last2 = current;
857 *num_items = 0;
858 if (!current.is_initialized())
859 return 0;
860
861 if (!current.SanityCheckForRankings())
800 return ERR_INVALID_HEAD; 862 return ERR_INVALID_HEAD;
801 863
802 if (my_tail.is_separate_file())
803 return ERR_INVALID_TAIL;
804
805 if (my_head.is_separate_file())
806 return ERR_INVALID_HEAD;
807
808 int num_items = 0;
809 Addr address(my_head.value());
810 Addr prev(my_head.value());
811 scoped_ptr<CacheRankingsBlock> node; 864 scoped_ptr<CacheRankingsBlock> node;
865 Addr prev_addr(current);
812 do { 866 do {
813 node.reset(new CacheRankingsBlock(backend_->File(address), address)); 867 node.reset(new CacheRankingsBlock(backend_->File(current), current));
814 node->Load(); 868 node->Load();
815 if (node->Data()->prev != prev.value()) 869 if (!SanityCheck(node.get(), true))
816 return ERR_INVALID_PREV;
817 if (!CheckEntry(node.get()))
818 return ERR_INVALID_ENTRY; 870 return ERR_INVALID_ENTRY;
819 871
820 prev.set_value(address.value()); 872 CacheAddr next = forward ? node->Data()->next : node->Data()->prev;
821 address.set_value(node->Data()->next); 873 CacheAddr prev = forward ? node->Data()->prev : node->Data()->next;
822 if (!address.is_initialized() || address.is_separate_file()) 874
875 if (prev != prev_addr.value())
876 return ERR_INVALID_PREV;
877
878 Addr next_addr(next);
879 if (!next_addr.SanityCheckForRankings())
823 return ERR_INVALID_NEXT; 880 return ERR_INVALID_NEXT;
824 881
825 num_items++; 882 prev_addr = current;
826 } while (node->address().value() != address.value()); 883 current = next_addr;
827 return num_items; 884 *last2 = *last1;
885 *last1 = current;
886 (*num_items)++;
887
888 if (next_addr == prev_addr) {
889 Addr last = forward ? tails_[list] : heads_[list];
890 if (next_addr == last)
891 return 0;
892 return ERR_INVALID_TAIL;
893 }
894 } while (current != stop1 && current != stop2);
895 return 0;
828 } 896 }
829 897
830 bool Rankings::IsHead(CacheAddr addr, List* list) const { 898 bool Rankings::IsHead(CacheAddr addr, List* list) const {
831 for (int i = 0; i < LAST_ELEMENT; i++) { 899 for (int i = 0; i < LAST_ELEMENT; i++) {
832 if (addr == heads_[i].value()) { 900 if (addr == heads_[i].value()) {
833 if (*list != i) 901 if (*list != i)
834 Trace("Changing list %d to %d", *list, i); 902 Trace("Changing list %d to %d", *list, i);
835 *list = static_cast<List>(i); 903 *list = static_cast<List>(i);
836 return true; 904 return true;
837 } 905 }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
888 void Rankings::DecrementCounter(List list) { 956 void Rankings::DecrementCounter(List list) {
889 if (!count_lists_) 957 if (!count_lists_)
890 return; 958 return;
891 959
892 DCHECK(control_data_->sizes[list] > 0); 960 DCHECK(control_data_->sizes[list] > 0);
893 if (control_data_->sizes[list] > 0) 961 if (control_data_->sizes[list] > 0)
894 control_data_->sizes[list]--; 962 control_data_->sizes[list]--;
895 } 963 }
896 964
897 } // namespace disk_cache 965 } // namespace disk_cache
OLDNEW
« no previous file with comments | « net/disk_cache/rankings.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698