| Index: chrome/browser/sync_file_system/drive_backend/metadata_database.cc
|
| diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database.cc b/chrome/browser/sync_file_system/drive_backend/metadata_database.cc
|
| index 711895d4dd9a28499481ac10d3d1e159af164500..b05a9cbe1688c271fe5e4111e7b72cab5f6c0824 100644
|
| --- a/chrome/browser/sync_file_system/drive_backend/metadata_database.cc
|
| +++ b/chrome/browser/sync_file_system/drive_backend/metadata_database.cc
|
| @@ -25,6 +25,7 @@
|
| #include "chrome/browser/sync_file_system/drive_backend/drive_backend_constants.h"
|
| #include "chrome/browser/sync_file_system/drive_backend/drive_backend_util.h"
|
| #include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
|
| +#include "chrome/browser/sync_file_system/drive_backend/metadata_database_index.h"
|
| #include "chrome/browser/sync_file_system/drive_backend/metadata_db_migration_util.h"
|
| #include "chrome/browser/sync_file_system/logger.h"
|
| #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
|
| @@ -40,11 +41,6 @@ namespace drive_backend {
|
|
|
| namespace {
|
|
|
| -typedef MetadataDatabase::MetadataByID MetadataByID;
|
| -typedef MetadataDatabase::TrackerByID TrackerByID;
|
| -typedef MetadataDatabase::TrackerIDsByParentAndTitle TrackerIDsByParentAndTitle;
|
| -typedef MetadataDatabase::TrackerIDsByTitle TrackerIDsByTitle;
|
| -
|
| bool IsAppRoot(const FileTracker& tracker) {
|
| return tracker.tracker_kind() == TRACKER_KIND_APP_ROOT ||
|
| tracker.tracker_kind() == TRACKER_KIND_DISABLED_APP_ROOT;
|
| @@ -114,28 +110,6 @@ void AdaptLevelDBStatusToSyncStatusCode(const SyncStatusCallback& callback,
|
| callback.Run(LevelDBStatusToSyncStatusCode(status));
|
| }
|
|
|
| -template <typename OutputIterator>
|
| -OutputIterator PushChildTrackersToContainer(
|
| - const TrackerIDsByParentAndTitle& trackers_by_parent,
|
| - int64 parent_tracker_id,
|
| - OutputIterator target_itr) {
|
| - TrackerIDsByParentAndTitle::const_iterator found =
|
| - trackers_by_parent.find(parent_tracker_id);
|
| - if (found == trackers_by_parent.end())
|
| - return target_itr;
|
| -
|
| - for (TrackerIDsByTitle::const_iterator title_itr = found->second.begin();
|
| - title_itr != found->second.end(); ++title_itr) {
|
| - const TrackerIDSet& trackers = title_itr->second;
|
| - for (TrackerIDSet::const_iterator tracker_itr = trackers.begin();
|
| - tracker_itr != trackers.end(); ++tracker_itr) {
|
| - *target_itr = *tracker_itr;
|
| - ++target_itr;
|
| - }
|
| - }
|
| - return target_itr;
|
| -}
|
| -
|
| std::string GetTrackerTitle(const FileTracker& tracker) {
|
| if (tracker.has_synced_details())
|
| return tracker.synced_details().title();
|
| @@ -379,29 +353,6 @@ SyncStatusCode RemoveUnreachableItems(DatabaseContents* contents,
|
| return SYNC_STATUS_OK;
|
| }
|
|
|
| -template <typename Container, typename Key, typename Value>
|
| -bool FindItem(const Container& container, const Key& key, Value* value) {
|
| - typename Container::const_iterator found = container.find(key);
|
| - if (found == container.end())
|
| - return false;
|
| - if (value)
|
| - *value = *found->second;
|
| - return true;
|
| -}
|
| -
|
| -template <typename Container, typename Key>
|
| -typename Container::mapped_type FindAndEraseItem(Container* container,
|
| - const Key& key) {
|
| - typedef typename Container::mapped_type Value;
|
| - typename Container::iterator found = container->find(key);
|
| - if (found == container->end())
|
| - return Value();
|
| -
|
| - Value result = found->second;
|
| - container->erase(found);
|
| - return result;
|
| -}
|
| -
|
| void RunSoon(const tracked_objects::Location& from_here,
|
| const base::Closure& closure) {
|
| base::MessageLoopProxy::current()->PostTask(from_here, closure);
|
| @@ -413,17 +364,251 @@ bool HasInvalidTitle(const std::string& title) {
|
| title.find('\\') != std::string::npos;
|
| }
|
|
|
| +void MarkTrackerSetDirty(const TrackerIDSet& trackers,
|
| + MetadataDatabaseIndex* index,
|
| + leveldb::WriteBatch* batch) {
|
| + for (TrackerIDSet::const_iterator itr = trackers.begin();
|
| + itr != trackers.end(); ++itr) {
|
| + scoped_ptr<FileTracker> tracker = Clone(index->GetFileTracker(*itr));
|
| + if (tracker->dirty())
|
| + continue;
|
| + tracker->set_dirty(true);
|
| + PutFileTrackerToBatch(*tracker, batch);
|
| + index->StoreFileTracker(tracker.Pass());
|
| + }
|
| +}
|
| +
|
| +void MarkTrackersDirtyByPath(int64 parent_tracker_id,
|
| + const std::string& title,
|
| + MetadataDatabaseIndex* index,
|
| + leveldb::WriteBatch* batch) {
|
| + if (parent_tracker_id == kInvalidTrackerID || title.empty())
|
| + return;
|
| + MarkTrackerSetDirty(
|
| + index->GetFileTrackerIDsByParentAndTitle(parent_tracker_id, title),
|
| + index, batch);
|
| +}
|
| +
|
| +void MarkTrackersDirtyByFileID(const std::string& file_id,
|
| + MetadataDatabaseIndex* index,
|
| + leveldb::WriteBatch* batch) {
|
| + MarkTrackerSetDirty(index->GetFileTrackerIDsByFileID(file_id),
|
| + index, batch);
|
| +}
|
| +
|
| +void MarkTrackersDirtyRecursively(int64 root_tracker_id,
|
| + MetadataDatabaseIndex* index,
|
| + leveldb::WriteBatch* batch) {
|
| + std::vector<int64> stack;
|
| + stack.push_back(root_tracker_id);
|
| + while (!stack.empty()) {
|
| + int64 tracker_id = stack.back();
|
| + stack.pop_back();
|
| + AppendContents(index->GetFileTrackerIDsByParent(tracker_id), &stack);
|
| +
|
| + scoped_ptr<FileTracker> tracker = Clone(index->GetFileTracker(tracker_id));
|
| + tracker->set_dirty(true);
|
| +
|
| + PutFileTrackerToBatch(*tracker, batch);
|
| + index->StoreFileTracker(tracker.Pass());
|
| + }
|
| +}
|
| +
|
| +void RemoveAllDescendantTrackers(int64 root_tracker_id,
|
| + MetadataDatabaseIndex* index,
|
| + leveldb::WriteBatch* batch) {
|
| + std::vector<int64> pending_trackers;
|
| + AppendContents(index->GetFileTrackerIDsByParent(root_tracker_id),
|
| + &pending_trackers);
|
| +
|
| + std::vector<int64> to_be_removed;
|
| + base::hash_set<std::string> affected_file_ids;
|
| +
|
| + // List trackers to remove.
|
| + while (!pending_trackers.empty()) {
|
| + int64 tracker_id = pending_trackers.back();
|
| + pending_trackers.pop_back();
|
| + AppendContents(index->GetFileTrackerIDsByParent(tracker_id),
|
| + &pending_trackers);
|
| + to_be_removed.push_back(tracker_id);
|
| + }
|
| +
|
| + // Remove trackers in the reversed order.
|
| + for (std::vector<int64>::reverse_iterator itr = to_be_removed.rbegin();
|
| + itr != to_be_removed.rend(); ++itr) {
|
| + const FileTracker* trackers = index->GetFileTracker(*itr);
|
| + affected_file_ids.insert(trackers->file_id());
|
| + PutFileTrackerDeletionToBatch(*itr, batch);
|
| + index->RemoveFileTracker(*itr);
|
| + }
|
| +
|
| + for (base::hash_set<std::string>::iterator itr = affected_file_ids.begin();
|
| + itr != affected_file_ids.end(); ++itr) {
|
| + TrackerIDSet trackers = index->GetFileTrackerIDsByFileID(*itr);
|
| + if (trackers.empty()) {
|
| + // Remove metadata that no longer has any tracker.
|
| + PutFileMetadataDeletionToBatch(*itr, batch);
|
| + index->RemoveFileMetadata(*itr);
|
| + } else {
|
| + MarkTrackerSetDirty(trackers, index, batch);
|
| + }
|
| + }
|
| +}
|
| +
|
| +const FileTracker* FilterFileTrackersByParent(
|
| + const MetadataDatabaseIndex& index,
|
| + const TrackerIDSet& trackers,
|
| + int64 parent_tracker_id) {
|
| + for (TrackerIDSet::const_iterator itr = trackers.begin();
|
| + itr != trackers.end();
|
| + ++itr) {
|
| + const FileTracker* tracker = index.GetFileTracker(*itr);
|
| + if (!tracker) {
|
| + NOTREACHED();
|
| + continue;
|
| + }
|
| +
|
| + if (tracker->parent_tracker_id() == parent_tracker_id)
|
| + return tracker;
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| +const FileTracker* FilterFileTrackersByParentAndTitle(
|
| + const MetadataDatabaseIndex& index,
|
| + const TrackerIDSet& trackers,
|
| + int64 parent_tracker_id,
|
| + const std::string& title) {
|
| + const FileTracker* result = NULL;
|
| +
|
| + for (TrackerIDSet::const_iterator itr = trackers.begin();
|
| + itr != trackers.end(); ++itr) {
|
| + const FileTracker* tracker = index.GetFileTracker(*itr);
|
| + if (!tracker) {
|
| + NOTREACHED();
|
| + continue;
|
| + }
|
| +
|
| + if (tracker->parent_tracker_id() != parent_tracker_id)
|
| + continue;
|
| +
|
| + if (tracker->has_synced_details() &&
|
| + tracker->synced_details().title() != title)
|
| + continue;
|
| +
|
| + // Prioritize trackers that has |synced_details|.
|
| + if (!result || !tracker->has_synced_details())
|
| + result = tracker;
|
| + }
|
| +
|
| + return result;
|
| +}
|
| +
|
| +const FileTracker* FilterFileTrackersByFileID(
|
| + const MetadataDatabaseIndex& index,
|
| + const TrackerIDSet& trackers,
|
| + const std::string& file_id) {
|
| + for (TrackerIDSet::const_iterator itr = trackers.begin();
|
| + itr != trackers.end(); ++itr) {
|
| + const FileTracker* tracker = index.GetFileTracker(*itr);
|
| + if (!tracker) {
|
| + NOTREACHED();
|
| + continue;
|
| + }
|
| +
|
| + if (tracker->file_id() == file_id)
|
| + return tracker;
|
| + }
|
| +
|
| + return NULL;
|
| +}
|
| +
|
| +enum DirtyingOption {
|
| + MARK_NOTHING_DIRTY = 0,
|
| + MARK_ITSELF_DIRTY = 1 << 0,
|
| + MARK_SAME_FILE_ID_TRACKERS_DIRTY = 1 << 1,
|
| + MARK_SAME_PATH_TRACKERS_DIRTY = 1 << 2,
|
| +};
|
| +
|
| +void ActivateFileTracker(int64 tracker_id,
|
| + int dirtying_options,
|
| + MetadataDatabaseIndex* index,
|
| + leveldb::WriteBatch* batch) {
|
| + DCHECK(dirtying_options == MARK_NOTHING_DIRTY ||
|
| + dirtying_options == MARK_ITSELF_DIRTY);
|
| +
|
| + scoped_ptr<FileTracker> tracker = Clone(index->GetFileTracker(tracker_id));
|
| + tracker->set_active(true);
|
| + if (dirtying_options & MARK_ITSELF_DIRTY) {
|
| + tracker->set_dirty(true);
|
| + tracker->set_needs_folder_listing(
|
| + tracker->has_synced_details() &&
|
| + tracker->synced_details().file_kind() == FILE_KIND_FOLDER);
|
| + } else {
|
| + tracker->set_dirty(false);
|
| + tracker->set_needs_folder_listing(false);
|
| + }
|
| +
|
| + PutFileTrackerToBatch(*tracker, batch);
|
| + index->StoreFileTracker(tracker.Pass());
|
| +}
|
| +
|
| +void DeactivateFileTracker(int64 tracker_id,
|
| + int dirtying_options,
|
| + MetadataDatabaseIndex* index,
|
| + leveldb::WriteBatch* batch) {
|
| + RemoveAllDescendantTrackers(tracker_id, index, batch);
|
| +
|
| + scoped_ptr<FileTracker> tracker = Clone(index->GetFileTracker(tracker_id));
|
| +
|
| + if (dirtying_options & MARK_SAME_FILE_ID_TRACKERS_DIRTY)
|
| + MarkTrackersDirtyByFileID(tracker->file_id(), index, batch);
|
| + if (dirtying_options & MARK_SAME_PATH_TRACKERS_DIRTY) {
|
| + MarkTrackersDirtyByPath(tracker->parent_tracker_id(),
|
| + GetTrackerTitle(*tracker),
|
| + index, batch);
|
| + }
|
| +
|
| + tracker->set_dirty(dirtying_options & MARK_ITSELF_DIRTY);
|
| + tracker->set_active(false);
|
| + PutFileTrackerToBatch(*tracker, batch);
|
| + index->StoreFileTracker(tracker.Pass());
|
| +}
|
| +
|
| +void RemoveTracker(int64 tracker_id,
|
| + int dirtying_options,
|
| + MetadataDatabaseIndex* index,
|
| + leveldb::WriteBatch* batch) {
|
| + DCHECK(!(dirtying_options & MARK_ITSELF_DIRTY));
|
| +
|
| + const FileTracker* tracker = index->GetFileTracker(tracker_id);
|
| + if (!tracker)
|
| + return;
|
| +
|
| + std::string file_id = tracker->file_id();
|
| + int64 parent_tracker_id = tracker->parent_tracker_id();
|
| + std::string title = GetTrackerTitle(*tracker);
|
| +
|
| + RemoveAllDescendantTrackers(tracker_id, index, batch);
|
| + PutFileTrackerDeletionToBatch(tracker_id, batch);
|
| + index->RemoveFileTracker(tracker_id);
|
| +
|
| + if (dirtying_options & MARK_SAME_FILE_ID_TRACKERS_DIRTY)
|
| + MarkTrackersDirtyByFileID(file_id, index, batch);
|
| + if (dirtying_options & MARK_SAME_PATH_TRACKERS_DIRTY)
|
| + MarkTrackersDirtyByPath(parent_tracker_id, title, index, batch);
|
| +
|
| + if (index->GetFileTrackerIDsByFileID(file_id).empty()) {
|
| + PutFileMetadataDeletionToBatch(file_id, batch);
|
| + index->RemoveFileMetadata(file_id);
|
| + }
|
| +}
|
| +
|
| } // namespace
|
|
|
| DatabaseContents::DatabaseContents() {}
|
| DatabaseContents::~DatabaseContents() {}
|
|
|
| -bool MetadataDatabase::DirtyTrackerComparator::operator()(
|
| - const FileTracker* left,
|
| - const FileTracker* right) const {
|
| - return left->tracker_id() < right->tracker_id();
|
| -}
|
| -
|
| // static
|
| void MetadataDatabase::Create(base::SequencedTaskRunner* task_runner,
|
| const base::FilePath& database_path,
|
| @@ -499,8 +684,8 @@ void MetadataDatabase::PopulateInitialData(
|
| const google_apis::FileResource& sync_root_folder,
|
| const ScopedVector<google_apis::FileResource>& app_root_folders,
|
| const SyncStatusCallback& callback) {
|
| - DCHECK(tracker_by_id_.empty());
|
| - DCHECK(metadata_by_id_.empty());
|
| + DCHECK(index_->tracker_by_id_.empty());
|
| + DCHECK(index_->metadata_by_id_.empty());
|
|
|
| scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
|
| service_metadata_->set_largest_change_id(largest_change_id);
|
| @@ -514,23 +699,30 @@ void MetadataDatabase::PopulateInitialData(
|
| }
|
|
|
| bool MetadataDatabase::IsAppEnabled(const std::string& app_id) const {
|
| - FileTracker tracker;
|
| - if (!FindAppRootTracker(app_id, &tracker))
|
| + int64 tracker_id = index_->GetAppRootTracker(app_id);
|
| + if (tracker_id == kInvalidTrackerID)
|
| return false;
|
| - return tracker.tracker_kind() == TRACKER_KIND_APP_ROOT;
|
| +
|
| + const FileTracker* tracker = index_->GetFileTracker(tracker_id);
|
| + return tracker && tracker->tracker_kind() == TRACKER_KIND_APP_ROOT;
|
| }
|
|
|
| void MetadataDatabase::RegisterApp(const std::string& app_id,
|
| const std::string& folder_id,
|
| const SyncStatusCallback& callback) {
|
| - if (FindAppRootTracker(app_id, NULL)) {
|
| + if (index_->GetAppRootTracker(app_id)) {
|
| // The app-root is already registered.
|
| RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
|
| return;
|
| }
|
|
|
| - TrackerIDSet trackers;
|
| - if (!FindTrackersByFileID(folder_id, &trackers) || trackers.has_active()) {
|
| + TrackerIDSet trackers = index_->GetFileTrackerIDsByFileID(folder_id);
|
| + if (trackers.empty()) {
|
| + RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND));
|
| + return;
|
| + }
|
| +
|
| + if (trackers.has_active()) {
|
| // The folder is tracked by another tracker.
|
| util::Log(logging::LOG_WARNING, FROM_HERE,
|
| "Failed to register App for %s", app_id.c_str());
|
| @@ -546,129 +738,164 @@ void MetadataDatabase::RegisterApp(const std::string& app_id,
|
| return;
|
| }
|
|
|
| - // Make this tracker an app-root tracker.
|
| - const FileTracker* app_root_tracker = NULL;
|
| - for (TrackerIDSet::iterator itr = trackers.begin();
|
| - itr != trackers.end(); ++itr) {
|
| - const FileTracker* tracker = tracker_by_id_.get(*itr);
|
| - if (!tracker) {
|
| - NOTREACHED();
|
| - continue;
|
| - }
|
| -
|
| - if (tracker->parent_tracker_id() == sync_root_tracker_id)
|
| - app_root_tracker = tracker;
|
| - }
|
| -
|
| - if (!app_root_tracker) {
|
| + scoped_ptr<FileTracker> tracker =
|
| + Clone(FilterFileTrackersByParent(*index_, trackers,
|
| + sync_root_tracker_id));
|
| + if (!tracker) {
|
| RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND));
|
| return;
|
| }
|
|
|
| scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
|
| - RegisterTrackerAsAppRoot(app_id, app_root_tracker->tracker_id(), batch.get());
|
| + tracker->set_app_id(app_id);
|
| + tracker->set_tracker_kind(TRACKER_KIND_APP_ROOT);
|
| + tracker->set_active(true);
|
| + tracker->set_needs_folder_listing(true);
|
| + tracker->set_dirty(true);
|
| +
|
| + PutFileTrackerToBatch(*tracker, batch.get());
|
| + index_->StoreFileTracker(tracker.Pass());
|
| WriteToDatabase(batch.Pass(), callback);
|
| }
|
|
|
| void MetadataDatabase::DisableApp(const std::string& app_id,
|
| const SyncStatusCallback& callback) {
|
| - FileTracker tracker;
|
| - if (!FindAppRootTracker(app_id, &tracker)) {
|
| + int64 tracker_id = index_->GetAppRootTracker(app_id);
|
| + scoped_ptr<FileTracker> tracker = Clone(index_->GetFileTracker(tracker_id));
|
| + if (!tracker) {
|
| RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND));
|
| return;
|
| }
|
|
|
| - if (tracker.tracker_kind() == TRACKER_KIND_DISABLED_APP_ROOT) {
|
| + if (tracker->tracker_kind() == TRACKER_KIND_DISABLED_APP_ROOT) {
|
| RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
|
| return;
|
| }
|
|
|
| + DCHECK_EQ(TRACKER_KIND_APP_ROOT, tracker->tracker_kind());
|
| + DCHECK(tracker->active());
|
| +
|
| scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
|
| - MakeAppRootDisabled(tracker.tracker_id(), batch.get());
|
| +
|
| + // Keep the app-root tracker active (but change the tracker_kind) so that
|
| + // other conflicting trackers won't become active.
|
| + tracker->set_tracker_kind(TRACKER_KIND_DISABLED_APP_ROOT);
|
| +
|
| + PutFileTrackerToBatch(*tracker, batch.get());
|
| + index_->StoreFileTracker(tracker.Pass());
|
| WriteToDatabase(batch.Pass(), callback);
|
| }
|
|
|
| void MetadataDatabase::EnableApp(const std::string& app_id,
|
| const SyncStatusCallback& callback) {
|
| - FileTracker tracker;
|
| - if (!FindAppRootTracker(app_id, &tracker) ||
|
| - tracker.tracker_kind() == TRACKER_KIND_REGULAR) {
|
| + int64 tracker_id = index_->GetAppRootTracker(app_id);
|
| + scoped_ptr<FileTracker> tracker = Clone(index_->GetFileTracker(tracker_id));
|
| + if (!tracker) {
|
| RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND));
|
| return;
|
| }
|
|
|
| - if (tracker.tracker_kind() == TRACKER_KIND_APP_ROOT) {
|
| + if (tracker->tracker_kind() == TRACKER_KIND_APP_ROOT) {
|
| RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
|
| return;
|
| }
|
|
|
| + DCHECK_EQ(TRACKER_KIND_DISABLED_APP_ROOT, tracker->tracker_kind());
|
| + DCHECK(tracker->active());
|
| +
|
| scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
|
| - MakeAppRootEnabled(tracker.tracker_id(), batch.get());
|
| +
|
| + tracker->set_tracker_kind(TRACKER_KIND_APP_ROOT);
|
| + PutFileTrackerToBatch(*tracker, batch.get());
|
| + index_->StoreFileTracker(tracker.Pass());
|
| +
|
| + MarkTrackersDirtyRecursively(tracker_id, index_.get(), batch.get());
|
| WriteToDatabase(batch.Pass(), callback);
|
| }
|
|
|
| void MetadataDatabase::UnregisterApp(const std::string& app_id,
|
| const SyncStatusCallback& callback) {
|
| - FileTracker tracker;
|
| - if (!FindAppRootTracker(app_id, &tracker) ||
|
| - tracker.tracker_kind() == TRACKER_KIND_REGULAR) {
|
| + int64 tracker_id = index_->GetAppRootTracker(app_id);
|
| + scoped_ptr<FileTracker> tracker = Clone(index_->GetFileTracker(tracker_id));
|
| + if (!tracker || tracker->tracker_kind() == TRACKER_KIND_REGULAR) {
|
| RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
|
| return;
|
| }
|
|
|
| scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
|
| - UnregisterTrackerAsAppRoot(app_id, batch.get());
|
| + RemoveAllDescendantTrackers(tracker_id, index_.get(), batch.get());
|
| +
|
| + tracker->clear_app_id();
|
| + tracker->set_tracker_kind(TRACKER_KIND_REGULAR);
|
| + tracker->set_active(false);
|
| + tracker->set_dirty(true);
|
| +
|
| + PutFileTrackerToBatch(*tracker, batch.get());
|
| + index_->StoreFileTracker(tracker.Pass());
|
| WriteToDatabase(batch.Pass(), callback);
|
| }
|
|
|
| bool MetadataDatabase::FindAppRootTracker(const std::string& app_id,
|
| - FileTracker* tracker) const {
|
| - TrackerIDByAppID::const_iterator found = app_root_by_app_id_.find(app_id);
|
| - if (found == app_root_by_app_id_.end())
|
| + FileTracker* tracker_out) const {
|
| + int64 app_root_tracker_id = index_->GetAppRootTracker(app_id);
|
| + if (!app_root_tracker_id)
|
| return false;
|
|
|
| - if (tracker)
|
| - *tracker = *tracker_by_id_.get(found->second);
|
| + if (tracker_out) {
|
| + const FileTracker* app_root_tracker =
|
| + index_->GetFileTracker(app_root_tracker_id);
|
| + if (!app_root_tracker) {
|
| + NOTREACHED();
|
| + return false;
|
| + }
|
| + *tracker_out = *app_root_tracker;
|
| + }
|
| return true;
|
| }
|
|
|
| bool MetadataDatabase::FindFileByFileID(const std::string& file_id,
|
| - FileMetadata* file) const {
|
| - return FindItem(metadata_by_id_, file_id, file);
|
| + FileMetadata* metadata_out) const {
|
| + const FileMetadata* metadata = index_->GetFileMetadata(file_id);
|
| + if (!metadata)
|
| + return false;
|
| + if (metadata_out)
|
| + *metadata_out = *metadata;
|
| + return true;
|
| }
|
|
|
| bool MetadataDatabase::FindTrackersByFileID(const std::string& file_id,
|
| - TrackerIDSet* trackers) const {
|
| - TrackerIDsByFileID::const_iterator found = trackers_by_file_id_.find(file_id);
|
| - if (found == trackers_by_file_id_.end())
|
| + TrackerIDSet* trackers_out) const {
|
| + TrackerIDSet trackers = index_->GetFileTrackerIDsByFileID(file_id);
|
| + if (trackers.empty())
|
| return false;
|
| - if (trackers)
|
| - *trackers = found->second;
|
| +
|
| + if (trackers_out)
|
| + std::swap(trackers, *trackers_out);
|
| return true;
|
| }
|
|
|
| bool MetadataDatabase::FindTrackersByParentAndTitle(
|
| int64 parent_tracker_id,
|
| const std::string& title,
|
| - TrackerIDSet* trackers) const {
|
| - TrackerIDsByParentAndTitle::const_iterator found_by_parent =
|
| - trackers_by_parent_and_title_.find(parent_tracker_id);
|
| - if (found_by_parent == trackers_by_parent_and_title_.end())
|
| + TrackerIDSet* trackers_out) const {
|
| + TrackerIDSet trackers =
|
| + index_->GetFileTrackerIDsByParentAndTitle(parent_tracker_id, title);
|
| + if (trackers.empty())
|
| return false;
|
|
|
| - TrackerIDsByTitle::const_iterator found_by_title =
|
| - found_by_parent->second.find(title);
|
| - if (found_by_title == found_by_parent->second.end())
|
| - return false;
|
| -
|
| - if (trackers)
|
| - *trackers = found_by_title->second;
|
| + if (trackers_out)
|
| + std::swap(trackers, *trackers_out);
|
| return true;
|
| }
|
|
|
| bool MetadataDatabase::FindTrackerByTrackerID(int64 tracker_id,
|
| - FileTracker* tracker) const {
|
| - return FindItem(tracker_by_id_, tracker_id, tracker);
|
| + FileTracker* tracker_out) const {
|
| + const FileTracker* tracker = index_->GetFileTracker(tracker_id);
|
| + if (!tracker)
|
| + return false;
|
| + if (tracker_out)
|
| + *tracker_out = *tracker;
|
| + return true;
|
| }
|
|
|
| bool MetadataDatabase::BuildPathForTracker(int64 tracker_id,
|
| @@ -738,14 +965,8 @@ bool MetadataDatabase::FindNearestActiveAncestor(
|
| return true;
|
| }
|
|
|
| - TrackerByID::const_iterator found =
|
| - tracker_by_id_.find(trackers.active_tracker());
|
| - if (found == tracker_by_id_.end()) {
|
| - NOTREACHED();
|
| - return false;
|
| - }
|
| -
|
| - FileTracker* tracker = found->second;
|
| + const FileTracker* tracker =
|
| + index_->GetFileTracker(trackers.active_tracker());;
|
|
|
| DCHECK(tracker->has_synced_details());
|
| const FileDetails& details = tracker->synced_details();
|
| @@ -769,11 +990,8 @@ void MetadataDatabase::UpdateByChangeList(
|
|
|
| scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
|
|
|
| - for (ScopedVector<google_apis::ChangeResource>::const_iterator itr =
|
| - changes.begin();
|
| - itr != changes.end();
|
| - ++itr) {
|
| - const google_apis::ChangeResource& change = **itr;
|
| + for (size_t i = 0; i < changes.size(); ++i) {
|
| + const google_apis::ChangeResource& change = *changes[i];
|
| if (HasNewerFileMetadata(change.file_id(), change.change_id()))
|
| continue;
|
|
|
| @@ -851,19 +1069,41 @@ void MetadataDatabase::ReplaceActiveTrackerWithNewResource(
|
| int64 parent_tracker_id,
|
| const google_apis::FileResource& resource,
|
| const SyncStatusCallback& callback) {
|
| - scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
|
| + DCHECK(index_->GetFileTracker(parent_tracker_id));
|
| + DCHECK(!index_->GetFileMetadata(resource.file_id()));
|
|
|
| - DCHECK(!ContainsKey(metadata_by_id_, resource.file_id()));
|
| + scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
|
| UpdateByFileMetadata(
|
| FROM_HERE,
|
| CreateFileMetadataFromFileResource(GetLargestKnownChangeID(), resource),
|
| UPDATE_TRACKER_FOR_SYNCED_FILE,
|
| batch.get());
|
| - DCHECK(ContainsKey(metadata_by_id_, resource.file_id()));
|
|
|
| - ForceActivateTrackerByPath(
|
| - parent_tracker_id, resource.title(), resource.file_id(), batch.get());
|
| + DCHECK(index_->GetFileMetadata(resource.file_id()));
|
| + DCHECK(!index_->GetFileTrackerIDsByFileID(resource.file_id()).has_active());
|
| +
|
| + TrackerIDSet same_path_trackers =
|
| + index_->GetFileTrackerIDsByParentAndTitle(
|
| + parent_tracker_id, resource.title());
|
| + const FileTracker* to_be_activated =
|
| + FilterFileTrackersByFileID(*index_, same_path_trackers,
|
| + resource.file_id());
|
| + if (!to_be_activated) {
|
| + NOTREACHED();
|
| + RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_FAILED));
|
| + return;
|
| + }
|
|
|
| + int64 tracker_id = to_be_activated->tracker_id();
|
| + if (same_path_trackers.has_active()) {
|
| + DeactivateFileTracker(same_path_trackers.active_tracker(),
|
| + MARK_ITSELF_DIRTY |
|
| + MARK_SAME_FILE_ID_TRACKERS_DIRTY,
|
| + index_.get(), batch.get());
|
| + }
|
| +
|
| + ActivateFileTracker(tracker_id, MARK_NOTHING_DIRTY,
|
| + index_.get(), batch.get());
|
| WriteToDatabase(batch.Pass(), callback);
|
| }
|
|
|
| @@ -871,35 +1111,45 @@ void MetadataDatabase::PopulateFolderByChildList(
|
| const std::string& folder_id,
|
| const FileIDList& child_file_ids,
|
| const SyncStatusCallback& callback) {
|
| - TrackerIDSet trackers;
|
| - if (!FindTrackersByFileID(folder_id, &trackers) ||
|
| - !trackers.has_active()) {
|
| + TrackerIDSet trackers = index_->GetFileTrackerIDsByFileID(folder_id);
|
| + if (!trackers.has_active()) {
|
| // It's OK that there is no folder to populate its children.
|
| // Inactive folders should ignore their contents updates.
|
| RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
|
| return;
|
| }
|
|
|
| - FileTracker* folder_tracker = tracker_by_id_.get(trackers.active_tracker());
|
| - DCHECK(folder_tracker);
|
| - std::set<std::string> children(child_file_ids.begin(), child_file_ids.end());
|
| + scoped_ptr<FileTracker> folder_tracker =
|
| + Clone(index_->GetFileTracker(trackers.active_tracker()));
|
| + if (!folder_tracker) {
|
| + NOTREACHED();
|
| + RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_FAILED));
|
| + return;
|
| + }
|
| +
|
| + base::hash_set<std::string> children(child_file_ids.begin(),
|
| + child_file_ids.end());
|
|
|
| - std::vector<int64> known_children;
|
| - PushChildTrackersToContainer(trackers_by_parent_and_title_,
|
| - folder_tracker->tracker_id(),
|
| - std::back_inserter(known_children));
|
| - for (std::vector<int64>::iterator itr = known_children.begin();
|
| - itr != known_children.end(); ++itr)
|
| - children.erase(tracker_by_id_.get(*itr)->file_id());
|
| + std::vector<int64> known_children =
|
| + index_->GetFileTrackerIDsByParent(folder_tracker->tracker_id());
|
| + for (size_t i = 0; i < known_children.size(); ++i) {
|
| + const FileTracker* tracker = index_->GetFileTracker(known_children[i]);
|
| + if (!tracker) {
|
| + NOTREACHED();
|
| + continue;
|
| + }
|
| + children.erase(tracker->file_id());
|
| + }
|
|
|
| scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
|
| - for (FileIDList::const_iterator itr = child_file_ids.begin();
|
| - itr != child_file_ids.end(); ++itr)
|
| + for (base::hash_set<std::string>::const_iterator itr = children.begin();
|
| + itr != children.end(); ++itr)
|
| CreateTrackerForParentAndFileID(*folder_tracker, *itr, batch.get());
|
| folder_tracker->set_needs_folder_listing(false);
|
| if (folder_tracker->dirty() && !ShouldKeepDirty(*folder_tracker))
|
| - ClearDirty(folder_tracker, NULL);
|
| + folder_tracker->set_dirty(false);
|
| PutFileTrackerToBatch(*folder_tracker, batch.get());
|
| + index_->StoreFileTracker(folder_tracker.Pass());
|
|
|
| WriteToDatabase(batch.Pass(), callback);
|
| }
|
| @@ -907,23 +1157,25 @@ void MetadataDatabase::PopulateFolderByChildList(
|
| void MetadataDatabase::UpdateTracker(int64 tracker_id,
|
| const FileDetails& updated_details,
|
| const SyncStatusCallback& callback) {
|
| - TrackerByID::iterator found = tracker_by_id_.find(tracker_id);
|
| - if (found == tracker_by_id_.end()) {
|
| + const FileTracker* tracker = index_->GetFileTracker(tracker_id);
|
| + if (!tracker) {
|
| RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND));
|
| return;
|
| }
|
| -
|
| - FileTracker* tracker = found->second;
|
| DCHECK(tracker);
|
|
|
| scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
|
|
|
| + // Check if the tracker is to be deleted.
|
| if (updated_details.missing()) {
|
| - MetadataByID::iterator found = metadata_by_id_.find(tracker->file_id());
|
| - if (found == metadata_by_id_.end() || found->second->details().missing()) {
|
| + const FileMetadata* metadata = index_->GetFileMetadata(tracker->file_id());
|
| + if (!metadata || metadata->details().missing()) {
|
| // Both the tracker and metadata have the missing flag, now it's safe to
|
| // delete the |tracker|.
|
| - RemoveTracker(tracker->tracker_id(), batch.get());
|
| + RemoveTracker(tracker_id,
|
| + MARK_SAME_FILE_ID_TRACKERS_DIRTY |
|
| + MARK_SAME_PATH_TRACKERS_DIRTY,
|
| + index_.get(), batch.get());
|
| WriteToDatabase(batch.Pass(), callback);
|
| return;
|
| }
|
| @@ -939,60 +1191,63 @@ void MetadataDatabase::UpdateTracker(int64 tracker_id,
|
| // Check if the tracker's parent is still in |parent_tracker_ids|.
|
| // If not, there should exist another tracker for the new parent, so delete
|
| // old tracker.
|
| - DCHECK(ContainsKey(tracker_by_id_, tracker->parent_tracker_id()));
|
| - FileTracker* parent_tracker =
|
| - tracker_by_id_.get(tracker->parent_tracker_id());
|
| + const FileTracker* parent_tracker =
|
| + index_->GetFileTracker(tracker->parent_tracker_id());
|
| + DCHECK(parent_tracker);
|
| +
|
| if (!HasFileAsParent(updated_details, parent_tracker->file_id())) {
|
| - RemoveTracker(tracker->tracker_id(), batch.get());
|
| + RemoveTracker(tracker->tracker_id(),
|
| + MARK_SAME_PATH_TRACKERS_DIRTY,
|
| + index_.get(), batch.get());
|
| WriteToDatabase(batch.Pass(), callback);
|
| return;
|
| }
|
|
|
| if (tracker->has_synced_details()) {
|
| // Check if the tracker was retitled. If it was, there should exist
|
| - // another tracker for the new title, so delete old tracker.
|
| + // another tracker for the new title, so delete the tracker being updated.
|
| if (tracker->synced_details().title() != updated_details.title()) {
|
| - RemoveTracker(tracker->tracker_id(), batch.get());
|
| + RemoveTracker(tracker->tracker_id(),
|
| + MARK_SAME_FILE_ID_TRACKERS_DIRTY,
|
| + index_.get(), batch.get());
|
| WriteToDatabase(batch.Pass(), callback);
|
| return;
|
| }
|
| } else {
|
| - int64 parent_tracker_id = parent_tracker->tracker_id();
|
| - const std::string& title = updated_details.title();
|
| - TrackerIDSet* trackers =
|
| - &trackers_by_parent_and_title_[parent_tracker_id][title];
|
| -
|
| - for (TrackerIDSet::iterator itr = trackers->begin();
|
| - itr != trackers->end(); ++itr) {
|
| - FileTracker* same_path_tracker = tracker_by_id_.get(*itr);
|
| - if (!same_path_tracker) {
|
| - NOTREACHED();
|
| - continue;
|
| - }
|
| -
|
| - if (same_path_tracker->file_id() == tracker->file_id()) {
|
| - RemoveTracker(tracker->tracker_id(), batch.get());
|
| - WriteToDatabase(batch.Pass(), callback);
|
| - return;
|
| - }
|
| + // Check if any other tracker exists has the same parent, title and
|
| + // file_id to the updated tracker. If it exists, delete the tracker being
|
| + // updated.
|
| + if (FilterFileTrackersByFileID(
|
| + *index_,
|
| + index_->GetFileTrackerIDsByParentAndTitle(
|
| + parent_tracker->tracker_id(),
|
| + updated_details.title()),
|
| + tracker->file_id())) {
|
| + RemoveTracker(tracker->tracker_id(),
|
| + MARK_NOTHING_DIRTY,
|
| + index_.get(), batch.get());
|
| + WriteToDatabase(batch.Pass(), callback);
|
| + return;
|
| }
|
| -
|
| - trackers_by_parent_and_title_[parent_tracker_id][std::string()].Erase(
|
| - tracker_id);
|
| - trackers->Insert(*tracker);
|
| }
|
| }
|
|
|
| - *tracker->mutable_synced_details() = updated_details;
|
| + scoped_ptr<FileTracker> updated_tracker = Clone(tracker);
|
| + *updated_tracker->mutable_synced_details() = updated_details;
|
|
|
| // Activate the tracker if:
|
| // - There is no active tracker that tracks |tracker->file_id()|.
|
| // - There is no active tracker that has the same |parent| and |title|.
|
| - if (!tracker->active() && CanActivateTracker(*tracker))
|
| - MakeTrackerActive(tracker->tracker_id(), batch.get());
|
| - if (tracker->dirty() && !ShouldKeepDirty(*tracker))
|
| - ClearDirty(tracker, NULL);
|
| + if (!tracker->active() && CanActivateTracker(*tracker)) {
|
| + updated_tracker->set_active(true);
|
| + updated_tracker->set_dirty(true);
|
| + updated_tracker->set_needs_folder_listing(
|
| + tracker->synced_details().file_kind() == FILE_KIND_FOLDER);
|
| + } else if (tracker->dirty() && !ShouldKeepDirty(*tracker)) {
|
| + updated_tracker->set_dirty(false);
|
| + }
|
| PutFileTrackerToBatch(*tracker, batch.get());
|
| + index_->StoreFileTracker(updated_tracker.Pass());
|
|
|
| WriteToDatabase(batch.Pass(), callback);
|
| }
|
| @@ -1001,174 +1256,163 @@ MetadataDatabase::ActivationStatus MetadataDatabase::TryActivateTracker(
|
| int64 parent_tracker_id,
|
| const std::string& file_id,
|
| const SyncStatusCallback& callback) {
|
| - DCHECK(ContainsKey(tracker_by_id_, parent_tracker_id));
|
| - DCHECK(ContainsKey(metadata_by_id_, file_id));
|
| + DCHECK(index_->GetFileTracker(parent_tracker_id));
|
|
|
| - FileMetadata metadata;
|
| - if (!FindFileByFileID(file_id, &metadata)) {
|
| + const FileMetadata* metadata = index_->GetFileMetadata(file_id);
|
| + if (!metadata) {
|
| NOTREACHED();
|
| RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_FAILED));
|
| return ACTIVATION_PENDING;
|
| }
|
| - std::string title = metadata.details().title();
|
| + std::string title = metadata->details().title();
|
| DCHECK(!HasInvalidTitle(title));
|
|
|
| - TrackerIDSet same_file_id;
|
| - FindTrackersByFileID(file_id, &same_file_id);
|
| -
|
| - // Pick up the tracker to be activated, that has:
|
| - // - |parent_tarcker_id| as the parent, and
|
| - // - |file_id| as the tracker's |file_id|.
|
| - FileTracker* tracker = NULL;
|
| - for (TrackerIDSet::iterator itr = same_file_id.begin();
|
| - itr != same_file_id.end(); ++itr) {
|
| - FileTracker* candidate = tracker_by_id_.get(*itr);
|
| - if (!candidate) {
|
| - NOTREACHED();
|
| - continue;
|
| - }
|
| -
|
| - if (candidate->parent_tracker_id() != parent_tracker_id)
|
| - continue;
|
| -
|
| - if (candidate->has_synced_details() &&
|
| - candidate->synced_details().title() != title)
|
| - continue;
|
| - tracker = candidate;
|
| - }
|
| -
|
| - DCHECK(tracker);
|
| + TrackerIDSet same_file_id_trackers =
|
| + index_->GetFileTrackerIDsByFileID(file_id);
|
| + scoped_ptr<FileTracker> tracker_to_be_activated =
|
| + Clone(FilterFileTrackersByParentAndTitle(
|
| + *index_, same_file_id_trackers,
|
| + parent_tracker_id, title));
|
| + DCHECK(tracker_to_be_activated);
|
|
|
| // Check if there is another active tracker that tracks |file_id|.
|
| // This can happen when the tracked file has multiple parents.
|
| // In this case, report the failure to the caller.
|
| - if (!tracker->active() && same_file_id.has_active())
|
| + if (!tracker_to_be_activated->active() && same_file_id_trackers.has_active())
|
| return ACTIVATION_FAILED_ANOTHER_ACTIVE_TRACKER;
|
|
|
| scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
|
|
|
| - if (!tracker->active()) {
|
| - // Check if there is another active tracker that has the same path to
|
| - // the tracker to be activated.
|
| - // Assuming the caller already overrides local file with newly added file,
|
| - // inactivate existing active tracker.
|
| - TrackerIDSet same_title;
|
| - FindTrackersByParentAndTitle(parent_tracker_id, title, &same_title);
|
| - if (same_title.has_active()) {
|
| - MakeTrackerInactive(same_title.active_tracker(), batch.get());
|
| + if (!tracker_to_be_activated->active()) {
|
| + // Check if there exists another active tracker that has the same path to
|
| + // the tracker. If there is, deactivate it, assuming the caller already
|
| + // overrides local file with newly added file,
|
| + TrackerIDSet same_title_trackers =
|
| + index_->GetFileTrackerIDsByParentAndTitle(parent_tracker_id, title);
|
| + if (same_title_trackers.has_active()) {
|
| + RemoveAllDescendantTrackers(same_title_trackers.active_tracker(),
|
| + index_.get(), batch.get());
|
| +
|
| + scoped_ptr<FileTracker> tracker_to_be_deactivated =
|
| + Clone(index_->GetFileTracker(same_title_trackers.active_tracker()));
|
| + if (tracker_to_be_deactivated) {
|
| + const std::string file_id = tracker_to_be_deactivated->file_id();
|
| + tracker_to_be_deactivated->set_active(false);
|
| + PutFileTrackerToBatch(*tracker_to_be_deactivated, batch.get());
|
| + index_->StoreFileTracker(tracker_to_be_deactivated.Pass());
|
| +
|
| + MarkTrackersDirtyByFileID(file_id, index_.get(), batch.get());
|
| + } else {
|
| + LOG(ERROR) << "HERE";
|
| + NOTREACHED();
|
| + }
|
| }
|
| }
|
|
|
| - if (!tracker->has_synced_details() ||
|
| - tracker->synced_details().title() != title) {
|
| - trackers_by_parent_and_title_[parent_tracker_id]
|
| - [GetTrackerTitle(*tracker)].Erase(tracker->tracker_id());
|
| - trackers_by_parent_and_title_[parent_tracker_id][title]
|
| - .InsertInactiveTracker(tracker->tracker_id());
|
| + tracker_to_be_activated->set_dirty(false);
|
| + tracker_to_be_activated->set_active(true);
|
| + *tracker_to_be_activated->mutable_synced_details() = metadata->details();
|
| + if (tracker_to_be_activated->synced_details().file_kind() ==
|
| + FILE_KIND_FOLDER) {
|
| + tracker_to_be_activated->set_needs_folder_listing(true);
|
| }
|
| - *tracker->mutable_synced_details() = metadata.details();
|
| + tracker_to_be_activated->set_dirty(false);
|
|
|
| - MakeTrackerActive(tracker->tracker_id(), batch.get());
|
| - ClearDirty(tracker_by_id_.get(tracker->tracker_id()), batch.get());
|
| + PutFileTrackerToBatch(*tracker_to_be_activated, batch.get());
|
| + index_->StoreFileTracker(tracker_to_be_activated.Pass());
|
|
|
| WriteToDatabase(batch.Pass(), callback);
|
| return ACTIVATION_PENDING;
|
| }
|
|
|
| void MetadataDatabase::LowerTrackerPriority(int64 tracker_id) {
|
| - TrackerByID::const_iterator found = tracker_by_id_.find(tracker_id);
|
| - if (found == tracker_by_id_.end())
|
| - return;
|
| -
|
| - FileTracker* tracker = found->second;
|
| - if (dirty_trackers_.erase(tracker))
|
| - low_priority_dirty_trackers_.insert(tracker);
|
| + index_->DemoteDirtyTracker(tracker_id);
|
| }
|
|
|
| void MetadataDatabase::PromoteLowerPriorityTrackersToNormal() {
|
| - if (dirty_trackers_.empty()) {
|
| - dirty_trackers_.swap(low_priority_dirty_trackers_);
|
| - return;
|
| - }
|
| - dirty_trackers_.insert(low_priority_dirty_trackers_.begin(),
|
| - low_priority_dirty_trackers_.end());
|
| - low_priority_dirty_trackers_.clear();
|
| + index_->PromoteDemotedDirtyTrackers();
|
| }
|
|
|
| bool MetadataDatabase::GetNormalPriorityDirtyTracker(
|
| - FileTracker* tracker) const {
|
| - DirtyTrackers::const_iterator itr = dirty_trackers_.begin();
|
| - if (itr == dirty_trackers_.end())
|
| + FileTracker* tracker_out) const {
|
| + int64 dirty_tracker_id = index_->PickDirtyTracker();
|
| + if (!dirty_tracker_id)
|
| return false;
|
| - if (tracker)
|
| - *tracker = **itr;
|
| +
|
| + if (tracker_out) {
|
| + const FileTracker* tracker =
|
| + index_->GetFileTracker(dirty_tracker_id);
|
| + if (!tracker) {
|
| + NOTREACHED();
|
| + return false;
|
| + }
|
| + *tracker_out = *tracker;
|
| + }
|
| return true;
|
| }
|
|
|
| bool MetadataDatabase::HasLowPriorityDirtyTracker() const {
|
| - return !low_priority_dirty_trackers_.empty();
|
| + return index_->HasDemotedDirtyTracker();
|
| }
|
|
|
| bool MetadataDatabase::HasDirtyTracker() const {
|
| - return CountDirtyTracker() != 0;
|
| + return index_->PickDirtyTracker() != kInvalidTrackerID;
|
| }
|
|
|
| size_t MetadataDatabase::CountDirtyTracker() const {
|
| - return dirty_trackers_.size() + low_priority_dirty_trackers_.size();
|
| + return index_->dirty_trackers_.size() +
|
| + index_->demoted_dirty_trackers_.size();
|
| +}
|
| +
|
| +bool MetadataDatabase::GetMultiParentFileTrackers(std::string* file_id_out,
|
| + TrackerIDSet* trackers_out) {
|
| + DCHECK(file_id_out);
|
| + DCHECK(trackers_out);
|
| +
|
| + std::string file_id = index_->PickMultiTrackerFileID();
|
| + if (file_id.empty())
|
| + return false;
|
| +
|
| + TrackerIDSet trackers = index_->GetFileTrackerIDsByFileID(file_id);
|
| + if (trackers.size() <= 1) {
|
| + NOTREACHED();
|
| + return false;
|
| + }
|
| +
|
| + *file_id_out = file_id;
|
| + std::swap(*trackers_out, trackers);
|
| + return true;
|
| }
|
|
|
| size_t MetadataDatabase::CountFileMetadata() const {
|
| - return metadata_by_id_.size();
|
| + return index_->metadata_by_id_.size();
|
| }
|
|
|
| size_t MetadataDatabase::CountFileTracker() const {
|
| - return tracker_by_id_.size();
|
| -}
|
| -
|
| -bool MetadataDatabase::GetMultiParentFileTrackers(std::string* file_id,
|
| - TrackerIDSet* trackers) {
|
| - DCHECK(file_id);
|
| - DCHECK(trackers);
|
| - // TODO(tzik): Make this function more efficient.
|
| - for (TrackerIDsByFileID::const_iterator itr = trackers_by_file_id_.begin();
|
| - itr != trackers_by_file_id_.end(); ++itr) {
|
| - if (itr->second.size() > 1 && itr->second.has_active()) {
|
| - *file_id = itr->first;
|
| - *trackers = itr->second;
|
| - return true;
|
| - }
|
| - }
|
| - return false;
|
| + return index_->tracker_by_id_.size();
|
| }
|
|
|
| -bool MetadataDatabase::GetConflictingTrackers(TrackerIDSet* trackers) {
|
| - DCHECK(trackers);
|
| - // TODO(tzik): Make this function more efficient.
|
| - for (TrackerIDsByParentAndTitle::const_iterator parent_itr =
|
| - trackers_by_parent_and_title_.begin();
|
| - parent_itr != trackers_by_parent_and_title_.end();
|
| - ++parent_itr) {
|
| - const TrackerIDsByTitle& trackers_by_title = parent_itr->second;
|
| - for (TrackerIDsByTitle::const_iterator itr = trackers_by_title.begin();
|
| - itr != trackers_by_title.end();
|
| - ++itr) {
|
| - if (itr->second.size() > 1 && itr->second.has_active()) {
|
| - *trackers = itr->second;
|
| - return true;
|
| - }
|
| - }
|
| +bool MetadataDatabase::GetConflictingTrackers(TrackerIDSet* trackers_out) {
|
| + DCHECK(trackers_out);
|
| +
|
| + ParentIDAndTitle parent_and_title = index_->PickMultiBackingFilePath();
|
| + if (parent_and_title.parent_id == kInvalidTrackerID)
|
| + return false;
|
| +
|
| + TrackerIDSet trackers = index_->GetFileTrackerIDsByParentAndTitle(
|
| + parent_and_title.parent_id, parent_and_title.title);
|
| + if (trackers.size() <= 1) {
|
| + NOTREACHED();
|
| + return false;
|
| }
|
| - return false;
|
| +
|
| + std::swap(*trackers_out, trackers);
|
| + return true;
|
| }
|
|
|
| void MetadataDatabase::GetRegisteredAppIDs(std::vector<std::string>* app_ids) {
|
| DCHECK(app_ids);
|
| - app_ids->clear();
|
| - app_ids->reserve(app_root_by_app_id_.size());
|
| - for (TrackerIDByAppID::iterator itr = app_root_by_app_id_.begin();
|
| - itr != app_root_by_app_id_.end(); ++itr) {
|
| - app_ids->push_back(itr->first);
|
| - }
|
| + *app_ids = index_->GetRegisteredAppIDs();
|
| }
|
|
|
| MetadataDatabase::MetadataDatabase(base::SequencedTaskRunner* task_runner,
|
| @@ -1249,137 +1493,7 @@ SyncStatusCode MetadataDatabase::InitializeOnTaskRunner() {
|
| void MetadataDatabase::BuildIndexes(DatabaseContents* contents) {
|
| service_metadata_ = contents->service_metadata.Pass();
|
| UpdateLargestKnownChangeID(service_metadata_->largest_change_id());
|
| -
|
| - for (ScopedVector<FileMetadata>::const_iterator itr =
|
| - contents->file_metadata.begin();
|
| - itr != contents->file_metadata.end();
|
| - ++itr) {
|
| - // make_scoped_ptr balances weak_clear below.
|
| - metadata_by_id_.set((*itr)->file_id(), make_scoped_ptr(*itr));
|
| - }
|
| - contents->file_metadata.weak_clear();
|
| -
|
| - for (ScopedVector<FileTracker>::const_iterator itr =
|
| - contents->file_trackers.begin();
|
| - itr != contents->file_trackers.end();
|
| - ++itr) {
|
| - FileTracker* tracker = *itr;
|
| - // make_scoped_ptr balances weak_clear below.
|
| - tracker_by_id_.set(tracker->tracker_id(), make_scoped_ptr(tracker));
|
| - trackers_by_file_id_[tracker->file_id()].Insert(*tracker);
|
| -
|
| - if (IsAppRoot(*tracker))
|
| - app_root_by_app_id_[tracker->app_id()] = tracker->tracker_id();
|
| -
|
| - if (tracker->parent_tracker_id()) {
|
| - std::string title = GetTrackerTitle(*tracker);
|
| - TrackerIDSet* trackers =
|
| - &trackers_by_parent_and_title_[tracker->parent_tracker_id()][title];
|
| - trackers->Insert(*tracker);
|
| - }
|
| -
|
| - if (tracker->dirty())
|
| - dirty_trackers_.insert(tracker);
|
| - }
|
| - contents->file_trackers.weak_clear();
|
| -}
|
| -
|
| -void MetadataDatabase::RegisterTrackerAsAppRoot(
|
| - const std::string& app_id,
|
| - int64 tracker_id,
|
| - leveldb::WriteBatch* batch) {
|
| - FileTracker* tracker = tracker_by_id_.get(tracker_id);
|
| - DCHECK(tracker);
|
| - tracker->set_app_id(app_id);
|
| - tracker->set_tracker_kind(TRACKER_KIND_APP_ROOT);
|
| - app_root_by_app_id_[app_id] = tracker_id;
|
| -
|
| - MakeTrackerActive(tracker->tracker_id(), batch);
|
| -}
|
| -
|
| -void MetadataDatabase::UnregisterTrackerAsAppRoot(
|
| - const std::string& app_id,
|
| - leveldb::WriteBatch* batch) {
|
| - int64 tracker_id = FindAndEraseItem(&app_root_by_app_id_, app_id);
|
| - FileTracker* tracker = tracker_by_id_.get(tracker_id);
|
| - tracker->set_app_id(std::string());
|
| - tracker->set_tracker_kind(TRACKER_KIND_REGULAR);
|
| -
|
| - // Inactivate the tracker to drop all descendant.
|
| - // (Note that we set tracker_kind to TRACKER_KIND_REGULAR before calling
|
| - // this.)
|
| - MakeTrackerInactive(tracker_id, batch);
|
| -}
|
| -
|
| -void MetadataDatabase::MakeTrackerActive(int64 tracker_id,
|
| - leveldb::WriteBatch* batch) {
|
| - FileTracker* tracker = tracker_by_id_.get(tracker_id);
|
| - DCHECK(tracker);
|
| - DCHECK(!tracker->active());
|
| -
|
| - int64 parent_tracker_id = tracker->parent_tracker_id();
|
| - DCHECK(tracker->has_synced_details());
|
| - trackers_by_file_id_[tracker->file_id()].Activate(tracker_id);
|
| - if (parent_tracker_id) {
|
| - trackers_by_parent_and_title_[parent_tracker_id][
|
| - tracker->synced_details().title()].Activate(tracker_id);
|
| - }
|
| - tracker->set_active(true);
|
| - tracker->set_needs_folder_listing(
|
| - tracker->synced_details().file_kind() == FILE_KIND_FOLDER);
|
| -
|
| - // Make |tracker| a normal priority dirty tracker.
|
| - MarkSingleTrackerAsDirty(tracker, NULL);
|
| - PutFileTrackerToBatch(*tracker, batch);
|
| -}
|
| -
|
| -void MetadataDatabase::MakeTrackerInactive(int64 tracker_id,
|
| - leveldb::WriteBatch* batch) {
|
| - FileTracker* tracker = tracker_by_id_.get(tracker_id);
|
| - DCHECK(tracker);
|
| - DCHECK(tracker->active());
|
| - DCHECK_EQ(TRACKER_KIND_REGULAR, tracker->tracker_kind());
|
| - trackers_by_file_id_[tracker->file_id()].Deactivate(tracker_id);
|
| -
|
| - std::string title = GetTrackerTitle(*tracker);
|
| - int64 parent_tracker_id = tracker->parent_tracker_id();
|
| - if (parent_tracker_id) {
|
| - trackers_by_parent_and_title_[parent_tracker_id][title]
|
| - .Deactivate(tracker_id);
|
| - }
|
| - tracker->set_active(false);
|
| -
|
| - RemoveAllDescendantTrackers(tracker_id, batch);
|
| - MarkTrackersDirtyByFileID(tracker->file_id(), batch);
|
| - if (parent_tracker_id)
|
| - MarkTrackersDirtyByPath(parent_tracker_id, title, batch);
|
| - PutFileTrackerToBatch(*tracker, batch);
|
| -}
|
| -
|
| -void MetadataDatabase::MakeAppRootDisabled(int64 tracker_id,
|
| - leveldb::WriteBatch* batch) {
|
| - FileTracker* tracker = tracker_by_id_.get(tracker_id);
|
| - DCHECK(tracker);
|
| - DCHECK_EQ(TRACKER_KIND_APP_ROOT, tracker->tracker_kind());
|
| - DCHECK(tracker->active());
|
| -
|
| - // Keep the app-root tracker active (but change the tracker_kind) so that
|
| - // other conflicting trackers won't become active.
|
| - tracker->set_tracker_kind(TRACKER_KIND_DISABLED_APP_ROOT);
|
| - PutFileTrackerToBatch(*tracker, batch);
|
| -}
|
| -
|
| -void MetadataDatabase::MakeAppRootEnabled(int64 tracker_id,
|
| - leveldb::WriteBatch* batch) {
|
| - FileTracker* tracker = tracker_by_id_.get(tracker_id);
|
| - DCHECK(tracker);
|
| - DCHECK_EQ(TRACKER_KIND_DISABLED_APP_ROOT, tracker->tracker_kind());
|
| - DCHECK(tracker->active());
|
| -
|
| - tracker->set_tracker_kind(TRACKER_KIND_APP_ROOT);
|
| - // Mark descendant trackers as dirty to handle changes in disable period.
|
| - RecursiveMarkTrackerAsDirty(tracker_id, batch);
|
| - PutFileTrackerToBatch(*tracker, batch);
|
| + index_.reset(new MetadataDatabaseIndex(contents));
|
| }
|
|
|
| void MetadataDatabase::CreateTrackerForParentAndFileID(
|
| @@ -1427,57 +1541,7 @@ void MetadataDatabase::CreateTrackerInternal(const FileTracker& parent_tracker,
|
| }
|
| }
|
| PutFileTrackerToBatch(*tracker, batch);
|
| -
|
| - trackers_by_file_id_[file_id].InsertInactiveTracker(tracker->tracker_id());
|
| - // Note: |trackers_by_parent_and_title_| does not map from
|
| - // FileMetadata::details but from FileTracker::synced_details, which is filled
|
| - // on tracker updated phase. Use empty string as the title since
|
| - // FileTracker::synced_details is empty here.
|
| - std::string title;
|
| - if (details)
|
| - title = details->title();
|
| - trackers_by_parent_and_title_[parent_tracker.tracker_id()][title]
|
| - .InsertInactiveTracker(tracker->tracker_id());
|
| - dirty_trackers_.insert(tracker.get());
|
| - StoreFileTracker(tracker.Pass());
|
| -}
|
| -
|
| -void MetadataDatabase::RemoveTracker(int64 tracker_id,
|
| - leveldb::WriteBatch* batch) {
|
| - RemoveTrackerInternal(tracker_id, batch, false);
|
| - RemoveAllDescendantTrackers(tracker_id, batch);
|
| -}
|
| -
|
| -void MetadataDatabase::RemoveTrackerIgnoringSameTitle(
|
| - int64 tracker_id,
|
| - leveldb::WriteBatch* batch) {
|
| - RemoveTrackerInternal(tracker_id, batch, true);
|
| -}
|
| -
|
| -void MetadataDatabase::RemoveTrackerInternal(
|
| - int64 tracker_id,
|
| - leveldb::WriteBatch* batch,
|
| - bool ignoring_same_title) {
|
| - scoped_ptr<FileTracker> tracker(
|
| - tracker_by_id_.take_and_erase(tracker_id));
|
| - if (!tracker)
|
| - return;
|
| -
|
| - EraseTrackerFromFileIDIndex(tracker.get(), batch);
|
| - if (IsAppRoot(*tracker))
|
| - app_root_by_app_id_.erase(tracker->app_id());
|
| - EraseTrackerFromPathIndex(tracker.get());
|
| - dirty_trackers_.erase(tracker.get());
|
| - low_priority_dirty_trackers_.erase(tracker.get());
|
| -
|
| - MarkTrackersDirtyByFileID(tracker->file_id(), batch);
|
| - if (!ignoring_same_title) {
|
| - // Mark trackers having the same title with the given tracker as dirty.
|
| - MarkTrackersDirtyByPath(tracker->parent_tracker_id(),
|
| - GetTrackerTitle(*tracker),
|
| - batch);
|
| - }
|
| - PutFileTrackerDeletionToBatch(tracker_id, batch);
|
| + index_->StoreFileTracker(tracker.Pass());
|
| }
|
|
|
| void MetadataDatabase::MaybeAddTrackersForNewFile(
|
| @@ -1485,40 +1549,39 @@ void MetadataDatabase::MaybeAddTrackersForNewFile(
|
| UpdateOption option,
|
| leveldb::WriteBatch* batch) {
|
| std::set<int64> parents_to_exclude;
|
| - TrackerIDsByFileID::iterator found =
|
| - trackers_by_file_id_.find(metadata.file_id());
|
| - if (found != trackers_by_file_id_.end()) {
|
| - for (TrackerIDSet::const_iterator itr = found->second.begin();
|
| - itr != found->second.end(); ++itr) {
|
| - const FileTracker& tracker = *tracker_by_id_.get(*itr);
|
| - int64 parent_tracker_id = tracker.parent_tracker_id();
|
| - if (!parent_tracker_id)
|
| - continue;
|
| + TrackerIDSet existing_trackers =
|
| + index_->GetFileTrackerIDsByFileID(metadata.file_id());
|
| + for (TrackerIDSet::const_iterator itr = existing_trackers.begin();
|
| + itr != existing_trackers.end(); ++itr) {
|
| + const FileTracker* tracker = index_->GetFileTracker(*itr);
|
| + if (!tracker) {
|
| + NOTREACHED();
|
| + continue;
|
| + }
|
|
|
| - // Exclude |parent_tracker_id| if it already has a tracker that has
|
| - // unknown title or has the same title with |file|.
|
| - if (!tracker.has_synced_details() ||
|
| - tracker.synced_details().title() == metadata.details().title()) {
|
| - parents_to_exclude.insert(parent_tracker_id);
|
| - }
|
| + int64 parent_tracker_id = tracker->parent_tracker_id();
|
| + if (!parent_tracker_id)
|
| + continue;
|
| +
|
| + // Exclude |parent_tracker_id| if it already has a tracker that has
|
| + // unknown title or has the same title with |file|.
|
| + if (!tracker->has_synced_details() ||
|
| + tracker->synced_details().title() == metadata.details().title()) {
|
| + parents_to_exclude.insert(parent_tracker_id);
|
| }
|
| }
|
|
|
| for (int i = 0; i < metadata.details().parent_folder_ids_size(); ++i) {
|
| std::string parent_folder_id = metadata.details().parent_folder_ids(i);
|
| - TrackerIDsByFileID::iterator found =
|
| - trackers_by_file_id_.find(parent_folder_id);
|
| - if (found == trackers_by_file_id_.end())
|
| - continue;
|
| -
|
| - for (TrackerIDSet::const_iterator itr = found->second.begin();
|
| - itr != found->second.end(); ++itr) {
|
| - FileTracker* parent_tracker = tracker_by_id_.get(*itr);
|
| - int64 parent_tracker_id = parent_tracker->tracker_id();
|
| + TrackerIDSet parent_trackers =
|
| + index_->GetFileTrackerIDsByFileID(parent_folder_id);
|
| + for (TrackerIDSet::const_iterator itr = parent_trackers.begin();
|
| + itr != parent_trackers.end(); ++itr) {
|
| + const FileTracker* parent_tracker = index_->GetFileTracker(*itr);
|
| if (!parent_tracker->active())
|
| continue;
|
|
|
| - if (ContainsKey(parents_to_exclude, parent_tracker_id))
|
| + if (ContainsKey(parents_to_exclude, parent_tracker->tracker_id()))
|
| continue;
|
|
|
| CreateTrackerForParentAndFileMetadata(
|
| @@ -1527,115 +1590,6 @@ void MetadataDatabase::MaybeAddTrackersForNewFile(
|
| }
|
| }
|
|
|
| -void MetadataDatabase::RemoveAllDescendantTrackers(int64 root_tracker_id,
|
| - leveldb::WriteBatch* batch) {
|
| - std::vector<int64> pending_trackers;
|
| - PushChildTrackersToContainer(trackers_by_parent_and_title_,
|
| - root_tracker_id,
|
| - std::back_inserter(pending_trackers));
|
| -
|
| - while (!pending_trackers.empty()) {
|
| - int64 tracker_id = pending_trackers.back();
|
| - pending_trackers.pop_back();
|
| - PushChildTrackersToContainer(trackers_by_parent_and_title_,
|
| - tracker_id,
|
| - std::back_inserter(pending_trackers));
|
| - RemoveTrackerIgnoringSameTitle(tracker_id, batch);
|
| - }
|
| -}
|
| -
|
| -void MetadataDatabase::EraseTrackerFromFileIDIndex(FileTracker* tracker,
|
| - leveldb::WriteBatch* batch) {
|
| - TrackerIDsByFileID::iterator found =
|
| - trackers_by_file_id_.find(tracker->file_id());
|
| - if (found == trackers_by_file_id_.end())
|
| - return;
|
| -
|
| - TrackerIDSet* trackers = &found->second;
|
| - trackers->Erase(tracker->tracker_id());
|
| - if (!trackers->empty())
|
| - return;
|
| - trackers_by_file_id_.erase(found);
|
| - EraseFileFromDatabase(tracker->file_id(), batch);
|
| -}
|
| -
|
| -void MetadataDatabase::EraseFileFromDatabase(const std::string& file_id,
|
| - leveldb::WriteBatch* batch) {
|
| - scoped_ptr<FileMetadata> file(metadata_by_id_.take_and_erase(file_id));
|
| - if (file)
|
| - PutFileMetadataDeletionToBatch(file_id, batch);
|
| -}
|
| -
|
| -void MetadataDatabase::EraseTrackerFromPathIndex(FileTracker* tracker) {
|
| - TrackerIDsByParentAndTitle::iterator found =
|
| - trackers_by_parent_and_title_.find(tracker->parent_tracker_id());
|
| - if (found == trackers_by_parent_and_title_.end())
|
| - return;
|
| -
|
| - std::string title = GetTrackerTitle(*tracker);
|
| - TrackerIDsByTitle* trackers_by_title = &found->second;
|
| - TrackerIDsByTitle::iterator found_by_title = trackers_by_title->find(title);
|
| - TrackerIDSet* conflicting_trackers = &found_by_title->second;
|
| - conflicting_trackers->Erase(tracker->tracker_id());
|
| -
|
| - if (conflicting_trackers->empty()) {
|
| - trackers_by_title->erase(found_by_title);
|
| - if (trackers_by_title->empty())
|
| - trackers_by_parent_and_title_.erase(found);
|
| - }
|
| -}
|
| -
|
| -void MetadataDatabase::MarkSingleTrackerAsDirty(FileTracker* tracker,
|
| - leveldb::WriteBatch* batch) {
|
| - if (!tracker->dirty()) {
|
| - tracker->set_dirty(true);
|
| - PutFileTrackerToBatch(*tracker, batch);
|
| - }
|
| - dirty_trackers_.insert(tracker);
|
| - low_priority_dirty_trackers_.erase(tracker);
|
| -}
|
| -
|
| -void MetadataDatabase::ClearDirty(FileTracker* tracker,
|
| - leveldb::WriteBatch* batch) {
|
| - if (tracker->dirty()) {
|
| - tracker->set_dirty(false);
|
| - PutFileTrackerToBatch(*tracker, batch);
|
| - }
|
| -
|
| - dirty_trackers_.erase(tracker);
|
| - low_priority_dirty_trackers_.erase(tracker);
|
| -}
|
| -
|
| -void MetadataDatabase::MarkTrackerSetDirty(
|
| - TrackerIDSet* trackers,
|
| - leveldb::WriteBatch* batch) {
|
| - for (TrackerIDSet::iterator itr = trackers->begin();
|
| - itr != trackers->end(); ++itr) {
|
| - MarkSingleTrackerAsDirty(tracker_by_id_.get(*itr), batch);
|
| - }
|
| -}
|
| -
|
| -void MetadataDatabase::MarkTrackersDirtyByFileID(
|
| - const std::string& file_id,
|
| - leveldb::WriteBatch* batch) {
|
| - TrackerIDsByFileID::iterator found = trackers_by_file_id_.find(file_id);
|
| - if (found != trackers_by_file_id_.end())
|
| - MarkTrackerSetDirty(&found->second, batch);
|
| -}
|
| -
|
| -void MetadataDatabase::MarkTrackersDirtyByPath(int64 parent_tracker_id,
|
| - const std::string& title,
|
| - leveldb::WriteBatch* batch) {
|
| - TrackerIDsByParentAndTitle::iterator found =
|
| - trackers_by_parent_and_title_.find(parent_tracker_id);
|
| - if (found == trackers_by_parent_and_title_.end())
|
| - return;
|
| -
|
| - TrackerIDsByTitle::iterator itr = found->second.find(title);
|
| - if (itr != found->second.end())
|
| - MarkTrackerSetDirty(&itr->second, batch);
|
| -}
|
| -
|
| int64 MetadataDatabase::IncrementTrackerID(leveldb::WriteBatch* batch) {
|
| int64 tracker_id = service_metadata_->next_tracker_id();
|
| service_metadata_->set_next_tracker_id(tracker_id + 1);
|
| @@ -1644,20 +1598,6 @@ int64 MetadataDatabase::IncrementTrackerID(leveldb::WriteBatch* batch) {
|
| return tracker_id;
|
| }
|
|
|
| -void MetadataDatabase::RecursiveMarkTrackerAsDirty(int64 root_tracker_id,
|
| - leveldb::WriteBatch* batch) {
|
| - std::vector<int64> stack;
|
| - stack.push_back(root_tracker_id);
|
| - while (!stack.empty()) {
|
| - int64 tracker_id = stack.back();
|
| - stack.pop_back();
|
| - PushChildTrackersToContainer(
|
| - trackers_by_parent_and_title_, tracker_id, std::back_inserter(stack));
|
| -
|
| - MarkSingleTrackerAsDirty(tracker_by_id_.get(tracker_id), batch);
|
| - }
|
| -}
|
| -
|
| bool MetadataDatabase::CanActivateTracker(const FileTracker& tracker) {
|
| DCHECK(!tracker.active());
|
| DCHECK_NE(service_metadata_->sync_root_tracker_id(), tracker.tracker_id());
|
| @@ -1690,10 +1630,9 @@ bool MetadataDatabase::ShouldKeepDirty(const FileTracker& tracker) const {
|
| if (!tracker.has_synced_details())
|
| return true;
|
|
|
| - MetadataByID::const_iterator found = metadata_by_id_.find(tracker.file_id());
|
| - if (found == metadata_by_id_.end())
|
| + const FileMetadata* metadata = index_->GetFileMetadata(tracker.file_id());
|
| + if (!metadata)
|
| return true;
|
| - const FileMetadata* metadata = found->second;
|
| DCHECK(metadata);
|
| DCHECK(metadata->has_details());
|
|
|
| @@ -1716,45 +1655,45 @@ bool MetadataDatabase::ShouldKeepDirty(const FileTracker& tracker) const {
|
| }
|
|
|
| bool MetadataDatabase::HasDisabledAppRoot(const FileTracker& tracker) const {
|
| - TrackerIDByAppID::const_iterator found =
|
| - app_root_by_app_id_.find(tracker.app_id());
|
| - if (found == app_root_by_app_id_.end())
|
| + int64 app_root_tracker_id = index_->GetAppRootTracker(tracker.app_id());
|
| + if (app_root_tracker_id == kInvalidTrackerID)
|
| return false;
|
|
|
| - const FileTracker* app_root_tracker = tracker_by_id_.get(found->second);
|
| - DCHECK(app_root_tracker);
|
| + const FileTracker* app_root_tracker =
|
| + index_->GetFileTracker(app_root_tracker_id);
|
| + if (!app_root_tracker) {
|
| + NOTREACHED();
|
| + return false;
|
| + }
|
| return app_root_tracker->tracker_kind() == TRACKER_KIND_DISABLED_APP_ROOT;
|
| }
|
|
|
| bool MetadataDatabase::HasActiveTrackerForFileID(
|
| const std::string& file_id) const {
|
| - TrackerIDsByFileID::const_iterator found = trackers_by_file_id_.find(file_id);
|
| - return found != trackers_by_file_id_.end() && found->second.has_active();
|
| + return index_->GetFileTrackerIDsByFileID(file_id).has_active();
|
| }
|
|
|
| bool MetadataDatabase::HasActiveTrackerForPath(int64 parent_tracker_id,
|
| const std::string& title) const {
|
| - TrackerIDsByParentAndTitle::const_iterator found_by_parent =
|
| - trackers_by_parent_and_title_.find(parent_tracker_id);
|
| - if (found_by_parent == trackers_by_parent_and_title_.end())
|
| - return false;
|
| -
|
| - const TrackerIDsByTitle& trackers_by_title = found_by_parent->second;
|
| - TrackerIDsByTitle::const_iterator found = trackers_by_title.find(title);
|
| - return found != trackers_by_title.end() && found->second.has_active();
|
| + return index_->GetFileTrackerIDsByParentAndTitle(parent_tracker_id, title)
|
| + .has_active();
|
| }
|
|
|
| void MetadataDatabase::RemoveUnneededTrackersForMissingFile(
|
| const std::string& file_id,
|
| leveldb::WriteBatch* batch) {
|
| - TrackerIDSet trackers;
|
| - FindTrackersByFileID(file_id, &trackers);
|
| + TrackerIDSet trackers = index_->GetFileTrackerIDsByFileID(file_id);
|
| for (TrackerIDSet::const_iterator itr = trackers.begin();
|
| itr != trackers.end(); ++itr) {
|
| - const FileTracker& tracker = *tracker_by_id_.get(*itr);
|
| - if (!tracker.has_synced_details() ||
|
| - tracker.synced_details().missing()) {
|
| - RemoveTracker(tracker.tracker_id(), batch);
|
| + const FileTracker* tracker = index_->GetFileTracker(*itr);
|
| + if (!tracker) {
|
| + NOTREACHED();
|
| + continue;
|
| + }
|
| +
|
| + if (!tracker->has_synced_details() ||
|
| + tracker->synced_details().missing()) {
|
| + RemoveTracker(*itr, MARK_NOTHING_DIRTY, index_.get(), batch);
|
| }
|
| }
|
| }
|
| @@ -1778,11 +1717,13 @@ void MetadataDatabase::UpdateByFileMetadata(
|
| else
|
| MaybeAddTrackersForNewFile(*metadata, option, batch);
|
|
|
| - if (FindTrackersByFileID(file_id, NULL)) {
|
| - if (option != UPDATE_TRACKER_FOR_SYNCED_FILE)
|
| - MarkTrackersDirtyByFileID(file_id, batch);
|
| + TrackerIDSet trackers = index_->GetFileTrackerIDsByFileID(file_id);
|
| + if (!trackers.empty()) {
|
| PutFileMetadataToBatch(*metadata, batch);
|
| - StoreFileMetadata(metadata.Pass());
|
| + index_->StoreFileMetadata(metadata.Pass());
|
| +
|
| + if (option != UPDATE_TRACKER_FOR_SYNCED_FILE)
|
| + MarkTrackerSetDirty(trackers, index_.get(), batch);
|
| }
|
| }
|
|
|
| @@ -1812,17 +1753,18 @@ scoped_ptr<base::ListValue> MetadataDatabase::DumpFiles(
|
| return files.Pass();
|
|
|
| std::vector<int64> stack;
|
| - PushChildTrackersToContainer(
|
| - trackers_by_parent_and_title_,
|
| - app_root_tracker.tracker_id(),
|
| - std::back_inserter(stack));
|
| + AppendContents(
|
| + index_->GetFileTrackerIDsByParent(app_root_tracker.tracker_id()), &stack);
|
| while (!stack.empty()) {
|
| int64 tracker_id = stack.back();
|
| stack.pop_back();
|
| - PushChildTrackersToContainer(
|
| - trackers_by_parent_and_title_, tracker_id, std::back_inserter(stack));
|
| + AppendContents(index_->GetFileTrackerIDsByParent(tracker_id), &stack);
|
|
|
| - const FileTracker* tracker = tracker_by_id_.get(tracker_id);
|
| + const FileTracker* tracker = index_->GetFileTracker(tracker_id);
|
| + if (!tracker) {
|
| + NOTREACHED();
|
| + continue;
|
| + }
|
| base::DictionaryValue* file = new base::DictionaryValue;
|
|
|
| base::FilePath path = BuildDisplayPathForTracker(*tracker);
|
| @@ -1858,11 +1800,11 @@ scoped_ptr<base::ListValue> MetadataDatabase::DumpDatabase() {
|
|
|
| bool MetadataDatabase::HasNewerFileMetadata(const std::string& file_id,
|
| int64 change_id) {
|
| - MetadataByID::const_iterator found = metadata_by_id_.find(file_id);
|
| - if (found == metadata_by_id_.end())
|
| + const FileMetadata* metadata = index_->GetFileMetadata(file_id);
|
| + if (!metadata)
|
| return false;
|
| - DCHECK(found->second->has_details());
|
| - return found->second->details().change_id() >= change_id;
|
| + DCHECK(metadata->has_details());
|
| + return metadata->details().change_id() >= change_id;
|
| }
|
|
|
| scoped_ptr<base::ListValue> MetadataDatabase::DumpTrackers() {
|
| @@ -1884,8 +1826,9 @@ scoped_ptr<base::ListValue> MetadataDatabase::DumpTrackers() {
|
| trackers->Append(metadata);
|
|
|
| // Append tracker data.
|
| - for (TrackerByID::const_iterator itr = tracker_by_id_.begin();
|
| - itr != tracker_by_id_.end(); ++itr) {
|
| + for (MetadataDatabaseIndex::TrackerByID::const_iterator itr =
|
| + index_->tracker_by_id_.begin();
|
| + itr != index_->tracker_by_id_.end(); ++itr) {
|
| const FileTracker& tracker = *itr->second;
|
| base::DictionaryValue* dict = new base::DictionaryValue;
|
| base::FilePath path = BuildDisplayPathForTracker(tracker);
|
| @@ -1936,8 +1879,9 @@ scoped_ptr<base::ListValue> MetadataDatabase::DumpMetadata() {
|
| files->Append(metadata);
|
|
|
| // Append metadata data.
|
| - for (MetadataByID::const_iterator itr = metadata_by_id_.begin();
|
| - itr != metadata_by_id_.end(); ++itr) {
|
| + for (MetadataDatabaseIndex::MetadataByID::const_iterator itr =
|
| + index_->metadata_by_id_.begin();
|
| + itr != index_->metadata_by_id_.end(); ++itr) {
|
| const FileMetadata& file = *itr->second;
|
|
|
| base::DictionaryValue* dict = new base::DictionaryValue;
|
| @@ -1961,22 +1905,6 @@ scoped_ptr<base::ListValue> MetadataDatabase::DumpMetadata() {
|
| return files.Pass();
|
| }
|
|
|
| -void MetadataDatabase::StoreFileMetadata(
|
| - scoped_ptr<FileMetadata> file_metadata) {
|
| - DCHECK(file_metadata);
|
| -
|
| - std::string file_id = file_metadata->file_id();
|
| - metadata_by_id_.set(file_id, file_metadata.Pass());
|
| -}
|
| -
|
| -void MetadataDatabase::StoreFileTracker(scoped_ptr<FileTracker> file_tracker) {
|
| - DCHECK(file_tracker);
|
| -
|
| - int64 tracker_id = file_tracker->tracker_id();
|
| - DCHECK(!ContainsKey(tracker_by_id_, tracker_id));
|
| - tracker_by_id_.set(tracker_id, file_tracker.Pass());
|
| -}
|
| -
|
| void MetadataDatabase::AttachSyncRoot(
|
| const google_apis::FileResource& sync_root_folder,
|
| leveldb::WriteBatch* batch) {
|
| @@ -1992,10 +1920,8 @@ void MetadataDatabase::AttachSyncRoot(
|
| service_metadata_->set_sync_root_tracker_id(sync_root_tracker->tracker_id());
|
| PutServiceMetadataToBatch(*service_metadata_, batch);
|
|
|
| - InsertFileTrackerToIndex(sync_root_tracker.get());
|
| -
|
| - StoreFileMetadata(sync_root_metadata.Pass());
|
| - StoreFileTracker(sync_root_tracker.Pass());
|
| + index_->StoreFileMetadata(sync_root_metadata.Pass());
|
| + index_->StoreFileTracker(sync_root_tracker.Pass());
|
| }
|
|
|
| void MetadataDatabase::AttachInitialAppRoot(
|
| @@ -2012,57 +1938,8 @@ void MetadataDatabase::AttachInitialAppRoot(
|
| PutFileMetadataToBatch(*app_root_metadata, batch);
|
| PutFileTrackerToBatch(*app_root_tracker, batch);
|
|
|
| - InsertFileTrackerToIndex(app_root_tracker.get());
|
| -
|
| - StoreFileMetadata(app_root_metadata.Pass());
|
| - StoreFileTracker(app_root_tracker.Pass());
|
| -}
|
| -
|
| -void MetadataDatabase::InsertFileTrackerToIndex(FileTracker* tracker) {
|
| - trackers_by_file_id_[tracker->file_id()].Insert(*tracker);
|
| - if (IsAppRoot(*tracker)) {
|
| - DCHECK(!ContainsKey(app_root_by_app_id_, tracker->app_id()));
|
| - app_root_by_app_id_[tracker->app_id()] = tracker->tracker_id();
|
| - }
|
| -
|
| - int64 parent_tracker_id = tracker->parent_tracker_id();
|
| - if (parent_tracker_id) {
|
| - std::string title = GetTrackerTitle(*tracker);
|
| - trackers_by_parent_and_title_[parent_tracker_id][title].Insert(*tracker);
|
| - }
|
| -
|
| - if (tracker->dirty()) {
|
| - dirty_trackers_.insert(tracker);
|
| - low_priority_dirty_trackers_.erase(tracker);
|
| - }
|
| -}
|
| -
|
| -void MetadataDatabase::ForceActivateTrackerByPath(int64 parent_tracker_id,
|
| - const std::string& title,
|
| - const std::string& file_id,
|
| - leveldb::WriteBatch* batch) {
|
| - DCHECK(ContainsKey(trackers_by_parent_and_title_, parent_tracker_id));
|
| - DCHECK(ContainsKey(trackers_by_parent_and_title_[parent_tracker_id], title));
|
| - DCHECK(!trackers_by_file_id_[file_id].has_active());
|
| -
|
| - TrackerIDSet* same_path_trackers =
|
| - &trackers_by_parent_and_title_[parent_tracker_id][title];
|
| -
|
| - for (TrackerIDSet::iterator itr = same_path_trackers->begin();
|
| - itr != same_path_trackers->end(); ++itr) {
|
| - FileTracker* tracker = tracker_by_id_.get(*itr);
|
| - if (tracker->file_id() != file_id)
|
| - continue;
|
| -
|
| - if (same_path_trackers->has_active()) {
|
| - MakeTrackerInactive(same_path_trackers->active_tracker(), batch);
|
| - }
|
| - MakeTrackerActive(tracker->tracker_id(), batch);
|
| - ClearDirty(tracker, batch);
|
| - return;
|
| - }
|
| -
|
| - NOTREACHED();
|
| + index_->StoreFileMetadata(app_root_metadata.Pass());
|
| + index_->StoreFileTracker(app_root_tracker.Pass());
|
| }
|
|
|
| } // namespace drive_backend
|
|
|