diff options
author | albertb@chromium.org <albertb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-27 17:17:05 +0000 |
---|---|---|
committer | albertb@chromium.org <albertb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-27 17:17:05 +0000 |
commit | 62e0dbdec1c30c929d7c6148372b153e9b1c1792 (patch) | |
tree | 5be4d32baa5d183554a3b1d6bf2e43afc1734f43 /chrome/browser | |
parent | 17a9a971303d65afcd32ab0921e1beb8dd27329c (diff) | |
download | chromium_src-62e0dbdec1c30c929d7c6148372b153e9b1c1792.zip chromium_src-62e0dbdec1c30c929d7c6148372b153e9b1c1792.tar.gz chromium_src-62e0dbdec1c30c929d7c6148372b153e9b1c1792.tar.bz2 |
Delete and recreate the sync database if it is corrupt.
BUG=40020
TEST=DirectoryBackingStoreTest.Corruption
Review URL: http://codereview.chromium.org/1733008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@45712 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
3 files changed, 41 insertions, 4 deletions
diff --git a/chrome/browser/sync/syncable/directory_backing_store.cc b/chrome/browser/sync/syncable/directory_backing_store.cc index 2635def..9c86ea7 100644 --- a/chrome/browser/sync/syncable/directory_backing_store.cc +++ b/chrome/browser/sync/syncable/directory_backing_store.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -12,6 +12,7 @@ #include <limits> +#include "base/file_util.h" #include "base/hash_tables.h" #include "base/logging.h" #include "chrome/browser/sync/protocol/bookmark_specifics.pb.h" @@ -179,19 +180,22 @@ DirectoryBackingStore::~DirectoryBackingStore() { bool DirectoryBackingStore::OpenAndConfigureHandleHelper( sqlite3** handle) const { if (SQLITE_OK == OpenSqliteDb(backing_filepath_, handle)) { + sqlite_utils::scoped_sqlite_db_ptr scoped_handle(*handle); sqlite3_busy_timeout(*handle, std::numeric_limits<int>::max()); { SQLStatement statement; statement.prepare(*handle, "PRAGMA fullfsync = 1"); if (SQLITE_DONE != statement.step()) { - LOG(FATAL) << sqlite3_errmsg(*handle); + LOG(ERROR) << sqlite3_errmsg(*handle); + return false; } } { SQLStatement statement; statement.prepare(*handle, "PRAGMA synchronous = 2"); if (SQLITE_DONE != statement.step()) { - LOG(FATAL) << sqlite3_errmsg(*handle); + LOG(ERROR) << sqlite3_errmsg(*handle); + return false; } } sqlite3_busy_timeout(*handle, kDirectoryBackingStoreBusyTimeoutMs); @@ -204,6 +208,7 @@ bool DirectoryBackingStore::OpenAndConfigureHandleHelper( attrs | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED); #endif + scoped_handle.release(); return true; } return false; @@ -230,6 +235,13 @@ DirOpenResult DirectoryBackingStore::Load(MetahandlesIndex* entry_bucket, bool DirectoryBackingStore::BeginLoad() { DCHECK(load_dbhandle_ == NULL); + bool ret = OpenAndConfigureHandleHelper(&load_dbhandle_); + if (ret) + return ret; + // Something's gone wrong. Nuke the database and try again. + LOG(ERROR) << "Sync database " << backing_filepath_.value() + << " corrupt. Deleting and recreating."; + file_util::Delete(backing_filepath_, false); return OpenAndConfigureHandleHelper(&load_dbhandle_); } diff --git a/chrome/browser/sync/syncable/directory_backing_store.h b/chrome/browser/sync/syncable/directory_backing_store.h index 34cb3ac..d1e7d7d 100644 --- a/chrome/browser/sync/syncable/directory_backing_store.h +++ b/chrome/browser/sync/syncable/directory_backing_store.h @@ -81,6 +81,7 @@ class DirectoryBackingStore { FRIEND_TEST(DirectoryBackingStoreTest, MigrateVersion69To70); FRIEND_TEST(DirectoryBackingStoreTest, MigrateVersion70To71); FRIEND_TEST(DirectoryBackingStoreTest, ModelTypeIds); + FRIEND_TEST(DirectoryBackingStoreTest, Corruption); FRIEND_TEST(MigrationTest, ToCurrentVersion); // General Directory initialization and load helpers. @@ -148,7 +149,7 @@ class DirectoryBackingStore { int GetVersion(); bool MigrateToSpecifics(const char* old_columns, const char* specifics_column, - void (*handler_function)( + void (*handler_function) ( SQLStatement* old_value_query, int old_value_column, sync_pb::EntitySpecifics* mutable_new_value)); diff --git a/chrome/browser/sync/syncable/directory_backing_store_unittest.cc b/chrome/browser/sync/syncable/directory_backing_store_unittest.cc index bf5dfde..777a163 100644 --- a/chrome/browser/sync/syncable/directory_backing_store_unittest.cc +++ b/chrome/browser/sync/syncable/directory_backing_store_unittest.cc @@ -10,6 +10,7 @@ #include "app/sql/statement.h" #include "app/sql/transaction.h" #include "base/file_path.h" +#include "base/file_util.h" #include "base/scoped_ptr.h" #include "base/scoped_temp_dir.h" #include "base/stl_util-inl.h" @@ -870,4 +871,27 @@ TEST_F(DirectoryBackingStoreTest, ModelTypeIds) { } } +TEST_F(DirectoryBackingStoreTest, Corruption) { + { + scoped_ptr<DirectoryBackingStore> dbs( + new DirectoryBackingStore(GetUsername(), GetDatabasePath())); + EXPECT_TRUE(dbs->BeginLoad()); + } + std::string bad_data("BAD DATA"); + EXPECT_TRUE(file_util::WriteFile(GetDatabasePath(), bad_data.data(), + bad_data.size())); + { + scoped_ptr<DirectoryBackingStore> dbs( + new DirectoryBackingStore(GetUsername(), GetDatabasePath())); + + // In release mode, we expect the sync database to nuke itself and start + // over if it detects invalid/corrupted data. +#if defined(NDEBUG) + EXPECT_TRUE(dbs->BeginLoad()); +#else + EXPECT_DEATH(dbs->BeginLoad(), "sqlite error"); +#endif + } +} + } // namespace syncable |