Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / sync_file_system / drive_backend / conflict_resolver.cc
index 176c2fd..a441397 100644 (file)
@@ -8,14 +8,16 @@
 #include "base/format_macros.h"
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/strings/stringprintf.h"
 #include "chrome/browser/drive/drive_api_util.h"
 #include "chrome/browser/drive/drive_service_interface.h"
 #include "chrome/browser/drive/drive_uploader.h"
-#include "chrome/browser/sync_file_system/drive_backend/conflict_resolver.h"
 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h"
 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
 #include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h"
+#include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h"
+#include "chrome/browser/sync_file_system/drive_backend/sync_task_token.h"
 #include "chrome/browser/sync_file_system/logger.h"
 #include "google_apis/drive/drive_api_parser.h"
 
@@ -24,46 +26,57 @@ namespace drive_backend {
 
 ConflictResolver::ConflictResolver(SyncEngineContext* sync_context)
     : sync_context_(sync_context),
-      weak_ptr_factory_(this) {
-}
+      weak_ptr_factory_(this) {}
+
+ConflictResolver::~ConflictResolver() {}
 
-ConflictResolver::~ConflictResolver() {
+void ConflictResolver::RunPreflight(scoped_ptr<SyncTaskToken> token) {
+  token->InitializeTaskLog("Conflict Resolution");
+
+  scoped_ptr<TaskBlocker> task_blocker(new TaskBlocker);
+  task_blocker->exclusive = true;
+  SyncTaskManager::UpdateTaskBlocker(
+      token.Pass(), task_blocker.Pass(),
+      base::Bind(&ConflictResolver::RunExclusive,
+                 weak_ptr_factory_.GetWeakPtr()));
 }
 
-void ConflictResolver::Run(const SyncStatusCallback& callback) {
+void ConflictResolver::RunExclusive(scoped_ptr<SyncTaskToken> token) {
   if (!IsContextReady()) {
-    NOTREACHED();
-    callback.Run(SYNC_STATUS_FAILED);
+    SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED);
     return;
   }
 
   // Conflict resolution should be invoked on clean tree.
-  if (metadata_database()->GetNormalPriorityDirtyTracker(NULL) ||
-      metadata_database()->GetLowPriorityDirtyTracker(NULL)) {
+  if (metadata_database()->HasDirtyTracker()) {
     NOTREACHED();
-    callback.Run(SYNC_STATUS_FAILED);
+    SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED);
     return;
   }
 
-  TrackerSet trackers;
+  TrackerIDSet trackers;
   if (metadata_database()->GetMultiParentFileTrackers(
           &target_file_id_, &trackers)) {
     DCHECK_LT(1u, trackers.size());
     if (!trackers.has_active()) {
       NOTREACHED();
-      callback.Run(SYNC_STATUS_FAILED);
+      SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED);
       return;
     }
 
-    util::Log(logging::LOG_VERBOSE, FROM_HERE,
-              "[ConflictResolver] Detected multi-parent trackers "
-              "(active tracker_id=%" PRId64 ")",
-              trackers.active_tracker()->tracker_id());
+    token->RecordLog(base::StringPrintf(
+        "Detected multi-parent trackers (active tracker_id=%" PRId64 ")",
+        trackers.active_tracker()));
 
     DCHECK(trackers.has_active());
-    for (TrackerSet::const_iterator itr = trackers.begin();
+    for (TrackerIDSet::const_iterator itr = trackers.begin();
          itr != trackers.end(); ++itr) {
-      const FileTracker& tracker = **itr;
+      FileTracker tracker;
+      if (!metadata_database()->FindTrackerByTrackerID(*itr, &tracker)) {
+        NOTREACHED();
+        continue;
+      }
+
       if (tracker.active())
         continue;
 
@@ -72,12 +85,12 @@ void ConflictResolver::Run(const SyncStatusCallback& callback) {
           tracker.parent_tracker_id(), &parent_tracker);
       if (!should_success) {
         NOTREACHED();
-        callback.Run(SYNC_STATUS_FAILED);
+        SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED);
         return;
       }
       parents_to_remove_.push_back(parent_tracker.file_id());
     }
-    DetachFromNonPrimaryParents(callback);
+    DetachFromNonPrimaryParents(token.Pass());
     return;
   }
 
@@ -85,9 +98,13 @@ void ConflictResolver::Run(const SyncStatusCallback& callback) {
     target_file_id_ = PickPrimaryFile(trackers);
     DCHECK(!target_file_id_.empty());
     int64 primary_tracker_id = -1;
-    for (TrackerSet::const_iterator itr = trackers.begin();
+    for (TrackerIDSet::const_iterator itr = trackers.begin();
          itr != trackers.end(); ++itr) {
-      const FileTracker& tracker = **itr;
+      FileTracker tracker;
+      if (!metadata_database()->FindTrackerByTrackerID(*itr, &tracker)) {
+        NOTREACHED();
+        continue;
+      }
       if (tracker.file_id() != target_file_id_) {
         non_primary_file_ids_.push_back(
             std::make_pair(tracker.file_id(), tracker.synced_details().etag()));
@@ -96,61 +113,67 @@ void ConflictResolver::Run(const SyncStatusCallback& callback) {
       }
     }
 
-    util::Log(logging::LOG_VERBOSE, FROM_HERE,
-              "[ConflictResolver] Detected %" PRIuS " conflicting trackers "
-              "(primary tracker_id=%" PRId64 ")",
-              non_primary_file_ids_.size(), primary_tracker_id);
+    token->RecordLog(base::StringPrintf(
+        "Detected %" PRIuS " conflicting trackers "
+        "(primary tracker_id=%" PRId64 ")",
+        non_primary_file_ids_.size(), primary_tracker_id));
 
-    RemoveNonPrimaryFiles(callback);
+    RemoveNonPrimaryFiles(token.Pass());
     return;
   }
 
-  callback.Run(SYNC_STATUS_NO_CONFLICT);
+  SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_NO_CONFLICT);
 }
 
 void ConflictResolver::DetachFromNonPrimaryParents(
-    const SyncStatusCallback& callback) {
+    scoped_ptr<SyncTaskToken> token) {
   DCHECK(!parents_to_remove_.empty());
 
   // TODO(tzik): Check if ETag match is available for
   // RemoteResourceFromDirectory.
   std::string parent_folder_id = parents_to_remove_.back();
   parents_to_remove_.pop_back();
+
+  token->RecordLog(base::StringPrintf(
+      "Detach %s from %s",
+      target_file_id_.c_str(), parent_folder_id.c_str()));
+
   drive_service()->RemoveResourceFromDirectory(
       parent_folder_id, target_file_id_,
       base::Bind(&ConflictResolver::DidDetachFromParent,
                  weak_ptr_factory_.GetWeakPtr(),
-                 callback));
-  util::Log(logging::LOG_VERBOSE, FROM_HERE,
-            "[ConflictResolver] Detach %s from %s",
-            target_file_id_.c_str(), parent_folder_id.c_str());
+                 base::Passed(&token)));
 }
 
-void ConflictResolver::DidDetachFromParent(const SyncStatusCallback& callback,
+void ConflictResolver::DidDetachFromParent(scoped_ptr<SyncTaskToken> token,
                                            google_apis::GDataErrorCode error) {
   SyncStatusCode status = GDataErrorCodeToSyncStatusCode(error);
   if (status != SYNC_STATUS_OK) {
-    callback.Run(status);
+    SyncTaskManager::NotifyTaskDone(token.Pass(), status);
     return;
   }
 
   if (!parents_to_remove_.empty()) {
-    DetachFromNonPrimaryParents(callback);
+    DetachFromNonPrimaryParents(token.Pass());
     return;
   }
 
-  callback.Run(SYNC_STATUS_OK);
+  SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_OK);
 }
 
-std::string ConflictResolver::PickPrimaryFile(const TrackerSet& trackers) {
+std::string ConflictResolver::PickPrimaryFile(const TrackerIDSet& trackers) {
   scoped_ptr<FileMetadata> primary;
-  for (TrackerSet::const_iterator itr = trackers.begin();
+  for (TrackerIDSet::const_iterator itr = trackers.begin();
        itr != trackers.end(); ++itr) {
-    const FileTracker& tracker = **itr;
+    FileTracker tracker;
+    if (!metadata_database()->FindTrackerByTrackerID(*itr, &tracker)) {
+      NOTREACHED();
+      continue;
+    }
+
     scoped_ptr<FileMetadata> file_metadata(new FileMetadata);
-    bool should_success = metadata_database()->FindFileByFileID(
-        tracker.file_id(), file_metadata.get());
-    if (!should_success) {
+    if (!metadata_database()->FindFileByFileID(
+            tracker.file_id(), file_metadata.get())) {
       NOTREACHED();
       continue;
     }
@@ -203,8 +226,7 @@ std::string ConflictResolver::PickPrimaryFile(const TrackerSet& trackers) {
   return std::string();
 }
 
-void ConflictResolver::RemoveNonPrimaryFiles(
-    const SyncStatusCallback& callback) {
+void ConflictResolver::RemoveNonPrimaryFiles(scoped_ptr<SyncTaskToken> token) {
   DCHECK(!non_primary_file_ids_.empty());
 
   std::string file_id = non_primary_file_ids_.back().first;
@@ -213,8 +235,8 @@ void ConflictResolver::RemoveNonPrimaryFiles(
 
   DCHECK_NE(target_file_id_, file_id);
 
-  util::Log(logging::LOG_VERBOSE, FROM_HERE,
-            "[ConflictResolver] Remove non-primary file %s", file_id.c_str());
+  token->RecordLog(base::StringPrintf(
+      "Remove non-primary file %s", file_id.c_str()));
 
   // TODO(tzik): Check if the file is a folder, and merge its contents into
   // the folder identified by |target_file_id_|.
@@ -222,32 +244,33 @@ void ConflictResolver::RemoveNonPrimaryFiles(
       file_id, etag,
       base::Bind(&ConflictResolver::DidRemoveFile,
                  weak_ptr_factory_.GetWeakPtr(),
-                 callback, file_id));
+                 base::Passed(&token), file_id));
 }
 
-void ConflictResolver::DidRemoveFile(const SyncStatusCallback& callback,
+void ConflictResolver::DidRemoveFile(scoped_ptr<SyncTaskToken> token,
                                      const std::string& file_id,
                                      google_apis::GDataErrorCode error) {
   if (error == google_apis::HTTP_PRECONDITION ||
       error == google_apis::HTTP_CONFLICT) {
-    UpdateFileMetadata(file_id, callback);
+    UpdateFileMetadata(file_id, token.Pass());
     return;
   }
 
   SyncStatusCode status = GDataErrorCodeToSyncStatusCode(error);
   if (status != SYNC_STATUS_OK && error != google_apis::HTTP_NOT_FOUND) {
-    callback.Run(status);
+    SyncTaskManager::NotifyTaskDone(token.Pass(), status);
     return;
   }
 
   deleted_file_ids_.push_back(file_id);
   if (!non_primary_file_ids_.empty()) {
-    RemoveNonPrimaryFiles(callback);
+    RemoveNonPrimaryFiles(token.Pass());
     return;
   }
 
-  metadata_database()->UpdateByDeletedRemoteFileList(
-      deleted_file_ids_, callback);
+  status = metadata_database()->UpdateByDeletedRemoteFileList(
+      deleted_file_ids_);
+  SyncTaskManager::NotifyTaskDone(token.Pass(), status);
 }
 
 bool ConflictResolver::IsContextReady() {
@@ -257,38 +280,39 @@ bool ConflictResolver::IsContextReady() {
 
 void ConflictResolver::UpdateFileMetadata(
     const std::string& file_id,
-    const SyncStatusCallback& callback) {
-  drive_service()->GetResourceEntry(
+    scoped_ptr<SyncTaskToken> token) {
+  drive_service()->GetFileResource(
       file_id,
       base::Bind(&ConflictResolver::DidGetRemoteMetadata,
-                 weak_ptr_factory_.GetWeakPtr(), file_id, callback));
+                 weak_ptr_factory_.GetWeakPtr(), file_id,
+                 base::Passed(&token)));
 }
 
 void ConflictResolver::DidGetRemoteMetadata(
     const std::string& file_id,
-    const SyncStatusCallback& callback,
+    scoped_ptr<SyncTaskToken> token,
     google_apis::GDataErrorCode error,
-    scoped_ptr<google_apis::ResourceEntry> entry) {
+    scoped_ptr<google_apis::FileResource> entry) {
   SyncStatusCode status = GDataErrorCodeToSyncStatusCode(error);
   if (status != SYNC_STATUS_OK && error != google_apis::HTTP_NOT_FOUND) {
-    callback.Run(status);
+    SyncTaskManager::NotifyTaskDone(token.Pass(), status);
     return;
   }
 
   if (error != google_apis::HTTP_NOT_FOUND) {
-    metadata_database()->UpdateByDeletedRemoteFile(file_id, callback);
+    status = metadata_database()->UpdateByDeletedRemoteFile(file_id);
+    SyncTaskManager::NotifyTaskDone(token.Pass(), status);
     return;
   }
 
   if (!entry) {
     NOTREACHED();
-    callback.Run(SYNC_STATUS_FAILED);
+    SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED);
     return;
   }
 
-  metadata_database()->UpdateByFileResource(
-      *drive::util::ConvertResourceEntryToFileResource(*entry),
-      callback);
+  status = metadata_database()->UpdateByFileResource(*entry);
+  SyncTaskManager::NotifyTaskDone(token.Pass(), status);
 }
 
 drive::DriveServiceInterface* ConflictResolver::drive_service() {