Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(204)

Side by Side Diff: chrome/browser/chromeos/drive/sync_client.cc

Issue 68543002: drive: Support offline delete (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Stop modifying local state after server side update Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/chromeos/drive/sync_client.h" 5 #include "chrome/browser/chromeos/drive/sync_client.h"
6 6
7 #include <vector> 7 #include <vector>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/message_loop/message_loop_proxy.h" 10 #include "base/message_loop/message_loop_proxy.h"
11 #include "chrome/browser/chromeos/drive/drive.pb.h" 11 #include "chrome/browser/chromeos/drive/drive.pb.h"
12 #include "chrome/browser/chromeos/drive/file_cache.h" 12 #include "chrome/browser/chromeos/drive/file_cache.h"
13 #include "chrome/browser/chromeos/drive/file_system/download_operation.h" 13 #include "chrome/browser/chromeos/drive/file_system/download_operation.h"
14 #include "chrome/browser/chromeos/drive/file_system/update_operation.h" 14 #include "chrome/browser/chromeos/drive/file_system/update_operation.h"
15 #include "chrome/browser/chromeos/drive/file_system_util.h" 15 #include "chrome/browser/chromeos/drive/file_system_util.h"
16 #include "chrome/browser/chromeos/drive/sync/remove_performer.h"
16 #include "chrome/browser/google_apis/task_util.h" 17 #include "chrome/browser/google_apis/task_util.h"
17 #include "content/public/browser/browser_thread.h" 18 #include "content/public/browser/browser_thread.h"
18 19
19 using content::BrowserThread; 20 using content::BrowserThread;
20 21
21 namespace drive { 22 namespace drive {
22 namespace internal { 23 namespace internal {
23 24
24 namespace { 25 namespace {
25 26
26 // The delay constant is used to delay processing a sync task. We should not 27 // The delay constant is used to delay processing a sync task. We should not
27 // process SyncTasks immediately for the following reasons: 28 // process SyncTasks immediately for the following reasons:
28 // 29 //
29 // 1) For fetching, the user may accidentally click on "Make available 30 // 1) For fetching, the user may accidentally click on "Make available
30 // offline" checkbox on a file, and immediately cancel it in a second. 31 // offline" checkbox on a file, and immediately cancel it in a second.
31 // It's a waste to fetch the file in this case. 32 // It's a waste to fetch the file in this case.
32 // 33 //
33 // 2) For uploading, file writing via HTML5 file system API is performed in 34 // 2) For uploading, file writing via HTML5 file system API is performed in
34 // two steps: 1) truncate a file to 0 bytes, 2) write contents. We 35 // two steps: 1) truncate a file to 0 bytes, 2) write contents. We
35 // shouldn't start uploading right after the step 1). Besides, the user 36 // shouldn't start uploading right after the step 1). Besides, the user
36 // may edit the same file repeatedly in a short period of time. 37 // may edit the same file repeatedly in a short period of time.
37 // 38 //
38 // TODO(satorux): We should find a way to handle the upload case more nicely, 39 // TODO(satorux): We should find a way to handle the upload case more nicely,
39 // and shorten the delay. crbug.com/134774 40 // and shorten the delay. crbug.com/134774
40 const int kDelaySeconds = 5; 41 const int kDelaySeconds = 5;
41 42
42 // The delay constant is used to delay retrying a sync task on server errors. 43 // The delay constant is used to delay retrying a sync task on server errors.
43 const int kLongDelaySeconds = 600; 44 const int kLongDelaySeconds = 600;
44 45
45 // Iterates cache entries and appends IDs to |to_fetch| if the file is pinned 46 // Iterates entries and appends IDs to |to_fetch| if the file is pinned but not
46 // but not fetched (not present locally), or to |to_upload| if the file is dirty 47 // fetched (not present locally), to |to_upload| if the file is dirty but not
47 // but not uploaded. 48 // uploaded, or to |to_remove| if the entry is in the trash.
48 void CollectBacklog(FileCache* cache, 49 void CollectBacklog(ResourceMetadata* metadata,
49 std::vector<std::string>* to_fetch, 50 std::vector<std::string>* to_fetch,
50 std::vector<std::string>* to_upload) { 51 std::vector<std::string>* to_upload,
52 std::vector<std::string>* to_remove) {
51 DCHECK(to_fetch); 53 DCHECK(to_fetch);
52 DCHECK(to_upload); 54 DCHECK(to_upload);
55 DCHECK(to_remove);
53 56
54 scoped_ptr<FileCache::Iterator> it = cache->GetIterator(); 57 scoped_ptr<ResourceMetadata::Iterator> it = metadata->GetIterator();
55 for (; !it->IsAtEnd(); it->Advance()) { 58 for (; !it->IsAtEnd(); it->Advance()) {
56 const FileCacheEntry& cache_entry = it->GetValue();
57 const std::string& local_id = it->GetID(); 59 const std::string& local_id = it->GetID();
58 if (cache_entry.is_pinned() && !cache_entry.is_present()) 60 const ResourceEntry& entry = it->GetValue();
59 to_fetch->push_back(local_id); 61 if (entry.parent_local_id() == util::kDriveTrashDirLocalId) {
62 to_remove->push_back(local_id);
63 continue;
64 }
60 65
61 if (cache_entry.is_dirty()) 66 FileCacheEntry cache_entry;
62 to_upload->push_back(local_id); 67 if (it->GetCacheEntry(&cache_entry)) {
68 if (cache_entry.is_pinned() && !cache_entry.is_present())
69 to_fetch->push_back(local_id);
70
71 if (cache_entry.is_dirty())
72 to_upload->push_back(local_id);
73 }
63 } 74 }
64 DCHECK(!it->HasError()); 75 DCHECK(!it->HasError());
65 } 76 }
66 77
67 // Iterates cache entries and collects IDs of ones with obsolete cache files. 78 // Iterates cache entries and collects IDs of ones with obsolete cache files.
68 void CheckExistingPinnedFiles(ResourceMetadata* metadata, 79 void CheckExistingPinnedFiles(ResourceMetadata* metadata,
69 FileCache* cache, 80 FileCache* cache,
70 std::vector<std::string>* local_ids) { 81 std::vector<std::string>* local_ids) {
71 scoped_ptr<FileCache::Iterator> it = cache->GetIterator(); 82 scoped_ptr<FileCache::Iterator> it = cache->GetIterator();
72 for (; !it->IsAtEnd(); it->Advance()) { 83 for (; !it->IsAtEnd(); it->Advance()) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 observer, 133 observer,
123 scheduler, 134 scheduler,
124 metadata, 135 metadata,
125 cache, 136 cache,
126 temporary_file_directory)), 137 temporary_file_directory)),
127 update_operation_(new file_system::UpdateOperation(blocking_task_runner, 138 update_operation_(new file_system::UpdateOperation(blocking_task_runner,
128 observer, 139 observer,
129 scheduler, 140 scheduler,
130 metadata, 141 metadata,
131 cache)), 142 cache)),
143 remove_performer_(new RemovePerformer(blocking_task_runner,
144 scheduler,
145 metadata)),
132 delay_(base::TimeDelta::FromSeconds(kDelaySeconds)), 146 delay_(base::TimeDelta::FromSeconds(kDelaySeconds)),
133 long_delay_(base::TimeDelta::FromSeconds(kLongDelaySeconds)), 147 long_delay_(base::TimeDelta::FromSeconds(kLongDelaySeconds)),
134 weak_ptr_factory_(this) { 148 weak_ptr_factory_(this) {
135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 149 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
136 } 150 }
137 151
138 SyncClient::~SyncClient() { 152 SyncClient::~SyncClient() {
139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 153 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
140 } 154 }
141 155
142 void SyncClient::StartProcessingBacklog() { 156 void SyncClient::StartProcessingBacklog() {
143 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
144 158
145 std::vector<std::string>* to_fetch = new std::vector<std::string>; 159 std::vector<std::string>* to_fetch = new std::vector<std::string>;
146 std::vector<std::string>* to_upload = new std::vector<std::string>; 160 std::vector<std::string>* to_upload = new std::vector<std::string>;
161 std::vector<std::string>* to_remove = new std::vector<std::string>;
147 blocking_task_runner_->PostTaskAndReply( 162 blocking_task_runner_->PostTaskAndReply(
148 FROM_HERE, 163 FROM_HERE,
149 base::Bind(&CollectBacklog, cache_, to_fetch, to_upload), 164 base::Bind(&CollectBacklog, metadata_, to_fetch, to_upload, to_remove),
150 base::Bind(&SyncClient::OnGetLocalIdsOfBacklog, 165 base::Bind(&SyncClient::OnGetLocalIdsOfBacklog,
151 weak_ptr_factory_.GetWeakPtr(), 166 weak_ptr_factory_.GetWeakPtr(),
152 base::Owned(to_fetch), 167 base::Owned(to_fetch),
153 base::Owned(to_upload))); 168 base::Owned(to_upload),
169 base::Owned(to_remove)));
154 } 170 }
155 171
156 void SyncClient::StartCheckingExistingPinnedFiles() { 172 void SyncClient::StartCheckingExistingPinnedFiles() {
157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 173 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
158 174
159 std::vector<std::string>* local_ids = new std::vector<std::string>; 175 std::vector<std::string>* local_ids = new std::vector<std::string>;
160 blocking_task_runner_->PostTaskAndReply( 176 blocking_task_runner_->PostTaskAndReply(
161 FROM_HERE, 177 FROM_HERE,
162 base::Bind(&CheckExistingPinnedFiles, 178 base::Bind(&CheckExistingPinnedFiles,
163 metadata_, 179 metadata_,
(...skipping 17 matching lines...) Expand all
181 pending_fetch_list_.erase(local_id); 197 pending_fetch_list_.erase(local_id);
182 } 198 }
183 199
184 void SyncClient::AddUploadTask(const ClientContext& context, 200 void SyncClient::AddUploadTask(const ClientContext& context,
185 const std::string& local_id) { 201 const std::string& local_id) {
186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 202 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
187 203
188 AddTaskToQueue(UPLOAD, context, local_id, delay_); 204 AddTaskToQueue(UPLOAD, context, local_id, delay_);
189 } 205 }
190 206
207 void SyncClient::AddRemoveTask(const std::string& local_id) {
208 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
209
210 DVLOG(1) << "Removing " << local_id;
211 remove_performer_->Remove(local_id,
212 base::Bind(&SyncClient::OnRemoveComplete,
213 weak_ptr_factory_.GetWeakPtr(),
214 local_id));
215 }
216
191 void SyncClient::AddTaskToQueue(SyncType type, 217 void SyncClient::AddTaskToQueue(SyncType type,
192 const ClientContext& context, 218 const ClientContext& context,
193 const std::string& local_id, 219 const std::string& local_id,
194 const base::TimeDelta& delay) { 220 const base::TimeDelta& delay) {
195 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
196 222
197 // If the same task is already queued, ignore this task. 223 // If the same task is already queued, ignore this task.
198 switch (type) { 224 switch (type) {
199 case FETCH: 225 case FETCH:
200 if (fetch_list_.find(local_id) == fetch_list_.end()) { 226 if (fetch_list_.find(local_id) == fetch_list_.end()) {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 check_mode, 287 check_mode,
262 base::Bind(&SyncClient::OnUploadFileComplete, 288 base::Bind(&SyncClient::OnUploadFileComplete,
263 weak_ptr_factory_.GetWeakPtr(), 289 weak_ptr_factory_.GetWeakPtr(),
264 local_id)); 290 local_id));
265 break; 291 break;
266 } 292 }
267 } 293 }
268 294
269 void SyncClient::OnGetLocalIdsOfBacklog( 295 void SyncClient::OnGetLocalIdsOfBacklog(
270 const std::vector<std::string>* to_fetch, 296 const std::vector<std::string>* to_fetch,
271 const std::vector<std::string>* to_upload) { 297 const std::vector<std::string>* to_upload,
298 const std::vector<std::string>* to_remove) {
272 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 299 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
273 300
274 // Give priority to upload tasks over fetch tasks, so that dirty files are 301 // Give priority to upload tasks over fetch tasks, so that dirty files are
275 // uploaded as soon as possible. 302 // uploaded as soon as possible.
276 for (size_t i = 0; i < to_upload->size(); ++i) { 303 for (size_t i = 0; i < to_upload->size(); ++i) {
277 const std::string& local_id = (*to_upload)[i]; 304 const std::string& local_id = (*to_upload)[i];
278 DVLOG(1) << "Queuing to upload: " << local_id; 305 DVLOG(1) << "Queuing to upload: " << local_id;
279 AddTaskToQueue(UPLOAD_RETRY, ClientContext(BACKGROUND), local_id, delay_); 306 AddTaskToQueue(UPLOAD_RETRY, ClientContext(BACKGROUND), local_id, delay_);
280 } 307 }
281 308
282 for (size_t i = 0; i < to_fetch->size(); ++i) { 309 for (size_t i = 0; i < to_fetch->size(); ++i) {
283 const std::string& local_id = (*to_fetch)[i]; 310 const std::string& local_id = (*to_fetch)[i];
284 DVLOG(1) << "Queuing to fetch: " << local_id; 311 DVLOG(1) << "Queuing to fetch: " << local_id;
285 AddTaskToQueue(FETCH, ClientContext(BACKGROUND), local_id, delay_); 312 AddTaskToQueue(FETCH, ClientContext(BACKGROUND), local_id, delay_);
286 } 313 }
314
315 for (size_t i = 0; i < to_remove->size(); ++i) {
316 const std::string& local_id = (*to_remove)[i];
317 DVLOG(1) << "Queuing to remove: " << local_id;
318 AddRemoveTask(local_id);
319 }
287 } 320 }
288 321
289 void SyncClient::AddFetchTasks(const std::vector<std::string>* local_ids) { 322 void SyncClient::AddFetchTasks(const std::vector<std::string>* local_ids) {
290 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 323 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
291 324
292 for (size_t i = 0; i < local_ids->size(); ++i) 325 for (size_t i = 0; i < local_ids->size(); ++i)
293 AddFetchTask((*local_ids)[i]); 326 AddFetchTask((*local_ids)[i]);
294 } 327 }
295 328
296 void SyncClient::OnFetchFileComplete(const std::string& local_id, 329 void SyncClient::OnFetchFileComplete(const std::string& local_id,
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 AddTaskToQueue(UPLOAD_RETRY, ClientContext(BACKGROUND), local_id, 379 AddTaskToQueue(UPLOAD_RETRY, ClientContext(BACKGROUND), local_id,
347 long_delay_); 380 long_delay_);
348 break; 381 break;
349 default: 382 default:
350 LOG(WARNING) << "Failed to upload " << local_id << ": " 383 LOG(WARNING) << "Failed to upload " << local_id << ": "
351 << FileErrorToString(error); 384 << FileErrorToString(error);
352 } 385 }
353 } 386 }
354 } 387 }
355 388
389 void SyncClient::OnRemoveComplete(const std::string& local_id,
390 FileError error) {
391 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
392
393 if (error == FILE_ERROR_OK) {
394 DVLOG(1) << "Removed " << local_id;
395 } else {
396 switch (error) {
397 case FILE_ERROR_NO_CONNECTION:
398 // Re-queue the task so that we'll retry once the connection is back.
399 AddRemoveTask(local_id);
400 break;
401 case FILE_ERROR_SERVICE_UNAVAILABLE:
402 // Re-queue the task so that we'll retry once the service is back.
403 base::MessageLoopProxy::current()->PostDelayedTask(
404 FROM_HERE,
405 base::Bind(&SyncClient::AddRemoveTask,
406 weak_ptr_factory_.GetWeakPtr(),
407 local_id),
408 long_delay_);
409 break;
410 default:
411 LOG(WARNING) << "Failed to remove " << local_id << ": "
412 << FileErrorToString(error);
413 }
414 }
415 }
416
356 } // namespace internal 417 } // namespace internal
357 } // namespace drive 418 } // namespace drive
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/drive/sync_client.h ('k') | chrome/browser/chromeos/drive/sync_client_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698