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