diff options
author | hashimoto@chromium.org <hashimoto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-03 06:53:38 +0000 |
---|---|---|
committer | hashimoto@chromium.org <hashimoto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-02-03 06:53:38 +0000 |
commit | 99bd5430ee4598514a85fbdab5100c751bfacbff (patch) | |
tree | 0b1e716983e011ccbbbf9212d05711ce1fc97e6d | |
parent | 893642c381cebeb4439cfc49e24ed1ae4d7bf808 (diff) | |
download | chromium_src-99bd5430ee4598514a85fbdab5100c751bfacbff.zip chromium_src-99bd5430ee4598514a85fbdab5100c751bfacbff.tar.gz chromium_src-99bd5430ee4598514a85fbdab5100c751bfacbff.tar.bz2 |
drive: Update parent entry first when appropriate
EntryUpdatePerformer does nothing if the parent is a locally created entry waiting for update.
SyncClient adds update tasks for child entries.
Add ResourceMetadata::ReadDirectoryById
BUG=260540
TEST=unit_tests
R=kinaba@chromium.org
Review URL: https://codereview.chromium.org/151203004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@248441 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/chromeos/drive/resource_metadata.cc | 10 | ||||
-rw-r--r-- | chrome/browser/chromeos/drive/resource_metadata.h | 4 | ||||
-rw-r--r-- | chrome/browser/chromeos/drive/sync/entry_update_performer.cc | 9 | ||||
-rw-r--r-- | chrome/browser/chromeos/drive/sync_client.cc | 25 | ||||
-rw-r--r-- | chrome/browser/chromeos/drive/sync_client.h | 10 | ||||
-rw-r--r-- | chrome/browser/chromeos/drive/sync_client_unittest.cc | 39 |
6 files changed, 91 insertions, 6 deletions
diff --git a/chrome/browser/chromeos/drive/resource_metadata.cc b/chrome/browser/chromeos/drive/resource_metadata.cc index 2c873a4..6fca4ce1 100644 --- a/chrome/browser/chromeos/drive/resource_metadata.cc +++ b/chrome/browser/chromeos/drive/resource_metadata.cc @@ -312,9 +312,17 @@ FileError ResourceMetadata::ReadDirectoryByPath( FileError error = GetIdByPath(path, &id); if (error != FILE_ERROR_OK) return error; + return ReadDirectoryById(id, out_entries); +} + +FileError ResourceMetadata::ReadDirectoryById( + const std::string& id, + ResourceEntryVector* out_entries) { + DCHECK(blocking_task_runner_->RunsTasksOnCurrentThread()); + DCHECK(out_entries); ResourceEntry entry; - error = GetResourceEntryById(id, &entry); + FileError error = GetResourceEntryById(id, &entry); if (error != FILE_ERROR_OK) return error; diff --git a/chrome/browser/chromeos/drive/resource_metadata.h b/chrome/browser/chromeos/drive/resource_metadata.h index e669114..52b5d41 100644 --- a/chrome/browser/chromeos/drive/resource_metadata.h +++ b/chrome/browser/chromeos/drive/resource_metadata.h @@ -97,6 +97,10 @@ class ResourceMetadata { FileError ReadDirectoryByPath(const base::FilePath& file_path, ResourceEntryVector* out_entries); + // Finds and reads a directory by |id|. + FileError ReadDirectoryById(const std::string& id, + ResourceEntryVector* out_entries); + // Replaces an existing entry with the same local ID as |entry|. FileError RefreshEntry(const ResourceEntry& entry); diff --git a/chrome/browser/chromeos/drive/sync/entry_update_performer.cc b/chrome/browser/chromeos/drive/sync/entry_update_performer.cc index b9a50cd..ec73b32 100644 --- a/chrome/browser/chromeos/drive/sync/entry_update_performer.cc +++ b/chrome/browser/chromeos/drive/sync/entry_update_performer.cc @@ -237,6 +237,14 @@ void EntryUpdatePerformer::UpdateEntryAfterPrepare( return; } + // Parent was locally created and needs update. Just return for now. + // This entry should be updated again after the parent update completes. + if (local_state->parent_entry.resource_id().empty() && + local_state->parent_entry.metadata_edit_state() != ResourceEntry::CLEAN) { + callback.Run(FILE_ERROR_OK); + return; + } + base::Time last_modified = base::Time::FromInternalValue( local_state->entry.file_info().last_modified()); base::Time last_accessed = base::Time::FromInternalValue( @@ -290,6 +298,7 @@ void EntryUpdatePerformer::UpdateEntryAfterPrepare( return; } + // Create directory. if (local_state->entry.file_info().is_directory() && local_state->entry.resource_id().empty()) { // Lock the loader to avoid race conditions. diff --git a/chrome/browser/chromeos/drive/sync_client.cc b/chrome/browser/chromeos/drive/sync_client.cc index d4488a2..5ab920f 100644 --- a/chrome/browser/chromeos/drive/sync_client.cc +++ b/chrome/browser/chromeos/drive/sync_client.cc @@ -397,6 +397,17 @@ void SyncClient::OnUpdateComplete(const std::string& local_id, if (error == FILE_ERROR_OK) { DVLOG(1) << "Updated " << local_id; + + // Add update tasks for child entries which may be waiting for the parent to + // be updated. + ResourceEntryVector* entries = new ResourceEntryVector; + base::PostTaskAndReplyWithResult( + blocking_task_runner_.get(), + FROM_HERE, + base::Bind(&ResourceMetadata::ReadDirectoryById, + base::Unretained(metadata_), local_id, entries), + base::Bind(&SyncClient::AddChildUpdateTasks, + weak_ptr_factory_.GetWeakPtr(), base::Owned(entries))); } else { switch (error) { case FILE_ERROR_ABORT: @@ -424,5 +435,19 @@ void SyncClient::OnUpdateComplete(const std::string& local_id, } } +void SyncClient::AddChildUpdateTasks(const ResourceEntryVector* entries, + FileError error) { + if (error != FILE_ERROR_OK) + return; + + for (size_t i = 0; i < entries->size(); ++i) { + const ResourceEntry& entry = (*entries)[i]; + if (entry.metadata_edit_state() != ResourceEntry::CLEAN) { + AddUpdateTaskInternal(ClientContext(BACKGROUND), entry.local_id(), + base::TimeDelta::FromSeconds(0)); + } + } +} + } // namespace internal } // namespace drive diff --git a/chrome/browser/chromeos/drive/sync_client.h b/chrome/browser/chromeos/drive/sync_client.h index 500f21d..3e9c574 100644 --- a/chrome/browser/chromeos/drive/sync_client.h +++ b/chrome/browser/chromeos/drive/sync_client.h @@ -14,6 +14,7 @@ #include "base/memory/weak_ptr.h" #include "base/time/time.h" #include "chrome/browser/chromeos/drive/file_errors.h" +#include "chrome/browser/chromeos/drive/resource_metadata.h" namespace base { class SequencedTaskRunner; @@ -134,19 +135,18 @@ class SyncClient { bool OnTaskComplete(SyncType type, const std::string& local_id); // Called when the file for |local_id| is fetched. - // Calls DoSyncLoop() to go back to the sync loop. void OnFetchFileComplete(const std::string& local_id, FileError error, const base::FilePath& local_path, scoped_ptr<ResourceEntry> entry); - // Called when the file for |local_id| is uploaded. - // Calls DoSyncLoop() to go back to the sync loop. - void OnUploadFileComplete(const std::string& local_id, FileError error); - // Called when the entry is updated. void OnUpdateComplete(const std::string& local_id, FileError error); + // Adds update tasks for |entries|. + void AddChildUpdateTasks(const ResourceEntryVector* entries, + FileError error); + scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; file_system::OperationObserver* operation_observer_; ResourceMetadata* metadata_; diff --git a/chrome/browser/chromeos/drive/sync_client_unittest.cc b/chrome/browser/chromeos/drive/sync_client_unittest.cc index fcfbfe8..e9e55c6 100644 --- a/chrome/browser/chromeos/drive/sync_client_unittest.cc +++ b/chrome/browser/chromeos/drive/sync_client_unittest.cc @@ -432,5 +432,44 @@ TEST_F(SyncClientTest, ScheduleRerun) { EXPECT_EQ(2, drive_service_->download_file_count()); } +TEST_F(SyncClientTest, Dependencies) { + // Create directories locally. + const base::FilePath kPath1(FILE_PATH_LITERAL("drive/root/dir1")); + const base::FilePath kPath2 = kPath1.AppendASCII("dir2"); + + ResourceEntry parent; + EXPECT_EQ(FILE_ERROR_OK, + metadata_->GetResourceEntryByPath(kPath1.DirName(), &parent)); + + ResourceEntry entry1; + entry1.set_parent_local_id(parent.local_id()); + entry1.set_title(kPath1.BaseName().AsUTF8Unsafe()); + entry1.mutable_file_info()->set_is_directory(true); + entry1.set_metadata_edit_state(ResourceEntry::DIRTY); + std::string local_id1; + EXPECT_EQ(FILE_ERROR_OK, metadata_->AddEntry(entry1, &local_id1)); + + ResourceEntry entry2; + entry2.set_parent_local_id(local_id1); + entry2.set_title(kPath2.BaseName().AsUTF8Unsafe()); + entry2.mutable_file_info()->set_is_directory(true); + entry2.set_metadata_edit_state(ResourceEntry::DIRTY); + std::string local_id2; + EXPECT_EQ(FILE_ERROR_OK, metadata_->AddEntry(entry2, &local_id2)); + + // Start syncing the child first. + sync_client_->AddUpdateTask(ClientContext(USER_INITIATED), local_id2); + base::RunLoop().RunUntilIdle(); + // Start syncing the parent later. + sync_client_->AddUpdateTask(ClientContext(USER_INITIATED), local_id1); + base::RunLoop().RunUntilIdle(); + + // Both entries are synced. + EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryById(local_id1, &entry1)); + EXPECT_EQ(ResourceEntry::CLEAN, entry1.metadata_edit_state()); + EXPECT_EQ(FILE_ERROR_OK, metadata_->GetResourceEntryById(local_id2, &entry2)); + EXPECT_EQ(ResourceEntry::CLEAN, entry2.metadata_edit_state()); +} + } // namespace internal } // namespace drive |