Index: sync/syncable/on_disk_directory_backing_store.cc |
diff --git a/sync/syncable/on_disk_directory_backing_store.cc b/sync/syncable/on_disk_directory_backing_store.cc |
index 1f43da6ada6744be7eacba8293c0801d12b7c730..10e694fccc996d9309e759fd6f3a1894737f9b6e 100644 |
--- a/sync/syncable/on_disk_directory_backing_store.cc |
+++ b/sync/syncable/on_disk_directory_backing_store.cc |
@@ -5,19 +5,33 @@ |
#include "sync/syncable/on_disk_directory_backing_store.h" |
#include "base/logging.h" |
+#include "base/metrics/histogram.h" |
+#include "sync/syncable/syncable-inl.h" |
namespace syncer { |
namespace syncable { |
+namespace { |
+ |
+enum HistogramResultEnum { |
+ FIRST_TRY_SUCCESS, |
+ SECOND_TRY_SUCCESS, |
+ SECOND_TRY_FAILURE, |
+ RESULT_COUNT |
+}; |
+ |
+} // namespace |
+ |
OnDiskDirectoryBackingStore::OnDiskDirectoryBackingStore( |
const std::string& dir_name, const FilePath& backing_filepath) |
: DirectoryBackingStore(dir_name), |
+ allow_failure_for_test_(false), |
backing_filepath_(backing_filepath) { |
db_->set_exclusive_locking(); |
db_->set_page_size(4096); |
} |
-DirOpenResult OnDiskDirectoryBackingStore::Load( |
+DirOpenResult OnDiskDirectoryBackingStore::TryLoad( |
MetahandlesIndex* entry_bucket, |
Directory::KernelLoadInfo* kernel_load_info) { |
DCHECK(CalledOnValidThread()); |
@@ -35,8 +49,50 @@ DirOpenResult OnDiskDirectoryBackingStore::Load( |
return FAILED_DATABASE_CORRUPT; |
if (!LoadInfo(kernel_load_info)) |
return FAILED_DATABASE_CORRUPT; |
+ if (!VerifyReferenceIntegrity(*entry_bucket)) |
+ return FAILED_DATABASE_CORRUPT; |
return OPENED; |
+ |
+} |
+ |
+DirOpenResult OnDiskDirectoryBackingStore::Load( |
+ MetahandlesIndex* entry_bucket, |
+ Directory::KernelLoadInfo* kernel_load_info) { |
+ DirOpenResult result = TryLoad(entry_bucket, kernel_load_info); |
+ if (result == OPENED) { |
+ HISTOGRAM_ENUMERATION( |
+ "Sync.DirectoryOpenResult", FIRST_TRY_SUCCESS, RESULT_COUNT); |
+ return OPENED; |
+ } |
+ |
+ // In debug builds, the last thing we want is to silently clear the database. |
+ // It's full of evidence that might help us determine what went wrong. It |
+ // might be sqlite's fault, but it could also be a bug in sync. We crash |
+ // 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
|
+ if (!allow_failure_for_test_) |
+ NOTREACHED() << "Crashing to preserve corrupt sync database"; |
+ |
+ // The fallback: delete the current database and return a fresh one. We can |
+ // fetch the user's data from the could. |
+ entry_bucket->clear(); |
+ 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
|
+ file_util::Delete(backing_filepath_, false); |
+ |
+ result = TryLoad(entry_bucket, kernel_load_info); |
+ if (result == OPENED) { |
+ HISTOGRAM_ENUMERATION( |
+ "Sync.DirectoryOpenResult", SECOND_TRY_SUCCESS, RESULT_COUNT); |
+ } else { |
+ HISTOGRAM_ENUMERATION( |
+ "Sync.DirectoryOpenResult", SECOND_TRY_FAILURE, RESULT_COUNT); |
+ } |
+ |
+ return result; |
+} |
+ |
+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
|
+ allow_failure_for_test_ = true; |
} |
} // namespace syncable |