diff options
author | tzik <tzik@chromium.org> | 2014-09-23 23:37:56 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-09-24 06:38:11 +0000 |
commit | 638d2c191d132640597d03926d6a7735f3f85a6f (patch) | |
tree | 6a1644805dc8270b590c43954bc90827acef9690 | |
parent | b171b53a96f5926e2462985f05450ca9054b7ac3 (diff) | |
download | chromium_src-638d2c191d132640597d03926d6a7735f3f85a6f.zip chromium_src-638d2c191d132640597d03926d6a7735f3f85a6f.tar.gz chromium_src-638d2c191d132640597d03926d6a7735f3f85a6f.tar.bz2 |
[SyncFS] Run RemoteToLocalSyncer as a background task
BUG=344769
Review URL: https://codereview.chromium.org/554213002
Cr-Commit-Position: refs/heads/master@{#296356}
3 files changed, 145 insertions, 35 deletions
diff --git a/chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer.cc b/chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer.cc index 0cb3783..e2ed201 100644 --- a/chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer.cc +++ b/chrome/browser/sync_file_system/drive_backend/local_to_remote_syncer.cc @@ -290,7 +290,7 @@ void LocalToRemoteSyncer::ContinueAsBackgroundTask( // and may delete FileTracker. So, ensure |change_id| is not changed and // check if FileTracker still exists. // - For UninstallAppTask, it may also delete FileMetadata and FileTracker. - // And also, check if FileTracker still exists. + // Check if FileTracker still exists. // - Others, SyncEngineInitializer and RegisterAppTask doesn't affect to // LocalToRemoteSyncer. if (remote_file_tracker_) { @@ -663,8 +663,7 @@ void LocalToRemoteSyncer::DidUploadNewFile( SyncCompleted(token.Pass(), status); } -void LocalToRemoteSyncer::CreateRemoteFolder( - scoped_ptr<SyncTaskToken> token) { +void LocalToRemoteSyncer::CreateRemoteFolder(scoped_ptr<SyncTaskToken> token) { DCHECK(remote_parent_folder_tracker_); base::FilePath title = storage::VirtualPath::BaseName(target_path_); diff --git a/chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.cc b/chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.cc index 003622c..dde9b44 100644 --- a/chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.cc +++ b/chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.cc @@ -106,15 +106,6 @@ RemoteToLocalSyncer::~RemoteToLocalSyncer() { void RemoteToLocalSyncer::RunPreflight(scoped_ptr<SyncTaskToken> token) { token->InitializeTaskLog("Remote -> Local"); - scoped_ptr<TaskBlocker> task_blocker(new TaskBlocker); - task_blocker->exclusive = true; - SyncTaskManager::UpdateTaskBlocker( - token.Pass(), task_blocker.Pass(), - base::Bind(&RemoteToLocalSyncer::RunExclusive, - weak_ptr_factory_.GetWeakPtr())); -} - -void RemoteToLocalSyncer::RunExclusive(scoped_ptr<SyncTaskToken> token) { if (!drive_service() || !metadata_database() || !remote_change_processor()) { token->RecordLog("Context not ready."); SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED); @@ -146,7 +137,11 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) { NOTREACHED(); } token->RecordLog("Missing remote metadata case."); - HandleMissingRemoteMetadata(token.Pass()); + + MoveToBackground( + token.Pass(), + base::Bind(&RemoteToLocalSyncer::HandleMissingRemoteMetadata, + weak_ptr_factory_.GetWeakPtr())); return; } @@ -183,7 +178,8 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) { synced_details.title() != remote_details.title() || remote_details.parent_folder_ids_size()) { token->RecordLog("Sync-root deletion."); - HandleSyncRootDeletion(token.Pass()); + sync_root_deletion_ = true; + SyncCompleted(token.Pass(), SYNC_STATUS_OK); return; } token->RecordLog("Trivial sync-root change."); @@ -194,10 +190,20 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) { DCHECK_NE(dirty_tracker_->tracker_id(), metadata_database()->GetSyncRootTrackerID()); + if (!BuildFileSystemURL(metadata_database(), *dirty_tracker_, &url_)) { + NOTREACHED(); + SyncCompleted(token.Pass(), SYNC_STATUS_FAILED); + return; + } + + DCHECK(url_.is_valid()); + if (remote_details.missing()) { if (!synced_details.missing()) { token->RecordLog("Remote file deletion."); - HandleDeletion(token.Pass()); + MoveToBackground(token.Pass(), + base::Bind(&RemoteToLocalSyncer::HandleDeletion, + weak_ptr_factory_.GetWeakPtr())); return; } @@ -238,9 +244,10 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) { if (synced_details.title() != remote_details.title()) { // Handle rename as deletion + addition. token->RecordLog("Detected file rename."); - Prepare(base::Bind(&RemoteToLocalSyncer::DidPrepareForDeletion, - weak_ptr_factory_.GetWeakPtr(), - base::Passed(&token))); + + MoveToBackground(token.Pass(), + base::Bind(&RemoteToLocalSyncer::HandleFileMove, + weak_ptr_factory_.GetWeakPtr())); return; } DCHECK_EQ(synced_details.title(), remote_details.title()); @@ -258,28 +265,35 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) { if (!HasFolderAsParent(remote_details, parent_tracker.file_id())) { // Handle reorganize as deletion + addition. token->RecordLog("Detected file reorganize."); - Prepare(base::Bind(&RemoteToLocalSyncer::DidPrepareForDeletion, - weak_ptr_factory_.GetWeakPtr(), - base::Passed(&token))); + + MoveToBackground(token.Pass(), + base::Bind(&RemoteToLocalSyncer::HandleFileMove, + weak_ptr_factory_.GetWeakPtr())); return; } if (synced_details.file_kind() == FILE_KIND_FILE) { if (synced_details.md5() != remote_details.md5()) { token->RecordLog("Detected file content update."); - HandleContentUpdate(token.Pass()); + MoveToBackground(token.Pass(), + base::Bind(&RemoteToLocalSyncer::HandleContentUpdate, + weak_ptr_factory_.GetWeakPtr())); return; } } else { DCHECK_EQ(FILE_KIND_FOLDER, synced_details.file_kind()); if (synced_details.missing()) { token->RecordLog("Detected folder update."); - HandleFolderUpdate(token.Pass()); + MoveToBackground(token.Pass(), + base::Bind(&RemoteToLocalSyncer::HandleFolderUpdate, + weak_ptr_factory_.GetWeakPtr())); return; } if (dirty_tracker_->needs_folder_listing()) { token->RecordLog("Needs listing folder."); - ListFolderContent(token.Pass()); + MoveToBackground(token.Pass(), + base::Bind(&RemoteToLocalSyncer::ListFolderContent, + weak_ptr_factory_.GetWeakPtr())); return; } SyncCompleted(token.Pass(), SYNC_STATUS_OK); @@ -290,6 +304,89 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) { SyncCompleted(token.Pass(), SYNC_STATUS_OK); } +void RemoteToLocalSyncer::MoveToBackground(scoped_ptr<SyncTaskToken> token, + const Continuation& continuation) { + DCHECK(dirty_tracker_); + + scoped_ptr<TaskBlocker> blocker(new TaskBlocker); + blocker->app_id = dirty_tracker_->app_id(); + if (url_.is_valid()) + blocker->paths.push_back(url_.path()); + blocker->file_ids.push_back(dirty_tracker_->file_id()); + blocker->tracker_ids.push_back(dirty_tracker_->tracker_id()); + + SyncTaskManager::UpdateTaskBlocker( + token.Pass(), blocker.Pass(), + base::Bind(&RemoteToLocalSyncer::ContinueAsBackgroundTask, + weak_ptr_factory_.GetWeakPtr(), continuation)); +} + +void RemoteToLocalSyncer::ContinueAsBackgroundTask( + const Continuation& continuation, + scoped_ptr<SyncTaskToken> token) { + DCHECK(dirty_tracker_); + + // The SyncTask runs as a background task beyond this point. + // Not that any task can run between MoveToBackground() and + // ContinueAsBackgroundTask(), so we need to make sure other tasks didn't + // affect to the current RemoteToLocalSyncer task. + // + // - For LocalToRemoteSyncer, it may update or delete any of FileTracker and + // FileMetadata. When it updates FileMetadata or FileDetails in FileTracker, + // it also updates |change_id|. So, ensure the target FileTracker and + // FileMetadata exist and their |change_id|s are not updated. + // - For ListChangesTask, it may update FileMetadata together with |change_id| + // and may delete FileTracker. + // - For UninstallAppTask, it may delete FileMetadata and FileTracker. + // Check if FileTracker still exists. + // - For other RemoteToLocalSyncer, it may delete the FileTracker of parent. + // Note that since RemoteToLocalSyncer demotes the target FileTracker first, + // any other RemoteToLocalSyncer does not run for current |dirty_tracker_|. + // - Others, SyncEngineInitializer and RegisterAppTask doesn't affect to + + FileTracker latest_dirty_tracker; + if (!metadata_database()->FindTrackerByTrackerID( + dirty_tracker_->tracker_id(), &latest_dirty_tracker) || + dirty_tracker_->active() != latest_dirty_tracker.active() || + !latest_dirty_tracker.dirty()) { + SyncCompleted(token.Pass(), SYNC_STATUS_RETRY); + return; + } + + int64 current_change_id = kint64min; + int64 latest_change_id = kint64min; + if (dirty_tracker_->has_synced_details()) + current_change_id = dirty_tracker_->synced_details().change_id(); + if (latest_dirty_tracker.has_synced_details()) + latest_change_id = latest_dirty_tracker.synced_details().change_id(); + if (current_change_id != latest_change_id) { + SyncCompleted(token.Pass(), SYNC_STATUS_RETRY); + return; + } + + FileMetadata latest_file_metadata; + if (metadata_database()->FindFileByFileID(dirty_tracker_->file_id(), + &latest_file_metadata)) { + if (!remote_metadata_) { + SyncCompleted(token.Pass(), SYNC_STATUS_RETRY); + return; + } + + int64 change_id = remote_metadata_->details().change_id(); + int64 latest_change_id = latest_file_metadata.details().change_id(); + if (change_id != latest_change_id) { + SyncCompleted(token.Pass(), SYNC_STATUS_RETRY); + return; + } + } else { + if (remote_metadata_) { + SyncCompleted(token.Pass(), SYNC_STATUS_RETRY); + return; + } + } + continuation.Run(token.Pass()); +} + void RemoteToLocalSyncer::HandleMissingRemoteMetadata( scoped_ptr<SyncTaskToken> token) { DCHECK(dirty_tracker_); @@ -444,12 +541,6 @@ void RemoteToLocalSyncer::DidPrepareForFolderUpdate( CreateFolder(token.Pass()); } -void RemoteToLocalSyncer::HandleSyncRootDeletion( - scoped_ptr<SyncTaskToken> token) { - sync_root_deletion_ = true; - SyncCompleted(token.Pass(), SYNC_STATUS_OK); -} - void RemoteToLocalSyncer::HandleDeletion( scoped_ptr<SyncTaskToken> token) { DCHECK(dirty_tracker_); @@ -467,6 +558,21 @@ void RemoteToLocalSyncer::HandleDeletion( base::Passed(&token))); } +void RemoteToLocalSyncer::HandleFileMove(scoped_ptr<SyncTaskToken> token) { + DCHECK(dirty_tracker_); + DCHECK(dirty_tracker_->active()); + DCHECK(!HasDisabledAppRoot(metadata_database(), *dirty_tracker_)); + DCHECK(dirty_tracker_->has_synced_details()); + + DCHECK(remote_metadata_); + DCHECK(remote_metadata_->has_details()); + DCHECK(!remote_metadata_->details().missing()); + + Prepare(base::Bind(&RemoteToLocalSyncer::DidPrepareForDeletion, + weak_ptr_factory_.GetWeakPtr(), + base::Passed(&token))); +} + void RemoteToLocalSyncer::DidPrepareForDeletion( scoped_ptr<SyncTaskToken> token, SyncStatusCode status) { @@ -639,9 +745,6 @@ void RemoteToLocalSyncer::FinalizeSync(scoped_ptr<SyncTaskToken> token, } void RemoteToLocalSyncer::Prepare(const SyncStatusCallback& callback) { - bool should_success = BuildFileSystemURL( - metadata_database(), *dirty_tracker_, &url_); - DCHECK(should_success); DCHECK(url_.is_valid()); remote_change_processor()->PrepareForProcessRemoteChange( url_, diff --git a/chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.h b/chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.h index 9108a53..2262e52 100644 --- a/chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.h +++ b/chrome/browser/sync_file_system/drive_backend/remote_to_local_syncer.h @@ -12,6 +12,7 @@ #include "base/memory/weak_ptr.h" #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h" #include "chrome/browser/sync_file_system/drive_backend/sync_task.h" +#include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h" #include "chrome/browser/sync_file_system/remote_change_processor.h" #include "chrome/browser/sync_file_system/sync_action.h" #include "chrome/browser/sync_file_system/sync_callbacks.h" @@ -41,6 +42,8 @@ class SyncEngineContext; class RemoteToLocalSyncer : public SyncTask { public: + typedef SyncTaskManager::Continuation Continuation; + // Conflicting trackers will have low priority for RemoteToLocalSyncer so that // it should be resolved by LocatToRemoteSyncer. explicit RemoteToLocalSyncer(SyncEngineContext* sync_context); @@ -102,6 +105,11 @@ class RemoteToLocalSyncer : public SyncTask { // - Dispatch to HandleOfflineSolvable() void ResolveRemoteChange(scoped_ptr<SyncTaskToken> token); + void MoveToBackground(scoped_ptr<SyncTaskToken> token, + const Continuation& continuation); + void ContinueAsBackgroundTask(const Continuation& continuation, + scoped_ptr<SyncTaskToken> token); + // Handles missing remote metadata case. // Fetches remote metadata and updates MetadataDatabase by that. The sync // operation itself will be deferred to the next sync round. @@ -132,8 +140,6 @@ class RemoteToLocalSyncer : public SyncTask { void DidPrepareForFolderUpdate(scoped_ptr<SyncTaskToken> token, SyncStatusCode status); - void HandleSyncRootDeletion(scoped_ptr<SyncTaskToken> token); - // Handles deleted remote file. Needs Prepare() call. // If the deleted tracker is the sync-root: // - TODO(tzik): Needs special handling. @@ -150,6 +156,8 @@ class RemoteToLocalSyncer : public SyncTask { void DidPrepareForDeletion(scoped_ptr<SyncTaskToken> token, SyncStatusCode status); + void HandleFileMove(scoped_ptr<SyncTaskToken> token); + // Handles new file. Needs Prepare() call. void HandleContentUpdate(scoped_ptr<SyncTaskToken> token); |