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

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: Move to drive/other and mark as deleted Created 7 years, 1 month 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 locally deleted.
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::kDriveOtherDirLocalId &&
62 entry.deleted())
63 to_remove->push_back(local_id);
kinaba 2013/11/12 06:21:29 Probably we don't want to, say, fetch a pinned and
hashimoto 2013/11/25 10:13:58 Done.
60 64
61 if (cache_entry.is_dirty()) 65 FileCacheEntry cache_entry;
62 to_upload->push_back(local_id); 66 if (it->GetCacheEntry(&cache_entry)) {
67 if (cache_entry.is_pinned() && !cache_entry.is_present())
68 to_fetch->push_back(local_id);
69
70 if (cache_entry.is_dirty())
71 to_upload->push_back(local_id);
72 }
63 } 73 }
64 DCHECK(!it->HasError()); 74 DCHECK(!it->HasError());
65 } 75 }
66 76
67 // Iterates cache entries and collects IDs of ones with obsolete cache files. 77 // Iterates cache entries and collects IDs of ones with obsolete cache files.
68 void CheckExistingPinnedFiles(ResourceMetadata* metadata, 78 void CheckExistingPinnedFiles(ResourceMetadata* metadata,
69 FileCache* cache, 79 FileCache* cache,
70 std::vector<std::string>* local_ids) { 80 std::vector<std::string>* local_ids) {
71 scoped_ptr<FileCache::Iterator> it = cache->GetIterator(); 81 scoped_ptr<FileCache::Iterator> it = cache->GetIterator();
72 for (; !it->IsAtEnd(); it->Advance()) { 82 for (; !it->IsAtEnd(); it->Advance()) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 observer, 132 observer,
123 scheduler, 133 scheduler,
124 metadata, 134 metadata,
125 cache, 135 cache,
126 temporary_file_directory)), 136 temporary_file_directory)),
127 update_operation_(new file_system::UpdateOperation(blocking_task_runner, 137 update_operation_(new file_system::UpdateOperation(blocking_task_runner,
128 observer, 138 observer,
129 scheduler, 139 scheduler,
130 metadata, 140 metadata,
131 cache)), 141 cache)),
142 remove_performer_(new RemovePerformer(blocking_task_runner,
143 scheduler,
144 metadata)),
132 delay_(base::TimeDelta::FromSeconds(kDelaySeconds)), 145 delay_(base::TimeDelta::FromSeconds(kDelaySeconds)),
133 long_delay_(base::TimeDelta::FromSeconds(kLongDelaySeconds)), 146 long_delay_(base::TimeDelta::FromSeconds(kLongDelaySeconds)),
134 weak_ptr_factory_(this) { 147 weak_ptr_factory_(this) {
135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 148 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
136 } 149 }
137 150
138 SyncClient::~SyncClient() { 151 SyncClient::~SyncClient() {
139 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 152 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
140 } 153 }
141 154
142 void SyncClient::StartProcessingBacklog() { 155 void SyncClient::StartProcessingBacklog() {
143 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
144 157
145 std::vector<std::string>* to_fetch = new std::vector<std::string>; 158 std::vector<std::string>* to_fetch = new std::vector<std::string>;
146 std::vector<std::string>* to_upload = new std::vector<std::string>; 159 std::vector<std::string>* to_upload = new std::vector<std::string>;
160 std::vector<std::string>* to_remove = new std::vector<std::string>;
147 blocking_task_runner_->PostTaskAndReply( 161 blocking_task_runner_->PostTaskAndReply(
148 FROM_HERE, 162 FROM_HERE,
149 base::Bind(&CollectBacklog, cache_, to_fetch, to_upload), 163 base::Bind(&CollectBacklog, metadata_, to_fetch, to_upload, to_remove),
150 base::Bind(&SyncClient::OnGetLocalIdsOfBacklog, 164 base::Bind(&SyncClient::OnGetLocalIdsOfBacklog,
151 weak_ptr_factory_.GetWeakPtr(), 165 weak_ptr_factory_.GetWeakPtr(),
152 base::Owned(to_fetch), 166 base::Owned(to_fetch),
153 base::Owned(to_upload))); 167 base::Owned(to_upload),
168 base::Owned(to_remove)));
154 } 169 }
155 170
156 void SyncClient::StartCheckingExistingPinnedFiles() { 171 void SyncClient::StartCheckingExistingPinnedFiles() {
157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
158 173
159 std::vector<std::string>* local_ids = new std::vector<std::string>; 174 std::vector<std::string>* local_ids = new std::vector<std::string>;
160 blocking_task_runner_->PostTaskAndReply( 175 blocking_task_runner_->PostTaskAndReply(
161 FROM_HERE, 176 FROM_HERE,
162 base::Bind(&CheckExistingPinnedFiles, 177 base::Bind(&CheckExistingPinnedFiles,
163 metadata_, 178 metadata_,
(...skipping 16 matching lines...) Expand all
180 // TODO(kinaba): Cancel tasks in JobScheduler as well. crbug.com/248856 195 // TODO(kinaba): Cancel tasks in JobScheduler as well. crbug.com/248856
181 pending_fetch_list_.erase(local_id); 196 pending_fetch_list_.erase(local_id);
182 } 197 }
183 198
184 void SyncClient::AddUploadTask(const std::string& local_id) { 199 void SyncClient::AddUploadTask(const std::string& local_id) {
185 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 200 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
186 201
187 AddTaskToQueue(UPLOAD, local_id, delay_); 202 AddTaskToQueue(UPLOAD, local_id, delay_);
188 } 203 }
189 204
205 void SyncClient::AddRemoveTask(const std::string& local_id) {
206 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
207
208 DVLOG(1) << "Removing " << local_id;
209 remove_performer_->Remove(local_id,
210 base::Bind(&SyncClient::OnRemoveComplete,
211 weak_ptr_factory_.GetWeakPtr(),
212 local_id));
213 }
214
190 void SyncClient::AddTaskToQueue(SyncType type, 215 void SyncClient::AddTaskToQueue(SyncType type,
191 const std::string& local_id, 216 const std::string& local_id,
192 const base::TimeDelta& delay) { 217 const base::TimeDelta& delay) {
193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 218 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
194 219
195 // If the same task is already queued, ignore this task. 220 // If the same task is already queued, ignore this task.
196 switch (type) { 221 switch (type) {
197 case FETCH: 222 case FETCH:
198 if (fetch_list_.find(local_id) == fetch_list_.end()) { 223 if (fetch_list_.find(local_id) == fetch_list_.end()) {
199 fetch_list_.insert(local_id); 224 fetch_list_.insert(local_id);
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 : file_system::UpdateOperation::NO_CONTENT_CHECK, 277 : file_system::UpdateOperation::NO_CONTENT_CHECK,
253 base::Bind(&SyncClient::OnUploadFileComplete, 278 base::Bind(&SyncClient::OnUploadFileComplete,
254 weak_ptr_factory_.GetWeakPtr(), 279 weak_ptr_factory_.GetWeakPtr(),
255 local_id)); 280 local_id));
256 break; 281 break;
257 } 282 }
258 } 283 }
259 284
260 void SyncClient::OnGetLocalIdsOfBacklog( 285 void SyncClient::OnGetLocalIdsOfBacklog(
261 const std::vector<std::string>* to_fetch, 286 const std::vector<std::string>* to_fetch,
262 const std::vector<std::string>* to_upload) { 287 const std::vector<std::string>* to_upload,
288 const std::vector<std::string>* to_remove) {
263 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 289 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
264 290
265 // Give priority to upload tasks over fetch tasks, so that dirty files are 291 // Give priority to upload tasks over fetch tasks, so that dirty files are
266 // uploaded as soon as possible. 292 // uploaded as soon as possible.
267 for (size_t i = 0; i < to_upload->size(); ++i) { 293 for (size_t i = 0; i < to_upload->size(); ++i) {
268 const std::string& local_id = (*to_upload)[i]; 294 const std::string& local_id = (*to_upload)[i];
269 DVLOG(1) << "Queuing to upload: " << local_id; 295 DVLOG(1) << "Queuing to upload: " << local_id;
270 AddTaskToQueue(UPLOAD_NO_CONTENT_CHECK, local_id, delay_); 296 AddTaskToQueue(UPLOAD_NO_CONTENT_CHECK, local_id, delay_);
271 } 297 }
272 298
273 for (size_t i = 0; i < to_fetch->size(); ++i) { 299 for (size_t i = 0; i < to_fetch->size(); ++i) {
274 const std::string& local_id = (*to_fetch)[i]; 300 const std::string& local_id = (*to_fetch)[i];
275 DVLOG(1) << "Queuing to fetch: " << local_id; 301 DVLOG(1) << "Queuing to fetch: " << local_id;
276 AddTaskToQueue(FETCH, local_id, delay_); 302 AddTaskToQueue(FETCH, local_id, delay_);
277 } 303 }
304
305 for (size_t i = 0; i < to_remove->size(); ++i) {
306 const std::string& local_id = (*to_remove)[i];
307 DVLOG(1) << "Queuing to remove: " << local_id;
308 AddRemoveTask(local_id);
309 }
278 } 310 }
279 311
280 void SyncClient::AddFetchTasks(const std::vector<std::string>* local_ids) { 312 void SyncClient::AddFetchTasks(const std::vector<std::string>* local_ids) {
281 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 313 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
282 314
283 for (size_t i = 0; i < local_ids->size(); ++i) 315 for (size_t i = 0; i < local_ids->size(); ++i)
284 AddFetchTask((*local_ids)[i]); 316 AddFetchTask((*local_ids)[i]);
285 } 317 }
286 318
287 void SyncClient::OnFetchFileComplete(const std::string& local_id, 319 void SyncClient::OnFetchFileComplete(const std::string& local_id,
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
335 // Re-queue the task so that we'll retry once the service is back. 367 // Re-queue the task so that we'll retry once the service is back.
336 AddTaskToQueue(UPLOAD_NO_CONTENT_CHECK, local_id, long_delay_); 368 AddTaskToQueue(UPLOAD_NO_CONTENT_CHECK, local_id, long_delay_);
337 break; 369 break;
338 default: 370 default:
339 LOG(WARNING) << "Failed to upload " << local_id << ": " 371 LOG(WARNING) << "Failed to upload " << local_id << ": "
340 << FileErrorToString(error); 372 << FileErrorToString(error);
341 } 373 }
342 } 374 }
343 } 375 }
344 376
377 void SyncClient::OnRemoveComplete(const std::string& local_id,
378 FileError error) {
379 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
380
381 if (error == FILE_ERROR_OK) {
382 DVLOG(1) << "Removed " << local_id;
383 } else {
384 switch (error) {
385 case FILE_ERROR_NO_CONNECTION:
386 // Re-queue the task so that we'll retry once the connection is back.
387 AddRemoveTask(local_id);
388 break;
389 case FILE_ERROR_SERVICE_UNAVAILABLE:
390 // Re-queue the task so that we'll retry once the service is back.
391 AddRemoveTask(local_id);
kinaba 2013/11/12 06:21:29 AddTaskToQueue posts the task after a long_delay_,
hashimoto 2013/11/25 10:13:58 Done.
392 break;
393 default:
394 LOG(WARNING) << "Failed to remove " << local_id << ": "
395 << FileErrorToString(error);
396 }
397 }
398 }
399
345 } // namespace internal 400 } // namespace internal
346 } // namespace drive 401 } // namespace drive
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698