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

Side by Side Diff: components/sync/engine_impl/loopback_server/loopback_server.cc

Issue 2910993002: [sync] Pull the Sieve implementation from FakeServer to LoopbackServer. (Closed)
Patch Set: Created 3 years, 6 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 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 "components/sync/engine_impl/loopback_server/loopback_server.h" 5 #include "components/sync/engine_impl/loopback_server/loopback_server.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 #include <set> 9 #include <set>
10 #include <utility> 10 #include <utility>
11 11
12 #include "base/files/file_util.h" 12 #include "base/files/file_util.h"
13 #include "base/guid.h" 13 #include "base/guid.h"
14 #include "base/logging.h" 14 #include "base/logging.h"
15 #include "base/memory/ptr_util.h"
15 #include "base/metrics/histogram_macros.h" 16 #include "base/metrics/histogram_macros.h"
16 #include "base/rand_util.h" 17 #include "base/rand_util.h"
17 #include "base/stl_util.h" 18 #include "base/stl_util.h"
18 #include "base/strings/string_number_conversions.h" 19 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h" 20 #include "base/strings/string_util.h"
20 #include "base/strings/stringprintf.h" 21 #include "base/strings/stringprintf.h"
21 #include "base/synchronization/lock.h" 22 #include "base/synchronization/lock.h"
22 #include "components/sync/engine_impl/loopback_server/persistent_bookmark_entity .h" 23 #include "components/sync/engine_impl/loopback_server/persistent_bookmark_entity .h"
23 #include "components/sync/engine_impl/loopback_server/persistent_permanent_entit y.h" 24 #include "components/sync/engine_impl/loopback_server/persistent_permanent_entit y.h"
24 #include "components/sync/engine_impl/loopback_server/persistent_tombstone_entit y.h" 25 #include "components/sync/engine_impl/loopback_server/persistent_tombstone_entit y.h"
(...skipping 20 matching lines...) Expand all
45 46
46 // Properties of the bookmark bar permanent folders. 47 // Properties of the bookmark bar permanent folders.
47 static const char kBookmarkBarFolderServerTag[] = "bookmark_bar"; 48 static const char kBookmarkBarFolderServerTag[] = "bookmark_bar";
48 static const char kBookmarkBarFolderName[] = "Bookmark Bar"; 49 static const char kBookmarkBarFolderName[] = "Bookmark Bar";
49 static const char kOtherBookmarksFolderServerTag[] = "other_bookmarks"; 50 static const char kOtherBookmarksFolderServerTag[] = "other_bookmarks";
50 static const char kOtherBookmarksFolderName[] = "Other Bookmarks"; 51 static const char kOtherBookmarksFolderName[] = "Other Bookmarks";
51 static const char kSyncedBookmarksFolderServerTag[] = "synced_bookmarks"; 52 static const char kSyncedBookmarksFolderServerTag[] = "synced_bookmarks";
52 static const char kSyncedBookmarksFolderName[] = "Synced Bookmarks"; 53 static const char kSyncedBookmarksFolderName[] = "Synced Bookmarks";
53 54
54 // A filter used during GetUpdates calls to determine what information to 55 // A filter used during GetUpdates calls to determine what information to
55 // send back to the client. There is a 1:1 correspondence between any given 56 // send back to the client; filtering out old entities and tracking versions to
56 // GetUpdates call and an UpdateSieve instance. 57 // use in response progress markers. Note that only the GetUpdatesMessage's
58 // from_progress_marker is used to determine this; legacy fields are ignored.
57 class UpdateSieve { 59 class UpdateSieve {
58 public: 60 public:
61 explicit UpdateSieve(const sync_pb::GetUpdatesMessage& message)
62 : UpdateSieve(MessageToVersionMap(message)) {}
59 ~UpdateSieve() {} 63 ~UpdateSieve() {}
60 64
61 // Factory method for creating an UpdateSieve. 65 // Sets the progress markers in |get_updates_response| based on the highest
62 static std::unique_ptr<UpdateSieve> Create( 66 // version between request progress markers and response entities.
63 const sync_pb::GetUpdatesMessage& get_updates_message); 67 void SetProgressMarkers(
64
65 // Sets the progress markers in |get_updates_response| given the progress
66 // markers from the original GetUpdatesMessage and |new_version| (the latest
67 // version in the entries sent back).
68 void UpdateProgressMarkers(
69 int64_t new_version,
70 sync_pb::GetUpdatesResponse* get_updates_response) const { 68 sync_pb::GetUpdatesResponse* get_updates_response) const {
71 ModelTypeToVersionMap::const_iterator it; 69 for (const auto& kv : response_version_map_) {
72 for (it = request_from_version_.begin(); it != request_from_version_.end();
73 ++it) {
74 sync_pb::DataTypeProgressMarker* new_marker = 70 sync_pb::DataTypeProgressMarker* new_marker =
75 get_updates_response->add_new_progress_marker(); 71 get_updates_response->add_new_progress_marker();
76 new_marker->set_data_type_id( 72 new_marker->set_data_type_id(
77 GetSpecificsFieldNumberFromModelType(it->first)); 73 GetSpecificsFieldNumberFromModelType(kv.first));
78 74 new_marker->set_token(base::Int64ToString(kv.second));
79 int64_t version = std::max(new_version, it->second);
80 new_marker->set_token(base::Int64ToString(version));
81 } 75 }
82 } 76 }
83 77
84 // Determines whether the server should send an |entity| to the client as 78 // Determines whether the server should send an |entity| to the client as
85 // part of a GetUpdatesResponse. 79 // part of a GetUpdatesResponse. Update internal tracking of max versions as a
86 bool ClientWantsItem(const LoopbackServerEntity& entity) const { 80 // side effect which will later be used to set response progress markers.
81 bool ClientWantsItem(const LoopbackServerEntity& entity) {
87 int64_t version = entity.GetVersion(); 82 int64_t version = entity.GetVersion();
88 if (version <= min_version_) { 83 ModelType type = entity.GetModelType();
89 return false; 84 response_version_map_[type] =
90 } else if (entity.IsDeleted()) { 85 std::max(response_version_map_[type], version);
91 return true; 86 auto it = request_version_map_.find(type);
92 } 87 return it == request_version_map_.end() ? false : it->second < version;
93
94 ModelTypeToVersionMap::const_iterator it =
95 request_from_version_.find(entity.GetModelType());
96
97 return it == request_from_version_.end() ? false : it->second < version;
98 } 88 }
99 89
100 // Returns the minimum version seen across all types.
101 int64_t GetMinVersion() const { return min_version_; }
102
103 private: 90 private:
104 using ModelTypeToVersionMap = std::map<ModelType, int64_t>; 91 using ModelTypeToVersionMap = std::map<ModelType, int64_t>;
105 92
106 // Creates an UpdateSieve. 93 static UpdateSieve::ModelTypeToVersionMap MessageToVersionMap(
107 UpdateSieve(const ModelTypeToVersionMap request_from_version, 94 const sync_pb::GetUpdatesMessage& get_updates_message) {
108 const int64_t min_version) 95 CHECK_GT(get_updates_message.from_progress_marker_size(), 0)
109 : request_from_version_(request_from_version), 96 << "A GetUpdates request must have at least one progress marker.";
110 min_version_(min_version) {} 97 ModelTypeToVersionMap request_version_map;
111 98
112 // Maps data type IDs to the latest version seen for that type. 99 for (int i = 0; i < get_updates_message.from_progress_marker_size(); i++) {
113 const ModelTypeToVersionMap request_from_version_; 100 sync_pb::DataTypeProgressMarker marker =
101 get_updates_message.from_progress_marker(i);
114 102
115 // The minimum version seen among all data types. 103 int64_t version = 0;
116 const int min_version_; 104 // Let the version remain zero if there is no token or an empty token (the
117 }; 105 // first request for this type).
106 if (marker.has_token() && !marker.token().empty()) {
107 bool parsed = base::StringToInt64(marker.token(), &version);
108 CHECK(parsed) << "Unable to parse progress marker token.";
109 }
118 110
119 std::unique_ptr<UpdateSieve> UpdateSieve::Create( 111 ModelType model_type =
120 const sync_pb::GetUpdatesMessage& get_updates_message) { 112 syncer::GetModelTypeFromSpecificsFieldNumber(marker.data_type_id());
121 CHECK_GT(get_updates_message.from_progress_marker_size(), 0) 113 DCHECK(request_version_map.find(model_type) == request_version_map.end());
122 << "A GetUpdates request must have at least one progress marker."; 114 request_version_map[model_type] = version;
123
124 UpdateSieve::ModelTypeToVersionMap request_from_version;
125 int64_t min_version = std::numeric_limits<int64_t>::max();
126 for (int i = 0; i < get_updates_message.from_progress_marker_size(); i++) {
127 sync_pb::DataTypeProgressMarker marker =
128 get_updates_message.from_progress_marker(i);
129
130 int64_t version = 0;
131 // Let the version remain zero if there is no token or an empty token (the
132 // first request for this type).
133 if (marker.has_token() && !marker.token().empty()) {
134 bool parsed = base::StringToInt64(marker.token(), &version);
135 CHECK(parsed) << "Unable to parse progress marker token.";
136 } 115 }
137 ModelType model_type = 116 return request_version_map;
138 syncer::GetModelTypeFromSpecificsFieldNumber(marker.data_type_id());
139 request_from_version[model_type] = version;
140
141 if (version < min_version)
142 min_version = version;
143 } 117 }
144 118
145 return std::unique_ptr<UpdateSieve>( 119 explicit UpdateSieve(const ModelTypeToVersionMap request_version_map)
146 new UpdateSieve(request_from_version, min_version)); 120 : request_version_map_(request_version_map),
147 } 121 response_version_map_(request_version_map) {}
122
123 // The largest versions the client has seen before this request, and is used
124 // to filter entities to send back to clients. The values in this map are not
125 // updated after being initially set. The presence of a type in this map is a
126 // proxy for the desire to receive results about this type.
127 const ModelTypeToVersionMap request_version_map_;
128
129 // The largest versions seen between client and server, ultimately used to
130 // send progress markers back to the client.
131 ModelTypeToVersionMap response_version_map_;
132 };
148 133
149 } // namespace 134 } // namespace
150 135
151 LoopbackServer::LoopbackServer(const base::FilePath& persistent_file) 136 LoopbackServer::LoopbackServer(const base::FilePath& persistent_file)
152 : version_(0), store_birthday_(0), persistent_file_(persistent_file) { 137 : version_(0), store_birthday_(0), persistent_file_(persistent_file) {
153 Init(); 138 Init();
154 } 139 }
155 140
156 LoopbackServer::~LoopbackServer() {} 141 LoopbackServer::~LoopbackServer() {}
157 142
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 SaveStateToFile(persistent_file_); 268 SaveStateToFile(persistent_file_);
284 } 269 }
285 270
286 bool LoopbackServer::HandleGetUpdatesRequest( 271 bool LoopbackServer::HandleGetUpdatesRequest(
287 const sync_pb::GetUpdatesMessage& get_updates, 272 const sync_pb::GetUpdatesMessage& get_updates,
288 sync_pb::GetUpdatesResponse* response) { 273 sync_pb::GetUpdatesResponse* response) {
289 // TODO(pvalenzuela): Implement batching instead of sending all information 274 // TODO(pvalenzuela): Implement batching instead of sending all information
290 // at once. 275 // at once.
291 response->set_changes_remaining(0); 276 response->set_changes_remaining(0);
292 277
293 std::unique_ptr<UpdateSieve> sieve = UpdateSieve::Create(get_updates); 278 auto sieve = base::MakeUnique<UpdateSieve>(get_updates);
294 279
295 // This folder is called "Synced Bookmarks" by sync and is renamed 280 // This folder is called "Synced Bookmarks" by sync and is renamed
296 // "Mobile Bookmarks" by the mobile client UIs. 281 // "Mobile Bookmarks" by the mobile client UIs.
297 if (get_updates.create_mobile_bookmarks_folder() && 282 if (get_updates.create_mobile_bookmarks_folder() &&
298 !CreatePermanentBookmarkFolder(kSyncedBookmarksFolderServerTag, 283 !CreatePermanentBookmarkFolder(kSyncedBookmarksFolderServerTag,
299 kSyncedBookmarksFolderName)) { 284 kSyncedBookmarksFolderName)) {
300 return false; 285 return false;
301 } 286 }
302 287
303 bool send_encryption_keys_based_on_nigori = false; 288 bool send_encryption_keys_based_on_nigori = false;
304 int64_t max_response_version = 0;
305 for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end(); 289 for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end();
306 ++it) { 290 ++it) {
307 const LoopbackServerEntity& entity = *it->second; 291 const LoopbackServerEntity& entity = *it->second;
308 if (sieve->ClientWantsItem(entity)) { 292 if (sieve->ClientWantsItem(entity)) {
309 sync_pb::SyncEntity* response_entity = response->add_entries(); 293 sync_pb::SyncEntity* response_entity = response->add_entries();
310 entity.SerializeAsProto(response_entity); 294 entity.SerializeAsProto(response_entity);
311 295
312 max_response_version =
313 std::max(max_response_version, response_entity->version());
314
315 if (entity.GetModelType() == syncer::NIGORI) { 296 if (entity.GetModelType() == syncer::NIGORI) {
316 send_encryption_keys_based_on_nigori = 297 send_encryption_keys_based_on_nigori =
317 response_entity->specifics().nigori().passphrase_type() == 298 response_entity->specifics().nigori().passphrase_type() ==
318 sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE; 299 sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE;
319 } 300 }
320 } 301 }
321 } 302 }
322 303
323 if (send_encryption_keys_based_on_nigori || 304 if (send_encryption_keys_based_on_nigori ||
324 get_updates.need_encryption_key()) { 305 get_updates.need_encryption_key()) {
325 for (vector<string>::iterator it = keystore_keys_.begin(); 306 for (vector<string>::iterator it = keystore_keys_.begin();
326 it != keystore_keys_.end(); ++it) { 307 it != keystore_keys_.end(); ++it) {
327 response->add_encryption_keys(*it); 308 response->add_encryption_keys(*it);
328 } 309 }
329 } 310 }
330 311
331 sieve->UpdateProgressMarkers(max_response_version, response); 312 sieve->SetProgressMarkers(response);
332 return true; 313 return true;
333 } 314 }
334 315
335 string LoopbackServer::CommitEntity( 316 string LoopbackServer::CommitEntity(
336 const sync_pb::SyncEntity& client_entity, 317 const sync_pb::SyncEntity& client_entity,
337 sync_pb::CommitResponse_EntryResponse* entry_response, 318 sync_pb::CommitResponse_EntryResponse* entry_response,
338 const string& client_guid, 319 const string& client_guid,
339 const string& parent_id) { 320 const string& parent_id) {
340 if (client_entity.version() == 0 && client_entity.deleted()) { 321 if (client_entity.version() == 0 && client_entity.deleted()) {
341 return string(); 322 return string();
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
547 // write. 528 // write.
548 LOG(ERROR) << "Loopback sync can not read the persistent state file."; 529 LOG(ERROR) << "Loopback sync can not read the persistent state file.";
549 return false; 530 return false;
550 } 531 }
551 } 532 }
552 LOG(WARNING) << "Loopback sync persistent state file does not exist."; 533 LOG(WARNING) << "Loopback sync persistent state file does not exist.";
553 return false; 534 return false;
554 } 535 }
555 536
556 } // namespace syncer 537 } // namespace syncer
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698