blob: 523d94e0dee95392b21398133520813c27bd65ee [file] [log] [blame]
[email protected]5051fdde2012-03-19 21:10:141// 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
yawano3513e142016-04-20 00:42:425#include "components/drive/chromeos/sync_client.h"
[email protected]5051fdde2012-03-19 21:10:146
avibc5337b2015-12-25 23:16:337#include <stddef.h>
8
[email protected]3653146a2012-05-29 13:41:479#include <vector>
10
[email protected]92b84f332012-03-21 20:45:2111#include "base/bind.h"
Sebastien Marchand17fa2782019-01-25 19:28:1012#include "base/bind_helpers.h"
gab7966d312016-05-11 20:35:0113#include "base/threading/thread_task_runner_handle.h"
yawano3513e142016-04-20 00:42:4214#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"
lukasza01b9d55a2015-07-21 15:19:2518#include "components/drive/drive.pb.h"
lukasza6364a022015-08-21 01:13:2419#include "components/drive/file_system_core_util.h"
lukaszab371ff4f2015-08-13 18:23:4720#include "components/drive/job_scheduler.h"
[email protected]e196bef32013-12-03 05:33:1321#include "google_apis/drive/task_util.h"
[email protected]92b84f332012-03-21 20:45:2122
[email protected]d9d04df2012-10-12 07:06:3523namespace drive {
[email protected]4e87c4862013-05-20 04:06:3224namespace internal {
[email protected]5051fdde2012-03-19 21:10:1425
[email protected]b83e5202012-06-27 07:50:2426namespace {
27
[email protected]e07bbd972013-01-23 17:38:4228// The delay constant is used to delay processing a sync task. We should not
29// process SyncTasks immediately for the following reasons:
[email protected]b83e5202012-06-27 07:50:2430//
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]f60c670b2012-09-13 06:19:2535// 2) For uploading, file writing via HTML5 file system API is performed in
[email protected]b83e5202012-06-27 07:50:2436// 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]0bbfb582014-02-10 07:33:3942const int kDelaySeconds = 1;
[email protected]b83e5202012-06-27 07:50:2443
[email protected]9432bc32013-08-08 22:42:5544// The delay constant is used to delay retrying a sync task on server errors.
45const int kLongDelaySeconds = 600;
46
[email protected]562af1c12013-11-26 10:27:5347// Iterates entries and appends IDs to |to_fetch| if the file is pinned but not
[email protected]5e273db2014-01-24 16:44:2948// fetched (not present locally), to |to_update| if the file needs update.
[email protected]562af1c12013-11-26 10:27:5349void CollectBacklog(ResourceMetadata* metadata,
[email protected]07635272013-09-24 06:40:2350 std::vector<std::string>* to_fetch,
[email protected]5a1b0d12013-11-29 07:53:1051 std::vector<std::string>* to_update) {
[email protected]d68ede02012-11-07 14:30:5352 DCHECK(to_fetch);
[email protected]5a1b0d12013-11-29 07:53:1053 DCHECK(to_update);
[email protected]d68ede02012-11-07 14:30:5354
dchengf42750232016-04-12 04:12:2755 std::unique_ptr<ResourceMetadata::Iterator> it = metadata->GetIterator();
[email protected]07635272013-09-24 06:40:2356 for (; !it->IsAtEnd(); it->Advance()) {
[email protected]07635272013-09-24 06:40:2357 const std::string& local_id = it->GetID();
[email protected]562af1c12013-11-26 10:27:5358 const ResourceEntry& entry = it->GetValue();
59 if (entry.parent_local_id() == util::kDriveTrashDirLocalId) {
[email protected]5a1b0d12013-11-29 07:53:1060 to_update->push_back(local_id);
[email protected]562af1c12013-11-26 10:27:5361 continue;
62 }
[email protected]d68ede02012-11-07 14:30:5363
[email protected]5e273db2014-01-24 16:44:2964 bool should_update = false;
[email protected]5170a132013-12-02 10:35:1365 switch (entry.metadata_edit_state()) {
66 case ResourceEntry::CLEAN:
67 break;
68 case ResourceEntry::SYNCING:
69 case ResourceEntry::DIRTY:
[email protected]5e273db2014-01-24 16:44:2970 should_update = true;
[email protected]5170a132013-12-02 10:35:1371 break;
72 }
73
[email protected]52525f82014-05-14 04:30:3074 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]562af1c12013-11-26 10:27:5377
[email protected]52525f82014-05-14 04:30:3078 if (entry.file_specific_info().cache_state().is_dirty())
79 should_update = true;
80
[email protected]5e273db2014-01-24 16:44:2981 if (should_update)
82 to_update->push_back(local_id);
[email protected]07635272013-09-24 06:40:2383 }
84 DCHECK(!it->HasError());
85}
86
87// Iterates cache entries and collects IDs of ones with obsolete cache files.
88void CheckExistingPinnedFiles(ResourceMetadata* metadata,
89 FileCache* cache,
90 std::vector<std::string>* local_ids) {
dchengf42750232016-04-12 04:12:2791 std::unique_ptr<ResourceMetadata::Iterator> it = metadata->GetIterator();
[email protected]07635272013-09-24 06:40:2392 for (; !it->IsAtEnd(); it->Advance()) {
[email protected]0c53f982014-05-15 05:51:3593 const ResourceEntry& entry = it->GetValue();
94 const FileCacheEntry& cache_state =
95 entry.file_specific_info().cache_state();
[email protected]07635272013-09-24 06:40:2396 const std::string& local_id = it->GetID();
[email protected]0c53f982014-05-15 05:51:3597 if (!cache_state.is_pinned() || !cache_state.is_present())
[email protected]07635272013-09-24 06:40:2398 continue;
99
[email protected]07635272013-09-24 06:40:23100 // 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]0c53f982014-05-15 05:51:35103 if (entry.file_specific_info().md5() == cache_state.md5() ||
104 cache_state.is_dirty())
[email protected]07635272013-09-24 06:40:23105 continue;
106
[email protected]0c53f982014-05-15 05:51:35107 FileError error = cache->Remove(local_id);
[email protected]07635272013-09-24 06:40:23108 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]d68ede02012-11-07 14:30:53122}
123
[email protected]8bef99742014-07-18 10:43:15124// Gets the parent entry of the entry specified by the ID.
125FileError 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]0167ff02014-03-28 17:22:23133}
134
[email protected]b83e5202012-06-27 07:50:24135} // namespace
136
[email protected]8bef99742014-07-18 10:43:15137SyncClient::SyncTask::SyncTask()
138 : state(SUSPENDED), context(BACKGROUND), should_run_again(false) {}
vmpstrb6449d512016-02-25 23:55:40139SyncClient::SyncTask::SyncTask(const SyncTask& other) = default;
Stuart Langleybe4035742018-05-10 05:32:27140SyncClient::SyncTask::~SyncTask() = default;
[email protected]b5fc21d2013-11-27 09:06:29141
[email protected]b568b882013-06-10 04:38:07142SyncClient::SyncClient(base::SequencedTaskRunner* blocking_task_runner,
[email protected]4ffef212014-07-24 02:33:18143 file_system::OperationDelegate* delegate,
[email protected]b568b882013-06-10 04:38:07144 JobScheduler* scheduler,
145 ResourceMetadata* metadata,
[email protected]e07f7b7b2013-06-19 03:43:12146 FileCache* cache,
[email protected]20f33e62014-01-30 10:50:39147 LoaderController* loader_controller,
[email protected]e07f7b7b2013-06-19 03:43:12148 const base::FilePath& temporary_file_directory)
[email protected]07635272013-09-24 06:40:23149 : blocking_task_runner_(blocking_task_runner),
[email protected]4ffef212014-07-24 02:33:18150 operation_delegate_(delegate),
[email protected]07635272013-09-24 06:40:23151 metadata_(metadata),
[email protected]e0529fc2012-06-12 11:07:58152 cache_(cache),
Jeremy Roman47d432e2019-08-20 14:24:00153 download_operation_(
154 new file_system::DownloadOperation(blocking_task_runner,
155 delegate,
156 scheduler,
157 metadata,
158 cache,
159 temporary_file_directory)),
[email protected]5a1b0d12013-11-29 07:53:10160 entry_update_performer_(new EntryUpdatePerformer(blocking_task_runner,
[email protected]4ffef212014-07-24 02:33:18161 delegate,
[email protected]5a1b0d12013-11-29 07:53:10162 scheduler,
[email protected]5e273db2014-01-24 16:44:29163 metadata,
[email protected]069011f2014-01-29 07:56:59164 cache,
[email protected]20f33e62014-01-30 10:50:39165 loader_controller)),
[email protected]b83e5202012-06-27 07:50:24166 delay_(base::TimeDelta::FromSeconds(kDelaySeconds)),
Jeremy Roman47d432e2019-08-20 14:24:00167 long_delay_(base::TimeDelta::FromSeconds(kLongDelaySeconds)) {}
[email protected]5051fdde2012-03-19 21:10:14168
[email protected]d876d70b2013-04-23 20:06:15169SyncClient::~SyncClient() {
Stuart Langleybe4035742018-05-10 05:32:27170 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
[email protected]5051fdde2012-03-19 21:10:14171}
172
[email protected]d876d70b2013-04-23 20:06:15173void SyncClient::StartProcessingBacklog() {
Stuart Langleybe4035742018-05-10 05:32:27174 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
[email protected]b83e5202012-06-27 07:50:24175
[email protected]d68ede02012-11-07 14:30:53176 std::vector<std::string>* to_fetch = new std::vector<std::string>;
[email protected]5e273db2014-01-24 16:44:29177 std::vector<std::string>* to_update = new std::vector<std::string>;
[email protected]07635272013-09-24 06:40:23178 blocking_task_runner_->PostTaskAndReply(
179 FROM_HERE,
tzik2bcf8e42018-07-31 11:22:15180 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]92b84f332012-03-21 20:45:21184}
185
[email protected]d876d70b2013-04-23 20:06:15186void SyncClient::StartCheckingExistingPinnedFiles() {
Stuart Langleybe4035742018-05-10 05:32:27187 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
[email protected]85b62192012-06-29 19:56:38188
[email protected]07635272013-09-24 06:40:23189 std::vector<std::string>* local_ids = new std::vector<std::string>;
190 blocking_task_runner_->PostTaskAndReply(
191 FROM_HERE,
tzik2bcf8e42018-07-31 11:22:15192 base::BindOnce(&CheckExistingPinnedFiles, metadata_, cache_, local_ids),
193 base::BindOnce(&SyncClient::AddFetchTasks, weak_ptr_factory_.GetWeakPtr(),
194 base::Owned(local_ids)));
[email protected]85b62192012-06-29 19:56:38195}
196
[email protected]c7241152013-08-28 02:17:16197void SyncClient::AddFetchTask(const std::string& local_id) {
Stuart Langleybe4035742018-05-10 05:32:27198 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
[email protected]b5fc21d2013-11-27 09:06:29199 AddFetchTaskInternal(local_id, delay_);
[email protected]6bf581142013-06-11 17:13:06200}
201
[email protected]c7241152013-08-28 02:17:16202void SyncClient::RemoveFetchTask(const std::string& local_id) {
Stuart Langleybe4035742018-05-10 05:32:27203 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
[email protected]bd2254d2013-06-12 16:00:47204
[email protected]b5fc21d2013-11-27 09:06:29205 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]8bef99742014-07-18 10:43:15211 case SUSPENDED:
[email protected]b5fc21d2013-11-27 09:06:29212 case PENDING:
[email protected]8bef99742014-07-18 10:43:15213 OnTaskComplete(FETCH, local_id, FILE_ERROR_ABORT);
[email protected]b5fc21d2013-11-27 09:06:29214 break;
215 case RUNNING:
Stuart Langleybe4035742018-05-10 05:32:27216 if (task->cancel_closure)
[email protected]551e9df2014-02-10 13:22:18217 task->cancel_closure.Run();
[email protected]b5fc21d2013-11-27 09:06:29218 break;
219 }
[email protected]bd2254d2013-06-12 16:00:47220}
221
[email protected]0f7477f82014-01-23 09:39:09222void SyncClient::AddUpdateTask(const ClientContext& context,
223 const std::string& local_id) {
Stuart Langleybe4035742018-05-10 05:32:27224 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
[email protected]5e273db2014-01-24 16:44:29225 AddUpdateTaskInternal(context, local_id, delay_);
[email protected]562af1c12013-11-26 10:27:53226}
227
[email protected]e849db52014-07-23 07:02:09228bool SyncClient:: WaitForUpdateTaskToComplete(
229 const std::string& local_id,
230 const FileOperationCallback& callback) {
Stuart Langleybe4035742018-05-10 05:32:27231 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
[email protected]e849db52014-07-23 07:02:09232
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]8bef99742014-07-18 10:43:15242base::Closure SyncClient::PerformFetchTask(const std::string& local_id,
243 const ClientContext& context) {
Stuart Langleybe4035742018-05-10 05:32:27244 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
[email protected]8bef99742014-07-18 10:43:15245 return download_operation_->EnsureFileDownloadedByLocalId(
[email protected]b5fc21d2013-11-27 09:06:29246 local_id,
[email protected]8bef99742014-07-18 10:43:15247 context,
[email protected]0167ff02014-03-28 17:22:23248 GetFileContentInitializedCallback(),
[email protected]b5fc21d2013-11-27 09:06:29249 google_apis::GetContentCallback(),
250 base::Bind(&SyncClient::OnFetchFileComplete,
251 weak_ptr_factory_.GetWeakPtr(),
252 local_id));
[email protected]8bef99742014-07-18 10:43:15253}
254
255void SyncClient::AddFetchTaskInternal(const std::string& local_id,
256 const base::TimeDelta& delay) {
Stuart Langleybe4035742018-05-10 05:32:27257 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
[email protected]8bef99742014-07-18 10:43:15258
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]b5fc21d2013-11-27 09:06:29265 AddTask(SyncTasks::key_type(FETCH, local_id), task, delay);
266}
267
[email protected]8bef99742014-07-18 10:43:15268base::Closure SyncClient::PerformUpdateTask(const std::string& local_id,
269 const ClientContext& context) {
Stuart Langleybe4035742018-05-10 05:32:27270 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
[email protected]8bef99742014-07-18 10:43:15271 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]0f7477f82014-01-23 09:39:09281void SyncClient::AddUpdateTaskInternal(const ClientContext& context,
282 const std::string& local_id,
[email protected]c742facc2013-11-27 13:44:20283 const base::TimeDelta& delay) {
Stuart Langleybe4035742018-05-10 05:32:27284 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
[email protected]8bef99742014-07-18 10:43:15285
[email protected]c742facc2013-11-27 13:44:20286 SyncTask task;
[email protected]8bef99742014-07-18 10:43:15287 task.state = PENDING;
288 task.context = context;
289 task.task = base::Bind(&SyncClient::PerformUpdateTask,
290 base::Unretained(this),
291 local_id);
[email protected]5a1b0d12013-11-29 07:53:10292 AddTask(SyncTasks::key_type(UPDATE, local_id), task, delay);
[email protected]c742facc2013-11-27 13:44:20293}
294
[email protected]b5fc21d2013-11-27 09:06:29295void SyncClient::AddTask(const SyncTasks::key_type& key,
296 const SyncTask& task,
297 const base::TimeDelta& delay) {
Stuart Langleybe4035742018-05-10 05:32:27298 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
[email protected]b5fc21d2013-11-27 09:06:29299
[email protected]799d4ec2013-12-06 07:39:23300 SyncTasks::iterator it = tasks_.find(key);
301 if (it != tasks_.end()) {
302 switch (it->second.state) {
[email protected]8bef99742014-07-18 10:43:15303 case SUSPENDED:
304 // Activate the task.
305 it->second.state = PENDING;
306 break;
[email protected]799d4ec2013-12-06 07:39:23307 case PENDING:
308 // The same task will run, do nothing.
[email protected]8bef99742014-07-18 10:43:15309 return;
[email protected]799d4ec2013-12-06 07:39:23310 case RUNNING:
311 // Something has changed since the task started. Schedule rerun.
312 it->second.should_run_again = true;
[email protected]8bef99742014-07-18 10:43:15313 return;
[email protected]799d4ec2013-12-06 07:39:23314 }
[email protected]8bef99742014-07-18 10:43:15315 } else {
316 tasks_[key] = task;
[email protected]799d4ec2013-12-06 07:39:23317 }
[email protected]b5fc21d2013-11-27 09:06:29318 DCHECK_EQ(PENDING, task.state);
pranay.kumar229290b52015-05-14 05:21:04319 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
[email protected]e07bbd972013-01-23 17:38:42320 FROM_HERE,
tzik2bcf8e42018-07-31 11:22:15321 base::BindOnce(&SyncClient::StartTask, weak_ptr_factory_.GetWeakPtr(),
322 key),
[email protected]9432bc32013-08-08 22:42:55323 delay);
[email protected]e07bbd972013-01-23 17:38:42324}
325
[email protected]b5fc21d2013-11-27 09:06:29326void SyncClient::StartTask(const SyncTasks::key_type& key) {
[email protected]8bef99742014-07-18 10:43:15327 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
338void 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]b5fc21d2013-11-27 09:06:29344 SyncTasks::iterator it = tasks_.find(key);
345 if (it == tasks_.end())
346 return;
[email protected]e07bbd972013-01-23 17:38:42347
[email protected]b5fc21d2013-11-27 09:06:29348 SyncTask* task = &it->second;
349 switch (task->state) {
[email protected]8bef99742014-07-18 10:43:15350 case SUSPENDED:
[email protected]b5fc21d2013-11-27 09:06:29351 case PENDING:
[email protected]e07bbd972013-01-23 17:38:42352 break;
[email protected]b5fc21d2013-11-27 09:06:29353 case RUNNING: // Do nothing.
[email protected]8bef99742014-07-18 10:43:15354 return;
[email protected]e07bbd972013-01-23 17:38:42355 }
[email protected]8bef99742014-07-18 10:43:15356
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]b83e5202012-06-27 07:50:24383}
384
[email protected]c7241152013-08-28 02:17:16385void SyncClient::OnGetLocalIdsOfBacklog(
[email protected]d68ede02012-11-07 14:30:53386 const std::vector<std::string>* to_fetch,
[email protected]5a1b0d12013-11-29 07:53:10387 const std::vector<std::string>* to_update) {
Stuart Langleybe4035742018-05-10 05:32:27388 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
[email protected]b83e5202012-06-27 07:50:24389
390 // Give priority to upload tasks over fetch tasks, so that dirty files are
391 // uploaded as soon as possible.
[email protected]5e273db2014-01-24 16:44:29392 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]b83e5202012-06-27 07:50:24396 }
397
[email protected]d68ede02012-11-07 14:30:53398 for (size_t i = 0; i < to_fetch->size(); ++i) {
[email protected]c7241152013-08-28 02:17:16399 const std::string& local_id = (*to_fetch)[i];
400 DVLOG(1) << "Queuing to fetch: " << local_id;
[email protected]b5fc21d2013-11-27 09:06:29401 AddFetchTaskInternal(local_id, delay_);
[email protected]92b84f332012-03-21 20:45:21402 }
403}
404
[email protected]07635272013-09-24 06:40:23405void SyncClient::AddFetchTasks(const std::vector<std::string>* local_ids) {
Stuart Langleybe4035742018-05-10 05:32:27406 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
[email protected]85b62192012-06-29 19:56:38407
[email protected]07635272013-09-24 06:40:23408 for (size_t i = 0; i < local_ids->size(); ++i)
409 AddFetchTask((*local_ids)[i]);
[email protected]85b62192012-06-29 19:56:38410}
411
[email protected]8bef99742014-07-18 10:43:15412void SyncClient::OnTaskComplete(SyncType type,
413 const std::string& local_id,
414 FileError error) {
Stuart Langleybe4035742018-05-10 05:32:27415 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
[email protected]799d4ec2013-12-06 07:39:23416
417 const SyncTasks::key_type key(type, local_id);
418 SyncTasks::iterator it = tasks_.find(key);
419 DCHECK(it != tasks_.end());
420
[email protected]8bef99742014-07-18 10:43:15421 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]4ffef212014-07-24 02:33:18440 operation_delegate_->OnDriveSyncError(
[email protected]8bef99742014-07-18 10:43:15441 file_system::DRIVE_SYNC_ERROR_SERVICE_UNAVAILABLE, local_id);
442 break;
hirono51739e182015-09-14 06:08:14443 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]8bef99742014-07-18 10:43:15447 default:
[email protected]4ffef212014-07-24 02:33:18448 operation_delegate_->OnDriveSyncError(
[email protected]8bef99742014-07-18 10:43:15449 file_system::DRIVE_SYNC_ERROR_MISC, local_id);
450 LOG(WARNING) << "Failed: type = " << type << ", id = " << local_id
451 << ": " << FileErrorToString(error);
[email protected]799d4ec2013-12-06 07:39:23452 }
453
[email protected]e849db52014-07-23 07:02:09454 for (size_t i = 0; i < it->second.waiting_callbacks.size(); ++i) {
pranay.kumar229290b52015-05-14 05:21:04455 base::ThreadTaskRunnerHandle::Get()->PostTask(
tzik2bcf8e42018-07-31 11:22:15456 FROM_HERE, base::BindOnce(it->second.waiting_callbacks[i], error));
[email protected]e849db52014-07-23 07:02:09457 }
458 it->second.waiting_callbacks.clear();
459
[email protected]8bef99742014-07-18 10:43:15460 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.kumar229290b52015-05-14 05:21:04464 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
[email protected]8bef99742014-07-18 10:43:15465 FROM_HERE,
tzik2bcf8e42018-07-31 11:22:15466 base::BindOnce(&SyncClient::StartTask, weak_ptr_factory_.GetWeakPtr(),
467 key),
[email protected]8bef99742014-07-18 10:43:15468 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]799d4ec2013-12-06 07:39:23474}
475
[email protected]c7241152013-08-28 02:17:16476void SyncClient::OnFetchFileComplete(const std::string& local_id,
[email protected]d876d70b2013-04-23 20:06:15477 FileError error,
478 const base::FilePath& local_path,
dchengf42750232016-04-12 04:12:27479 std::unique_ptr<ResourceEntry> entry) {
Stuart Langleybe4035742018-05-10 05:32:27480 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
[email protected]8bef99742014-07-18 10:43:15481 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]99bd5432014-02-03 06:53:38485 base::PostTaskAndReplyWithResult(
Peter Kasting341e1fb2018-02-24 00:03:01486 blocking_task_runner_.get(), FROM_HERE,
[email protected]8bef99742014-07-18 10:43:15487 base::Bind(&FileCache::Unpin, base::Unretained(cache_), local_id),
Peter Kasting341e1fb2018-02-24 00:03:01488 base::DoNothing::Repeatedly<FileError>());
[email protected]99bd5432014-02-03 06:53:38489 }
490}
491
[email protected]4e87c4862013-05-20 04:06:32492} // namespace internal
[email protected]d9d04df2012-10-12 07:06:35493} // namespace drive