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

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

Issue 423433006: [SyncFS] Implement RemoveUnreachableItems for MetadataDatabaseIndexOnDisk (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 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_index_on_disk.cc
diff --git a/chrome/browser/sync_file_system/drive_backend/metadata_database_index_on_disk.cc b/chrome/browser/sync_file_system/drive_backend/metadata_database_index_on_disk.cc
index f4c32af6d75b525a36fbfe849e6c0eb7e91245d6..096338ad3719a6aacaa9cfb17f6abc6cd3d2c2df 100644
--- a/chrome/browser/sync_file_system/drive_backend/metadata_database_index_on_disk.cc
+++ b/chrome/browser/sync_file_system/drive_backend/metadata_database_index_on_disk.cc
@@ -140,6 +140,110 @@ std::string GenerateDemotedDirtyIDKey(int64 tracker_id) {
return kDemotedDirtyIDKeyPrefix + base::Int64ToString(tracker_id);
}
+void RemoveUnreachableItems(LevelDBWrapper* db) {
+ DCHECK(db);
+
+ typedef std::map<int64, std::set<int64> > ChildTrackersByParent;
+ ChildTrackersByParent trackers_by_parent;
+ {
+ // Set up links from parent tracker to child trackers.
+ std::set<int64> inactive_trackers;
+ scoped_ptr<LevelDBWrapper::Iterator> itr = db->NewIterator();
+ for (itr->Seek(kFileTrackerKeyPrefix); itr->Valid(); itr->Next()) {
+ if (!RemovePrefix(itr->key().ToString(), kFileTrackerKeyPrefix, NULL))
+ break;
+
+ scoped_ptr<FileTracker> tracker(new FileTracker);
+ if (!tracker->ParseFromString(itr->value().ToString())) {
+ util::Log(logging::LOG_WARNING, FROM_HERE,
+ "Failed to parse a Tracker");
+ continue;
+ }
+
+ int64 parent_tracker_id = tracker->parent_tracker_id();
+ int64 tracker_id = tracker->tracker_id();
+ trackers_by_parent[parent_tracker_id].insert(tracker_id);
+ if (!tracker->active())
+ inactive_trackers.insert(tracker_id);
+ }
+
+ // Drop links from inactive trackers.
+ for (std::set<int64>::iterator iter = inactive_trackers.begin();
+ iter != inactive_trackers.end(); ++iter) {
+ trackers_by_parent.erase(*iter);
+ }
+ }
+
+ // Traverse tracker tree from sync-root.
+ std::set<int64> visited_trackers;
+ {
+ scoped_ptr<ServiceMetadata> service_metadata =
+ InitializeServiceMetadata(db);
+ int64 sync_root_tracker_id = service_metadata->sync_root_tracker_id();
+ std::vector<int64> pending;
+ if (sync_root_tracker_id != kInvalidTrackerID)
+ pending.push_back(sync_root_tracker_id);
+
+ while (!pending.empty()) {
+ int64 tracker_id = pending.back();
+ DCHECK_NE(kInvalidTrackerID, tracker_id);
+ pending.pop_back();
+
+ if (!visited_trackers.insert(tracker_id).second) {
+ NOTREACHED();
+ continue;
+ }
+
+ AppendContents(
+ LookUpMap(trackers_by_parent, tracker_id, std::set<int64>()),
+ &pending);
+ }
+ }
+
+ // Delete all unreachable trackers, and list all |file_id| referred by
+ // remained trackers.
+ base::hash_set<std::string> referred_file_ids;
+ {
+ scoped_ptr<LevelDBWrapper::Iterator> itr = db->NewIterator();
+ for (itr->Seek(kFileTrackerKeyPrefix); itr->Valid(); itr->Next()) {
+ if (!RemovePrefix(itr->key().ToString(), kFileTrackerKeyPrefix, NULL))
+ break;
+
+ scoped_ptr<FileTracker> tracker(new FileTracker);
+ if (!tracker->ParseFromString(itr->value().ToString())) {
+ util::Log(logging::LOG_WARNING, FROM_HERE,
+ "Failed to parse a Tracker");
+ continue;
+ }
+
+ if (ContainsKey(visited_trackers, tracker->tracker_id())) {
+ referred_file_ids.insert(tracker->file_id());
+ } else {
+ PutFileTrackerDeletionToDB(tracker->tracker_id(), db);
+ }
+ }
+ }
+
+ // Delete all unreferred metadata.
+ {
+ scoped_ptr<LevelDBWrapper::Iterator> itr = db->NewIterator();
+ for (itr->Seek(kFileMetadataKeyPrefix); itr->Valid(); itr->Next()) {
+ if (!RemovePrefix(itr->key().ToString(), kFileMetadataKeyPrefix, NULL))
+ break;
+
+ scoped_ptr<FileMetadata> metadata(new FileMetadata);
+ if (!metadata->ParseFromString(itr->value().ToString())) {
+ util::Log(logging::LOG_WARNING, FROM_HERE,
+ "Failed to parse a Tracker");
+ continue;
+ }
+
+ if (!ContainsKey(referred_file_ids, metadata->file_id()))
+ PutFileMetadataDeletionToDB(metadata->file_id(), db);
+ }
+ }
+}
+
} // namespace
// static
@@ -148,6 +252,9 @@ MetadataDatabaseIndexOnDisk::Create(LevelDBWrapper* db) {
DCHECK(db);
PutVersionToDB(kDatabaseOnDiskVersion, db);
+ // TODO(peria): It is not good to call RemoveUnreachableItems on every
+ // creation.
+ RemoveUnreachableItems(db);
scoped_ptr<MetadataDatabaseIndexOnDisk>
index(new MetadataDatabaseIndexOnDisk(db));
nhiroki 2014/08/05 07:19:16 When is |db| committed?
peria 2014/08/05 07:35:59 It is handled by MetadataDatabase class. This clas
nhiroki 2014/08/05 09:21:50 I see, thanks!
return index.Pass();
@@ -573,6 +680,10 @@ void MetadataDatabaseIndexOnDisk::BuildTrackerIndexes() {
}
}
+LevelDBWrapper* MetadataDatabaseIndexOnDisk::GetDBForTesting() {
+ return db_;
+}
+
MetadataDatabaseIndexOnDisk::MetadataDatabaseIndexOnDisk(LevelDBWrapper* db)
: db_(db) {
// TODO(peria): Add UMA to measure the number of FileMetadata, FileTracker,

Powered by Google App Engine
This is Rietveld 408576698