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

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, 7 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 int head_items;
792 if (!my_head.is_initialized()) { 784 int rv = CheckListSection(list, last1, last2, true, // Head to tail.
rvargas (doing something else) 2012/04/30 22:03:01 How about this then. No name to mess, no changing
793 if (!my_tail.is_initialized()) 785 &last1, &last2, &head_items);
794 return 0; 786 if (rv == 0)
795 // If there is no head, having a tail is an error. 787 return head_items;
796 return ERR_INVALID_TAIL; 788
789 Addr last3, last4;
790 int tail_items;
791 int rv2 = CheckListSection(list, last1, last2, false, // Tail to head.
792 &last3, &last4, &tail_items);
793
794 if (!head_items && rv != ERR_INVALID_NEXT)
795 rv = ERR_INVALID_HEAD;
796
797 if (!tail_items && rv2 != ERR_INVALID_NEXT)
798 rv2 = ERR_INVALID_HEAD;
799
800 int expected = control_data_->sizes[list];
801 int total_items = head_items + tail_items;
802
803 if (!count_lists_) {
804 // There's no expected value, so we'll use something else. If it looks like
805 // we can rebuild the list, we lost at least one entry.
806 if (last3 == last1 || last3 == last2 || last4 == last1 || last4 == last2)
807 expected = total_items + 1;
797 } 808 }
798 // If there is no tail, having a head is an error. 809
799 if (!my_tail.is_initialized()) 810 if (expected) {
811 // This histogram has an offset so that we can see small negative values. In
812 // practice, it is linear from -9 to +8.
813 UMA_HISTOGRAM_CUSTOM_COUNTS("DiskCache.LostItems(Plus10)",
814 expected - total_items + 10, 0, 2000, 75);
815 }
816
817 const int kInvalidHead = 1;
818 const int kInvalidTail = 2;
819 const int kInvalidHeadAndTail = 3;
820 const int kOneInvalidEntry = 4;
821 const int kTwoInvalidEntries = 5;
822 const int kOneInvalidLink = 6;
823 const int kTwoInvalidLinks = 7;
824 const int kOneInvalidEntryOneInvalidLink = 8;
825
826 int error = list * 10;
827 if (rv == ERR_INVALID_HEAD && rv2 != ERR_INVALID_HEAD) {
828 error += kInvalidHead;
829 } else if (rv == ERR_INVALID_HEAD && rv2 == ERR_INVALID_HEAD) {
830 error += kInvalidHeadAndTail;
831 } else if (rv != ERR_INVALID_HEAD && rv2 == ERR_INVALID_HEAD) {
832 error += kInvalidTail;
833 } else if (rv == ERR_INVALID_ENTRY && rv2 == ERR_INVALID_ENTRY) {
834 error += kTwoInvalidEntries;
835 } else if (rv == ERR_INVALID_ENTRY && rv2 == 0) {
836 error += kOneInvalidEntry;
837 } else if (rv == ERR_INVALID_ENTRY || rv2 == ERR_INVALID_ENTRY) {
838 error += kOneInvalidEntryOneInvalidLink;
839 } else if (rv2 != 0) {
840 error += kTwoInvalidLinks;
841 } else {
842 error += kOneInvalidLink;
843 }
844 CACHE_UMA(CACHE_ERROR, "ListError", 0, error);
845
846 return rv;
847 }
848
849 // Note that the returned error codes assume a forward walk (from head to tail)
850 // so they have to be adjusted accordingly by the caller. We use two stop values
851 // to be able to detect a corrupt node at the end that is not linked going back.
852 int Rankings::CheckListSection(List list, Addr end1, Addr end2,
853 ListDirection dir,
854 Addr* last, Addr* second_last, int* num_items) {
855 Addr current = (dir == FORWARD) ? heads_[list] : tails_[list];
856 *last = *second_last = current;
857 *num_items = 0;
858 if (!current.is_initialized())
859 return ERR_NO_ERROR;
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 = (dir == FORWARD) ? node->Data()->next : node->Data()->prev;
821 address.set_value(node->Data()->next); 873 CacheAddr prev = (dir == 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 *second_last = *last;
885 *last = current;
886 (*num_items)++;
887
888 if (next_addr == prev_addr) {
889 Addr last = (dir == FORWARD) ? tails_[list] : heads_[list];
890 if (next_addr == last)
891 return ERR_NO_ERROR;
892 return ERR_INVALID_TAIL;
893 }
894 } while (current != end1 && current != end2);
895 return ERR_NO_ERROR;
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