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

Unified Diff: components/sync/engine_impl/loopback_server/loopback_server.cc

Issue 2887343002: wip 3 (Closed)
Patch Set: cleanup Created 3 years, 7 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: components/sync/engine_impl/loopback_server/loopback_server.cc
diff --git a/components/sync/engine_impl/loopback_server/loopback_server.cc b/components/sync/engine_impl/loopback_server/loopback_server.cc
index 55ea0cd369c09a738f9bacd1b9797bc6cb50b821..b09b01f71942a8160a1389bb6e9ec25a69931216 100644
--- a/components/sync/engine_impl/loopback_server/loopback_server.cc
+++ b/components/sync/engine_impl/loopback_server/loopback_server.cc
@@ -12,6 +12,7 @@
#include "base/files/file_util.h"
#include "base/guid.h"
#include "base/logging.h"
+#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/rand_util.h"
#include "base/stl_util.h"
@@ -52,104 +53,91 @@ static const char kSyncedBookmarksFolderServerTag[] = "synced_bookmarks";
static const char kSyncedBookmarksFolderName[] = "Synced Bookmarks";
// A filter used during GetUpdates calls to determine what information to
-// send back to the client. There is a 1:1 correspondence between any given
-// GetUpdates call and an UpdateSieve instance.
+// send back to the client; filtering out old entities and tracking versions to
+// use in response progress markers. Note that only the GetUpdatesMessage's
+// from_progress_marker is used to determine this; legacy fields are ignored.
class UpdateSieve {
public:
+ explicit UpdateSieve(const sync_pb::GetUpdatesMessage& message)
+ : UpdateSieve(MessageToVersionMap(message)) {}
~UpdateSieve() {}
- // Factory method for creating an UpdateSieve.
- static std::unique_ptr<UpdateSieve> Create(
- const sync_pb::GetUpdatesMessage& get_updates_message);
-
- // Sets the progress markers in |get_updates_response| given the progress
- // markers from the original GetUpdatesMessage and |new_version| (the latest
- // version in the entries sent back).
- void UpdateProgressMarkers(
- int64_t new_version,
+ // Sets the progress markers in |get_updates_response| based on the highest
+ // version between request progress markers and response entities.
+ void SetProgressMarkers(
sync_pb::GetUpdatesResponse* get_updates_response) const {
- ModelTypeToVersionMap::const_iterator it;
- for (it = request_from_version_.begin(); it != request_from_version_.end();
- ++it) {
+ for (const auto& kv : response_version_map_) {
sync_pb::DataTypeProgressMarker* new_marker =
get_updates_response->add_new_progress_marker();
new_marker->set_data_type_id(
- GetSpecificsFieldNumberFromModelType(it->first));
-
- int64_t version = std::max(new_version, it->second);
- new_marker->set_token(base::Int64ToString(version));
+ GetSpecificsFieldNumberFromModelType(kv.first));
+ new_marker->set_token(base::Int64ToString(kv.second));
}
}
// Determines whether the server should send an |entity| to the client as
- // part of a GetUpdatesResponse.
- bool ClientWantsItem(const LoopbackServerEntity& entity) const {
+ // part of a GetUpdatesResponse. Update internal tracking of max versions as a
+ // side effect which will later be used to set response progress markers.
+ bool ClientWantsItem(const LoopbackServerEntity& entity) {
int64_t version = entity.GetVersion();
- if (version <= min_version_) {
- return false;
- } else if (entity.IsDeleted()) {
- return true;
- }
-
- ModelTypeToVersionMap::const_iterator it =
- request_from_version_.find(entity.GetModelType());
-
- return it == request_from_version_.end() ? false : it->second < version;
+ ModelType type = entity.GetModelType();
+ response_version_map_[type] =
+ std::max(response_version_map_[type], version);
+ auto it = request_version_map_.find(type);
+ return it == request_version_map_.end() ? false : it->second < version;
}
- // Returns the minimum version seen across all types.
- int64_t GetMinVersion() const { return min_version_; }
-
private:
using ModelTypeToVersionMap = std::map<ModelType, int64_t>;
- // Creates an UpdateSieve.
- UpdateSieve(const ModelTypeToVersionMap request_from_version,
- const int64_t min_version)
- : request_from_version_(request_from_version),
- min_version_(min_version) {}
-
- // Maps data type IDs to the latest version seen for that type.
- const ModelTypeToVersionMap request_from_version_;
-
- // The minimum version seen among all data types.
- const int min_version_;
-};
+ static UpdateSieve::ModelTypeToVersionMap MessageToVersionMap(
+ const sync_pb::GetUpdatesMessage& get_updates_message) {
+ CHECK_GT(get_updates_message.from_progress_marker_size(), 0)
+ << "A GetUpdates request must have at least one progress marker.";
+ ModelTypeToVersionMap request_version_map;
+
+ for (int i = 0; i < get_updates_message.from_progress_marker_size(); i++) {
+ sync_pb::DataTypeProgressMarker marker =
+ get_updates_message.from_progress_marker(i);
+
+ int64_t version = 0;
+ // Let the version remain zero if there is no token or an empty token (the
+ // first request for this type).
+ if (marker.has_token() && !marker.token().empty()) {
+ bool parsed = base::StringToInt64(marker.token(), &version);
+ CHECK(parsed) << "Unable to parse progress marker token.";
+ }
-std::unique_ptr<UpdateSieve> UpdateSieve::Create(
- const sync_pb::GetUpdatesMessage& get_updates_message) {
- CHECK_GT(get_updates_message.from_progress_marker_size(), 0)
- << "A GetUpdates request must have at least one progress marker.";
-
- UpdateSieve::ModelTypeToVersionMap request_from_version;
- int64_t min_version = std::numeric_limits<int64_t>::max();
- for (int i = 0; i < get_updates_message.from_progress_marker_size(); i++) {
- sync_pb::DataTypeProgressMarker marker =
- get_updates_message.from_progress_marker(i);
-
- int64_t version = 0;
- // Let the version remain zero if there is no token or an empty token (the
- // first request for this type).
- if (marker.has_token() && !marker.token().empty()) {
- bool parsed = base::StringToInt64(marker.token(), &version);
- CHECK(parsed) << "Unable to parse progress marker token.";
+ ModelType model_type =
+ syncer::GetModelTypeFromSpecificsFieldNumber(marker.data_type_id());
+ DCHECK(request_version_map.find(model_type) == request_version_map.end());
+ request_version_map[model_type] = version;
}
- ModelType model_type =
- syncer::GetModelTypeFromSpecificsFieldNumber(marker.data_type_id());
- request_from_version[model_type] = version;
-
- if (version < min_version)
- min_version = version;
+ return request_version_map;
}
- return std::unique_ptr<UpdateSieve>(
- new UpdateSieve(request_from_version, min_version));
-}
+ explicit UpdateSieve(const ModelTypeToVersionMap request_version_map)
+ : request_version_map_(request_version_map),
+ response_version_map_(request_version_map) {}
+
+ // The largest versions the client has seen before this request, and is used
+ // to filter entities to send back to clients. The values in this map are not
+ // updated after being initially set. The presence of a type in this map is a
+ // proxy for the desire to receive results about this type.
+ const ModelTypeToVersionMap request_version_map_;
+
+ // The largest versions seen between client and server, ultimately used to
+ // send progress markers back to the client.
+ ModelTypeToVersionMap response_version_map_;
+};
} // namespace
LoopbackServer::LoopbackServer(const base::FilePath& persistent_file)
- : version_(0), store_birthday_(0), persistent_file_(persistent_file) {
+ : version_(0),
+ store_birthday_(0),
+ persistent_file_(persistent_file),
+ observer_for_tests_(NULL) {
Init();
}
@@ -290,7 +278,7 @@ bool LoopbackServer::HandleGetUpdatesRequest(
// at once.
response->set_changes_remaining(0);
- std::unique_ptr<UpdateSieve> sieve = UpdateSieve::Create(get_updates);
+ auto sieve = base::MakeUnique<UpdateSieve>(get_updates);
// This folder is called "Synced Bookmarks" by sync and is renamed
// "Mobile Bookmarks" by the mobile client UIs.
@@ -301,7 +289,6 @@ bool LoopbackServer::HandleGetUpdatesRequest(
}
bool send_encryption_keys_based_on_nigori = false;
- int64_t max_response_version = 0;
for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end();
++it) {
const LoopbackServerEntity& entity = *it->second;
@@ -309,9 +296,6 @@ bool LoopbackServer::HandleGetUpdatesRequest(
sync_pb::SyncEntity* response_entity = response->add_entries();
entity.SerializeAsProto(response_entity);
- max_response_version =
- std::max(max_response_version, response_entity->version());
-
if (entity.GetModelType() == syncer::NIGORI) {
send_encryption_keys_based_on_nigori =
response_entity->specifics().nigori().passphrase_type() ==
@@ -328,7 +312,7 @@ bool LoopbackServer::HandleGetUpdatesRequest(
}
}
- sieve->UpdateProgressMarkers(max_response_version, response);
+ sieve->SetProgressMarkers(response);
return true;
}
@@ -465,6 +449,9 @@ bool LoopbackServer::HandleCommitRequest(
committed_model_types.Put(iter->second->GetModelType());
}
+ if (observer_for_tests_)
+ observer_for_tests_->OnCommit(invalidator_client_id, committed_model_types);
+
return true;
}
@@ -473,6 +460,7 @@ void LoopbackServer::ClearServerData() {
entities_.clear();
keystore_keys_.clear();
++store_birthday_;
+ base::DeleteFile(persistent_file_, false);
Init();
}
@@ -481,6 +469,74 @@ std::string LoopbackServer::GetStoreBirthday() const {
return base::Int64ToString(store_birthday_);
}
+std::vector<sync_pb::SyncEntity> LoopbackServer::GetSyncEntitiesByModelType(
+ ModelType model_type) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ std::vector<sync_pb::SyncEntity> sync_entities;
+ for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end();
+ ++it) {
+ const LoopbackServerEntity& entity = *it->second;
+ if (!(entity.IsDeleted() || entity.IsPermanent()) &&
+ entity.GetModelType() == model_type) {
+ sync_pb::SyncEntity sync_entity;
+ entity.SerializeAsProto(&sync_entity);
+ sync_entities.push_back(sync_entity);
+ }
+ }
+ return sync_entities;
+}
+
+std::unique_ptr<base::DictionaryValue>
+LoopbackServer::GetEntitiesAsDictionaryValue() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ std::unique_ptr<base::DictionaryValue> dictionary(
+ new base::DictionaryValue());
+
+ // Initialize an empty ListValue for all ModelTypes.
+ ModelTypeSet all_types = ModelTypeSet::All();
+ for (ModelTypeSet::Iterator it = all_types.First(); it.Good(); it.Inc()) {
+ dictionary->Set(ModelTypeToString(it.Get()), new base::ListValue());
+ }
+
+ for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end();
+ ++it) {
+ const LoopbackServerEntity& entity = *it->second;
+ if (entity.IsDeleted() || entity.IsPermanent()) {
+ // Tombstones are ignored as they don't represent current data. Folders
+ // are also ignored as current verification infrastructure does not
+ // consider them.
+ continue;
+ }
+ base::ListValue* list_value;
+ if (!dictionary->GetList(ModelTypeToString(entity.GetModelType()),
+ &list_value)) {
+ return std::unique_ptr<base::DictionaryValue>();
+ }
+ // TODO(pvalenzuela): Store more data for each entity so additional
+ // verification can be performed. One example of additional verification
+ // is checking the correctness of the bookmark hierarchy.
+ list_value->AppendString(entity.GetName());
+ }
+
+ return dictionary;
+}
+
+bool LoopbackServer::ModifyEntitySpecifics(
+ const std::string& id,
+ const sync_pb::EntitySpecifics& updated_specifics) {
+ EntityMap::const_iterator iter = entities_.find(id);
+ if (iter == entities_.end() ||
+ iter->second->GetModelType() !=
+ GetModelTypeFromSpecifics(updated_specifics)) {
+ return false;
+ }
+
+ LoopbackServerEntity* entity = iter->second.get();
+ entity->SetSpecifics(updated_specifics);
+ UpdateEntityVersion(entity);
+ return true;
+}
+
void LoopbackServer::SerializeState(sync_pb::LoopbackServerProto* proto) const {
DCHECK(thread_checker_.CalledOnValidThread());

Powered by Google App Engine
This is Rietveld 408576698