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

Side by Side Diff: chrome/browser/chromeos/drive/resource_metadata_storage.cc

Issue 445513002: Add Drive.MetadataDBValidityCheckFailureReason UMA histogram (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix owners Created 6 years, 4 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 | « no previous file | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 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 "chrome/browser/chromeos/drive/resource_metadata_storage.h" 5 #include "chrome/browser/chromeos/drive/resource_metadata_storage.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/file_util.h" 8 #include "base/file_util.h"
9 #include "base/location.h" 9 #include "base/location.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 20 matching lines...) Expand all
31 DB_INIT_IO_ERROR, 31 DB_INIT_IO_ERROR,
32 DB_INIT_FAILED, 32 DB_INIT_FAILED,
33 DB_INIT_INCOMPATIBLE, 33 DB_INIT_INCOMPATIBLE,
34 DB_INIT_BROKEN, 34 DB_INIT_BROKEN,
35 DB_INIT_OPENED_EXISTING_DB, 35 DB_INIT_OPENED_EXISTING_DB,
36 DB_INIT_CREATED_NEW_DB, 36 DB_INIT_CREATED_NEW_DB,
37 DB_INIT_REPLACED_EXISTING_DB_WITH_NEW_DB, 37 DB_INIT_REPLACED_EXISTING_DB_WITH_NEW_DB,
38 DB_INIT_MAX_VALUE, 38 DB_INIT_MAX_VALUE,
39 }; 39 };
40 40
41 // Enum to describe DB validity check failure reason.
42 enum CheckValidityFailureReason {
43 CHECK_VALIDITY_FAILURE_INVALID_HEADER,
44 CHECK_VALIDITY_FAILURE_BROKEN_ID_ENTRY,
45 CHECK_VALIDITY_FAILURE_BROKEN_ENTRY,
46 CHECK_VALIDITY_FAILURE_INVALID_LOCAL_ID,
47 CHECK_VALIDITY_FAILURE_INVALID_PARENT_ID,
48 CHECK_VALIDITY_FAILURE_BROKEN_CHILD_MAP,
49 CHECK_VALIDITY_FAILURE_CHILD_ENTRY_COUNT_MISMATCH,
50 CHECK_VALIDITY_FAILURE_ITERATOR_ERROR,
51 CHECK_VALIDITY_FAILURE_MAX_VALUE,
52 };
53
41 // The name of the DB which stores the metadata. 54 // The name of the DB which stores the metadata.
42 const base::FilePath::CharType kResourceMapDBName[] = 55 const base::FilePath::CharType kResourceMapDBName[] =
43 FILE_PATH_LITERAL("resource_metadata_resource_map.db"); 56 FILE_PATH_LITERAL("resource_metadata_resource_map.db");
44 57
45 // The name of the DB which couldn't be opened, but is preserved just in case. 58 // The name of the DB which couldn't be opened, but is preserved just in case.
46 const base::FilePath::CharType kPreservedResourceMapDBName[] = 59 const base::FilePath::CharType kPreservedResourceMapDBName[] =
47 FILE_PATH_LITERAL("resource_metadata_preserved_resource_map.db"); 60 FILE_PATH_LITERAL("resource_metadata_preserved_resource_map.db");
48 61
49 // The name of the DB which couldn't be opened, and was replaced with a new one. 62 // The name of the DB which couldn't be opened, and was replaced with a new one.
50 const base::FilePath::CharType kTrashedResourceMapDBName[] = 63 const base::FilePath::CharType kTrashedResourceMapDBName[] =
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 ResourceMetadataHeader GetDefaultHeaderEntry() { 169 ResourceMetadataHeader GetDefaultHeaderEntry() {
157 ResourceMetadataHeader header; 170 ResourceMetadataHeader header;
158 header.set_version(ResourceMetadataStorage::kDBVersion); 171 header.set_version(ResourceMetadataStorage::kDBVersion);
159 return header; 172 return header;
160 } 173 }
161 174
162 bool MoveIfPossible(const base::FilePath& from, const base::FilePath& to) { 175 bool MoveIfPossible(const base::FilePath& from, const base::FilePath& to) {
163 return !base::PathExists(from) || base::Move(from, to); 176 return !base::PathExists(from) || base::Move(from, to);
164 } 177 }
165 178
179 void RecordCheckValidityFailure(CheckValidityFailureReason reason) {
180 UMA_HISTOGRAM_ENUMERATION("Drive.MetadataDBValidityCheckFailureReason",
181 reason,
182 CHECK_VALIDITY_FAILURE_MAX_VALUE);
183 }
184
166 } // namespace 185 } // namespace
167 186
168 ResourceMetadataStorage::Iterator::Iterator(scoped_ptr<leveldb::Iterator> it) 187 ResourceMetadataStorage::Iterator::Iterator(scoped_ptr<leveldb::Iterator> it)
169 : it_(it.Pass()) { 188 : it_(it.Pass()) {
170 base::ThreadRestrictions::AssertIOAllowed(); 189 base::ThreadRestrictions::AssertIOAllowed();
171 DCHECK(it_); 190 DCHECK(it_);
172 191
173 // Skip the header entry. 192 // Skip the header entry.
174 // Note: The header entry comes before all other entries because its key 193 // Note: The header entry comes before all other entries because its key
175 // starts with kDBKeyDelimeter. (i.e. '\0') 194 // starts with kDBKeyDelimeter. (i.e. '\0')
(...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after
925 // "|ID of B|" : ResourceEntry for entry B. 944 // "|ID of B|" : ResourceEntry for entry B.
926 // ... 945 // ...
927 946
928 // Check the header. 947 // Check the header.
929 ResourceMetadataHeader header; 948 ResourceMetadataHeader header;
930 if (!it->Valid() || 949 if (!it->Valid() ||
931 it->key() != GetHeaderDBKey() || // Header entry must come first. 950 it->key() != GetHeaderDBKey() || // Header entry must come first.
932 !header.ParseFromArray(it->value().data(), it->value().size()) || 951 !header.ParseFromArray(it->value().data(), it->value().size()) ||
933 header.version() != kDBVersion) { 952 header.version() != kDBVersion) {
934 DLOG(ERROR) << "Invalid header detected. version = " << header.version(); 953 DLOG(ERROR) << "Invalid header detected. version = " << header.version();
954 RecordCheckValidityFailure(CHECK_VALIDITY_FAILURE_INVALID_HEADER);
935 return false; 955 return false;
936 } 956 }
937 957
938 // Check all entries. 958 // Check all entries.
939 size_t num_entries_with_parent = 0; 959 size_t num_entries_with_parent = 0;
940 size_t num_child_entries = 0; 960 size_t num_child_entries = 0;
941 ResourceEntry entry; 961 ResourceEntry entry;
942 std::string serialized_entry; 962 std::string serialized_entry;
943 std::string child_id; 963 std::string child_id;
944 for (it->Next(); it->Valid(); it->Next()) { 964 for (it->Next(); it->Valid(); it->Next()) {
(...skipping 10 matching lines...) Expand all
955 // Resource-ID-to-local-ID mapping without entry for the local ID is ok. 975 // Resource-ID-to-local-ID mapping without entry for the local ID is ok.
956 if (status.IsNotFound()) 976 if (status.IsNotFound())
957 continue; 977 continue;
958 // When the entry exists, its resource ID must be consistent. 978 // When the entry exists, its resource ID must be consistent.
959 const bool ok = status.ok() && 979 const bool ok = status.ok() &&
960 entry.ParseFromString(serialized_entry) && 980 entry.ParseFromString(serialized_entry) &&
961 !entry.resource_id().empty() && 981 !entry.resource_id().empty() &&
962 leveldb::Slice(GetIdEntryKey(entry.resource_id())) == it->key(); 982 leveldb::Slice(GetIdEntryKey(entry.resource_id())) == it->key();
963 if (!ok) { 983 if (!ok) {
964 DLOG(ERROR) << "Broken ID entry. status = " << status.ToString(); 984 DLOG(ERROR) << "Broken ID entry. status = " << status.ToString();
985 RecordCheckValidityFailure(CHECK_VALIDITY_FAILURE_BROKEN_ID_ENTRY);
965 return false; 986 return false;
966 } 987 }
967 continue; 988 continue;
968 } 989 }
969 990
970 // Check if stored data is broken. 991 // Check if stored data is broken.
971 if (!entry.ParseFromArray(it->value().data(), it->value().size())) { 992 if (!entry.ParseFromArray(it->value().data(), it->value().size())) {
972 DLOG(ERROR) << "Broken entry detected"; 993 DLOG(ERROR) << "Broken entry detected";
994 RecordCheckValidityFailure(CHECK_VALIDITY_FAILURE_BROKEN_ENTRY);
973 return false; 995 return false;
974 } 996 }
975 997
976 if (leveldb::Slice(entry.local_id()) != it->key()) { 998 if (leveldb::Slice(entry.local_id()) != it->key()) {
977 DLOG(ERROR) << "Wrong local ID."; 999 DLOG(ERROR) << "Wrong local ID.";
1000 RecordCheckValidityFailure(CHECK_VALIDITY_FAILURE_INVALID_LOCAL_ID);
978 return false; 1001 return false;
979 } 1002 }
980 1003
981 if (!entry.parent_local_id().empty()) { 1004 if (!entry.parent_local_id().empty()) {
982 // Check if the parent entry is stored. 1005 // Check if the parent entry is stored.
983 leveldb::Status status = resource_map_->Get( 1006 leveldb::Status status = resource_map_->Get(
984 options, 1007 options,
985 leveldb::Slice(entry.parent_local_id()), 1008 leveldb::Slice(entry.parent_local_id()),
986 &serialized_entry); 1009 &serialized_entry);
987 if (!status.ok()) { 1010 if (!status.ok()) {
988 DLOG(ERROR) << "Can't get parent entry. status = " << status.ToString(); 1011 DLOG(ERROR) << "Can't get parent entry. status = " << status.ToString();
1012 RecordCheckValidityFailure(CHECK_VALIDITY_FAILURE_INVALID_PARENT_ID);
989 return false; 1013 return false;
990 } 1014 }
991 1015
992 // Check if parent-child relationship is stored correctly. 1016 // Check if parent-child relationship is stored correctly.
993 status = resource_map_->Get( 1017 status = resource_map_->Get(
994 options, 1018 options,
995 leveldb::Slice(GetChildEntryKey(entry.parent_local_id(), 1019 leveldb::Slice(GetChildEntryKey(entry.parent_local_id(),
996 entry.base_name())), 1020 entry.base_name())),
997 &child_id); 1021 &child_id);
998 if (!status.ok() || leveldb::Slice(child_id) != it->key()) { 1022 if (!status.ok() || leveldb::Slice(child_id) != it->key()) {
999 DLOG(ERROR) << "Child map is broken. status = " << status.ToString(); 1023 DLOG(ERROR) << "Child map is broken. status = " << status.ToString();
1024 RecordCheckValidityFailure(CHECK_VALIDITY_FAILURE_BROKEN_CHILD_MAP);
1000 return false; 1025 return false;
1001 } 1026 }
1002 ++num_entries_with_parent; 1027 ++num_entries_with_parent;
1003 } 1028 }
1004 } 1029 }
1005 if (!it->status().ok() || num_child_entries != num_entries_with_parent) { 1030 if (!it->status().ok()) {
1006 DLOG(ERROR) << "Error during checking resource map. status = " 1031 DLOG(ERROR) << "Error during checking resource map. status = "
1007 << it->status().ToString(); 1032 << it->status().ToString();
1033 RecordCheckValidityFailure(CHECK_VALIDITY_FAILURE_ITERATOR_ERROR);
1034 return false;
1035 }
1036 if (num_child_entries != num_entries_with_parent) {
1037 DLOG(ERROR) << "Child entry count mismatch";
1038 RecordCheckValidityFailure(
1039 CHECK_VALIDITY_FAILURE_CHILD_ENTRY_COUNT_MISMATCH);
1008 return false; 1040 return false;
1009 } 1041 }
1010 return true; 1042 return true;
1011 } 1043 }
1012 1044
1013 } // namespace internal 1045 } // namespace internal
1014 } // namespace drive 1046 } // namespace drive
OLDNEW
« no previous file with comments | « no previous file | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698