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

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

Powered by Google App Engine
This is Rietveld 408576698