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/drive_backend/metadata_database.h" | 5 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <stack> | 8 #include <stack> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/callback.h" | 11 #include "base/callback.h" |
12 #include "base/file_util.h" | 12 #include "base/file_util.h" |
13 #include "base/files/file_path.h" | 13 #include "base/files/file_path.h" |
14 #include "base/location.h" | 14 #include "base/location.h" |
15 #include "base/memory/scoped_vector.h" | 15 #include "base/memory/scoped_vector.h" |
16 #include "base/message_loop/message_loop_proxy.h" | 16 #include "base/message_loop/message_loop_proxy.h" |
17 #include "base/sequenced_task_runner.h" | 17 #include "base/sequenced_task_runner.h" |
18 #include "base/stl_util.h" | 18 #include "base/stl_util.h" |
19 #include "base/strings/string_number_conversions.h" | 19 #include "base/strings/string_number_conversions.h" |
20 #include "base/strings/string_util.h" | 20 #include "base/strings/string_util.h" |
21 #include "base/strings/stringprintf.h" | 21 #include "base/strings/stringprintf.h" |
22 #include "base/task_runner_util.h" | 22 #include "base/task_runner_util.h" |
23 #include "base/threading/thread_restrictions.h" | 23 #include "base/threading/thread_restrictions.h" |
24 #include "chrome/browser/drive/drive_api_util.h" | 24 #include "chrome/browser/drive/drive_api_util.h" |
25 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants. h" | 25 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants. h" |
26 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h" | 26 #include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h" |
27 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h" | 27 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h" |
28 #include "chrome/browser/sync_file_system/drive_backend/metadata_database_index. h" | |
28 #include "chrome/browser/sync_file_system/drive_backend/metadata_db_migration_ut il.h" | 29 #include "chrome/browser/sync_file_system/drive_backend/metadata_db_migration_ut il.h" |
29 #include "chrome/browser/sync_file_system/logger.h" | 30 #include "chrome/browser/sync_file_system/logger.h" |
30 #include "chrome/browser/sync_file_system/syncable_file_system_util.h" | 31 #include "chrome/browser/sync_file_system/syncable_file_system_util.h" |
31 #include "google_apis/drive/drive_api_parser.h" | 32 #include "google_apis/drive/drive_api_parser.h" |
32 #include "google_apis/drive/drive_entry_kinds.h" | 33 #include "google_apis/drive/drive_entry_kinds.h" |
33 #include "third_party/leveldatabase/src/include/leveldb/db.h" | 34 #include "third_party/leveldatabase/src/include/leveldb/db.h" |
34 #include "third_party/leveldatabase/src/include/leveldb/env.h" | 35 #include "third_party/leveldatabase/src/include/leveldb/env.h" |
35 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" | 36 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" |
36 #include "webkit/common/fileapi/file_system_util.h" | 37 #include "webkit/common/fileapi/file_system_util.h" |
37 | 38 |
38 namespace sync_file_system { | 39 namespace sync_file_system { |
39 namespace drive_backend { | 40 namespace drive_backend { |
40 | 41 |
41 namespace { | 42 namespace { |
42 | 43 |
43 typedef MetadataDatabase::MetadataByID MetadataByID; | |
44 typedef MetadataDatabase::TrackerByID TrackerByID; | |
45 typedef MetadataDatabase::TrackerIDsByParentAndTitle TrackerIDsByParentAndTitle; | |
46 typedef MetadataDatabase::TrackerIDsByTitle TrackerIDsByTitle; | |
47 | |
48 bool IsAppRoot(const FileTracker& tracker) { | 44 bool IsAppRoot(const FileTracker& tracker) { |
49 return tracker.tracker_kind() == TRACKER_KIND_APP_ROOT || | 45 return tracker.tracker_kind() == TRACKER_KIND_APP_ROOT || |
50 tracker.tracker_kind() == TRACKER_KIND_DISABLED_APP_ROOT; | 46 tracker.tracker_kind() == TRACKER_KIND_DISABLED_APP_ROOT; |
51 } | 47 } |
52 | 48 |
53 std::string RemovePrefix(const std::string& str, const std::string& prefix) { | 49 std::string RemovePrefix(const std::string& str, const std::string& prefix) { |
54 if (StartsWithASCII(str, prefix, true)) | 50 if (StartsWithASCII(str, prefix, true)) |
55 return str.substr(prefix.size()); | 51 return str.substr(prefix.size()); |
56 return str; | 52 return str; |
57 } | 53 } |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
107 app_root_tracker->set_needs_folder_listing(false); | 103 app_root_tracker->set_needs_folder_listing(false); |
108 *app_root_tracker->mutable_synced_details() = app_root_metadata.details(); | 104 *app_root_tracker->mutable_synced_details() = app_root_metadata.details(); |
109 return app_root_tracker.Pass(); | 105 return app_root_tracker.Pass(); |
110 } | 106 } |
111 | 107 |
112 void AdaptLevelDBStatusToSyncStatusCode(const SyncStatusCallback& callback, | 108 void AdaptLevelDBStatusToSyncStatusCode(const SyncStatusCallback& callback, |
113 const leveldb::Status& status) { | 109 const leveldb::Status& status) { |
114 callback.Run(LevelDBStatusToSyncStatusCode(status)); | 110 callback.Run(LevelDBStatusToSyncStatusCode(status)); |
115 } | 111 } |
116 | 112 |
117 template <typename OutputIterator> | |
118 OutputIterator PushChildTrackersToContainer( | |
119 const TrackerIDsByParentAndTitle& trackers_by_parent, | |
120 int64 parent_tracker_id, | |
121 OutputIterator target_itr) { | |
122 TrackerIDsByParentAndTitle::const_iterator found = | |
123 trackers_by_parent.find(parent_tracker_id); | |
124 if (found == trackers_by_parent.end()) | |
125 return target_itr; | |
126 | |
127 for (TrackerIDsByTitle::const_iterator title_itr = found->second.begin(); | |
128 title_itr != found->second.end(); ++title_itr) { | |
129 const TrackerIDSet& trackers = title_itr->second; | |
130 for (TrackerIDSet::const_iterator tracker_itr = trackers.begin(); | |
131 tracker_itr != trackers.end(); ++tracker_itr) { | |
132 *target_itr = *tracker_itr; | |
133 ++target_itr; | |
134 } | |
135 } | |
136 return target_itr; | |
137 } | |
138 | |
139 std::string GetTrackerTitle(const FileTracker& tracker) { | 113 std::string GetTrackerTitle(const FileTracker& tracker) { |
140 if (tracker.has_synced_details()) | 114 if (tracker.has_synced_details()) |
141 return tracker.synced_details().title(); | 115 return tracker.synced_details().title(); |
142 return std::string(); | 116 return std::string(); |
143 } | 117 } |
144 | 118 |
145 // Returns true if |db| has no content. | 119 // Returns true if |db| has no content. |
146 bool IsDatabaseEmpty(leveldb::DB* db) { | 120 bool IsDatabaseEmpty(leveldb::DB* db) { |
147 DCHECK(db); | 121 DCHECK(db); |
148 scoped_ptr<leveldb::Iterator> itr(db->NewIterator(leveldb::ReadOptions())); | 122 scoped_ptr<leveldb::Iterator> itr(db->NewIterator(leveldb::ReadOptions())); |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
372 contents->file_metadata[i] = NULL; | 346 contents->file_metadata[i] = NULL; |
373 } else { | 347 } else { |
374 PutFileMetadataDeletionToBatch(metadata->file_id(), batch); | 348 PutFileMetadataDeletionToBatch(metadata->file_id(), batch); |
375 } | 349 } |
376 } | 350 } |
377 contents->file_metadata = referred_file_metadata.Pass(); | 351 contents->file_metadata = referred_file_metadata.Pass(); |
378 | 352 |
379 return SYNC_STATUS_OK; | 353 return SYNC_STATUS_OK; |
380 } | 354 } |
381 | 355 |
382 template <typename Container, typename Key, typename Value> | |
383 bool FindItem(const Container& container, const Key& key, Value* value) { | |
384 typename Container::const_iterator found = container.find(key); | |
385 if (found == container.end()) | |
386 return false; | |
387 if (value) | |
388 *value = *found->second; | |
389 return true; | |
390 } | |
391 | |
392 template <typename Container, typename Key> | |
393 typename Container::mapped_type FindAndEraseItem(Container* container, | |
394 const Key& key) { | |
395 typedef typename Container::mapped_type Value; | |
396 typename Container::iterator found = container->find(key); | |
397 if (found == container->end()) | |
398 return Value(); | |
399 | |
400 Value result = found->second; | |
401 container->erase(found); | |
402 return result; | |
403 } | |
404 | |
405 void RunSoon(const tracked_objects::Location& from_here, | 356 void RunSoon(const tracked_objects::Location& from_here, |
406 const base::Closure& closure) { | 357 const base::Closure& closure) { |
407 base::MessageLoopProxy::current()->PostTask(from_here, closure); | 358 base::MessageLoopProxy::current()->PostTask(from_here, closure); |
408 } | 359 } |
409 | 360 |
410 bool HasInvalidTitle(const std::string& title) { | 361 bool HasInvalidTitle(const std::string& title) { |
411 return title.empty() || | 362 return title.empty() || |
412 title.find('/') != std::string::npos || | 363 title.find('/') != std::string::npos || |
413 title.find('\\') != std::string::npos; | 364 title.find('\\') != std::string::npos; |
414 } | 365 } |
415 | 366 |
367 void MarkTrackerSetDirty(const TrackerIDSet& trackers, | |
368 MetadataDatabaseIndex* index, | |
369 leveldb::WriteBatch* batch) { | |
370 for (TrackerIDSet::const_iterator itr = trackers.begin(); | |
371 itr != trackers.end(); ++itr) { | |
372 scoped_ptr<FileTracker> tracker = Clone(index->GetFileTracker(*itr)); | |
373 if (tracker->dirty()) | |
374 continue; | |
375 tracker->set_dirty(true); | |
376 PutFileTrackerToBatch(*tracker, batch); | |
377 index->StoreFileTracker(tracker.Pass()); | |
378 } | |
379 } | |
380 | |
381 void MarkTrackersDirtyByPath(int64 parent_tracker_id, | |
382 const std::string& title, | |
383 MetadataDatabaseIndex* index, | |
384 leveldb::WriteBatch* batch) { | |
385 if (parent_tracker_id == kInvalidTrackerID || title.empty()) | |
386 return; | |
387 MarkTrackerSetDirty( | |
388 index->GetFileTrackerIDsByParentAndTitle(parent_tracker_id, title), | |
389 index, batch); | |
390 } | |
391 | |
392 void MarkTrackersDirtyByFileID(const std::string& file_id, | |
393 MetadataDatabaseIndex* index, | |
394 leveldb::WriteBatch* batch) { | |
395 MarkTrackerSetDirty(index->GetFileTrackerIDsByFileID(file_id), | |
396 index, batch); | |
397 } | |
398 | |
399 void MarkTrackersDirtyRecursively(int64 root_tracker_id, | |
400 MetadataDatabaseIndex* index, | |
401 leveldb::WriteBatch* batch) { | |
402 std::vector<int64> stack; | |
403 stack.push_back(root_tracker_id); | |
404 while (!stack.empty()) { | |
405 int64 tracker_id = stack.back(); | |
406 stack.pop_back(); | |
407 AppendContents(index->GetFileTrackerIDsByParent(tracker_id), &stack); | |
408 | |
409 scoped_ptr<FileTracker> tracker = Clone(index->GetFileTracker(tracker_id)); | |
410 tracker->set_dirty(true); | |
411 | |
412 PutFileTrackerToBatch(*tracker, batch); | |
413 index->StoreFileTracker(tracker.Pass()); | |
414 } | |
415 } | |
416 | |
417 void RemoveAllDescendantTrackers(int64 root_tracker_id, | |
418 MetadataDatabaseIndex* index, | |
419 leveldb::WriteBatch* batch) { | |
420 std::vector<int64> pending_trackers; | |
421 AppendContents(index->GetFileTrackerIDsByParent(root_tracker_id), | |
422 &pending_trackers); | |
423 | |
424 std::vector<int64> to_be_removed; | |
425 base::hash_set<std::string> affected_file_ids; | |
nhiroki
2014/03/05 06:21:35
Can you move |affected_file_ids| to line 435 for r
tzik
2014/03/05 07:05:54
Done.
| |
426 | |
427 // List trackers to remove. | |
428 while (!pending_trackers.empty()) { | |
429 int64 tracker_id = pending_trackers.back(); | |
430 pending_trackers.pop_back(); | |
431 AppendContents(index->GetFileTrackerIDsByParent(tracker_id), | |
432 &pending_trackers); | |
433 to_be_removed.push_back(tracker_id); | |
434 } | |
435 | |
436 // Remove trackers in the reversed order. | |
437 for (std::vector<int64>::reverse_iterator itr = to_be_removed.rbegin(); | |
438 itr != to_be_removed.rend(); ++itr) { | |
439 const FileTracker* trackers = index->GetFileTracker(*itr); | |
440 affected_file_ids.insert(trackers->file_id()); | |
441 PutFileTrackerDeletionToBatch(*itr, batch); | |
442 index->RemoveFileTracker(*itr); | |
443 } | |
444 | |
445 for (base::hash_set<std::string>::iterator itr = affected_file_ids.begin(); | |
446 itr != affected_file_ids.end(); ++itr) { | |
447 TrackerIDSet trackers = index->GetFileTrackerIDsByFileID(*itr); | |
448 if (trackers.empty()) { | |
449 // Remove metadata that no longer has any tracker. | |
450 PutFileMetadataDeletionToBatch(*itr, batch); | |
451 index->RemoveFileMetadata(*itr); | |
452 } else { | |
453 MarkTrackerSetDirty(trackers, index, batch); | |
454 } | |
455 } | |
456 } | |
457 | |
458 const FileTracker* FilterFileTrackersByParent( | |
459 const MetadataDatabaseIndex& index, | |
460 const TrackerIDSet& trackers, | |
461 int64 parent_tracker_id) { | |
462 for (TrackerIDSet::const_iterator itr = trackers.begin(); | |
463 itr != trackers.end(); | |
464 ++itr) { | |
nhiroki
2014/03/05 06:21:35
super-nit: Can you move this "++itr" to line 463?
tzik
2014/03/05 07:05:54
Done.
| |
465 const FileTracker* tracker = index.GetFileTracker(*itr); | |
466 if (!tracker) { | |
467 NOTREACHED(); | |
468 continue; | |
469 } | |
470 | |
471 if (tracker->parent_tracker_id() == parent_tracker_id) | |
472 return tracker; | |
473 } | |
474 return NULL; | |
475 } | |
476 | |
477 const FileTracker* FilterFileTrackersByParentAndTitle( | |
478 const MetadataDatabaseIndex& index, | |
479 const TrackerIDSet& trackers, | |
480 int64 parent_tracker_id, | |
481 const std::string& title) { | |
482 const FileTracker* result = NULL; | |
483 | |
484 for (TrackerIDSet::const_iterator itr = trackers.begin(); | |
485 itr != trackers.end(); ++itr) { | |
486 const FileTracker* tracker = index.GetFileTracker(*itr); | |
487 if (!tracker) { | |
488 NOTREACHED(); | |
489 continue; | |
490 } | |
491 | |
492 if (tracker->parent_tracker_id() != parent_tracker_id) | |
493 continue; | |
494 | |
495 if (tracker->has_synced_details() && | |
496 tracker->synced_details().title() != title) | |
497 continue; | |
498 | |
499 // Prioritize trackers that has |synced_details|. | |
500 if (!result || !tracker->has_synced_details()) | |
501 result = tracker; | |
502 } | |
503 | |
504 return result; | |
505 } | |
506 | |
507 const FileTracker* FilterFileTrackersByFileID( | |
508 const MetadataDatabaseIndex& index, | |
509 const TrackerIDSet& trackers, | |
510 const std::string& file_id) { | |
511 for (TrackerIDSet::const_iterator itr = trackers.begin(); | |
512 itr != trackers.end(); ++itr) { | |
513 const FileTracker* tracker = index.GetFileTracker(*itr); | |
514 if (!tracker) { | |
515 NOTREACHED(); | |
516 continue; | |
517 } | |
518 | |
519 if (tracker->file_id() == file_id) | |
520 return tracker; | |
521 } | |
522 | |
523 return NULL; | |
524 } | |
525 | |
526 enum DirtyingOption { | |
527 MARK_NOTHING_DIRTY = 0, | |
528 MARK_ITSELF_DIRTY = 1 << 0, | |
529 MARK_SAME_FILE_ID_TRACKERS_DIRTY = 1 << 1, | |
530 MARK_SAME_PATH_TRACKERS_DIRTY = 1 << 2, | |
531 }; | |
532 | |
533 void ActivateFileTracker(int64 tracker_id, | |
534 int dirtying_options, | |
535 MetadataDatabaseIndex* index, | |
536 leveldb::WriteBatch* batch) { | |
537 DCHECK(dirtying_options == MARK_NOTHING_DIRTY || | |
538 dirtying_options == MARK_ITSELF_DIRTY); | |
539 | |
540 scoped_ptr<FileTracker> tracker = Clone(index->GetFileTracker(tracker_id)); | |
541 tracker->set_active(true); | |
542 if (dirtying_options & MARK_ITSELF_DIRTY) { | |
543 tracker->set_dirty(true); | |
544 tracker->set_needs_folder_listing( | |
545 tracker->has_synced_details() && | |
546 tracker->synced_details().file_kind() == FILE_KIND_FOLDER); | |
547 } else { | |
548 tracker->set_dirty(false); | |
549 tracker->set_needs_folder_listing(false); | |
550 } | |
551 | |
552 PutFileTrackerToBatch(*tracker, batch); | |
553 index->StoreFileTracker(tracker.Pass()); | |
554 } | |
555 | |
556 void DeactivateFileTracker(int64 tracker_id, | |
557 int dirtying_options, | |
558 MetadataDatabaseIndex* index, | |
559 leveldb::WriteBatch* batch) { | |
560 RemoveAllDescendantTrackers(tracker_id, index, batch); | |
561 | |
562 scoped_ptr<FileTracker> tracker = Clone(index->GetFileTracker(tracker_id)); | |
563 | |
564 if (dirtying_options & MARK_SAME_FILE_ID_TRACKERS_DIRTY) | |
565 MarkTrackersDirtyByFileID(tracker->file_id(), index, batch); | |
566 if (dirtying_options & MARK_SAME_PATH_TRACKERS_DIRTY) { | |
567 MarkTrackersDirtyByPath(tracker->parent_tracker_id(), | |
568 GetTrackerTitle(*tracker), | |
569 index, batch); | |
570 } | |
571 | |
572 tracker->set_dirty(dirtying_options & MARK_ITSELF_DIRTY); | |
573 tracker->set_active(false); | |
574 PutFileTrackerToBatch(*tracker, batch); | |
575 index->StoreFileTracker(tracker.Pass()); | |
576 } | |
577 | |
578 void RemoveTracker(int64 tracker_id, | |
nhiroki
2014/03/05 06:21:35
nit: RemoveTracker -> RemoveFileTracker
tzik
2014/03/05 07:05:54
Done.
| |
579 int dirtying_options, | |
580 MetadataDatabaseIndex* index, | |
581 leveldb::WriteBatch* batch) { | |
582 DCHECK(!(dirtying_options & MARK_ITSELF_DIRTY)); | |
583 | |
584 const FileTracker* tracker = index->GetFileTracker(tracker_id); | |
585 if (!tracker) | |
586 return; | |
587 | |
588 std::string file_id = tracker->file_id(); | |
589 int64 parent_tracker_id = tracker->parent_tracker_id(); | |
590 std::string title = GetTrackerTitle(*tracker); | |
591 | |
592 RemoveAllDescendantTrackers(tracker_id, index, batch); | |
593 PutFileTrackerDeletionToBatch(tracker_id, batch); | |
594 index->RemoveFileTracker(tracker_id); | |
595 | |
596 if (dirtying_options & MARK_SAME_FILE_ID_TRACKERS_DIRTY) | |
597 MarkTrackersDirtyByFileID(file_id, index, batch); | |
598 if (dirtying_options & MARK_SAME_PATH_TRACKERS_DIRTY) | |
599 MarkTrackersDirtyByPath(parent_tracker_id, title, index, batch); | |
600 | |
601 if (index->GetFileTrackerIDsByFileID(file_id).empty()) { | |
602 PutFileMetadataDeletionToBatch(file_id, batch); | |
603 index->RemoveFileMetadata(file_id); | |
604 } | |
605 } | |
606 | |
416 } // namespace | 607 } // namespace |
417 | 608 |
418 DatabaseContents::DatabaseContents() {} | 609 DatabaseContents::DatabaseContents() {} |
419 DatabaseContents::~DatabaseContents() {} | 610 DatabaseContents::~DatabaseContents() {} |
420 | 611 |
421 bool MetadataDatabase::DirtyTrackerComparator::operator()( | |
422 const FileTracker* left, | |
423 const FileTracker* right) const { | |
424 return left->tracker_id() < right->tracker_id(); | |
425 } | |
426 | |
427 // static | 612 // static |
428 void MetadataDatabase::Create(base::SequencedTaskRunner* task_runner, | 613 void MetadataDatabase::Create(base::SequencedTaskRunner* task_runner, |
429 const base::FilePath& database_path, | 614 const base::FilePath& database_path, |
430 leveldb::Env* env_override, | 615 leveldb::Env* env_override, |
431 const CreateCallback& callback) { | 616 const CreateCallback& callback) { |
432 task_runner->PostTask(FROM_HERE, base::Bind( | 617 task_runner->PostTask(FROM_HERE, base::Bind( |
433 &CreateOnTaskRunner, | 618 &CreateOnTaskRunner, |
434 base::MessageLoopProxy::current(), | 619 base::MessageLoopProxy::current(), |
435 make_scoped_refptr(task_runner), | 620 make_scoped_refptr(task_runner), |
436 database_path, env_override, callback)); | 621 database_path, env_override, callback)); |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
492 bool MetadataDatabase::HasSyncRoot() const { | 677 bool MetadataDatabase::HasSyncRoot() const { |
493 return service_metadata_->has_sync_root_tracker_id() && | 678 return service_metadata_->has_sync_root_tracker_id() && |
494 !!service_metadata_->sync_root_tracker_id(); | 679 !!service_metadata_->sync_root_tracker_id(); |
495 } | 680 } |
496 | 681 |
497 void MetadataDatabase::PopulateInitialData( | 682 void MetadataDatabase::PopulateInitialData( |
498 int64 largest_change_id, | 683 int64 largest_change_id, |
499 const google_apis::FileResource& sync_root_folder, | 684 const google_apis::FileResource& sync_root_folder, |
500 const ScopedVector<google_apis::FileResource>& app_root_folders, | 685 const ScopedVector<google_apis::FileResource>& app_root_folders, |
501 const SyncStatusCallback& callback) { | 686 const SyncStatusCallback& callback) { |
502 DCHECK(tracker_by_id_.empty()); | 687 DCHECK(index_->tracker_by_id_.empty()); |
503 DCHECK(metadata_by_id_.empty()); | 688 DCHECK(index_->metadata_by_id_.empty()); |
504 | 689 |
505 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); | 690 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); |
506 service_metadata_->set_largest_change_id(largest_change_id); | 691 service_metadata_->set_largest_change_id(largest_change_id); |
507 UpdateLargestKnownChangeID(largest_change_id); | 692 UpdateLargestKnownChangeID(largest_change_id); |
508 | 693 |
509 AttachSyncRoot(sync_root_folder, batch.get()); | 694 AttachSyncRoot(sync_root_folder, batch.get()); |
510 for (size_t i = 0; i < app_root_folders.size(); ++i) | 695 for (size_t i = 0; i < app_root_folders.size(); ++i) |
511 AttachInitialAppRoot(*app_root_folders[i], batch.get()); | 696 AttachInitialAppRoot(*app_root_folders[i], batch.get()); |
512 | 697 |
513 WriteToDatabase(batch.Pass(), callback); | 698 WriteToDatabase(batch.Pass(), callback); |
514 } | 699 } |
515 | 700 |
516 bool MetadataDatabase::IsAppEnabled(const std::string& app_id) const { | 701 bool MetadataDatabase::IsAppEnabled(const std::string& app_id) const { |
517 FileTracker tracker; | 702 int64 tracker_id = index_->GetAppRootTracker(app_id); |
518 if (!FindAppRootTracker(app_id, &tracker)) | 703 if (tracker_id == kInvalidTrackerID) |
519 return false; | 704 return false; |
520 return tracker.tracker_kind() == TRACKER_KIND_APP_ROOT; | 705 |
706 const FileTracker* tracker = index_->GetFileTracker(tracker_id); | |
707 return tracker && tracker->tracker_kind() == TRACKER_KIND_APP_ROOT; | |
521 } | 708 } |
522 | 709 |
523 void MetadataDatabase::RegisterApp(const std::string& app_id, | 710 void MetadataDatabase::RegisterApp(const std::string& app_id, |
524 const std::string& folder_id, | 711 const std::string& folder_id, |
525 const SyncStatusCallback& callback) { | 712 const SyncStatusCallback& callback) { |
526 if (FindAppRootTracker(app_id, NULL)) { | 713 if (index_->GetAppRootTracker(app_id)) { |
527 // The app-root is already registered. | 714 // The app-root is already registered. |
528 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK)); | 715 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK)); |
529 return; | 716 return; |
530 } | 717 } |
531 | 718 |
532 TrackerIDSet trackers; | 719 TrackerIDSet trackers = index_->GetFileTrackerIDsByFileID(folder_id); |
533 if (!FindTrackersByFileID(folder_id, &trackers) || trackers.has_active()) { | 720 if (trackers.empty()) { |
721 RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND)); | |
722 return; | |
723 } | |
724 | |
725 if (trackers.has_active()) { | |
534 // The folder is tracked by another tracker. | 726 // The folder is tracked by another tracker. |
535 util::Log(logging::LOG_WARNING, FROM_HERE, | 727 util::Log(logging::LOG_WARNING, FROM_HERE, |
536 "Failed to register App for %s", app_id.c_str()); | 728 "Failed to register App for %s", app_id.c_str()); |
537 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_HAS_CONFLICT)); | 729 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_HAS_CONFLICT)); |
538 return; | 730 return; |
539 } | 731 } |
540 | 732 |
541 int64 sync_root_tracker_id = service_metadata_->sync_root_tracker_id(); | 733 int64 sync_root_tracker_id = service_metadata_->sync_root_tracker_id(); |
542 if (!sync_root_tracker_id) { | 734 if (!sync_root_tracker_id) { |
543 util::Log(logging::LOG_WARNING, FROM_HERE, | 735 util::Log(logging::LOG_WARNING, FROM_HERE, |
544 "Sync-root needs to be set up before registering app-root"); | 736 "Sync-root needs to be set up before registering app-root"); |
545 RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND)); | 737 RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND)); |
546 return; | 738 return; |
547 } | 739 } |
548 | 740 |
549 // Make this tracker an app-root tracker. | 741 scoped_ptr<FileTracker> tracker = |
550 const FileTracker* app_root_tracker = NULL; | 742 Clone(FilterFileTrackersByParent(*index_, trackers, |
551 for (TrackerIDSet::iterator itr = trackers.begin(); | 743 sync_root_tracker_id)); |
552 itr != trackers.end(); ++itr) { | 744 if (!tracker) { |
553 const FileTracker* tracker = tracker_by_id_.get(*itr); | |
554 if (!tracker) { | |
555 NOTREACHED(); | |
556 continue; | |
557 } | |
558 | |
559 if (tracker->parent_tracker_id() == sync_root_tracker_id) | |
560 app_root_tracker = tracker; | |
561 } | |
562 | |
563 if (!app_root_tracker) { | |
564 RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND)); | 745 RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND)); |
565 return; | 746 return; |
566 } | 747 } |
567 | 748 |
568 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); | 749 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); |
569 RegisterTrackerAsAppRoot(app_id, app_root_tracker->tracker_id(), batch.get()); | 750 tracker->set_app_id(app_id); |
751 tracker->set_tracker_kind(TRACKER_KIND_APP_ROOT); | |
752 tracker->set_active(true); | |
753 tracker->set_needs_folder_listing(true); | |
754 tracker->set_dirty(true); | |
755 | |
756 PutFileTrackerToBatch(*tracker, batch.get()); | |
757 index_->StoreFileTracker(tracker.Pass()); | |
570 WriteToDatabase(batch.Pass(), callback); | 758 WriteToDatabase(batch.Pass(), callback); |
571 } | 759 } |
572 | 760 |
573 void MetadataDatabase::DisableApp(const std::string& app_id, | 761 void MetadataDatabase::DisableApp(const std::string& app_id, |
574 const SyncStatusCallback& callback) { | 762 const SyncStatusCallback& callback) { |
575 FileTracker tracker; | 763 int64 tracker_id = index_->GetAppRootTracker(app_id); |
576 if (!FindAppRootTracker(app_id, &tracker)) { | 764 scoped_ptr<FileTracker> tracker = Clone(index_->GetFileTracker(tracker_id)); |
765 if (!tracker) { | |
577 RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND)); | 766 RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND)); |
578 return; | 767 return; |
579 } | 768 } |
580 | 769 |
581 if (tracker.tracker_kind() == TRACKER_KIND_DISABLED_APP_ROOT) { | 770 if (tracker->tracker_kind() == TRACKER_KIND_DISABLED_APP_ROOT) { |
771 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK)); | |
772 return; | |
773 } | |
774 | |
775 DCHECK_EQ(TRACKER_KIND_APP_ROOT, tracker->tracker_kind()); | |
776 DCHECK(tracker->active()); | |
777 | |
778 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); | |
779 | |
780 // Keep the app-root tracker active (but change the tracker_kind) so that | |
781 // other conflicting trackers won't become active. | |
782 tracker->set_tracker_kind(TRACKER_KIND_DISABLED_APP_ROOT); | |
783 | |
784 PutFileTrackerToBatch(*tracker, batch.get()); | |
785 index_->StoreFileTracker(tracker.Pass()); | |
786 WriteToDatabase(batch.Pass(), callback); | |
787 } | |
788 | |
789 void MetadataDatabase::EnableApp(const std::string& app_id, | |
790 const SyncStatusCallback& callback) { | |
791 int64 tracker_id = index_->GetAppRootTracker(app_id); | |
792 scoped_ptr<FileTracker> tracker = Clone(index_->GetFileTracker(tracker_id)); | |
793 if (!tracker) { | |
794 RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND)); | |
795 return; | |
796 } | |
797 | |
798 if (tracker->tracker_kind() == TRACKER_KIND_APP_ROOT) { | |
799 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK)); | |
800 return; | |
801 } | |
802 | |
803 DCHECK_EQ(TRACKER_KIND_DISABLED_APP_ROOT, tracker->tracker_kind()); | |
804 DCHECK(tracker->active()); | |
805 | |
806 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); | |
807 | |
808 tracker->set_tracker_kind(TRACKER_KIND_APP_ROOT); | |
809 PutFileTrackerToBatch(*tracker, batch.get()); | |
810 index_->StoreFileTracker(tracker.Pass()); | |
811 | |
812 MarkTrackersDirtyRecursively(tracker_id, index_.get(), batch.get()); | |
813 WriteToDatabase(batch.Pass(), callback); | |
814 } | |
815 | |
816 void MetadataDatabase::UnregisterApp(const std::string& app_id, | |
817 const SyncStatusCallback& callback) { | |
818 int64 tracker_id = index_->GetAppRootTracker(app_id); | |
819 scoped_ptr<FileTracker> tracker = Clone(index_->GetFileTracker(tracker_id)); | |
820 if (!tracker || tracker->tracker_kind() == TRACKER_KIND_REGULAR) { | |
582 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK)); | 821 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK)); |
583 return; | 822 return; |
584 } | 823 } |
585 | 824 |
586 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); | 825 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); |
587 MakeAppRootDisabled(tracker.tracker_id(), batch.get()); | 826 RemoveAllDescendantTrackers(tracker_id, index_.get(), batch.get()); |
588 WriteToDatabase(batch.Pass(), callback); | |
589 } | |
590 | 827 |
591 void MetadataDatabase::EnableApp(const std::string& app_id, | 828 tracker->clear_app_id(); |
592 const SyncStatusCallback& callback) { | 829 tracker->set_tracker_kind(TRACKER_KIND_REGULAR); |
593 FileTracker tracker; | 830 tracker->set_active(false); |
594 if (!FindAppRootTracker(app_id, &tracker) || | 831 tracker->set_dirty(true); |
595 tracker.tracker_kind() == TRACKER_KIND_REGULAR) { | |
596 RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND)); | |
597 return; | |
598 } | |
599 | 832 |
600 if (tracker.tracker_kind() == TRACKER_KIND_APP_ROOT) { | 833 PutFileTrackerToBatch(*tracker, batch.get()); |
601 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK)); | 834 index_->StoreFileTracker(tracker.Pass()); |
602 return; | |
603 } | |
604 | |
605 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); | |
606 MakeAppRootEnabled(tracker.tracker_id(), batch.get()); | |
607 WriteToDatabase(batch.Pass(), callback); | |
608 } | |
609 | |
610 void MetadataDatabase::UnregisterApp(const std::string& app_id, | |
611 const SyncStatusCallback& callback) { | |
612 FileTracker tracker; | |
613 if (!FindAppRootTracker(app_id, &tracker) || | |
614 tracker.tracker_kind() == TRACKER_KIND_REGULAR) { | |
615 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK)); | |
616 return; | |
617 } | |
618 | |
619 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); | |
620 UnregisterTrackerAsAppRoot(app_id, batch.get()); | |
621 WriteToDatabase(batch.Pass(), callback); | 835 WriteToDatabase(batch.Pass(), callback); |
622 } | 836 } |
623 | 837 |
624 bool MetadataDatabase::FindAppRootTracker(const std::string& app_id, | 838 bool MetadataDatabase::FindAppRootTracker(const std::string& app_id, |
625 FileTracker* tracker) const { | 839 FileTracker* tracker_out) const { |
626 TrackerIDByAppID::const_iterator found = app_root_by_app_id_.find(app_id); | 840 int64 app_root_tracker_id = index_->GetAppRootTracker(app_id); |
627 if (found == app_root_by_app_id_.end()) | 841 if (!app_root_tracker_id) |
628 return false; | 842 return false; |
629 | 843 |
630 if (tracker) | 844 if (tracker_out) { |
631 *tracker = *tracker_by_id_.get(found->second); | 845 const FileTracker* app_root_tracker = |
846 index_->GetFileTracker(app_root_tracker_id); | |
847 if (!app_root_tracker) { | |
848 NOTREACHED(); | |
849 return false; | |
850 } | |
851 *tracker_out = *app_root_tracker; | |
852 } | |
632 return true; | 853 return true; |
633 } | 854 } |
634 | 855 |
635 bool MetadataDatabase::FindFileByFileID(const std::string& file_id, | 856 bool MetadataDatabase::FindFileByFileID(const std::string& file_id, |
636 FileMetadata* file) const { | 857 FileMetadata* metadata_out) const { |
637 return FindItem(metadata_by_id_, file_id, file); | 858 const FileMetadata* metadata = index_->GetFileMetadata(file_id); |
859 if (!metadata) | |
860 return false; | |
861 if (metadata_out) | |
862 *metadata_out = *metadata; | |
863 return true; | |
638 } | 864 } |
639 | 865 |
640 bool MetadataDatabase::FindTrackersByFileID(const std::string& file_id, | 866 bool MetadataDatabase::FindTrackersByFileID(const std::string& file_id, |
641 TrackerIDSet* trackers) const { | 867 TrackerIDSet* trackers_out) const { |
642 TrackerIDsByFileID::const_iterator found = trackers_by_file_id_.find(file_id); | 868 TrackerIDSet trackers = index_->GetFileTrackerIDsByFileID(file_id); |
643 if (found == trackers_by_file_id_.end()) | 869 if (trackers.empty()) |
644 return false; | 870 return false; |
645 if (trackers) | 871 |
646 *trackers = found->second; | 872 if (trackers_out) |
873 std::swap(trackers, *trackers_out); | |
647 return true; | 874 return true; |
648 } | 875 } |
649 | 876 |
650 bool MetadataDatabase::FindTrackersByParentAndTitle( | 877 bool MetadataDatabase::FindTrackersByParentAndTitle( |
651 int64 parent_tracker_id, | 878 int64 parent_tracker_id, |
652 const std::string& title, | 879 const std::string& title, |
653 TrackerIDSet* trackers) const { | 880 TrackerIDSet* trackers_out) const { |
654 TrackerIDsByParentAndTitle::const_iterator found_by_parent = | 881 TrackerIDSet trackers = |
655 trackers_by_parent_and_title_.find(parent_tracker_id); | 882 index_->GetFileTrackerIDsByParentAndTitle(parent_tracker_id, title); |
656 if (found_by_parent == trackers_by_parent_and_title_.end()) | 883 if (trackers.empty()) |
657 return false; | 884 return false; |
658 | 885 |
659 TrackerIDsByTitle::const_iterator found_by_title = | 886 if (trackers_out) |
660 found_by_parent->second.find(title); | 887 std::swap(trackers, *trackers_out); |
661 if (found_by_title == found_by_parent->second.end()) | |
662 return false; | |
663 | |
664 if (trackers) | |
665 *trackers = found_by_title->second; | |
666 return true; | 888 return true; |
667 } | 889 } |
668 | 890 |
669 bool MetadataDatabase::FindTrackerByTrackerID(int64 tracker_id, | 891 bool MetadataDatabase::FindTrackerByTrackerID(int64 tracker_id, |
670 FileTracker* tracker) const { | 892 FileTracker* tracker_out) const { |
671 return FindItem(tracker_by_id_, tracker_id, tracker); | 893 const FileTracker* tracker = index_->GetFileTracker(tracker_id); |
894 if (!tracker) | |
895 return false; | |
896 if (tracker_out) | |
897 *tracker_out = *tracker; | |
898 return true; | |
672 } | 899 } |
673 | 900 |
674 bool MetadataDatabase::BuildPathForTracker(int64 tracker_id, | 901 bool MetadataDatabase::BuildPathForTracker(int64 tracker_id, |
675 base::FilePath* path) const { | 902 base::FilePath* path) const { |
676 FileTracker current; | 903 FileTracker current; |
677 if (!FindTrackerByTrackerID(tracker_id, ¤t) || !current.active()) | 904 if (!FindTrackerByTrackerID(tracker_id, ¤t) || !current.active()) |
678 return false; | 905 return false; |
679 | 906 |
680 std::vector<base::FilePath> components; | 907 std::vector<base::FilePath> components; |
681 while (!IsAppRoot(current)) { | 908 while (!IsAppRoot(current)) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
731 | 958 |
732 for (size_t i = 0; i < components.size(); ++i) { | 959 for (size_t i = 0; i < components.size(); ++i) { |
733 const std::string title = base::FilePath(components[i]).AsUTF8Unsafe(); | 960 const std::string title = base::FilePath(components[i]).AsUTF8Unsafe(); |
734 TrackerIDSet trackers; | 961 TrackerIDSet trackers; |
735 if (!FindTrackersByParentAndTitle( | 962 if (!FindTrackersByParentAndTitle( |
736 tracker_out->tracker_id(), title, &trackers) || | 963 tracker_out->tracker_id(), title, &trackers) || |
737 !trackers.has_active()) { | 964 !trackers.has_active()) { |
738 return true; | 965 return true; |
739 } | 966 } |
740 | 967 |
741 TrackerByID::const_iterator found = | 968 const FileTracker* tracker = |
742 tracker_by_id_.find(trackers.active_tracker()); | 969 index_->GetFileTracker(trackers.active_tracker());; |
743 if (found == tracker_by_id_.end()) { | |
744 NOTREACHED(); | |
745 return false; | |
746 } | |
747 | |
748 FileTracker* tracker = found->second; | |
749 | 970 |
750 DCHECK(tracker->has_synced_details()); | 971 DCHECK(tracker->has_synced_details()); |
751 const FileDetails& details = tracker->synced_details(); | 972 const FileDetails& details = tracker->synced_details(); |
752 if (details.file_kind() != FILE_KIND_FOLDER && i != components.size() - 1) { | 973 if (details.file_kind() != FILE_KIND_FOLDER && i != components.size() - 1) { |
753 // This non-last component indicates file. Give up search. | 974 // This non-last component indicates file. Give up search. |
754 return true; | 975 return true; |
755 } | 976 } |
756 | 977 |
757 *tracker_out = *tracker; | 978 *tracker_out = *tracker; |
758 *path_out = path_out->Append(components[i]); | 979 *path_out = path_out->Append(components[i]); |
759 } | 980 } |
760 | 981 |
761 return true; | 982 return true; |
762 } | 983 } |
763 | 984 |
764 void MetadataDatabase::UpdateByChangeList( | 985 void MetadataDatabase::UpdateByChangeList( |
765 int64 largest_change_id, | 986 int64 largest_change_id, |
766 ScopedVector<google_apis::ChangeResource> changes, | 987 ScopedVector<google_apis::ChangeResource> changes, |
767 const SyncStatusCallback& callback) { | 988 const SyncStatusCallback& callback) { |
768 DCHECK_LE(service_metadata_->largest_change_id(), largest_change_id); | 989 DCHECK_LE(service_metadata_->largest_change_id(), largest_change_id); |
769 | 990 |
770 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); | 991 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); |
771 | 992 |
772 for (ScopedVector<google_apis::ChangeResource>::const_iterator itr = | 993 for (size_t i = 0; i < changes.size(); ++i) { |
773 changes.begin(); | 994 const google_apis::ChangeResource& change = *changes[i]; |
774 itr != changes.end(); | |
775 ++itr) { | |
776 const google_apis::ChangeResource& change = **itr; | |
777 if (HasNewerFileMetadata(change.file_id(), change.change_id())) | 995 if (HasNewerFileMetadata(change.file_id(), change.change_id())) |
778 continue; | 996 continue; |
779 | 997 |
780 scoped_ptr<FileMetadata> metadata( | 998 scoped_ptr<FileMetadata> metadata( |
781 CreateFileMetadataFromChangeResource(change)); | 999 CreateFileMetadataFromChangeResource(change)); |
782 UpdateByFileMetadata(FROM_HERE, metadata.Pass(), | 1000 UpdateByFileMetadata(FROM_HERE, metadata.Pass(), |
783 UPDATE_TRACKER_FOR_UNSYNCED_FILE, | 1001 UPDATE_TRACKER_FOR_UNSYNCED_FILE, |
784 batch.get()); | 1002 batch.get()); |
785 } | 1003 } |
786 | 1004 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
844 UPDATE_TRACKER_FOR_UNSYNCED_FILE, | 1062 UPDATE_TRACKER_FOR_UNSYNCED_FILE, |
845 batch.get()); | 1063 batch.get()); |
846 } | 1064 } |
847 WriteToDatabase(batch.Pass(), callback); | 1065 WriteToDatabase(batch.Pass(), callback); |
848 } | 1066 } |
849 | 1067 |
850 void MetadataDatabase::ReplaceActiveTrackerWithNewResource( | 1068 void MetadataDatabase::ReplaceActiveTrackerWithNewResource( |
851 int64 parent_tracker_id, | 1069 int64 parent_tracker_id, |
852 const google_apis::FileResource& resource, | 1070 const google_apis::FileResource& resource, |
853 const SyncStatusCallback& callback) { | 1071 const SyncStatusCallback& callback) { |
1072 DCHECK(index_->GetFileTracker(parent_tracker_id)); | |
1073 DCHECK(!index_->GetFileMetadata(resource.file_id())); | |
1074 | |
854 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); | 1075 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); |
855 | |
856 DCHECK(!ContainsKey(metadata_by_id_, resource.file_id())); | |
857 UpdateByFileMetadata( | 1076 UpdateByFileMetadata( |
858 FROM_HERE, | 1077 FROM_HERE, |
859 CreateFileMetadataFromFileResource(GetLargestKnownChangeID(), resource), | 1078 CreateFileMetadataFromFileResource(GetLargestKnownChangeID(), resource), |
860 UPDATE_TRACKER_FOR_SYNCED_FILE, | 1079 UPDATE_TRACKER_FOR_SYNCED_FILE, |
861 batch.get()); | 1080 batch.get()); |
862 DCHECK(ContainsKey(metadata_by_id_, resource.file_id())); | |
863 | 1081 |
864 ForceActivateTrackerByPath( | 1082 DCHECK(index_->GetFileMetadata(resource.file_id())); |
865 parent_tracker_id, resource.title(), resource.file_id(), batch.get()); | 1083 DCHECK(!index_->GetFileTrackerIDsByFileID(resource.file_id()).has_active()); |
866 | 1084 |
1085 TrackerIDSet same_path_trackers = | |
1086 index_->GetFileTrackerIDsByParentAndTitle( | |
1087 parent_tracker_id, resource.title()); | |
1088 const FileTracker* to_be_activated = | |
1089 FilterFileTrackersByFileID(*index_, same_path_trackers, | |
1090 resource.file_id()); | |
1091 if (!to_be_activated) { | |
1092 NOTREACHED(); | |
1093 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_FAILED)); | |
1094 return; | |
1095 } | |
1096 | |
1097 int64 tracker_id = to_be_activated->tracker_id(); | |
1098 if (same_path_trackers.has_active()) { | |
1099 DeactivateFileTracker(same_path_trackers.active_tracker(), | |
1100 MARK_ITSELF_DIRTY | | |
1101 MARK_SAME_FILE_ID_TRACKERS_DIRTY, | |
1102 index_.get(), batch.get()); | |
1103 } | |
1104 | |
1105 ActivateFileTracker(tracker_id, MARK_NOTHING_DIRTY, | |
1106 index_.get(), batch.get()); | |
867 WriteToDatabase(batch.Pass(), callback); | 1107 WriteToDatabase(batch.Pass(), callback); |
868 } | 1108 } |
869 | 1109 |
870 void MetadataDatabase::PopulateFolderByChildList( | 1110 void MetadataDatabase::PopulateFolderByChildList( |
871 const std::string& folder_id, | 1111 const std::string& folder_id, |
872 const FileIDList& child_file_ids, | 1112 const FileIDList& child_file_ids, |
873 const SyncStatusCallback& callback) { | 1113 const SyncStatusCallback& callback) { |
874 TrackerIDSet trackers; | 1114 TrackerIDSet trackers = index_->GetFileTrackerIDsByFileID(folder_id); |
875 if (!FindTrackersByFileID(folder_id, &trackers) || | 1115 if (!trackers.has_active()) { |
876 !trackers.has_active()) { | |
877 // It's OK that there is no folder to populate its children. | 1116 // It's OK that there is no folder to populate its children. |
878 // Inactive folders should ignore their contents updates. | 1117 // Inactive folders should ignore their contents updates. |
879 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK)); | 1118 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK)); |
880 return; | 1119 return; |
881 } | 1120 } |
882 | 1121 |
883 FileTracker* folder_tracker = tracker_by_id_.get(trackers.active_tracker()); | 1122 scoped_ptr<FileTracker> folder_tracker = |
884 DCHECK(folder_tracker); | 1123 Clone(index_->GetFileTracker(trackers.active_tracker())); |
885 std::set<std::string> children(child_file_ids.begin(), child_file_ids.end()); | 1124 if (!folder_tracker) { |
1125 NOTREACHED(); | |
1126 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_FAILED)); | |
1127 return; | |
1128 } | |
886 | 1129 |
887 std::vector<int64> known_children; | 1130 base::hash_set<std::string> children(child_file_ids.begin(), |
888 PushChildTrackersToContainer(trackers_by_parent_and_title_, | 1131 child_file_ids.end()); |
nhiroki
2014/03/05 06:21:35
indent-nit
tzik
2014/03/05 07:05:54
Done.
| |
889 folder_tracker->tracker_id(), | 1132 |
890 std::back_inserter(known_children)); | 1133 std::vector<int64> known_children = |
891 for (std::vector<int64>::iterator itr = known_children.begin(); | 1134 index_->GetFileTrackerIDsByParent(folder_tracker->tracker_id()); |
892 itr != known_children.end(); ++itr) | 1135 for (size_t i = 0; i < known_children.size(); ++i) { |
893 children.erase(tracker_by_id_.get(*itr)->file_id()); | 1136 const FileTracker* tracker = index_->GetFileTracker(known_children[i]); |
1137 if (!tracker) { | |
1138 NOTREACHED(); | |
1139 continue; | |
1140 } | |
1141 children.erase(tracker->file_id()); | |
1142 } | |
894 | 1143 |
895 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); | 1144 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); |
896 for (FileIDList::const_iterator itr = child_file_ids.begin(); | 1145 for (base::hash_set<std::string>::const_iterator itr = children.begin(); |
897 itr != child_file_ids.end(); ++itr) | 1146 itr != children.end(); ++itr) |
898 CreateTrackerForParentAndFileID(*folder_tracker, *itr, batch.get()); | 1147 CreateTrackerForParentAndFileID(*folder_tracker, *itr, batch.get()); |
899 folder_tracker->set_needs_folder_listing(false); | 1148 folder_tracker->set_needs_folder_listing(false); |
900 if (folder_tracker->dirty() && !ShouldKeepDirty(*folder_tracker)) | 1149 if (folder_tracker->dirty() && !ShouldKeepDirty(*folder_tracker)) |
901 ClearDirty(folder_tracker, NULL); | 1150 folder_tracker->set_dirty(false); |
902 PutFileTrackerToBatch(*folder_tracker, batch.get()); | 1151 PutFileTrackerToBatch(*folder_tracker, batch.get()); |
1152 index_->StoreFileTracker(folder_tracker.Pass()); | |
903 | 1153 |
904 WriteToDatabase(batch.Pass(), callback); | 1154 WriteToDatabase(batch.Pass(), callback); |
905 } | 1155 } |
906 | 1156 |
907 void MetadataDatabase::UpdateTracker(int64 tracker_id, | 1157 void MetadataDatabase::UpdateTracker(int64 tracker_id, |
908 const FileDetails& updated_details, | 1158 const FileDetails& updated_details, |
909 const SyncStatusCallback& callback) { | 1159 const SyncStatusCallback& callback) { |
910 TrackerByID::iterator found = tracker_by_id_.find(tracker_id); | 1160 const FileTracker* tracker = index_->GetFileTracker(tracker_id); |
911 if (found == tracker_by_id_.end()) { | 1161 if (!tracker) { |
912 RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND)); | 1162 RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND)); |
913 return; | 1163 return; |
914 } | 1164 } |
915 | |
916 FileTracker* tracker = found->second; | |
917 DCHECK(tracker); | 1165 DCHECK(tracker); |
918 | 1166 |
919 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); | 1167 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); |
920 | 1168 |
1169 // Check if the tracker is to be deleted. | |
921 if (updated_details.missing()) { | 1170 if (updated_details.missing()) { |
922 MetadataByID::iterator found = metadata_by_id_.find(tracker->file_id()); | 1171 const FileMetadata* metadata = index_->GetFileMetadata(tracker->file_id()); |
923 if (found == metadata_by_id_.end() || found->second->details().missing()) { | 1172 if (!metadata || metadata->details().missing()) { |
924 // Both the tracker and metadata have the missing flag, now it's safe to | 1173 // Both the tracker and metadata have the missing flag, now it's safe to |
925 // delete the |tracker|. | 1174 // delete the |tracker|. |
926 RemoveTracker(tracker->tracker_id(), batch.get()); | 1175 RemoveTracker(tracker_id, |
1176 MARK_SAME_FILE_ID_TRACKERS_DIRTY | | |
1177 MARK_SAME_PATH_TRACKERS_DIRTY, | |
1178 index_.get(), batch.get()); | |
927 WriteToDatabase(batch.Pass(), callback); | 1179 WriteToDatabase(batch.Pass(), callback); |
928 return; | 1180 return; |
929 } | 1181 } |
930 } | 1182 } |
931 | 1183 |
932 // Sync-root deletion should be handled separately by SyncEngine. | 1184 // Sync-root deletion should be handled separately by SyncEngine. |
933 DCHECK(tracker_id != GetSyncRootTrackerID() || | 1185 DCHECK(tracker_id != GetSyncRootTrackerID() || |
934 (tracker->has_synced_details() && | 1186 (tracker->has_synced_details() && |
935 tracker->synced_details().title() == updated_details.title() && | 1187 tracker->synced_details().title() == updated_details.title() && |
936 !updated_details.missing())); | 1188 !updated_details.missing())); |
937 | 1189 |
938 if (tracker_id != GetSyncRootTrackerID()) { | 1190 if (tracker_id != GetSyncRootTrackerID()) { |
939 // Check if the tracker's parent is still in |parent_tracker_ids|. | 1191 // Check if the tracker's parent is still in |parent_tracker_ids|. |
940 // If not, there should exist another tracker for the new parent, so delete | 1192 // If not, there should exist another tracker for the new parent, so delete |
941 // old tracker. | 1193 // old tracker. |
942 DCHECK(ContainsKey(tracker_by_id_, tracker->parent_tracker_id())); | 1194 const FileTracker* parent_tracker = |
943 FileTracker* parent_tracker = | 1195 index_->GetFileTracker(tracker->parent_tracker_id()); |
944 tracker_by_id_.get(tracker->parent_tracker_id()); | 1196 DCHECK(parent_tracker); |
1197 | |
945 if (!HasFileAsParent(updated_details, parent_tracker->file_id())) { | 1198 if (!HasFileAsParent(updated_details, parent_tracker->file_id())) { |
946 RemoveTracker(tracker->tracker_id(), batch.get()); | 1199 RemoveTracker(tracker->tracker_id(), |
1200 MARK_SAME_PATH_TRACKERS_DIRTY, | |
1201 index_.get(), batch.get()); | |
947 WriteToDatabase(batch.Pass(), callback); | 1202 WriteToDatabase(batch.Pass(), callback); |
948 return; | 1203 return; |
949 } | 1204 } |
950 | 1205 |
951 if (tracker->has_synced_details()) { | 1206 if (tracker->has_synced_details()) { |
952 // Check if the tracker was retitled. If it was, there should exist | 1207 // Check if the tracker was retitled. If it was, there should exist |
953 // another tracker for the new title, so delete old tracker. | 1208 // another tracker for the new title, so delete the tracker being updated. |
954 if (tracker->synced_details().title() != updated_details.title()) { | 1209 if (tracker->synced_details().title() != updated_details.title()) { |
955 RemoveTracker(tracker->tracker_id(), batch.get()); | 1210 RemoveTracker(tracker->tracker_id(), |
1211 MARK_SAME_FILE_ID_TRACKERS_DIRTY, | |
1212 index_.get(), batch.get()); | |
956 WriteToDatabase(batch.Pass(), callback); | 1213 WriteToDatabase(batch.Pass(), callback); |
957 return; | 1214 return; |
958 } | 1215 } |
959 } else { | 1216 } else { |
960 int64 parent_tracker_id = parent_tracker->tracker_id(); | 1217 // Check if any other tracker exists has the same parent, title and |
kinuko
2014/03/05 07:41:32
exists has -> "has", or "exists and has" ?
| |
961 const std::string& title = updated_details.title(); | 1218 // file_id to the updated tracker. If it exists, delete the tracker being |
962 TrackerIDSet* trackers = | 1219 // updated. |
963 &trackers_by_parent_and_title_[parent_tracker_id][title]; | 1220 if (FilterFileTrackersByFileID( |
964 | 1221 *index_, |
965 for (TrackerIDSet::iterator itr = trackers->begin(); | 1222 index_->GetFileTrackerIDsByParentAndTitle( |
966 itr != trackers->end(); ++itr) { | 1223 parent_tracker->tracker_id(), |
967 FileTracker* same_path_tracker = tracker_by_id_.get(*itr); | 1224 updated_details.title()), |
968 if (!same_path_tracker) { | 1225 tracker->file_id())) { |
969 NOTREACHED(); | 1226 RemoveTracker(tracker->tracker_id(), |
970 continue; | 1227 MARK_NOTHING_DIRTY, |
971 } | 1228 index_.get(), batch.get()); |
972 | 1229 WriteToDatabase(batch.Pass(), callback); |
973 if (same_path_tracker->file_id() == tracker->file_id()) { | 1230 return; |
974 RemoveTracker(tracker->tracker_id(), batch.get()); | |
975 WriteToDatabase(batch.Pass(), callback); | |
976 return; | |
977 } | |
978 } | 1231 } |
979 | |
980 trackers_by_parent_and_title_[parent_tracker_id][std::string()].Erase( | |
981 tracker_id); | |
982 trackers->Insert(*tracker); | |
983 } | 1232 } |
984 } | 1233 } |
985 | 1234 |
986 *tracker->mutable_synced_details() = updated_details; | 1235 scoped_ptr<FileTracker> updated_tracker = Clone(tracker); |
1236 *updated_tracker->mutable_synced_details() = updated_details; | |
987 | 1237 |
988 // Activate the tracker if: | 1238 // Activate the tracker if: |
989 // - There is no active tracker that tracks |tracker->file_id()|. | 1239 // - There is no active tracker that tracks |tracker->file_id()|. |
990 // - There is no active tracker that has the same |parent| and |title|. | 1240 // - There is no active tracker that has the same |parent| and |title|. |
991 if (!tracker->active() && CanActivateTracker(*tracker)) | 1241 if (!tracker->active() && CanActivateTracker(*tracker)) { |
992 MakeTrackerActive(tracker->tracker_id(), batch.get()); | 1242 updated_tracker->set_active(true); |
993 if (tracker->dirty() && !ShouldKeepDirty(*tracker)) | 1243 updated_tracker->set_dirty(true); |
994 ClearDirty(tracker, NULL); | 1244 updated_tracker->set_needs_folder_listing( |
1245 tracker->synced_details().file_kind() == FILE_KIND_FOLDER); | |
1246 } else if (tracker->dirty() && !ShouldKeepDirty(*tracker)) { | |
1247 updated_tracker->set_dirty(false); | |
1248 } | |
995 PutFileTrackerToBatch(*tracker, batch.get()); | 1249 PutFileTrackerToBatch(*tracker, batch.get()); |
1250 index_->StoreFileTracker(updated_tracker.Pass()); | |
996 | 1251 |
997 WriteToDatabase(batch.Pass(), callback); | 1252 WriteToDatabase(batch.Pass(), callback); |
998 } | 1253 } |
999 | 1254 |
1000 MetadataDatabase::ActivationStatus MetadataDatabase::TryActivateTracker( | 1255 MetadataDatabase::ActivationStatus MetadataDatabase::TryActivateTracker( |
1001 int64 parent_tracker_id, | 1256 int64 parent_tracker_id, |
1002 const std::string& file_id, | 1257 const std::string& file_id, |
1003 const SyncStatusCallback& callback) { | 1258 const SyncStatusCallback& callback) { |
1004 DCHECK(ContainsKey(tracker_by_id_, parent_tracker_id)); | 1259 DCHECK(index_->GetFileTracker(parent_tracker_id)); |
1005 DCHECK(ContainsKey(metadata_by_id_, file_id)); | |
1006 | 1260 |
1007 FileMetadata metadata; | 1261 const FileMetadata* metadata = index_->GetFileMetadata(file_id); |
1008 if (!FindFileByFileID(file_id, &metadata)) { | 1262 if (!metadata) { |
1009 NOTREACHED(); | 1263 NOTREACHED(); |
1010 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_FAILED)); | 1264 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_FAILED)); |
1011 return ACTIVATION_PENDING; | 1265 return ACTIVATION_PENDING; |
1012 } | 1266 } |
1013 std::string title = metadata.details().title(); | 1267 std::string title = metadata->details().title(); |
1014 DCHECK(!HasInvalidTitle(title)); | 1268 DCHECK(!HasInvalidTitle(title)); |
1015 | 1269 |
1016 TrackerIDSet same_file_id; | 1270 TrackerIDSet same_file_id_trackers = |
1017 FindTrackersByFileID(file_id, &same_file_id); | 1271 index_->GetFileTrackerIDsByFileID(file_id); |
1018 | 1272 scoped_ptr<FileTracker> tracker_to_be_activated = |
1019 // Pick up the tracker to be activated, that has: | 1273 Clone(FilterFileTrackersByParentAndTitle( |
1020 // - |parent_tarcker_id| as the parent, and | 1274 *index_, same_file_id_trackers, |
1021 // - |file_id| as the tracker's |file_id|. | 1275 parent_tracker_id, title)); |
1022 FileTracker* tracker = NULL; | 1276 DCHECK(tracker_to_be_activated); |
1023 for (TrackerIDSet::iterator itr = same_file_id.begin(); | |
1024 itr != same_file_id.end(); ++itr) { | |
1025 FileTracker* candidate = tracker_by_id_.get(*itr); | |
1026 if (!candidate) { | |
1027 NOTREACHED(); | |
1028 continue; | |
1029 } | |
1030 | |
1031 if (candidate->parent_tracker_id() != parent_tracker_id) | |
1032 continue; | |
1033 | |
1034 if (candidate->has_synced_details() && | |
1035 candidate->synced_details().title() != title) | |
1036 continue; | |
1037 tracker = candidate; | |
1038 } | |
1039 | |
1040 DCHECK(tracker); | |
1041 | 1277 |
1042 // Check if there is another active tracker that tracks |file_id|. | 1278 // Check if there is another active tracker that tracks |file_id|. |
1043 // This can happen when the tracked file has multiple parents. | 1279 // This can happen when the tracked file has multiple parents. |
1044 // In this case, report the failure to the caller. | 1280 // In this case, report the failure to the caller. |
1045 if (!tracker->active() && same_file_id.has_active()) | 1281 if (!tracker_to_be_activated->active() && same_file_id_trackers.has_active()) |
1046 return ACTIVATION_FAILED_ANOTHER_ACTIVE_TRACKER; | 1282 return ACTIVATION_FAILED_ANOTHER_ACTIVE_TRACKER; |
1047 | 1283 |
1048 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); | 1284 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); |
1049 | 1285 |
1050 if (!tracker->active()) { | 1286 if (!tracker_to_be_activated->active()) { |
1051 // Check if there is another active tracker that has the same path to | 1287 // Check if there exists another active tracker that has the same path to |
1052 // the tracker to be activated. | 1288 // the tracker. If there is, deactivate it, assuming the caller already |
1053 // Assuming the caller already overrides local file with newly added file, | 1289 // overrides local file with newly added file, |
1054 // inactivate existing active tracker. | 1290 TrackerIDSet same_title_trackers = |
1055 TrackerIDSet same_title; | 1291 index_->GetFileTrackerIDsByParentAndTitle(parent_tracker_id, title); |
1056 FindTrackersByParentAndTitle(parent_tracker_id, title, &same_title); | 1292 if (same_title_trackers.has_active()) { |
1057 if (same_title.has_active()) { | 1293 RemoveAllDescendantTrackers(same_title_trackers.active_tracker(), |
1058 MakeTrackerInactive(same_title.active_tracker(), batch.get()); | 1294 index_.get(), batch.get()); |
1295 | |
1296 scoped_ptr<FileTracker> tracker_to_be_deactivated = | |
1297 Clone(index_->GetFileTracker(same_title_trackers.active_tracker())); | |
1298 if (tracker_to_be_deactivated) { | |
1299 const std::string file_id = tracker_to_be_deactivated->file_id(); | |
1300 tracker_to_be_deactivated->set_active(false); | |
1301 PutFileTrackerToBatch(*tracker_to_be_deactivated, batch.get()); | |
1302 index_->StoreFileTracker(tracker_to_be_deactivated.Pass()); | |
1303 | |
1304 MarkTrackersDirtyByFileID(file_id, index_.get(), batch.get()); | |
1305 } else { | |
1306 LOG(ERROR) << "HERE"; | |
kinuko
2014/03/05 07:41:32
?
tzik
2014/03/05 08:23:41
Awww. It's a remnant of my local debugging.
Remove
| |
1307 NOTREACHED(); | |
1308 } | |
1059 } | 1309 } |
1060 } | 1310 } |
1061 | 1311 |
1062 if (!tracker->has_synced_details() || | 1312 tracker_to_be_activated->set_dirty(false); |
1063 tracker->synced_details().title() != title) { | 1313 tracker_to_be_activated->set_active(true); |
1064 trackers_by_parent_and_title_[parent_tracker_id] | 1314 *tracker_to_be_activated->mutable_synced_details() = metadata->details(); |
1065 [GetTrackerTitle(*tracker)].Erase(tracker->tracker_id()); | 1315 if (tracker_to_be_activated->synced_details().file_kind() == |
1066 trackers_by_parent_and_title_[parent_tracker_id][title] | 1316 FILE_KIND_FOLDER) { |
1067 .InsertInactiveTracker(tracker->tracker_id()); | 1317 tracker_to_be_activated->set_needs_folder_listing(true); |
1068 } | 1318 } |
1069 *tracker->mutable_synced_details() = metadata.details(); | 1319 tracker_to_be_activated->set_dirty(false); |
1070 | 1320 |
1071 MakeTrackerActive(tracker->tracker_id(), batch.get()); | 1321 PutFileTrackerToBatch(*tracker_to_be_activated, batch.get()); |
1072 ClearDirty(tracker_by_id_.get(tracker->tracker_id()), batch.get()); | 1322 index_->StoreFileTracker(tracker_to_be_activated.Pass()); |
1073 | 1323 |
1074 WriteToDatabase(batch.Pass(), callback); | 1324 WriteToDatabase(batch.Pass(), callback); |
1075 return ACTIVATION_PENDING; | 1325 return ACTIVATION_PENDING; |
1076 } | 1326 } |
1077 | 1327 |
1078 void MetadataDatabase::LowerTrackerPriority(int64 tracker_id) { | 1328 void MetadataDatabase::LowerTrackerPriority(int64 tracker_id) { |
1079 TrackerByID::const_iterator found = tracker_by_id_.find(tracker_id); | 1329 index_->DemoteDirtyTracker(tracker_id); |
1080 if (found == tracker_by_id_.end()) | |
1081 return; | |
1082 | |
1083 FileTracker* tracker = found->second; | |
1084 if (dirty_trackers_.erase(tracker)) | |
1085 low_priority_dirty_trackers_.insert(tracker); | |
1086 } | 1330 } |
1087 | 1331 |
1088 void MetadataDatabase::PromoteLowerPriorityTrackersToNormal() { | 1332 void MetadataDatabase::PromoteLowerPriorityTrackersToNormal() { |
1089 if (dirty_trackers_.empty()) { | 1333 index_->PromoteDemotedDirtyTrackers(); |
1090 dirty_trackers_.swap(low_priority_dirty_trackers_); | |
1091 return; | |
1092 } | |
1093 dirty_trackers_.insert(low_priority_dirty_trackers_.begin(), | |
1094 low_priority_dirty_trackers_.end()); | |
1095 low_priority_dirty_trackers_.clear(); | |
1096 } | 1334 } |
1097 | 1335 |
1098 bool MetadataDatabase::GetNormalPriorityDirtyTracker( | 1336 bool MetadataDatabase::GetNormalPriorityDirtyTracker( |
1099 FileTracker* tracker) const { | 1337 FileTracker* tracker_out) const { |
1100 DirtyTrackers::const_iterator itr = dirty_trackers_.begin(); | 1338 int64 dirty_tracker_id = index_->PickDirtyTracker(); |
1101 if (itr == dirty_trackers_.end()) | 1339 if (!dirty_tracker_id) |
1102 return false; | 1340 return false; |
1103 if (tracker) | 1341 |
1104 *tracker = **itr; | 1342 if (tracker_out) { |
1343 const FileTracker* tracker = | |
1344 index_->GetFileTracker(dirty_tracker_id); | |
1345 if (!tracker) { | |
1346 NOTREACHED(); | |
1347 return false; | |
1348 } | |
1349 *tracker_out = *tracker; | |
1350 } | |
1105 return true; | 1351 return true; |
1106 } | 1352 } |
1107 | 1353 |
1108 bool MetadataDatabase::HasLowPriorityDirtyTracker() const { | 1354 bool MetadataDatabase::HasLowPriorityDirtyTracker() const { |
1109 return !low_priority_dirty_trackers_.empty(); | 1355 return index_->HasDemotedDirtyTracker(); |
1110 } | 1356 } |
1111 | 1357 |
1112 bool MetadataDatabase::HasDirtyTracker() const { | 1358 bool MetadataDatabase::HasDirtyTracker() const { |
1113 return CountDirtyTracker() != 0; | 1359 return index_->PickDirtyTracker() != kInvalidTrackerID; |
1114 } | 1360 } |
1115 | 1361 |
1116 size_t MetadataDatabase::CountDirtyTracker() const { | 1362 size_t MetadataDatabase::CountDirtyTracker() const { |
1117 return dirty_trackers_.size() + low_priority_dirty_trackers_.size(); | 1363 return index_->dirty_trackers_.size() + |
1364 index_->demoted_dirty_trackers_.size(); | |
1365 } | |
1366 | |
1367 bool MetadataDatabase::GetMultiParentFileTrackers(std::string* file_id_out, | |
1368 TrackerIDSet* trackers_out) { | |
1369 DCHECK(file_id_out); | |
1370 DCHECK(trackers_out); | |
1371 | |
1372 std::string file_id = index_->PickMultiTrackerFileID(); | |
1373 if (file_id.empty()) | |
1374 return false; | |
1375 | |
1376 TrackerIDSet trackers = index_->GetFileTrackerIDsByFileID(file_id); | |
1377 if (trackers.size() <= 1) { | |
1378 NOTREACHED(); | |
1379 return false; | |
1380 } | |
1381 | |
1382 *file_id_out = file_id; | |
1383 std::swap(*trackers_out, trackers); | |
1384 return true; | |
1118 } | 1385 } |
1119 | 1386 |
1120 size_t MetadataDatabase::CountFileMetadata() const { | 1387 size_t MetadataDatabase::CountFileMetadata() const { |
1121 return metadata_by_id_.size(); | 1388 return index_->metadata_by_id_.size(); |
1122 } | 1389 } |
1123 | 1390 |
1124 size_t MetadataDatabase::CountFileTracker() const { | 1391 size_t MetadataDatabase::CountFileTracker() const { |
1125 return tracker_by_id_.size(); | 1392 return index_->tracker_by_id_.size(); |
1126 } | 1393 } |
1127 | 1394 |
1128 bool MetadataDatabase::GetMultiParentFileTrackers(std::string* file_id, | 1395 bool MetadataDatabase::GetConflictingTrackers(TrackerIDSet* trackers_out) { |
1129 TrackerIDSet* trackers) { | 1396 DCHECK(trackers_out); |
1130 DCHECK(file_id); | 1397 |
1131 DCHECK(trackers); | 1398 ParentIDAndTitle parent_and_title = index_->PickMultiBackingFilePath(); |
1132 // TODO(tzik): Make this function more efficient. | 1399 if (parent_and_title.parent_id == kInvalidTrackerID) |
1133 for (TrackerIDsByFileID::const_iterator itr = trackers_by_file_id_.begin(); | 1400 return false; |
1134 itr != trackers_by_file_id_.end(); ++itr) { | 1401 |
1135 if (itr->second.size() > 1 && itr->second.has_active()) { | 1402 TrackerIDSet trackers = index_->GetFileTrackerIDsByParentAndTitle( |
1136 *file_id = itr->first; | 1403 parent_and_title.parent_id, parent_and_title.title); |
1137 *trackers = itr->second; | 1404 if (trackers.size() <= 1) { |
1138 return true; | 1405 NOTREACHED(); |
1139 } | 1406 return false; |
1140 } | 1407 } |
1141 return false; | |
1142 } | |
1143 | 1408 |
1144 bool MetadataDatabase::GetConflictingTrackers(TrackerIDSet* trackers) { | 1409 std::swap(*trackers_out, trackers); |
1145 DCHECK(trackers); | 1410 return true; |
1146 // TODO(tzik): Make this function more efficient. | |
1147 for (TrackerIDsByParentAndTitle::const_iterator parent_itr = | |
1148 trackers_by_parent_and_title_.begin(); | |
1149 parent_itr != trackers_by_parent_and_title_.end(); | |
1150 ++parent_itr) { | |
1151 const TrackerIDsByTitle& trackers_by_title = parent_itr->second; | |
1152 for (TrackerIDsByTitle::const_iterator itr = trackers_by_title.begin(); | |
1153 itr != trackers_by_title.end(); | |
1154 ++itr) { | |
1155 if (itr->second.size() > 1 && itr->second.has_active()) { | |
1156 *trackers = itr->second; | |
1157 return true; | |
1158 } | |
1159 } | |
1160 } | |
1161 return false; | |
1162 } | 1411 } |
1163 | 1412 |
1164 void MetadataDatabase::GetRegisteredAppIDs(std::vector<std::string>* app_ids) { | 1413 void MetadataDatabase::GetRegisteredAppIDs(std::vector<std::string>* app_ids) { |
1165 DCHECK(app_ids); | 1414 DCHECK(app_ids); |
1166 app_ids->clear(); | 1415 *app_ids = index_->GetRegisteredAppIDs(); |
1167 app_ids->reserve(app_root_by_app_id_.size()); | |
1168 for (TrackerIDByAppID::iterator itr = app_root_by_app_id_.begin(); | |
1169 itr != app_root_by_app_id_.end(); ++itr) { | |
1170 app_ids->push_back(itr->first); | |
1171 } | |
1172 } | 1416 } |
1173 | 1417 |
1174 MetadataDatabase::MetadataDatabase(base::SequencedTaskRunner* task_runner, | 1418 MetadataDatabase::MetadataDatabase(base::SequencedTaskRunner* task_runner, |
1175 const base::FilePath& database_path, | 1419 const base::FilePath& database_path, |
1176 leveldb::Env* env_override) | 1420 leveldb::Env* env_override) |
1177 : task_runner_(task_runner), | 1421 : task_runner_(task_runner), |
1178 database_path_(database_path), | 1422 database_path_(database_path), |
1179 env_override_(env_override), | 1423 env_override_(env_override), |
1180 largest_known_change_id_(0), | 1424 largest_known_change_id_(0), |
1181 weak_ptr_factory_(this) { | 1425 weak_ptr_factory_(this) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1242 if (status != SYNC_STATUS_OK) | 1486 if (status != SYNC_STATUS_OK) |
1243 return status; | 1487 return status; |
1244 | 1488 |
1245 BuildIndexes(&contents); | 1489 BuildIndexes(&contents); |
1246 return status; | 1490 return status; |
1247 } | 1491 } |
1248 | 1492 |
1249 void MetadataDatabase::BuildIndexes(DatabaseContents* contents) { | 1493 void MetadataDatabase::BuildIndexes(DatabaseContents* contents) { |
1250 service_metadata_ = contents->service_metadata.Pass(); | 1494 service_metadata_ = contents->service_metadata.Pass(); |
1251 UpdateLargestKnownChangeID(service_metadata_->largest_change_id()); | 1495 UpdateLargestKnownChangeID(service_metadata_->largest_change_id()); |
1252 | 1496 index_.reset(new MetadataDatabaseIndex(contents)); |
1253 for (ScopedVector<FileMetadata>::const_iterator itr = | |
1254 contents->file_metadata.begin(); | |
1255 itr != contents->file_metadata.end(); | |
1256 ++itr) { | |
1257 // make_scoped_ptr balances weak_clear below. | |
1258 metadata_by_id_.set((*itr)->file_id(), make_scoped_ptr(*itr)); | |
1259 } | |
1260 contents->file_metadata.weak_clear(); | |
1261 | |
1262 for (ScopedVector<FileTracker>::const_iterator itr = | |
1263 contents->file_trackers.begin(); | |
1264 itr != contents->file_trackers.end(); | |
1265 ++itr) { | |
1266 FileTracker* tracker = *itr; | |
1267 // make_scoped_ptr balances weak_clear below. | |
1268 tracker_by_id_.set(tracker->tracker_id(), make_scoped_ptr(tracker)); | |
1269 trackers_by_file_id_[tracker->file_id()].Insert(*tracker); | |
1270 | |
1271 if (IsAppRoot(*tracker)) | |
1272 app_root_by_app_id_[tracker->app_id()] = tracker->tracker_id(); | |
1273 | |
1274 if (tracker->parent_tracker_id()) { | |
1275 std::string title = GetTrackerTitle(*tracker); | |
1276 TrackerIDSet* trackers = | |
1277 &trackers_by_parent_and_title_[tracker->parent_tracker_id()][title]; | |
1278 trackers->Insert(*tracker); | |
1279 } | |
1280 | |
1281 if (tracker->dirty()) | |
1282 dirty_trackers_.insert(tracker); | |
1283 } | |
1284 contents->file_trackers.weak_clear(); | |
1285 } | |
1286 | |
1287 void MetadataDatabase::RegisterTrackerAsAppRoot( | |
1288 const std::string& app_id, | |
1289 int64 tracker_id, | |
1290 leveldb::WriteBatch* batch) { | |
1291 FileTracker* tracker = tracker_by_id_.get(tracker_id); | |
1292 DCHECK(tracker); | |
1293 tracker->set_app_id(app_id); | |
1294 tracker->set_tracker_kind(TRACKER_KIND_APP_ROOT); | |
1295 app_root_by_app_id_[app_id] = tracker_id; | |
1296 | |
1297 MakeTrackerActive(tracker->tracker_id(), batch); | |
1298 } | |
1299 | |
1300 void MetadataDatabase::UnregisterTrackerAsAppRoot( | |
1301 const std::string& app_id, | |
1302 leveldb::WriteBatch* batch) { | |
1303 int64 tracker_id = FindAndEraseItem(&app_root_by_app_id_, app_id); | |
1304 FileTracker* tracker = tracker_by_id_.get(tracker_id); | |
1305 tracker->set_app_id(std::string()); | |
1306 tracker->set_tracker_kind(TRACKER_KIND_REGULAR); | |
1307 | |
1308 // Inactivate the tracker to drop all descendant. | |
1309 // (Note that we set tracker_kind to TRACKER_KIND_REGULAR before calling | |
1310 // this.) | |
1311 MakeTrackerInactive(tracker_id, batch); | |
1312 } | |
1313 | |
1314 void MetadataDatabase::MakeTrackerActive(int64 tracker_id, | |
1315 leveldb::WriteBatch* batch) { | |
1316 FileTracker* tracker = tracker_by_id_.get(tracker_id); | |
1317 DCHECK(tracker); | |
1318 DCHECK(!tracker->active()); | |
1319 | |
1320 int64 parent_tracker_id = tracker->parent_tracker_id(); | |
1321 DCHECK(tracker->has_synced_details()); | |
1322 trackers_by_file_id_[tracker->file_id()].Activate(tracker_id); | |
1323 if (parent_tracker_id) { | |
1324 trackers_by_parent_and_title_[parent_tracker_id][ | |
1325 tracker->synced_details().title()].Activate(tracker_id); | |
1326 } | |
1327 tracker->set_active(true); | |
1328 tracker->set_needs_folder_listing( | |
1329 tracker->synced_details().file_kind() == FILE_KIND_FOLDER); | |
1330 | |
1331 // Make |tracker| a normal priority dirty tracker. | |
1332 MarkSingleTrackerAsDirty(tracker, NULL); | |
1333 PutFileTrackerToBatch(*tracker, batch); | |
1334 } | |
1335 | |
1336 void MetadataDatabase::MakeTrackerInactive(int64 tracker_id, | |
1337 leveldb::WriteBatch* batch) { | |
1338 FileTracker* tracker = tracker_by_id_.get(tracker_id); | |
1339 DCHECK(tracker); | |
1340 DCHECK(tracker->active()); | |
1341 DCHECK_EQ(TRACKER_KIND_REGULAR, tracker->tracker_kind()); | |
1342 trackers_by_file_id_[tracker->file_id()].Deactivate(tracker_id); | |
1343 | |
1344 std::string title = GetTrackerTitle(*tracker); | |
1345 int64 parent_tracker_id = tracker->parent_tracker_id(); | |
1346 if (parent_tracker_id) { | |
1347 trackers_by_parent_and_title_[parent_tracker_id][title] | |
1348 .Deactivate(tracker_id); | |
1349 } | |
1350 tracker->set_active(false); | |
1351 | |
1352 RemoveAllDescendantTrackers(tracker_id, batch); | |
1353 MarkTrackersDirtyByFileID(tracker->file_id(), batch); | |
1354 if (parent_tracker_id) | |
1355 MarkTrackersDirtyByPath(parent_tracker_id, title, batch); | |
1356 PutFileTrackerToBatch(*tracker, batch); | |
1357 } | |
1358 | |
1359 void MetadataDatabase::MakeAppRootDisabled(int64 tracker_id, | |
1360 leveldb::WriteBatch* batch) { | |
1361 FileTracker* tracker = tracker_by_id_.get(tracker_id); | |
1362 DCHECK(tracker); | |
1363 DCHECK_EQ(TRACKER_KIND_APP_ROOT, tracker->tracker_kind()); | |
1364 DCHECK(tracker->active()); | |
1365 | |
1366 // Keep the app-root tracker active (but change the tracker_kind) so that | |
1367 // other conflicting trackers won't become active. | |
1368 tracker->set_tracker_kind(TRACKER_KIND_DISABLED_APP_ROOT); | |
1369 PutFileTrackerToBatch(*tracker, batch); | |
1370 } | |
1371 | |
1372 void MetadataDatabase::MakeAppRootEnabled(int64 tracker_id, | |
1373 leveldb::WriteBatch* batch) { | |
1374 FileTracker* tracker = tracker_by_id_.get(tracker_id); | |
1375 DCHECK(tracker); | |
1376 DCHECK_EQ(TRACKER_KIND_DISABLED_APP_ROOT, tracker->tracker_kind()); | |
1377 DCHECK(tracker->active()); | |
1378 | |
1379 tracker->set_tracker_kind(TRACKER_KIND_APP_ROOT); | |
1380 // Mark descendant trackers as dirty to handle changes in disable period. | |
1381 RecursiveMarkTrackerAsDirty(tracker_id, batch); | |
1382 PutFileTrackerToBatch(*tracker, batch); | |
1383 } | 1497 } |
1384 | 1498 |
1385 void MetadataDatabase::CreateTrackerForParentAndFileID( | 1499 void MetadataDatabase::CreateTrackerForParentAndFileID( |
1386 const FileTracker& parent_tracker, | 1500 const FileTracker& parent_tracker, |
1387 const std::string& file_id, | 1501 const std::string& file_id, |
1388 leveldb::WriteBatch* batch) { | 1502 leveldb::WriteBatch* batch) { |
1389 CreateTrackerInternal(parent_tracker, file_id, NULL, | 1503 CreateTrackerInternal(parent_tracker, file_id, NULL, |
1390 UPDATE_TRACKER_FOR_UNSYNCED_FILE, | 1504 UPDATE_TRACKER_FOR_UNSYNCED_FILE, |
1391 batch); | 1505 batch); |
1392 } | 1506 } |
(...skipping 27 matching lines...) Expand all Loading... | |
1420 tracker->set_active(false); | 1534 tracker->set_active(false); |
1421 tracker->set_needs_folder_listing(false); | 1535 tracker->set_needs_folder_listing(false); |
1422 if (details) { | 1536 if (details) { |
1423 *tracker->mutable_synced_details() = *details; | 1537 *tracker->mutable_synced_details() = *details; |
1424 if (option == UPDATE_TRACKER_FOR_UNSYNCED_FILE) { | 1538 if (option == UPDATE_TRACKER_FOR_UNSYNCED_FILE) { |
1425 tracker->mutable_synced_details()->set_missing(true); | 1539 tracker->mutable_synced_details()->set_missing(true); |
1426 tracker->mutable_synced_details()->clear_md5(); | 1540 tracker->mutable_synced_details()->clear_md5(); |
1427 } | 1541 } |
1428 } | 1542 } |
1429 PutFileTrackerToBatch(*tracker, batch); | 1543 PutFileTrackerToBatch(*tracker, batch); |
1430 | 1544 index_->StoreFileTracker(tracker.Pass()); |
1431 trackers_by_file_id_[file_id].InsertInactiveTracker(tracker->tracker_id()); | |
1432 // Note: |trackers_by_parent_and_title_| does not map from | |
1433 // FileMetadata::details but from FileTracker::synced_details, which is filled | |
1434 // on tracker updated phase. Use empty string as the title since | |
1435 // FileTracker::synced_details is empty here. | |
1436 std::string title; | |
1437 if (details) | |
1438 title = details->title(); | |
1439 trackers_by_parent_and_title_[parent_tracker.tracker_id()][title] | |
1440 .InsertInactiveTracker(tracker->tracker_id()); | |
1441 dirty_trackers_.insert(tracker.get()); | |
1442 StoreFileTracker(tracker.Pass()); | |
1443 } | |
1444 | |
1445 void MetadataDatabase::RemoveTracker(int64 tracker_id, | |
1446 leveldb::WriteBatch* batch) { | |
1447 RemoveTrackerInternal(tracker_id, batch, false); | |
1448 RemoveAllDescendantTrackers(tracker_id, batch); | |
1449 } | |
1450 | |
1451 void MetadataDatabase::RemoveTrackerIgnoringSameTitle( | |
1452 int64 tracker_id, | |
1453 leveldb::WriteBatch* batch) { | |
1454 RemoveTrackerInternal(tracker_id, batch, true); | |
1455 } | |
1456 | |
1457 void MetadataDatabase::RemoveTrackerInternal( | |
1458 int64 tracker_id, | |
1459 leveldb::WriteBatch* batch, | |
1460 bool ignoring_same_title) { | |
1461 scoped_ptr<FileTracker> tracker( | |
1462 tracker_by_id_.take_and_erase(tracker_id)); | |
1463 if (!tracker) | |
1464 return; | |
1465 | |
1466 EraseTrackerFromFileIDIndex(tracker.get(), batch); | |
1467 if (IsAppRoot(*tracker)) | |
1468 app_root_by_app_id_.erase(tracker->app_id()); | |
1469 EraseTrackerFromPathIndex(tracker.get()); | |
1470 dirty_trackers_.erase(tracker.get()); | |
1471 low_priority_dirty_trackers_.erase(tracker.get()); | |
1472 | |
1473 MarkTrackersDirtyByFileID(tracker->file_id(), batch); | |
1474 if (!ignoring_same_title) { | |
1475 // Mark trackers having the same title with the given tracker as dirty. | |
1476 MarkTrackersDirtyByPath(tracker->parent_tracker_id(), | |
1477 GetTrackerTitle(*tracker), | |
1478 batch); | |
1479 } | |
1480 PutFileTrackerDeletionToBatch(tracker_id, batch); | |
1481 } | 1545 } |
1482 | 1546 |
1483 void MetadataDatabase::MaybeAddTrackersForNewFile( | 1547 void MetadataDatabase::MaybeAddTrackersForNewFile( |
1484 const FileMetadata& metadata, | 1548 const FileMetadata& metadata, |
1485 UpdateOption option, | 1549 UpdateOption option, |
1486 leveldb::WriteBatch* batch) { | 1550 leveldb::WriteBatch* batch) { |
1487 std::set<int64> parents_to_exclude; | 1551 std::set<int64> parents_to_exclude; |
1488 TrackerIDsByFileID::iterator found = | 1552 TrackerIDSet existing_trackers = |
1489 trackers_by_file_id_.find(metadata.file_id()); | 1553 index_->GetFileTrackerIDsByFileID(metadata.file_id()); |
1490 if (found != trackers_by_file_id_.end()) { | 1554 for (TrackerIDSet::const_iterator itr = existing_trackers.begin(); |
1491 for (TrackerIDSet::const_iterator itr = found->second.begin(); | 1555 itr != existing_trackers.end(); ++itr) { |
1492 itr != found->second.end(); ++itr) { | 1556 const FileTracker* tracker = index_->GetFileTracker(*itr); |
1493 const FileTracker& tracker = *tracker_by_id_.get(*itr); | 1557 if (!tracker) { |
1494 int64 parent_tracker_id = tracker.parent_tracker_id(); | 1558 NOTREACHED(); |
1495 if (!parent_tracker_id) | 1559 continue; |
1496 continue; | 1560 } |
1497 | 1561 |
1498 // Exclude |parent_tracker_id| if it already has a tracker that has | 1562 int64 parent_tracker_id = tracker->parent_tracker_id(); |
1499 // unknown title or has the same title with |file|. | 1563 if (!parent_tracker_id) |
1500 if (!tracker.has_synced_details() || | 1564 continue; |
1501 tracker.synced_details().title() == metadata.details().title()) { | 1565 |
1502 parents_to_exclude.insert(parent_tracker_id); | 1566 // Exclude |parent_tracker_id| if it already has a tracker that has |
1503 } | 1567 // unknown title or has the same title with |file|. |
1568 if (!tracker->has_synced_details() || | |
1569 tracker->synced_details().title() == metadata.details().title()) { | |
1570 parents_to_exclude.insert(parent_tracker_id); | |
1504 } | 1571 } |
1505 } | 1572 } |
1506 | 1573 |
1507 for (int i = 0; i < metadata.details().parent_folder_ids_size(); ++i) { | 1574 for (int i = 0; i < metadata.details().parent_folder_ids_size(); ++i) { |
1508 std::string parent_folder_id = metadata.details().parent_folder_ids(i); | 1575 std::string parent_folder_id = metadata.details().parent_folder_ids(i); |
1509 TrackerIDsByFileID::iterator found = | 1576 TrackerIDSet parent_trackers = |
1510 trackers_by_file_id_.find(parent_folder_id); | 1577 index_->GetFileTrackerIDsByFileID(parent_folder_id); |
1511 if (found == trackers_by_file_id_.end()) | 1578 for (TrackerIDSet::const_iterator itr = parent_trackers.begin(); |
1512 continue; | 1579 itr != parent_trackers.end(); ++itr) { |
1513 | 1580 const FileTracker* parent_tracker = index_->GetFileTracker(*itr); |
1514 for (TrackerIDSet::const_iterator itr = found->second.begin(); | |
1515 itr != found->second.end(); ++itr) { | |
1516 FileTracker* parent_tracker = tracker_by_id_.get(*itr); | |
1517 int64 parent_tracker_id = parent_tracker->tracker_id(); | |
1518 if (!parent_tracker->active()) | 1581 if (!parent_tracker->active()) |
1519 continue; | 1582 continue; |
1520 | 1583 |
1521 if (ContainsKey(parents_to_exclude, parent_tracker_id)) | 1584 if (ContainsKey(parents_to_exclude, parent_tracker->tracker_id())) |
1522 continue; | 1585 continue; |
1523 | 1586 |
1524 CreateTrackerForParentAndFileMetadata( | 1587 CreateTrackerForParentAndFileMetadata( |
1525 *parent_tracker, metadata, option, batch); | 1588 *parent_tracker, metadata, option, batch); |
1526 } | 1589 } |
1527 } | 1590 } |
1528 } | 1591 } |
1529 | 1592 |
1530 void MetadataDatabase::RemoveAllDescendantTrackers(int64 root_tracker_id, | |
1531 leveldb::WriteBatch* batch) { | |
1532 std::vector<int64> pending_trackers; | |
1533 PushChildTrackersToContainer(trackers_by_parent_and_title_, | |
1534 root_tracker_id, | |
1535 std::back_inserter(pending_trackers)); | |
1536 | |
1537 while (!pending_trackers.empty()) { | |
1538 int64 tracker_id = pending_trackers.back(); | |
1539 pending_trackers.pop_back(); | |
1540 PushChildTrackersToContainer(trackers_by_parent_and_title_, | |
1541 tracker_id, | |
1542 std::back_inserter(pending_trackers)); | |
1543 RemoveTrackerIgnoringSameTitle(tracker_id, batch); | |
1544 } | |
1545 } | |
1546 | |
1547 void MetadataDatabase::EraseTrackerFromFileIDIndex(FileTracker* tracker, | |
1548 leveldb::WriteBatch* batch) { | |
1549 TrackerIDsByFileID::iterator found = | |
1550 trackers_by_file_id_.find(tracker->file_id()); | |
1551 if (found == trackers_by_file_id_.end()) | |
1552 return; | |
1553 | |
1554 TrackerIDSet* trackers = &found->second; | |
1555 trackers->Erase(tracker->tracker_id()); | |
1556 if (!trackers->empty()) | |
1557 return; | |
1558 trackers_by_file_id_.erase(found); | |
1559 EraseFileFromDatabase(tracker->file_id(), batch); | |
1560 } | |
1561 | |
1562 void MetadataDatabase::EraseFileFromDatabase(const std::string& file_id, | |
1563 leveldb::WriteBatch* batch) { | |
1564 scoped_ptr<FileMetadata> file(metadata_by_id_.take_and_erase(file_id)); | |
1565 if (file) | |
1566 PutFileMetadataDeletionToBatch(file_id, batch); | |
1567 } | |
1568 | |
1569 void MetadataDatabase::EraseTrackerFromPathIndex(FileTracker* tracker) { | |
1570 TrackerIDsByParentAndTitle::iterator found = | |
1571 trackers_by_parent_and_title_.find(tracker->parent_tracker_id()); | |
1572 if (found == trackers_by_parent_and_title_.end()) | |
1573 return; | |
1574 | |
1575 std::string title = GetTrackerTitle(*tracker); | |
1576 TrackerIDsByTitle* trackers_by_title = &found->second; | |
1577 TrackerIDsByTitle::iterator found_by_title = trackers_by_title->find(title); | |
1578 TrackerIDSet* conflicting_trackers = &found_by_title->second; | |
1579 conflicting_trackers->Erase(tracker->tracker_id()); | |
1580 | |
1581 if (conflicting_trackers->empty()) { | |
1582 trackers_by_title->erase(found_by_title); | |
1583 if (trackers_by_title->empty()) | |
1584 trackers_by_parent_and_title_.erase(found); | |
1585 } | |
1586 } | |
1587 | |
1588 void MetadataDatabase::MarkSingleTrackerAsDirty(FileTracker* tracker, | |
1589 leveldb::WriteBatch* batch) { | |
1590 if (!tracker->dirty()) { | |
1591 tracker->set_dirty(true); | |
1592 PutFileTrackerToBatch(*tracker, batch); | |
1593 } | |
1594 dirty_trackers_.insert(tracker); | |
1595 low_priority_dirty_trackers_.erase(tracker); | |
1596 } | |
1597 | |
1598 void MetadataDatabase::ClearDirty(FileTracker* tracker, | |
1599 leveldb::WriteBatch* batch) { | |
1600 if (tracker->dirty()) { | |
1601 tracker->set_dirty(false); | |
1602 PutFileTrackerToBatch(*tracker, batch); | |
1603 } | |
1604 | |
1605 dirty_trackers_.erase(tracker); | |
1606 low_priority_dirty_trackers_.erase(tracker); | |
1607 } | |
1608 | |
1609 void MetadataDatabase::MarkTrackerSetDirty( | |
1610 TrackerIDSet* trackers, | |
1611 leveldb::WriteBatch* batch) { | |
1612 for (TrackerIDSet::iterator itr = trackers->begin(); | |
1613 itr != trackers->end(); ++itr) { | |
1614 MarkSingleTrackerAsDirty(tracker_by_id_.get(*itr), batch); | |
1615 } | |
1616 } | |
1617 | |
1618 void MetadataDatabase::MarkTrackersDirtyByFileID( | |
1619 const std::string& file_id, | |
1620 leveldb::WriteBatch* batch) { | |
1621 TrackerIDsByFileID::iterator found = trackers_by_file_id_.find(file_id); | |
1622 if (found != trackers_by_file_id_.end()) | |
1623 MarkTrackerSetDirty(&found->second, batch); | |
1624 } | |
1625 | |
1626 void MetadataDatabase::MarkTrackersDirtyByPath(int64 parent_tracker_id, | |
1627 const std::string& title, | |
1628 leveldb::WriteBatch* batch) { | |
1629 TrackerIDsByParentAndTitle::iterator found = | |
1630 trackers_by_parent_and_title_.find(parent_tracker_id); | |
1631 if (found == trackers_by_parent_and_title_.end()) | |
1632 return; | |
1633 | |
1634 TrackerIDsByTitle::iterator itr = found->second.find(title); | |
1635 if (itr != found->second.end()) | |
1636 MarkTrackerSetDirty(&itr->second, batch); | |
1637 } | |
1638 | |
1639 int64 MetadataDatabase::IncrementTrackerID(leveldb::WriteBatch* batch) { | 1593 int64 MetadataDatabase::IncrementTrackerID(leveldb::WriteBatch* batch) { |
1640 int64 tracker_id = service_metadata_->next_tracker_id(); | 1594 int64 tracker_id = service_metadata_->next_tracker_id(); |
1641 service_metadata_->set_next_tracker_id(tracker_id + 1); | 1595 service_metadata_->set_next_tracker_id(tracker_id + 1); |
1642 PutServiceMetadataToBatch(*service_metadata_, batch); | 1596 PutServiceMetadataToBatch(*service_metadata_, batch); |
1643 DCHECK_GT(tracker_id, 0); | 1597 DCHECK_GT(tracker_id, 0); |
1644 return tracker_id; | 1598 return tracker_id; |
1645 } | 1599 } |
1646 | 1600 |
1647 void MetadataDatabase::RecursiveMarkTrackerAsDirty(int64 root_tracker_id, | |
1648 leveldb::WriteBatch* batch) { | |
1649 std::vector<int64> stack; | |
1650 stack.push_back(root_tracker_id); | |
1651 while (!stack.empty()) { | |
1652 int64 tracker_id = stack.back(); | |
1653 stack.pop_back(); | |
1654 PushChildTrackersToContainer( | |
1655 trackers_by_parent_and_title_, tracker_id, std::back_inserter(stack)); | |
1656 | |
1657 MarkSingleTrackerAsDirty(tracker_by_id_.get(tracker_id), batch); | |
1658 } | |
1659 } | |
1660 | |
1661 bool MetadataDatabase::CanActivateTracker(const FileTracker& tracker) { | 1601 bool MetadataDatabase::CanActivateTracker(const FileTracker& tracker) { |
1662 DCHECK(!tracker.active()); | 1602 DCHECK(!tracker.active()); |
1663 DCHECK_NE(service_metadata_->sync_root_tracker_id(), tracker.tracker_id()); | 1603 DCHECK_NE(service_metadata_->sync_root_tracker_id(), tracker.tracker_id()); |
1664 | 1604 |
1665 if (HasActiveTrackerForFileID(tracker.file_id())) | 1605 if (HasActiveTrackerForFileID(tracker.file_id())) |
1666 return false; | 1606 return false; |
1667 | 1607 |
1668 if (tracker.app_id().empty() && | 1608 if (tracker.app_id().empty() && |
1669 tracker.tracker_id() != GetSyncRootTrackerID()) { | 1609 tracker.tracker_id() != GetSyncRootTrackerID()) { |
1670 return false; | 1610 return false; |
(...skipping 12 matching lines...) Expand all Loading... | |
1683 } | 1623 } |
1684 | 1624 |
1685 bool MetadataDatabase::ShouldKeepDirty(const FileTracker& tracker) const { | 1625 bool MetadataDatabase::ShouldKeepDirty(const FileTracker& tracker) const { |
1686 if (HasDisabledAppRoot(tracker)) | 1626 if (HasDisabledAppRoot(tracker)) |
1687 return false; | 1627 return false; |
1688 | 1628 |
1689 DCHECK(tracker.dirty()); | 1629 DCHECK(tracker.dirty()); |
1690 if (!tracker.has_synced_details()) | 1630 if (!tracker.has_synced_details()) |
1691 return true; | 1631 return true; |
1692 | 1632 |
1693 MetadataByID::const_iterator found = metadata_by_id_.find(tracker.file_id()); | 1633 const FileMetadata* metadata = index_->GetFileMetadata(tracker.file_id()); |
1694 if (found == metadata_by_id_.end()) | 1634 if (!metadata) |
1695 return true; | 1635 return true; |
1696 const FileMetadata* metadata = found->second; | |
1697 DCHECK(metadata); | 1636 DCHECK(metadata); |
1698 DCHECK(metadata->has_details()); | 1637 DCHECK(metadata->has_details()); |
1699 | 1638 |
1700 const FileDetails& local_details = tracker.synced_details(); | 1639 const FileDetails& local_details = tracker.synced_details(); |
1701 const FileDetails& remote_details = metadata->details(); | 1640 const FileDetails& remote_details = metadata->details(); |
1702 | 1641 |
1703 if (tracker.active()) { | 1642 if (tracker.active()) { |
1704 if (tracker.needs_folder_listing()) | 1643 if (tracker.needs_folder_listing()) |
1705 return true; | 1644 return true; |
1706 if (local_details.md5() != remote_details.md5()) | 1645 if (local_details.md5() != remote_details.md5()) |
1707 return true; | 1646 return true; |
1708 if (local_details.missing() != remote_details.missing()) | 1647 if (local_details.missing() != remote_details.missing()) |
1709 return true; | 1648 return true; |
1710 } | 1649 } |
1711 | 1650 |
1712 if (local_details.title() != remote_details.title()) | 1651 if (local_details.title() != remote_details.title()) |
1713 return true; | 1652 return true; |
1714 | 1653 |
1715 return false; | 1654 return false; |
1716 } | 1655 } |
1717 | 1656 |
1718 bool MetadataDatabase::HasDisabledAppRoot(const FileTracker& tracker) const { | 1657 bool MetadataDatabase::HasDisabledAppRoot(const FileTracker& tracker) const { |
1719 TrackerIDByAppID::const_iterator found = | 1658 int64 app_root_tracker_id = index_->GetAppRootTracker(tracker.app_id()); |
kinuko
2014/03/05 07:41:32
nit: not related to this CL, but it might have bee
| |
1720 app_root_by_app_id_.find(tracker.app_id()); | 1659 if (app_root_tracker_id == kInvalidTrackerID) |
1721 if (found == app_root_by_app_id_.end()) | |
1722 return false; | 1660 return false; |
1723 | 1661 |
1724 const FileTracker* app_root_tracker = tracker_by_id_.get(found->second); | 1662 const FileTracker* app_root_tracker = |
1725 DCHECK(app_root_tracker); | 1663 index_->GetFileTracker(app_root_tracker_id); |
1664 if (!app_root_tracker) { | |
1665 NOTREACHED(); | |
1666 return false; | |
1667 } | |
1726 return app_root_tracker->tracker_kind() == TRACKER_KIND_DISABLED_APP_ROOT; | 1668 return app_root_tracker->tracker_kind() == TRACKER_KIND_DISABLED_APP_ROOT; |
1727 } | 1669 } |
1728 | 1670 |
1729 bool MetadataDatabase::HasActiveTrackerForFileID( | 1671 bool MetadataDatabase::HasActiveTrackerForFileID( |
1730 const std::string& file_id) const { | 1672 const std::string& file_id) const { |
1731 TrackerIDsByFileID::const_iterator found = trackers_by_file_id_.find(file_id); | 1673 return index_->GetFileTrackerIDsByFileID(file_id).has_active(); |
1732 return found != trackers_by_file_id_.end() && found->second.has_active(); | |
1733 } | 1674 } |
1734 | 1675 |
1735 bool MetadataDatabase::HasActiveTrackerForPath(int64 parent_tracker_id, | 1676 bool MetadataDatabase::HasActiveTrackerForPath(int64 parent_tracker_id, |
1736 const std::string& title) const { | 1677 const std::string& title) const { |
1737 TrackerIDsByParentAndTitle::const_iterator found_by_parent = | 1678 return index_->GetFileTrackerIDsByParentAndTitle(parent_tracker_id, title) |
1738 trackers_by_parent_and_title_.find(parent_tracker_id); | 1679 .has_active(); |
1739 if (found_by_parent == trackers_by_parent_and_title_.end()) | |
1740 return false; | |
1741 | |
1742 const TrackerIDsByTitle& trackers_by_title = found_by_parent->second; | |
1743 TrackerIDsByTitle::const_iterator found = trackers_by_title.find(title); | |
1744 return found != trackers_by_title.end() && found->second.has_active(); | |
1745 } | 1680 } |
1746 | 1681 |
1747 void MetadataDatabase::RemoveUnneededTrackersForMissingFile( | 1682 void MetadataDatabase::RemoveUnneededTrackersForMissingFile( |
1748 const std::string& file_id, | 1683 const std::string& file_id, |
1749 leveldb::WriteBatch* batch) { | 1684 leveldb::WriteBatch* batch) { |
1750 TrackerIDSet trackers; | 1685 TrackerIDSet trackers = index_->GetFileTrackerIDsByFileID(file_id); |
1751 FindTrackersByFileID(file_id, &trackers); | |
1752 for (TrackerIDSet::const_iterator itr = trackers.begin(); | 1686 for (TrackerIDSet::const_iterator itr = trackers.begin(); |
1753 itr != trackers.end(); ++itr) { | 1687 itr != trackers.end(); ++itr) { |
1754 const FileTracker& tracker = *tracker_by_id_.get(*itr); | 1688 const FileTracker* tracker = index_->GetFileTracker(*itr); |
1755 if (!tracker.has_synced_details() || | 1689 if (!tracker) { |
1756 tracker.synced_details().missing()) { | 1690 NOTREACHED(); |
1757 RemoveTracker(tracker.tracker_id(), batch); | 1691 continue; |
1692 } | |
1693 | |
1694 if (!tracker->has_synced_details() || | |
1695 tracker->synced_details().missing()) { | |
1696 RemoveTracker(*itr, MARK_NOTHING_DIRTY, index_.get(), batch); | |
1758 } | 1697 } |
1759 } | 1698 } |
1760 } | 1699 } |
1761 | 1700 |
1762 void MetadataDatabase::UpdateByFileMetadata( | 1701 void MetadataDatabase::UpdateByFileMetadata( |
1763 const tracked_objects::Location& from_where, | 1702 const tracked_objects::Location& from_where, |
1764 scoped_ptr<FileMetadata> metadata, | 1703 scoped_ptr<FileMetadata> metadata, |
1765 UpdateOption option, | 1704 UpdateOption option, |
1766 leveldb::WriteBatch* batch) { | 1705 leveldb::WriteBatch* batch) { |
1767 DCHECK(metadata); | 1706 DCHECK(metadata); |
1768 DCHECK(metadata->has_details()); | 1707 DCHECK(metadata->has_details()); |
1769 | 1708 |
1770 DVLOG(1) << from_where.function_name() << ": " | 1709 DVLOG(1) << from_where.function_name() << ": " |
1771 << metadata->file_id() << " (" | 1710 << metadata->file_id() << " (" |
1772 << metadata->details().title() << ")" | 1711 << metadata->details().title() << ")" |
1773 << (metadata->details().missing() ? " deleted" : ""); | 1712 << (metadata->details().missing() ? " deleted" : ""); |
1774 | 1713 |
1775 std::string file_id = metadata->file_id(); | 1714 std::string file_id = metadata->file_id(); |
1776 if (metadata->details().missing()) | 1715 if (metadata->details().missing()) |
1777 RemoveUnneededTrackersForMissingFile(file_id, batch); | 1716 RemoveUnneededTrackersForMissingFile(file_id, batch); |
1778 else | 1717 else |
1779 MaybeAddTrackersForNewFile(*metadata, option, batch); | 1718 MaybeAddTrackersForNewFile(*metadata, option, batch); |
1780 | 1719 |
1781 if (FindTrackersByFileID(file_id, NULL)) { | 1720 TrackerIDSet trackers = index_->GetFileTrackerIDsByFileID(file_id); |
1721 if (!trackers.empty()) { | |
1722 PutFileMetadataToBatch(*metadata, batch); | |
1723 index_->StoreFileMetadata(metadata.Pass()); | |
1724 | |
1782 if (option != UPDATE_TRACKER_FOR_SYNCED_FILE) | 1725 if (option != UPDATE_TRACKER_FOR_SYNCED_FILE) |
1783 MarkTrackersDirtyByFileID(file_id, batch); | 1726 MarkTrackerSetDirty(trackers, index_.get(), batch); |
1784 PutFileMetadataToBatch(*metadata, batch); | |
1785 StoreFileMetadata(metadata.Pass()); | |
1786 } | 1727 } |
1787 } | 1728 } |
1788 | 1729 |
1789 void MetadataDatabase::WriteToDatabase(scoped_ptr<leveldb::WriteBatch> batch, | 1730 void MetadataDatabase::WriteToDatabase(scoped_ptr<leveldb::WriteBatch> batch, |
1790 const SyncStatusCallback& callback) { | 1731 const SyncStatusCallback& callback) { |
1791 if (!batch) { | 1732 if (!batch) { |
1792 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK)); | 1733 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK)); |
1793 return; | 1734 return; |
1794 } | 1735 } |
1795 | 1736 |
1796 base::PostTaskAndReplyWithResult( | 1737 base::PostTaskAndReplyWithResult( |
1797 task_runner_.get(), | 1738 task_runner_.get(), |
1798 FROM_HERE, | 1739 FROM_HERE, |
1799 base::Bind(&leveldb::DB::Write, | 1740 base::Bind(&leveldb::DB::Write, |
1800 base::Unretained(db_.get()), | 1741 base::Unretained(db_.get()), |
1801 leveldb::WriteOptions(), | 1742 leveldb::WriteOptions(), |
1802 base::Owned(batch.release())), | 1743 base::Owned(batch.release())), |
1803 base::Bind(&AdaptLevelDBStatusToSyncStatusCode, callback)); | 1744 base::Bind(&AdaptLevelDBStatusToSyncStatusCode, callback)); |
1804 } | 1745 } |
1805 | 1746 |
1806 scoped_ptr<base::ListValue> MetadataDatabase::DumpFiles( | 1747 scoped_ptr<base::ListValue> MetadataDatabase::DumpFiles( |
1807 const std::string& app_id) { | 1748 const std::string& app_id) { |
1808 scoped_ptr<base::ListValue> files(new base::ListValue); | 1749 scoped_ptr<base::ListValue> files(new base::ListValue); |
1809 | 1750 |
1810 FileTracker app_root_tracker; | 1751 FileTracker app_root_tracker; |
1811 if (!FindAppRootTracker(app_id, &app_root_tracker)) | 1752 if (!FindAppRootTracker(app_id, &app_root_tracker)) |
1812 return files.Pass(); | 1753 return files.Pass(); |
1813 | 1754 |
1814 std::vector<int64> stack; | 1755 std::vector<int64> stack; |
1815 PushChildTrackersToContainer( | 1756 AppendContents( |
1816 trackers_by_parent_and_title_, | 1757 index_->GetFileTrackerIDsByParent(app_root_tracker.tracker_id()), &stack); |
1817 app_root_tracker.tracker_id(), | |
1818 std::back_inserter(stack)); | |
1819 while (!stack.empty()) { | 1758 while (!stack.empty()) { |
1820 int64 tracker_id = stack.back(); | 1759 int64 tracker_id = stack.back(); |
1821 stack.pop_back(); | 1760 stack.pop_back(); |
1822 PushChildTrackersToContainer( | 1761 AppendContents(index_->GetFileTrackerIDsByParent(tracker_id), &stack); |
1823 trackers_by_parent_and_title_, tracker_id, std::back_inserter(stack)); | |
1824 | 1762 |
1825 const FileTracker* tracker = tracker_by_id_.get(tracker_id); | 1763 const FileTracker* tracker = index_->GetFileTracker(tracker_id); |
1764 if (!tracker) { | |
1765 NOTREACHED(); | |
1766 continue; | |
1767 } | |
1826 base::DictionaryValue* file = new base::DictionaryValue; | 1768 base::DictionaryValue* file = new base::DictionaryValue; |
1827 | 1769 |
1828 base::FilePath path = BuildDisplayPathForTracker(*tracker); | 1770 base::FilePath path = BuildDisplayPathForTracker(*tracker); |
1829 file->SetString("path", path.AsUTF8Unsafe()); | 1771 file->SetString("path", path.AsUTF8Unsafe()); |
1830 if (tracker->has_synced_details()) { | 1772 if (tracker->has_synced_details()) { |
1831 file->SetString("title", tracker->synced_details().title()); | 1773 file->SetString("title", tracker->synced_details().title()); |
1832 file->SetString("type", | 1774 file->SetString("type", |
1833 FileKindToString(tracker->synced_details().file_kind())); | 1775 FileKindToString(tracker->synced_details().file_kind())); |
1834 } | 1776 } |
1835 | 1777 |
(...skipping 15 matching lines...) Expand all Loading... | |
1851 | 1793 |
1852 scoped_ptr<base::ListValue> MetadataDatabase::DumpDatabase() { | 1794 scoped_ptr<base::ListValue> MetadataDatabase::DumpDatabase() { |
1853 scoped_ptr<base::ListValue> list(new base::ListValue); | 1795 scoped_ptr<base::ListValue> list(new base::ListValue); |
1854 list->Append(DumpTrackers().release()); | 1796 list->Append(DumpTrackers().release()); |
1855 list->Append(DumpMetadata().release()); | 1797 list->Append(DumpMetadata().release()); |
1856 return list.Pass(); | 1798 return list.Pass(); |
1857 } | 1799 } |
1858 | 1800 |
1859 bool MetadataDatabase::HasNewerFileMetadata(const std::string& file_id, | 1801 bool MetadataDatabase::HasNewerFileMetadata(const std::string& file_id, |
1860 int64 change_id) { | 1802 int64 change_id) { |
1861 MetadataByID::const_iterator found = metadata_by_id_.find(file_id); | 1803 const FileMetadata* metadata = index_->GetFileMetadata(file_id); |
1862 if (found == metadata_by_id_.end()) | 1804 if (!metadata) |
1863 return false; | 1805 return false; |
1864 DCHECK(found->second->has_details()); | 1806 DCHECK(metadata->has_details()); |
1865 return found->second->details().change_id() >= change_id; | 1807 return metadata->details().change_id() >= change_id; |
1866 } | 1808 } |
1867 | 1809 |
1868 scoped_ptr<base::ListValue> MetadataDatabase::DumpTrackers() { | 1810 scoped_ptr<base::ListValue> MetadataDatabase::DumpTrackers() { |
1869 scoped_ptr<base::ListValue> trackers(new base::ListValue); | 1811 scoped_ptr<base::ListValue> trackers(new base::ListValue); |
1870 | 1812 |
1871 // Append the first element for metadata. | 1813 // Append the first element for metadata. |
1872 base::DictionaryValue* metadata = new base::DictionaryValue; | 1814 base::DictionaryValue* metadata = new base::DictionaryValue; |
1873 const char *trackerKeys[] = { | 1815 const char *trackerKeys[] = { |
1874 "tracker_id", "path", "file_id", "tracker_kind", "app_id", | 1816 "tracker_id", "path", "file_id", "tracker_kind", "app_id", |
1875 "active", "dirty", "folder_listing", | 1817 "active", "dirty", "folder_listing", |
1876 "title", "kind", "md5", "etag", "missing", "change_id", | 1818 "title", "kind", "md5", "etag", "missing", "change_id", |
1877 }; | 1819 }; |
1878 std::vector<std::string> key_strings( | 1820 std::vector<std::string> key_strings( |
1879 trackerKeys, trackerKeys + ARRAYSIZE_UNSAFE(trackerKeys)); | 1821 trackerKeys, trackerKeys + ARRAYSIZE_UNSAFE(trackerKeys)); |
1880 base::ListValue* keys = new base::ListValue; | 1822 base::ListValue* keys = new base::ListValue; |
1881 keys->AppendStrings(key_strings); | 1823 keys->AppendStrings(key_strings); |
1882 metadata->SetString("title", "Trackers"); | 1824 metadata->SetString("title", "Trackers"); |
1883 metadata->Set("keys", keys); | 1825 metadata->Set("keys", keys); |
1884 trackers->Append(metadata); | 1826 trackers->Append(metadata); |
1885 | 1827 |
1886 // Append tracker data. | 1828 // Append tracker data. |
1887 for (TrackerByID::const_iterator itr = tracker_by_id_.begin(); | 1829 for (MetadataDatabaseIndex::TrackerByID::const_iterator itr = |
1888 itr != tracker_by_id_.end(); ++itr) { | 1830 index_->tracker_by_id_.begin(); |
1831 itr != index_->tracker_by_id_.end(); ++itr) { | |
1889 const FileTracker& tracker = *itr->second; | 1832 const FileTracker& tracker = *itr->second; |
1890 base::DictionaryValue* dict = new base::DictionaryValue; | 1833 base::DictionaryValue* dict = new base::DictionaryValue; |
1891 base::FilePath path = BuildDisplayPathForTracker(tracker); | 1834 base::FilePath path = BuildDisplayPathForTracker(tracker); |
1892 dict->SetString("tracker_id", base::Int64ToString(tracker.tracker_id())); | 1835 dict->SetString("tracker_id", base::Int64ToString(tracker.tracker_id())); |
1893 dict->SetString("path", path.AsUTF8Unsafe()); | 1836 dict->SetString("path", path.AsUTF8Unsafe()); |
1894 dict->SetString("file_id", tracker.file_id()); | 1837 dict->SetString("file_id", tracker.file_id()); |
1895 TrackerKind tracker_kind = tracker.tracker_kind(); | 1838 TrackerKind tracker_kind = tracker.tracker_kind(); |
1896 dict->SetString( | 1839 dict->SetString( |
1897 "tracker_kind", | 1840 "tracker_kind", |
1898 tracker_kind == TRACKER_KIND_APP_ROOT ? "AppRoot" : | 1841 tracker_kind == TRACKER_KIND_APP_ROOT ? "AppRoot" : |
(...skipping 30 matching lines...) Expand all Loading... | |
1929 }; | 1872 }; |
1930 std::vector<std::string> key_strings( | 1873 std::vector<std::string> key_strings( |
1931 fileKeys, fileKeys + ARRAYSIZE_UNSAFE(fileKeys)); | 1874 fileKeys, fileKeys + ARRAYSIZE_UNSAFE(fileKeys)); |
1932 base::ListValue* keys = new base::ListValue; | 1875 base::ListValue* keys = new base::ListValue; |
1933 keys->AppendStrings(key_strings); | 1876 keys->AppendStrings(key_strings); |
1934 metadata->SetString("title", "Metadata"); | 1877 metadata->SetString("title", "Metadata"); |
1935 metadata->Set("keys", keys); | 1878 metadata->Set("keys", keys); |
1936 files->Append(metadata); | 1879 files->Append(metadata); |
1937 | 1880 |
1938 // Append metadata data. | 1881 // Append metadata data. |
1939 for (MetadataByID::const_iterator itr = metadata_by_id_.begin(); | 1882 for (MetadataDatabaseIndex::MetadataByID::const_iterator itr = |
1940 itr != metadata_by_id_.end(); ++itr) { | 1883 index_->metadata_by_id_.begin(); |
1884 itr != index_->metadata_by_id_.end(); ++itr) { | |
1941 const FileMetadata& file = *itr->second; | 1885 const FileMetadata& file = *itr->second; |
1942 | 1886 |
1943 base::DictionaryValue* dict = new base::DictionaryValue; | 1887 base::DictionaryValue* dict = new base::DictionaryValue; |
1944 dict->SetString("file_id", file.file_id()); | 1888 dict->SetString("file_id", file.file_id()); |
1945 if (file.has_details()) { | 1889 if (file.has_details()) { |
1946 const FileDetails& details = file.details(); | 1890 const FileDetails& details = file.details(); |
1947 dict->SetString("title", details.title()); | 1891 dict->SetString("title", details.title()); |
1948 dict->SetString("type", FileKindToString(details.file_kind())); | 1892 dict->SetString("type", FileKindToString(details.file_kind())); |
1949 dict->SetString("md5", details.md5()); | 1893 dict->SetString("md5", details.md5()); |
1950 dict->SetString("etag", details.etag()); | 1894 dict->SetString("etag", details.etag()); |
1951 dict->SetString("missing", details.missing() ? "true" : "false"); | 1895 dict->SetString("missing", details.missing() ? "true" : "false"); |
1952 dict->SetString("change_id", base::Int64ToString(details.change_id())); | 1896 dict->SetString("change_id", base::Int64ToString(details.change_id())); |
1953 | 1897 |
1954 std::vector<std::string> parents; | 1898 std::vector<std::string> parents; |
1955 for (int i = 0; i < details.parent_folder_ids_size(); ++i) | 1899 for (int i = 0; i < details.parent_folder_ids_size(); ++i) |
1956 parents.push_back(details.parent_folder_ids(i)); | 1900 parents.push_back(details.parent_folder_ids(i)); |
1957 dict->SetString("parents", JoinString(parents, ",")); | 1901 dict->SetString("parents", JoinString(parents, ",")); |
1958 } | 1902 } |
1959 files->Append(dict); | 1903 files->Append(dict); |
1960 } | 1904 } |
1961 return files.Pass(); | 1905 return files.Pass(); |
1962 } | 1906 } |
1963 | 1907 |
1964 void MetadataDatabase::StoreFileMetadata( | |
1965 scoped_ptr<FileMetadata> file_metadata) { | |
1966 DCHECK(file_metadata); | |
1967 | |
1968 std::string file_id = file_metadata->file_id(); | |
1969 metadata_by_id_.set(file_id, file_metadata.Pass()); | |
1970 } | |
1971 | |
1972 void MetadataDatabase::StoreFileTracker(scoped_ptr<FileTracker> file_tracker) { | |
1973 DCHECK(file_tracker); | |
1974 | |
1975 int64 tracker_id = file_tracker->tracker_id(); | |
1976 DCHECK(!ContainsKey(tracker_by_id_, tracker_id)); | |
1977 tracker_by_id_.set(tracker_id, file_tracker.Pass()); | |
1978 } | |
1979 | |
1980 void MetadataDatabase::AttachSyncRoot( | 1908 void MetadataDatabase::AttachSyncRoot( |
1981 const google_apis::FileResource& sync_root_folder, | 1909 const google_apis::FileResource& sync_root_folder, |
1982 leveldb::WriteBatch* batch) { | 1910 leveldb::WriteBatch* batch) { |
1983 scoped_ptr<FileMetadata> sync_root_metadata = | 1911 scoped_ptr<FileMetadata> sync_root_metadata = |
1984 CreateFileMetadataFromFileResource( | 1912 CreateFileMetadataFromFileResource( |
1985 GetLargestKnownChangeID(), sync_root_folder); | 1913 GetLargestKnownChangeID(), sync_root_folder); |
1986 scoped_ptr<FileTracker> sync_root_tracker = | 1914 scoped_ptr<FileTracker> sync_root_tracker = |
1987 CreateSyncRootTracker(IncrementTrackerID(batch), *sync_root_metadata); | 1915 CreateSyncRootTracker(IncrementTrackerID(batch), *sync_root_metadata); |
1988 | 1916 |
1989 PutFileMetadataToBatch(*sync_root_metadata, batch); | 1917 PutFileMetadataToBatch(*sync_root_metadata, batch); |
1990 PutFileTrackerToBatch(*sync_root_tracker, batch); | 1918 PutFileTrackerToBatch(*sync_root_tracker, batch); |
1991 | 1919 |
1992 service_metadata_->set_sync_root_tracker_id(sync_root_tracker->tracker_id()); | 1920 service_metadata_->set_sync_root_tracker_id(sync_root_tracker->tracker_id()); |
1993 PutServiceMetadataToBatch(*service_metadata_, batch); | 1921 PutServiceMetadataToBatch(*service_metadata_, batch); |
1994 | 1922 |
1995 InsertFileTrackerToIndex(sync_root_tracker.get()); | 1923 index_->StoreFileMetadata(sync_root_metadata.Pass()); |
1996 | 1924 index_->StoreFileTracker(sync_root_tracker.Pass()); |
1997 StoreFileMetadata(sync_root_metadata.Pass()); | |
1998 StoreFileTracker(sync_root_tracker.Pass()); | |
1999 } | 1925 } |
2000 | 1926 |
2001 void MetadataDatabase::AttachInitialAppRoot( | 1927 void MetadataDatabase::AttachInitialAppRoot( |
2002 const google_apis::FileResource& app_root_folder, | 1928 const google_apis::FileResource& app_root_folder, |
2003 leveldb::WriteBatch* batch) { | 1929 leveldb::WriteBatch* batch) { |
2004 scoped_ptr<FileMetadata> app_root_metadata = | 1930 scoped_ptr<FileMetadata> app_root_metadata = |
2005 CreateFileMetadataFromFileResource( | 1931 CreateFileMetadataFromFileResource( |
2006 GetLargestKnownChangeID(), app_root_folder); | 1932 GetLargestKnownChangeID(), app_root_folder); |
2007 scoped_ptr<FileTracker> app_root_tracker = | 1933 scoped_ptr<FileTracker> app_root_tracker = |
2008 CreateInitialAppRootTracker(IncrementTrackerID(batch), | 1934 CreateInitialAppRootTracker(IncrementTrackerID(batch), |
2009 GetSyncRootTrackerID(), | 1935 GetSyncRootTrackerID(), |
2010 *app_root_metadata); | 1936 *app_root_metadata); |
2011 | 1937 |
2012 PutFileMetadataToBatch(*app_root_metadata, batch); | 1938 PutFileMetadataToBatch(*app_root_metadata, batch); |
2013 PutFileTrackerToBatch(*app_root_tracker, batch); | 1939 PutFileTrackerToBatch(*app_root_tracker, batch); |
2014 | 1940 |
2015 InsertFileTrackerToIndex(app_root_tracker.get()); | 1941 index_->StoreFileMetadata(app_root_metadata.Pass()); |
2016 | 1942 index_->StoreFileTracker(app_root_tracker.Pass()); |
2017 StoreFileMetadata(app_root_metadata.Pass()); | |
2018 StoreFileTracker(app_root_tracker.Pass()); | |
2019 } | |
2020 | |
2021 void MetadataDatabase::InsertFileTrackerToIndex(FileTracker* tracker) { | |
2022 trackers_by_file_id_[tracker->file_id()].Insert(*tracker); | |
2023 if (IsAppRoot(*tracker)) { | |
2024 DCHECK(!ContainsKey(app_root_by_app_id_, tracker->app_id())); | |
2025 app_root_by_app_id_[tracker->app_id()] = tracker->tracker_id(); | |
2026 } | |
2027 | |
2028 int64 parent_tracker_id = tracker->parent_tracker_id(); | |
2029 if (parent_tracker_id) { | |
2030 std::string title = GetTrackerTitle(*tracker); | |
2031 trackers_by_parent_and_title_[parent_tracker_id][title].Insert(*tracker); | |
2032 } | |
2033 | |
2034 if (tracker->dirty()) { | |
2035 dirty_trackers_.insert(tracker); | |
2036 low_priority_dirty_trackers_.erase(tracker); | |
2037 } | |
2038 } | |
2039 | |
2040 void MetadataDatabase::ForceActivateTrackerByPath(int64 parent_tracker_id, | |
2041 const std::string& title, | |
2042 const std::string& file_id, | |
2043 leveldb::WriteBatch* batch) { | |
2044 DCHECK(ContainsKey(trackers_by_parent_and_title_, parent_tracker_id)); | |
2045 DCHECK(ContainsKey(trackers_by_parent_and_title_[parent_tracker_id], title)); | |
2046 DCHECK(!trackers_by_file_id_[file_id].has_active()); | |
2047 | |
2048 TrackerIDSet* same_path_trackers = | |
2049 &trackers_by_parent_and_title_[parent_tracker_id][title]; | |
2050 | |
2051 for (TrackerIDSet::iterator itr = same_path_trackers->begin(); | |
2052 itr != same_path_trackers->end(); ++itr) { | |
2053 FileTracker* tracker = tracker_by_id_.get(*itr); | |
2054 if (tracker->file_id() != file_id) | |
2055 continue; | |
2056 | |
2057 if (same_path_trackers->has_active()) { | |
2058 MakeTrackerInactive(same_path_trackers->active_tracker(), batch); | |
2059 } | |
2060 MakeTrackerActive(tracker->tracker_id(), batch); | |
2061 ClearDirty(tracker, batch); | |
2062 return; | |
2063 } | |
2064 | |
2065 NOTREACHED(); | |
2066 } | 1943 } |
2067 | 1944 |
2068 } // namespace drive_backend | 1945 } // namespace drive_backend |
2069 } // namespace sync_file_system | 1946 } // namespace sync_file_system |
OLD | NEW |