| Index: sync/internal_api/shared_model_type_processor.cc
|
| diff --git a/sync/internal_api/shared_model_type_processor.cc b/sync/internal_api/shared_model_type_processor.cc
|
| index a6ed683bfcb17dc93bb37882dbaa7eea20417461..f6573bec9e038b1960a020242688c8dd2343a030 100644
|
| --- a/sync/internal_api/shared_model_type_processor.cc
|
| +++ b/sync/internal_api/shared_model_type_processor.cc
|
| @@ -151,16 +151,15 @@ void SharedModelTypeProcessor::OnConnect(scoped_ptr<CommitQueue> worker) {
|
| void SharedModelTypeProcessor::Put(const std::string& client_tag,
|
| scoped_ptr<EntityData> entity_data,
|
| MetadataChangeList* metadata_change_list) {
|
| - // TODO(skym): Add metadata to persist to MetadataChangeList, crbug/569636.
|
| -
|
| DCHECK(entity_data.get());
|
| DCHECK(!entity_data->is_deleted());
|
| DCHECK(!entity_data->non_unique_name.empty());
|
| DCHECK_EQ(type_, syncer::GetModelTypeFromSpecifics(entity_data->specifics));
|
|
|
| // If the service specified an overriding hash, use that, otherwise generate
|
| - // one from the tag. TODO(skym): This behavior should be delayed, once
|
| - // crbug/561818 is fixed we will only perform this logic in the create case.
|
| + // one from the tag.
|
| + // TODO(skym): This behavior should be delayed, once crbug.com/561818 is fixed
|
| + // we will only perform this logic in the create case.
|
| const std::string client_tag_hash(
|
| entity_data->client_tag_hash.empty()
|
| ? syncer::syncable::GenerateSyncableHash(type_, client_tag)
|
| @@ -169,9 +168,9 @@ void SharedModelTypeProcessor::Put(const std::string& client_tag,
|
| base::Time now = base::Time::Now();
|
|
|
| ModelTypeEntity* entity = nullptr;
|
| - // TODO(stanisc): crbug/561818: Search by client_tag rather than
|
| + // TODO(stanisc): crbug.com/561818: Search by client_tag rather than
|
| // client_tag_hash.
|
| - EntityMap::const_iterator it = entities_.find(client_tag_hash);
|
| + auto it = entities_.find(client_tag_hash);
|
| if (it == entities_.end()) {
|
| // The service is creating a new entity.
|
| scoped_ptr<ModelTypeEntity> scoped_entity = ModelTypeEntity::CreateNew(
|
| @@ -182,32 +181,39 @@ void SharedModelTypeProcessor::Put(const std::string& client_tag,
|
| } else {
|
| // The service is updating an existing entity.
|
| entity = it->second.get();
|
| + DCHECK_EQ(client_tag, entity->client_key());
|
| }
|
|
|
| + // TODO(stanisc): crbug.com/561829: Avoid committing a change if there is no
|
| + // actual change.
|
| entity->MakeLocalChange(std::move(entity_data), now);
|
| + metadata_change_list->UpdateMetadata(client_tag, entity->metadata());
|
| +
|
| FlushPendingCommitRequests();
|
| }
|
|
|
| void SharedModelTypeProcessor::Delete(
|
| const std::string& client_key,
|
| MetadataChangeList* metadata_change_list) {
|
| - // TODO(skym): Add metadata to persist to MetadataChangeList, crbug/569636.
|
| -
|
| const std::string client_tag_hash(
|
| syncer::syncable::GenerateSyncableHash(type_, client_key));
|
|
|
| - // TODO(skym): crbug/561818: Search by client_tag rather than client_tag_hash.
|
| - EntityMap::const_iterator it = entities_.find(client_tag_hash);
|
| + // TODO(skym): crbug.com/561818: Search by client_tag rather than
|
| + // client_tag_hash.
|
| + auto it = entities_.find(client_tag_hash);
|
| if (it == entities_.end()) {
|
| // That's unusual, but not necessarily a bad thing.
|
| // Missing is as good as deleted as far as the model is concerned.
|
| DLOG(WARNING) << "Attempted to delete missing item."
|
| << " client tag: " << client_key;
|
| - } else {
|
| - ModelTypeEntity* entity = it->second.get();
|
| - entity->Delete();
|
| + return;
|
| }
|
|
|
| + ModelTypeEntity* entity = it->second.get();
|
| + entity->Delete();
|
| +
|
| + metadata_change_list->UpdateMetadata(client_key, entity->metadata());
|
| +
|
| FlushPendingCommitRequests();
|
| }
|
|
|
| @@ -223,8 +229,7 @@ void SharedModelTypeProcessor::FlushPendingCommitRequests() {
|
| return;
|
|
|
| // TODO(rlarocque): Do something smarter than iterate here.
|
| - for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end();
|
| - ++it) {
|
| + for (auto it = entities_.begin(); it != entities_.end(); ++it) {
|
| if (it->second->RequiresCommitRequest()) {
|
| CommitRequestData request;
|
| it->second->InitializeCommitRequestData(&request);
|
| @@ -240,14 +245,18 @@ void SharedModelTypeProcessor::FlushPendingCommitRequests() {
|
| void SharedModelTypeProcessor::OnCommitCompleted(
|
| const DataTypeState& type_state,
|
| const CommitResponseDataList& response_list) {
|
| + scoped_ptr<MetadataChangeList> change_list =
|
| + service_->CreateMetadataChangeList();
|
| +
|
| data_type_state_ = type_state;
|
| + change_list->UpdateDataTypeState(data_type_state_);
|
|
|
| - for (CommitResponseDataList::const_iterator list_it = response_list.begin();
|
| - list_it != response_list.end(); ++list_it) {
|
| + for (auto list_it = response_list.begin(); list_it != response_list.end();
|
| + ++list_it) {
|
| const CommitResponseData& response_data = *list_it;
|
| const std::string& client_tag_hash = response_data.client_tag_hash;
|
|
|
| - EntityMap::const_iterator it = entities_.find(client_tag_hash);
|
| + auto it = entities_.find(client_tag_hash);
|
| if (it == entities_.end()) {
|
| NOTREACHED() << "Received commit response for missing item."
|
| << " type: " << type_ << " client_tag: " << client_tag_hash;
|
| @@ -256,21 +265,35 @@ void SharedModelTypeProcessor::OnCommitCompleted(
|
| it->second->ReceiveCommitResponse(
|
| response_data.id, response_data.sequence_number,
|
| response_data.response_version, data_type_state_.encryption_key_name);
|
| + // TODO(stanisc): crbug.com/573333: Delete case.
|
| + // This might be the right place to clear a metadata entry that has
|
| + // been deleted locally and confirmed deleted by the server.
|
| + change_list->UpdateMetadata(it->second->client_key(),
|
| + it->second->metadata());
|
| }
|
| }
|
| +
|
| + // TODO(stanisc): What is the right method to submit metadata changes to the
|
| + // service? Is using empty EntityChangeList OK?
|
| + // TODO(stanisc): crbug.com/570085: Error handling.
|
| + service_->ApplySyncChanges(std::move(change_list), EntityChangeList());
|
| }
|
|
|
| void SharedModelTypeProcessor::OnUpdateReceived(
|
| const DataTypeState& data_type_state,
|
| const UpdateResponseDataList& response_list,
|
| const UpdateResponseDataList& pending_updates) {
|
| + scoped_ptr<MetadataChangeList> metadata_changes =
|
| + service_->CreateMetadataChangeList();
|
| + EntityChangeList entity_changes;
|
| +
|
| + metadata_changes->UpdateDataTypeState(data_type_state);
|
| bool got_new_encryption_requirements = data_type_state_.encryption_key_name !=
|
| data_type_state.encryption_key_name;
|
| -
|
| data_type_state_ = data_type_state;
|
|
|
| - for (UpdateResponseDataList::const_iterator list_it = response_list.begin();
|
| - list_it != response_list.end(); ++list_it) {
|
| + for (auto list_it = response_list.begin(); list_it != response_list.end();
|
| + ++list_it) {
|
| const UpdateResponseData& response_data = *list_it;
|
| const EntityData& data = response_data.entity.value();
|
| const std::string& client_tag_hash = data.client_tag_hash;
|
| @@ -280,24 +303,47 @@ void SharedModelTypeProcessor::OnUpdateReceived(
|
| pending_updates_map_.erase(client_tag_hash);
|
|
|
| ModelTypeEntity* entity = nullptr;
|
| - EntityMap::const_iterator it = entities_.find(client_tag_hash);
|
| + auto it = entities_.find(client_tag_hash);
|
| if (it == entities_.end()) {
|
| + if (data.is_deleted()) {
|
| + DLOG(WARNING) << "Received remote delete for a non-existing item."
|
| + << " client_tag_hash: " << client_tag_hash;
|
| + continue;
|
| + }
|
| +
|
| // Let the service define |client_tag| based on the entity data.
|
| - std::string client_tag = service_->GetClientTag(data);
|
| + std::string client_key = service_->GetClientTag(data);
|
|
|
| scoped_ptr<ModelTypeEntity> scoped_entity = ModelTypeEntity::CreateNew(
|
| - client_tag, client_tag_hash, data.id, data.creation_time);
|
| + client_key, client_tag_hash, data.id, data.creation_time);
|
| entity = scoped_entity.get();
|
| entities_.insert(
|
| std::make_pair(client_tag_hash, std::move(scoped_entity)));
|
|
|
| + entity_changes.push_back(
|
| + EntityChange::CreateAdd(client_key, response_data.entity));
|
| +
|
| } else {
|
| entity = it->second.get();
|
| + if (data.is_deleted()) {
|
| + entity_changes.push_back(
|
| + EntityChange::CreateDelete(entity->client_key()));
|
| + } else {
|
| + // TODO(stanisc): crbug.com/561829: Avoid sending an update to the
|
| + // service if there is no actual change.
|
| + entity_changes.push_back(EntityChange::CreateUpdate(
|
| + entity->client_key(), response_data.entity));
|
| + }
|
| }
|
|
|
| entity->ApplyUpdateFromServer(response_data);
|
| + // TODO(stanisc): crbug.com/573333: Delete case.
|
| + // This might be the right place to clear metadata entry instead of
|
| + // updating it.
|
| + metadata_changes->UpdateMetadata(entity->client_key(), entity->metadata());
|
|
|
| - // TODO(stanisc): Do something special when conflicts are detected.
|
| + // TODO(stanisc): crbug.com/521867: Do something special when conflicts are
|
| + // detected.
|
|
|
| // If the received entity has out of date encryption, we schedule another
|
| // commit to fix it.
|
| @@ -306,20 +352,20 @@ void SharedModelTypeProcessor::OnUpdateReceived(
|
| DVLOG(2) << ModelTypeToString(type_) << ": Requesting re-encrypt commit "
|
| << response_data.encryption_key_name << " -> "
|
| << data_type_state_.encryption_key_name;
|
| - EntityMap::const_iterator it2 = entities_.find(client_tag_hash);
|
| + auto it2 = entities_.find(client_tag_hash);
|
| it2->second->UpdateDesiredEncryptionKey(
|
| data_type_state_.encryption_key_name);
|
| }
|
| }
|
|
|
| + // TODO: crbug.com/529498: stop saving pending updates.
|
| // Save pending updates in the appropriate data structure.
|
| - for (UpdateResponseDataList::const_iterator list_it = pending_updates.begin();
|
| - list_it != pending_updates.end(); ++list_it) {
|
| + for (auto list_it = pending_updates.begin(); list_it != pending_updates.end();
|
| + ++list_it) {
|
| const UpdateResponseData& update = *list_it;
|
| const std::string& client_tag_hash = update.entity->client_tag_hash;
|
|
|
| - UpdateMap::const_iterator lookup_it =
|
| - pending_updates_map_.find(client_tag_hash);
|
| + auto lookup_it = pending_updates_map_.find(client_tag_hash);
|
| if (lookup_it == pending_updates_map_.end()) {
|
| pending_updates_map_.insert(std::make_pair(
|
| client_tag_hash, make_scoped_ptr(new UpdateResponseData(update))));
|
| @@ -333,43 +379,43 @@ void SharedModelTypeProcessor::OnUpdateReceived(
|
| }
|
|
|
| if (got_new_encryption_requirements) {
|
| - for (EntityMap::const_iterator it = entities_.begin();
|
| - it != entities_.end(); ++it) {
|
| + for (auto it = entities_.begin(); it != entities_.end(); ++it) {
|
| it->second->UpdateDesiredEncryptionKey(
|
| data_type_state_.encryption_key_name);
|
| }
|
| }
|
|
|
| + // Inform the service of the new or updated data.
|
| + // TODO(stanisc): crbug.com/570085: Error handling.
|
| + service_->ApplySyncChanges(std::move(metadata_changes), entity_changes);
|
| +
|
| // We may have new reasons to commit by the time this function is done.
|
| FlushPendingCommitRequests();
|
| -
|
| - // TODO(rlarocque): Inform the model of the new or updated data.
|
| - // TODO(rlarocque): Persist the new data on disk.
|
| }
|
|
|
| UpdateResponseDataList SharedModelTypeProcessor::GetPendingUpdates() {
|
| UpdateResponseDataList pending_updates_list;
|
| - for (UpdateMap::const_iterator it = pending_updates_map_.begin();
|
| - it != pending_updates_map_.end(); ++it) {
|
| + for (auto it = pending_updates_map_.begin(); it != pending_updates_map_.end();
|
| + ++it) {
|
| pending_updates_list.push_back(*it->second);
|
| }
|
| return pending_updates_list;
|
| }
|
|
|
| void SharedModelTypeProcessor::ClearTransientSyncState() {
|
| - for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end();
|
| - ++it) {
|
| + for (auto it = entities_.begin(); it != entities_.end(); ++it) {
|
| it->second->ClearTransientSyncState();
|
| }
|
| }
|
|
|
| void SharedModelTypeProcessor::ClearSyncState() {
|
| - for (EntityMap::const_iterator it = entities_.begin(); it != entities_.end();
|
| - ++it) {
|
| + for (auto it = entities_.begin(); it != entities_.end(); ++it) {
|
| it->second->ClearSyncState();
|
| }
|
| pending_updates_map_.clear();
|
| data_type_state_ = DataTypeState();
|
| + // TODO(stanisc): crbug.com/561830, crbug.com/573333: Update the service to
|
| + // let it know that all metadata need to be cleared from the storage.
|
| }
|
|
|
| } // namespace syncer_v2
|
|
|