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

Side by Side Diff: sync/syncable/directory.cc

Issue 10821121: sync: Attempt to recover from directory corruption (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Review fixes Created 8 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
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 "sync/syncable/directory.h" 5 #include "sync/syncable/directory.h"
6 6
7 #include "base/debug/trace_event.h" 7 #include "base/debug/trace_event.h"
8 #include "base/perftimer.h" 8 #include "base/perftimer.h"
9 #include "base/stl_util.h" 9 #include "base/stl_util.h"
10 #include "base/string_number_conversions.h" 10 #include "base/string_number_conversions.h"
(...skipping 18 matching lines...) Expand all
29 namespace { 29 namespace {
30 // Helper function to add an item to the index, if it ought to be added. 30 // Helper function to add an item to the index, if it ought to be added.
31 template<typename Indexer> 31 template<typename Indexer>
32 void InitializeIndexEntry(EntryKernel* entry, 32 void InitializeIndexEntry(EntryKernel* entry,
33 typename Index<Indexer>::Set* index) { 33 typename Index<Indexer>::Set* index) {
34 if (Indexer::ShouldInclude(entry)) { 34 if (Indexer::ShouldInclude(entry)) {
35 index->insert(entry); 35 index->insert(entry);
36 } 36 }
37 } 37 }
38 38
39 // This function checks to see if the given list of Metahandles has any nodes
40 // whose PREV_ID, PARENT_ID or NEXT_ID values refer to ID values that do not
41 // actually exist. Returns true on success.
42 //
43 // This function is "Unsafe" because it does not attempt to acquire any locks
44 // that may be protecting this list that gets passed in. The caller is
45 // responsible for ensuring that no one modifies this list while the function is
46 // running.
47 bool VerifyReferenceIntegrityUnsafe(const syncable::MetahandlesIndex &index) {
48 TRACE_EVENT0("sync", "SyncDatabaseIntegrityCheck");
49 using namespace syncable;
50 typedef base::hash_set<std::string> IdsSet;
51
52 IdsSet ids_set;
53 bool is_ok = true;
54
55 for (MetahandlesIndex::const_iterator it = index.begin();
56 it != index.end(); ++it) {
57 EntryKernel* entry = *it;
58 bool is_duplicate_id = !(ids_set.insert(entry->ref(ID).value()).second);
59 is_ok = is_ok && !is_duplicate_id;
60 }
61
62 IdsSet::iterator end = ids_set.end();
63 for (MetahandlesIndex::const_iterator it = index.begin();
64 it != index.end(); ++it) {
65 EntryKernel* entry = *it;
66 bool prev_exists = (ids_set.find(entry->ref(PREV_ID).value()) != end);
67 bool parent_exists = (ids_set.find(entry->ref(PARENT_ID).value()) != end);
68 bool next_exists = (ids_set.find(entry->ref(NEXT_ID).value()) != end);
69 is_ok = is_ok && prev_exists && parent_exists && next_exists;
70 }
71 return is_ok;
72 }
73
74 } 39 }
75 40
76 // static 41 // static
77 bool ClientTagIndexer::ShouldInclude(const EntryKernel* a) { 42 bool ClientTagIndexer::ShouldInclude(const EntryKernel* a) {
78 return !a->ref(UNIQUE_CLIENT_TAG).empty(); 43 return !a->ref(UNIQUE_CLIENT_TAG).empty();
79 } 44 }
80 45
81 bool ParentIdAndHandleIndexer::Comparator::operator() ( 46 bool ParentIdAndHandleIndexer::Comparator::operator() (
82 const syncable::EntryKernel* a, 47 const syncable::EntryKernel* a,
83 const syncable::EntryKernel* b) const { 48 const syncable::EntryKernel* b) const {
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 transaction_observer) { 194 transaction_observer) {
230 195
231 KernelLoadInfo info; 196 KernelLoadInfo info;
232 // Temporary indices before kernel_ initialized in case Load fails. We 0(1) 197 // Temporary indices before kernel_ initialized in case Load fails. We 0(1)
233 // swap these later. 198 // swap these later.
234 MetahandlesIndex metas_bucket; 199 MetahandlesIndex metas_bucket;
235 DirOpenResult result = store_->Load(&metas_bucket, &info); 200 DirOpenResult result = store_->Load(&metas_bucket, &info);
236 if (OPENED != result) 201 if (OPENED != result)
237 return result; 202 return result;
238 203
239 if (!VerifyReferenceIntegrityUnsafe(metas_bucket))
240 return FAILED_LOGICAL_CORRUPTION;
241
242 kernel_ = new Kernel(name, info, delegate, transaction_observer); 204 kernel_ = new Kernel(name, info, delegate, transaction_observer);
243 kernel_->metahandles_index->swap(metas_bucket); 205 kernel_->metahandles_index->swap(metas_bucket);
244 InitializeIndices(); 206 InitializeIndices();
245 return OPENED; 207 return OPENED;
246 } 208 }
247 209
248 void Directory::Close() { 210 void Directory::Close() {
249 store_.reset(); 211 store_.reset();
250 if (kernel_) { 212 if (kernel_) {
251 delete kernel_; 213 delete kernel_;
(...skipping 993 matching lines...) Expand 10 before | Expand all | Expand 10 after
1245 // There were no children in the linked list. 1207 // There were no children in the linked list.
1246 return NULL; 1208 return NULL;
1247 } 1209 }
1248 1210
1249 ScopedKernelLock::ScopedKernelLock(const Directory* dir) 1211 ScopedKernelLock::ScopedKernelLock(const Directory* dir)
1250 : scoped_lock_(dir->kernel_->mutex), dir_(const_cast<Directory*>(dir)) { 1212 : scoped_lock_(dir->kernel_->mutex), dir_(const_cast<Directory*>(dir)) {
1251 } 1213 }
1252 1214
1253 } // namespace syncable 1215 } // namespace syncable
1254 } // namespace syncer 1216 } // namespace syncer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698