1a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// found in the LICENSE file. 4a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/conflict_resolver.h" 6a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 7a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/callback.h" 85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/format_macros.h" 9a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/location.h" 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/logging.h" 1146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "base/strings/stringprintf.h" 12a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/drive/drive_api_util.h" 13a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/drive/drive_service_interface.h" 14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/drive/drive_uploader.h" 15a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h" 16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/metadata_database.h" 17a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h" 18a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/sync_engine_context.h" 1946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/sync_task_manager.h" 2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "chrome/browser/sync_file_system/drive_backend/sync_task_token.h" 215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/sync_file_system/logger.h" 22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "google_apis/drive/drive_api_parser.h" 23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace sync_file_system { 25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)namespace drive_backend { 26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)ConflictResolver::ConflictResolver(SyncEngineContext* sync_context) 28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : sync_context_(sync_context), 29effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch weak_ptr_factory_(this) {} 30a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 31effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochConflictResolver::~ConflictResolver() {} 32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ConflictResolver::RunPreflight(scoped_ptr<SyncTaskToken> token) { 3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) token->InitializeTaskLog("Conflict Resolution"); 3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<TaskBlocker> task_blocker(new TaskBlocker); 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci task_blocker->exclusive = true; 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SyncTaskManager::UpdateTaskBlocker( 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci token.Pass(), task_blocker.Pass(), 4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&ConflictResolver::RunExclusive, 4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr())); 4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ConflictResolver::RunExclusive(scoped_ptr<SyncTaskToken> token) { 45a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!IsContextReady()) { 4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED); 47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 49a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 50a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Conflict resolution should be invoked on clean tree. 51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (metadata_database()->HasDirtyTracker()) { 52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NOTREACHED(); 5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED); 54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) TrackerIDSet trackers; 58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (metadata_database()->GetMultiParentFileTrackers( 59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) &target_file_id_, &trackers)) { 60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK_LT(1u, trackers.size()); 61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!trackers.has_active()) { 62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NOTREACHED(); 6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED); 64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 6746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) token->RecordLog(base::StringPrintf( 6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "Detected multi-parent trackers (active tracker_id=%" PRId64 ")", 6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) trackers.active_tracker())); 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 71a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(trackers.has_active()); 72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (TrackerIDSet::const_iterator itr = trackers.begin(); 73a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) itr != trackers.end(); ++itr) { 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FileTracker tracker; 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!metadata_database()->FindTrackerByTrackerID(*itr, &tracker)) { 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NOTREACHED(); 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) continue; 78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (tracker.active()) 81a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) continue; 82a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 83a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) FileTracker parent_tracker; 84a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool should_success = metadata_database()->FindTrackerByTrackerID( 85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) tracker.parent_tracker_id(), &parent_tracker); 86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!should_success) { 87a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NOTREACHED(); 8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED); 89a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 90a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) parents_to_remove_.push_back(parent_tracker.file_id()); 92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 9346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DetachFromNonPrimaryParents(token.Pass()); 94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 95a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 96a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 97a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (metadata_database()->GetConflictingTrackers(&trackers)) { 98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) target_file_id_ = PickPrimaryFile(trackers); 99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(!target_file_id_.empty()); 1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int64 primary_tracker_id = -1; 101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (TrackerIDSet::const_iterator itr = trackers.begin(); 102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) itr != trackers.end(); ++itr) { 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FileTracker tracker; 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!metadata_database()->FindTrackerByTrackerID(*itr, &tracker)) { 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NOTREACHED(); 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) continue; 107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (tracker.file_id() != target_file_id_) { 109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) non_primary_file_ids_.push_back( 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::make_pair(tracker.file_id(), tracker.synced_details().etag())); 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) primary_tracker_id = tracker.tracker_id(); 113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) token->RecordLog(base::StringPrintf( 11746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "Detected %" PRIuS " conflicting trackers " 11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "(primary tracker_id=%" PRId64 ")", 11946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) non_primary_file_ids_.size(), primary_tracker_id)); 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 12146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) RemoveNonPrimaryFiles(token.Pass()); 122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 12546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_NO_CONFLICT); 126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ConflictResolver::DetachFromNonPrimaryParents( 12946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<SyncTaskToken> token) { 130a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(!parents_to_remove_.empty()); 131a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // TODO(tzik): Check if ETag match is available for 133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // RemoteResourceFromDirectory. 134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string parent_folder_id = parents_to_remove_.back(); 135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) parents_to_remove_.pop_back(); 13646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 13746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) token->RecordLog(base::StringPrintf( 13846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "Detach %s from %s", 13946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) target_file_id_.c_str(), parent_folder_id.c_str())); 14046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) drive_service()->RemoveResourceFromDirectory( 142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) parent_folder_id, target_file_id_, 143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&ConflictResolver::DidDetachFromParent, 144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 14546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Passed(&token))); 146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 14846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ConflictResolver::DidDetachFromParent(scoped_ptr<SyncTaskToken> token, 149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) google_apis::GDataErrorCode error) { 150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SyncStatusCode status = GDataErrorCodeToSyncStatusCode(error); 151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (status != SYNC_STATUS_OK) { 15246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) SyncTaskManager::NotifyTaskDone(token.Pass(), status); 153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 155a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!parents_to_remove_.empty()) { 15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DetachFromNonPrimaryParents(token.Pass()); 158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 16146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_OK); 162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)std::string ConflictResolver::PickPrimaryFile(const TrackerIDSet& trackers) { 165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<FileMetadata> primary; 166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (TrackerIDSet::const_iterator itr = trackers.begin(); 167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) itr != trackers.end(); ++itr) { 168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FileTracker tracker; 169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!metadata_database()->FindTrackerByTrackerID(*itr, &tracker)) { 170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NOTREACHED(); 171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) continue; 172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) scoped_ptr<FileMetadata> file_metadata(new FileMetadata); 175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!metadata_database()->FindFileByFileID( 176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) tracker.file_id(), file_metadata.get())) { 177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NOTREACHED(); 178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) continue; 179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!primary) { 182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) primary = file_metadata.Pass(); 183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) continue; 184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(primary->details().file_kind() == FILE_KIND_FILE || 187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) primary->details().file_kind() == FILE_KIND_FOLDER); 188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(file_metadata->details().file_kind() == FILE_KIND_FILE || 189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) file_metadata->details().file_kind() == FILE_KIND_FOLDER); 190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (primary->details().file_kind() == FILE_KIND_FILE) { 192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (file_metadata->details().file_kind() == FILE_KIND_FOLDER) { 193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Prioritize folders over regular files. 194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) primary = file_metadata.Pass(); 195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) continue; 196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(file_metadata->details().file_kind() == FILE_KIND_FILE); 199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (primary->details().modification_time() < 200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) file_metadata->details().modification_time()) { 201a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Prioritize last write for regular files. 202a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) primary = file_metadata.Pass(); 203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) continue; 204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 206a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) continue; 207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 209a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(primary->details().file_kind() == FILE_KIND_FOLDER); 210a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (file_metadata->details().file_kind() == FILE_KIND_FILE) { 211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Prioritize folders over regular files. 212a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) continue; 213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 214a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(file_metadata->details().file_kind() == FILE_KIND_FOLDER); 216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (primary->details().creation_time() > 217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) file_metadata->details().creation_time()) { 218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Prioritize first create for folders. 219a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) primary = file_metadata.Pass(); 220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) continue; 221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 223a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (primary) 225a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return primary->file_id(); 226a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return std::string(); 227a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 228a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 22946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ConflictResolver::RemoveNonPrimaryFiles(scoped_ptr<SyncTaskToken> token) { 230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK(!non_primary_file_ids_.empty()); 231a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string file_id = non_primary_file_ids_.back().first; 233a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string etag = non_primary_file_ids_.back().second; 234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) non_primary_file_ids_.pop_back(); 2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK_NE(target_file_id_, file_id); 237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 23846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) token->RecordLog(base::StringPrintf( 23946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) "Remove non-primary file %s", file_id.c_str())); 2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // TODO(tzik): Check if the file is a folder, and merge its contents into 242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // the folder identified by |target_file_id_|. 243a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) drive_service()->DeleteResource( 244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) file_id, etag, 245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&ConflictResolver::DidRemoveFile, 246a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 24746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Passed(&token), file_id)); 248a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 249a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 25046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void ConflictResolver::DidRemoveFile(scoped_ptr<SyncTaskToken> token, 251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const std::string& file_id, 252a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) google_apis::GDataErrorCode error) { 253a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (error == google_apis::HTTP_PRECONDITION || 254a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) error == google_apis::HTTP_CONFLICT) { 25546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) UpdateFileMetadata(file_id, token.Pass()); 256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 257a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 258a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SyncStatusCode status = GDataErrorCodeToSyncStatusCode(error); 260a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (status != SYNC_STATUS_OK && error != google_apis::HTTP_NOT_FOUND) { 26146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) SyncTaskManager::NotifyTaskDone(token.Pass(), status); 262a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 263a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 264a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) deleted_file_ids_.push_back(file_id); 266a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!non_primary_file_ids_.empty()) { 26746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) RemoveNonPrimaryFiles(token.Pass()); 268a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return; 269a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 270a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci status = metadata_database()->UpdateByDeletedRemoteFileList( 2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci deleted_file_ids_); 2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SyncTaskManager::NotifyTaskDone(token.Pass(), status); 274a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 275a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 276a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ConflictResolver::IsContextReady() { 277a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return sync_context_->GetDriveService() && 278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) sync_context_->GetMetadataDatabase(); 279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 280a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ConflictResolver::UpdateFileMetadata( 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& file_id, 28346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<SyncTaskToken> token) { 28446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) drive_service()->GetFileResource( 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) file_id, 2865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&ConflictResolver::DidGetRemoteMetadata, 28746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), file_id, 28846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Passed(&token))); 2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ConflictResolver::DidGetRemoteMetadata( 2925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& file_id, 29346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<SyncTaskToken> token, 2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) google_apis::GDataErrorCode error, 29546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<google_apis::FileResource> entry) { 2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SyncStatusCode status = GDataErrorCodeToSyncStatusCode(error); 2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status != SYNC_STATUS_OK && error != google_apis::HTTP_NOT_FOUND) { 29846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) SyncTaskManager::NotifyTaskDone(token.Pass(), status); 2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (error != google_apis::HTTP_NOT_FOUND) { 3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci status = metadata_database()->UpdateByDeletedRemoteFile(file_id); 3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SyncTaskManager::NotifyTaskDone(token.Pass(), status); 3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!entry) { 3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED(); 31046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) SyncTaskManager::NotifyTaskDone(token.Pass(), SYNC_STATUS_FAILED); 3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return; 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci status = metadata_database()->UpdateByFileResource(*entry); 3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SyncTaskManager::NotifyTaskDone(token.Pass(), status); 3165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 3175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 318a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)drive::DriveServiceInterface* ConflictResolver::drive_service() { 319a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) set_used_network(true); 320a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return sync_context_->GetDriveService(); 321a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 322a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 323a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)MetadataDatabase* ConflictResolver::metadata_database() { 324a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return sync_context_->GetMetadataDatabase(); 325a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 326a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 327a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace drive_backend 328a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} // namespace sync_file_system 329