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

Unified Diff: chrome/browser/sync_file_system/drive_backend/metadata_database.cc

Issue 23288007: [SyncFS] Add MetadataDatabase::UpdateTracker (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: comment fix Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 98df266c11fd8f5129d1653f23c9f7484d337260..b37d578de922457587fa4a199e2acebbcd610475 100644
--- a/chrome/browser/sync_file_system/drive_backend/metadata_database.cc
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_database.cc
@@ -710,7 +710,7 @@ void MetadataDatabase::PopulateFolder(const std::string& folder_id,
itr != child_file_ids.end(); ++itr)
CreateTrackerForParentAndFileID(*folder_tracker, *itr, batch.get());
folder_tracker->set_needs_folder_listing(false);
- if (!ShouldKeepDirty(*folder_tracker)) {
+ if (folder_tracker->dirty() && !ShouldKeepDirty(*folder_tracker)) {
folder_tracker->set_dirty(false);
dirty_trackers_.erase(folder_tracker);
}
@@ -719,6 +719,63 @@ void MetadataDatabase::PopulateFolder(const std::string& folder_id,
WriteToDatabase(batch.Pass(), callback);
}
+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()) {
+ 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);
+
+ // Local file is deleted.
kinuko 2013/08/27 07:47:05 nit: the term 'local' is confusing here. Do you as
tzik 2013/08/30 05:51:57 Yes, the updated_details should contain latest loc
+ if (updated_details.deleted()) {
+ FileByID::iterator found = file_by_id_.find(tracker->file_id());
+ if (found == file_by_id_.end() || found->second->details().deleted()) {
+ // Both the tracker and metadata have the deleted flag, now it's safe to
+ // delete the |tracker|.
+ RemoveTracker(tracker->tracker_id(), batch.get());
+ } else {
+ // The local file is deleted, but corresponding remote file isn't.
+ // Put the tracker back to the initial state.
+ tracker->clear_synced_details();
+ tracker->set_dirty(true);
+ tracker->set_active(false);
+ PutTrackerToBatch(*tracker, batch.get());
+ }
+
+ WriteToDatabase(batch.Pass(), callback);
+ return;
+ }
+
+ // Check if the tracker was retitled. If it was, update the title and its
+ // index in advance.
+ if (!tracker->has_synced_details() ||
+ tracker->synced_details().title() != updated_details.title()) {
+ UpdateTrackerTitle(tracker, updated_details.title(), batch.get());
+ }
+
+ *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)) {
+ tracker->set_dirty(false);
+ dirty_trackers_.erase(tracker);
+ }
+ PutTrackerToBatch(*tracker, batch.get());
+
+ WriteToDatabase(batch.Pass(), callback);
+}
+
MetadataDatabase::MetadataDatabase(base::SequencedTaskRunner* task_runner)
: task_runner_(task_runner), weak_ptr_factory_(this) {
DCHECK(task_runner);
@@ -960,9 +1017,21 @@ void MetadataDatabase::CreateTrackerForParentAndFileID(
tracker_by_id_[tracker_id] = tracker.release();
}
+void MetadataDatabase::RemoveTracker(int64 tracker_id,
+ leveldb::WriteBatch* batch) {
+ RemoveTrackerInternal(tracker_id, batch, false);
+}
+
void MetadataDatabase::RemoveTrackerIgnoringSiblings(
int64 tracker_id,
leveldb::WriteBatch* batch) {
+ RemoveTrackerInternal(tracker_id, batch, true);
+}
+
+void MetadataDatabase::RemoveTrackerInternal(
+ int64 tracker_id,
+ leveldb::WriteBatch* batch,
+ bool ignore_name_conflicted_trackers) {
kinuko 2013/08/27 13:20:19 nit: I'd name this bool parameter similar to the m
tzik 2013/08/30 05:51:57 Done.
scoped_ptr<FileTracker> tracker(
FindAndEraseItem(&tracker_by_id_, tracker_id));
if (!tracker)
@@ -974,8 +1043,11 @@ void MetadataDatabase::RemoveTrackerIgnoringSiblings(
EraseTrackerFromPathIndex(tracker.get());
MarkTrackersDirtyByFileID(tracker->file_id(), batch);
- // Do not mark the same path trackers as dirty, since the caller is deleting
- // all its siblings.
+ if (!ignore_name_conflicted_trackers) {
+ MarkTrackersDirtyByPath(tracker->parent_tracker_id(),
+ GetTrackerTitle(*tracker),
+ batch);
+ }
PutTrackerDeletionToBatch(tracker_id, batch);
}
@@ -1138,7 +1210,27 @@ void MetadataDatabase::RecursiveMarkTrackerAsDirty(int64 root_tracker_id,
}
}
+bool MetadataDatabase::CanActivateTracker(const FileTracker& tracker) {
+ DCHECK(!tracker.active());
+ DCHECK_NE(service_metadata_->sync_root_tracker_id(), tracker.tracker_id());
+
+ if (HasActiveTrackerForFileID(tracker.file_id()))
+ return false;
+
+ if (tracker.app_id().empty())
+ return false;
+ if (!tracker.has_synced_details())
+ return false;
+ DCHECK(tracker.parent_tracker_id());
+
+ return !HasActiveTrackerForPath(tracker.parent_tracker_id(),
+ tracker.synced_details().title());
+}
+
bool MetadataDatabase::ShouldKeepDirty(const FileTracker& tracker) const {
+ if (HasDisabledAppRoot(tracker))
+ return false;
+
DCHECK(tracker.dirty());
if (!tracker.has_synced_details())
return true;
@@ -1146,17 +1238,18 @@ bool MetadataDatabase::ShouldKeepDirty(const FileTracker& tracker) const {
FileByID::const_iterator found = file_by_id_.find(tracker.file_id());
if (found == file_by_id_.end())
return true;
- const FileMetadata& file = *found->second;
+ const FileMetadata* file = found->second;
+ DCHECK(file);
if (tracker.active()) {
if (tracker.needs_folder_listing())
return true;
- if (tracker.synced_details().md5() != file.details().md5())
+ if (tracker.synced_details().md5() != file->details().md5())
return true;
}
const FileDetails& local_details = tracker.synced_details();
- const FileDetails& remote_details = file.details();
+ const FileDetails& remote_details = file->details();
if (local_details.title() != remote_details.title())
return true;
@@ -1166,6 +1259,75 @@ bool MetadataDatabase::ShouldKeepDirty(const FileTracker& tracker) const {
return false;
}
+bool MetadataDatabase::HasDisabledAppRoot(const FileTracker& tracker) const {
+ TrackerByAppID::const_iterator found =
+ app_root_by_app_id_.find(tracker.app_id());
+ if (found == app_root_by_app_id_.end())
+ return false;
kinuko 2013/08/27 13:20:19 What does this case mean..?
tzik 2013/08/30 05:51:57 This means the trackers is out of any app-root tre
+
+ const FileTracker* app_root_tracker = found->second;
+ DCHECK(app_root_tracker);
+ return app_root_tracker->tracker_kind() == TRACKER_KIND_DISABLED_APP_ROOT;
+}
+
+bool MetadataDatabase::HasActiveTrackerForFileID(
+ const std::string& file_id) const {
+ TrackersByFileID::const_iterator found = trackers_by_file_id_.find(file_id);
+ return found != trackers_by_file_id_.end() && found->second.has_active();
+}
+
+bool MetadataDatabase::HasActiveTrackerForPath(int64 parent_tracker_id,
+ const std::string& title) const {
+ TrackersByParentAndTitle::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 TrackersByTitle& trackers_by_title = found_by_parent->second;
+ TrackersByTitle::const_iterator found = trackers_by_title.find(title);
+ return found != trackers_by_title.end() && found->second.has_active();
+}
+
+void MetadataDatabase::UpdateTrackerTitle(FileTracker* tracker,
+ const std::string& new_title,
+ leveldb::WriteBatch* batch) {
+ int64 parent_id = tracker->parent_tracker_id();
+ std::string old_title = GetTrackerTitle(*tracker);
+ DCHECK_NE(old_title, new_title);
+ DCHECK(!new_title.empty());
kinuko 2013/08/27 13:20:19 We don't check this in UpdateTracker. Is new_titl
tzik 2013/08/30 05:51:57 New title should not be empty unless the file is d
kinuko 2013/08/30 06:03:46 Ok, I assume title cannot be assigned to an empty
+
+ TrackersByTitle* trackers_by_title =
+ &trackers_by_parent_and_title_[parent_id];
+ TrackerSet* old_siblings = &(*trackers_by_title)[old_title];
+ TrackerSet* new_siblings = &(*trackers_by_title)[new_title];
+
+ old_siblings->Erase(tracker);
+ if (old_siblings->empty())
+ trackers_by_title->erase(old_title);
+ else
+ MarkTrackerSetDirty(old_siblings, batch);
+
+ if (tracker->active() && new_siblings->has_active()) {
+ // Inactivate existing active tracker.
kinuko 2013/08/27 13:20:19 Why does the new one always win here?
tzik 2013/08/30 05:51:57 The file is already updated locally here by the sy
+ FileTracker* obstacle = new_siblings->active_tracker();
+ new_siblings->Inactivate(obstacle);
kinuko 2013/08/27 13:20:19 Do we need to check if the obstacle is KIND_REGULA
tzik 2013/08/30 05:51:57 Done.
+
+ TrackerSet* chain = &trackers_by_file_id_[obstacle->file_id()];
kinuko 2013/08/27 13:20:19 chain... ?
tzik 2013/08/30 05:51:57 Done.
+ chain->Inactivate(obstacle);
+ MarkTrackerSetDirty(chain, batch);
+
+ obstacle->set_active(false);
+ PutTrackerToBatch(*obstacle, batch);
+
+ RemoveAllDescendantTrackers(obstacle->tracker_id(), batch);
+ new_siblings->Insert(tracker);
kinuko 2013/08/27 13:20:19 duplicated with line 1327?
tzik 2013/08/30 05:51:57 Done.
+ }
+
+ tracker->mutable_synced_details()->set_title(new_title);
+ new_siblings->Insert(tracker);
+ PutTrackerToBatch(*tracker, batch);
+}
+
void MetadataDatabase::WriteToDatabase(scoped_ptr<leveldb::WriteBatch> batch,
const SyncStatusCallback& callback) {
base::PostTaskAndReplyWithResult(

Powered by Google App Engine
This is Rietveld 408576698