diff options
Diffstat (limited to 'sync/engine/model_type_sync_proxy_impl.cc')
-rw-r--r-- | sync/engine/model_type_sync_proxy_impl.cc | 83 |
1 files changed, 74 insertions, 9 deletions
diff --git a/sync/engine/model_type_sync_proxy_impl.cc b/sync/engine/model_type_sync_proxy_impl.cc index 7b2148a..7ea5d52 100644 --- a/sync/engine/model_type_sync_proxy_impl.cc +++ b/sync/engine/model_type_sync_proxy_impl.cc @@ -18,6 +18,7 @@ ModelTypeSyncProxyImpl::ModelTypeSyncProxyImpl(ModelType type) is_preferred_(false), is_connected_(false), entities_deleter_(&entities_), + pending_updates_map_deleter_(&pending_updates_map_), weak_ptr_factory_for_ui_(this), weak_ptr_factory_for_sync_(this) { } @@ -51,10 +52,12 @@ void ModelTypeSyncProxyImpl::Enable( data_type_state_.progress_marker.set_data_type_id( GetSpecificsFieldNumberFromModelType(type_)); + UpdateResponseDataList saved_pending_updates = GetPendingUpdates(); sync_context_proxy_ = sync_context_proxy.Pass(); sync_context_proxy_->ConnectTypeToSync( GetModelType(), data_type_state_, + saved_pending_updates, weak_ptr_factory_for_sync_.GetWeakPtr()); } @@ -180,16 +183,18 @@ void ModelTypeSyncProxyImpl::OnCommitCompleted( } else { it->second->ReceiveCommitResponse(response_data.id, response_data.sequence_number, - response_data.response_version); + response_data.response_version, + data_type_state_.encryption_key_name); } } } void ModelTypeSyncProxyImpl::OnUpdateReceived( const DataTypeState& data_type_state, - const UpdateResponseDataList& response_list) { - bool initial_sync_just_finished = - !data_type_state_.initial_sync_done && data_type_state.initial_sync_done; + const UpdateResponseDataList& response_list, + const UpdateResponseDataList& pending_updates) { + bool got_new_encryption_requirements = data_type_state_.encryption_key_name != + data_type_state.encryption_key_name; data_type_state_ = data_type_state; @@ -199,6 +204,14 @@ void ModelTypeSyncProxyImpl::OnUpdateReceived( const UpdateResponseData& response_data = *list_it; const std::string& client_tag_hash = response_data.client_tag_hash; + UpdateMap::iterator old_it = pending_updates_map_.find(client_tag_hash); + if (old_it != pending_updates_map_.end()) { + // If we're being asked to apply an update to this entity, this overrides + // the previous pending updates. + delete old_it->second; + pending_updates_map_.erase(old_it); + } + EntityMap::iterator it = entities_.find(client_tag_hash); if (it == entities_.end()) { scoped_ptr<ModelTypeEntity> entity = @@ -209,22 +222,74 @@ void ModelTypeSyncProxyImpl::OnUpdateReceived( response_data.specifics, response_data.deleted, response_data.ctime, - response_data.mtime); + response_data.mtime, + response_data.encryption_key_name); entities_.insert(std::make_pair(client_tag_hash, entity.release())); } else { ModelTypeEntity* entity = it->second; entity->ApplyUpdateFromServer(response_data.response_version, response_data.deleted, response_data.specifics, - response_data.mtime); + response_data.mtime, + response_data.encryption_key_name); + // TODO: Do something special when conflicts are detected. } + + // If the received entity has out of date encryption, we schedule another + // commit to fix it. + if (data_type_state_.encryption_key_name != + response_data.encryption_key_name) { + EntityMap::iterator it2 = entities_.find(client_tag_hash); + it2->second->UpdateDesiredEncryptionKey( + data_type_state_.encryption_key_name); + } } - if (initial_sync_just_finished) - FlushPendingCommitRequests(); + // Save pending updates in the appropriate data structure. + for (UpdateResponseDataList::const_iterator list_it = pending_updates.begin(); + list_it != pending_updates.end(); + ++list_it) { + const UpdateResponseData& update = *list_it; + const std::string& client_tag_hash = update.client_tag_hash; + + UpdateMap::iterator 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, new UpdateResponseData(update))); + } else if (lookup_it->second->response_version <= update.response_version) { + delete lookup_it->second; + pending_updates_map_.erase(lookup_it); + pending_updates_map_.insert( + std::make_pair(client_tag_hash, new UpdateResponseData(update))); + } else { + // Received update is stale, do not overwrite existing. + } + } + + if (got_new_encryption_requirements) { + for (EntityMap::iterator it = entities_.begin(); it != entities_.end(); + ++it) { + it->second->UpdateDesiredEncryptionKey( + data_type_state_.encryption_key_name); + } + } + + // We may have new reasons to commit by the time this function is done. + FlushPendingCommitRequests(); // TODO: Inform the model of the new or updated data. + // TODO: Persist the new data on disk. +} + +UpdateResponseDataList ModelTypeSyncProxyImpl::GetPendingUpdates() { + UpdateResponseDataList pending_updates_list; + for (UpdateMap::const_iterator it = pending_updates_map_.begin(); + it != pending_updates_map_.end(); + ++it) { + pending_updates_list.push_back(*it->second); + } + return pending_updates_list; } void ModelTypeSyncProxyImpl::ClearTransientSyncState() { @@ -239,7 +304,7 @@ void ModelTypeSyncProxyImpl::ClearSyncState() { ++it) { it->second->ClearSyncState(); } - + STLDeleteValues(&pending_updates_map_); data_type_state_ = DataTypeState(); } |