[email protected] | 5051fdde | 2012-03-19 21:10:14 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
yawano | 3513e14 | 2016-04-20 00:42:42 | [diff] [blame] | 5 | #include "components/drive/chromeos/sync_client.h" |
[email protected] | 5051fdde | 2012-03-19 21:10:14 | [diff] [blame] | 6 | |
avi | bc5337b | 2015-12-25 23:16:33 | [diff] [blame] | 7 | #include <stddef.h> |
| 8 | |
[email protected] | 3653146a | 2012-05-29 13:41:47 | [diff] [blame] | 9 | #include <vector> |
| 10 | |
[email protected] | 92b84f33 | 2012-03-21 20:45:21 | [diff] [blame] | 11 | #include "base/bind.h" |
Sebastien Marchand | 17fa278 | 2019-01-25 19:28:10 | [diff] [blame] | 12 | #include "base/bind_helpers.h" |
gab | 7966d31 | 2016-05-11 20:35:01 | [diff] [blame] | 13 | #include "base/threading/thread_task_runner_handle.h" |
yawano | 3513e14 | 2016-04-20 00:42:42 | [diff] [blame] | 14 | #include "components/drive/chromeos/file_cache.h" |
| 15 | #include "components/drive/chromeos/file_system/download_operation.h" |
| 16 | #include "components/drive/chromeos/file_system/operation_delegate.h" |
| 17 | #include "components/drive/chromeos/sync/entry_update_performer.h" |
lukasza | 01b9d55a | 2015-07-21 15:19:25 | [diff] [blame] | 18 | #include "components/drive/drive.pb.h" |
lukasza | 6364a02 | 2015-08-21 01:13:24 | [diff] [blame] | 19 | #include "components/drive/file_system_core_util.h" |
lukasza | b371ff4f | 2015-08-13 18:23:47 | [diff] [blame] | 20 | #include "components/drive/job_scheduler.h" |
[email protected] | e196bef3 | 2013-12-03 05:33:13 | [diff] [blame] | 21 | #include "google_apis/drive/task_util.h" |
[email protected] | 92b84f33 | 2012-03-21 20:45:21 | [diff] [blame] | 22 | |
[email protected] | d9d04df | 2012-10-12 07:06:35 | [diff] [blame] | 23 | namespace drive { |
[email protected] | 4e87c486 | 2013-05-20 04:06:32 | [diff] [blame] | 24 | namespace internal { |
[email protected] | 5051fdde | 2012-03-19 21:10:14 | [diff] [blame] | 25 | |
[email protected] | b83e520 | 2012-06-27 07:50:24 | [diff] [blame] | 26 | namespace { |
| 27 | |
[email protected] | e07bbd97 | 2013-01-23 17:38:42 | [diff] [blame] | 28 | // The delay constant is used to delay processing a sync task. We should not |
| 29 | // process SyncTasks immediately for the following reasons: |
[email protected] | b83e520 | 2012-06-27 07:50:24 | [diff] [blame] | 30 | // |
| 31 | // 1) For fetching, the user may accidentally click on "Make available |
| 32 | // offline" checkbox on a file, and immediately cancel it in a second. |
| 33 | // It's a waste to fetch the file in this case. |
| 34 | // |
[email protected] | f60c670b | 2012-09-13 06:19:25 | [diff] [blame] | 35 | // 2) For uploading, file writing via HTML5 file system API is performed in |
[email protected] | b83e520 | 2012-06-27 07:50:24 | [diff] [blame] | 36 | // two steps: 1) truncate a file to 0 bytes, 2) write contents. We |
| 37 | // shouldn't start uploading right after the step 1). Besides, the user |
| 38 | // may edit the same file repeatedly in a short period of time. |
| 39 | // |
| 40 | // TODO(satorux): We should find a way to handle the upload case more nicely, |
| 41 | // and shorten the delay. crbug.com/134774 |
[email protected] | 0bbfb58 | 2014-02-10 07:33:39 | [diff] [blame] | 42 | const int kDelaySeconds = 1; |
[email protected] | b83e520 | 2012-06-27 07:50:24 | [diff] [blame] | 43 | |
[email protected] | 9432bc3 | 2013-08-08 22:42:55 | [diff] [blame] | 44 | // The delay constant is used to delay retrying a sync task on server errors. |
| 45 | const int kLongDelaySeconds = 600; |
| 46 | |
[email protected] | 562af1c1 | 2013-11-26 10:27:53 | [diff] [blame] | 47 | // Iterates entries and appends IDs to |to_fetch| if the file is pinned but not |
[email protected] | 5e273db | 2014-01-24 16:44:29 | [diff] [blame] | 48 | // fetched (not present locally), to |to_update| if the file needs update. |
[email protected] | 562af1c1 | 2013-11-26 10:27:53 | [diff] [blame] | 49 | void CollectBacklog(ResourceMetadata* metadata, |
[email protected] | 0763527 | 2013-09-24 06:40:23 | [diff] [blame] | 50 | std::vector<std::string>* to_fetch, |
[email protected] | 5a1b0d1 | 2013-11-29 07:53:10 | [diff] [blame] | 51 | std::vector<std::string>* to_update) { |
[email protected] | d68ede0 | 2012-11-07 14:30:53 | [diff] [blame] | 52 | DCHECK(to_fetch); |
[email protected] | 5a1b0d1 | 2013-11-29 07:53:10 | [diff] [blame] | 53 | DCHECK(to_update); |
[email protected] | d68ede0 | 2012-11-07 14:30:53 | [diff] [blame] | 54 | |
dcheng | f4275023 | 2016-04-12 04:12:27 | [diff] [blame] | 55 | std::unique_ptr<ResourceMetadata::Iterator> it = metadata->GetIterator(); |
[email protected] | 0763527 | 2013-09-24 06:40:23 | [diff] [blame] | 56 | for (; !it->IsAtEnd(); it->Advance()) { |
[email protected] | 0763527 | 2013-09-24 06:40:23 | [diff] [blame] | 57 | const std::string& local_id = it->GetID(); |
[email protected] | 562af1c1 | 2013-11-26 10:27:53 | [diff] [blame] | 58 | const ResourceEntry& entry = it->GetValue(); |
| 59 | if (entry.parent_local_id() == util::kDriveTrashDirLocalId) { |
[email protected] | 5a1b0d1 | 2013-11-29 07:53:10 | [diff] [blame] | 60 | to_update->push_back(local_id); |
[email protected] | 562af1c1 | 2013-11-26 10:27:53 | [diff] [blame] | 61 | continue; |
| 62 | } |
[email protected] | d68ede0 | 2012-11-07 14:30:53 | [diff] [blame] | 63 | |
[email protected] | 5e273db | 2014-01-24 16:44:29 | [diff] [blame] | 64 | bool should_update = false; |
[email protected] | 5170a13 | 2013-12-02 10:35:13 | [diff] [blame] | 65 | switch (entry.metadata_edit_state()) { |
| 66 | case ResourceEntry::CLEAN: |
| 67 | break; |
| 68 | case ResourceEntry::SYNCING: |
| 69 | case ResourceEntry::DIRTY: |
[email protected] | 5e273db | 2014-01-24 16:44:29 | [diff] [blame] | 70 | should_update = true; |
[email protected] | 5170a13 | 2013-12-02 10:35:13 | [diff] [blame] | 71 | break; |
| 72 | } |
| 73 | |
[email protected] | 52525f8 | 2014-05-14 04:30:30 | [diff] [blame] | 74 | if (entry.file_specific_info().cache_state().is_pinned() && |
| 75 | !entry.file_specific_info().cache_state().is_present()) |
| 76 | to_fetch->push_back(local_id); |
[email protected] | 562af1c1 | 2013-11-26 10:27:53 | [diff] [blame] | 77 | |
[email protected] | 52525f8 | 2014-05-14 04:30:30 | [diff] [blame] | 78 | if (entry.file_specific_info().cache_state().is_dirty()) |
| 79 | should_update = true; |
| 80 | |
[email protected] | 5e273db | 2014-01-24 16:44:29 | [diff] [blame] | 81 | if (should_update) |
| 82 | to_update->push_back(local_id); |
[email protected] | 0763527 | 2013-09-24 06:40:23 | [diff] [blame] | 83 | } |
| 84 | DCHECK(!it->HasError()); |
| 85 | } |
| 86 | |
| 87 | // Iterates cache entries and collects IDs of ones with obsolete cache files. |
| 88 | void CheckExistingPinnedFiles(ResourceMetadata* metadata, |
| 89 | FileCache* cache, |
| 90 | std::vector<std::string>* local_ids) { |
dcheng | f4275023 | 2016-04-12 04:12:27 | [diff] [blame] | 91 | std::unique_ptr<ResourceMetadata::Iterator> it = metadata->GetIterator(); |
[email protected] | 0763527 | 2013-09-24 06:40:23 | [diff] [blame] | 92 | for (; !it->IsAtEnd(); it->Advance()) { |
[email protected] | 0c53f98 | 2014-05-15 05:51:35 | [diff] [blame] | 93 | const ResourceEntry& entry = it->GetValue(); |
| 94 | const FileCacheEntry& cache_state = |
| 95 | entry.file_specific_info().cache_state(); |
[email protected] | 0763527 | 2013-09-24 06:40:23 | [diff] [blame] | 96 | const std::string& local_id = it->GetID(); |
[email protected] | 0c53f98 | 2014-05-15 05:51:35 | [diff] [blame] | 97 | if (!cache_state.is_pinned() || !cache_state.is_present()) |
[email protected] | 0763527 | 2013-09-24 06:40:23 | [diff] [blame] | 98 | continue; |
| 99 | |
[email protected] | 0763527 | 2013-09-24 06:40:23 | [diff] [blame] | 100 | // If MD5s don't match, it indicates the local cache file is stale, unless |
| 101 | // the file is dirty (the MD5 is "local"). We should never re-fetch the |
| 102 | // file when we have a locally modified version. |
[email protected] | 0c53f98 | 2014-05-15 05:51:35 | [diff] [blame] | 103 | if (entry.file_specific_info().md5() == cache_state.md5() || |
| 104 | cache_state.is_dirty()) |
[email protected] | 0763527 | 2013-09-24 06:40:23 | [diff] [blame] | 105 | continue; |
| 106 | |
[email protected] | 0c53f98 | 2014-05-15 05:51:35 | [diff] [blame] | 107 | FileError error = cache->Remove(local_id); |
[email protected] | 0763527 | 2013-09-24 06:40:23 | [diff] [blame] | 108 | if (error != FILE_ERROR_OK) { |
| 109 | LOG(WARNING) << "Failed to remove cache entry: " << local_id; |
| 110 | continue; |
| 111 | } |
| 112 | |
| 113 | error = cache->Pin(local_id); |
| 114 | if (error != FILE_ERROR_OK) { |
| 115 | LOG(WARNING) << "Failed to pin cache entry: " << local_id; |
| 116 | continue; |
| 117 | } |
| 118 | |
| 119 | local_ids->push_back(local_id); |
| 120 | } |
| 121 | DCHECK(!it->HasError()); |
[email protected] | d68ede0 | 2012-11-07 14:30:53 | [diff] [blame] | 122 | } |
| 123 | |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 124 | // Gets the parent entry of the entry specified by the ID. |
| 125 | FileError GetParentResourceEntry(ResourceMetadata* metadata, |
| 126 | const std::string& local_id, |
| 127 | ResourceEntry* parent) { |
| 128 | ResourceEntry entry; |
| 129 | FileError error = metadata->GetResourceEntryById(local_id, &entry); |
| 130 | if (error != FILE_ERROR_OK) |
| 131 | return error; |
| 132 | return metadata->GetResourceEntryById(entry.parent_local_id(), parent); |
[email protected] | 0167ff0 | 2014-03-28 17:22:23 | [diff] [blame] | 133 | } |
| 134 | |
[email protected] | b83e520 | 2012-06-27 07:50:24 | [diff] [blame] | 135 | } // namespace |
| 136 | |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 137 | SyncClient::SyncTask::SyncTask() |
| 138 | : state(SUSPENDED), context(BACKGROUND), should_run_again(false) {} |
vmpstr | b6449d51 | 2016-02-25 23:55:40 | [diff] [blame] | 139 | SyncClient::SyncTask::SyncTask(const SyncTask& other) = default; |
Stuart Langley | be403574 | 2018-05-10 05:32:27 | [diff] [blame] | 140 | SyncClient::SyncTask::~SyncTask() = default; |
[email protected] | b5fc21d | 2013-11-27 09:06:29 | [diff] [blame] | 141 | |
[email protected] | b568b88 | 2013-06-10 04:38:07 | [diff] [blame] | 142 | SyncClient::SyncClient(base::SequencedTaskRunner* blocking_task_runner, |
[email protected] | 4ffef21 | 2014-07-24 02:33:18 | [diff] [blame] | 143 | file_system::OperationDelegate* delegate, |
[email protected] | b568b88 | 2013-06-10 04:38:07 | [diff] [blame] | 144 | JobScheduler* scheduler, |
| 145 | ResourceMetadata* metadata, |
[email protected] | e07f7b7b | 2013-06-19 03:43:12 | [diff] [blame] | 146 | FileCache* cache, |
[email protected] | 20f33e6 | 2014-01-30 10:50:39 | [diff] [blame] | 147 | LoaderController* loader_controller, |
[email protected] | e07f7b7b | 2013-06-19 03:43:12 | [diff] [blame] | 148 | const base::FilePath& temporary_file_directory) |
[email protected] | 0763527 | 2013-09-24 06:40:23 | [diff] [blame] | 149 | : blocking_task_runner_(blocking_task_runner), |
[email protected] | 4ffef21 | 2014-07-24 02:33:18 | [diff] [blame] | 150 | operation_delegate_(delegate), |
[email protected] | 0763527 | 2013-09-24 06:40:23 | [diff] [blame] | 151 | metadata_(metadata), |
[email protected] | e0529fc | 2012-06-12 11:07:58 | [diff] [blame] | 152 | cache_(cache), |
Jeremy Roman | 47d432e | 2019-08-20 14:24:00 | [diff] [blame] | 153 | download_operation_( |
| 154 | new file_system::DownloadOperation(blocking_task_runner, |
| 155 | delegate, |
| 156 | scheduler, |
| 157 | metadata, |
| 158 | cache, |
| 159 | temporary_file_directory)), |
[email protected] | 5a1b0d1 | 2013-11-29 07:53:10 | [diff] [blame] | 160 | entry_update_performer_(new EntryUpdatePerformer(blocking_task_runner, |
[email protected] | 4ffef21 | 2014-07-24 02:33:18 | [diff] [blame] | 161 | delegate, |
[email protected] | 5a1b0d1 | 2013-11-29 07:53:10 | [diff] [blame] | 162 | scheduler, |
[email protected] | 5e273db | 2014-01-24 16:44:29 | [diff] [blame] | 163 | metadata, |
[email protected] | 069011f | 2014-01-29 07:56:59 | [diff] [blame] | 164 | cache, |
[email protected] | 20f33e6 | 2014-01-30 10:50:39 | [diff] [blame] | 165 | loader_controller)), |
[email protected] | b83e520 | 2012-06-27 07:50:24 | [diff] [blame] | 166 | delay_(base::TimeDelta::FromSeconds(kDelaySeconds)), |
Jeremy Roman | 47d432e | 2019-08-20 14:24:00 | [diff] [blame] | 167 | long_delay_(base::TimeDelta::FromSeconds(kLongDelaySeconds)) {} |
[email protected] | 5051fdde | 2012-03-19 21:10:14 | [diff] [blame] | 168 | |
[email protected] | d876d70b | 2013-04-23 20:06:15 | [diff] [blame] | 169 | SyncClient::~SyncClient() { |
Stuart Langley | be403574 | 2018-05-10 05:32:27 | [diff] [blame] | 170 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
[email protected] | 5051fdde | 2012-03-19 21:10:14 | [diff] [blame] | 171 | } |
| 172 | |
[email protected] | d876d70b | 2013-04-23 20:06:15 | [diff] [blame] | 173 | void SyncClient::StartProcessingBacklog() { |
Stuart Langley | be403574 | 2018-05-10 05:32:27 | [diff] [blame] | 174 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
[email protected] | b83e520 | 2012-06-27 07:50:24 | [diff] [blame] | 175 | |
[email protected] | d68ede0 | 2012-11-07 14:30:53 | [diff] [blame] | 176 | std::vector<std::string>* to_fetch = new std::vector<std::string>; |
[email protected] | 5e273db | 2014-01-24 16:44:29 | [diff] [blame] | 177 | std::vector<std::string>* to_update = new std::vector<std::string>; |
[email protected] | 0763527 | 2013-09-24 06:40:23 | [diff] [blame] | 178 | blocking_task_runner_->PostTaskAndReply( |
| 179 | FROM_HERE, |
tzik | 2bcf8e4 | 2018-07-31 11:22:15 | [diff] [blame] | 180 | base::BindOnce(&CollectBacklog, metadata_, to_fetch, to_update), |
| 181 | base::BindOnce(&SyncClient::OnGetLocalIdsOfBacklog, |
| 182 | weak_ptr_factory_.GetWeakPtr(), base::Owned(to_fetch), |
| 183 | base::Owned(to_update))); |
[email protected] | 92b84f33 | 2012-03-21 20:45:21 | [diff] [blame] | 184 | } |
| 185 | |
[email protected] | d876d70b | 2013-04-23 20:06:15 | [diff] [blame] | 186 | void SyncClient::StartCheckingExistingPinnedFiles() { |
Stuart Langley | be403574 | 2018-05-10 05:32:27 | [diff] [blame] | 187 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
[email protected] | 85b6219 | 2012-06-29 19:56:38 | [diff] [blame] | 188 | |
[email protected] | 0763527 | 2013-09-24 06:40:23 | [diff] [blame] | 189 | std::vector<std::string>* local_ids = new std::vector<std::string>; |
| 190 | blocking_task_runner_->PostTaskAndReply( |
| 191 | FROM_HERE, |
tzik | 2bcf8e4 | 2018-07-31 11:22:15 | [diff] [blame] | 192 | base::BindOnce(&CheckExistingPinnedFiles, metadata_, cache_, local_ids), |
| 193 | base::BindOnce(&SyncClient::AddFetchTasks, weak_ptr_factory_.GetWeakPtr(), |
| 194 | base::Owned(local_ids))); |
[email protected] | 85b6219 | 2012-06-29 19:56:38 | [diff] [blame] | 195 | } |
| 196 | |
[email protected] | c724115 | 2013-08-28 02:17:16 | [diff] [blame] | 197 | void SyncClient::AddFetchTask(const std::string& local_id) { |
Stuart Langley | be403574 | 2018-05-10 05:32:27 | [diff] [blame] | 198 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
[email protected] | b5fc21d | 2013-11-27 09:06:29 | [diff] [blame] | 199 | AddFetchTaskInternal(local_id, delay_); |
[email protected] | 6bf58114 | 2013-06-11 17:13:06 | [diff] [blame] | 200 | } |
| 201 | |
[email protected] | c724115 | 2013-08-28 02:17:16 | [diff] [blame] | 202 | void SyncClient::RemoveFetchTask(const std::string& local_id) { |
Stuart Langley | be403574 | 2018-05-10 05:32:27 | [diff] [blame] | 203 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
[email protected] | bd2254d | 2013-06-12 16:00:47 | [diff] [blame] | 204 | |
[email protected] | b5fc21d | 2013-11-27 09:06:29 | [diff] [blame] | 205 | SyncTasks::iterator it = tasks_.find(SyncTasks::key_type(FETCH, local_id)); |
| 206 | if (it == tasks_.end()) |
| 207 | return; |
| 208 | |
| 209 | SyncTask* task = &it->second; |
| 210 | switch (task->state) { |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 211 | case SUSPENDED: |
[email protected] | b5fc21d | 2013-11-27 09:06:29 | [diff] [blame] | 212 | case PENDING: |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 213 | OnTaskComplete(FETCH, local_id, FILE_ERROR_ABORT); |
[email protected] | b5fc21d | 2013-11-27 09:06:29 | [diff] [blame] | 214 | break; |
| 215 | case RUNNING: |
Stuart Langley | be403574 | 2018-05-10 05:32:27 | [diff] [blame] | 216 | if (task->cancel_closure) |
[email protected] | 551e9df | 2014-02-10 13:22:18 | [diff] [blame] | 217 | task->cancel_closure.Run(); |
[email protected] | b5fc21d | 2013-11-27 09:06:29 | [diff] [blame] | 218 | break; |
| 219 | } |
[email protected] | bd2254d | 2013-06-12 16:00:47 | [diff] [blame] | 220 | } |
| 221 | |
[email protected] | 0f7477f8 | 2014-01-23 09:39:09 | [diff] [blame] | 222 | void SyncClient::AddUpdateTask(const ClientContext& context, |
| 223 | const std::string& local_id) { |
Stuart Langley | be403574 | 2018-05-10 05:32:27 | [diff] [blame] | 224 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
[email protected] | 5e273db | 2014-01-24 16:44:29 | [diff] [blame] | 225 | AddUpdateTaskInternal(context, local_id, delay_); |
[email protected] | 562af1c1 | 2013-11-26 10:27:53 | [diff] [blame] | 226 | } |
| 227 | |
[email protected] | e849db5 | 2014-07-23 07:02:09 | [diff] [blame] | 228 | bool SyncClient:: WaitForUpdateTaskToComplete( |
| 229 | const std::string& local_id, |
| 230 | const FileOperationCallback& callback) { |
Stuart Langley | be403574 | 2018-05-10 05:32:27 | [diff] [blame] | 231 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
[email protected] | e849db5 | 2014-07-23 07:02:09 | [diff] [blame] | 232 | |
| 233 | SyncTasks::iterator it = tasks_.find(SyncTasks::key_type(UPDATE, local_id)); |
| 234 | if (it == tasks_.end()) |
| 235 | return false; |
| 236 | |
| 237 | SyncTask* task = &it->second; |
| 238 | task->waiting_callbacks.push_back(callback); |
| 239 | return true; |
| 240 | } |
| 241 | |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 242 | base::Closure SyncClient::PerformFetchTask(const std::string& local_id, |
| 243 | const ClientContext& context) { |
Stuart Langley | be403574 | 2018-05-10 05:32:27 | [diff] [blame] | 244 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 245 | return download_operation_->EnsureFileDownloadedByLocalId( |
[email protected] | b5fc21d | 2013-11-27 09:06:29 | [diff] [blame] | 246 | local_id, |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 247 | context, |
[email protected] | 0167ff0 | 2014-03-28 17:22:23 | [diff] [blame] | 248 | GetFileContentInitializedCallback(), |
[email protected] | b5fc21d | 2013-11-27 09:06:29 | [diff] [blame] | 249 | google_apis::GetContentCallback(), |
| 250 | base::Bind(&SyncClient::OnFetchFileComplete, |
| 251 | weak_ptr_factory_.GetWeakPtr(), |
| 252 | local_id)); |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 253 | } |
| 254 | |
| 255 | void SyncClient::AddFetchTaskInternal(const std::string& local_id, |
| 256 | const base::TimeDelta& delay) { |
Stuart Langley | be403574 | 2018-05-10 05:32:27 | [diff] [blame] | 257 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 258 | |
| 259 | SyncTask task; |
| 260 | task.state = PENDING; |
| 261 | task.context = ClientContext(BACKGROUND); |
| 262 | task.task = base::Bind(&SyncClient::PerformFetchTask, |
| 263 | base::Unretained(this), |
| 264 | local_id); |
[email protected] | b5fc21d | 2013-11-27 09:06:29 | [diff] [blame] | 265 | AddTask(SyncTasks::key_type(FETCH, local_id), task, delay); |
| 266 | } |
| 267 | |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 268 | base::Closure SyncClient::PerformUpdateTask(const std::string& local_id, |
| 269 | const ClientContext& context) { |
Stuart Langley | be403574 | 2018-05-10 05:32:27 | [diff] [blame] | 270 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 271 | entry_update_performer_->UpdateEntry( |
| 272 | local_id, |
| 273 | context, |
| 274 | base::Bind(&SyncClient::OnTaskComplete, |
| 275 | weak_ptr_factory_.GetWeakPtr(), |
| 276 | UPDATE, |
| 277 | local_id)); |
| 278 | return base::Closure(); |
| 279 | } |
| 280 | |
[email protected] | 0f7477f8 | 2014-01-23 09:39:09 | [diff] [blame] | 281 | void SyncClient::AddUpdateTaskInternal(const ClientContext& context, |
| 282 | const std::string& local_id, |
[email protected] | c742facc | 2013-11-27 13:44:20 | [diff] [blame] | 283 | const base::TimeDelta& delay) { |
Stuart Langley | be403574 | 2018-05-10 05:32:27 | [diff] [blame] | 284 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 285 | |
[email protected] | c742facc | 2013-11-27 13:44:20 | [diff] [blame] | 286 | SyncTask task; |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 287 | task.state = PENDING; |
| 288 | task.context = context; |
| 289 | task.task = base::Bind(&SyncClient::PerformUpdateTask, |
| 290 | base::Unretained(this), |
| 291 | local_id); |
[email protected] | 5a1b0d1 | 2013-11-29 07:53:10 | [diff] [blame] | 292 | AddTask(SyncTasks::key_type(UPDATE, local_id), task, delay); |
[email protected] | c742facc | 2013-11-27 13:44:20 | [diff] [blame] | 293 | } |
| 294 | |
[email protected] | b5fc21d | 2013-11-27 09:06:29 | [diff] [blame] | 295 | void SyncClient::AddTask(const SyncTasks::key_type& key, |
| 296 | const SyncTask& task, |
| 297 | const base::TimeDelta& delay) { |
Stuart Langley | be403574 | 2018-05-10 05:32:27 | [diff] [blame] | 298 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
[email protected] | b5fc21d | 2013-11-27 09:06:29 | [diff] [blame] | 299 | |
[email protected] | 799d4ec | 2013-12-06 07:39:23 | [diff] [blame] | 300 | SyncTasks::iterator it = tasks_.find(key); |
| 301 | if (it != tasks_.end()) { |
| 302 | switch (it->second.state) { |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 303 | case SUSPENDED: |
| 304 | // Activate the task. |
| 305 | it->second.state = PENDING; |
| 306 | break; |
[email protected] | 799d4ec | 2013-12-06 07:39:23 | [diff] [blame] | 307 | case PENDING: |
| 308 | // The same task will run, do nothing. |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 309 | return; |
[email protected] | 799d4ec | 2013-12-06 07:39:23 | [diff] [blame] | 310 | case RUNNING: |
| 311 | // Something has changed since the task started. Schedule rerun. |
| 312 | it->second.should_run_again = true; |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 313 | return; |
[email protected] | 799d4ec | 2013-12-06 07:39:23 | [diff] [blame] | 314 | } |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 315 | } else { |
| 316 | tasks_[key] = task; |
[email protected] | 799d4ec | 2013-12-06 07:39:23 | [diff] [blame] | 317 | } |
[email protected] | b5fc21d | 2013-11-27 09:06:29 | [diff] [blame] | 318 | DCHECK_EQ(PENDING, task.state); |
pranay.kumar | 229290b5 | 2015-05-14 05:21:04 | [diff] [blame] | 319 | base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
[email protected] | e07bbd97 | 2013-01-23 17:38:42 | [diff] [blame] | 320 | FROM_HERE, |
tzik | 2bcf8e4 | 2018-07-31 11:22:15 | [diff] [blame] | 321 | base::BindOnce(&SyncClient::StartTask, weak_ptr_factory_.GetWeakPtr(), |
| 322 | key), |
[email protected] | 9432bc3 | 2013-08-08 22:42:55 | [diff] [blame] | 323 | delay); |
[email protected] | e07bbd97 | 2013-01-23 17:38:42 | [diff] [blame] | 324 | } |
| 325 | |
[email protected] | b5fc21d | 2013-11-27 09:06:29 | [diff] [blame] | 326 | void SyncClient::StartTask(const SyncTasks::key_type& key) { |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 327 | ResourceEntry* parent = new ResourceEntry; |
| 328 | base::PostTaskAndReplyWithResult( |
| 329 | blocking_task_runner_.get(), |
| 330 | FROM_HERE, |
| 331 | base::Bind(&GetParentResourceEntry, metadata_, key.second, parent), |
| 332 | base::Bind(&SyncClient::StartTaskAfterGetParentResourceEntry, |
| 333 | weak_ptr_factory_.GetWeakPtr(), |
| 334 | key, |
| 335 | base::Owned(parent))); |
| 336 | } |
| 337 | |
| 338 | void SyncClient::StartTaskAfterGetParentResourceEntry( |
| 339 | const SyncTasks::key_type& key, |
| 340 | const ResourceEntry* parent, |
| 341 | FileError error) { |
| 342 | const SyncType type = key.first; |
| 343 | const std::string& local_id = key.second; |
[email protected] | b5fc21d | 2013-11-27 09:06:29 | [diff] [blame] | 344 | SyncTasks::iterator it = tasks_.find(key); |
| 345 | if (it == tasks_.end()) |
| 346 | return; |
[email protected] | e07bbd97 | 2013-01-23 17:38:42 | [diff] [blame] | 347 | |
[email protected] | b5fc21d | 2013-11-27 09:06:29 | [diff] [blame] | 348 | SyncTask* task = &it->second; |
| 349 | switch (task->state) { |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 350 | case SUSPENDED: |
[email protected] | b5fc21d | 2013-11-27 09:06:29 | [diff] [blame] | 351 | case PENDING: |
[email protected] | e07bbd97 | 2013-01-23 17:38:42 | [diff] [blame] | 352 | break; |
[email protected] | b5fc21d | 2013-11-27 09:06:29 | [diff] [blame] | 353 | case RUNNING: // Do nothing. |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 354 | return; |
[email protected] | e07bbd97 | 2013-01-23 17:38:42 | [diff] [blame] | 355 | } |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 356 | |
| 357 | if (error != FILE_ERROR_OK) { |
| 358 | OnTaskComplete(type, local_id, error); |
| 359 | return; |
| 360 | } |
| 361 | |
| 362 | if (type == UPDATE && |
| 363 | parent->resource_id().empty() && |
| 364 | parent->local_id() != util::kDriveTrashDirLocalId) { |
| 365 | // Parent entry needs to be synced to get a resource ID. |
| 366 | // Suspend the task and register it as a dependent task of the parent. |
| 367 | const SyncTasks::key_type key_parent(type, parent->local_id()); |
| 368 | SyncTasks::iterator it_parent = tasks_.find(key_parent); |
| 369 | if (it_parent == tasks_.end()) { |
| 370 | OnTaskComplete(type, local_id, FILE_ERROR_INVALID_OPERATION); |
| 371 | LOG(WARNING) << "Parent task not found: type = " << type << ", id = " |
| 372 | << local_id << ", parent_id = " << parent->local_id(); |
| 373 | return; |
| 374 | } |
| 375 | task->state = SUSPENDED; |
| 376 | it_parent->second.dependent_tasks.push_back(key); |
| 377 | return; |
| 378 | } |
| 379 | |
| 380 | // Run the task. |
| 381 | task->state = RUNNING; |
| 382 | task->cancel_closure = task->task.Run(task->context); |
[email protected] | b83e520 | 2012-06-27 07:50:24 | [diff] [blame] | 383 | } |
| 384 | |
[email protected] | c724115 | 2013-08-28 02:17:16 | [diff] [blame] | 385 | void SyncClient::OnGetLocalIdsOfBacklog( |
[email protected] | d68ede0 | 2012-11-07 14:30:53 | [diff] [blame] | 386 | const std::vector<std::string>* to_fetch, |
[email protected] | 5a1b0d1 | 2013-11-29 07:53:10 | [diff] [blame] | 387 | const std::vector<std::string>* to_update) { |
Stuart Langley | be403574 | 2018-05-10 05:32:27 | [diff] [blame] | 388 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
[email protected] | b83e520 | 2012-06-27 07:50:24 | [diff] [blame] | 389 | |
| 390 | // Give priority to upload tasks over fetch tasks, so that dirty files are |
| 391 | // uploaded as soon as possible. |
[email protected] | 5e273db | 2014-01-24 16:44:29 | [diff] [blame] | 392 | for (size_t i = 0; i < to_update->size(); ++i) { |
| 393 | const std::string& local_id = (*to_update)[i]; |
| 394 | DVLOG(1) << "Queuing to update: " << local_id; |
| 395 | AddUpdateTask(ClientContext(BACKGROUND), local_id); |
[email protected] | b83e520 | 2012-06-27 07:50:24 | [diff] [blame] | 396 | } |
| 397 | |
[email protected] | d68ede0 | 2012-11-07 14:30:53 | [diff] [blame] | 398 | for (size_t i = 0; i < to_fetch->size(); ++i) { |
[email protected] | c724115 | 2013-08-28 02:17:16 | [diff] [blame] | 399 | const std::string& local_id = (*to_fetch)[i]; |
| 400 | DVLOG(1) << "Queuing to fetch: " << local_id; |
[email protected] | b5fc21d | 2013-11-27 09:06:29 | [diff] [blame] | 401 | AddFetchTaskInternal(local_id, delay_); |
[email protected] | 92b84f33 | 2012-03-21 20:45:21 | [diff] [blame] | 402 | } |
| 403 | } |
| 404 | |
[email protected] | 0763527 | 2013-09-24 06:40:23 | [diff] [blame] | 405 | void SyncClient::AddFetchTasks(const std::vector<std::string>* local_ids) { |
Stuart Langley | be403574 | 2018-05-10 05:32:27 | [diff] [blame] | 406 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
[email protected] | 85b6219 | 2012-06-29 19:56:38 | [diff] [blame] | 407 | |
[email protected] | 0763527 | 2013-09-24 06:40:23 | [diff] [blame] | 408 | for (size_t i = 0; i < local_ids->size(); ++i) |
| 409 | AddFetchTask((*local_ids)[i]); |
[email protected] | 85b6219 | 2012-06-29 19:56:38 | [diff] [blame] | 410 | } |
| 411 | |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 412 | void SyncClient::OnTaskComplete(SyncType type, |
| 413 | const std::string& local_id, |
| 414 | FileError error) { |
Stuart Langley | be403574 | 2018-05-10 05:32:27 | [diff] [blame] | 415 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
[email protected] | 799d4ec | 2013-12-06 07:39:23 | [diff] [blame] | 416 | |
| 417 | const SyncTasks::key_type key(type, local_id); |
| 418 | SyncTasks::iterator it = tasks_.find(key); |
| 419 | DCHECK(it != tasks_.end()); |
| 420 | |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 421 | base::TimeDelta retry_delay = base::TimeDelta::FromSeconds(0); |
| 422 | |
| 423 | switch (error) { |
| 424 | case FILE_ERROR_OK: |
| 425 | DVLOG(1) << "Completed: type = " << type << ", id = " << local_id; |
| 426 | break; |
| 427 | case FILE_ERROR_ABORT: |
| 428 | // Ignore it because this is caused by user's cancel operations. |
| 429 | break; |
| 430 | case FILE_ERROR_NO_CONNECTION: |
| 431 | // Run the task again so that we'll retry once the connection is back. |
| 432 | it->second.should_run_again = true; |
| 433 | it->second.context = ClientContext(BACKGROUND); |
| 434 | break; |
| 435 | case FILE_ERROR_SERVICE_UNAVAILABLE: |
| 436 | // Run the task again so that we'll retry once the service is back. |
| 437 | it->second.should_run_again = true; |
| 438 | it->second.context = ClientContext(BACKGROUND); |
| 439 | retry_delay = long_delay_; |
[email protected] | 4ffef21 | 2014-07-24 02:33:18 | [diff] [blame] | 440 | operation_delegate_->OnDriveSyncError( |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 441 | file_system::DRIVE_SYNC_ERROR_SERVICE_UNAVAILABLE, local_id); |
| 442 | break; |
hirono | 51739e18 | 2015-09-14 06:08:14 | [diff] [blame] | 443 | case FILE_ERROR_NO_SERVER_SPACE: |
| 444 | operation_delegate_->OnDriveSyncError( |
| 445 | file_system::DRIVE_SYNC_ERROR_NO_SERVER_SPACE, local_id); |
| 446 | break; |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 447 | default: |
[email protected] | 4ffef21 | 2014-07-24 02:33:18 | [diff] [blame] | 448 | operation_delegate_->OnDriveSyncError( |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 449 | file_system::DRIVE_SYNC_ERROR_MISC, local_id); |
| 450 | LOG(WARNING) << "Failed: type = " << type << ", id = " << local_id |
| 451 | << ": " << FileErrorToString(error); |
[email protected] | 799d4ec | 2013-12-06 07:39:23 | [diff] [blame] | 452 | } |
| 453 | |
[email protected] | e849db5 | 2014-07-23 07:02:09 | [diff] [blame] | 454 | for (size_t i = 0; i < it->second.waiting_callbacks.size(); ++i) { |
pranay.kumar | 229290b5 | 2015-05-14 05:21:04 | [diff] [blame] | 455 | base::ThreadTaskRunnerHandle::Get()->PostTask( |
tzik | 2bcf8e4 | 2018-07-31 11:22:15 | [diff] [blame] | 456 | FROM_HERE, base::BindOnce(it->second.waiting_callbacks[i], error)); |
[email protected] | e849db5 | 2014-07-23 07:02:09 | [diff] [blame] | 457 | } |
| 458 | it->second.waiting_callbacks.clear(); |
| 459 | |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 460 | if (it->second.should_run_again) { |
| 461 | DVLOG(1) << "Running again: type = " << type << ", id = " << local_id; |
| 462 | it->second.state = PENDING; |
| 463 | it->second.should_run_again = false; |
pranay.kumar | 229290b5 | 2015-05-14 05:21:04 | [diff] [blame] | 464 | base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 465 | FROM_HERE, |
tzik | 2bcf8e4 | 2018-07-31 11:22:15 | [diff] [blame] | 466 | base::BindOnce(&SyncClient::StartTask, weak_ptr_factory_.GetWeakPtr(), |
| 467 | key), |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 468 | retry_delay); |
| 469 | } else { |
| 470 | for (size_t i = 0; i < it->second.dependent_tasks.size(); ++i) |
| 471 | StartTask(it->second.dependent_tasks[i]); |
| 472 | tasks_.erase(it); |
| 473 | } |
[email protected] | 799d4ec | 2013-12-06 07:39:23 | [diff] [blame] | 474 | } |
| 475 | |
[email protected] | c724115 | 2013-08-28 02:17:16 | [diff] [blame] | 476 | void SyncClient::OnFetchFileComplete(const std::string& local_id, |
[email protected] | d876d70b | 2013-04-23 20:06:15 | [diff] [blame] | 477 | FileError error, |
| 478 | const base::FilePath& local_path, |
dcheng | f4275023 | 2016-04-12 04:12:27 | [diff] [blame] | 479 | std::unique_ptr<ResourceEntry> entry) { |
Stuart Langley | be403574 | 2018-05-10 05:32:27 | [diff] [blame] | 480 | DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 481 | OnTaskComplete(FETCH, local_id, error); |
| 482 | if (error == FILE_ERROR_ABORT) { |
| 483 | // If user cancels download, unpin the file so that we do not sync the file |
| 484 | // again. |
[email protected] | 99bd543 | 2014-02-03 06:53:38 | [diff] [blame] | 485 | base::PostTaskAndReplyWithResult( |
Peter Kasting | 341e1fb | 2018-02-24 00:03:01 | [diff] [blame] | 486 | blocking_task_runner_.get(), FROM_HERE, |
[email protected] | 8bef9974 | 2014-07-18 10:43:15 | [diff] [blame] | 487 | base::Bind(&FileCache::Unpin, base::Unretained(cache_), local_id), |
Peter Kasting | 341e1fb | 2018-02-24 00:03:01 | [diff] [blame] | 488 | base::DoNothing::Repeatedly<FileError>()); |
[email protected] | 99bd543 | 2014-02-03 06:53:38 | [diff] [blame] | 489 | } |
| 490 | } |
| 491 | |
[email protected] | 4e87c486 | 2013-05-20 04:06:32 | [diff] [blame] | 492 | } // namespace internal |
[email protected] | d9d04df | 2012-10-12 07:06:35 | [diff] [blame] | 493 | } // namespace drive |