Commit 638d2c19 authored by tzik's avatar tzik Committed by Commit bot

[SyncFS] Run RemoteToLocalSyncer as a background task

BUG=344769

Review URL: https://codereview.chromium.org/554213002

Cr-Commit-Position: refs/heads/master@{#296356}
parent b171b53a
...@@ -290,7 +290,7 @@ void LocalToRemoteSyncer::ContinueAsBackgroundTask( ...@@ -290,7 +290,7 @@ void LocalToRemoteSyncer::ContinueAsBackgroundTask(
// and may delete FileTracker. So, ensure |change_id| is not changed and // and may delete FileTracker. So, ensure |change_id| is not changed and
// check if FileTracker still exists. // check if FileTracker still exists.
// - For UninstallAppTask, it may also delete FileMetadata and FileTracker. // - 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 // - Others, SyncEngineInitializer and RegisterAppTask doesn't affect to
// LocalToRemoteSyncer. // LocalToRemoteSyncer.
if (remote_file_tracker_) { if (remote_file_tracker_) {
...@@ -663,8 +663,7 @@ void LocalToRemoteSyncer::DidUploadNewFile( ...@@ -663,8 +663,7 @@ void LocalToRemoteSyncer::DidUploadNewFile(
SyncCompleted(token.Pass(), status); SyncCompleted(token.Pass(), status);
} }
void LocalToRemoteSyncer::CreateRemoteFolder( void LocalToRemoteSyncer::CreateRemoteFolder(scoped_ptr<SyncTaskToken> token) {
scoped_ptr<SyncTaskToken> token) {
DCHECK(remote_parent_folder_tracker_); DCHECK(remote_parent_folder_tracker_);
base::FilePath title = storage::VirtualPath::BaseName(target_path_); base::FilePath title = storage::VirtualPath::BaseName(target_path_);
......
...@@ -106,15 +106,6 @@ RemoteToLocalSyncer::~RemoteToLocalSyncer() { ...@@ -106,15 +106,6 @@ RemoteToLocalSyncer::~RemoteToLocalSyncer() {
void RemoteToLocalSyncer::RunPreflight(scoped_ptr<SyncTaskToken> token) { void RemoteToLocalSyncer::RunPreflight(scoped_ptr<SyncTaskToken> token) {
token->InitializeTaskLog("Remote -> Local"); 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()) { if (!drive_service() || !metadata_database() || !remote_change_processor()) {
token->RecordLog("Context not ready."); token->RecordLog("Context not ready.");
SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED); SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED);
...@@ -146,7 +137,11 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) { ...@@ -146,7 +137,11 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) {
NOTREACHED(); NOTREACHED();
} }
token->RecordLog("Missing remote metadata case."); token->RecordLog("Missing remote metadata case.");
HandleMissingRemoteMetadata(token.Pass());
MoveToBackground(
token.Pass(),
base::Bind(&RemoteToLocalSyncer::HandleMissingRemoteMetadata,
weak_ptr_factory_.GetWeakPtr()));
return; return;
} }
...@@ -183,7 +178,8 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) { ...@@ -183,7 +178,8 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) {
synced_details.title() != remote_details.title() || synced_details.title() != remote_details.title() ||
remote_details.parent_folder_ids_size()) { remote_details.parent_folder_ids_size()) {
token->RecordLog("Sync-root deletion."); token->RecordLog("Sync-root deletion.");
HandleSyncRootDeletion(token.Pass()); sync_root_deletion_ = true;
SyncCompleted(token.Pass(), SYNC_STATUS_OK);
return; return;
} }
token->RecordLog("Trivial sync-root change."); token->RecordLog("Trivial sync-root change.");
...@@ -194,10 +190,20 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) { ...@@ -194,10 +190,20 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) {
DCHECK_NE(dirty_tracker_->tracker_id(), DCHECK_NE(dirty_tracker_->tracker_id(),
metadata_database()->GetSyncRootTrackerID()); 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 (remote_details.missing()) {
if (!synced_details.missing()) { if (!synced_details.missing()) {
token->RecordLog("Remote file deletion."); token->RecordLog("Remote file deletion.");
HandleDeletion(token.Pass()); MoveToBackground(token.Pass(),
base::Bind(&RemoteToLocalSyncer::HandleDeletion,
weak_ptr_factory_.GetWeakPtr()));
return; return;
} }
...@@ -238,9 +244,10 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) { ...@@ -238,9 +244,10 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) {
if (synced_details.title() != remote_details.title()) { if (synced_details.title() != remote_details.title()) {
// Handle rename as deletion + addition. // Handle rename as deletion + addition.
token->RecordLog("Detected file rename."); token->RecordLog("Detected file rename.");
Prepare(base::Bind(&RemoteToLocalSyncer::DidPrepareForDeletion,
weak_ptr_factory_.GetWeakPtr(), MoveToBackground(token.Pass(),
base::Passed(&token))); base::Bind(&RemoteToLocalSyncer::HandleFileMove,
weak_ptr_factory_.GetWeakPtr()));
return; return;
} }
DCHECK_EQ(synced_details.title(), remote_details.title()); DCHECK_EQ(synced_details.title(), remote_details.title());
...@@ -258,28 +265,35 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) { ...@@ -258,28 +265,35 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) {
if (!HasFolderAsParent(remote_details, parent_tracker.file_id())) { if (!HasFolderAsParent(remote_details, parent_tracker.file_id())) {
// Handle reorganize as deletion + addition. // Handle reorganize as deletion + addition.
token->RecordLog("Detected file reorganize."); token->RecordLog("Detected file reorganize.");
Prepare(base::Bind(&RemoteToLocalSyncer::DidPrepareForDeletion,
weak_ptr_factory_.GetWeakPtr(), MoveToBackground(token.Pass(),
base::Passed(&token))); base::Bind(&RemoteToLocalSyncer::HandleFileMove,
weak_ptr_factory_.GetWeakPtr()));
return; return;
} }
if (synced_details.file_kind() == FILE_KIND_FILE) { if (synced_details.file_kind() == FILE_KIND_FILE) {
if (synced_details.md5() != remote_details.md5()) { if (synced_details.md5() != remote_details.md5()) {
token->RecordLog("Detected file content update."); token->RecordLog("Detected file content update.");
HandleContentUpdate(token.Pass()); MoveToBackground(token.Pass(),
base::Bind(&RemoteToLocalSyncer::HandleContentUpdate,
weak_ptr_factory_.GetWeakPtr()));
return; return;
} }
} else { } else {
DCHECK_EQ(FILE_KIND_FOLDER, synced_details.file_kind()); DCHECK_EQ(FILE_KIND_FOLDER, synced_details.file_kind());
if (synced_details.missing()) { if (synced_details.missing()) {
token->RecordLog("Detected folder update."); token->RecordLog("Detected folder update.");
HandleFolderUpdate(token.Pass()); MoveToBackground(token.Pass(),
base::Bind(&RemoteToLocalSyncer::HandleFolderUpdate,
weak_ptr_factory_.GetWeakPtr()));
return; return;
} }
if (dirty_tracker_->needs_folder_listing()) { if (dirty_tracker_->needs_folder_listing()) {
token->RecordLog("Needs listing folder."); token->RecordLog("Needs listing folder.");
ListFolderContent(token.Pass()); MoveToBackground(token.Pass(),
base::Bind(&RemoteToLocalSyncer::ListFolderContent,
weak_ptr_factory_.GetWeakPtr()));
return; return;
} }
SyncCompleted(token.Pass(), SYNC_STATUS_OK); SyncCompleted(token.Pass(), SYNC_STATUS_OK);
...@@ -290,6 +304,89 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) { ...@@ -290,6 +304,89 @@ void RemoteToLocalSyncer::ResolveRemoteChange(scoped_ptr<SyncTaskToken> token) {
SyncCompleted(token.Pass(), SYNC_STATUS_OK); 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( void RemoteToLocalSyncer::HandleMissingRemoteMetadata(
scoped_ptr<SyncTaskToken> token) { scoped_ptr<SyncTaskToken> token) {
DCHECK(dirty_tracker_); DCHECK(dirty_tracker_);
...@@ -444,12 +541,6 @@ void RemoteToLocalSyncer::DidPrepareForFolderUpdate( ...@@ -444,12 +541,6 @@ void RemoteToLocalSyncer::DidPrepareForFolderUpdate(
CreateFolder(token.Pass()); CreateFolder(token.Pass());
} }
void RemoteToLocalSyncer::HandleSyncRootDeletion(
scoped_ptr<SyncTaskToken> token) {
sync_root_deletion_ = true;
SyncCompleted(token.Pass(), SYNC_STATUS_OK);
}
void RemoteToLocalSyncer::HandleDeletion( void RemoteToLocalSyncer::HandleDeletion(
scoped_ptr<SyncTaskToken> token) { scoped_ptr<SyncTaskToken> token) {
DCHECK(dirty_tracker_); DCHECK(dirty_tracker_);
...@@ -467,6 +558,21 @@ void RemoteToLocalSyncer::HandleDeletion( ...@@ -467,6 +558,21 @@ void RemoteToLocalSyncer::HandleDeletion(
base::Passed(&token))); 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( void RemoteToLocalSyncer::DidPrepareForDeletion(
scoped_ptr<SyncTaskToken> token, scoped_ptr<SyncTaskToken> token,
SyncStatusCode status) { SyncStatusCode status) {
...@@ -639,9 +745,6 @@ void RemoteToLocalSyncer::FinalizeSync(scoped_ptr<SyncTaskToken> token, ...@@ -639,9 +745,6 @@ void RemoteToLocalSyncer::FinalizeSync(scoped_ptr<SyncTaskToken> token,
} }
void RemoteToLocalSyncer::Prepare(const SyncStatusCallback& callback) { void RemoteToLocalSyncer::Prepare(const SyncStatusCallback& callback) {
bool should_success = BuildFileSystemURL(
metadata_database(), *dirty_tracker_, &url_);
DCHECK(should_success);
DCHECK(url_.is_valid()); DCHECK(url_.is_valid());
remote_change_processor()->PrepareForProcessRemoteChange( remote_change_processor()->PrepareForProcessRemoteChange(
url_, url_,
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/memory/weak_ptr.h" #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/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.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/remote_change_processor.h"
#include "chrome/browser/sync_file_system/sync_action.h" #include "chrome/browser/sync_file_system/sync_action.h"
#include "chrome/browser/sync_file_system/sync_callbacks.h" #include "chrome/browser/sync_file_system/sync_callbacks.h"
...@@ -41,6 +42,8 @@ class SyncEngineContext; ...@@ -41,6 +42,8 @@ class SyncEngineContext;
class RemoteToLocalSyncer : public SyncTask { class RemoteToLocalSyncer : public SyncTask {
public: public:
typedef SyncTaskManager::Continuation Continuation;
// Conflicting trackers will have low priority for RemoteToLocalSyncer so that // Conflicting trackers will have low priority for RemoteToLocalSyncer so that
// it should be resolved by LocatToRemoteSyncer. // it should be resolved by LocatToRemoteSyncer.
explicit RemoteToLocalSyncer(SyncEngineContext* sync_context); explicit RemoteToLocalSyncer(SyncEngineContext* sync_context);
...@@ -102,6 +105,11 @@ class RemoteToLocalSyncer : public SyncTask { ...@@ -102,6 +105,11 @@ class RemoteToLocalSyncer : public SyncTask {
// - Dispatch to HandleOfflineSolvable() // - Dispatch to HandleOfflineSolvable()
void ResolveRemoteChange(scoped_ptr<SyncTaskToken> token); 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. // Handles missing remote metadata case.
// Fetches remote metadata and updates MetadataDatabase by that. The sync // Fetches remote metadata and updates MetadataDatabase by that. The sync
// operation itself will be deferred to the next sync round. // operation itself will be deferred to the next sync round.
...@@ -132,8 +140,6 @@ class RemoteToLocalSyncer : public SyncTask { ...@@ -132,8 +140,6 @@ class RemoteToLocalSyncer : public SyncTask {
void DidPrepareForFolderUpdate(scoped_ptr<SyncTaskToken> token, void DidPrepareForFolderUpdate(scoped_ptr<SyncTaskToken> token,
SyncStatusCode status); SyncStatusCode status);
void HandleSyncRootDeletion(scoped_ptr<SyncTaskToken> token);
// Handles deleted remote file. Needs Prepare() call. // Handles deleted remote file. Needs Prepare() call.
// If the deleted tracker is the sync-root: // If the deleted tracker is the sync-root:
// - TODO(tzik): Needs special handling. // - TODO(tzik): Needs special handling.
...@@ -150,6 +156,8 @@ class RemoteToLocalSyncer : public SyncTask { ...@@ -150,6 +156,8 @@ class RemoteToLocalSyncer : public SyncTask {
void DidPrepareForDeletion(scoped_ptr<SyncTaskToken> token, void DidPrepareForDeletion(scoped_ptr<SyncTaskToken> token,
SyncStatusCode status); SyncStatusCode status);
void HandleFileMove(scoped_ptr<SyncTaskToken> token);
// Handles new file. Needs Prepare() call. // Handles new file. Needs Prepare() call.
void HandleContentUpdate(scoped_ptr<SyncTaskToken> token); void HandleContentUpdate(scoped_ptr<SyncTaskToken> token);
......
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