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

Side by Side Diff: chrome/browser/sync_file_system/drive_backend/metadata_database.cc

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

Powered by Google App Engine
This is Rietveld 408576698