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

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

Powered by Google App Engine
This is Rietveld 408576698