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

Side by Side 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: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h" 5 #include "chrome/browser/sync_file_system/drive_backend/metadata_database.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <stack> 8 #include <stack>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 663 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 674
675 FileMetadata* file_ptr = file.release(); 675 FileMetadata* file_ptr = file.release();
676 std::swap(file_ptr, file_by_id_[file_id]); 676 std::swap(file_ptr, file_by_id_[file_id]);
677 delete file_ptr; 677 delete file_ptr;
678 } 678 }
679 } 679 }
680 680
681 WriteToDatabase(batch.Pass(), callback); 681 WriteToDatabase(batch.Pass(), callback);
682 } 682 }
683 683
684 void MetadataDatabase::PopulateFolder(const std::string& folder_id, 684 void MetadataDatabase::PopulateFolderByChildList(
685 const FileIDList& child_file_ids, 685 const std::string& folder_id,
686 const SyncStatusCallback& callback) { 686 const FileIDList& child_file_ids,
687 const SyncStatusCallback& callback) {
687 TrackerSet trackers; 688 TrackerSet trackers;
688 if (!FindTrackersByFileID(folder_id, &trackers) || 689 if (!FindTrackersByFileID(folder_id, &trackers) ||
689 !trackers.has_active()) { 690 !trackers.has_active()) {
690 // It's OK that there is no folder to populate its children. 691 // It's OK that there is no folder to populate its children.
691 // Inactive folders should ignore their contents updates. 692 // Inactive folders should ignore their contents updates.
692 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK)); 693 RunSoon(FROM_HERE, base::Bind(callback, SYNC_STATUS_OK));
693 return; 694 return;
694 } 695 }
695 696
696 FileTracker* folder_tracker = 697 FileTracker* folder_tracker =
697 tracker_by_id_[trackers.active_tracker()->tracker_id()]; 698 tracker_by_id_[trackers.active_tracker()->tracker_id()];
698 DCHECK(folder_tracker); 699 DCHECK(folder_tracker);
699 std::set<std::string> children(child_file_ids.begin(), child_file_ids.end()); 700 std::set<std::string> children(child_file_ids.begin(), child_file_ids.end());
700 701
701 std::vector<int64> known_children; 702 std::vector<int64> known_children;
702 PushChildTrackersToContainer(trackers_by_parent_and_title_, 703 PushChildTrackersToContainer(trackers_by_parent_and_title_,
703 folder_tracker->tracker_id(), 704 folder_tracker->tracker_id(),
704 std::back_inserter(known_children)); 705 std::back_inserter(known_children));
705 for (std::vector<int64>::iterator itr = known_children.begin(); 706 for (std::vector<int64>::iterator itr = known_children.begin();
706 itr != known_children.end(); ++itr) 707 itr != known_children.end(); ++itr)
707 children.erase(tracker_by_id_[*itr]->file_id()); 708 children.erase(tracker_by_id_[*itr]->file_id());
708 709
709 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch); 710 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
710 for (FileIDList::const_iterator itr = child_file_ids.begin(); 711 for (FileIDList::const_iterator itr = child_file_ids.begin();
711 itr != child_file_ids.end(); ++itr) 712 itr != child_file_ids.end(); ++itr)
712 CreateTrackerForParentAndFileID(*folder_tracker, *itr, batch.get()); 713 CreateTrackerForParentAndFileID(*folder_tracker, *itr, batch.get());
713 folder_tracker->set_needs_folder_listing(false); 714 folder_tracker->set_needs_folder_listing(false);
714 if (!ShouldKeepDirty(*folder_tracker)) { 715 if (folder_tracker->dirty() && !ShouldKeepDirty(*folder_tracker)) {
715 folder_tracker->set_dirty(false); 716 folder_tracker->set_dirty(false);
716 dirty_trackers_.erase(folder_tracker); 717 dirty_trackers_.erase(folder_tracker);
717 } 718 }
718 PutTrackerToBatch(*folder_tracker, batch.get()); 719 PutTrackerToBatch(*folder_tracker, batch.get());
719 720
720 WriteToDatabase(batch.Pass(), callback); 721 WriteToDatabase(batch.Pass(), callback);
721 } 722 }
722 723
724 void MetadataDatabase::UpdateTracker(int64 tracker_id,
725 const FileDetails& updated_details,
726 const SyncStatusCallback& callback) {
727 TrackerByID::iterator found = tracker_by_id_.find(tracker_id);
728 if (found == tracker_by_id_.end()) {
729 RunSoon(FROM_HERE, base::Bind(callback, SYNC_DATABASE_ERROR_NOT_FOUND));
730 return;
731 }
732
733 FileTracker* tracker = found->second;
734 DCHECK(tracker);
735
736 scoped_ptr<leveldb::WriteBatch> batch(new leveldb::WriteBatch);
737
738 if (updated_details.deleted()) {
739 // The update deletes the local file.
740 FileByID::iterator found = file_by_id_.find(tracker->file_id());
741 if (found == file_by_id_.end() || found->second->details().deleted()) {
742 // Both the tracker and metadata have the deleted flag, now it's safe to
743 // delete the |tracker|.
744 RemoveTracker(tracker->tracker_id(), batch.get());
745 } else {
746 // The local file is deleted, but corresponding remote file isn't.
747 // Put the tracker back to the initial state.
748 tracker->clear_synced_details();
749 tracker->set_dirty(true);
750 tracker->set_active(false);
751 PutTrackerToBatch(*tracker, batch.get());
752 }
753
754 WriteToDatabase(batch.Pass(), callback);
755 return;
756 }
757
758 // Check if the tracker was retitled. If it was, update the title and its
759 // index in advance.
760 if (!tracker->has_synced_details() ||
761 tracker->synced_details().title() != updated_details.title()) {
762 UpdateTrackerTitle(tracker, updated_details.title(), batch.get());
763 }
764
765 *tracker->mutable_synced_details() = updated_details;
766
767 // Activate the tracker if:
768 // - There is no active tracker that tracks |tracker->file_id()|.
769 // - There is no active tracker that has the same |parent| and |title|.
770 if (!tracker->active() && CanActivateTracker(*tracker))
771 MakeTrackerActive(tracker->tracker_id(), batch.get());
772 if (tracker->dirty() && !ShouldKeepDirty(*tracker)) {
773 tracker->set_dirty(false);
774 dirty_trackers_.erase(tracker);
775 }
776 PutTrackerToBatch(*tracker, batch.get());
777
778 WriteToDatabase(batch.Pass(), callback);
779 }
780
723 MetadataDatabase::MetadataDatabase(base::SequencedTaskRunner* task_runner) 781 MetadataDatabase::MetadataDatabase(base::SequencedTaskRunner* task_runner)
724 : task_runner_(task_runner), weak_ptr_factory_(this) { 782 : task_runner_(task_runner), weak_ptr_factory_(this) {
725 DCHECK(task_runner); 783 DCHECK(task_runner);
726 } 784 }
727 785
728 // static 786 // static
729 void MetadataDatabase::CreateOnTaskRunner( 787 void MetadataDatabase::CreateOnTaskRunner(
730 base::SingleThreadTaskRunner* callback_runner, 788 base::SingleThreadTaskRunner* callback_runner,
731 base::SequencedTaskRunner* task_runner, 789 base::SequencedTaskRunner* task_runner,
732 const base::FilePath& database_path, 790 const base::FilePath& database_path,
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
954 // FileMetadata::details but from FileTracker::synced_details, which is filled 1012 // FileMetadata::details but from FileTracker::synced_details, which is filled
955 // on tracker updated phase. Use empty string as the title since 1013 // on tracker updated phase. Use empty string as the title since
956 // FileTracker::synced_details is empty here. 1014 // FileTracker::synced_details is empty here.
957 trackers_by_parent_and_title_[parent_tracker.tracker_id()][std::string()] 1015 trackers_by_parent_and_title_[parent_tracker.tracker_id()][std::string()]
958 .Insert(tracker.get()); 1016 .Insert(tracker.get());
959 dirty_trackers_.insert(tracker.get()); 1017 dirty_trackers_.insert(tracker.get());
960 DCHECK(!ContainsKey(tracker_by_id_, tracker_id)); 1018 DCHECK(!ContainsKey(tracker_by_id_, tracker_id));
961 tracker_by_id_[tracker_id] = tracker.release(); 1019 tracker_by_id_[tracker_id] = tracker.release();
962 } 1020 }
963 1021
1022 void MetadataDatabase::RemoveTracker(int64 tracker_id,
1023 leveldb::WriteBatch* batch) {
1024 RemoveTrackerInternal(tracker_id, batch, false);
1025 }
1026
964 void MetadataDatabase::RemoveTrackerIgnoringSiblings( 1027 void MetadataDatabase::RemoveTrackerIgnoringSiblings(
965 int64 tracker_id, 1028 int64 tracker_id,
966 leveldb::WriteBatch* batch) { 1029 leveldb::WriteBatch* batch) {
1030 RemoveTrackerInternal(tracker_id, batch, true);
1031 }
1032
1033 void MetadataDatabase::RemoveTrackerInternal(
1034 int64 tracker_id,
1035 leveldb::WriteBatch* batch,
1036 bool ignoring_siblings) {
967 scoped_ptr<FileTracker> tracker( 1037 scoped_ptr<FileTracker> tracker(
968 FindAndEraseItem(&tracker_by_id_, tracker_id)); 1038 FindAndEraseItem(&tracker_by_id_, tracker_id));
969 if (!tracker) 1039 if (!tracker)
970 return; 1040 return;
971 1041
972 EraseTrackerFromFileIDIndex(tracker.get(), batch); 1042 EraseTrackerFromFileIDIndex(tracker.get(), batch);
973 if (IsAppRoot(*tracker)) 1043 if (IsAppRoot(*tracker))
974 app_root_by_app_id_.erase(tracker->app_id()); 1044 app_root_by_app_id_.erase(tracker->app_id());
975 EraseTrackerFromPathIndex(tracker.get()); 1045 EraseTrackerFromPathIndex(tracker.get());
976 1046
977 MarkTrackersDirtyByFileID(tracker->file_id(), batch); 1047 MarkTrackersDirtyByFileID(tracker->file_id(), batch);
978 // Do not mark the same path trackers as dirty, since the caller is deleting 1048 if (!ignoring_siblings) {
979 // all its siblings. 1049 MarkTrackersDirtyByPath(tracker->parent_tracker_id(),
1050 GetTrackerTitle(*tracker),
1051 batch);
1052 }
980 PutTrackerDeletionToBatch(tracker_id, batch); 1053 PutTrackerDeletionToBatch(tracker_id, batch);
981 } 1054 }
982 1055
983 void MetadataDatabase::MaybeAddTrackersForNewFile( 1056 void MetadataDatabase::MaybeAddTrackersForNewFile(
984 const FileMetadata& file, 1057 const FileMetadata& file,
985 leveldb::WriteBatch* batch) { 1058 leveldb::WriteBatch* batch) {
986 std::set<int64> known_parents; 1059 std::set<int64> known_parents;
987 TrackersByFileID::iterator found = trackers_by_file_id_.find(file.file_id()); 1060 TrackersByFileID::iterator found = trackers_by_file_id_.find(file.file_id());
988 if (found != trackers_by_file_id_.end()) { 1061 if (found != trackers_by_file_id_.end()) {
989 for (TrackerSet::const_iterator itr = found->second.begin(); 1062 for (TrackerSet::const_iterator itr = found->second.begin();
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
1132 1205
1133 FileTracker* tracker = tracker_by_id_[tracker_id]; 1206 FileTracker* tracker = tracker_by_id_[tracker_id];
1134 if (!tracker->dirty()) { 1207 if (!tracker->dirty()) {
1135 tracker->set_dirty(true); 1208 tracker->set_dirty(true);
1136 PutTrackerToBatch(*tracker, batch); 1209 PutTrackerToBatch(*tracker, batch);
1137 dirty_trackers_.insert(tracker); 1210 dirty_trackers_.insert(tracker);
1138 } 1211 }
1139 } 1212 }
1140 } 1213 }
1141 1214
1215 bool MetadataDatabase::CanActivateTracker(const FileTracker& tracker) {
1216 DCHECK(!tracker.active());
1217 DCHECK_NE(service_metadata_->sync_root_tracker_id(), tracker.tracker_id());
1218
1219 if (HasActiveTrackerForFileID(tracker.file_id()))
1220 return false;
1221
1222 if (tracker.app_id().empty())
1223 return false;
1224 if (!tracker.has_synced_details())
1225 return false;
1226 DCHECK(tracker.parent_tracker_id());
1227
1228 return !HasActiveTrackerForPath(tracker.parent_tracker_id(),
1229 tracker.synced_details().title());
1230 }
1231
1142 bool MetadataDatabase::ShouldKeepDirty(const FileTracker& tracker) const { 1232 bool MetadataDatabase::ShouldKeepDirty(const FileTracker& tracker) const {
1233 if (HasDisabledAppRoot(tracker))
1234 return false;
1235
1143 DCHECK(tracker.dirty()); 1236 DCHECK(tracker.dirty());
1144 if (!tracker.has_synced_details()) 1237 if (!tracker.has_synced_details())
1145 return true; 1238 return true;
1146 1239
1147 FileByID::const_iterator found = file_by_id_.find(tracker.file_id()); 1240 FileByID::const_iterator found = file_by_id_.find(tracker.file_id());
1148 if (found == file_by_id_.end()) 1241 if (found == file_by_id_.end())
1149 return true; 1242 return true;
1150 const FileMetadata& file = *found->second; 1243 const FileMetadata* file = found->second;
1244 DCHECK(file);
1151 1245
1152 if (tracker.active()) { 1246 if (tracker.active()) {
1153 if (tracker.needs_folder_listing()) 1247 if (tracker.needs_folder_listing())
1154 return true; 1248 return true;
1155 if (tracker.synced_details().md5() != file.details().md5()) 1249 if (tracker.synced_details().md5() != file->details().md5())
1156 return true; 1250 return true;
1157 } 1251 }
1158 1252
1159 const FileDetails& local_details = tracker.synced_details(); 1253 const FileDetails& local_details = tracker.synced_details();
1160 const FileDetails& remote_details = file.details(); 1254 const FileDetails& remote_details = file->details();
1161 1255
1162 if (local_details.title() != remote_details.title()) 1256 if (local_details.title() != remote_details.title())
1163 return true; 1257 return true;
1164 if (local_details.deleted() != remote_details.deleted()) 1258 if (local_details.deleted() != remote_details.deleted())
1165 return true; 1259 return true;
1166 1260
1167 return false; 1261 return false;
1168 } 1262 }
1169 1263
1264 bool MetadataDatabase::HasDisabledAppRoot(const FileTracker& tracker) const {
1265 TrackerByAppID::const_iterator found =
1266 app_root_by_app_id_.find(tracker.app_id());
1267 if (found == app_root_by_app_id_.end())
1268 return false;
1269
1270 const FileTracker* app_root_tracker = found->second;
1271 DCHECK(app_root_tracker);
1272 return app_root_tracker->tracker_kind() == TRACKER_KIND_DISABLED_APP_ROOT;
1273 }
1274
1275 bool MetadataDatabase::HasActiveTrackerForFileID(
1276 const std::string& file_id) const {
1277 TrackersByFileID::const_iterator found = trackers_by_file_id_.find(file_id);
1278 return found != trackers_by_file_id_.end() && found->second.has_active();
1279 }
1280
1281 bool MetadataDatabase::HasActiveTrackerForPath(int64 parent_tracker_id,
1282 const std::string& title) const {
1283 TrackersByParentAndTitle::const_iterator found_by_parent =
1284 trackers_by_parent_and_title_.find(parent_tracker_id);
1285 if (found_by_parent == trackers_by_parent_and_title_.end())
1286 return false;
1287
1288 const TrackersByTitle& trackers_by_title = found_by_parent->second;
1289 TrackersByTitle::const_iterator found = trackers_by_title.find(title);
1290 return found != trackers_by_title.end() && found->second.has_active();
1291 }
1292
1293 void MetadataDatabase::UpdateTrackerTitle(FileTracker* tracker,
1294 const std::string& new_title,
1295 leveldb::WriteBatch* batch) {
1296 int64 parent_id = tracker->parent_tracker_id();
1297 std::string old_title = GetTrackerTitle(*tracker);
1298 DCHECK_NE(old_title, new_title);
1299 DCHECK(!new_title.empty());
1300
1301 TrackersByTitle* trackers_by_title =
1302 &trackers_by_parent_and_title_[parent_id];
1303 TrackerSet* old_siblings = &(*trackers_by_title)[old_title];
1304 TrackerSet* new_siblings = &(*trackers_by_title)[new_title];
1305
1306 old_siblings->Erase(tracker);
1307 if (old_siblings->empty())
1308 trackers_by_title->erase(old_title);
1309 else
1310 MarkTrackerSetDirty(old_siblings, batch);
1311
1312 if (tracker->active() && new_siblings->has_active()) {
1313 // Inactivate existing active tracker.
1314 FileTracker* obstacle = new_siblings->active_tracker();
1315 new_siblings->Inactivate(obstacle);
1316 DCHECK_EQ(TRACKER_KIND_REGULAR, obstacle->tracker_kind());
1317
1318 TrackerSet* same_file_id_trackers_to_obstacle =
1319 &trackers_by_file_id_[obstacle->file_id()];
1320 same_file_id_trackers_to_obstacle->Inactivate(obstacle);
1321 MarkTrackerSetDirty(same_file_id_trackers_to_obstacle, batch);
1322
1323 obstacle->set_active(false);
1324 PutTrackerToBatch(*obstacle, batch);
1325
1326 RemoveAllDescendantTrackers(obstacle->tracker_id(), batch);
1327 }
1328
1329 tracker->mutable_synced_details()->set_title(new_title);
1330 new_siblings->Insert(tracker);
1331 PutTrackerToBatch(*tracker, batch);
1332 }
1333
1170 void MetadataDatabase::WriteToDatabase(scoped_ptr<leveldb::WriteBatch> batch, 1334 void MetadataDatabase::WriteToDatabase(scoped_ptr<leveldb::WriteBatch> batch,
1171 const SyncStatusCallback& callback) { 1335 const SyncStatusCallback& callback) {
1172 base::PostTaskAndReplyWithResult( 1336 base::PostTaskAndReplyWithResult(
1173 task_runner_.get(), 1337 task_runner_.get(),
1174 FROM_HERE, 1338 FROM_HERE,
1175 base::Bind(&leveldb::DB::Write, 1339 base::Bind(&leveldb::DB::Write,
1176 base::Unretained(db_.get()), 1340 base::Unretained(db_.get()),
1177 leveldb::WriteOptions(), 1341 leveldb::WriteOptions(),
1178 base::Owned(batch.release())), 1342 base::Owned(batch.release())),
1179 base::Bind(&AdaptLevelDBStatusToSyncStatusCode, callback)); 1343 base::Bind(&AdaptLevelDBStatusToSyncStatusCode, callback));
1180 } 1344 }
1181 1345
1182 } // namespace drive_backend 1346 } // namespace drive_backend
1183 } // namespace sync_file_system 1347 } // namespace sync_file_system
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698