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

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

Issue 10821121: sync: Attempt to recover from directory corruption (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: 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/on_disk_directory_backing_store.h" 5 #include "sync/syncable/on_disk_directory_backing_store.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/metrics/histogram.h"
9 #include "sync/syncable/syncable-inl.h"
8 10
9 namespace syncer { 11 namespace syncer {
10 namespace syncable { 12 namespace syncable {
11 13
14 namespace {
15
16 enum HistogramResultEnum {
17 FIRST_TRY_SUCCESS,
18 SECOND_TRY_SUCCESS,
19 SECOND_TRY_FAILURE,
20 RESULT_COUNT
21 };
22
23 } // namespace
24
12 OnDiskDirectoryBackingStore::OnDiskDirectoryBackingStore( 25 OnDiskDirectoryBackingStore::OnDiskDirectoryBackingStore(
13 const std::string& dir_name, const FilePath& backing_filepath) 26 const std::string& dir_name, const FilePath& backing_filepath)
14 : DirectoryBackingStore(dir_name), 27 : DirectoryBackingStore(dir_name),
28 allow_failure_for_test_(false),
15 backing_filepath_(backing_filepath) { 29 backing_filepath_(backing_filepath) {
16 db_->set_exclusive_locking(); 30 db_->set_exclusive_locking();
17 db_->set_page_size(4096); 31 db_->set_page_size(4096);
18 } 32 }
19 33
20 DirOpenResult OnDiskDirectoryBackingStore::Load( 34 DirOpenResult OnDiskDirectoryBackingStore::TryLoad(
21 MetahandlesIndex* entry_bucket, 35 MetahandlesIndex* entry_bucket,
22 Directory::KernelLoadInfo* kernel_load_info) { 36 Directory::KernelLoadInfo* kernel_load_info) {
23 DCHECK(CalledOnValidThread()); 37 DCHECK(CalledOnValidThread());
24 if (!db_->is_open()) { 38 if (!db_->is_open()) {
25 if (!db_->Open(backing_filepath_)) 39 if (!db_->Open(backing_filepath_))
26 return FAILED_OPEN_DATABASE; 40 return FAILED_OPEN_DATABASE;
27 } 41 }
28 42
29 if (!InitializeTables()) 43 if (!InitializeTables())
30 return FAILED_OPEN_DATABASE; 44 return FAILED_OPEN_DATABASE;
31 45
32 if (!DropDeletedEntries()) 46 if (!DropDeletedEntries())
33 return FAILED_DATABASE_CORRUPT; 47 return FAILED_DATABASE_CORRUPT;
34 if (!LoadEntries(entry_bucket)) 48 if (!LoadEntries(entry_bucket))
35 return FAILED_DATABASE_CORRUPT; 49 return FAILED_DATABASE_CORRUPT;
36 if (!LoadInfo(kernel_load_info)) 50 if (!LoadInfo(kernel_load_info))
37 return FAILED_DATABASE_CORRUPT; 51 return FAILED_DATABASE_CORRUPT;
52 if (!VerifyReferenceIntegrity(*entry_bucket))
53 return FAILED_DATABASE_CORRUPT;
38 54
39 return OPENED; 55 return OPENED;
56
57 }
58
59 DirOpenResult OnDiskDirectoryBackingStore::Load(
60 MetahandlesIndex* entry_bucket,
61 Directory::KernelLoadInfo* kernel_load_info) {
62 DirOpenResult result = TryLoad(entry_bucket, kernel_load_info);
63 if (result == OPENED) {
64 HISTOGRAM_ENUMERATION(
65 "Sync.DirectoryOpenResult", FIRST_TRY_SUCCESS, RESULT_COUNT);
66 return OPENED;
67 }
68
69 // In debug builds, the last thing we want is to silently clear the database.
70 // It's full of evidence that might help us determine what went wrong. It
71 // might be sqlite's fault, but it could also be a bug in sync. We crash
72 // immediately so a developer can investigate.
tim (not reviewing) 2012/08/01 21:31:59 Let's keep an eye on this. I've seen similar dche
rlarocque 2012/08/01 22:37:51 I've updated the comment with instructions on how
73 if (!allow_failure_for_test_)
74 NOTREACHED() << "Crashing to preserve corrupt sync database";
75
76 // The fallback: delete the current database and return a fresh one. We can
77 // fetch the user's data from the could.
78 entry_bucket->clear();
79 db_.reset(new sql::Connection);
tim (not reviewing) 2012/08/01 21:31:59 A bit nervous to swap this out since we set it in
80 file_util::Delete(backing_filepath_, false);
81
82 result = TryLoad(entry_bucket, kernel_load_info);
83 if (result == OPENED) {
84 HISTOGRAM_ENUMERATION(
85 "Sync.DirectoryOpenResult", SECOND_TRY_SUCCESS, RESULT_COUNT);
86 } else {
87 HISTOGRAM_ENUMERATION(
88 "Sync.DirectoryOpenResult", SECOND_TRY_FAILURE, RESULT_COUNT);
89 }
90
91 return result;
92 }
93
94 void OnDiskDirectoryBackingStore::AllowFailureForTest() {
tim (not reviewing) 2012/08/01 21:31:59 I think it would be clearer / preferable to have a
rlarocque 2012/08/01 21:53:50 Yet another implementation of DirectoryBackingStor
95 allow_failure_for_test_ = true;
40 } 96 }
41 97
42 } // namespace syncable 98 } // namespace syncable
43 } // namespace syncer 99 } // namespace syncer
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698