diff options
5 files changed, 52 insertions, 12 deletions
diff --git a/chrome/browser/sync_file_system/drive_backend/drive_backend_util.cc b/chrome/browser/sync_file_system/drive_backend/drive_backend_util.cc index 031e1d7..d743980 100644 --- a/chrome/browser/sync_file_system/drive_backend/drive_backend_util.cc +++ b/chrome/browser/sync_file_system/drive_backend/drive_backend_util.cc @@ -169,12 +169,18 @@ scoped_ptr<ServiceMetadata> InitializeServiceMetadata(LevelDBWrapper* db) { base::ThreadRestrictions::AssertIOAllowed(); DCHECK(db); + scoped_ptr<ServiceMetadata> service_metadata; + std::string value; leveldb::Status status = db->Get(kServiceMetadataKey, &value); - - scoped_ptr<ServiceMetadata> service_metadata(new ServiceMetadata); - if (!status.ok() || !service_metadata->ParseFromString(value)) + if (status.ok()) { + service_metadata.reset(new ServiceMetadata); + if (!service_metadata->ParseFromString(value)) + service_metadata.reset(); + } else if (status.IsNotFound()) { + service_metadata.reset(new ServiceMetadata); service_metadata->set_next_tracker_id(1); + } return service_metadata.Pass(); } diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database.cc b/chrome/browser/sync_file_system/drive_backend/metadata_database.cc index 5456f52..73aa434 100644 --- a/chrome/browser/sync_file_system/drive_backend/metadata_database.cc +++ b/chrome/browser/sync_file_system/drive_backend/metadata_database.cc @@ -1424,11 +1424,25 @@ void MetadataDatabase::CreateOnWorkerTaskRunner( new MetadataDatabase(create_param->worker_task_runner, create_param->database_path, create_param->env_override)); + SyncStatusCode status = metadata_database->Initialize(); + if (status == SYNC_DATABASE_ERROR_FAILED) { + // Delete the previous instance to avoid creating a LevelDB instance for + // the same path. + metadata_database.reset(); + + metadata_database.reset( + new MetadataDatabase(create_param->worker_task_runner, + create_param->database_path, + create_param->env_override)); + status = metadata_database->Initialize(); + } + if (status != SYNC_STATUS_OK) metadata_database.reset(); - metadata_database->DetachFromSequence(); + if (metadata_database) + metadata_database->DetachFromSequence(); create_param->worker_task_runner->PostTask( FROM_HERE, base::Bind( @@ -1460,6 +1474,16 @@ SyncStatusCode MetadataDatabase::Initialize() { } else { index_ = MetadataDatabaseIndex::Create(db_.get()); } + if (!index_) { + // Delete all entries in |db_| to reset it. + // TODO(peria): Make LevelDBWrapper::DestroyDB() to avoid a full scan. + scoped_ptr<LevelDBWrapper::Iterator> itr = db_->NewIterator(); + for (itr->SeekToFirst(); itr->Valid();) + itr->Delete(); + db_->Commit(); + + return SYNC_DATABASE_ERROR_FAILED; + } status = LevelDBStatusToSyncStatusCode(db_->Commit()); if (status != SYNC_STATUS_OK) diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database_index.cc b/chrome/browser/sync_file_system/drive_backend/metadata_database_index.cc index 4e0c10b..90fb183 100644 --- a/chrome/browser/sync_file_system/drive_backend/metadata_database_index.cc +++ b/chrome/browser/sync_file_system/drive_backend/metadata_database_index.cc @@ -204,8 +204,10 @@ MetadataDatabaseIndex::Create(LevelDBWrapper* db) { DCHECK(db); scoped_ptr<ServiceMetadata> service_metadata = InitializeServiceMetadata(db); - DatabaseContents contents; + if (!service_metadata) + return scoped_ptr<MetadataDatabaseIndex>(); + DatabaseContents contents; PutVersionToDB(kCurrentDatabaseVersion, db); ReadDatabaseContents(db, &contents); RemoveUnreachableItems(&contents, diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database_index_on_disk.cc b/chrome/browser/sync_file_system/drive_backend/metadata_database_index_on_disk.cc index 1199a13..51899b8 100644 --- a/chrome/browser/sync_file_system/drive_backend/metadata_database_index_on_disk.cc +++ b/chrome/browser/sync_file_system/drive_backend/metadata_database_index_on_disk.cc @@ -144,7 +144,7 @@ std::string GenerateDemotedDirtyIDKey(int64 tracker_id) { return kDemotedDirtyIDKeyPrefix + base::Int64ToString(tracker_id); } -void RemoveUnreachableItems(LevelDBWrapper* db) { +void RemoveUnreachableItems(LevelDBWrapper* db, int64 sync_root_tracker_id) { DCHECK(db); typedef std::map<int64, std::set<int64> > ChildTrackersByParent; @@ -181,9 +181,6 @@ void RemoveUnreachableItems(LevelDBWrapper* db) { // Traverse tracker tree from sync-root. std::set<int64> visited_trackers; { - scoped_ptr<ServiceMetadata> service_metadata = - InitializeServiceMetadata(db); - int64 sync_root_tracker_id = service_metadata->sync_root_tracker_id(); std::vector<int64> pending; if (sync_root_tracker_id != kInvalidTrackerID) pending.push_back(sync_root_tracker_id); @@ -255,10 +252,12 @@ scoped_ptr<MetadataDatabaseIndexOnDisk> MetadataDatabaseIndexOnDisk::Create(LevelDBWrapper* db) { DCHECK(db); + scoped_ptr<ServiceMetadata> service_metadata = InitializeServiceMetadata(db); + if (!service_metadata) + return scoped_ptr<MetadataDatabaseIndexOnDisk>(); + PutVersionToDB(kDatabaseOnDiskVersion, db); - // TODO(peria): It is not good to call RemoveUnreachableItems on every - // creation. - RemoveUnreachableItems(db); + RemoveUnreachableItems(db, service_metadata->sync_root_tracker_id()); scoped_ptr<MetadataDatabaseIndexOnDisk> index(new MetadataDatabaseIndexOnDisk(db)); diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database_unittest.cc b/chrome/browser/sync_file_system/drive_backend/metadata_database_unittest.cc index 733797a..370f93d 100644 --- a/chrome/browser/sync_file_system/drive_backend/metadata_database_unittest.cc +++ b/chrome/browser/sync_file_system/drive_backend/metadata_database_unittest.cc @@ -641,6 +641,15 @@ TEST_F(MetadataDatabaseTest, InitializationTest_Empty) { EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase()); DropDatabase(); EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase()); + + DropDatabase(); + + scoped_ptr<LevelDBWrapper> db = InitializeLevelDB(); + db->Put(kServiceMetadataKey, "Unparsable string"); + EXPECT_TRUE(db->Commit().ok()); + db.reset(); + + EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase()); } TEST_F(MetadataDatabaseTest, InitializationTest_SimpleTree) { |