Commit 2c8259e6 authored by Mikel Astiz's avatar Mikel Astiz Committed by Commit Bot

Introduce generic bridge for SyncableService-s

The class allows legacy datatypes (non-USS), which implement
SyncableService, to be integrated within the USS architecture, making
it possible to reuse central objects like
ClientTagBasedModelTypeProcessor and ModelTypeWorker.

Design Doc (Googlers only):
https://docs.google.com/document/d/14ScYZ0sop921gjBwXuReIEuQJlwftqkuSM1jMK_A_x4

In this first patch, we introduce the bridge itself. Follow-up patches
will introduce the necessary plumbing to exercise it.

Expected main benefits:
- Unify logic across datatypes by avoiding subtle behavioral differences
  across architectures.
- Remove lots of code (~25K LoC), hence:
  a) reduce Chrome binary size.
  b) reduce maintenance cost.
  c) eng ramp-up time.
- Improve resource footprint (less RAM, ~50% savings).
- Reduce the gap for datatypes to actually migrate to USS.
- Unblock multiple cleanup work, including a massive simplification of
  DataTypeManager and related classes, including controllers.

Bug: 870624
Change-Id: I1bd7f553bf22886c5136e7e12f13b37a3dc77a39
Reviewed-on: https://chromium-review.googlesource.com/1164742Reviewed-by: default avatarMarc Treib <treib@chromium.org>
Commit-Queue: Mikel Astiz <mastiz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#595017}
parent aac52ed0
......@@ -450,6 +450,8 @@ jumbo_static_library("sync") {
"model_impl/proxy_model_type_controller_delegate.h",
"model_impl/sync_metadata_store_change_list.cc",
"model_impl/sync_metadata_store_change_list.h",
"model_impl/syncable_service_based_bridge.cc",
"model_impl/syncable_service_based_bridge.h",
"protocol/proto_enum_conversions.cc",
"protocol/proto_enum_conversions.h",
"protocol/proto_memory_estimations.cc",
......@@ -902,6 +904,7 @@ source_set("unit_tests") {
"model_impl/model_type_store_backend_unittest.cc",
"model_impl/model_type_store_impl_unittest.cc",
"model_impl/processor_entity_tracker_unittest.cc",
"model_impl/syncable_service_based_bridge_unittest.cc",
"protocol/proto_enum_conversions_unittest.cc",
"protocol/proto_value_conversions_unittest.cc",
"syncable/change_record_unittest.cc",
......
......@@ -108,10 +108,10 @@ class ModelTypeSyncBridge {
// Get or generate a client tag for |entity_data|. This must be the same tag
// that was/would have been generated in the SyncableService/Directory world
// for backward compatibility with pre-USS clients. The only time this
// theoretically needs to be called is on the creation of local data, however
// it is also used to verify the hash of remote data. If a model type was
// never launched pre-USS, then method does not need to be different from
// GetStorageKey(). Only the hash of this value is kept.
// theoretically needs to be called is on the creation of local data.
//
// If a model type was never launched pre-USS, then method does not need to be
// different from GetStorageKey(). Only the hash of this value is kept.
virtual std::string GetClientTag(const EntityData& entity_data) = 0;
// Must not be called unless SupportsGetStorageKey() returns true.
......
......@@ -1169,6 +1169,8 @@ size_t ClientTagBasedModelTypeProcessor::EstimateMemoryUsage() const {
memory_usage += EstimateMemoryUsage(model_type_state_);
memory_usage += EstimateMemoryUsage(entities_);
memory_usage += EstimateMemoryUsage(storage_key_to_tag_hash_);
// TODO(crbug.com/870624): Let bridges provide custom additional memory
// overhead, which is important for SyncableServiceBasedBridge.
return memory_usage;
}
......
This diff is collapsed.
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_SYNC_MODEL_IMPL_SYNCABLE_SERVICE_BASED_BRIDGE_H_
#define COMPONENTS_SYNC_MODEL_IMPL_SYNCABLE_SERVICE_BASED_BRIDGE_H_
#include <map>
#include <memory>
#include <string>
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "components/sync/model/model_error.h"
#include "components/sync/model/model_type_store.h"
#include "components/sync/model/model_type_sync_bridge.h"
#include "components/sync/model/sync_change_processor.h"
namespace syncer {
class MetadataBatch;
class ModelTypeChangeProcessor;
class SyncableService;
// Implementation of ModelTypeSyncBridge that allows integrating legacy
// datatypes that implement SyncableService. Internally, it uses a database to
// persist and mimic the legacy directory's behavior, but as opposed to the
// legacy directory, it's not exposed anywhere outside this bridge, and is
// considered an implementation detail.
class SyncableServiceBasedBridge : public ModelTypeSyncBridge {
public:
// Pointers must not be null and |syncable_service| must outlive this object.
SyncableServiceBasedBridge(
ModelType type,
OnceModelTypeStoreFactory store_factory,
std::unique_ptr<ModelTypeChangeProcessor> change_processor,
SyncableService* syncable_service);
~SyncableServiceBasedBridge() override;
// ModelTypeSyncBridge implementation.
void OnSyncStarting(const DataTypeActivationRequest& request) override;
std::unique_ptr<MetadataChangeList> CreateMetadataChangeList() override;
base::Optional<ModelError> MergeSyncData(
std::unique_ptr<MetadataChangeList> metadata_change_list,
EntityChangeList entity_change_list) override;
base::Optional<ModelError> ApplySyncChanges(
std::unique_ptr<MetadataChangeList> metadata_change_list,
EntityChangeList entity_change_list) override;
void GetData(StorageKeyList storage_keys, DataCallback callback) override;
void GetAllDataForDebugging(DataCallback callback) override;
std::string GetClientTag(const EntityData& entity_data) override;
std::string GetStorageKey(const EntityData& entity_data) override;
bool SupportsGetClientTag() const override;
bool SupportsGetStorageKey() const override;
ConflictResolution ResolveConflict(
const EntityData& local_data,
const EntityData& remote_data) const override;
StopSyncResponse ApplyStopSyncChanges(
std::unique_ptr<MetadataChangeList> delete_metadata_change_list) override;
private:
void OnStoreCreated(const base::Optional<ModelError>& error,
std::unique_ptr<ModelTypeStore> store);
void OnReadAllDataForInit(
const base::Optional<ModelError>& error,
std::unique_ptr<ModelTypeStore::RecordList> record_list);
void OnReadAllMetadataForInit(const base::Optional<ModelError>& error,
std::unique_ptr<MetadataBatch> metadata_batch);
void MaybeStartSyncableService();
SyncChangeList StoreAndConvertRemoteChanges(
std::unique_ptr<MetadataChangeList> metadata_change_list,
EntityChangeList entity_change_list);
void OnReadDataForProcessor(
DataCallback callback,
const base::Optional<ModelError>& error,
std::unique_ptr<ModelTypeStore::RecordList> record_list,
std::unique_ptr<ModelTypeStore::IdList> missing_id_list);
void OnReadAllDataForProcessor(
DataCallback callback,
const base::Optional<ModelError>& error,
std::unique_ptr<ModelTypeStore::RecordList> record_list);
void ReportErrorIfSet(const base::Optional<ModelError>& error);
const ModelType type_;
SyncableService* const syncable_service_;
OnceModelTypeStoreFactory store_factory_;
std::unique_ptr<ModelTypeStore> store_;
bool syncable_service_started_;
// In-memory copy of |store_|, needed for remote deletions, because we need to
// provide specifics of the deleted entity to the SyncableService.
std::map<std::string, sync_pb::EntitySpecifics> in_memory_store_;
base::WeakPtrFactory<SyncableServiceBasedBridge> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(SyncableServiceBasedBridge);
};
} // namespace syncer
#endif // COMPONENTS_SYNC_MODEL_IMPL_SYNCABLE_SERVICE_BASED_BRIDGE_H_
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
syntax = "proto2";
option optimize_for = LITE_RUNTIME;
package sync_pb;
import "sync.proto";
// Sync proto to store entity data similar to what directory stores, used to
// persist data locally and never sent through the wire.
//
// Because it's conceptually similar to SyncEntity (actual protocol) and it's
// unclear how big this'll grow, we've kept compatibility with SyncEntity by
// using the same field numbers.
message PersistedEntityData {
// See corresponding fields in SyncEntity for details.
optional string non_unique_name = 8;
optional EntitySpecifics specifics = 21;
}
......@@ -37,6 +37,7 @@ sync_protocol_bases = [
"mountain_share_specifics",
"nigori_specifics",
"password_specifics",
"persisted_entity_data",
"preference_specifics",
"printer_specifics",
"priority_preference_specifics",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment