summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhashimoto@chromium.org <hashimoto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-03 06:53:38 +0000
committerhashimoto@chromium.org <hashimoto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-02-03 06:53:38 +0000
commit99bd5430ee4598514a85fbdab5100c751bfacbff (patch)
tree0b1e716983e011ccbbbf9212d05711ce1fc97e6d
parent893642c381cebeb4439cfc49e24ed1ae4d7bf808 (diff)
downloadchromium_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.cc10
-rw-r--r--chrome/browser/chromeos/drive/resource_metadata.h4
-rw-r--r--chrome/browser/chromeos/drive/sync/entry_update_performer.cc9
-rw-r--r--chrome/browser/chromeos/drive/sync_client.cc25
-rw-r--r--chrome/browser/chromeos/drive/sync_client.h10
-rw-r--r--chrome/browser/chromeos/drive/sync_client_unittest.cc39
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