OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/sync_file_system/local/local_file_change_tracker.h" | 5 #include "chrome/browser/sync_file_system/local/local_file_change_tracker.h" |
6 | 6 |
7 #include <queue> | 7 #include <queue> |
8 | 8 |
9 #include "base/location.h" | 9 #include "base/location.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
83 num_changes_(0) { | 83 num_changes_(0) { |
84 } | 84 } |
85 | 85 |
86 LocalFileChangeTracker::~LocalFileChangeTracker() { | 86 LocalFileChangeTracker::~LocalFileChangeTracker() { |
87 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 87 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
88 tracker_db_.reset(); | 88 tracker_db_.reset(); |
89 } | 89 } |
90 | 90 |
91 void LocalFileChangeTracker::OnStartUpdate(const FileSystemURL& url) { | 91 void LocalFileChangeTracker::OnStartUpdate(const FileSystemURL& url) { |
92 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 92 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
93 if (ContainsKey(changes_, url)) | 93 if (ContainsKey(changes_, url) || ContainsKey(demoted_changes_, url)) |
94 return; | 94 return; |
95 // TODO(nhiroki): propagate the error code (see http://crbug.com/152127). | 95 // TODO(nhiroki): propagate the error code (see http://crbug.com/152127). |
96 MarkDirtyOnDatabase(url); | 96 MarkDirtyOnDatabase(url); |
97 } | 97 } |
98 | 98 |
99 void LocalFileChangeTracker::OnEndUpdate(const FileSystemURL& url) {} | 99 void LocalFileChangeTracker::OnEndUpdate(const FileSystemURL& url) {} |
100 | 100 |
101 void LocalFileChangeTracker::OnCreateFile(const FileSystemURL& url) { | 101 void LocalFileChangeTracker::OnCreateFile(const FileSystemURL& url) { |
102 RecordChange(url, FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, | 102 RecordChange(url, FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, |
103 SYNC_FILE_TYPE_FILE)); | 103 SYNC_FILE_TYPE_FILE)); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
179 } | 179 } |
180 | 180 |
181 void LocalFileChangeTracker::RemoveMirrorAndCommitChangesForURL( | 181 void LocalFileChangeTracker::RemoveMirrorAndCommitChangesForURL( |
182 const fileapi::FileSystemURL& url) { | 182 const fileapi::FileSystemURL& url) { |
183 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 183 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
184 FileChangeMap::iterator found = mirror_changes_.find(url); | 184 FileChangeMap::iterator found = mirror_changes_.find(url); |
185 if (found == mirror_changes_.end()) | 185 if (found == mirror_changes_.end()) |
186 return; | 186 return; |
187 mirror_changes_.erase(found); | 187 mirror_changes_.erase(found); |
188 | 188 |
189 if (ContainsKey(changes_, url)) | 189 if (ContainsKey(changes_, url) || ContainsKey(demoted_changes_, url)) |
190 MarkDirtyOnDatabase(url); | 190 MarkDirtyOnDatabase(url); |
191 else | 191 else |
192 ClearDirtyOnDatabase(url); | 192 ClearDirtyOnDatabase(url); |
193 UpdateNumChanges(); | 193 UpdateNumChanges(); |
194 } | 194 } |
195 | 195 |
196 void LocalFileChangeTracker::ResetToMirrorAndCommitChangesForURL( | 196 void LocalFileChangeTracker::ResetToMirrorAndCommitChangesForURL( |
197 const fileapi::FileSystemURL& url) { | 197 const fileapi::FileSystemURL& url) { |
198 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 198 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
199 FileChangeMap::iterator found = mirror_changes_.find(url); | 199 FileChangeMap::iterator found = mirror_changes_.find(url); |
200 if (found == mirror_changes_.end() || found->second.change_list.empty()) { | 200 if (found == mirror_changes_.end() || found->second.change_list.empty()) { |
201 ClearChangesForURL(url); | 201 ClearChangesForURL(url); |
202 return; | 202 return; |
203 } | 203 } |
204 const ChangeInfo& info = found->second; | 204 const ChangeInfo& info = found->second; |
205 change_seqs_[info.change_seq] = url; | 205 if (ContainsKey(demoted_changes_, url)) { |
nhiroki
2014/07/23 06:37:13
Can you have "DCHECK(!ContainsKey(changes_, url))"
tzik
2014/07/24 15:35:20
Done.
| |
206 changes_[url] = info; | 206 demoted_changes_[url] = info; |
207 } else { | |
nhiroki
2014/07/23 06:37:13
ditto: "DCHECK(!ContainsKey(demoted_changes_, url)
tzik
2014/07/24 15:35:20
Done.
| |
208 change_seqs_[info.change_seq] = url; | |
209 changes_[url] = info; | |
210 } | |
207 RemoveMirrorAndCommitChangesForURL(url); | 211 RemoveMirrorAndCommitChangesForURL(url); |
208 } | 212 } |
209 | 213 |
210 void LocalFileChangeTracker::DemoteChangesForURL( | 214 void LocalFileChangeTracker::DemoteChangesForURL( |
211 const fileapi::FileSystemURL& url) { | 215 const fileapi::FileSystemURL& url) { |
212 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 216 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
217 | |
213 FileChangeMap::iterator found = changes_.find(url); | 218 FileChangeMap::iterator found = changes_.find(url); |
214 if (found == changes_.end()) | 219 if (found == changes_.end()) |
215 return; | 220 return; |
216 FileChangeList changes = found->second.change_list; | 221 DCHECK(!ContainsKey(demoted_changes_, url)); |
217 | |
218 mirror_changes_.erase(url); | |
219 change_seqs_.erase(found->second.change_seq); | 222 change_seqs_.erase(found->second.change_seq); |
223 demoted_changes_.insert(*found); | |
220 changes_.erase(found); | 224 changes_.erase(found); |
221 | 225 UpdateNumChanges(); |
222 FileChangeList::List change_list = changes.list(); | |
223 while (!change_list.empty()) { | |
224 RecordChangeToChangeMaps(url, change_list.front(), 0, | |
225 &demoted_changes_, NULL); | |
226 change_list.pop_front(); | |
227 } | |
228 } | 226 } |
229 | 227 |
230 void LocalFileChangeTracker::PromoteDemotedChangesForURL( | 228 void LocalFileChangeTracker::PromoteDemotedChangesForURL( |
231 const fileapi::FileSystemURL& url) { | 229 const fileapi::FileSystemURL& url) { |
232 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 230 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
233 | 231 |
234 FileChangeMap::iterator iter = demoted_changes_.find(url); | 232 FileChangeMap::iterator iter = demoted_changes_.find(url); |
235 if (iter == demoted_changes_.end()) | 233 if (iter == demoted_changes_.end()) |
236 return; | 234 return; |
237 | 235 |
238 FileChangeList::List change_list = iter->second.change_list.list(); | 236 FileChangeList::List change_list = iter->second.change_list.list(); |
239 // Make sure that this URL is in no queues. | 237 // Make sure that this URL is in no queues. |
238 DCHECK(!ContainsKey(change_seqs_, iter->second.change_seq)); | |
240 DCHECK(!ContainsKey(changes_, url)); | 239 DCHECK(!ContainsKey(changes_, url)); |
241 DCHECK(!ContainsKey(mirror_changes_, url)); | |
242 | 240 |
241 change_seqs_[iter->second.change_seq] = url; | |
242 changes_.insert(*iter); | |
243 demoted_changes_.erase(iter); | 243 demoted_changes_.erase(iter); |
244 | |
245 while (!change_list.empty()) { | |
246 RecordChange(url, change_list.front()); | |
247 change_list.pop_front(); | |
248 } | |
249 } | 244 } |
250 | 245 |
251 bool LocalFileChangeTracker::PromoteDemotedChanges() { | 246 bool LocalFileChangeTracker::PromoteDemotedChanges() { |
252 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 247 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
253 if (demoted_changes_.empty()) | 248 if (demoted_changes_.empty()) |
254 return false; | 249 return false; |
255 while (!demoted_changes_.empty()) { | 250 while (!demoted_changes_.empty()) { |
256 fileapi::FileSystemURL url = demoted_changes_.begin()->first; | 251 fileapi::FileSystemURL url = demoted_changes_.begin()->first; |
257 PromoteDemotedChangesForURL(url); | 252 PromoteDemotedChangesForURL(url); |
258 } | 253 } |
254 UpdateNumChanges(); | |
259 return true; | 255 return true; |
260 } | 256 } |
261 | 257 |
262 SyncStatusCode LocalFileChangeTracker::Initialize( | 258 SyncStatusCode LocalFileChangeTracker::Initialize( |
263 FileSystemContext* file_system_context) { | 259 FileSystemContext* file_system_context) { |
264 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 260 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
265 DCHECK(!initialized_); | 261 DCHECK(!initialized_); |
266 DCHECK(file_system_context); | 262 DCHECK(file_system_context); |
267 | 263 |
268 SyncStatusCode status = CollectLastDirtyChanges(file_system_context); | 264 SyncStatusCode status = CollectLastDirtyChanges(file_system_context); |
269 if (status == SYNC_STATUS_OK) | 265 if (status == SYNC_STATUS_OK) |
270 initialized_ = true; | 266 initialized_ = true; |
271 return status; | 267 return status; |
272 } | 268 } |
273 | 269 |
274 void LocalFileChangeTracker::ResetForFileSystem( | 270 void LocalFileChangeTracker::ResetForFileSystem( |
275 const GURL& origin, | 271 const GURL& origin, |
276 fileapi::FileSystemType type) { | 272 fileapi::FileSystemType type) { |
277 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 273 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
278 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); | 274 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); |
279 for (FileChangeMap::iterator iter = changes_.begin(); | 275 for (FileChangeMap::iterator iter = changes_.begin(); |
280 iter != changes_.end();) { | 276 iter != changes_.end();) { |
281 fileapi::FileSystemURL url = iter->first; | 277 fileapi::FileSystemURL url = iter->first; |
282 if (url.origin() != origin || url.type() != type) { | 278 int change_seq = iter->second.change_seq; |
283 ++iter; | 279 // Advance |iter| before calling ResetForURL to avoid the iterator |
284 continue; | 280 // invalidation in it. |
285 } | 281 ++iter; |
286 mirror_changes_.erase(url); | 282 if (url.origin() == origin && url.type() == type) |
287 demoted_changes_.erase(url); | 283 ResetForURL(url, change_seq, batch.get()); |
288 change_seqs_.erase(iter->second.change_seq); | 284 } |
289 changes_.erase(iter++); | |
290 | 285 |
291 std::string serialized_url; | 286 for (FileChangeMap::iterator iter = demoted_changes_.begin(); |
292 const bool should_success = | 287 iter != demoted_changes_.end();) { |
293 SerializeSyncableFileSystemURL(url, &serialized_url); | 288 fileapi::FileSystemURL url = iter->first; |
294 if (!should_success) { | 289 int change_seq = iter->second.change_seq; |
295 NOTREACHED() << "Failed to serialize: " << url.DebugString(); | 290 // Advance |iter| before calling ResetForURL to avoid the iterator |
296 continue; | 291 // invalidation in it. |
297 } | 292 ++iter; |
298 batch->Delete(serialized_url); | 293 if (url.origin() == origin && url.type() == type) |
294 ResetForURL(url, change_seq, batch.get()); | |
299 } | 295 } |
296 | |
300 // Fail to apply batch to database wouldn't have critical effect, they'll be | 297 // Fail to apply batch to database wouldn't have critical effect, they'll be |
301 // just marked deleted on next relaunch. | 298 // just marked deleted on next relaunch. |
302 tracker_db_->WriteBatch(batch.Pass()); | 299 tracker_db_->WriteBatch(batch.Pass()); |
303 UpdateNumChanges(); | 300 UpdateNumChanges(); |
304 } | 301 } |
305 | 302 |
306 void LocalFileChangeTracker::UpdateNumChanges() { | 303 void LocalFileChangeTracker::UpdateNumChanges() { |
307 base::AutoLock lock(num_changes_lock_); | 304 base::AutoLock lock(num_changes_lock_); |
308 num_changes_ = static_cast<int64>(change_seqs_.size()); | 305 num_changes_ = static_cast<int64>(change_seqs_.size()); |
309 } | 306 } |
310 | 307 |
311 void LocalFileChangeTracker::GetAllChangedURLs(FileSystemURLSet* urls) { | 308 void LocalFileChangeTracker::GetAllChangedURLs(FileSystemURLSet* urls) { |
312 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 309 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
313 std::deque<FileSystemURL> url_deque; | 310 std::deque<FileSystemURL> url_deque; |
314 GetNextChangedURLs(&url_deque, 0); | 311 GetNextChangedURLs(&url_deque, 0); |
315 urls->clear(); | 312 urls->clear(); |
316 urls->insert(url_deque.begin(), url_deque.end()); | 313 urls->insert(url_deque.begin(), url_deque.end()); |
317 } | 314 } |
318 | 315 |
319 void LocalFileChangeTracker::DropAllChanges() { | 316 void LocalFileChangeTracker::DropAllChanges() { |
320 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 317 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
321 changes_.clear(); | 318 changes_.clear(); |
322 change_seqs_.clear(); | 319 change_seqs_.clear(); |
323 mirror_changes_.clear(); | 320 mirror_changes_.clear(); |
321 UpdateNumChanges(); | |
324 } | 322 } |
325 | 323 |
326 SyncStatusCode LocalFileChangeTracker::MarkDirtyOnDatabase( | 324 SyncStatusCode LocalFileChangeTracker::MarkDirtyOnDatabase( |
327 const FileSystemURL& url) { | 325 const FileSystemURL& url) { |
328 std::string serialized_url; | 326 std::string serialized_url; |
329 if (!SerializeSyncableFileSystemURL(url, &serialized_url)) | 327 if (!SerializeSyncableFileSystemURL(url, &serialized_url)) |
330 return SYNC_FILE_ERROR_INVALID_URL; | 328 return SYNC_FILE_ERROR_INVALID_URL; |
331 | 329 |
332 return tracker_db_->MarkDirty(serialized_url); | 330 return tracker_db_->MarkDirty(serialized_url); |
333 } | 331 } |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
405 LOG(WARNING) << "Failed to access local file."; | 403 LOG(WARNING) << "Failed to access local file."; |
406 break; | 404 break; |
407 } | 405 } |
408 } | 406 } |
409 return SYNC_STATUS_OK; | 407 return SYNC_STATUS_OK; |
410 } | 408 } |
411 | 409 |
412 void LocalFileChangeTracker::RecordChange( | 410 void LocalFileChangeTracker::RecordChange( |
413 const FileSystemURL& url, const FileChange& change) { | 411 const FileSystemURL& url, const FileChange& change) { |
414 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); | 412 DCHECK(file_task_runner_->RunsTasksOnCurrentThread()); |
413 int change_seq = current_change_seq_++; | |
415 if (ContainsKey(demoted_changes_, url)) { | 414 if (ContainsKey(demoted_changes_, url)) { |
416 RecordChangeToChangeMaps(url, change, 0, &demoted_changes_, NULL); | 415 RecordChangeToChangeMaps(url, change, change_seq, |
417 return; | 416 &demoted_changes_, NULL); |
417 } else{ | |
418 RecordChangeToChangeMaps(url, change, change_seq, &changes_, &change_seqs_); | |
418 } | 419 } |
419 int change_seq = current_change_seq_++; | |
420 RecordChangeToChangeMaps(url, change, change_seq, &changes_, &change_seqs_); | |
421 if (ContainsKey(mirror_changes_, url)) | 420 if (ContainsKey(mirror_changes_, url)) |
422 RecordChangeToChangeMaps(url, change, change_seq, &mirror_changes_, NULL); | 421 RecordChangeToChangeMaps(url, change, change_seq, &mirror_changes_, NULL); |
423 UpdateNumChanges(); | 422 UpdateNumChanges(); |
424 } | 423 } |
425 | 424 |
426 // static | 425 // static |
427 void LocalFileChangeTracker::RecordChangeToChangeMaps( | 426 void LocalFileChangeTracker::RecordChangeToChangeMaps( |
428 const FileSystemURL& url, | 427 const FileSystemURL& url, |
429 const FileChange& change, | 428 const FileChange& change, |
430 int new_change_seq, | 429 int new_change_seq, |
431 FileChangeMap* changes, | 430 FileChangeMap* changes, |
432 ChangeSeqMap* change_seqs) { | 431 ChangeSeqMap* change_seqs) { |
433 ChangeInfo& info = (*changes)[url]; | 432 ChangeInfo& info = (*changes)[url]; |
434 if (info.change_seq >= 0 && change_seqs) | 433 if (info.change_seq >= 0 && change_seqs) |
435 change_seqs->erase(info.change_seq); | 434 change_seqs->erase(info.change_seq); |
436 info.change_list.Update(change); | 435 info.change_list.Update(change); |
437 if (info.change_list.empty()) { | 436 if (info.change_list.empty()) { |
438 changes->erase(url); | 437 changes->erase(url); |
439 return; | 438 return; |
440 } | 439 } |
441 info.change_seq = new_change_seq; | 440 info.change_seq = new_change_seq; |
442 if (change_seqs) | 441 if (change_seqs) |
443 (*change_seqs)[info.change_seq] = url; | 442 (*change_seqs)[info.change_seq] = url; |
444 } | 443 } |
445 | 444 |
445 void LocalFileChangeTracker::ResetForURL(const fileapi::FileSystemURL& url, | |
446 int change_seq, | |
447 leveldb::WriteBatch* batch) { | |
448 mirror_changes_.erase(url); | |
449 demoted_changes_.erase(url); | |
450 change_seqs_.erase(change_seq); | |
451 changes_.erase(url); | |
452 | |
453 std::string serialized_url; | |
454 if (!SerializeSyncableFileSystemURL(url, &serialized_url)) { | |
455 NOTREACHED() << "Failed to serialize: " << url.DebugString(); | |
456 return; | |
457 } | |
458 batch->Delete(serialized_url); | |
459 } | |
460 | |
446 // TrackerDB ------------------------------------------------------------------- | 461 // TrackerDB ------------------------------------------------------------------- |
447 | 462 |
448 LocalFileChangeTracker::TrackerDB::TrackerDB(const base::FilePath& base_path, | 463 LocalFileChangeTracker::TrackerDB::TrackerDB(const base::FilePath& base_path, |
449 leveldb::Env* env_override) | 464 leveldb::Env* env_override) |
450 : base_path_(base_path), | 465 : base_path_(base_path), |
451 env_override_(env_override), | 466 env_override_(env_override), |
452 db_status_(SYNC_STATUS_OK) {} | 467 db_status_(SYNC_STATUS_OK) {} |
453 | 468 |
454 SyncStatusCode LocalFileChangeTracker::TrackerDB::Init( | 469 SyncStatusCode LocalFileChangeTracker::TrackerDB::Init( |
455 RecoveryOption recovery_option) { | 470 RecoveryOption recovery_option) { |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
590 if (!status.ok() && !status.IsNotFound()) { | 605 if (!status.ok() && !status.IsNotFound()) { |
591 HandleError(FROM_HERE, status); | 606 HandleError(FROM_HERE, status); |
592 db_status_ = LevelDBStatusToSyncStatusCode(status); | 607 db_status_ = LevelDBStatusToSyncStatusCode(status); |
593 db_.reset(); | 608 db_.reset(); |
594 return db_status_; | 609 return db_status_; |
595 } | 610 } |
596 return SYNC_STATUS_OK; | 611 return SYNC_STATUS_OK; |
597 } | 612 } |
598 | 613 |
599 } // namespace sync_file_system | 614 } // namespace sync_file_system |
OLD | NEW |