Commit aacbc52f authored by tzik@chromium.org's avatar tzik@chromium.org

[SyncFS] Add MetadataDatabase::PopulateInitialData

* Add a method to populate database with initial data.
* Add a test for it.

BUG=240165

Review URL: https://chromiumcodereview.appspot.com/23582013

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@221671 0039d316-1c4b-4281-b951-d872f2087c98
parent 190dbb5c
...@@ -84,20 +84,10 @@ base::FilePath ReverseConcatPathComponents( ...@@ -84,20 +84,10 @@ base::FilePath ReverseConcatPathComponents(
return base::FilePath(result).NormalizePathSeparators(); return base::FilePath(result).NormalizePathSeparators();
} }
scoped_ptr<FileMetadata> CreateFileMetadataFromChangeResource( void PopulateFileDetailsByFileResource(
const google_apis::ChangeResource& change) { const google_apis::FileResource& file_resource,
scoped_ptr<FileMetadata> file(new FileMetadata); FileDetails* details) {
file->set_file_id(change.file_id()); details->clear_parent_folder_ids();
FileDetails* details = file->mutable_details();
details->set_change_id(change.change_id());
if (change.is_deleted()) {
details->set_deleted(true);
return file.Pass();
}
const google_apis::FileResource& file_resource = *change.file();
for (ScopedVector<google_apis::ParentReference>::const_iterator itr = for (ScopedVector<google_apis::ParentReference>::const_iterator itr =
file_resource.parents().begin(); file_resource.parents().begin();
itr != file_resource.parents().end(); itr != file_resource.parents().end();
...@@ -120,10 +110,78 @@ scoped_ptr<FileMetadata> CreateFileMetadataFromChangeResource( ...@@ -120,10 +110,78 @@ scoped_ptr<FileMetadata> CreateFileMetadataFromChangeResource(
details->set_modification_time( details->set_modification_time(
file_resource.modified_date().ToInternalValue()); file_resource.modified_date().ToInternalValue());
details->set_deleted(false); details->set_deleted(false);
}
scoped_ptr<FileMetadata> CreateFileMetadataFromChangeResource(
const google_apis::ChangeResource& change) {
scoped_ptr<FileMetadata> file(new FileMetadata);
file->set_file_id(change.file_id());
FileDetails* details = file->mutable_details();
details->set_change_id(change.change_id());
if (change.is_deleted()) {
details->set_deleted(true);
return file.Pass();
}
PopulateFileDetailsByFileResource(*change.file(), details);
return file.Pass(); return file.Pass();
} }
void CreateInitialSyncRootTracker(
int64 tracker_id,
const google_apis::FileResource& file_resource,
scoped_ptr<FileMetadata>* file_out,
scoped_ptr<FileTracker>* tracker_out) {
FileDetails details;
PopulateFileDetailsByFileResource(file_resource, &details);
scoped_ptr<FileMetadata> file(new FileMetadata);
file->set_file_id(file_resource.file_id());
*file->mutable_details() = details;
scoped_ptr<FileTracker> tracker(new FileTracker);
tracker->set_tracker_id(tracker_id);
tracker->set_file_id(file_resource.file_id());
tracker->set_parent_tracker_id(0);
tracker->set_tracker_kind(TRACKER_KIND_REGULAR);
tracker->set_dirty(false);
tracker->set_active(true);
tracker->set_needs_folder_listing(false);
*tracker->mutable_synced_details() = details;
*file_out = file.Pass();
*tracker_out = tracker.Pass();
}
void CreateInitialAppRootTracker(
int64 tracker_id,
const FileTracker& parent_tracker,
const google_apis::FileResource& file_resource,
scoped_ptr<FileMetadata>* file_out,
scoped_ptr<FileTracker>* tracker_out) {
FileDetails details;
PopulateFileDetailsByFileResource(file_resource, &details);
scoped_ptr<FileMetadata> file(new FileMetadata);
file->set_file_id(file_resource.file_id());
*file->mutable_details() = details;
scoped_ptr<FileTracker> tracker(new FileTracker);
tracker->set_tracker_id(tracker_id);
tracker->set_parent_tracker_id(parent_tracker.tracker_id());
tracker->set_file_id(file_resource.file_id());
tracker->set_tracker_kind(TRACKER_KIND_REGULAR);
tracker->set_dirty(false);
tracker->set_active(false);
tracker->set_needs_folder_listing(false);
*tracker->mutable_synced_details() = details;
*file_out = file.Pass();
*tracker_out = tracker.Pass();
}
void AdaptLevelDBStatusToSyncStatusCode(const SyncStatusCallback& callback, void AdaptLevelDBStatusToSyncStatusCode(const SyncStatusCallback& callback,
const leveldb::Status& status) { const leveldb::Status& status) {
callback.Run(LevelDBStatusToSyncStatusCode(status)); callback.Run(LevelDBStatusToSyncStatusCode(status));
...@@ -507,6 +565,78 @@ int64 MetadataDatabase::GetLargestChangeID() const { ...@@ -507,6 +565,78 @@ int64 MetadataDatabase::GetLargestChangeID() const {
return service_metadata_->largest_change_id(); return service_metadata_->largest_change_id();
} }
bool MetadataDatabase::HasSyncRoot() const {
return service_metadata_->has_sync_root_tracker_id() &&
!!service_metadata_->sync_root_tracker_id();
}
void MetadataDatabase::PopulateInitialData(
int64 largest_change_id,
const google_apis::FileResource& sync_root_folder,
const ScopedVector<google_apis::FileResource>& app_root_folders,
const SyncStatusCallback& callback) {
DCHECK(tracker_by_id_.empty());
DCHECK(file_by_id_.empty());
scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
service_metadata_->set_largest_change_id(largest_change_id);
FileTracker* sync_root_tracker = NULL;
int64 sync_root_tracker_id = 0;
{
scoped_ptr<FileMetadata> folder;
scoped_ptr<FileTracker> tracker;
CreateInitialSyncRootTracker(GetNextTrackerID(batch.get()),
sync_root_folder,
&folder,
&tracker);
std::string sync_root_folder_id = folder->file_id();
sync_root_tracker = tracker.get();
sync_root_tracker_id = tracker->tracker_id();
PutFileToBatch(*folder, batch.get());
PutTrackerToBatch(*tracker, batch.get());
service_metadata_->set_sync_root_tracker_id(tracker->tracker_id());
PutServiceMetadataToBatch(*service_metadata_, batch.get());
trackers_by_file_id_[folder->file_id()].Insert(tracker.get());
file_by_id_[sync_root_folder_id] = folder.release();
tracker_by_id_[sync_root_tracker_id] = tracker.release();
}
for (ScopedVector<google_apis::FileResource>::const_iterator itr =
app_root_folders.begin();
itr != app_root_folders.end();
++itr) {
const google_apis::FileResource& folder_resource = **itr;
scoped_ptr<FileMetadata> folder;
scoped_ptr<FileTracker> tracker;
CreateInitialAppRootTracker(GetNextTrackerID(batch.get()),
*sync_root_tracker,
folder_resource,
&folder,
&tracker);
std::string title = folder->details().title();
std::string folder_id = folder->file_id();
int64 tracker_id = tracker->tracker_id();
PutFileToBatch(*folder, batch.get());
PutTrackerToBatch(*tracker, batch.get());
trackers_by_file_id_[folder_id].Insert(tracker.get());
trackers_by_parent_and_title_[sync_root_tracker_id][title]
.Insert(tracker.get());
file_by_id_[folder_id] = folder.release();
tracker_by_id_[tracker_id] = tracker.release();
}
WriteToDatabase(batch.Pass(), callback);
}
void MetadataDatabase::RegisterApp(const std::string& app_id, void MetadataDatabase::RegisterApp(const std::string& app_id,
const std::string& folder_id, const std::string& folder_id,
const SyncStatusCallback& callback) { const SyncStatusCallback& callback) {
......
...@@ -124,6 +124,21 @@ class MetadataDatabase { ...@@ -124,6 +124,21 @@ class MetadataDatabase {
int64 GetLargestChangeID() const; int64 GetLargestChangeID() const;
bool HasSyncRoot() const;
// Populates empty database with initial data.
// Adds a file metadata and a file tracker for |sync_root_folder|, and adds
// file metadata and file trackers for each |app_root_folders|.
// Newly added tracker for |sync_root_folder| is active and non-dirty.
// Newly added trackers for |app_root_folders| are inactive and non-dirty.
// Trackers for |app_root_folders| are not yet registered as app-roots, but
// are ready to register.
void PopulateInitialData(
int64 largest_change_id,
const google_apis::FileResource& sync_root_folder,
const ScopedVector<google_apis::FileResource>& app_root_folders,
const SyncStatusCallback& callback);
// Registers existing folder as the app-root for |app_id|. The folder // Registers existing folder as the app-root for |app_id|. The folder
// must be an inactive folder that does not yet associated to any App. // must be an inactive folder that does not yet associated to any App.
// This method associates the folder with |app_id| and activates it. // This method associates the folder with |app_id| and activates it.
......
...@@ -391,16 +391,8 @@ class MetadataDatabaseTest : public testing::Test { ...@@ -391,16 +391,8 @@ class MetadataDatabaseTest : public testing::Test {
return folder; return folder;
} }
scoped_ptr<google_apis::ChangeResource> CreateChangeResourceFromMetadata( scoped_ptr<google_apis::FileResource> CreateFileResourceFromMetadata(
const FileMetadata& file) { const FileMetadata& file) {
scoped_ptr<google_apis::ChangeResource> change(
new google_apis::ChangeResource);
change->set_change_id(file.details().change_id());
change->set_file_id(file.file_id());
change->set_deleted(file.details().deleted());
if (change->is_deleted())
return change.Pass();
scoped_ptr<google_apis::FileResource> file_resource( scoped_ptr<google_apis::FileResource> file_resource(
new google_apis::FileResource); new google_apis::FileResource);
ScopedVector<google_apis::ParentReference> parents; ScopedVector<google_apis::ParentReference> parents;
...@@ -427,7 +419,20 @@ class MetadataDatabaseTest : public testing::Test { ...@@ -427,7 +419,20 @@ class MetadataDatabaseTest : public testing::Test {
file_resource->set_modified_date(base::Time::FromInternalValue( file_resource->set_modified_date(base::Time::FromInternalValue(
file.details().modification_time())); file.details().modification_time()));
change->set_file(file_resource.Pass()); return file_resource.Pass();
}
scoped_ptr<google_apis::ChangeResource> CreateChangeResourceFromMetadata(
const FileMetadata& file) {
scoped_ptr<google_apis::ChangeResource> change(
new google_apis::ChangeResource);
change->set_change_id(file.details().change_id());
change->set_file_id(file.file_id());
change->set_deleted(file.details().deleted());
if (change->is_deleted())
return change.Pass();
change->set_file(CreateFileResourceFromMetadata(file));
return change.Pass(); return change.Pass();
} }
...@@ -605,6 +610,24 @@ class MetadataDatabaseTest : public testing::Test { ...@@ -605,6 +610,24 @@ class MetadataDatabaseTest : public testing::Test {
return status; return status;
} }
SyncStatusCode PopulateInitialData(
int64 largest_change_id,
const google_apis::FileResource& sync_root_folder,
const ScopedVector<google_apis::FileResource>& app_root_folders) {
SyncStatusCode status = SYNC_STATUS_UNKNOWN;
metadata_database_->PopulateInitialData(
largest_change_id,
sync_root_folder,
app_root_folders,
base::Bind(&SyncStatusResultCallback, &status));
message_loop_.RunUntilIdle();
return status;
}
void ResetTrackerID(FileTracker* tracker) {
tracker->set_tracker_id(GetTrackerIDByFileID(tracker->file_id()));
}
private: private:
base::ScopedTempDir database_dir_; base::ScopedTempDir database_dir_;
base::MessageLoop message_loop_; base::MessageLoop message_loop_;
...@@ -802,8 +825,7 @@ TEST_F(MetadataDatabaseTest, UpdateByChangeListTest) { ...@@ -802,8 +825,7 @@ TEST_F(MetadataDatabaseTest, UpdateByChangeListTest) {
new_file.tracker.clear_synced_details(); new_file.tracker.clear_synced_details();
new_file.tracker.set_active(false); new_file.tracker.set_active(false);
new_file.tracker.set_dirty(true); new_file.tracker.set_dirty(true);
new_file.tracker.set_tracker_id( ResetTrackerID(&new_file.tracker);
GetTrackerIDByFileID(new_file.metadata.file_id()));
EXPECT_NE(0, new_file.tracker.tracker_id()); EXPECT_NE(0, new_file.tracker.tracker_id());
new_file.should_be_absent = false; new_file.should_be_absent = false;
...@@ -844,8 +866,7 @@ TEST_F(MetadataDatabaseTest, PopulateFolderTest_RegularFolder) { ...@@ -844,8 +866,7 @@ TEST_F(MetadataDatabaseTest, PopulateFolderTest_RegularFolder) {
folder_to_populate.tracker.set_dirty(false); folder_to_populate.tracker.set_dirty(false);
folder_to_populate.tracker.set_needs_folder_listing(false); folder_to_populate.tracker.set_needs_folder_listing(false);
new_file.tracker.set_tracker_id( ResetTrackerID(&new_file.tracker);
GetTrackerIDByFileID(new_file.metadata.file_id()));
new_file.tracker.set_dirty(true); new_file.tracker.set_dirty(true);
new_file.tracker.set_active(false); new_file.tracker.set_active(false);
new_file.tracker.clear_synced_details(); new_file.tracker.clear_synced_details();
...@@ -908,7 +929,7 @@ TEST_F(MetadataDatabaseTest, PopulateFolderTest_DisabledAppRoot) { ...@@ -908,7 +929,7 @@ TEST_F(MetadataDatabaseTest, PopulateFolderTest_DisabledAppRoot) {
disabled_app_children.push_back(file.metadata.file_id()); disabled_app_children.push_back(file.metadata.file_id());
EXPECT_EQ(SYNC_STATUS_OK, PopulateFolder( EXPECT_EQ(SYNC_STATUS_OK, PopulateFolder(
disabled_app_root.metadata.file_id(), disabled_app_children)); disabled_app_root.metadata.file_id(), disabled_app_children));
file.tracker.set_tracker_id(GetTrackerIDByFileID(file.metadata.file_id())); ResetTrackerID(&file.tracker);
file.tracker.clear_synced_details(); file.tracker.clear_synced_details();
file.tracker.set_dirty(true); file.tracker.set_dirty(true);
file.tracker.set_active(false); file.tracker.set_active(false);
...@@ -972,5 +993,37 @@ TEST_F(MetadataDatabaseTest, UpdateTrackerTest) { ...@@ -972,5 +993,37 @@ TEST_F(MetadataDatabaseTest, UpdateTrackerTest) {
VerifyReloadConsistency(); VerifyReloadConsistency();
} }
TEST_F(MetadataDatabaseTest, PopulateInitialDataTest) {
TrackedFile sync_root(CreateTrackedSyncRoot());
TrackedFile app_root(CreateTrackedFolder(sync_root, "app_root"));
app_root.tracker.set_active(false);
const TrackedFile* tracked_files[] = {
&sync_root, &app_root
};
int64 largest_change_id = 42;
scoped_ptr<google_apis::FileResource> sync_root_folder(
CreateFileResourceFromMetadata(sync_root.metadata));
scoped_ptr<google_apis::FileResource> app_root_folder(
CreateFileResourceFromMetadata(app_root.metadata));
ScopedVector<google_apis::FileResource> app_root_folders;
app_root_folders.push_back(app_root_folder.release());
EXPECT_EQ(SYNC_STATUS_OK, InitializeMetadataDatabase());
EXPECT_EQ(SYNC_STATUS_OK, PopulateInitialData(
largest_change_id,
*sync_root_folder,
app_root_folders));
ResetTrackerID(&sync_root.tracker);
ResetTrackerID(&app_root.tracker);
app_root.tracker.set_parent_tracker_id(sync_root.tracker.tracker_id());
VerifyTrackedFiles(tracked_files, arraysize(tracked_files));
VerifyReloadConsistency();
}
} // namespace drive_backend } // namespace drive_backend
} // namespace sync_file_system } // namespace sync_file_system
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment